agent-device 0.10.0 → 0.10.1

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 (36) hide show
  1. package/README.md +1 -607
  2. package/dist/src/bin.js +9 -9
  3. package/dist/src/daemon/android-system-dialog.d.ts +11 -0
  4. package/dist/src/daemon/handlers/interaction-touch.d.ts +46 -0
  5. package/dist/src/daemon/handlers/interaction.d.ts +14 -5
  6. package/dist/src/daemon/handlers/record-trace-android.d.ts +18 -0
  7. package/dist/src/daemon/handlers/record-trace-ios.d.ts +52 -0
  8. package/dist/src/daemon/handlers/record-trace-recording.d.ts +32 -0
  9. package/dist/src/daemon/handlers/record-trace.d.ts +2 -7
  10. package/dist/src/daemon/record-trace-errors.d.ts +6 -0
  11. package/dist/src/daemon/recording-gestures.d.ts +3 -0
  12. package/dist/src/daemon/recording-telemetry.d.ts +20 -0
  13. package/dist/src/daemon/recording-timing.d.ts +24 -0
  14. package/dist/src/daemon/request-router.d.ts +6 -0
  15. package/dist/src/daemon/script-utils.d.ts +1 -0
  16. package/dist/src/daemon/touch-reference-frame.d.ts +7 -0
  17. package/dist/src/daemon/types.d.ts +62 -10
  18. package/dist/src/daemon.js +62 -36
  19. package/dist/src/platforms/android/index.d.ts +1 -1
  20. package/dist/src/platforms/android/input-actions.d.ts +4 -0
  21. package/dist/src/platforms/ios/runner-client.d.ts +2 -2
  22. package/dist/src/platforms/ios/runner-session.d.ts +5 -0
  23. package/dist/src/platforms/ios/runner-xctestrun.d.ts +3 -1
  24. package/dist/src/recording/overlay.d.ts +10 -0
  25. package/dist/src/utils/command-schema.d.ts +1 -0
  26. package/dist/src/utils/interactors.d.ts +7 -7
  27. package/dist/src/utils/video.d.ts +9 -0
  28. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +188 -51
  29. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +73 -0
  30. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +29 -1
  31. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +4 -6
  32. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +1 -0
  33. package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +571 -0
  34. package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-trim.swift +140 -0
  35. package/package.json +1 -1
  36. package/skills/agent-device/references/video-recording.md +9 -1
@@ -1,42 +1,68 @@
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 S,readVersion as N,getDiagnosticsMeta as _,runCmdSync as D,withDiagnosticTimer as E,findProjectRoot as k,emitDiagnostic as L,promises as O,isProcessAlive as x,readProcessStartTime as M,withDiagnosticsScope as C,node_fs as R,flushDiagnosticsToSessionFile as P,node_os as T,node_net as $,resolveDaemonServerMode as F,resolveDaemonPaths as U,node_http as V}from"./331.js";import{buildSnapshotDisplayLines as G,DEFAULT_BATCH_MAX_STEPS as B,formatRole as j,validateAndNormalizeBatchSteps as q,SETTINGS_INVALID_ARGS_MESSAGE as H,displayLabel as W,TextDecoder as z,formatSnapshotLine as J}from"./274.js";let K=X(process.env.AGENT_DEVICE_RETRY_LOGS);function X(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let Z=2e4,Y=12e4,Q=1e4;class ee{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new ee(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 et(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()}),ea({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),ea(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),ea(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),ea(n),a)throw a;throw new w("COMMAND_FAILED","retry failed")}async function er(e,t={}){return et(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function ea(e){L({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),K&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
2
- `)}let ei=new Set,en=new Map,eo="request_canceled",es="request canceled";function el(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 ed(e){if(!e)return;let t=new AbortController;en.set(e,t),ei.has(e)&&t.abort()}function eu(e){e&&(ei.add(e),en.get(e)?.abort())}function ec(e){e&&(ei.delete(e),en.delete(e))}function ep(e){return!!e&&ei.has(e)}function ef(e){if(e)return en.get(e)?.signal}function em(){return new w("COMMAND_FAILED",es,{reason:eo})}function eh(e){return e instanceof w&&"COMMAND_FAILED"===e.code&&(e.details?.reason===eo||e.message===es)}function ew(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 eg(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 eI(e){return!(e instanceof w)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function eA(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:ew({error:i,message:n,context:{platform:"ios",phase:"connect"}}),hint:eg("IOS_RUNNER_CONNECT_TIMEOUT")})}async function ev(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=ew({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}
1
+ let e,t,r,a;import i 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,expandUserHomePath as w,pathToFileURL as g,AppError as v,external_node_url_URL as A,whichCmd as I,fileURLToPath as y,runCmdStreaming as b,normalizeError as S,resolveSessionIsolationMode as _,resolveUserPath as N,readVersion as D,getDiagnosticsMeta as E,runCmdSync as M,withDiagnosticTimer as k,findProjectRoot as L,emitDiagnostic as O,promises as x,isProcessAlive as C,readProcessStartTime as P,withDiagnosticsScope as R,node_fs as T,flushDiagnosticsToSessionFile as $,node_os as F,node_net as U,resolveDaemonServerMode as V,resolveDaemonPaths as G,node_http as j}from"./331.js";import{buildSnapshotDisplayLines as B,DEFAULT_BATCH_MAX_STEPS as q,formatRole as H,validateAndNormalizeBatchSteps as W,SETTINGS_INVALID_ARGS_MESSAGE as z,displayLabel as J,TextDecoder as K,formatSnapshotLine as X}from"./274.js";let Y=Z(process.env.AGENT_DEVICE_RETRY_LOGS);function Z(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let Q=2e4,ee=12e4,et=1e4;class er{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new er(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 ea(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 v("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(r.deadline?.isExpired()&&t>1)break;try{let a=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),en({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),a}catch(d){a=d;let e=r.classifyReason?.(d),n={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(n),en(n),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(d,t))break;let o=function(e,t,r,a){let i=Math.min(t,e*2**(a-1));return Math.max(0,i+i*r*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),s=r.deadline?Math.min(o,r.deadline.remainingMs()):o;if(s<=0)break;let l={phase:r.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),en(l),await function(e,t){return new Promise(r=>{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),en(n),a)throw a;throw new v("COMMAND_FAILED","retry failed")}async function ei(e,t={}){return ea(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function en(e){O({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),Y&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
2
+ `)}let eo=new Set,es=new Map,el="request_canceled",ed="request canceled";function eu(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 ec(e){if(!e)return;let t=new AbortController;es.set(e,t),eo.has(e)&&t.abort()}function ep(e){e&&(eo.add(e),es.get(e)?.abort())}function ef(e){e&&(eo.delete(e),es.delete(e))}function em(e){return!!e&&eo.has(e)}function eh(e){if(e)return es.get(e)?.signal}function ew(){return new v("COMMAND_FAILED",ed,{reason:el})}function eg(e){return e instanceof v&&"COMMAND_FAILED"===e.code&&(e.details?.reason===el||e.message===ed)}function ev(e){let t=e.error?h(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 eA(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 eI(e){return!(e instanceof v)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function ey(e){let{port:t,endpoints:r,logPath:a,lastError:i}=e,n="Runner did not accept connection";return new v("COMMAND_FAILED",n,{port:t,endpoints:r,logPath:a,lastError:i?String(i):void 0,reason:ev({error:i,message:n,context:{platform:"ios",phase:"connect"}}),hint:eA("IOS_RUNNER_CONNECT_TIMEOUT")})}async function eb(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=ev({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new v("COMMAND_FAILED",l,{port:n,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(a=`${l}
3
3
  ${t}
4
- ${r}`.toLowerCase()).includes("device is busy")&&a.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":eg("IOS_RUNNER_CONNECT_TIMEOUT"))})}function ey(e){if(ep(e))throw em()}function eb(e,t,r){if(!e)return t;let a=Number(e);return Number.isFinite(a)?Math.max(r,Math.floor(a)):t}let eS=["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 eD(e,t){for(let r of e){let e=e_(t[r]);if(e)return e}}function eE(e,t=process.env){return e_(e)??eD(eS,t)}function ek(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function eL(e,t=process.env){let r=e_(e)??eD(eN,t);if(r)return ek(r)}function eO(e,t={}){let r=eE(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function ex(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:eO(t,{simulatorSetPath:e.simulatorSetPath})}let eM=eb(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),eC=eb(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),eR=eb(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),eP=eb(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),eT=eb(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),e$=eb(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),eF=eb(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),eU=eb(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function eV(e,t,r,a,i=eM,n,o){let s=ee.fromTimeoutMs(i),l=await eG(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/eR));try{return await et(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 ev({session:n,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await eG(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 eB(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(e$,e),o)}catch(e){if(o?.aborted||eh(e))throw em();d=e}throw new w("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:eP,maxDelayMs:eT,jitter:.2,shouldRetry:eI},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||eh(e))throw em();d||(d=e)}if(o?.aborted)throw em();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw eA({port:t,endpoints:l,logPath:a,lastError:d});let n=await eq(e,t,r,i);return new Response(n.body,{status:n.status})}throw eA({port:t,endpoints:l,logPath:a,lastError:d})}async function eG(e,t,r){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await ej(e.id,r);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function eB(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 ej(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(eF,t)):eF,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||!R.existsSync(a))return null;let n=JSON.parse(R.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{ez(a)}}async function eq(e,t,r,a){let i=JSON.stringify(r),n=ex(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=ew({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:eg(e)})}return{status:200,body:s}}async function eH(){return await new Promise((e,t)=>{let r=$.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 eW(e,t,r,a){t&&R.appendFileSync(t,e),r&&R.appendFileSync(r,e),a&&process.stderr.write(e)}function ez(e){try{R.existsSync(e)&&R.unlinkSync(e)}catch{}}async function eJ(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 eK(e){return"apple"===e||"ios"===e||"macos"===e}function eX(e,t){return!t||("apple"===t?eK(e):e===t)}function eZ(e){let{simulatorSetPath:t,platform:r,target:a}=e;if(t&&"macos"!==r&&"desktop"!==a)return t}async function eY(e,t,r={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>eX(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&&eK(e.platform));if(!e)throw new w("DEVICE_NOT_FOUND",`No Apple device with UDID ${t.udid}`);return e}if(t.serial){let e=a.find(e=>e.id===t.serial&&"android"===e.platform);if(!e)throw new 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){var n;let e=r.simulatorSetPath;if(e&&(!(n=t.platform)||"apple"===n||"ios"===n))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 o=a.filter(e=>"device"!==e.kind);o.length>0&&(a=o);let s=a.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??a[0]}let eQ=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function e0(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new w("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:r});let a=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of a)if(!R.existsSync(e))throw new w("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==D("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await c("codesign",["--remove-signature",e],{allowFailure:!0});try{await c("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof w?a:new w("COMMAND_FAILED",String(a));throw new w("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}let e1=i.join(T.homedir(),".agent-device","ios-runner"),e2=new Map,e3=new Set;function e4(e){return e?.trim()??""}function e8(e=process.env){return e4(e.AGENT_DEVICE_IOS_BUNDLE_ID)||e4(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function e6(e=process.env){let t=e4(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${e8(e)}.uitests`}let e5=function(e=process.env){let t=e8(e),r=e6(e);return Array.from(new Set([e4(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env),e9={findProjectRoot: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(R.existsSync(e))return t;t=i.dirname(t)}return e},findXctestrun:function(e){if(!R.existsSync(e))return null;let t=[],r=[e];for(;r.length>0;){let e=r.pop();for(let a of R.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=R.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)},xctestrunReferencesProjectRoot:function(e,t){try{let r=R.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(R.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}},resolveExistingXctestrunProductPaths:function(e){let t=function(e){let t=function(e){try{let t=D("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())return null;return JSON.parse(t.stdout)}catch{return null}}(e);if(t){var r,a=t;let e=new Set,i=t=>{if(t&&"object"==typeof t)for(let r of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),r=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){r.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};i(a);let n=a.TestConfigurations;if(Array.isArray(n))for(let e of n){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)i(e)}for(let e of Object.values(a))e&&"object"==typeof e&&"TestBundlePath"in e&&i(e);return Array.from(e)}if("darwin"===process.platform)return null;try{return r=R.readFileSync(e,"utf8"),Array.from(new Set([...["ProductPaths","DependentProductPaths"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<array>([\\s\\S]*?)</array>`,"g"),i=/<string>([\s\S]*?)<\/string>/g,n=new Set;for(;null!==(r=a.exec(e));){let e,t=r[1]??"";for(;null!==(e=i.exec(t));){let t=e[1]?.trim();t&&n.add(t)}}return Array.from(n)})(r,e)),...["TestHostPath","TestBundlePath","UITargetAppPath"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<string>([\\s\\S]*?)</string>`,"g"),i=new Set;for(;null!==(r=a.exec(e));){let e=r[1]?.trim();e&&i.add(e)}return Array.from(i)})(r,e))]))}catch{return null}}(e);if(!t||0===t.length)return null;let r=i.dirname(e),a=new Set,n=new Set,o=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),o=i.join(r,t);if(!R.existsSync(o))return null;a.add(o);let s=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);s&&n.add(i.join(r,s));continue}e.startsWith("__TESTHOST__/")&&o.push(e.slice(13))}for(let e of o){let t=Array.from(n).find(t=>R.existsSync(i.join(t,e)));if(!t)return null;a.add(i.join(t,e))}return Array.from(a)},repairRunnerProductsIfNeeded:e0,assertSafeDerivedCleanup:function(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return X(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."})},cleanRunnerDerivedArtifacts:function(e){try{if(!R.existsSync(e))return;if("derived"!==i.basename(e))return void R.rmSync(e,{recursive:!0,force:!0});for(let r of R.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,te.has(t)&&R.rmSync(i.join(e,r.name),{recursive:!0,force:!0})}}catch{}},buildRunnerXctestrun:tr};async function e7(e,t,r=e9){var a;let n,o=(a=e,(n=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?i.resolve(n):"macos"===a.platform?i.join(e1,"derived","macos"):"simulator"===a.kind?i.join(e1,"derived"):i.join(e1,"derived",a.kind)),s=r.findProjectRoot();return await eJ(e2,o,async()=>{X(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(to("clean","forced_clean",{derived:o}),r.assertSafeDerivedCleanup(o),r.cleanRunnerDerivedArtifacts(o));let a=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let r=e.resolveExistingXctestrunProductPaths(t);return r?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:r}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:r}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:o,projectRoot:s,findXctestrun:r.findXctestrun,xctestrunReferencesProjectRoot:r.xctestrunReferencesProjectRoot,resolveExistingXctestrunProductPaths:r.resolveExistingXctestrunProductPaths});if("reuse_ready"!==a.reason&&to("rebuild",a.reason,{derived:o,xctestrunPath:a.xctestrunPath}),"reuse_ready"===a.reason)try{return await r.repairRunnerProductsIfNeeded(e,a.productPaths,a.xctestrunPath),to("reuse","reuse_ready",{derived:o,xctestrunPath:a.xctestrunPath}),a.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof w))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&eQ.has(t)}(e))throw e;to("rebuild","repair_failed",{derived:o,xctestrunPath:a.xctestrunPath})}a.xctestrunPath&&(r.assertSafeDerivedCleanup(o),r.cleanRunnerDerivedArtifacts(o));let n=i.join(s,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!R.existsSync(n))throw new w("COMMAND_FAILED","iOS runner project not found",{projectPath:n});await r.buildRunnerXctestrun(e,n,o,t);let l=r.findXctestrun(o);if(!l)throw new w("COMMAND_FAILED","Failed to locate .xctestrun after build");let d=r.resolveExistingXctestrunProductPaths(l);if(!d)throw new w("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:l});return await r.repairRunnerProductsIfNeeded(e,d,l),to("build","built_new",{derived:o,xctestrunPath:l}),l})}let te=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);async function tt(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);R.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}}async function tr(e,t,r,a){let i=function(e=process.env){let t=e8(e),r=e6(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),n=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),i&&o.push(`CODE_SIGN_IDENTITY=${i}`),n&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var s;let l;await v("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",tn(e),"1","-destination",(s=e,l=ta(s),"macOS"===l?`platform=macOS,arch=${ti()}`:"simulator"===s.kind?`platform=${l} Simulator,id=${s.id}`:`generic/platform=${l}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...n],{detached:!0,onSpawn:e=>{e3.add(e),e.on("close",()=>{e3.delete(e)})},onStdoutChunk:e=>{eW(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{eW(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(n){let e,t,r=n instanceof w?n:new w("COMMAND_FAILED",String(n)),i=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
6
- ${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new w("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:r.message,details:r.details,logPath:a.logPath,hint:i})}}function ta(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new w("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"macos"===e.platform?"macOS":"macos"===(t=e.target)||"desktop"===t?"macOS":"tv"===t?"tvOS":"iOS"}function ti(){return"arm64"===process.arch?"arm64":"x86_64"}function tn(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function to(e,t,r){L({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}let ts=new Map,tl=new Map;async function td(e,t){return await eJ(tl,e.id,async()=>{var r,a;let i,n=ts.get(e.id);if(n){if((r=n.child.pid)&&x(r))return n;await tc(e.id,n)}await ("simulator"!==(a=e).kind?Promise.resolve():tw(a));let o=await e7(e,t),s=await eH(),{xctestrunPath:l,jsonPath:u}=await tt(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",tn(e),"1","-destination-timeout",String(eU),"-xctestrun",l,"-destination","macOS"===(i=ta(e))?`platform=macOS,arch=${ti()}`:"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=>{eW(e,t.logPath,t.traceLogPath,t.verbose)}),c.stderr?.on("data",e=>{eW(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 ts.set(e.id,f),f})}async function tu(e){await eJ(tl,e.deviceId,async()=>{await tc(e.deviceId,e)})}async function tc(e,t){let r=t??ts.get(e);if(r){try{await eV(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await th(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await th(r.child.pid,"SIGKILL"),ez(r.xctestrunPath),ez(r.jsonPath),ts.get(e)===r&&ts.delete(e)}}async function tp(e){await eJ(tl,e,async()=>{await tc(e)})}async function tf(){let e=Array.from(ts.values()),t=Array.from(e3);await Promise.allSettled(e.map(async e=>{await th(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await th(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await th(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await th(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await th(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await th(e.pid,"SIGKILL"),e3.delete(e)}))}async function tm(){await tf();let e=Array.from(ts.keys());await Promise.allSettled(e.map(async e=>{await tp(e)}));let t=Array.from(e3);await Promise.allSettled(t.map(async e=>{try{await th(e.pid,"SIGTERM"),await th(e.pid,"SIGKILL")}finally{e3.delete(e)}}))}async function th(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 tw(e){await c("xcrun",ex(e,["bootstatus",e.id,"-b"]),{timeoutMs:eM})}async function tg(e,t,r,a,i,n){let o=await eV(e,t.port,r,a,i,t,n);return await tI(o,t,a)}async function tI(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 tA(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==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(ey(r.requestId),"snapshot"===(a=t.command)||"screenshot"===a||"findText"===a||"alert"===a)?er(()=>(ey(r.requestId),tv(e,t,r)),{shouldRetry:e=>{ey(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"))}}):tv(e,t,r)}async function tv(e,t,r={}){let a;ey(r.requestId);let i=ef(r.requestId);try{let n=(a=await td(e,r)).ready?eC:eM;return await tg(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")&&eI(n)&&a?.ready){ey(r.requestId),a?await tu(a):await tp(e.id),a=await td(e,r);let n=await eV(a.device,a.port,t,r.logPath,eM,void 0,i);return await tI(n,a,r.logPath)}throw o}}function ty(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 tb(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tS=/^-?\d+(\.\d+)?$/,tN=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),t_=new Map([["--count","count"],["--pause-ms","pauseMs"]]);function tD(e){return"click"===e||"press"===e}function tE(e){let t=e.trim();return t.startsWith("@")||tS.test(t)?t:JSON.stringify(t)}function tk(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function tL(e,t){let r=t.flags??{};if(tD(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}"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 tO(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",tk(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",tk(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tk(t.launchUrl)))}function tx(e,t){let r=[],a={},i=tD(e)?tN:"swipe"===e?t_:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tD(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tD(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=tC(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 tM(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=tC(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function tC(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tR(e,t){for(let r of t.positionals??[])e.push(tE(r));t.flags?.relaunch&&e.push("--relaunch"),tO(e,t.runtime)}class tP{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=tP.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:I,count:A,intervalMs:v,holdMs:y,jitterPx:b,doubleTap:S,clickButton:N,pauseMs:_,pattern:D}=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:S,clickButton:N,pauseMs:_,pattern:D}}(t.flags),result:t.result}),L({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);R.existsSync(r)||R.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(tD(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tE(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tE(a)),tL(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tE(r)),tL(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tE(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tE(a)),i&&t.push(tE(i)),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tE(r)),t.push(tE(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tE(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",tE(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tR(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tk(r)),tO(t,e.flags),t.join(" ")}for(let r of e.positionals??[])t.push(tE(r));return tL(t,e),t.join(" ")}(n));return`${r.join("\n")}
7
- `}(e,this.buildOptimizedActions(e));R.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=tP.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,tP.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return i.join(this.sessionsDir,tP.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return S(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return tP.expandHome(e.saveScriptPath);R.existsSync(this.sessionsDir)||R.mkdirSync(this.sessionsDir,{recursive:!0});let t=tP.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&&(tD(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tD(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=ty(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(tD(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 tT(e,t){if(!e)return;let r=i.dirname(e);R.existsSync(r)||R.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:M(t)??void 0,command:n(t)??void 0};R.writeFileSync(e,`${JSON.stringify(a)}
8
- `)}function t$(e){if(e&&R.existsSync(e))try{R.unlinkSync(e)}catch{}}async function tF(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function tU(e){await new Promise(t=>setTimeout(t,e))}function tV(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 tG(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 tB(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 tj(e,t,r,a,i){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await tB(e,t);if(!d){await tU(1e3);continue}let u=p("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=tV(r,{redactionPatterns:a});o=tG(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&tT(i,u.pid);let f=await o;if(t$(i),n=void 0,o=void 0,l)break;0!==f.exitCode&&(s="failed"),await tU(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),t$(i)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await tF(o),n&&!n.killed&&n.kill("SIGKILL"),await tF(d),t$(i)}}}async function tq(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=tV(t,{redactionPatterns:r});"number"==typeof n.pid&&tT(a,n.pid);let s=tG(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),t$(a),e));return{backend:"ios-simulator",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tF(s),n.killed||n.kill("SIGKILL"),await tF(s),t$(a)}}}async function tH(e,t,r,a){let i="active",n=p("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tV(t,{redactionPatterns:r});"number"==typeof n.pid&&tT(a,n.pid);let s=tG(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),t$(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tF(s),n.killed||n.kill("SIGKILL"),await tF(s),t$(a)}}}function tW(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 tz(e){let t=i.dirname(e);R.existsSync(t)||R.mkdirSync(t,{recursive:!0}),function(e,t){if(R.existsSync(e)&&!(R.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}`;R.existsSync(t)&&(R.existsSync(a)&&R.unlinkSync(a),R.renameSync(t,a))}}(e,{maxBytes:tW("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:tW("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function tJ(e,t,r,a){tz(r);let i=R.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 tH(e.id,i,n,a):await tq(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 tj(e.id,t,i,n,a)}throw i.end(),new w("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function tK(e){await e.stop(),await tF(e.wait)}async function tX(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 tZ(e){let t=i.dirname(e),r=i.basename(e);R.existsSync(t)||R.mkdirSync(t,{recursive:!0}),R.existsSync(e)?R.truncateSync(e,0):R.writeFileSync(e,"","utf8");let a=0;for(let e of R.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let n=e.slice(r.length+1);if(/^\d+$/.test(n))try{R.unlinkSync(i.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let tY=new Map;function tQ(e){let t=tY.get(e);if(t&&(clearTimeout(t.timer),tY.delete(e),t.deleteAfterDownload))try{R.rmSync(t.artifactPath,{force:!0})}catch{}}let t0=new Map;function t1(e,t){let r=t0.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 t2(e){let t=t0.get(e);t&&(clearTimeout(t.timer),t0.delete(e),R.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function t3(e){let t=await t4(e);await c("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=i.join(e.tempDir,t);if(!R.existsSync(r))throw new w("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function t4(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 t8=eb(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function t6(e,t){return new Promise((r,a)=>{let i,n=R.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(),R.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:t8});o(e),n.destroy(e),d(e)},t8)};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 t5(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"),R.mkdtempSync(i.join(T.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=i.join(o,n);return await t6(e,t),{artifactPath:t,tempDir:o}}let t=i.join(o,"artifact.tar");await t6(e,t);let a=await t3({archivePath:t,tempDir:o,platform:"ios",expectedRootName:n});return R.rmSync(t,{force:!0}),{artifactPath:a,tempDir:o}}catch(e){throw R.rmSync(o,{recursive:!0,force:!0}),e}}let t9=new Set(["agent_device.command","agent-device.command"]),t7=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),re=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rt={"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"},rr=new Set([...t9,...t7,...re,...Object.keys(rt)]);function ra(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function ri(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rn(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function ro(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 rs(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rl(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rd(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:ra(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:ra(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:ra(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function ru(){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 rc(e){let t=await ru(),{handleRequest:r,token:a}=e;return V.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 rp(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rf(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||ri(i,ra(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{ri(i,ra(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void ri(i,ra(a.id??null,-32600,"Invalid Request"),400);if(!rr.has(a.method))return void ri(i,ra(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void ri(i,ra(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(t9.has(e))return{token:ro(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(t7.has(e)){let e,a=rs(t,"platform");if("ios"!==a&&"android"!==a)throw new w("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:ro(t,r),session:rs(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rs(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:rl(t,"retentionMs")}}}if(re.has(e)){let e=rs(t,"materializationId")?.trim();if(!e)throw new w("INVALID_ARGS","Invalid params: materializationId is required");return{token:ro(t,r),session:rs(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rs(t,"requestId"),materializationId:e}}}let a=rt[e];if(a)return{token:ro(t,r),session:rs(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rs(t,"tenantId")??rs(t,"tenant"),runId:rs(t,"runId"),leaseId:rs(t,"leaseId"),leaseTtlMs:rl(t,"ttlMs"),leaseBackend:rs(t,"backend")}};throw new w("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,t9.has(s)&&("string"!=typeof l.command||0===l.command.length))return void ri(i,ra(a.id??null,-32602,"Invalid params: command is required"),400);o=el(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},ed(o);let d=()=>{i.writableFinished||eu(o)};e.on("aborted",d),i.on("close",d);let u=await rd(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void ri(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 ri(i,{jsonrpc:"2.0",id:a.id??null,result:c});ri(i,ra(a.id??null,-32e3,c.error.message,c.error),rn(c.error.code))}catch(t){let e=y(t);ri(i,ra(a.id??null,-32e3,e.message,e),rn(e.code))}finally{ec(o)}})})}async function rp(e,t,r,a){try{var i;let n,o,s=ro({},e.headers),l=rm(s,a);if(l){t.statusCode=rn(l.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.message,code:l.code}));return}let d=await rd(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 t5(e),p=(i={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:d.tenantId},n=u.randomUUID(),o=setTimeout(()=>{t2(n)},3e5),t0.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=rn(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rf(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=ro({},e.headers),o=rm(n,a);if(o){t.statusCode=rn(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let s=await rd(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=tY.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(!R.existsSync(r.artifactPath))throw tQ(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=R.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=rn(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&tQ(i)}),d.pipe(t)}catch(r){let e=y(r);t.statusCode=rn(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rm(e,t){return t&&e!==t?y(new w("UNAUTHORIZED","Invalid token")):null}function rh(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rw(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rg(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new w("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rI{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=rg(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=rh(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=rw(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=rw(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=rg(e.backend),r=o(e.tenantId);if(!r)throw new w("INVALID_ARGS","tenant isolation requires tenant id.");let a=rh(e.runId);if(!a)throw new w("INVALID_ARGS","tenant isolation requires run id.");let i=rw(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=rh(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"})}}let rA=["emulator","platform-tools",i.join("cmdline-tools","latest","bin"),i.join("cmdline-tools","tools","bin")];function rv(e){let t=new Set,r=[];for(let a of e){let e=a.trim();!e||t.has(e)||(t.add(e),r.push(e))}return r}function ry(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||T.homedir();return rv([t??"",r??"",a?i.join(a,"Android","Sdk"):""])}async function rb(e){try{return await O.access(e,O.constants.X_OK),!0}catch{return!1}}async function rS(e=process.env){let t,r=[];for(let a of ry(e)){let e=[];for(let t of rA){let r=i.join(a,t);await rb(r)&&e.push(r)}0!==e.length&&(t||(t=a),r.push(...e))}if(t&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||t,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||t),0===r.length)return;let a=(e.PATH??"").split(i.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=rv([...r,...a]).join(i.delimiter)}function rN(e,t){return["-s",e.id,...t]}async function r_(){if(await rS(),!await I("adb"))throw new w("TOOL_MISSING","adb not found in PATH")}function rD(e,t){let r=`${e}
10
- ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function rE(e){await new Promise(t=>setTimeout(t,e))}function rk(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 rL(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 rO=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function rx(e){return`${e.stdout}
11
- ${e.stderr}`}function rM(e,t){return["-s",e,...t]}function rC(e){return e.startsWith("emulator-")}function rR(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}function rP(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}async function rT(e,t=Q){return c("adb",rM(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function r$(e,t){let r=t.replace(/_/g," ").trim();if(!rC(e))return r||e;let a=await rU(e);return a?a.replace(/_/g," "):r||e}async function rF(e,t,r){try{return await r("adb",rM(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=f(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function rU(e,t=c){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await rF(e,["shell","getprop",r],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let r=await rF(e,["emu","avd","name"],t);if(!r)return;let a=rP(r.stdout);if(0===r.exitCode&&a)return a}function rV(e){let t=e.toLowerCase();return t.includes("tv")||t.includes("leanback")?"tv":null}function rG(e){return/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(e)}async function rB(e,t){let r=rx(await c("adb",rM(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:Q})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function rj(e){return(await Promise.all(rO.map(async t=>await rB(e,t)))).some(e=>!0===e)}async function rq(e){return"tv"===rV(rx(await c("adb",rM(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:Q})))||await rj(e)||rG(rx(await c("adb",rM(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:Q})))?"tv":"mobile"}async function rH(e={}){if(await rS(),!await I("adb"))throw new w("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??eL(void 0),r=(await rW()).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([r$(e,t),rY(e),rq(e)]);return{platform:"android",id:e,name:r,kind:rC(e)?"emulator":"device",target:i,booted:a}}))}async function rW(){return(await c("adb",["devices","-l"],{timeoutMs:Q})).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:","")}))}function rz(e){return e.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}function rJ(e,t){let r=e.find(e=>e===t);if(r)return r;let a=rR(t);return e.find(e=>rR(e)===a)}async function rK(){let e=await c("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:Q});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 rz(e.stdout)}async function rX(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await rZ(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 rZ(e,t){let r=rR(e);for(let e of(await rW()).filter(e=>(!t||e.serial===t)&&rC(e.serial)))if(rR(e.rawModel)===r||rR(await r$(e.serial,e.rawModel))===r)return e.serial}async function rY(e){try{let t=await rT(e);return"1"===t.stdout.trim()}catch{return!1}}async function rQ(e){var t,r;let a;await rS();let 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 rK(),s=rJ(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 rH(),r=e.serial,a=rR(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&rR(e.name)===a));if(!u){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),l("emulator",t)}let c=u??await rX({avdName:s,serial:e.serial,timeoutMs:n}),p=Math.max(1e3,n-(Date.now()-d));await r1(c.id,p);let f=(await rH()).find(e=>e.id===c.id);return f?{...f,name:s,booted:!0}:{...c,name:s,booted:!0}}async function r0(e){return await rQ({...e,headless:!0})}async function r1(e,t=6e4){let r,a=ee.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await et(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 rT(e,Math.min(o,Q));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=ew({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=>ew({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=ew({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:eg(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 r2=/\.(?:apk|aab)$/i,r3=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function r4(e){var t,r;let a=e.trim();return 0===a.length?"other":r2.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!r3.test(t))?"binary":"package":(r=a,r3.test(r))?"package":"other"}function r8(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let r6=[".zip",".tar",".tar.gz",".tgz"],r5=eb(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),r9=["1","true","yes","on"];async function r7(e){let t=[];try{let r=await ae(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await an(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 ad(t)}}}catch(e){throw await ad(t),e}}async function ae(e,t){if("path"===e.kind)return{localPath:m(e.path),cleanup:async()=>{}};let r=await O.mkdtemp(i.join(T.tmpdir(),"agent-device-source-"));try{return{localPath:await at(r,e.url,e.headers,t),cleanup:async()=>{await O.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await O.rm(r,{recursive:!0,force:!0}),e}}async function at(e,t,r,a){let n;try{n=new URL(t)}catch{throw new w("INVALID_ARGS",`Invalid source URL: ${t}`)}await ar(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??r5,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 O.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 ar(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new w("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!r9.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||ai(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=>ai(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 aa(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 ai(e){let t,r=$.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 an(e,t){let r=await O.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()&&al(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 as(e);return t.registerCleanup(r.cleanup),await an(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await ao(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 ao(e,(e,t)=>t.isFile()&&al(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 as(a[0]);return t.registerCleanup(e.cleanup),await an(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 ao(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let n=await O.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 as(e){let t=await O.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 O.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await O.rm(t,{recursive:!0,force:!0}),e}}function al(e){let t=e.toLowerCase();return r6.some(e=>t.endsWith(e))}async function ad(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let au=new z("utf-16le");async function ac(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await ap(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]=af(e,t),[a,i]=af(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 au.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 am(e)}async function ap(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 af(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function am(e){let t=await ah();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 ah(){if(void 0!==e)return e??void 0;try{for(let t of ry()){let r=i.join(t,"build-tools");try{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{}}}catch{}e=null}async function aw(e,t){let r="url"===e.kind&&aa(e.url),a=await r7({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 ag(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:n.packageName,cleanup:a.cleanup}}async function ag(e){let t=i.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await ac(e)}}let aI={settings:{type:"intent",value:"android.settings.SETTINGS"}},aA="android.intent.category.LAUNCHER",av="android.intent.category.LEANBACK_LAUNCHER",ay="android.intent.category.DEFAULT";async function ab(e,t){let r=t.trim();if("package"===r4(r))return{type:"package",value:r};let a=aI[r.toLowerCase()];if(a)return a;let i=(await c("adb",rN(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 aS(e,t="all"){let r=await aN(e);return("user-installed"===t?(await aD(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:aE(e)}))}async function aN(e){let t=new Set;for(let r of a_(e,{includeFallbackWhenUnknown:!0})){let a=await c("adb",rN(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 a_(e,t={}){return"tv"===e.target?[av]:"mobile"===e.target?[aA]:t.includeFallbackWhenUnknown?[aA,av]:[aA]}async function aD(e){return(await c("adb",rN(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function aE(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 ak(e){let t=await aL(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await aL(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function aL(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",rN(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function aO(e,t,r){e.booted||await r1(e.id);let a=t.trim();if(rk(a)){if(r)throw new w("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await c("adb",rN(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",a]));return}let i=await ab(e,t),n=a_(e)[0]??aA;if("intent"===i.type){if(r)throw new w("INVALID_ARGS","Activity override requires a package name, not an intent");await c("adb",rN(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",rN(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",ay,"-c",n,"-n",t]));return}let o=await c("adb",rN(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",ay,"-c",n,"-p",i.value]),{allowFailure:!0});if(0===o.exitCode&&!aM(o.stdout,o.stderr))return;let s=await ax(e,i.value);if(!s)throw new w("COMMAND_FAILED",`Failed to launch ${i.value}`,{stdout:o.stdout,stderr:o.stderr});await c("adb",rN(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",ay,"-c",n,"-n",s]))}async function ax(e,t){for(let r of Array.from(new Set(a_(e,{includeFallbackWhenUnknown:!0})))){let a=await c("adb",rN(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=aC(a.stdout);if(i)return i}return null}function aM(e,t){let r=`${e}
12
- ${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(r)}function aC(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 aR(e){e.booted||await r1(e.id)}async function aP(e,t){if("settings"===t.trim().toLowerCase())return void await c("adb",rN(e,["shell","am","force-stop","com.android.settings"]));let r=await ab(e,t);if("intent"===r.type)throw new w("INVALID_ARGS","Close requires a package name, not an intent");await c("adb",rN(e,["shell","am","force-stop",r.value]))}async function aT(e,t){let r=await ab(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",rN(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 a$=null;async function aF(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(a$?.key===e)return a$.invocation;if(await I("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return a$={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 O.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 a$={key:e,invocation:r},r}async function aU(e){let t=await aF();await c(t.cmd,[...t.prefixArgs,...e])}async function aV(e,t){let r,a=await O.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 aU(["build-apks","--bundle",t,"--output",n,"--mode",o]),await aU(["install-apks","--apks",n,"--device-id",e.id])}finally{await O.rm(a,{recursive:!0,force:!0})}}async function aG(e,t){".aab"===i.extname(t).toLowerCase()?await aV(e,t):await c("adb",rN(e,["install","-r",t]))}async function aB(e){return new Set((await c("adb",rN(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function aj(e,t){let r=Array.from(await aB(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function aq(e,t){e.booted||await r1(e.id),await aG(e,t)}async function aH(e,t,r){let a=r?void 0:await aB(e);return await aq(e,t),r??(a?await aj(e,a):void 0)}async function aW(e,t){e.booted||await r1(e.id);let r=await aw({kind:"path",path:t});try{let t=await aH(e,r.installablePath,r.packageName),a=t?aE(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function az(e,t,r){e.booted||await r1(e.id);let{package:a}=await aT(e,t),i=await aw({kind:"path",path:r},{resolveIdentity:!1});try{return await aq(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function aJ(e){let t=aK(e),r=e=>{let r=aX(t,e);if(null!==r)return"true"===r};return{text:aX(t,"text"),desc:aX(t,"content-desc"),resourceId:aX(t,"resource-id"),className:aX(t,"class"),bounds:aX(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function aK(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 aX(e,t){return e.get(t)??null}function aZ(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 aY(e){return e?e.toLowerCase():""}function aQ(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function a0(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=aJ(t),o=aZ(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,S,N;if(i.length>=800){n=!0;return}if(t>o)return;let _=!!r.raw||(d=e,p=r,f=s,m=u(e),h=l,I=aY(d.type),A=!!(d.label&&d.label.trim().length>0),v=!!(d.identifier&&d.identifier.trim().length>0),y=A&&!aQ(d.label??""),b=v&&!aQ(d.identifier??""),S=(g=(w=I).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,N="imageview"===I||"imagebutton"===I,p.interactiveOnly?!!d.hittable||!!(y||b)&&!N&&(!S||!!h)&&(f||m||h):p.compact?y||b||!!d.hittable:!S&&!N||!!d.hittable||!!y||!!b&&!!m||m),D=a;_&&(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=aY(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 a1(e),0,t)}async function a1(e){return er(()=>a2(e),{shouldRetry:a4})}async function a2(e){var t,r,a;let i,n,o=await c("adb",rN(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=a3(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await c("adb",rN(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",rN(e,["shell","cat",d])),p=a3(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 a3(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 a4(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 a8(e,t,r){await c("adb",rN(e,["shell","input","tap",String(t),String(r)]))}async function a6(e,t,r,a,i,n=250){await c("adb",rN(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function a5(e){await c("adb",rN(e,["shell","input","keyevent","4"]))}async function a9(e){await c("adb",rN(e,["shell","input","keyevent","3"]))}async function a7(e){await c("adb",rN(e,["shell","input","keyevent","187"]))}async function ie(e,t,r,a=800){await c("adb",rN(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function it(e,t){let r=id(t);if(!r||"ok"!==await iu(e,t))try{let r=t.replace(/ /g,"%s");await c("adb",rN(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 ir(e,t,r){await a8(e,t,r)}async function ia(e,t,r,a){let i=Array.from(a).length,n=id(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 ir(e,t,r);let o=(l=i+n.clearPadding,d=n.minClear,Math.max(d,Math.min(n.maxClear,l)));if(await ic(e,o),"input_text"===n.strategy)await it(e,a);else if("clipboard_paste"===n.strategy){if("ok"!==await iu(e,a))continue}else await il(e,a,1,15);if((s=await ip(e,t,r))===a)return}throw new w("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:s??null})}async function ii(e,t,r=.6){let{width:a,height:i}=await is(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",rN(e,["shell","input","swipe",String(d),String(u),String(p),String(f),"300"]))}async function io(e,t){for(let r=0;r<8;r+=1){let r="";try{r=await a1(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=aK(i[0]),n=(aX(t,"text")??"").toLowerCase(),o=(aX(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=aZ(aX(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 ii(e,"down",.5)}throw new w("COMMAND_FAILED",`Could not find element containing "${t}" after scrolling`)}async function is(e){let t=(await c("adb",rN(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 il(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 it(e,r),a>0&&t+i<n.length&&await rE(a)}}function id(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 iu(e,t){let r=await c("adb",rN(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":rD(r.stdout,r.stderr)?"unsupported":0===(await c("adb",rN(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await c("adb",rN(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function ic(e,t){let r=Math.max(0,t);await c("adb",rN(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",rN(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function ip(e,t,r){let a,i=await a1(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=aJ(a[0]),i=aZ(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&&im(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&im(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 im(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function ih(e){let t=await c("adb",rN(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 iw(e){let t=await ih(e),r=t,a=0;for(;r.visible&&a<2;)await a5(e),a+=1,await rE(120),r=await ih(e);return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function ig(e){let t,r;return(r=(t=(await iA(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 iI(e,t){await iA(e,["shell","cmd","clipboard","set","text",t],"write")}async function iA(e,t,r){let a=await c("adb",rN(e,t),{allowFailure:!0});if(rD(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 iv=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iy(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 ib(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: ${iv.join("|")}`)}function iS(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 iN(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=iD(r);await c("adb",rN(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=iD(r);await c("adb",rN(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await c("adb",rN(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=iD(r);await c("adb",rN(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await iE(e,r);await c("adb",rN(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 i_(e,t);return}case"permission":{if(!a)throw new w("INVALID_ARGS","permission setting requires an active app in session");let t=iy(r),n=function(e,t){let r=ib(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 iL(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await ik(e,a,o);await c("adb",rN(e,["shell","pm",o,a,n.value]));return}default:throw new w("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function i_(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",rN(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 iD(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 iE(e,t){let r=iS(t);if("toggle"!==r)return r;let a=await c("adb",rN(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 ik(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",rN(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 iL(e,t,r,a){"grant"===r?await c("adb",rN(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await c("adb",rN(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await c("adb",rN(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await c("adb",rN(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await c("adb",rN(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function iO(e){let t=await c("adb",rN(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 ix(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",rN(e,i)),{action:a,extrasCount:s}}let iM=Buffer.from([137,80,78,71,13,10,26,10]),iC={enableDemoMode:iP,settle:rE,capture:i$,disableDemoMode:iT};async function iR(e,t,r=iC){await r.enableDemoMode(e);try{await r.settle(1e3),await r.capture(e,t)}finally{await r.disableDemoMode(e).catch(()=>{})}}async function iP(e){let t=t=>c("adb",rN(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 iT(e){await c("adb",rN(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function i$(e,t){let r=await c("adb",rN(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new w("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(iM);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+iM.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 O.writeFile(t,r.stdoutBuffer.subarray(a,i))}let iF=eb(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,Y,5e3),iU=eb(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,Z,1e3),iV=eb(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),iG=eb(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),iB=eb(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),ij=eb(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),iq=eb(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function iH(e,t){let r=["devicectl",...e],a=await c("xcrun",r,{allowFailure:!0,timeoutMs:iG});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:iK(i,n)??iJ})}async function iW(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:iG});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:iK(t,r)??iJ})}let i=await O.readFile(r,"utf8");return o=iz(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 O.unlink(r).catch(()=>{})}}function iz(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 iJ="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function iK(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 iX(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 iZ(e,t){let r=await c("xcrun",ex(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 iY(e,t){if("simulator"!==e.kind)throw new w("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function iQ(){await c("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:iB})}async function i0(e){let t,r;if("simulator"!==e.kind||"Booted"===await i2(e))return;let a=ee.fromTimeoutMs(iF);try{await et(async({deadline:a})=>{if(a?.isExpired())throw new w("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:iF});let i=Math.max(1e3,a?.remainingMs()??iF),n=await c("xcrun",ex(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",ex(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 i2(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=ew({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=>ew({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(n){let i=ew({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:iF,elapsedMs:a.elapsedMs(),reason:i,hint:eg(i),boot:t,bootstatus:r})}}async function i1(e){let t=ex(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 i2(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?eO(["list","devices","-j"]):ex(e,["list","devices","-j"]),a=await c("xcrun",r,{allowFailure:!0,timeoutMs:iU});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 i3(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 O.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 i4(e,t){if("url"===e.kind&&!aa(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 r7({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||aa(e.url),signal:t?.signal}),a=await i6(r.installablePath,t),i=await i8(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 i8(e){let t=i.join(e,"Info.plist"),[r,a,n]=await Promise.all([i3(t,"CFBundleIdentifier"),i3(t,"CFBundleDisplayName"),i3(t,"CFBundleName")]);return{bundleId:r,appName:a??n}}async function i6(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await O.mkdtemp(i.join(T.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await O.rm(r,{recursive:!0,force:!0})};try{await c("ditto",["-x","-k",e,r]);let n=i.join(r,"Payload"),o=(await O.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 i5(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(i9).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(i9).join(", ")}`)}catch(e){throw await a(),e}}async function i5(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await i8(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function i9(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function i7(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let ne={settings:"com.apple.systempreferences"},nt=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function nr(e){return e.replace(/\\/g,"\\\\").replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/"/g,'\\"')}function na(e,t){let r=["-b",e];return t&&r.push(t),r}async function ni(e){for(let t of[i.join(e,"Contents","Info.plist"),i.join(e,"Info.plist")]){let[e,r,a]=await Promise.all([i3(t,"CFBundleIdentifier"),i3(t,"CFBundleDisplayName"),i3(t,"CFBundleName")]);if(e||r||a)return{bundleId:e,appName:r??a}}return{}}async function nn(e){let t=e.trim(),r=ne[t.toLowerCase()];if(r)return r;let a=`id of app "${nr(t)}"`,i=await c("osascript",["-e",a],{allowFailure:!0});if(0===i.exitCode){let e=i.stdout.trim();if(e)return e}let n=(await np("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===n.length)return n[0].bundleId;if(n.length>1)throw new w("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:n});if(nt.test(t))return t;throw new w("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function no(e,t,r){let a=r?.url?.trim();if(a){if(!rk(a))throw new w("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await nn(t);await c("open",na(e,a));return}let i=t.trim();if(rk(i))return void await c("open",[i]);let n=r?.appBundleId??await nn(i);await c("open",na(n))}async function ns(e,t){let r=await nn(t),a=`tell application id "${nr(r)}" to quit`,i=await c("osascript",["-e",a],{allowFailure:!0});if(0===i.exitCode)return;let n=`${i.stdout}
20
- ${i.stderr}`.toLowerCase();if(!(n.includes("isn’t running")||n.includes("isn't running")))throw new w("COMMAND_FAILED",`Failed to close macOS app ${t}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function nl(){let e=await c("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new w("COMMAND_FAILED","Failed to read macOS clipboard",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});return e.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function nd(e){let t=await c("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new w("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function nu(){let e=await c("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new w("COMMAND_FAILED","Failed to read macOS appearance",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});let t=e.stdout.trim().toLowerCase();if("true"===t)return!0;if("false"===t)return!1;throw new w("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function nc(e){let t=iS(e),r="toggle"===t?!await nu():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${r?"true":"false"}`,i=await c("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new w("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function np(e="all"){let t=["/Applications","/System/Applications",i.join(T.homedir(),"Applications")],r=new Set;for(let e of t){let t=await O.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await c("find",[e,"-maxdepth","4","-type","d","-name","*.app"],{allowFailure:!0});if(0===a.exitCode)for(let e of a.stdout.split("\n")){let t=e.trim();t&&r.add(t)}}return i7((await Promise.all(Array.from(r).map(async e=>{let t=await ni(e).catch(()=>({})),r=t.bundleId;return r?{bundleId:r,name:t.appName??i.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let nf=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],nm={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"},nh={1:"searching",2:"failed",3:"active"},nw={0:"notSupported",1:"searching",2:"failed",3:"active"};function ng(e,t,r){return c("xcrun",ex(e,t),r)}async function nI(e,t){var r,a;let i;await nv(e),t&&await ny(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 nA(e){let t=await ng(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=nm[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=nh[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=nw[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 nv(e){await ng(e,["status_bar",e.id,"clear"])}async function ny(e,t){0!==t.length&&await ng(e,["status_bar",e.id,"override",...t])}function nb(e,t,r){L({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 nS(e,t,r){return c("xcrun",ex(e,t),r)}let nN={ensureBooted:i0,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await nA(e),r=!0}catch(t){nb(e,"snapshot_failed",t)}try{await nv(e),await ny(e,nf)}catch(t){nb(e,"prepare_failed",t)}return async()=>{await nI(e,r?t:null)}},captureWithRetry:nE,captureWithRunner:nk,shouldFallbackToRunner:nP};async function n_(e,t,r){if("macos"===e.platform)return void await nk(e,t,r);if("simulator"===e.kind)return void await nD(e,t,r);try{await iH(["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}
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.":eA("IOS_RUNNER_CONNECT_TIMEOUT"))})}function eS(e){if(em(e))throw ew()}function e_(e,t,r){if(!e)return t;let a=Number(e);return Number.isFinite(a)?Math.max(r,Math.floor(a)):t}let eN=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],eD=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function eE(e){return e?.trim()||void 0}function eM(e,t){for(let r of e){let e=eE(t[r]);if(e)return e}}function ek(e,t=process.env){return eE(e)??eM(eN,t)}function eL(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function eO(e,t=process.env){let r=eE(e)??eM(eD,t);if(r)return eL(r)}function ex(e,t={}){let r=ek(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function eC(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:ex(t,{simulatorSetPath:e.simulatorSetPath})}let eP=e_(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),eR=e_(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),eT=e_(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),e$=e_(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),eF=e_(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),eU=e_(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),eV=e_(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),eG=e_(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function ej(e,t,r,a,i=eP,n,o){let s=er.fromTimeoutMs(i),l=await eB(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/eT));try{return await ea(async({deadline:s})=>{if(s?.isExpired())throw new v("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(n&&null!==n.child.exitCode&&void 0!==n.child.exitCode)throw await eb({session:n,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await eB(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new v("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await eq(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(eU,e),o)}catch(e){if(o?.aborted||eg(e))throw ew();d=e}throw new v("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:e$,maxDelayMs:eF,jitter:.2,shouldRetry:eI},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||eg(e))throw ew();d||(d=e)}if(o?.aborted)throw ew();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw ey({port:t,endpoints:l,logPath:a,lastError:d});let n=await eW(e,t,r,i);return new Response(n.body,{status:n.status})}throw ey({port:t,endpoints:l,logPath:a,lastError:d})}async function eB(e,t,r){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await eH(e.id,r);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function eq(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 eH(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(eV,t)):eV,a=o.join(F.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),i=await f("xcrun",["devicectl","device","info","details","--device",e,"--json-output",a,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==i.exitCode||!T.existsSync(a))return null;let n=JSON.parse(T.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{eK(a)}}async function eW(e,t,r,a){let i=JSON.stringify(r),n=eC(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 f("xcrun",n,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=ev({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new v("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:eA(e)})}return{status:200,body:s}}async function ez(){return await new Promise((e,t)=>{let r=U.createServer();r.listen(0,"127.0.0.1",()=>{let a=r.address();r.close(),"object"==typeof a&&a?.port?e(a.port):t(new v("COMMAND_FAILED","Failed to allocate port"))}),r.on("error",t)})}function eJ(e,t,r,a){t&&T.appendFileSync(t,e),r&&T.appendFileSync(r,e),a&&process.stderr.write(e)}function eK(e){try{T.existsSync(e)&&T.unlinkSync(e)}catch{}}async function eX(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 eY(e){return"apple"===e||"ios"===e||"macos"===e}function eZ(e,t){return!t||("apple"===t?eY(e):e===t)}function eQ(e){let{simulatorSetPath:t,platform:r,target:a}=e;if(t&&"macos"!==r&&"desktop"!==a)return t}async function e0(e,t,r={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>eZ(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&&eY(e.platform));if(!e)throw new v("DEVICE_NOT_FOUND",`No Apple device with UDID ${t.udid}`);return e}if(t.serial){let e=a.find(e=>e.id===t.serial&&"android"===e.platform);if(!e)throw new v("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 v("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===a.length)return a[0];if(0===a.length){var n;let e=r.simulatorSetPath;if(e&&(!(n=t.platform)||"apple"===n||"ios"===n))throw new v("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 v("DEVICE_NOT_FOUND","No devices found",{selector:t})}let o=a.filter(e=>"device"!==e.kind);o.length>0&&(a=o);let s=a.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??a[0]}let e1=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function e2(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new v("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:r});let a=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of a)if(!T.existsSync(e))throw new v("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==M("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await f("codesign",["--remove-signature",e],{allowFailure:!0});try{await f("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof v?a:new v("COMMAND_FAILED",String(a));throw new v("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}let e3=o.join(F.homedir(),".agent-device","ios-runner"),e4=new Map,e8=new Set;function e5(e){return e?.trim()??""}function e6(e=process.env){return e5(e.AGENT_DEVICE_IOS_BUNDLE_ID)||e5(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function e9(e=process.env){let t=e5(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${e6(e)}.uitests`}let e7=function(e=process.env){let t=e6(e),r=e9(e);return Array.from(new Set([e5(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env),te={findProjectRoot:function(){let e=o.dirname(y(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=o.join(t,"package.json");if(T.existsSync(e))return t;t=o.dirname(t)}return e},findXctestrun:function(e,t){if(!T.existsSync(e))return null;let r=[],a=[e];for(;a.length>0;){let e=a.pop();for(let t of T.readdirSync(e,{withFileTypes:!0})){let i=o.join(e,t.name);if(t.isDirectory()){a.push(i);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=T.statSync(i);r.push({path:i,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let a=ta(r.path,t)-ta(e.path,t);if(0!==a)return a}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)},xctestrunReferencesProjectRoot:function(e,t){try{let r=T.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(T.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}},resolveExistingXctestrunProductPaths:function(e){let t=function(e){let t=function(e){try{let t=M("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())return null;return JSON.parse(t.stdout)}catch{return null}}(e);if(t){var r,a=t;let e=new Set,i=t=>{if(t&&"object"==typeof t)for(let r of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),r=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){r.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};i(a);let n=a.TestConfigurations;if(Array.isArray(n))for(let e of n){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)i(e)}for(let e of Object.values(a))e&&"object"==typeof e&&"TestBundlePath"in e&&i(e);return Array.from(e)}if("darwin"===process.platform)return null;try{return r=T.readFileSync(e,"utf8"),Array.from(new Set([...["ProductPaths","DependentProductPaths"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<array>([\\s\\S]*?)</array>`,"g"),i=/<string>([\s\S]*?)<\/string>/g,n=new Set;for(;null!==(r=a.exec(e));){let e,t=r[1]??"";for(;null!==(e=i.exec(t));){let t=e[1]?.trim();t&&n.add(t)}}return Array.from(n)})(r,e)),...["TestHostPath","TestBundlePath","UITargetAppPath"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<string>([\\s\\S]*?)</string>`,"g"),i=new Set;for(;null!==(r=a.exec(e));){let e=r[1]?.trim();e&&i.add(e)}return Array.from(i)})(r,e))]))}catch{return null}}(e);if(!t||0===t.length)return null;let r=o.dirname(e),a=new Set,i=new Set,n=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),n=o.join(r,t);if(!T.existsSync(n))return null;a.add(n);let s=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);s&&i.add(o.join(r,s));continue}e.startsWith("__TESTHOST__/")&&n.push(e.slice(13))}for(let e of n){let t=Array.from(i).find(t=>T.existsSync(o.join(t,e)));if(!t)return null;a.add(o.join(t,e))}return Array.from(a)},repairRunnerProductsIfNeeded:e2,assertSafeDerivedCleanup:function(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return Z(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new v("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."})},cleanRunnerDerivedArtifacts:function(e){try{if(!T.existsSync(e))return;if("derived"!==o.basename(e))return void T.rmSync(e,{recursive:!0,force:!0});for(let r of T.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,tr.has(t)&&T.rmSync(o.join(e,r.name),{recursive:!0,force:!0})}}catch{}},buildRunnerXctestrun:tn};async function tt(e,t,r=te){var a;let i,n=(a=e,(i=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?o.resolve(i):"macos"===a.platform?o.join(e3,"derived","macos"):"simulator"===a.kind?o.join(e3,"derived"):o.join(e3,"derived",a.kind)),s=r.findProjectRoot();return await eX(e4,n,async()=>{Z(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(td("clean","forced_clean",{derived:n}),r.assertSafeDerivedCleanup(n),r.cleanRunnerDerivedArtifacts(n));let a=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let r=e.resolveExistingXctestrunProductPaths(t);return r?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:r}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:r}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:n,projectRoot:s,findXctestrun:t=>r.findXctestrun(t,e),xctestrunReferencesProjectRoot:r.xctestrunReferencesProjectRoot,resolveExistingXctestrunProductPaths:r.resolveExistingXctestrunProductPaths});if("reuse_ready"!==a.reason&&td("rebuild",a.reason,{derived:n,xctestrunPath:a.xctestrunPath}),"reuse_ready"===a.reason)try{return await r.repairRunnerProductsIfNeeded(e,a.productPaths,a.xctestrunPath),td("reuse","reuse_ready",{derived:n,xctestrunPath:a.xctestrunPath}),a.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof v))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&e1.has(t)}(e))throw e;td("rebuild","repair_failed",{derived:n,xctestrunPath:a.xctestrunPath})}a.xctestrunPath&&(r.assertSafeDerivedCleanup(n),r.cleanRunnerDerivedArtifacts(n));let i=o.join(s,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!T.existsSync(i))throw new v("COMMAND_FAILED","iOS runner project not found",{projectPath:i});await r.buildRunnerXctestrun(e,i,n,t);let l=r.findXctestrun(n,e);if(!l)throw new v("COMMAND_FAILED","Failed to locate .xctestrun after build");let d=r.resolveExistingXctestrunProductPaths(l);if(!d)throw new v("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:l});return await r.repairRunnerProductsIfNeeded(e,d,l),td("build","built_new",{derived:n,xctestrunPath:l}),l})}let tr=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function ta(e,t){var r;let a=0,i=e.toLowerCase();o.basename(i).startsWith("agentdevicerunner.env.")&&(a-=1e3),i.includes(`${o.sep}macos${o.sep}`)&&(a-=5e3);let n="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return n.preferred.length>0&&(n.preferred.some(e=>i.includes(e))?a+=2e3:a-=500),n.disallowed.some(e=>i.includes(e))&&(a-=2500),a}async function ti(e,t,r){let a,i=o.dirname(e),n=r.replace(/[^a-zA-Z0-9._-]/g,"_"),s=o.join(i,`AgentDeviceRunner.env.${n}.json`),l=o.join(i,`AgentDeviceRunner.env.${n}.xctestrun`),d=await f("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new v("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new v("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=a.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(a))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),a[e]=t);T.writeFileSync(s,JSON.stringify(a,null,2));let p=await f("plutil",["-convert","xml1","-o",l,s],{allowFailure:!0});if(0!==p.exitCode)throw new v("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:p.stderr});return{xctestrunPath:l,jsonPath:s}}async function tn(e,t,r,a){let i=function(e=process.env){let t=e6(e),r=e9(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),n=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),i&&o.push(`CODE_SIGN_IDENTITY=${i}`),n&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var s;let l;await b("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",tl(e),"1","-destination",(s=e,l=to(s),"macOS"===l?`platform=macOS,arch=${ts()}`:"simulator"===s.kind?`platform=${l} Simulator,id=${s.id}`:`generic/platform=${l}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...n],{detached:!0,onSpawn:e=>{e8.add(e),e.on("close",()=>{e8.delete(e)})},onStdoutChunk:e=>{eJ(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{eJ(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(n){let e,t,r=n instanceof v?n:new v("COMMAND_FAILED",String(n)),i=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
6
+ ${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new v("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:r.message,details:r.details,logPath:a.logPath,hint:i})}}function to(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new v("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"macos"===e.platform?"macOS":"macos"===(t=e.target)||"desktop"===t?"macOS":"tv"===t?"tvOS":"iOS"}function ts(){return"arm64"===process.arch?"arm64":"x86_64"}function tl(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function td(e,t,r){O({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}let tu=new Map,tc=new Map;async function tp(e,t){return await eX(tc,e.id,async()=>{var r;let a,i=tu.get(e.id);if(i){if(function(e){return!!e&&C(e)}(i.child.pid))return i;await th(e.id,i)}await ("simulator"!==(r=e).kind?Promise.resolve():tI(r)),await tf(e);let n=await tt(e,t),o=await ez(),{xctestrunPath:s,jsonPath:l}=await ti(n,{AGENT_DEVICE_RUNNER_PORT:String(o)},`session-${e.id}-${o}`),{child:d,wait:u}=c("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",tl(e),"1","-destination-timeout",String(eG),"-xctestrun",s,"-destination","macOS"===(a=to(e))?`platform=macOS,arch=${ts()}`:"simulator"===e.kind?`platform=${a} Simulator,id=${e.id}`:`platform=${a},id=${e.id}`],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(o)},detached:!0});d.stdout?.on("data",e=>{eJ(e,t.logPath,t.traceLogPath,t.verbose)}),d.stderr?.on("data",e=>{eJ(e,t.logPath,t.traceLogPath,t.verbose)});let p={sessionId:`${e.id}:${o}:${Date.now()}`,device:e,deviceId:e.id,port:o,xctestrunPath:s,jsonPath:l,testPromise:u,child:d,ready:!1};return tu.set(e.id,p),p})}async function tf(e){if("simulator"===e.kind)for(let t of e7){let r=await f("xcrun",eC(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==r.exitCode){let e=`${r.stdout}
7
+ ${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found nothing")&&!e.includes("no such file")&&!e.includes("invalid device")&&!e.includes("could not find"))continue}}}async function tm(e){await eX(tc,e.deviceId,async()=>{await th(e.deviceId,e)})}async function th(e,t){let r=t??tu.get(e);if(r){try{await ej(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await tA(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await tA(r.child.pid,"SIGKILL"),eK(r.xctestrunPath),eK(r.jsonPath),tu.get(e)===r&&tu.delete(e)}}async function tw(e){await eX(tc,e,async()=>{await th(e)})}async function tg(){let e=Array.from(tu.values()),t=Array.from(e8);await Promise.allSettled(e.map(async e=>{await tA(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await tA(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await tA(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await tA(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await tA(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await tA(e.pid,"SIGKILL"),e8.delete(e)}))}async function tv(){await tg();let e=Array.from(tu.keys());await Promise.allSettled(e.map(async e=>{await tw(e)}));let t=Array.from(e8);await Promise.allSettled(t.map(async e=>{try{await tA(e.pid,"SIGTERM"),await tA(e.pid,"SIGKILL")}finally{e8.delete(e)}}))}async function tA(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 tI(e){await f("xcrun",eC(e,["bootstatus",e.id,"-b"]),{timeoutMs:eP})}async function ty(e,t,r,a,i,n){let o=await ej(e,t.port,r,a,i,t,n);return await tb(o,t,a)}async function tb(e,t,r){let a=await e.text(),i={};try{i=JSON.parse(a)}catch{throw new v("COMMAND_FAILED","Invalid runner response",{text:a})}if(!i.ok)throw new v("COMMAND_FAILED",i.error?.message??"Runner error",{runner:i,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,i.data??{}}async function tS(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new v("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new v("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(eS(r.requestId),"snapshot"===(a=t.command)||"screenshot"===a||"findText"===a||"alert"===a||"uptime"===a)?ei(()=>(eS(r.requestId),t_(e,t,r)),{shouldRetry:e=>{eS(r.requestId);if(!(e instanceof v)||"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"))}}):t_(e,t,r)}async function t_(e,t,r={}){let a;eS(r.requestId);let i=eh(r.requestId);try{let n=(a=await tp(e,r)).ready?eR:eP;return await ty(e,a,t,r.logPath,n,i)}catch(o){let n=o instanceof v?o:new v("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&eI(n)&&a?.ready){eS(r.requestId),a?await tm(a):await tw(e.id),a=await tp(e,r);let n=await ej(a.device,a.port,t,r.logPath,eP,void 0,i);return await tb(n,a,r.logPath)}throw o}}function tN(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 tD(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tE=/^-?\d+(\.\d+)?$/,tM=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tk=new Map([["--count","count"],["--pause-ms","pauseMs"]]);function tL(e){return"click"===e||"press"===e}function tO(e){let t=e.trim();return t.startsWith("@")||tE.test(t)?t:JSON.stringify(t)}function tx(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function tC(e,t){let r=t.flags??{};if(tL(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}"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 tP(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",tx(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",tx(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tx(t.launchUrl)))}function tR(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tx(r)),a))e.push(tO(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function tT(e,t){let r=[],a={},i=tL(e)?tM:"swipe"===e?tk:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tL(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tL(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=tF(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 t$(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=tF(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function tF(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tU(e,t){for(let r of t.positionals??[])e.push(tO(r));t.flags?.relaunch&&e.push("--relaunch"),tP(e,t.runtime)}class tV{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=tV.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:v,fps:A,hideTouches:I,count:y,intervalMs:b,holdMs:S,jitterPx:_,doubleTap:N,clickButton:D,pauseMs:E,pattern:M}=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:v,fps:A,hideTouches:I,count:y,intervalMs:b,holdMs:S,jitterPx:_,doubleTap:N,clickButton:D,pauseMs:E,pattern:M}}(t.flags),result:t.result}),O({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);T.existsSync(r)||T.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(tL(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tO(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tO(a)),tC(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tO(r)),tC(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tO(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tO(a)),i&&t.push(tO(i)),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tO(r)),t.push(tO(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tO(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",tO(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tU(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tx(r)),tP(t,e.flags),t.join(" ")}if("record"===e.command)return tR(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tO(r));return tC(t,e),t.join(" ")}(n));return`${r.join("\n")}
8
+ `}(e,this.buildOptimizedActions(e));T.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=tV.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,tV.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return o.join(this.sessionsDir,tV.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 tV.expandHome(e.saveScriptPath);T.existsSync(this.sessionsDir)||T.mkdirSync(this.sessionsDir,{recursive:!0});let t=tV.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 a=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(a.length>0&&(tL(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tL(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=tN(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(tL(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 tG(e,t){if(!e)return;let r=o.dirname(e);T.existsSync(r)||T.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:P(t)??void 0,command:s(t)??void 0};T.writeFileSync(e,`${JSON.stringify(a)}
9
+ `)}function tj(e){if(e&&T.existsSync(e))try{T.unlinkSync(e)}catch{}}async function tB(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function tq(e){await new Promise(t=>setTimeout(t,e))}function tH(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],a="",i=a=>{(!(r.length>0)||r.some(e=>a.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(a,t.redactionPatterns))};return{onChunk:e=>{let t=`${a}${e}`.split("\n");for(let e of(a=t.pop()??"",t))i(`${e}
10
+ `)},flush:()=>{a&&(i(a),a="")}}}function tW(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 tz(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 tJ(e,t,r,a,i){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await tz(e,t);if(!d){await tq(1e3);continue}let u=m("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=tH(r,{redactionPatterns:a});o=tW(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&tG(i,u.pid);let p=await o;if(tj(i),n=void 0,o=void 0,l)break;0!==p.exitCode&&(s="failed"),await tq(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tj(i)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await tB(o),n&&!n.killed&&n.kill("SIGKILL"),await tB(d),tj(i)}}}async function tK(e,t,r,a){let i="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=tH(t,{redactionPatterns:r});"number"==typeof n.pid&&tG(a,n.pid);let s=tW(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tj(a),e));return{backend:"ios-simulator",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tB(s),n.killed||n.kill("SIGKILL"),await tB(s),tj(a)}}}async function tX(e,t,r,a){let i="active",n=m("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tH(t,{redactionPatterns:r});"number"==typeof n.pid&&tG(a,n.pid);let s=tW(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tj(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tB(s),n.killed||n.kill("SIGKILL"),await tB(s),tj(a)}}}function tY(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 tZ(e){let t=o.dirname(e);T.existsSync(t)||T.mkdirSync(t,{recursive:!0}),function(e,t){if(T.existsSync(e)&&!(T.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}`;T.existsSync(t)&&(T.existsSync(a)&&T.unlinkSync(a),T.renameSync(t,a))}}(e,{maxBytes:tY("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:tY("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function tQ(e,t,r,a){tZ(r);let i=T.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 tX(e.id,i,n,a):await tK(t,i,n,a);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new v("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await tJ(e.id,t,i,n,a)}throw i.end(),new v("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function t0(e){await e.stop(),await tB(e.wait)}async function t1(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 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:a}}function t2(e){let t=o.dirname(e),r=o.basename(e);T.existsSync(t)||T.mkdirSync(t,{recursive:!0}),T.existsSync(e)?T.truncateSync(e,0):T.writeFileSync(e,"","utf8");let a=0;for(let e of T.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let i=e.slice(r.length+1);if(/^\d+$/.test(i))try{T.unlinkSync(o.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let t3=new Map;function t4(e){let t=t3.get(e);if(t&&(clearTimeout(t.timer),t3.delete(e),t.deleteAfterDownload))try{T.rmSync(t.artifactPath,{force:!0})}catch{}}let t8=new Map;function t5(e,t){let r=t8.get(e);if(!r)throw new v("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new v("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function t6(e){let t=t8.get(e);t&&(clearTimeout(t.timer),t8.delete(e),T.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function t9(e){let t=await t7(e);await f("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=o.join(e.tempDir,t);if(!T.existsSync(r))throw new v("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function t7(e){let t=await f("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new v("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 v("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(e=>(function(e){if(e.includes("\0"))throw new v("INVALID_ARGS",`Invalid archive entry: ${e}`);if(o.posix.isAbsolute(e))throw new v("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=o.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new v("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t})(e)),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new v("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new v("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 v("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===i||e.startsWith(`${i}/`)))throw new v("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,s=i;if(n!==s&&!n.startsWith(`${s}/`))throw new v("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 v("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links")}return i}let re=e_(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rt(e,t){return new Promise((r,a)=>{let i,n=T.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(),T.rmSync(t,{force:!0}),a(e);return}r()}},u=()=>{i&&clearTimeout(i),i=setTimeout(()=>{let e=new v("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:re});o(e),n.destroy(e),d(e)},re)};e.on("data",e=>{u();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((l+=t)>0x80000000){let e=new v("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 v("COMMAND_FAILED","Artifact transfer was interrupted"))}),n.on("error",d),n.on("finish",()=>d()),u(),e.pipe(n)})}async function rr(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new v("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new v("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 v("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let i=function(e){let t=e.trim(),r=o.basename(t);if(!r||"."===r||".."===r)throw new v("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),n=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),T.mkdtempSync(o.join(F.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=o.join(n,i);return await rt(e,t),{artifactPath:t,tempDir:n}}let t=o.join(n,"artifact.tar");await rt(e,t);let a=await t9({archivePath:t,tempDir:n,platform:"ios",expectedRootName:i});return T.rmSync(t,{force:!0}),{artifactPath:a,tempDir:n}}catch(e){throw T.rmSync(n,{recursive:!0,force:!0}),e}}let ra=new Set(["agent_device.command","agent-device.command"]),ri=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rn=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),ro={"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"},rs=new Set([...ra,...ri,...rn,...Object.keys(ro)]);function rl(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rd(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function ru(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rc(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 rp(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rf(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rm(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=S(new v("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:rl(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=S(new v(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:rl(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=S(new v("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:rl(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rh(){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=o.isAbsolute(t)?t:o.resolve(t);try{e=await import(g(a).href)}catch(e){throw new v("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let i=e[r];if("function"!=typeof i)throw new v("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rw(e){let t=await rh(),{handleRequest:r,token:a}=e;return j.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 rg(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rv(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||rd(i,rl(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rd(i,rl(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rd(i,rl(a.id??null,-32600,"Invalid Request"),400);if(!rs.has(a.method))return void rd(i,rl(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rd(i,rl(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(ra.has(e))return{token:rc(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(ri.has(e)){let e,a=rp(t,"platform");if("ios"!==a&&"android"!==a)throw new v("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rc(t,r),session:rp(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rp(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new v("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new v("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 v("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 v("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 v("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new v("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rf(t,"retentionMs")}}}if(rn.has(e)){let e=rp(t,"materializationId")?.trim();if(!e)throw new v("INVALID_ARGS","Invalid params: materializationId is required");return{token:rc(t,r),session:rp(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rp(t,"requestId"),materializationId:e}}}let a=ro[e];if(a)return{token:rc(t,r),session:rp(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rp(t,"tenantId")??rp(t,"tenant"),runId:rp(t,"runId"),leaseId:rp(t,"leaseId"),leaseTtlMs:rf(t,"ttlMs"),leaseBackend:rp(t,"backend")}};throw new v("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,ra.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rd(i,rl(a.id??null,-32602,"Invalid params: command is required"),400);o=eu(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},ec(o);let d=()=>{i.writableFinished||ep(o)};e.on("aborted",d),i.on("close",d);let u=await rm(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rd(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 rd(i,{jsonrpc:"2.0",id:a.id??null,result:c});rd(i,rl(a.id??null,-32e3,c.error.message,c.error),ru(c.error.code))}catch(t){let e=S(t);rd(i,rl(a.id??null,-32e3,e.message,e),ru(e.code))}finally{ef(o)}})})}async function rg(e,t,r,a){try{var i;let n,o,s=rc({},e.headers),l=rA(s,a);if(l){t.statusCode=ru(l.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.message,code:l.code}));return}let d=await rm(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 rr(e),c=(i={artifactPath:u.artifactPath,tempDir:u.tempDir,tenantId:d.tenantId},n=p.randomUUID(),o=setTimeout(()=>{t6(n)},3e5),t8.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:c}))}catch(r){let e=S(r);t.statusCode=ru(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rv(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=rc({},e.headers),o=rA(n,a);if(o){t.statusCode=ru(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let s=await rm(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=t3.get(e);if(!r)throw new v("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new v("UNAUTHORIZED","Artifact belongs to a different tenant");if(!T.existsSync(r.artifactPath))throw t4(e),new v("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(i,s.tenantId),d=T.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=S(e);t.statusCode=ru(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&t4(i)}),d.pipe(t)}catch(r){let e=S(r);t.statusCode=ru(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rA(e,t){return t&&e!==t?S(new v("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 ry(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rb(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new v("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=rb(e.backend),r=l(e.tenantId);if(!r)throw new v("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=rI(e.runId);if(!a)throw new v("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),o=this.runBindings.get(n);if(o){let e=this.leases.get(o);if(e)return this.refreshLease(e,i);this.runBindings.delete(n)}this.enforceCapacity(t);let s=this.now(),d={leaseId:p.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:s,heartbeatAt:s,expiresAt:s+i};return this.leases.set(d.leaseId,d),this.runBindings.set(n,d.leaseId),{...d}}heartbeatLease(e){let t=ry(e.leaseId);if(!t)throw new v("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new v("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=ry(e.leaseId);if(!t)throw new v("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=rb(e.backend),r=l(e.tenantId);if(!r)throw new v("INVALID_ARGS","tenant isolation requires tenant id.");let a=rI(e.runId);if(!a)throw new v("INVALID_ARGS","tenant isolation requires run id.");let i=ry(e.leaseId);if(!i)throw new v("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new v("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new v("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 v("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 v("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=l(t),i=rI(r);if(t&&!a)throw new v("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new v("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 v("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let r_=["emulator","platform-tools",o.join("cmdline-tools","latest","bin"),o.join("cmdline-tools","tools","bin")];function rN(e){let t=new Set,r=[];for(let a of e){let e=a.trim();!e||t.has(e)||(t.add(e),r.push(e))}return r}function rD(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||F.homedir();return rN([t??"",r??"",a?o.join(a,"Android","Sdk"):""])}async function rE(e){try{return await x.access(e,x.constants.X_OK),!0}catch{return!1}}async function rM(e=process.env){let t,r=[];for(let a of rD(e)){let e=[];for(let t of r_){let r=o.join(a,t);await rE(r)&&e.push(r)}0!==e.length&&(t||(t=a),r.push(...e))}if(t&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||t,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||t),0===r.length)return;let a=(e.PATH??"").split(o.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=rN([...r,...a]).join(o.delimiter)}function rk(e,t){return["-s",e.id,...t]}async function rL(){if(await rM(),!await I("adb"))throw new v("TOOL_MISSING","adb not found in PATH")}function rO(e,t){let r=`${e}
11
+ ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function rx(e){await new Promise(t=>setTimeout(t,e))}function rC(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 rP(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 rR=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function rT(e){return`${e.stdout}
12
+ ${e.stderr}`}function r$(e,t){return["-s",e,...t]}function rF(e){return e.startsWith("emulator-")}function rU(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}function rV(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}async function rG(e,t=et){return f("adb",r$(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function rj(e,t){let r=t.replace(/_/g," ").trim();if(!rF(e))return r||e;let a=await rq(e);return a?a.replace(/_/g," "):r||e}async function rB(e,t,r){try{return await r("adb",r$(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=h(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function rq(e,t=f){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await rB(e,["shell","getprop",r],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let r=await rB(e,["emu","avd","name"],t);if(!r)return;let a=rV(r.stdout);if(0===r.exitCode&&a)return a}function rH(e){let t=e.toLowerCase();return t.includes("tv")||t.includes("leanback")?"tv":null}function rW(e){return/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(e)}async function rz(e,t){let r=rT(await f("adb",r$(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:et})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function rJ(e){return(await Promise.all(rR.map(async t=>await rz(e,t)))).some(e=>!0===e)}async function rK(e){return"tv"===rH(rT(await f("adb",r$(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:et})))||await rJ(e)||rW(rT(await f("adb",r$(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:et})))?"tv":"mobile"}async function rX(e={}){if(await rM(),!await I("adb"))throw new v("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??eO(void 0),r=(await rY()).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([rj(e,t),r3(e),rK(e)]);return{platform:"android",id:e,name:r,kind:rF(e)?"emulator":"device",target:i,booted:a}}))}async function rY(){return(await f("adb",["devices","-l"],{timeoutMs:et})).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:","")}))}function rZ(e){return e.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}function rQ(e,t){let r=e.find(e=>e===t);if(r)return r;let a=rU(t);return e.find(e=>rU(e)===a)}async function r0(){let e=await f("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:et});if(0!==e.exitCode)throw new v("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 rZ(e.stdout)}async function r1(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await r2(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 v("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 r2(e,t){let r=rU(e);for(let e of(await rY()).filter(e=>(!t||e.serial===t)&&rF(e.serial)))if(rU(e.rawModel)===r||rU(await rj(e.serial,e.rawModel))===r)return e.serial}async function r3(e){try{let t=await rG(e);return"1"===t.stdout.trim()}catch{return!1}}async function r4(e){var t,r;let a;await rM();let i=e.avdName.trim();if(!i)throw new v("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await I("adb"))throw new v("TOOL_MISSING","adb not found in PATH");if(!await I("emulator"))throw new v("TOOL_MISSING","emulator not found in PATH");let o=await r0(),s=rQ(o,i);if(!s)throw new v("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:i,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),d=(t=await rX(),r=e.serial,a=rU(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&rU(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),u("emulator",t)}let c=d??await r1({avdName:s,serial:e.serial,timeoutMs:n}),p=Math.max(1e3,n-(Date.now()-l));await r5(c.id,p);let f=(await rX()).find(e=>e.id===c.id);return f?{...f,name:s,booted:!0}:{...c,name:s,booted:!0}}async function r8(e){return await r4({...e,headless:!0})}async function r5(e,t=6e4){let r,a=er.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await ea(async({deadline:i})=>{if(i?.isExpired())throw n=!0,new v("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 rG(e,Math.min(o,et));if(r=s,"1"!==s.stdout.trim())throw new v("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=ev({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=>ev({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=h(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=ev({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:eA(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new v("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new v("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new v("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new v(i.code,i.message,{...u,...i.details??{}},i.cause)}}let r6=/\.(?:apk|aab)$/i,r9=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function r7(e){var t,r;let a=e.trim();return 0===a.length?"other":r6.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!r9.test(t))?"binary":"package":(r=a,r9.test(r))?"package":"other"}function ae(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let at=[".zip",".tar",".tar.gz",".tgz"],ar=e_(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),aa=["1","true","yes","on"];async function ai(e){let t=[];try{let r=await an(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await au(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 am(t)}}}catch(e){throw await am(t),e}}async function an(e,t){if("path"===e.kind)return{localPath:w(e.path),cleanup:async()=>{}};let r=await x.mkdtemp(o.join(F.tmpdir(),"agent-device-source-"));try{return{localPath:await ao(r,e.url,e.headers,t),cleanup:async()=>{await x.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await x.rm(r,{recursive:!0,force:!0}),e}}async function ao(e,t,r,a){let i;try{i=new URL(t)}catch{throw new v("INVALID_ARGS",`Invalid source URL: ${t}`)}await as(i);let n=a?.signal;if(n?.aborted)throw new v("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let s=new AbortController,l=()=>{s.abort(n?.reason)};n?.addEventListener("abort",l,{once:!0});let d=a?.downloadTimeoutMs??ar,u=setTimeout(()=>{s.abort(Error("download timeout"))},d);try{let t=await fetch(i,{headers:r,redirect:"follow",signal:s.signal});if(!t.ok)throw new v("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:i.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),i=a?.[1]?.trim();if(i)return o.basename(i);let n=o.basename(t.pathname);return n||"downloaded-artifact.bin"}(t,i),n=o.join(e,a),l=t.body;if(!l)throw new v("COMMAND_FAILED","Download response body was empty",{url:i.toString()});let d=await x.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 v("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(s.signal.aborted)throw new v("COMMAND_FAILED",`App source download timed out after ${d}ms`,{timeoutMs:d,url:i.toString()},e);throw e}finally{n?.removeEventListener("abort",l),clearTimeout(u)}}async function as(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new v("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!aa.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||ad(t))throw new v("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 i.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>ad(e.address)))throw new v("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 al(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 ad(e){let t,r=U.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 au(e,t){let r=await x.stat(e).catch(()=>null);if(!r)throw new v("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&af(e)){if(!t.allowArchiveExtraction)throw new v("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await ap(e);return t.registerCleanup(r.cleanup),await au(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await ac(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new v("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await ac(e,(e,t)=>t.isFile()&&af(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new v("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await ap(a[0]);return t.registerCleanup(e.cleanup),await au(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new v("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new v("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function ac(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let i=await x.readdir(e.path,{withFileTypes:!0});for(let n of(i.sort((e,t)=>e.name.localeCompare(t.name)),i)){let i=o.join(e.path,n.name);if(t(i,n)){r.push(i);continue}n.isDirectory()&&e.depth<5&&a.push({path:i,depth:e.depth+1})}}return r}async function ap(e){let t=await x.mkdtemp(o.join(F.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 x.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await x.rm(t,{recursive:!0,force:!0}),e}}function af(e){let t=e.toLowerCase();return at.some(e=>t.endsWith(e))}async function am(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let ah=new K("utf-16le");async function aw(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await ag(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]=av(e,t),[a,i]=av(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 ah.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 aA(e)}async function ag(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 av(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function aA(e){let t=await aI();if(!t)return;let r=await f(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function aI(){if(void 0!==e)return e??void 0;try{for(let t of rD()){let r=o.join(t,"build-tools");try{for(let t of(await n.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=o.join(r,t,"aapt");try{return await n.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function ay(e,t){let r="url"===e.kind&&al(e.url),a=await ai({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=o.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await ab(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function ab(e){let t=o.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await aw(e)}}let aS={settings:{type:"intent",value:"android.settings.SETTINGS"}},a_="android.intent.category.LAUNCHER",aN="android.intent.category.LEANBACK_LAUNCHER",aD="android.intent.category.DEFAULT";async function aE(e,t){let r=t.trim();if("package"===r7(r))return{type:"package",value:r};let a=aS[r.toLowerCase()];if(a)return a;let i=(await f("adb",rk(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 v("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:i});throw new v("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function aM(e,t="all"){let r=await ak(e);return("user-installed"===t?(await aO(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:ax(e)}))}async function ak(e){let t=new Set;for(let r of aL(e,{includeFallbackWhenUnknown:!0})){let a=await f("adb",rk(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 aL(e,t={}){return"tv"===e.target?[aN]:"mobile"===e.target?[a_]:t.includeFallbackWhenUnknown?[a_,aN]:[a_]}async function aO(e){return(await f("adb",rk(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function ax(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 aC(e){let t=await aP(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await aP(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function aP(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",rk(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function aR(e,t,r){e.booted||await r5(e.id);let a=t.trim();if(rC(a)){if(r)throw new v("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await f("adb",rk(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",a]));return}let i=await aE(e,t),n=aL(e)[0]??a_;if("intent"===i.type){if(r)throw new v("INVALID_ARGS","Activity override requires a package name, not an intent");await f("adb",rk(e,["shell","am","start","-W","-a",i.value]));return}if(r){let t=r.includes("/")?r:`${i.value}/${r.startsWith(".")?r:`.${r}`}`;await f("adb",rk(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aD,"-c",n,"-n",t]));return}let o=await f("adb",rk(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aD,"-c",n,"-p",i.value]),{allowFailure:!0});if(0===o.exitCode&&!a$(o.stdout,o.stderr))return;let s=await aT(e,i.value);if(!s)throw new v("COMMAND_FAILED",`Failed to launch ${i.value}`,{stdout:o.stdout,stderr:o.stderr});await f("adb",rk(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aD,"-c",n,"-n",s]))}async function aT(e,t){for(let r of Array.from(new Set(aL(e,{includeFallbackWhenUnknown:!0})))){let a=await f("adb",rk(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=aF(a.stdout);if(i)return i}return null}function a$(e,t){let r=`${e}
13
+ ${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(r)}function aF(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 aU(e){e.booted||await r5(e.id)}async function aV(e,t){if("settings"===t.trim().toLowerCase())return void await f("adb",rk(e,["shell","am","force-stop","com.android.settings"]));let r=await aE(e,t);if("intent"===r.type)throw new v("INVALID_ARGS","Close requires a package name, not an intent");await f("adb",rk(e,["shell","am","force-stop",r.value]))}async function aG(e,t){let r=await aE(e,t);if("intent"===r.type)throw new v("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await f("adb",rk(e,["uninstall",r.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
14
+ ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new v("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let aj=null;async function aB(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(aj?.key===e)return aj.invocation;if(await I("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return aj={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new v("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await x.access(t)}catch{throw new v("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return aj={key:e,invocation:r},r}async function aq(e){let t=await aB();await f(t.cmd,[...t.prefixArgs,...e])}async function aH(e,t){let r,a=await x.mkdtemp(o.join(F.tmpdir(),"agent-device-aab-")),i=o.join(a,"bundle.apks"),n=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await aq(["build-apks","--bundle",t,"--output",i,"--mode",n]),await aq(["install-apks","--apks",i,"--device-id",e.id])}finally{await x.rm(a,{recursive:!0,force:!0})}}async function aW(e,t){".aab"===o.extname(t).toLowerCase()?await aH(e,t):await f("adb",rk(e,["install","-r",t]))}async function az(e){return new Set((await f("adb",rk(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function aJ(e,t){let r=Array.from(await az(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function aK(e,t){e.booted||await r5(e.id),await aW(e,t)}async function aX(e,t,r){let a=r?void 0:await az(e);return await aK(e,t),r??(a?await aJ(e,a):void 0)}async function aY(e,t){e.booted||await r5(e.id);let r=await ay({kind:"path",path:t});try{let t=await aX(e,r.installablePath,r.packageName),a=t?ax(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function aZ(e,t,r){e.booted||await r5(e.id);let{package:a}=await aG(e,t),i=await ay({kind:"path",path:r},{resolveIdentity:!1});try{return await aK(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function aQ(e){let t=a0(e),r=e=>{let r=a1(t,e);if(null!==r)return"true"===r};return{text:a1(t,"text"),desc:a1(t,"content-desc"),resourceId:a1(t,"resource-id"),className:a1(t,"class"),bounds:a1(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function a0(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 a1(e,t){return e.get(t)??null}function a2(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 a3(e){return e?e.toLowerCase():""}function a4(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function a8(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=aQ(t),o=a2(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,v,A,I,y,b,S,_;if(i.length>=800){n=!0;return}if(t>o)return;let N=!!r.raw||(d=e,p=r,f=s,m=u(e),h=l,v=a3(d.type),A=!!(d.label&&d.label.trim().length>0),I=!!(d.identifier&&d.identifier.trim().length>0),y=A&&!a4(d.label??""),b=I&&!a4(d.identifier??""),S=(g=(w=v).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,_="imageview"===v||"imagebutton"===v,p.interactiveOnly?!!d.hittable||!!(y||b)&&!_&&(!S||!!h)&&(f||m||h):p.compact?y||b||!!d.hittable:!S&&!_||!!d.hittable||!!y||!!b&&!!m||m),D=a;N&&(D=i.length,i.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:t,parentIndex:a}));let E=s||!!e.hittable,M=l||function(e){if(!e)return!1;let t=a3(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,M),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 a5(e),0,t)}async function a5(e){return ei(()=>a6(e),{shouldRetry:a7})}async function a6(e){var t,r,a;let i,n,o=await f("adb",rk(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=a9(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await f("adb",rk(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,a=l.stderr,i=`${r}
15
+ ${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),u=await f("adb",rk(e,["shell","cat",d])),c=a9(u.stdout,u.stderr);if(!c)throw new v("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return c}function a9(e,t){let r=`${e}
16
+ ${t}`,a=r.indexOf("<?xml"),i=a>=0?a:r.indexOf("<hierarchy");if(i<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<i)return null;let o=r.slice(i,n+12).trim();return o.length>0?o:null}function a7(e){if(!(e instanceof v)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.details?.stderr??""}`.toLowerCase();return!!(t.includes("device offline")||t.includes("device not found")||t.includes("transport error")||t.includes("connection reset")||t.includes("broken pipe")||t.includes("timed out")||t.includes("no such file or directory"))}async function ie(e,t,r){await f("adb",rk(e,["shell","input","tap",String(t),String(r)]))}async function it(e,t,r,a,i,n=250){await f("adb",rk(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function ir(e){await f("adb",rk(e,["shell","input","keyevent","4"]))}async function ia(e){await f("adb",rk(e,["shell","input","keyevent","3"]))}async function ii(e){await f("adb",rk(e,["shell","input","keyevent","187"]))}async function io(e,t,r,a=800){await f("adb",rk(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function is(e,t){let r=ih(t);if(!r||"ok"!==await iw(e,t))try{let r=t.replace(/ /g,"%s");await f("adb",rk(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof v)||"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 v("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 il(e,t,r){await ie(e,t,r)}async function id(e,t,r,a){let i=Array.from(a).length,n=ih(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 il(e,t,r);let o=(l=i+n.clearPadding,d=n.minClear,Math.max(d,Math.min(n.maxClear,l)));if(await ig(e,o),"input_text"===n.strategy)await is(e,a);else if("clipboard_paste"===n.strategy){if("ok"!==await iw(e,a))continue}else await im(e,a,1,15);if((s=await iv(e,t,r))===a)return}throw new v("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:s??null})}async function iu(e,t,r=.6){let{width:a,height:i}=await ip(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,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 v("INVALID_ARGS",`Unknown direction: ${t}`)}await f("adb",rk(e,["shell","input","swipe",String(d),String(u),String(c),String(p),"300"]))}async function ic(e,t){for(let r=0;r<8;r+=1){let r="";try{r=await a5(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new v("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=a0(i[0]),n=(a1(t,"text")??"").toLowerCase(),o=(a1(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=a2(a1(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 iu(e,"down",.5)}throw new v("COMMAND_FAILED",`Could not find element containing "${t}" after scrolling`)}async function ip(e){let t=(await f("adb",rk(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new v("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function im(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 is(e,r),a>0&&t+i<n.length&&await rx(a)}}function ih(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 iw(e,t){let r=await f("adb",rk(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":rO(r.stdout,r.stderr)?"unsupported":0===(await f("adb",rk(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await f("adb",rk(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function ig(e,t){let r=Math.max(0,t);await f("adb",rk(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 f("adb",rk(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function iv(e,t,r){let a,i=await a5(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=aQ(a[0]),i=a2(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&&iA(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&iA(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 iA(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iI(e){let t=await f("adb",rk(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new v("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 iy(e){let t=await iI(e),r=t,a=0;for(;r.visible&&a<2;)await ir(e),a+=1,await rx(120),r=await iI(e);return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function ib(e){let t,r;return(r=(t=(await i_(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 iS(e,t){await i_(e,["shell","cmd","clipboard","set","text",t],"write")}async function i_(e,t,r){let a=await f("adb",rk(e,t),{allowFailure:!0});if(rO(a.stdout,a.stderr))throw new v("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new v("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let iN=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iD(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new v("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iE(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 v("INVALID_ARGS",`permission setting requires a target: ${iN.join("|")}`)}function iM(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new v("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function ik(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=iO(r);await f("adb",rk(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=iO(r);await f("adb",rk(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await f("adb",rk(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=iO(r);await f("adb",rk(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await ix(e,r);await f("adb",rk(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 v("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await iL(e,t);return}case"permission":{if(!a)throw new v("INVALID_ARGS","permission setting requires an active app in session");let t=iD(r),n=function(e,t){let r=iE(e);if(t?.trim())throw new v("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 v("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 iP(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await iC(e,a,o);await f("adb",rk(e,["shell","pm",o,a,n.value]));return}default:throw new v("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function iL(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 f("adb",rk(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
17
+ ${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new v("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 v("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function iO(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 v("INVALID_ARGS",`Invalid setting state: ${e}`)}async function ix(e,t){let r=iM(t);if("toggle"!==r)return r;let a=await f("adb",rk(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new v("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
18
+ ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new v("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 iC(e,t,r){let a=await iR(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 f("adb",rk(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 v("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function iP(e,t,r,a){"grant"===r?await f("adb",rk(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await f("adb",rk(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await f("adb",rk(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await f("adb",rk(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await f("adb",rk(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function iR(e){let t=await f("adb",rk(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 iT(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 v("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 v("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await f("adb",rk(e,i)),{action:a,extrasCount:s}}let i$=Buffer.from([137,80,78,71,13,10,26,10]),iF={enableDemoMode:iV,settle:rx,capture:ij,disableDemoMode:iG};async function iU(e,t,r=iF){await r.enableDemoMode(e);try{await r.settle(1e3),await r.capture(e,t)}finally{await r.disableDemoMode(e).catch(()=>{})}}async function iV(e){let t=t=>f("adb",rk(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 iG(e){await f("adb",rk(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function ij(e,t){let r=await f("adb",rk(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new v("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(i$);if(a<0)throw new v("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let i=function(e,t){let r=t+i$.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 v("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await x.writeFile(t,r.stdoutBuffer.subarray(a,i))}let iB=e_(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,ee,5e3),iq=e_(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,Q,1e3),iH=e_(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),iW=e_(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),iz=e_(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),iJ=e_(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),iK=e_(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function iX(e,t){let r=["devicectl",...e],a=await f("xcrun",r,{allowFailure:!0,timeoutMs:iW});if(0===a.exitCode)return;let i=String(a.stdout??""),n=String(a.stderr??"");throw new v("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:t.deviceId,hint:i0(i,n)??iQ})}async function iY(e,t){let r=o.join(F.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),a=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],i=await f("xcrun",a,{allowFailure:!0,timeoutMs:iW});try{var n,s;if(0!==i.exitCode){let t=String(i.stdout??""),r=String(i.stderr??"");throw new v("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:i.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:i0(t,r)??iQ})}let o=await x.readFile(r,"utf8");return n=iZ(JSON.parse(o)),s=t,"user-installed"===s?n.filter(e=>!e.bundleId.startsWith("com.apple.")):n}catch(t){if(t instanceof v)throw t;throw new v("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await x.unlink(r).catch(()=>{})}}function iZ(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 iQ="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function i0(e,t){let r=`${e}
19
+ ${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function i1(e){if(!(e instanceof v)||"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 i2(e,t){let r=await f("xcrun",eC(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 f("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 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 i3(e,t){if("simulator"!==e.kind)throw new v("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function i4(){await f("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:iz})}async function i8(e){let t,r;if("simulator"!==e.kind||"Booted"===await i6(e))return;let a=er.fromTimeoutMs(iB);try{await ea(async({deadline:a})=>{if(a?.isExpired())throw new v("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:iB});let i=Math.max(1e3,a?.remainingMs()??iB),n=await f("xcrun",eC(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode};let o=`${t.stdout}
20
+ ${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new v("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await f("xcrun",eC(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 v("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await i6(e);if("Booted"!==d)throw new v("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=ev({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=>ev({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(n){let i=ev({error:n,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new v("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:iB,elapsedMs:a.elapsedMs(),reason:i,hint:eA(i),boot:t,bootstatus:r})}}async function i5(e){let t=eC(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 i6(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?ex(["list","devices","-j"]):eC(e,["list","devices","-j"]),a=await f("xcrun",r,{allowFailure:!0,timeoutMs:iq});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 i9(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 x.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 i7(e,t){if("url"===e.kind&&!al(e.url))throw new v("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 ai({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||al(e.url),signal:t?.signal}),a=await nt(r.installablePath,t),i=await ne(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 ne(e){let t=o.join(e,"Info.plist"),[r,a,i]=await Promise.all([i9(t,"CFBundleIdentifier"),i9(t,"CFBundleDisplayName"),i9(t,"CFBundleName")]);return{bundleId:r,appName:a??i}}async function nt(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await x.mkdtemp(o.join(F.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await x.rm(r,{recursive:!0,force:!0})};try{await f("ditto",["-x","-k",e,r]);let i=o.join(r,"Payload"),n=(await x.readdir(i,{withFileTypes:!0}).catch(()=>{throw new v("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:o.join(i,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===n.length)return{installPath:n[0].installPath,cleanup:a};if(0===n.length)throw new v("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await nr(n);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 v("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:a};throw new v("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload and none matched "${s}". Available bundles: ${n.map(na).join(", ")}`)}throw new v("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${n.map(na).join(", ")}`)}catch(e){throw await a(),e}}async function nr(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await ne(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function na(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function ni(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let nn={settings:"com.apple.systempreferences"},no=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function ns(e){return e.replace(/\\/g,"\\\\").replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/"/g,'\\"')}function nl(e,t){let r=["-b",e];return t&&r.push(t),r}async function nd(e){for(let t of[o.join(e,"Contents","Info.plist"),o.join(e,"Info.plist")]){let[e,r,a]=await Promise.all([i9(t,"CFBundleIdentifier"),i9(t,"CFBundleDisplayName"),i9(t,"CFBundleName")]);if(e||r||a)return{bundleId:e,appName:r??a}}return{}}async function nu(e){let t=e.trim(),r=nn[t.toLowerCase()];if(r)return r;let a=`id of app "${ns(t)}"`,i=await f("osascript",["-e",a],{allowFailure:!0});if(0===i.exitCode){let e=i.stdout.trim();if(e)return e}let n=(await ng("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===n.length)return n[0].bundleId;if(n.length>1)throw new v("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:n});if(no.test(t))return t;throw new v("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function nc(e,t,r){let a=r?.url?.trim();if(a){if(!rC(a))throw new v("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await nu(t);await f("open",nl(e,a));return}let i=t.trim();if(rC(i))return void await f("open",[i]);let n=r?.appBundleId??await nu(i);await f("open",nl(n))}async function np(e,t){let r=await nu(t),a=`tell application id "${ns(r)}" to quit`,i=await f("osascript",["-e",a],{allowFailure:!0});if(0===i.exitCode)return;let n=`${i.stdout}
21
+ ${i.stderr}`.toLowerCase();if(!(n.includes("isn’t running")||n.includes("isn't running")))throw new v("COMMAND_FAILED",`Failed to close macOS app ${t}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function nf(){let e=await f("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new v("COMMAND_FAILED","Failed to read macOS clipboard",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});return e.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function nm(e){let t=await f("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new v("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function nh(){let e=await f("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new v("COMMAND_FAILED","Failed to read macOS appearance",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});let t=e.stdout.trim().toLowerCase();if("true"===t)return!0;if("false"===t)return!1;throw new v("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function nw(e){let t=iM(e),r="toggle"===t?!await nh():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${r?"true":"false"}`,i=await f("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new v("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function ng(e="all"){let t=["/Applications","/System/Applications",o.join(F.homedir(),"Applications")],r=new Set;for(let e of t){let t=await x.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await f("find",[e,"-maxdepth","4","-type","d","-name","*.app"],{allowFailure:!0});if(0===a.exitCode)for(let e of a.stdout.split("\n")){let t=e.trim();t&&r.add(t)}}return ni((await Promise.all(Array.from(r).map(async e=>{let t=await nd(e).catch(()=>({})),r=t.bundleId;return r?{bundleId:r,name:t.appName??o.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let nv=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],nA={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"},nI={1:"searching",2:"failed",3:"active"},ny={0:"notSupported",1:"searching",2:"failed",3:"active"};function nb(e,t,r){return f("xcrun",eC(e,t),r)}async function nS(e,t){var r,a;let i;await nN(e),t&&await nD(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 n_(e){let t=await nb(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new v("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=nA[r];if(!a)throw new v("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=nI[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=ny[e];if(!r)throw new v("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 nN(e){await nb(e,["status_bar",e.id,"clear"])}async function nD(e,t){0!==t.length&&await nb(e,["status_bar",e.id,"override",...t])}function nE(e,t,r){O({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof v))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 nM(e,t,r){return f("xcrun",eC(e,t),r)}let nk={ensureBooted:i8,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await n_(e),r=!0}catch(t){nE(e,"snapshot_failed",t)}try{await nN(e),await nD(e,nv)}catch(t){nE(e,"prepare_failed",t)}return async()=>{await nS(e,r?t:null)}},captureWithRetry:nx,captureWithRunner:nC,shouldFallbackToRunner:nV};async function nL(e,t,r){if("macos"===e.platform)return void await nC(e,t,r);if("simulator"===e.kind)return void await nO(e,t,r);try{await iX(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof v)||"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}
21
22
  ${r}
22
- ${a}`.toLowerCase();return i.includes("unknown option '--device'")||i.includes("unknown subcommand")&&i.includes("screenshot")||i.includes("unrecognized subcommand")&&i.includes("screenshot")}(t))throw t;nM(e,"devicectl_screenshot",t)}await nk(e,t,r)}async function nD(e,t,r,a=nN){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){nC(e,"prepare_failed",t)}try{try{await a.captureWithRetry(e,t);return}catch(t){if(!a.shouldFallbackToRunner(t))throw t;nM(e,"simctl_screenshot",t)}await a.captureWithRunner(e,t,r)}finally{await i().catch(t=>nC(e,"restore_failed",t))}}async function nE(e,t){let r=ee.fromTimeoutMs(ij);await iQ(),await et(async({attempt:r,deadline:a})=>{r>1&&await iQ(),await nS(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,a?.remainingMs()??ij)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>nP(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function nk(e,t,r){let a=(await tA(e,{command:"screenshot",appBundleId:r})).message;if(!a)throw new w("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await O.copyFile(a,t):"simulator"===e.kind?await nO(e,a,t):await nL(e,a,t)}async function nL(e,t,r){let a=ee.fromTimeoutMs(iq),i={exitCode:1,stdout:"",stderr:""};for(let n of e5)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:nx(a,iq,"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 nO(e,t,r){let a=ee.fromTimeoutMs(iq),n="Unable to locate runner container for simulator screenshot";for(let o of e5){let s=await nS(e,["get_app_container",e.id,o,"data"],{allowFailure:!0,timeoutMs:nx(a,iq,"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 O.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 nx(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 nM(e,t,r){let a=nR(r);L({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function nC(e,t,r){L({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...nR(r)}})}function nR(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 nP(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}
23
+ ${a}`.toLowerCase();return i.includes("unknown option '--device'")||i.includes("unknown subcommand")&&i.includes("screenshot")||i.includes("unrecognized subcommand")&&i.includes("screenshot")}(t))throw t;n$(e,"devicectl_screenshot",t)}await nC(e,t,r)}async function nO(e,t,r,a=nk){if("simulator"!==e.kind)throw new v("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){nF(e,"prepare_failed",t)}try{try{await a.captureWithRetry(e,t);return}catch(t){if(!a.shouldFallbackToRunner(t))throw t;n$(e,"simctl_screenshot",t)}await a.captureWithRunner(e,t,r)}finally{await i().catch(t=>nF(e,"restore_failed",t))}}async function nx(e,t){let r=er.fromTimeoutMs(iJ);await i4(),await ea(async({attempt:r,deadline:a})=>{r>1&&await i4(),await nM(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,a?.remainingMs()??iJ)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>nV(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function nC(e,t,r){let a=(await tS(e,{command:"screenshot",appBundleId:r})).message;if(!a)throw new v("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await x.copyFile(a,t):"simulator"===e.kind?await nR(e,a,t):await nP(e,a,t)}async function nP(e,t,r){let a=er.fromTimeoutMs(iK),i={exitCode:1,stdout:"",stderr:""};for(let n of e7)if(0===(i=await f("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",n],{allowFailure:!0,timeoutMs:nT(a,iK,"runner screenshot copy")})).exitCode)return;let n=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new v("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}async function nR(e,t,r){let a=er.fromTimeoutMs(iK),i="Unable to locate runner container for simulator screenshot";for(let n of e7){let s=await nM(e,["get_app_container",e.id,n,"data"],{allowFailure:!0,timeoutMs:nT(a,iK,"runner screenshot container lookup")});if(0!==s.exitCode){let e=s.stderr.trim();e&&(i=e);continue}let l=s.stdout.trim();if(!l){i="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=o.resolve(e),a=t.trim();if(!a)return[];let i=[],n=new Set,s=e=>{let t=o.normalize(e);n.has(t)||(n.add(t),i.push(t))},l=a.replace(/^\/+/,""),d=l.replace(/\\/g,"/");if(l&&s(o.join(r,l)),o.isAbsolute(a)&&s(o.normalize(a)),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(a);return u&&s(o.join(r,"tmp",u)),i}(l,t))try{await x.copyFile(e,r);return}catch(e){i=e instanceof Error?e.message:String(e)}}throw new v("COMMAND_FAILED",`Failed to capture iOS screenshot: ${i}`)}function nT(e,t,r){let a=e.remainingMs();if(a>0)return a;throw new v("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function n$(e,t,r){let a=nU(r);O({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function nF(e,t,r){O({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...nU(r)}})}function nU(e){if(!(e instanceof v))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 nV(e){if(!(e instanceof v)||"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}
23
24
  ${r}
24
25
  ${a}
25
- ${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 nT={settings:"com.apple.Preferences"},n$=null;function nF(e,t,r){return c("xcrun",ex(e,t),r)}function nU(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function nV(e,t){if("macos"===e.platform)return await nn(t);let r=t.trim();if(r.includes("."))return r;let a=nT[r.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await nQ(e):await iW(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 nG(e,t,r){if("macos"===e.platform)return void await no(e,t,r);let a=r?.url?.trim();if(a){if(!rk(a))throw new w("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await i0(e),await iQ(),await nF(e,["openurl",e.id,a]);return}let i=rL(r?.appBundleId??await nV(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 n9(e,i,{payloadUrl:a});return}let i=t.trim();if(rk(i)){if("simulator"===e.kind){await i0(e),await iQ(),await nF(e,["openurl",e.id,i]);return}let t=rL(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 n9(e,t,{payloadUrl:i});return}let n=r?.appBundleId??await nV(e,t);"simulator"===e.kind?await n5(e,n):await n9(e,n)}async function nB(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await i2(e)&&(await i0(e),await iQ())}async function nj(e,t){if("macos"===e.platform)return void await ns(e,t);let r=await nV(e,t);if("simulator"===e.kind){await i0(e);let t=ex(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 iH(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function nq(e,t){let r=await nV(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],a=await c("xcrun",t,{allowFailure:!0,timeoutMs:iG});if(0!==a.exitCode){let i=String(a.stdout??""),n=String(a.stderr??"");if(!nU(`${i}
26
- ${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:iK(i,n)??iJ})}return{bundleId:r}}await i0(e);let a=await nF(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==a.exitCode&&!nU(`${a.stdout}
27
- ${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 nH(e,t,r){let a=await i4({kind:"path",path:t},r);try{return await nz(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function nW(e,t,r){let{bundleId:a}=await nq(e,t);return await nH(e,r,{appIdentifierHint:t}),{bundleId:a}}async function nz(e,t){"simulator"!==e.kind?await iH(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await i0(e),await nF(e,["install",e.id,t]))}async function nJ(e){if("macos"===e.platform)return await nl();iY(e,"clipboard"),await i0(e);let t=await nF(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 nK(e,t){if("macos"===e.platform)return void await nd(t);iY(e,"clipboard"),await i0(e);let r=await nF(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 nX(e,t,r){iY(e,"push"),await i0(e);let a=await O.mkdtemp(i.join(T.tmpdir(),"agent-device-ios-push-")),n=i.join(a,"payload.apns");try{await O.writeFile(n,`${JSON.stringify(r)}
28
- `,"utf8"),await nF(e,["push",e.id,t,n])}finally{await O.rm(a,{recursive:!0,force:!0})}}async function nZ(e,t,r,a,i){if("macos"===e.platform){if("appearance"!==t.toLowerCase())throw new w("INVALID_ARGS",`Unsupported macOS setting: ${t}. macOS currently supports only settings appearance <light|dark|toggle>.`);await nc(r);return}iY(e,"settings"),await i0(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=n0(r);await nF(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(n0(r)?await nF(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await nF(e,["status_bar",e.id,"clear"]));case"location":{let t=n0(r);if(!a)throw new w("INVALID_ARGS","location setting requires an active app in session");await nF(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=n2[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 n6(e,a,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await n1(e,r);await nF(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=iy(r))?"revoke":o,n=function(e,t){let r=ib(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 n3(e,t,n,a);return}default:throw new w("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function nY(e,t="all"){return"macos"===e.platform?await np(t):"simulator"===e.kind?i7(await nQ(e),t):await iW(e,t)}async function nQ(e){let t=(await nF(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 n0(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 n1(e,t){let r=iS(t);if("toggle"!==r)return r;let a=await nF(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}
29
- ${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 n2={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function n3(e,t,r,a){let i=await n8(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 nF(e,n);return}catch(t){if(!(o&&n4(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 nF(e,n);return}catch(e){if(!n4(e))throw e}try{await nF(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 n4(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 n8(e){let r=eE(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(n$&&t===a)return n$;let i=await nF(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}
30
- ${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 n$=n,t=a,n}async function n6(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=ex(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}
31
- ${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 n5(e,t){await i0(e),await iQ();let r=0,a=ee.fromTimeoutMs(iV);try{await et(async({deadline:r})=>{var a;if(r?.isExpired())throw new w("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:iV});let i=(a=["launch",e.id,t],ex(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=>!!iX(e)&&(r+=1)<3},{deadline:a})}catch(r){if(iX(r)){var i;let a=(i=await iZ(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 n9(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await iH(a,{action:"launch iOS app",deviceId:e.id})}function n7(e){return e?.clickButton??"primary"}function oe(e){return"primary"===e.button?null:"click"!==e.commandLabel?new w("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new w("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new w("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new w("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let ot=/^[A-Za-z0-9_.:-]{1,64}$/,or=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function oa(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 oi(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await on(t)}async function on(e){await new Promise(t=>setTimeout(t,e))}function oo(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(!R.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 os(e){let t=oo(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await ol(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 ol(e){try{return await O.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 od=eb(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),ou=/^(iphone|ipad|ipod|appletv)/i,oc=/^appletv/i,op=["apple tv","appletv","tvos"];function of(e){return(e??"").trim().toLowerCase()}function om(e){return of(e.hardwareProperties?.platform)}function oh(e){return e.includes("tvos")}function ow(e){return oh(of(e))?"tv":"mobile"}function og(e){let t=of(e);return t.includes("ios")||t.includes("tvos")}function oI(e){let t=of(e);return op.some(e=>t.includes(e))}function oA(e){return ou.test(e.trim())}function ov(e){return oc.test(e.trim())}function oy(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function ob(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}function oS(e){return oh(om(e))||ov(ob(e))||oy(e).some(oI)?"tv":"mobile"}function oN(e){let t=om(e);return!!(t.includes("ios")||t.includes("tvos")||oA(ob(e)))||oy(e).some(oI)}async function o_(e={}){let t,r,a=eE(e.simulatorSetPath),i=e.target;try{t=await c("xcrun",eO(["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(!og(e))continue;let r=ow(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 oD(e={}){if("darwin"!==process.platform)throw new w("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await I("xcrun"))throw new w("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eE(e.simulatorSetPath),a=await c("xcrun",eO(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(og(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:ow(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(t.push({platform:"macos",id:"host-macos-local",name:T.hostname(),kind:"device",target:"desktop",booted:!0}),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:od});if(0!==e.exitCode)return t;let r=await O.readFile(n,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(oN(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:oS(e),booted:!0})}}catch{}finally{n&&await O.rm(n,{force:!0}).catch(()=>{})}return t}async function oE(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&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!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 ok(e){let t=e.platform,r=eZ({simulatorSetPath:eE(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=eL(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|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await r_();let e=await rH({serialAllowlist:a});return await eY(e,i)}if(i.platform){let e=await oD({simulatorSetPath:r});return await oE(e,i,{simulatorSetPath:r},{resolveDevice:eY,findBootableSimulator:o_})}let n=[];try{n.push(...await rH({serialAllowlist:a}))}catch{}try{n.push(...await oD({simulatorSetPath:r}))}catch{}return await eY(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function oL(e,t,r,a,n){let o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>aO(e,t,r?.activity),openDevice:()=>aR(e),close:t=>aP(e,t),tap:(t,r)=>a8(e,t,r),doubleTap:async(t,r)=>{await a8(e,t,r),await a8(e,t,r)},swipe:(t,r,a,i,n)=>a6(e,t,r,a,i,n),longPress:(t,r,a)=>ie(e,t,r,a),focus:(t,r)=>ir(e,t,r),type:t=>it(e,t),fill:(t,r,a)=>ia(e,t,r,a),scroll:(t,r)=>ii(e,t,r),scrollIntoView:t=>io(e,t),screenshot:(t,r)=>iR(e,t),back:()=>a5(e),home:()=>a9(e),appSwitcher:()=>a7(e),readClipboard:()=>ig(e),writeClipboard:t=>iI(e,t),setSetting:(t,r,a,i)=>iN(e,t,r,a,i)};case"ios":case"macos":{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(ep(a.requestId))throw em()},{runnerOpts:i,overrides:{tap:async(e,t)=>{await tA(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i)},doubleTap:async(e,t)=>{await tA(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 tA(r,{command:"drag",x:e,y:t,x2:n,y2:o,durationMs:s,appBundleId:a.appBundleId},i)},longPress:async(e,t,n)=>{await tA(r,{command:"longPress",x:e,y:t,durationMs:n,appBundleId:a.appBundleId},i)},focus:async(e,t)=>{await tA(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i)},type:async e=>{await tA(r,{command:"type",text:e,appBundleId:a.appBundleId},i)},fill:async(e,t,n)=>{await tA(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),await tA(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 tA(r,{command:"swipe",direction:n,appBundleId:a.appBundleId},i)},scrollIntoView:async e=>{let t=await tA(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 tA(r,{command:"swipe",direction:"up",appBundleId:a.appBundleId},i),await new Promise(e=>setTimeout(e,80));n();let o=await tA(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)=>nG(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>nB(e),close:t=>nj(e,t),screenshot:(t,r)=>n_(e,t,r),back:async()=>{await tA(e,{command:"back",appBundleId:t.appBundleId},s)},home:async()=>{await tA(e,{command:"home",appBundleId:t.appBundleId},s)},appSwitcher:async()=>{await tA(e,{command:"appSwitcher",appBundleId:t.appBundleId},s)},readClipboard:()=>nJ(e),writeClipboard:t=>nK(e,t),setSetting:(t,r,a,i)=>nZ(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 L({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("android"===e.platform)throw new w("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(rk(t))throw new w("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!rk(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=n7(n);if("primary"!==i){let r=oe({commandLabel:"click",platform:e.platform,button:i,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(r)throw r;return await tA(e,{command:"mouseClick",x:t,y:a,button:i,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{x:t,y:a,button:i}}let s=oa(n?.count??1,"count",1,200),l=oa(n?.intervalMs??0,"interval-ms",0,1e4),d=oa(n?.holdMs??0,"hold-ms",0,1e4),u=oa(n?.jitterPx??0,"jitter-px",0,100),c=n?.doubleTap===!0;if(c&&d>0)throw new w("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(c&&u>0)throw new w("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&s>1&&0===d&&0===u)return await tA(e,{command:"tapSeries",x:t,y:a,count:s,intervalMs:l,doubleTap:c,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{x:t,y:a,count:s,intervalMs:l,holdMs:d,jitterPx:u,doubleTap:c,timingMode:"runner-series"};return await oi(s,l,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=or[e%or.length];return[r*t,a*t]}(e,u),n=t+r,s=a+i;c?await o.doubleTap(n,s):d>0?await o.longPress(n,s,d):await o.tap(n,s)}),{x:t,y:a,count:s,intervalMs:l,holdMs:d,jitterPx:u,doubleTap:c}}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=oa(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=oa(n?.count??1,"count",1,200),c=oa(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||"macos"===e.platform)&&u>1)return await tA(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 oi(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 tA(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(!ot.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){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new 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 o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new w("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await o.open(i,{appBundleId:n?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link"}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await O.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 iw(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 ih(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 L({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 os(a);if("ios"===e.platform)return await nX(e,t,i),{platform:"ios",bundleId:t};let n=await ix(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount}}case"snapshot":{if("android"!==e.platform){let t=await E("snapshot_capture",async()=>await tA(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 a0(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 oO=e=>"macos"!==e.platform,ox={alert:{apple:{simulator:!0},android:{}},pinch:{apple:{simulator:!0},android:{}},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{},android:{emulator:!0,device:!0,unknown:!0}},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oO},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function oM(e,t){let r=ox[e];if(!r)return!0;let a=eK(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function oC(e,t,r,a,i){return{requestId:i??_().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,clickButton:n7(t),pauseMs:t?.pauseMs,pattern:t?.pattern}}let oR=eb(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function oP(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:i0}));await t(e);return}if("device"===e.kind)return void await oT(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:r1}));await t(e.id)}}async function oT(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(oR/1e3));try{let a=await c("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:oR+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await o$(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:oF(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??oR),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?oF(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 O.rm(t,{force:!0}).catch(()=>{})}}async function o$(e){try{let t=await O.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 oF(e,t){let r=iK(e,t);return r||(`${e}
32
- ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":iJ)}function oU(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function oV(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function oG(e,t){return e.find(e=>e.ref===t)??null}function oB(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function oj(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 oq(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&&oH(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||!oH(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&&oH(r)?r:void 0)}function oH(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function oW(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=oz(a.type??""),n=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&oH(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 oz(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 oJ(e,t){let r=oz(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 oK(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let oX=new Set(["id","role","text","label","value"]),oZ=new Set(["visible","hidden","editable","selected","enabled","hittable"]),oY=new Set([...oX,...oZ]);function oQ(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)&&!o8(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)&&!o8(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(o3)}})(e))}}function o0(e){try{return oQ(e)}catch{return null}}function o1(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 oY.has(e)}return oY.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&o0(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 o2(e){let t=e[0]??"",r=o1(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function o3(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(!oZ.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(!oY.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(oZ.has(a)){let e,t="true"===(e=o4(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:o4(i)}}function o4(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function o8(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function o6(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return o7(e.identifier,String(t.value));case"role":var a,i;return a=e.type,i=String(t.value),function(e){return oz(e)}(a??"")===function(e){return oz(e)}(i);case"label":return o7(e.label,String(t.value));case"value":return o7(e.value,String(t.value));case"text":{let r=se(String(t.value));return se(oK(e))===r}case"visible":return o5(e)===!!t.value;case"hidden":return!o5(e)==!!t.value;case"editable":return o9(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 o5(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function o9(e,t){return oJ(e.type??"",t)&&!1!==e.enabled}function o7(e,t){return se(e??"")===se(t)}function se(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function st(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||!o6(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=si(e),n=si(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 sr(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)&&o6(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 sa(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 si(e){return e.rect?e.rect.width*e.rect.height:1/0}function sn(e,t,r={}){let a=[],i=oz(e.type??""),n=ss(e.identifier),o=ss(e.label),s=ss(e.value),l=ss(oK(e)),d="fill"===r.action;n&&a.push(`id=${so(n)}`),i&&o&&a.push(d?`role=${so(i)} label=${so(o)} editable=true`:`role=${so(i)} label=${so(o)}`),o&&a.push(d?`label=${so(o)} editable=true`:`label=${so(o)}`),s&&a.push(d?`value=${so(s)} editable=true`:`value=${so(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${so(l)} editable=true`:`text=${so(l)}`),i&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${so(i)} editable=true`);let u=tb(a);return 0===u.length&&i&&u.push(d?`role=${so(i)} editable=true`:`role=${so(i)}`),0===u.length&&o5(e)&&u.push("visible=true"),u}function so(e){return JSON.stringify(e)}function ss(e){if(!e)return null;let t=e.trim();return t||null}let sl=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),sd=/https?:\/\/[^\s"'<>\])]+/i,su=[/\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 sc(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 sp(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return sf(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 sf(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function sm(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function sh(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}let sw="shared_prefs/ReactNativeDevPrefs.xml",sg="debug_http_host",sI="dev_server_https",sA="RCT_jsLocation",sv="RCT_packager_scheme",sy="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",sb='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function sS(e){return void 0!==sN(e)}function sN(e){if(!e)return;let t=sT(e.metroHost),r=sF(e.metroPort),a="http",i=sT(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??=sT(e.hostname),r??=sF(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 s_(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=sN(a);if(i){if("android"===t.platform)return void await sE(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await sx(t,r,i)}}async function sD(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await sk(t,r);"ios"===t.platform&&"simulator"===t.kind&&await sM(t,r)}}async function sE(e,t,r){var a,i,n,o,s,l;let d,u;s$(t);let c=(a=await sL(e,t),i=sg,n=`${r.host}:${r.port}`,d=` <string name="${sU(i)}">${sU(n)}</string>`,sR(sP(a,i),d));o=c,s=sI,l="https"===r.scheme,u=` <boolean name="${sU(s)}" value="${l?"true":"false"}" />`,c=sR(sP(o,s),u),await sO(e,t,c)}async function sk(e,t){s$(t);let r=await sL(e,t),a=sP(r,sg),i=sP(a,sI);i!==r&&await sO(e,t,i)}async function sL(e,t){let r=await c("adb",rN(e,["shell","run-as",t,"cat",sw]),{allowFailure:!0});return 0!==r.exitCode?sb:sC(r.stdout)}async function sO(e,t,r){let a=rN(e,["shell","run-as",t,"id"]),i=await c("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=sV(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?sy:"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",rN(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await c("adb",rN(e,["shell","run-as",t,"tee",sw]),{stdin:r.trimEnd()})}catch(a){let e=f(a);if("TOOL_MISSING"===e.code)throw e;let r=sV("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?sy:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function sx(e,t,r){await c("xcrun",ex(e,["spawn",e.id,"defaults","write",t,sA,"-string",`${r.host}:${r.port}`])),await c("xcrun",ex(e,["spawn",e.id,"defaults","write",t,sv,"-string",r.scheme]))}async function sM(e,t){await c("xcrun",ex(e,["spawn",e.id,"defaults","delete",t,sA]),{allowFailure:!0}),await c("xcrun",ex(e,["spawn",e.id,"defaults","delete",t,sv]),{allowFailure:!0})}function sC(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
33
- `:sb}function sR(e,t){return sC(e).replace("</map>",`${t}
34
- </map>`)}function sP(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return sC(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 sT(e){let t=e?.trim();return t&&t.length>0?t:void 0}function s$(e){if("binary"!==r4(e))return;let t=r8(e);throw new w("INVALID_ARGS",t,{package:e,hint:t})}function sF(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function sU(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function sV(e,t){let r=`${e}
35
- ${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 sG(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=o1(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 sB(e){return!!e&&!Number.isNaN(Number(e))}let sj=eb(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),sq=new Map;async function sH(e){let t=await a.mkdtemp(i.join(T.tmpdir(),"agent-device-materialized-"));try{let r=await sJ(e.installablePath,i.join(t,"installable")),a=e.archivePath?await sJ(e.archivePath,i.join(t,"archive")):void 0,n=u.randomUUID(),o=e.ttlMs??sj,s=Date.now()+o,l=setTimeout(()=>{sW(n)},o);return sq.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 sW(e,t){let r=sq.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),sq.delete(e),await a.rm(r.rootPath,{recursive:!0,force:!0})}async function sz(e){let t=Array.from(sq.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await sW(e)}))}async function sJ(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 sK(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 oP(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 ok(e.flags??{});return await oP(a),a}async function sX(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:t1(s,t.meta?.tenantId)},cleanup:()=>{t2(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??sK)({session:n,flags:t.flags});if(!oM("install",u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let c=(i?.getRequestSignal??ef)(t.meta?.requestId);if("ios"===u.platform){let e,o=i?.installIosInstallablePath??(await Promise.resolve().then(()=>({closeIosApp:nj,ensureBootedSimulator:i0,installIosApp:nH,installIosInstallablePath:nz,listIosApps:nY,listSimulatorApps:nQ,openIosApp:nG,openIosDevice:nB,parseIosDeviceAppsPayload:iz,pushIosNotification:nX,readIosClipboardText:nJ,reinstallIosApp:nW,resolveIosApp:nV,screenshotIos:n_,setIosSetting:nZ,uninstallIosApp:nq,writeIosClipboardText:nK}))).installIosInstallablePath,s=i?.prepareIosInstallArtifact??(await Promise.resolve().then(()=>({prepareIosInstallArtifact:i4,readIosBundleInfo:i8}))).prepareIosInstallArtifact,p=await s(l.source,{signal:c});try{if(d.enabled&&(e=await sH({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 sW(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),l.cleanup()}}let p=i?.prepareAndroidInstallArtifact??(await Promise.resolve().then(()=>({prepareAndroidInstallArtifact:aw}))).prepareAndroidInstallArtifact,f=i?.installAndroidInstallablePathAndResolvePackageName??(await Promise.resolve().then(()=>({appSwitcherAndroid:a7,backAndroid:a5,closeAndroidApp:aP,dismissAndroidKeyboard:iw,ensureAdb:r_,fillAndroid:ia,focusAndroid:ir,getAndroidAppState:ak,getAndroidKeyboardState:ih,homeAndroid:a9,inferAndroidAppName:aE,installAndroidApp:aW,installAndroidInstallablePath:aq,installAndroidInstallablePathAndResolvePackageName:aH,isAmStartError:aM,listAndroidApps:aS,longPressAndroid:ie,openAndroidApp:aO,openAndroidDevice:aR,parseAndroidLaunchComponent:aC,pressAndroid:a8,pushAndroidNotification:ix,readAndroidClipboardText:ig,reinstallAndroidApp:az,resolveAndroidApp:ab,screenshotAndroid:iR,scrollAndroid:ii,scrollIntoViewAndroid:io,setAndroidSetting:iN,snapshotAndroid:a0,swipeAndroid:a6,typeAndroid:it,writeAndroidClipboardText:iI}))).installAndroidInstallablePathAndResolvePackageName,m=await p(l.source,{signal:c});try{d.enabled&&(e=await sH({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:a7,backAndroid:a5,closeAndroidApp:aP,dismissAndroidKeyboard:iw,ensureAdb:r_,fillAndroid:ia,focusAndroid:ir,getAndroidAppState:ak,getAndroidKeyboardState:ih,homeAndroid:a9,inferAndroidAppName:aE,installAndroidApp:aW,installAndroidInstallablePath:aq,installAndroidInstallablePathAndResolvePackageName:aH,isAmStartError:aM,listAndroidApps:aS,longPressAndroid:ie,openAndroidApp:aO,openAndroidDevice:aR,parseAndroidLaunchComponent:aC,pressAndroid:a8,pushAndroidNotification:ix,readAndroidClipboardText:ig,reinstallAndroidApp:az,resolveAndroidApp:ab,screenshotAndroid:iR,scrollAndroid:ii,scrollIntoViewAndroid:io,setAndroidSetting:iN,snapshotAndroid:a0,swipeAndroid:a6,typeAndroid:it,writeAndroidClipboardText:iI}))).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 sW(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await m.cleanup(),l.cleanup()}}catch(e){return{ok:!1,error:y(e)}}}async function sZ(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 sW(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:y(e)}}}async function sY(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 sQ({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await s0({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await s1(t,u),a=!0)}else t=(await s0({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await s1(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 sQ(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await c("xcrun",eO(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:iU});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||s2(a).includes(s2(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 s0(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await c("xcrun",eO(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 s1(e,t){let r=await c("xcrun",eO(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:iU});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 s2(e){return e.toLowerCase().replace(/[._-]/g,"")}let s3=eb(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),s4=eb(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function s8(e,t,r){return t||s6(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function s6(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function s5(e){return"ios"===e.platform&&"simulator"===e.kind}async function s9(e,t){s5(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function s7(e){let t=s6(e.flags)||!e.session?await e.resolveTargetDeviceFn(e.flags??{}):await le(e.session.device,e.resolveTargetDeviceFn);return!1!==e.ensureReady&&await e.ensureReadyFn(t),t}async function le(e,t){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let r={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await t(r)}catch(e){if(!(e instanceof w)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await t({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function lt(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 lr=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function la(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function li(e){let t=e?.trim();return t&&t.length>0?t:void 0}function ln(e,t){if(void 0!==e){if("string"!=typeof e)throw new w("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return li(e)}}function lo(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 ls(e){if("ios"===e||"android"===e)return e}function ll(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=>!lr.includes(e));if(i)throw new w("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${lr.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:ln(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 lo(e)}}(t.metroPort),bundleUrl:ln(t.bundleUrl,"bundleUrl"),launchUrl:ln(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:ls(i.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let i=r?.platform,n=ls(i);if(a.platform&&r&&!n)throw new w("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new w("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&la(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 ld(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i,clearRuntimeHints:n}=e;!t||!i?.appBundleId||!sS(r)||sS(a)||await n({device:i.device,appId:i.appBundleId})}async function lu(e){var t,r;let{req:a,sessionName:i,sessionStore:n,clearRuntimeHints:o=sD}=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){sS(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=ls(a.flags?.platform??d?.platform??l?.device.platform);if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first."}};if(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:li(t?.metroHost),metroPort:lo(t?.metroPort),bundleUrl:li(t?.bundleUrl),launchUrl:li(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===la(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 lc(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return rk(t)?"macos"===e.platform?void 0:"device"===e.kind?rL(r,t):void 0:await lp(e,t)}async function lp(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:nV}));return await r(e,t)}catch{return}}async function lf(e,t){if(!("android"!==e.platform||!t||rk(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:ab})),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function lm(e,t,r,a){return await lc(e,t,r)??await a(e,t)??("android"===e.platform&&t&&rk(t)?r:void 0)}let lh="open-command-roundtrip",lw="Not implemented for this platform in this release.";async function lg(e){let{device:t,closeTarget:r,stopIosRunner:a,dispatch:i,outFlag:n,context:o,settleSimulator:s}=e;"android"!==t.platform&&await a(t.id),await i(t,"close",[r],n,o),await s(t,s3)}async function lI(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||rk(u)||await a(r,"open",[d],i.flags?.out,{...oC(n,i.flags,o,s)})}async function lA(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 lg({device:l,closeTarget:e,stopIosRunner:c,dispatch:d,outFlag:i.flags?.out,context:{...oC(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,{...oC(s,i.flags,h)}),await lI({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:lh,appTarget:f,appBundleId:h}:void 0;await p(l,s4);let b=function(e){let{existingSession:t,sessionName:r,device:a,appBundleId:i,openTarget:n,saveScript:o}=e;return t?{...t,device:a,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===la(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let S=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&&la(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 o.recordAction(b,{command:"open",positionals:m,flags:i.flags??{},runtime:void 0!==i.runtime?w:void 0,result:S}),o.set(n,b),{ok:!0,data:S}}async function lv(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n,ensureReady:o,resolveDevice:s,applyRuntimeHints:l=s_,clearRuntimeHints:d=sD,stopIosRunner:u=tp,settleSimulator:c=s9,resolveAndroidPackageForOpen:p=lf}=e,f=t.flags?.relaunch===!0;if(i.has(r)){let e=i.get(r),m=t.positionals?.[0],h=m??(f?e?.appName:void 0);if(!e||!h)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&&rk(h))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};if(f&&"android"===e.device.platform&&"binary"===r4(h))return{ok:!1,error:{code:"INVALID_ARGS",message:r8(h)}};let w=await le(e.device,s);await o(w);let g=await lm(w,h,e.appBundleId,p),I=ll({req:t,sessionStore:i,sessionName:r,device:w});if(!I.ok)return I.response;let{runtime:A,previousRuntime:v,replacedStoredRuntime:y}=I.data;await ld({replacedStoredRuntime:y,previousRuntime:v,runtime:A,session:e,clearRuntimeHints:d});let b=m?t.positionals??[]:[h];return await lA({req:t,sessionName:r,sessionStore:i,logPath:a,device:w,dispatch:n,applyRuntimeHints:l,stopIosRunner:u,settleSimulator:c,openTarget:h,openPositionals:b,appBundleId:g,runtime:A,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&&rk(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"===r4(m))return{ok:!1,error:{code:"INVALID_ARGS",message:r8(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 lm(h,m,void 0,p),I=ll({req:t,sessionStore:i,sessionName:r,device:h});if(!I.ok)return I.response;let{runtime:A}=I.data;return await lA({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 ly(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 lb(e){let{device:t,shutdownRequested:r,shutdownSimulator:a,shutdownAndroidEmulator:i}=e;if(r&&(s5(t)||"android"===t.platform&&"emulator"===t.kind))try{return s5(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 lS(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n,stopIosRunner:o=tp,clearRuntimeHints:s=sD,settleSimulator:l=s9,shutdownSimulator:d=i1,shutdownAndroidEmulator:u=ly,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,{...oC(a,t.flags,p.appBundleId,p.trace?.outPath)}),await l(p.device,s3)),"ios"===p.device.platform&&await o(p.device.id),sS(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 sz(r).catch(()=>{}),i.delete(r);let f=await lb({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 lN={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve().then(()=>({reinstallIosApp:nW}));return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve().then(()=>({reinstallAndroidApp:az}));return await a(e,t,r)}},l_={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve().then(()=>({installIosApp:nH})),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:aW})),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function lD(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=s8(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?t1(f,t.meta?.tenantId):tP.expandHome(p);if(!R.existsSync(a))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${a}`}};let u=await s7({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!1});if(!oM(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&&t2(f)}}let lE=["platform","target","device","udid","serial","verbose","out"];async function lk(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??B;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=q(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await lL(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 lL(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{},o=e??{};for(let e of lE)void 0===n[e]&&void 0!==o[e]&&(n[e]=o[e]);return n}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}let lO='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',lx='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").',lM=["platform","target","device","udid","serial","verbose","out"],lC=["path","start","stop","doctor","mark","clear"],lR=`logs requires ${lC.slice(0,-1).join(", ")}, or ${lC.at(-1)}`,lP=["dump","log"],lT=`network requires ${lP.join(" or ")}`,l$=["summary","headers","body","all"],lF=`network include mode must be one of: ${l$.join(", ")}`,lU=async({avdName:e,serial:t,headless:r})=>{let{ensureAndroidEmulatorBooted:a}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:rQ}));return await a({avdName:e,serial:t,headless:r})};async function lV(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=s8(l,p,f);if(m)return m;let h=await s7({session:p,flags:f,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!oM(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,{...oC(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??{}}}function lG(e){return e.appLog?e.appLog.backend:"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"}async function lB(e){let{req:t,sessionName:r,sessionStore:a,ensureReady:i,resolveDevice:n}=e,o=a.get(r),s=t.flags??{},l=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=s8("appstate",o,s);if(d)return d;let u=(o?.device.platform==="ios"||o?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!s6(e))return!0;let r=e?.platform;return!(r&&!eX(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(s,o);if("ios"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lO}};if("macos"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lx}};if(u&&o){let e=o.appName??o.appBundleId;if(!o.appName&&!o.appBundleId){let e="macos"===o.device.platform?"macOS":"iOS";return{ok:!1,error:{code:"COMMAND_FAILED",message:`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`}}}return{ok:!0,data:{platform:o.device.platform,appName:e??"unknown",appBundleId:o.appBundleId,source:"session",..."ios"===o.device.platform?{device_udid:o.device.id,ios_simulator_device_set:o.device.simulatorSetPath??null}:{}}}}let c=await s7({session:o,flags:s,ensureReadyFn:i,resolveTargetDeviceFn:n,ensureReady:!0});if("ios"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lO}};if("macos"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lx}};let{getAndroidAppState:p}=await Promise.resolve().then(()=>({getAndroidAppState:ak})),f=await p(c);return{ok:!0,data:{platform:"android",package:f.package,activity:f.activity}}}async function lj(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=s8("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 s7({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!oM("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,{...oC(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 lq(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,dispatch:o,ensureReady:s,resolveTargetDevice:l,installOps:d=l_,reinstallOps:u=lN,stopIosRunner:c,appLogOps:p={start:tJ,stop:tK},ensureAndroidEmulatorBoot:m=lU,resolveAndroidPackageForOpen:h=lf,applyRuntimeHints:g=s_,clearRuntimeHints:I=sD,settleSimulator:A,shutdownSimulator:v,shutdownAndroidEmulator:b,listAndroidDevices:S,listAppleDevices:N,listAppleApps:_}=e,D=o??oL,E=s??oP,k=l??ok,L=c??tp,O=A??s9,x=t.command;if("session_list"===x)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,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("runtime"===x)return await lu({req:t,sessionName:r,sessionStore:i,clearRuntimeHints:I});if("ensure-simulator"===x)try{let e=t.flags??{},r=e.device,a=e.runtime,i=eE(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 sY({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:o,boot:n,ensureReady:E});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"===x)try{let e=[],r=eL(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,i=eZ({simulatorSetPath:eE(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let t=S??(await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:rQ,ensureAndroidEmulatorHeadlessBooted:r0,listAndroidDevices:rH,parseAndroidAvdList:rz,parseAndroidEmulatorAvdNameOutput:rP,parseAndroidFeatureListForTv:rG,parseAndroidTargetFromCharacteristics:rV,resolveAndroidAvdName:rJ,resolveAndroidEmulatorAvdName:rU,waitForAndroidBoot:r1}))).listAndroidDevices;e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let t=N??(await Promise.resolve().then(()=>({findBootableIosSimulator:o_,isAppleProductType:oA,isAppleTvProductType:ov,isSupportedAppleDevicectlDevice:oN,listAppleDevices:oD,listIosDevices:oD,resolveAppleTargetFromDevicectlDevice:oS}))).listAppleDevices;e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let t=S??(await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:rQ,ensureAndroidEmulatorHeadlessBooted:r0,listAndroidDevices:rH,parseAndroidAvdList:rz,parseAndroidEmulatorAvdNameOutput:rP,parseAndroidFeatureListForTv:rG,parseAndroidTargetFromCharacteristics:rV,resolveAndroidAvdName:rJ,resolveAndroidEmulatorAvdName:rU,waitForAndroidBoot:r1}))).listAndroidDevices;try{e.push(...await t({serialAllowlist:r}))}catch{}}let t=N??(await Promise.resolve().then(()=>({findBootableIosSimulator:o_,isAppleProductType:oA,isAppleTvProductType:ov,isSupportedAppleDevicectlDevice:oN,listAppleDevices:oD,listIosDevices:oD,resolveAppleTargetFromDevicectlDevice:oS}))).listAppleDevices;try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=f(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===x){let e=i.get(r),a=t.flags??{},n=s8(x,e,a);if(n)return n;let o=await s7({session:e,flags:a,ensureReadyFn:E,resolveTargetDeviceFn:k,ensureReady:!0});if(!oM("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(eK(o.platform)){let e=_??(await Promise.resolve().then(()=>({closeIosApp:nj,ensureBootedSimulator:i0,installIosApp:nH,installIosInstallablePath:nz,listIosApps:nY,listSimulatorApps:nQ,openIosApp:nG,openIosDevice:nB,parseIosDeviceAppsPayload:iz,pushIosNotification:nX,readIosClipboardText:nJ,reinstallIosApp:nW,resolveIosApp:nV,screenshotIos:n_,setIosSetting:nZ,uninstallIosApp:nq,writeIosClipboardText:nK}))).listIosApps;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:aS}));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"===x){let e,a=i.get(r),n=t.flags??{},o=s8(x,a,n);if(o)return o;let s="android"===(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=lt({flags:n,sessionDevice:a?.device}),u=s&&!!d,c=!1;try{e=await s7({session:a,flags:n,ensureReadyFn:E,resolveTargetDeviceFn:k,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=lt({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(e)}else("android"!==e.platform||!0!==e.booted)&&await E(e);return oM("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"===x)return await lB({req:t,sessionName:r,sessionStore:i,ensureReady:E,resolveDevice:k});if("clipboard"===x)return await lj({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:k,dispatch:D});if("keyboard"===x)return await lV({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:k,dispatch:D,command:"keyboard",positionals:t.positionals??[]});if("perf"===x){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===lh&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:lh,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(n.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:lh,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:lh},{session:n.name,platform:n.device.platform,device:n.device.name,deviceId:n.device.id,metrics:{startup:a,fps:{available:!1,reason:lw},memory:{available:!1,reason:lw},cpu:{available:!1,reason:lw}},sampling:{startup:{method:lh,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"}}})}:{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}}}if("install"===x||"reinstall"===x)return await lD({req:t,command:x,sessionName:r,sessionStore:i,ensureReady:E,resolveDevice:k,deployOps:"install"===x?d:u});if("install_source"===x)return await sX({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===x)return await sZ({req:t});if("push"===x){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=oo(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tP.expandHome(e,t)})).kind?e.path:e.text;return await lV({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:k,dispatch:D,command:"push",positionals:[n,s],recordPositionals:[n,o]})}if("trigger-app-event"===x)return await lV({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:k,dispatch:D,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await lm(e.device,r,e.appBundleId,h)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}});if("open"===x)return await lv({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:D,ensureReady:E,resolveDevice:k,applyRuntimeHints:g,clearRuntimeHints:I,stopIosRunner:L,settleSimulator:O,resolveAndroidPackageForOpen:h});if("replay"===x){let e=t.positionals?.[0];if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};try{let o=tP.expandHome(e,t.meta?.cwd),s=R.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){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=tM(r);return{positionals:i.positionals,flags:a,runtime:(t=i.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?i.flags:void 0}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n.runtime=e.runtime,n}if("runtime"===a){let e=tM(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tD(a)){let e=tx(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 sB(r)&&sB(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=tx(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:lW(t.flags,s.flags),runtime:s.runtime,meta:t.meta});if(l.ok)continue;if(!u)return lH(l,s,e,o);let p=await lz({action:s,sessionName:r,logPath:a,sessionStore:i,dispatch:D});if(!p)return lH(l,s,e,o);if(d[e]=p,!(l=await n({token:t.token,session:r,command:p.command,positionals:p.positionals??[],flags:lW(t.flags,p.flags),runtime:p.runtime,meta:t.meta})).ok)return lH(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",tE(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tR(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tk(r));return tO(t,e.flags),t.join(" ")}for(let r of e.positionals??[])t.push(tE(r));return tL(t,e),t.join(" ")}(e));let i=`${a.join("\n")}
36
- `,n=`${e}.tmp-${process.pid}-${Date.now()}`;R.writeFileSync(n,i),R.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"===x){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!oM("logs",e.device))return{ok:!1,error:y(new w("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let a=(t.positionals?.[0]??"path").toLowerCase(),n=!!t.flags?.restart;if(!lC.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:lR}};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(!R.existsSync(e))return{exists:!1,sizeBytes:0};let t=R.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t),n=lG(e);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 tX(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 tz(n),e=`[agent-device][mark][${new Date().toISOString()}] ${a.trim()||"marker"}
37
- `,R.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&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let t=i.resolveAppLogPath(r);if(n){e.appLog&&await p.stop(e.appLog);let a=tZ(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:tZ(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"}};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"===x){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!oM("network",e.device))return{ok:!1,error:y(new w("UNSUPPORTED_OPERATION","network is not supported on this device"))};let a=(t.positionals?.[0]??"dump").toLowerCase();if(!lP.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:lT}};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(!l$.includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:lF}};let l=function(e,t){let r=sh(t?.maxEntries,25,1,200),a=t?.include??"summary",i=sh(t?.maxPayloadChars,2048,64,16384),n=sh(t?.maxScanLines,4e3,100,2e4);if(!R.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}};let o=R.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=sc(i,["method","httpMethod"]),o=sc(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=sl.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(n??d?.[1]??l?.[1])?.toUpperCase(),c=sd.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of su){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:sm(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 sf(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,i);t&&(f.headers=sm(t,a))}if("body"===r||"all"===r){let t=sp(e,i,["requestBody","body","payload","request"]),r=sp(e,i,["responseBody","response"]);t&&(f.requestBody=sm(t,a)),r&&(f.responseBody=sm(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=lG(e),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"===x?await lk(t,r,n):"close"===x?await lS({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:D,stopIosRunner:L,clearRuntimeHints:I,settleSimulator:O,shutdownSimulator:v??i1,shutdownAndroidEmulator:b,appLogOps:{stop:p.stop}}):null}function lH(e,t,r,a){if(e.ok)return e;let i=r+1,n=function(e){let t;return t=(e.positionals??[]).map(e=>tE(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 lW(e,t){let r={...t??{}},a=e??{};for(let e of lM)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}async function lz(e){let{action:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n}=e;if(!(tD(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let o=i.get(r);if(!o)return null;let s=tD(t.command)||"fill"===t.command,l=tD(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await lJ(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),tD(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}=o2(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=sG(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 tb(t).filter(e=>e.trim().length>0)}(t)){let r=o0(e);if(!r)continue;let a=st(d.nodes,r,{platform:o.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!a)continue;let i=sn(a.node,o.device.platform,{action:tD(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tD(t.command))return{...t,positionals:[i]};if("fill"===t.command){let e=ty(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}=o2(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}=sG(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=o0(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(oz(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=oK(e).trim();return!!/^\d+$/.test(t)&&(0===n.size||n.has(oz(e.type??"")))});if(0===s.length||1!==tb(s.map(e=>oK(e).trim())).length)return null;let l=s[0];if(!l)return null;let d=sn(l,r.device.platform,{action:"get"});return 0===d.length?null:{...e,positionals:["text",d.join(" || ")]}}(t,d,o);return u||null}async function lJ(e,t,r,a,i,n){let o=await i(e.device,"snapshot",[],t.flags?.out,{...oC(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[],l={nodes:oU(t.flags?.snapshotRaw?s:oW(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend};return e.snapshot=l,n.set(e.name,e),l}function lK(e,t){let r=j(e.type??"Element"),a=W(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 lX(e,t){return t.flatten?e.map(e=>({text:J(e,0,!1),comparable:lK(e,0)})):G(e).map(e=>({text:e.text,comparable:lK(e.node,e.depth)}))}function lZ(e,t){return e.get(t)??0}async function lY(e){let{dispatchSnapshotCommand:t,device:r,session:a,req:i,logPath:n,snapshotScope:o}=e;return{snapshot:lQ(await t(r,"snapshot",[],i.flags?.out,{...oC(n,{...i.flags,snapshotScope:o},a?.appBundleId,a?.trace?.outPath)}),i.flags?.snapshotRaw)}}function lQ(e,t){let r=e?.nodes??[];return{nodes:oU(t?r:oW(r)),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend}}function l0(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=oV(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=oG(t.snapshot.nodes,r),i=a?oq(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 l1(e,t,r){let a=e.get(t),i=a?.device??await ok(r??{});return a||await oP(i),{session:a,device:i}}async function l2(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await tp(t.id)}}function l3(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function l4(e){let{session:t,sessionName:r,device:a,snapshot:i,appBundleId:n}=e;return t?{...t,snapshot:i}:{name:r,device:a,createdAt:Date.now(),appBundleId:n,snapshot:i,actions:[]}}function l8(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function l6(e){let{parsed:t,req:r,sessionName:a,logPath:i,sessionStore:n,session:o,device:s}=e,l=e.dispatchSnapshotCommand??oL,d=e.runnerCommand??tA;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),l3(n,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!oM("wait",s))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}};if("selector"===t.kind)return await l5({dispatchSnapshotCommand:l,device:s,logPath:i,parsed:t,req:r,session:o,sessionName:a,sessionStore:n});let u=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}}};let r=oV(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=oG(t.snapshot.nodes,r),i=a?oq(a,t.snapshot.nodes):void 0;return i?{ok:!0,text:i,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return u.ok?await l9({device:s,logPath:i,req:r,runnerCommand:d,session:o,sessionStore:n,text:u.text,timeoutMs:u.timeoutMs}):u.response}async function l5(e){let{dispatchSnapshotCommand:t,device:r,logPath:a,parsed:i,req:n,session:o,sessionName:s,sessionStore:l}=e,d=i.timeoutMs??1e4,u=Date.now();for(;Date.now()-u<d;){let e=lQ(await t(r,"snapshot",[],n.flags?.out,{...oC(a,{...n.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},o?.appBundleId,o?.trace?.outPath)}),n.flags?.snapshotRaw),d=e.nodes;o&&(o.snapshot=e,l.set(s,o));let c=sr(d,i.selector,{platform:r.platform});if(c)return l3(l,o,n,{selector:c.selector.raw,waitedMs:Date.now()-u}),{ok:!0,data:{selector:c.selector.raw,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${i.selectorExpression}`}}}async function l9(e){let{device:t,logPath:r,req:a,runnerCommand:i,session:n,sessionStore:o,text:s,timeoutMs:l}=e,d=l??1e4,u=Date.now();for(;Date.now()-u<d;){if(eK(t.platform)){let e=await i(t,{command:"findText",text:s,appBundleId:n?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return l3(o,n,a,{text:s,waitedMs:Date.now()-u}),{ok:!0,data:{text:s,waitedMs:Date.now()-u}}}else if("android"===t.platform&&oj(oU((await a0(t,{scope:s})).nodes??[]),s))return l3(o,n,a,{text:s,waitedMs:Date.now()-u}),{ok:!0,data:{text:s,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${s}`}}}async function l7(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n}=e,o=e.runnerCommand??tA,s=(t.positionals?.[0]??"get").toLowerCase();if(!oM("alert",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is only supported on iOS simulators"}};if("wait"===s){let e=l8(t.positionals?.[1])??1e4,s=Date.now();for(;Date.now()-s<e;){try{let e=await o(n,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return l3(a,i,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let l="accept"===s||"dismiss"===s?s:"get",d={verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await o(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return l3(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let u=await o(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return l3(a,i,t,u),{ok:!0,data:u}}async function de(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!oM("settings",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};let u=i?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],p=await oL(n,"settings",c,t.flags?.out,{...oC(r,t.flags,u,i?.trace?.outPath)});return l3(a,i,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}async function dt(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=e.dispatchSnapshotCommand??oL,o=e.runnerCommand??tA,s=e.sessionlessRunnerCleanup??l2,l=t.command;if("snapshot"===l){let{session:e,device:o}=await l1(i,r,t.flags);if(!oM("snapshot",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let l=l0(t.flags?.snapshotScope,e);return l.ok?await s(e,o,async()=>{let s=await lY({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:a,snapshotScope:l.scope}),d=l4({session:e,sessionName:r,device:o,snapshot:s.snapshot,appBundleId:e?.appBundleId});return l3(i,d,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),i.set(r,d),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,appName:d.appBundleId?d.appName??d.appBundleId:void 0,appBundleId:d.appBundleId}}}):l.response}if("diff"===l){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 l1(i,r,t.flags);if(!oM("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let l=l0(t.flags?.snapshotScope,e);if(!l.ok)return l.response;let d=t.flags?.snapshotInteractiveOnly===!0;return await s(e,o,async()=>{let s=(await lY({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:a,snapshotScope:l.scope})).snapshot;if(!e?.snapshot){let a=function(e,t={}){return lX(e,t).length}(s.nodes,{flatten:d}),n=l4({session:e,sessionName:r,device:o,snapshot:s,appBundleId:e?.appBundleId});return l3(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 u=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&&lZ(n,i-1)<lZ(n,i+1)?lZ(n,i+1):lZ(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&&lZ(i,l-1)<lZ(i,l+1)?l+1:l-1,u=lZ(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[]}(lX(e,r),lX(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,s.nodes,{flatten:d}),c={...e,snapshot:s};return l3(i,c,t,{mode:"snapshot",baselineInitialized:!1,summary:u.summary}),i.set(r,c),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:u.summary,lines:u.lines}}})}if("wait"===l){let{session:e,device:l}=await l1(i,r,t.flags),d=function(e){if(0===e.length)return null;let t=l8(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=l8(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=l8(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=l8(e[e.length-1]),a=o1(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=o0(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}};let u=()=>l6({parsed:d,req:t,sessionName:r,logPath:a,sessionStore:i,session:e,device:l,dispatchSnapshotCommand:n,runnerCommand:o});return"sleep"===d.kind?await u():await s(e,l,u)}if("alert"===l){let{session:e,device:n}=await l1(i,r,t.flags);return await s(e,n,async()=>await l7({req:t,logPath:a,sessionStore:i,session:e,device:n,runnerCommand:o}))}if("settings"===l){let e,n,o,l=(e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&n&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:n,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:H}}});if(!l.ok)return l.response;let{session:d,device:u}=await l1(i,r,t.flags);return await s(d,u,async()=>await de({req:t,logPath:a,sessionStore:i,session:d,device:u,parsed:l.parsed}))}return null}function dr(e,t,r,a={}){let i=di(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 da(e.label,r);case"value":return da(e.value,r);case"id":return da(e.identifier,r);default:return Math.max(da(e.label,r),da(e.value,r),da(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 da(e,t){let r=di(e??"");return r?r===t?2:+!!r.includes(t):0}function di(e){return e.trim().toLowerCase().replace(/\s+/g," ")}async function dn(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=e.dispatch??oL,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:l8(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 ok(t.flags??{});m||await oP(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,{...oC(a,{...t.flags,snapshotScope:I,snapshotInteractiveOnly:A,snapshotCompact:A},g,m?.trace?.outPath)}),s=n?.nodes??[],l=oU(t.flags?.snapshotRaw?s:oW(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(dr(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:S}=await b(),N=dr(S,d,u,{requireRect:A});if(A&&N.matches.length>1){let e=N.matches.slice(0,8).map(e=>{let t=oK(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`});return{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${N.matches.length} elements for ${d} "${u}". Use a more specific locator or selector.`,details:{locator:d,query:u,matches:N.matches.length,candidates:e}}}}let _=N.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,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}(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=oK(_);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:_}}}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:_}};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?oB(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=_.rect?oB(_.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,{...oC(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=_.rect?oB(_.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,{...oC(a,t.flags,m?.appBundleId,m?.trace?.outPath)});let r=await o(h,"type",[p],t.flags?.out,{...oC(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 ds(e){return e instanceof Error?e.message:String(e)}function dl(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function dd(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function du(e){let{deps:t,device:r,sessionStore:a,session:i,req:n,logPath:o,fps:s,appBundleId:l,runnerOutPath:d}=e,u=dd(n,o,i),c=async()=>{await t.runIosRunnerCommand(r,{command:"recordStart",outPath:d,fps:s,appBundleId:l},u)};try{await c()}catch(e){if(!ds(e).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${ds(e)}`}};{var p,f;L({level:"warn",phase:"record_start_runner_desynced",data:{platform:r.platform,kind:r.kind,deviceId:r.id,session:i.name,error:ds(e)}});let n=(p=r.id,f=i.name,a.toArray().find(e=>e.name!==f&&e.device.id===p&&(e.recording?.platform==="ios-device-runner"||e.recording?.platform==="macos-runner")));if(n)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${n.name}'`}};try{await t.runIosRunnerCommand(r,{command:"recordStop",appBundleId:l},u)}catch{}try{await c()}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${ds(e)}`}}}}}return{recording:e.recording}}async function dc(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,o=e.deps??{runCmd:c,runCmdBackground:d,runIosRunnerCommand:tA},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 l=a.get(r),d=l?.device??await ok(t.flags??{});l||await oP(d);let u=l??{name:r,device:d,createdAt:Date.now(),actions:[]};if("start"===e){if(u.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 l=t.positionals?.[1]??`./recording-${Date.now()}.mp4`;if(!oM("record",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let c="ios"===d.platform&&"device"===d.kind||"macos"===d.platform?dl(u):void 0;if(!c&&("ios"===d.platform&&"device"===d.kind||"macos"===d.platform))return{ok:!1,error:{code:"INVALID_ARGS",message:"macos"===d.platform?"record on macOS requires an active app session; run open <app> first":"record on physical iOS devices requires an active app session; run open <app> first"}};let p=tP.expandHome(l,t.meta?.cwd),f=t.meta?.clientArtifactPaths?.outPath;if(R.mkdirSync(i.dirname(p),{recursive:!0}),"ios"===d.platform&&"device"===d.kind){let r=`agent-device-recording-${Date.now()}.mp4`,i=`tmp/${r}`,s=await du({deps:o,device:d,sessionStore:a,session:u,req:t,logPath:n,fps:e,appBundleId:c,runnerOutPath:r,recording:{platform:"ios-device-runner",outPath:p,clientOutPath:f,remotePath:i}});if("ok"in s)return s;u.recording=s.recording}else if("macos"===d.platform){let r=await du({deps:o,device:d,sessionStore:a,session:u,req:t,logPath:n,fps:e,appBundleId:c,runnerOutPath:p,recording:{platform:"macos-runner",outPath:p,clientOutPath:f}});if("ok"in r)return r;u.recording=r.recording}else if("ios"===d.platform){let{child:e,wait:t}=o.runCmdBackground("xcrun",ex(d,["io",d.id,"recordVideo",p]),{allowFailure:!0});u.recording={platform:"ios",outPath:p,clientOutPath:f,child:e,wait:t}}else{let e=`/sdcard/agent-device-recording-${Date.now()}.mp4`,{child:t,wait:r}=o.runCmdBackground("adb",["-s",d.id,"shell","screenrecord",e],{allowFailure:!0});u.recording={platform:"android",outPath:p,clientOutPath:f,remotePath:e,child:t,wait:r}}return a.set(r,u),a.recordAction(u,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start"}}),{ok:!0,data:{recording:"started",outPath:f??l}}}if(!u.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let c=u.recording;if("ios-device-runner"===c.platform||"macos-runner"===c.platform){let e=dl(u);try{await o.runIosRunnerCommand(d,{command:"recordStop",appBundleId:e},dd(t,n,u))}catch(e){L({level:"warn",phase:"record_stop_runner_failed",data:{platform:d.platform,kind:d.kind,deviceId:d.id,session:u.name,error:ds(e)}})}if(u.recording=void 0,"ios-device-runner"===c.platform){let e={stdout:"",stderr:"",exitCode:1};for(let t of e5)if(0===(e=await o.runCmd("xcrun",["devicectl","device","copy","from","--device",d.id,"--source",c.remotePath,"--destination",c.outPath,"--domain-type","appDataContainer","--domain-identifier",t],{allowFailure:!0})).exitCode)break;if(0!==e.exitCode){let t=e.stderr.trim()||e.stdout.trim()||`devicectl exited with code ${e.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${t}`}}}}}else if("child"in c){c.child.kill("SIGINT");try{await c.wait}catch{}if("android"===c.platform&&c.remotePath)try{await o.runCmd("adb",["-s",d.id,"pull",c.remotePath,c.outPath],{allowFailure:!0}),await o.runCmd("adb",["-s",d.id,"shell","rm","-f",c.remotePath],{allowFailure:!0})}catch{}u.recording=void 0}a.recordAction(u,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:c.outPath}});let p=[{field:"outPath",path:c.outPath,localPath:c.clientOutPath,fileName:i.basename(c.clientOutPath??c.outPath)}];return{ok:!0,data:{recording:"stopped",outPath:c.outPath,artifacts:p}}}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=tP.expandHome(e);return R.mkdirSync(i.dirname(r),{recursive:!0}),R.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=tP.expandHome(t.positionals[1]);R.mkdirSync(i.dirname(e),{recursive:!0}),R.existsSync(o)?R.renameSync(o,e):R.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}let dp=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function df(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of dp)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 dm(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=oV(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=oG(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=oj(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 dh(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=oB(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}async function dw(e,t,r,a,i,n=oL){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:oU(t?.snapshotRaw?s:oW(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend},r.set(e.name,e),e.snapshot}async function dg(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u,dispatch:c}=e,p=oQ(r),f=await dw(a,i,n,o,{interactiveOnly:s},c),m=await E("selector_resolve",()=>st(f.nodes,p,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return m&&(!l||m.node.rect)?{ok:!0,chain:p,snapshot:f,resolved:m}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:sa(p,m?.diagnostics??[],{unique:d})}}}}async function dI(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o=a.get(r);if(o&&!oM("fill",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let e=df("fill",t.flags);if(e)return e;let r=t.positionals.length>=3?t.positionals[1]:"",s=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let l=dm({session:o,refInput:t.positionals[0],fallbackLabel:r,requireRect:!0,invalidRefMessage:"fill requires a ref like @e2",notFoundMessage:`Ref ${t.positionals[0]} not found or has no bounds`});if(!l.ok)return l.response;let{ref:d,node:u,snapshotNodes:c}=l.target;if(!u.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${t.positionals[0]} not found or has no bounds`}};let p=u.type??"",f=p&&!oJ(p,o.device.platform)?`fill target ${t.positionals[0]} resolved to "${p}", attempting fill anyway.`:void 0,m=oq(u,c),h=sn(u,o.device.platform,{action:"fill"}),{x:w,y:g}=oB(u.rect),I={...await n(o.device,"fill",[String(w),String(g),s],t.flags?.out,{...i(t.flags,o.appBundleId,o.trace?.outPath)})??{ref:d,x:w,y:g}};return f&&(I.warning=f),a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{...I,refLabel:m,selectorChain:h}}),{ok:!0,data:I}}if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let s=o1(t.positionals??[],{preferTrailingValue:!0});if(!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}};if(0===s.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let l=s.rest.join(" ").trim();if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let d=await dg({command:t.command,selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!0,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0,dispatch:n});if(!d.ok)return d.response;let{resolved:u,snapshot:c}=d,p=u.node;if(!p.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${u.selector.raw} resolved to invalid bounds`}};let f=p.type??"",m=f&&!oJ(f,o.device.platform)?`fill target ${u.selector.raw} resolved to "${f}", attempting fill anyway.`:void 0,{x:h,y:w}=oB(p.rect),g=await n(o.device,"fill",[String(h),String(w),l],t.flags?.out,{...i(t.flags,o.appBundleId,o.trace?.outPath)}),I=sn(p,o.device.platform,{action:"fill"}),A={...g??{x:h,y:w,text:l},selector:u.selector.raw,selectorChain:I,refLabel:oq(p,c.nodes)};return m&&(A.warning=m),a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:A}),{ok:!0,data:A}}async function dA(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o=t.positionals?.[0];if("text"!==o&&"attrs"!==o)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(!oM("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 e=df("get",t.flags);if(e)return e;let r=dm({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(!r.ok)return r.response;let{ref:i,node:n}=r.target,d=sn(n,s.device.platform,{action:"get"});if("attrs"===o)return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:i,selectorChain:d}}),{ok:!0,data:{ref:i,node:n}};let u=oK(n);return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:i,text:u,refLabel:u||void 0,selectorChain:d}}),{ok:!0,data:{ref:i,text:u,node:n}}}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=await dg({command:t.command,selectorExpression:d,session:s,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===o,dispatch:n});if(!u.ok)return u.response;let{resolved:c}=u,p=c.node,f=sn(p,s.device.platform,{action:"get"});if("attrs"===o)return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:c.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:c.selector.raw,node:p}};let m=oK(p);return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:m,refLabel:m||void 0,selector:c.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:c.selector.raw,text:m,node:p}}}async function dv(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(o))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(!oM("is",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:l}=o2(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"===o&&!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==o&&l.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${o} does not accept trailing values`}};let u=oQ(l.selectorExpression);if("exists"===o){let e=sr((await dw(s,t.flags,a,i,{interactiveOnly:!1},n)).nodes,u,{platform:s.device.platform});return e?(a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:o,selector:e.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:o,pass:!0,selector:e.selector.raw,matches:e.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:sa(u,[],{unique:!1})}}}let c=await dg({command:"is",selectorExpression:l.selectorExpression,session:s,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1,dispatch:n});if(!c.ok)return c.response;let{resolved:p}=c,f=function(e){let{predicate:t,node:r,expectedText:a,platform:i}=e,n=oK(r),o=!1;switch(t){case"visible":o=o5(r);break;case"hidden":o=!o5(r);break;case"editable":o=o9(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:o5(r),editable:o9(r,i),selected:!0===r.selected})}`;return{pass:o,actualText:n,details:s}}({predicate:o,node:p.node,expectedText:d,platform:s.device.platform});return f.pass?(a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:o,selector:p.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,text:"text"===o?f.actualText:void 0}}),{ok:!0,data:{predicate:o,pass:!0,selector:p.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${o} failed for selector ${p.selector.raw}: ${f.details}`}}}async function dy(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o="click"===t.command?"click":"press",s=a.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!oM("press",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let l=n7(t.flags),d="primary"===l?{}:{button:l};if("primary"!==l){let e=oe({commandLabel:o,platform:s.device.platform,button:l,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(e)return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}let u=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(u){let e=await n(s.device,"press",[String(u.x),String(u.y)],t.flags?.out,{...i(t.flags,s.appBundleId,s.trace?.outPath)});return a.recordAction(s,{command:t.command,positionals:t.positionals??[String(u.x),String(u.y)],flags:t.flags??{},result:e??{x:u.x,y:u.y,...d}}),{ok:!0,data:e??{x:u.x,y:u.y,...d}}}let c=t.positionals?.[0]??"";if(c.startsWith("@")){let e=df("press",t.flags);if(e)return e;let r=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",l=dm({session:s,refInput:c,fallbackLabel:r,requireRect:!0,invalidRefMessage:`${o} requires a ref like @e2`,notFoundMessage:`Ref ${c} not found or has no bounds`});if(!l.ok)return l.response;let{ref:u}=l.target,p=l.target.node,f=l.target.snapshotNodes,m=dh(p.rect);if(!m){let e=await dw(s,t.flags,a,i,{interactiveOnly:!0},n),o=oG(e.nodes,u),l=r.length>0?oj(e.nodes,r):null,d=dh(l?.rect),c=dh(o?.rect)?o:d?l:o??l,h=dh(c?.rect);c&&h&&(p=c,f=e.nodes,m=h)}if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${c} not found or has invalid bounds`}};let h=oq(p,f),w=sn(p,s.device.platform,{action:"click"}),{x:g,y:I}=m,A=await n(s.device,"press",[String(g),String(I)],t.flags?.out,{...i(t.flags,s.appBundleId,s.trace?.outPath)});return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:u,x:g,y:I,refLabel:h,selectorChain:w,...d}}),{ok:!0,data:{...A??{},ref:u,x:g,y:I,...d}}}let p=(t.positionals??[]).join(" ").trim();if(!p)return{ok:!1,error:{code:"INVALID_ARGS",message:`${o} requires @ref, selector expression, or x y coordinates`}};let f=await dg({command:t.command,selectorExpression:p,session:s,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!0,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0,dispatch:n});if(!f.ok)return f.response;let{resolved:m,snapshot:h}=f,w=dh(m.node.rect);if(!w)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${m.selector.raw} resolved to invalid bounds`}};let{x:g,y:I}=w,A=await n(s.device,"press",[String(g),String(I)],t.flags?.out,{...i(t.flags,s.appBundleId,s.trace?.outPath)}),v=sn(m.node,s.device.platform,{action:"click"}),y=oq(m.node,h.nodes);return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{x:g,y:I,selector:m.selector.raw,selectorChain:v,refLabel:y,...d}}),{ok:!0,data:{...A??{},selector:m.selector.raw,x:g,y:I,...d}}}function db(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function dS(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 dN(e,t,r){return Math.min(r,Math.max(t,Math.round(e)))}async function d_(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!oM("scrollintoview",o.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=df("scrollintoview",t.flags);if(l)return l;let d=dm({session:o,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=oB(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=dS(i.map(e=>e.rect).filter(e=>db(e,r.x,r.y)));if(n)return n;let o=dS(i.map(e=>e.rect));if(o)return o;let s=dS(a.map(e=>e.rect).filter(e=>db(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:dN(Math.ceil((f-c)/I),1,50),direction:"down"}:{x:h,startY:g,endY:w,count:dN(Math.ceil((u-f)/I),1,50),direction:"up"}}(c.rect,f),h=oq(c,p),w=sn(c,o.device.platform,{action:"get"});if(!m)return a.recordAction(o,{command:t.command,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(o.device,"swipe",[String(m.x),String(m.startY),String(m.x),String(m.endY),"16"],t.flags?.out,{...i(t.flags,o.appBundleId,o.trace?.outPath),count:m.count,pauseMs:0,pattern:"one-way"});return a.recordAction(o,{command:t.command,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}}}async function dD(e){let t={...e,dispatch:e.dispatch??oL};switch(e.req.command){case"click":case"press":return await dy(t);case"fill":return await dI(t);case"get":return await dA(t);case"is":return await dv(t);case"scrollintoview":return await d_(t);default:return null}}function dE(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 dk(e){let{req:t,leaseRegistry:r}=e,a=dE(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 dL(e,t){if(!t)return[];let r=[],a=e.device,i=t.platform;if(i&&!eX(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=ek(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function dO(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 dx=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],dM=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),dC=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function dR(e,t,r,a){let i=_().requestId;return{...oC(e,t,r,a,i),requestId:i}}function dP(e){R.existsSync(e)&&R.unlinkSync(e)}function dT(e){if(!R.existsSync(e))return null;try{let t=JSON.parse(R.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function d$(e){let t=dT(e);if(!t||t.pid===process.pid)try{R.existsSync(e)&&R.unlinkSync(e)}catch{}}function dF(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:dU,infoPath:dV,lockPath:dG,logPath:dB,sessionsDir:dj}=U(process.env.AGENT_DEVICE_STATE_DIR),dq=F(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var dH=dj;if(R.existsSync(dH))for(let e of R.readdirSync(dH,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=i.join(dH,e.name,"app-log.pid");if(R.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}}(R.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{t$(t)}}let dW=new tP(dj),dz=new rI({maxActiveSimulatorLeases:dF(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:dF(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:dF(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:dF(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),dJ=N(),dK=u.randomBytes(24).toString("hex"),dX=M(process.pid)??void 0,dZ=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=R.statSync(e),r=k(),a=i.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),dY=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:n,trackDownloadableArtifact:s}=e,l=e.dispatchCommand??oL;async function d(e){let u=!!(e.meta?.debug||e.flags?.verbose);return await C({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:u,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:y(new w("UNAUTHORIZED","Invalid token"))};try{let r=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).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);L({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let u=r.command,c=dE(r);dC.has(u)||r.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}(r,a),f=a.get(p),m=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?dL(t,a):function(e,t){var r,a;let i=[];for(let n of(void 0!==e.platform&&t&&(r=e.platform,a=t,r&&a&&r!==a&&("apple"===r?!eK(a):"apple"!==a||!eK(r)))&&i.push({key:"platform",value:e.platform}),dx)){let t=e[n];"string"==typeof t&&t.trim().length>0&&i.push({key:n,value:t})}return i}(a,e.meta?.lockPlatform);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of dx)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(dO).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,f),h=e=>(function(e,t,r){let a=_();if(!t.ok){L({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=P({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 L({level:"info",phase:"request_success"}),P(),{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||dM.has(u)||function(e,t){let r=dL(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(dO).join(", ")}. Use a different --session name or close this session first.`)}}(f,m.flags);let g=await dk({req:m,leaseRegistry:n});if(g)return h(g);let I=await lq({req:m,sessionName:p,logPath:t,sessionStore:a,invoke:d});if(I)return h(I);let A=await dt({req:m,sessionName:p,logPath:t,sessionStore:a});if(A)return h(A);let v=await dc({req:m,sessionName:p,sessionStore:a,logPath:t});if(v)return h(v);let S=await dn({req:m,sessionName:p,logPath:t,sessionStore:a,invoke:d});if(S)return h(S);let N=await dD({req:m,sessionName:p,sessionStore:a,contextFromFlags:(e,r,a)=>dR(t,e,r,a)});if(N)return h(N);let D=a.get(p);if(!D)return h({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!oM(u,D.device))return h({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${u} is not supported on this device`}});let E=m.positionals??[],k=m.flags?.out,O="screenshot"===u&&E[0]?[tP.expandHome(E[0],m.meta?.cwd),...E.slice(1)]:E,x="screenshot"===u&&k?tP.expandHome(k,m.meta?.cwd):k,M="screenshot"===u?O:E,C="screenshot"===u&&x?{...m.flags??{},out:x}:m.flags??{},R=await l(D.device,u,O,x,{...dR(t,m.flags,D.appBundleId,D.trace?.outPath)});return a.recordAction(D,{command:u,positionals:M,flags:C,result:R??{}}),h({ok:!0,data:R??{}})}catch(r){L({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=_(),t=P({force:!0})??void 0;return{ok:!1,error:y(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return d}({logPath:dB,token:dK,sessionStore:dW,leaseRegistry:dz,trackDownloadableArtifact:function(e){let t=u.randomUUID(),r=setTimeout(()=>{tQ(t)},9e5);return r.unref(),tY.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){R.existsSync(e)||R.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),i=()=>{try{return R.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(i())return!0;let n=dT(t);if(n?.pid&&n.pid!==process.pid&&s(n.pid,n.processStartTime))return!1;try{R.unlinkSync(t)}catch{}return i()}(dU,dG,{pid:process.pid,version:dJ,startedAt:Date.now(),processStartTime:dX})){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"===dq||"dual"===dq){let t=$.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))eu(e);L({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await tf(),!(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=el(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),ed(o),ep(o))throw em();i=await dY(e)}catch(e){i={ok:!1,error:y(e)}}finally{r-=1,o&&(a.delete(o),ec(o))}e.destroyed||e.write(`${JSON.stringify(i)}
38
- `),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"===dq||"dual"===dq){let e=await rc({handleRequest:dY,token:dK});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:dK,version:dJ,codeSignature:dZ,processStartTime:dX},R.existsSync(dU)||R.mkdirSync(dU,{recursive:!0}),R.writeFileSync(dB,""),i=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",R.writeFileSync(dV,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:dU},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
26
+ ${i}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")||n.includes("timed out")&&n.includes("screenshot")}let nG={settings:"com.apple.Preferences"},nj=null;function nB(e,t,r){return f("xcrun",eC(e,t),r)}function nq(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function nH(e,t){if("macos"===e.platform)return await nu(t);let r=t.trim();if(r.includes("."))return r;let a=nG[r.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await n4(e):await iY(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new v("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new v("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function nW(e,t,r){if("macos"===e.platform)return void await nc(e,t,r);let a=r?.url?.trim();if(a){if(!rC(a))throw new v("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await i8(e),await i4(),await nB(e,["openurl",e.id,a]);return}let i=rP(r?.appBundleId??await nH(e,t),a);if(!i)throw new v("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oa(e,i,{payloadUrl:a});return}let i=t.trim();if(rC(i)){if("simulator"===e.kind){await i8(e),await i4(),await nB(e,["openurl",e.id,i]);return}let t=rP(r?.appBundleId,i);if(!t)throw new v("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oa(e,t,{payloadUrl:i});return}let n=r?.appBundleId??await nH(e,t);"simulator"===e.kind?await or(e,n):await oa(e,n)}async function nz(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await i6(e)&&(await i8(e),await i4())}async function nJ(e,t){if("macos"===e.platform)return void await np(e,t);let r=await nH(e,t);if("simulator"===e.kind){await i8(e);let t=eC(e,["terminate",e.id,r]),a=await f("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new v("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await iX(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function nK(e,t){let r=await nH(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],a=await f("xcrun",t,{allowFailure:!0,timeoutMs:iW});if(0!==a.exitCode){let i=String(a.stdout??""),n=String(a.stderr??"");if(!nq(`${i}
27
+ ${n}`.toLowerCase()))throw new v("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:e.id,hint:i0(i,n)??iQ})}return{bundleId:r}}await i8(e);let a=await nB(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==a.exitCode&&!nq(`${a.stdout}
28
+ ${a.stderr}`.toLowerCase()))throw new v("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:r}}async function nX(e,t,r){let a=await i7({kind:"path",path:t},r);try{return await nZ(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function nY(e,t,r){let{bundleId:a}=await nK(e,t);return await nX(e,r,{appIdentifierHint:t}),{bundleId:a}}async function nZ(e,t){"simulator"!==e.kind?await iX(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await i8(e),await nB(e,["install",e.id,t]))}async function nQ(e){if("macos"===e.platform)return await nf();i3(e,"clipboard"),await i8(e);let t=await nB(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new v("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 n0(e,t){if("macos"===e.platform)return void await nm(t);i3(e,"clipboard"),await i8(e);let r=await nB(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new v("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function n1(e,t,r){i3(e,"push"),await i8(e);let a=await x.mkdtemp(o.join(F.tmpdir(),"agent-device-ios-push-")),i=o.join(a,"payload.apns");try{await x.writeFile(i,`${JSON.stringify(r)}
29
+ `,"utf8"),await nB(e,["push",e.id,t,i])}finally{await x.rm(a,{recursive:!0,force:!0})}}async function n2(e,t,r,a,i){if("macos"===e.platform){if("appearance"!==t.toLowerCase())throw new v("INVALID_ARGS",`Unsupported macOS setting: ${t}. macOS currently supports only settings appearance <light|dark|toggle>.`);await nw(r);return}i3(e,"settings"),await i8(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=n8(r);await nB(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(n8(r)?await nB(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await nB(e,["status_bar",e.id,"clear"]));case"location":{let t=n8(r);if(!a)throw new v("INVALID_ARGS","location setting requires an active app in session");await nB(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=n6[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 v("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,n);await ot(e,a,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await n5(e,r);await nB(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new v("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=iD(r))?"revoke":o,n=function(e,t){let r=iE(e);if("photos"!==r&&t?.trim())throw new v("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 v("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new v("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 n9(e,t,n,a);return}default:throw new v("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function n3(e,t="all"){return"macos"===e.platform?await ng(t):"simulator"===e.kind?ni(await n4(e),t):await iY(e,t)}async function n4(e){let t=(await nB(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 n8(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 v("INVALID_ARGS",`Invalid setting state: ${e}`)}async function n5(e,t){let r=iM(t);if("toggle"!==r)return r;let a=await nB(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new v("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
30
+ ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new v("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let n6={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function n9(e,t,r,a){let i=await oe(e);if(!i.has(r))throw new v("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 nB(e,n);return}catch(t){if(!(o&&n7(t)))throw t;throw new v("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 nB(e,n);return}catch(e){if(!n7(e))throw e}try{await nB(e,["privacy",e.id,"reset","all",a])}catch(t){throw new v("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 n7(e){if(!(e instanceof v)||"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 oe(e){let r=ek(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(nj&&t===a)return nj;let i=await nB(e,["privacy","help"],{allowFailure:!0}),n=function(e){let t=new Set,r=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let i=/^([a-z-]+)\s+-\s+/.exec(e);i&&t.add(i[1])}return t}(`${i.stdout}
31
+ ${i.stderr}`);if(0===n.size)throw new v("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 nj=n,t=a,n}async function ot(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=eC(e,t),a=await f("xcrun",r,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:r,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let n=i.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(i.length>0&&i.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
32
+ ${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new v("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new v("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function or(e,t){await i8(e),await i4();let r=0,a=er.fromTimeoutMs(iH);try{await ea(async({deadline:r})=>{var a;if(r?.isExpired())throw new v("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:iH});let i=(a=["launch",e.id,t],eC(e,a)),n=await f("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new v("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=>!!i1(e)&&(r+=1)<3},{deadline:a})}catch(r){if(i1(r)){var i;let a=(i=await i2(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 oa(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await iX(a,{action:"launch iOS app",deviceId:e.id})}function oi(e){return e?.clickButton??"primary"}function on(e){return"primary"===e.button?null:"click"!==e.commandLabel?new v("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new v("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new v("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new v("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let oo=/^[A-Za-z0-9_.:-]{1,64}$/,os=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function ol(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new v("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function od(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await ou(t)}async function ou(e){await new Promise(t=>setTimeout(t,e))}function oc(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new v("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!T.statSync(n).isFile())throw new v("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof v)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new v("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new v("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 v("INVALID_ARGS",`${a} file not found: ${n}`)}async function op(e){let t=oc(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await of(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new v("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof v)throw t;throw new v("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function of(e){try{return await x.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new v("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new v("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new v("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new v("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let om=e_(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),oh=/^(iphone|ipad|ipod|appletv)/i,ow=/^appletv/i,og=["apple tv","appletv","tvos"];function ov(e){return(e??"").trim().toLowerCase()}function oA(e){return ov(e.hardwareProperties?.platform)}function oI(e){return e.includes("tvos")}function oy(e){return oI(ov(e))?"tv":"mobile"}function ob(e){let t=ov(e);return t.includes("ios")||t.includes("tvos")}function oS(e){let t=ov(e);return og.some(e=>t.includes(e))}function o_(e){return oh.test(e.trim())}function oN(e){return ow.test(e.trim())}function oD(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function oE(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}function oM(e){return oI(oA(e))||oN(oE(e))||oD(e).some(oS)?"tv":"mobile"}function ok(e){let t=oA(e);return!!(t.includes("ios")||t.includes("tvos")||o_(oE(e)))||oD(e).some(oS)}async function oL(e={}){let t,r,a=ek(e.simulatorSetPath),i=e.target;try{t=await f("xcrun",ex(["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(!ob(e))continue;let r=oy(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 oO(e={}){if("darwin"!==process.platform)throw new v("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await I("xcrun"))throw new v("TOOL_MISSING","xcrun not found in PATH");let t=[],r=ek(e.simulatorSetPath),a=await f("xcrun",ex(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(ob(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:oy(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new v("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(t.push({platform:"macos",id:"host-macos-local",name:F.hostname(),kind:"device",target:"desktop",booted:!0}),r)return t;let i=null;try{i=o.join(F.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",i],{allowFailure:!0,timeoutMs:om});if(0!==e.exitCode)return t;let r=await x.readFile(i,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(ok(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:oM(e),booted:!0})}}catch{}finally{i&&await x.rm(i,{force:!0}).catch(()=>{})}return t}async function ox(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 v)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!n&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!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 v("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function oC(e){let t=e.platform,r=eQ({simulatorSetPath:ek(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=eO(e.androidDeviceAllowlist);return await k("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 v("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await rL();let e=await rX({serialAllowlist:a});return await e0(e,i)}if(i.platform){let e=await oO({simulatorSetPath:r});return await ox(e,i,{simulatorSetPath:r},{resolveDevice:e0,findBootableSimulator:oL})}let n=[];try{n.push(...await rX({serialAllowlist:a}))}catch{}try{n.push(...await oO({simulatorSetPath:r}))}catch{}return await e0(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function oP(e,t,r,a,i){let n=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>aR(e,t,r?.activity),openDevice:()=>aU(e),close:t=>aV(e,t),tap:(t,r)=>ie(e,t,r),doubleTap:async(t,r)=>{await ie(e,t,r),await ie(e,t,r)},swipe:(t,r,a,i,n)=>it(e,t,r,a,i,n),longPress:(t,r,a)=>io(e,t,r,a),focus:(t,r)=>il(e,t,r),type:t=>is(e,t),fill:(t,r,a)=>id(e,t,r,a),scroll:(t,r)=>iu(e,t,r),scrollIntoView:t=>ic(e,t),screenshot:(t,r)=>iU(e,t),back:()=>ir(e),home:()=>ia(e),appSwitcher:()=>ii(e),readClipboard:()=>ib(e),writeClipboard:t=>iS(e,t),setSetting:(t,r,a,i)=>ik(e,t,r,a,i)};case"ios":case"macos":{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(em(a.requestId))throw ew()},{runnerOpts:i,overrides:{tap:async(e,t)=>await tS(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),doubleTap:async(e,t)=>await tS(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 tS(r,{command:"drag",x:e,y:t,x2:n,y2:o,durationMs:s,appBundleId:a.appBundleId},i),longPress:async(e,t,n)=>await tS(r,{command:"longPress",x:e,y:t,durationMs:n,appBundleId:a.appBundleId},i),focus:async(e,t)=>await tS(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),type:async e=>{await tS(r,{command:"type",text:e,appBundleId:a.appBundleId},i)},fill:async(e,t,n)=>{let o=await tS(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i);return await tS(r,{command:"type",text:n,clearFirst:!0,appBundleId:a.appBundleId},i),o},scroll:async(e,t)=>{if(!["up","down","left","right"].includes(e))throw new v("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);return await tS(r,{command:"swipe",direction:n,appBundleId:a.appBundleId},i)},scrollIntoView:async e=>{let t=await tS(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 tS(r,{command:"swipe",direction:"up",appBundleId:a.appBundleId},i),await new Promise(e=>setTimeout(e,80));n();let o=await tS(r,{command:"findText",text:e,appBundleId:a.appBundleId},i);if(o?.found)return{attempts:t+2}}throw new v("COMMAND_FAILED",`scrollintoview could not find text: ${e}`)}}});return{open:(t,r)=>nW(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>nz(e),close:t=>nJ(e,t),screenshot:(t,r)=>nL(e,t,r),back:async()=>{await tS(e,{command:"back",appBundleId:t.appBundleId},s)},home:async()=>{await tS(e,{command:"home",appBundleId:t.appBundleId},s)},appSwitcher:async()=>{await tS(e,{command:"appSwitcher",appBundleId:t.appBundleId},s)},readClipboard:()=>nQ(e),writeClipboard:t=>n0(e,t),setSetting:(t,r,a,i)=>n2(e,t,r,a,i),...o}}default:throw new v("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,{requestId:i?.requestId,appBundleId:i?.appBundleId,verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath});return O({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await k("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new v("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await n.openDevice(),{app:null};if(void 0!==a){if("android"===e.platform)throw new v("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(rC(t))throw new v("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!rC(a))throw new v("INVALID_ARGS","open <app> <url> requires a valid URL target");return await n.open(t,{activity:i?.activity,appBundleId:i?.appBundleId,url:a}),{app:t,url:a}}return await n.open(t,{activity:i?.activity,appBundleId:i?.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,[a,o]=r.map(Number);if(Number.isNaN(a)||Number.isNaN(o))throw new v("INVALID_ARGS","press requires x y");let s=oi(i);if("primary"!==s){let t=on({commandLabel:"click",platform:e.platform,button:s,count:i?.count,intervalMs:i?.intervalMs,holdMs:i?.holdMs,jitterPx:i?.jitterPx,doubleTap:i?.doubleTap});if(t)throw t;return await tS(e,{command:"mouseClick",x:a,y:o,button:s,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{x:a,y:o,button:s}}let l=ol(i?.count??1,"count",1,200),d=ol(i?.intervalMs??0,"interval-ms",0,1e4),u=ol(i?.holdMs??0,"hold-ms",0,1e4),c=ol(i?.jitterPx??0,"jitter-px",0,100),p=i?.doubleTap===!0;if(p&&u>0)throw new v("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(p&&c>0)throw new v("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&l>1&&0===u&&0===c){let t=await tS(e,{command:"tapSeries",x:a,y:o,count:l,intervalMs:d,doubleTap:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x:a,y:o,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,timingMode:"runner-series",...t}}return await od(l,d,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=os[e%os.length];return[r*t,a*t]}(e,c),s=a+r,l=o+i;if(p){t??=await n.doubleTap(s,l)??void 0;return}u>0?t??=await n.longPress(s,l,u)??void 0:t??=await n.tap(s,l)??void 0}),{x:a,y:o,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,...t}}case"swipe":{let t=Number(r[0]),a=Number(r[1]),o=Number(r[2]),s=Number(r[3]);if([t,a,o,s].some(Number.isNaN))throw new v("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=ol(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=ol(i?.count??1,"count",1,200),c=ol(i?.pauseMs??0,"pause-ms",0,1e4),p=i?.pattern??"one-way";if("one-way"!==p&&"ping-pong"!==p)throw new v("INVALID_ARGS",`Invalid pattern: ${p}`);if(("ios"===e.platform||"macos"===e.platform)&&u>1){let r=await tS(e,{command:"dragSeries",x:t,y:a,x2:o,y2:s,durationMs:d,count:u,pauseMs:c,pattern:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x1:t,y1:a,x2:o,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:p,...r}}return await od(u,c,async e=>{"ping-pong"===p&&e%2==1?await n.swipe(o,s,t,a,d):await n.swipe(t,a,o,s,d)}),{x1:t,y1:a,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]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new v("INVALID_ARGS","longpress requires x y [durationMs]");return await n.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 v("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 v("INVALID_ARGS","type requires text");return await n.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 v("INVALID_ARGS","fill requires x y text");return await n.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 v("INVALID_ARGS","scroll requires direction");let a=await n.scroll(e,t);return{direction:e,amount:t,...a}}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new v("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 v("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,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new v("INVALID_ARGS","pinch requires scale > 0");return await tS(e,{command:"pinch",scale:t,x:a,y:n,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{scale:t,x:a,y:n}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new v("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oo.test(t))throw new v("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 v("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 v("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 v("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof v)throw t;throw new v("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),o=function(e,t,r){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new v("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new v("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await n.open(o,{appBundleId:i?.appBundleId}),{event:t,eventUrl:o,transport:"deep-link"}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await x.mkdir(o.dirname(e),{recursive:!0}),await n.screenshot(e,i?.appBundleId),{path:e}}case"back":return await n.back(),{action:"back"};case"home":return await n.home(),{action:"home"};case"app-switcher":return await n.appSwitcher(),{action:"app-switcher"};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new v("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new v("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await n.readClipboard()}}if(r.length<2)throw new v("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await n.writeClipboard(t),{action:e,textLength:Array.from(t).length}}case"keyboard":{if("android"!==e.platform)throw new v("UNSUPPORTED_OPERATION","keyboard is currently supported only on Android");let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new v("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new v("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("dismiss"===t){let t=await iy(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 iI(e);return{platform:"android",action:"status",visible:a.visible,inputType:a.inputType,type:a.type}}case"settings":{let[t,a,o,s,l]=r,d="permission"===t?{permissionTarget:o,permissionMode:s}:void 0;return O({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:o,mode:s,platform:e.platform}}),await n.setSetting(t,a,l??i?.appBundleId,d),{setting:t,state:a}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new v("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await op(a);if("ios"===e.platform)return await n1(e,t,i),{platform:"ios",bundleId:t};let n=await iT(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount}}case"snapshot":{if("android"!==e.platform){let t=await k("snapshot_capture",async()=>await tS(e,{command:"snapshot",appBundleId:i?.appBundleId,interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new v("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await k("snapshot_capture",async()=>await a8(e,{interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}default:throw new v("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}let oR=e=>"macos"!==e.platform,oT={alert:{apple:{simulator:!0},android:{}},pinch:{apple:{simulator:!0},android:{}},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{},android:{emulator:!0,device:!0,unknown:!0}},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},supports:oR},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function o$(e,t){let r=oT[e];if(!r)return!0;let a=eY(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function oF(e,t,r,a,i){return{requestId:i??E().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,clickButton:oi(t),pauseMs:t?.pauseMs,pattern:t?.pattern}}let oU=e_(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function oV(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:i8}));await t(e);return}if("device"===e.kind)return void await oG(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:r5}));await t(e.id)}}async function oG(e){let t=o.join(F.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(oU/1e3));try{let a=await f("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:oU+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await oj(t);if(0===a.exitCode){if(!o.parsed)throw new v("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 v("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 v("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:oB(i,n)})}catch(t){if(t instanceof v&&"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??oU),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 v("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?oB(a,i):o},t)}throw new v("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 x.rm(t,{force:!0}).catch(()=>{})}}async function oj(e){try{let t=await x.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 oB(e,t){let r=i0(e,t);return r||(`${e}
33
+ ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":iQ)}function oq(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function oH(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function oW(e,t){return e.find(e=>e.ref===t)??null}function oz(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function oJ(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 oK(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&&oX(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||!oX(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&&oX(r)?r:void 0)}function oX(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function oY(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=oZ(a.type??""),n=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&oX(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 oZ(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 oQ(e,t){let r=oZ(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 o0(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let o1=new Set(["id","role","text","label","value"]),o2=new Set(["visible","hidden","editable","selected","enabled","hittable"]),o3=new Set([...o1,...o2]);function o4(e){let t=e.trim();if(!t)throw new v("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)&&!se(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 v("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",i+=1;continue}r+=n}let i=r.trim();if(!i)throw new v("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(i),t}(t);if(0===r.length)throw new v("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new v("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)&&!se(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 v("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim().length>0&&t.push(r.trim()),t}(t);if(0===r.length)throw new v("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(o9)}})(e))}}function o8(e){try{return o4(e)}catch{return null}}function o5(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 o3.has(e)}return o3.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&o8(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 o6(e){let t=e[0]??"",r=o5(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function o9(e){let t=e.trim();if(!t)throw new v("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!o2.has(r))throw new v("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(!o3.has(a))throw new v("INVALID_ARGS",`Unknown selector key: ${a}`);if(!i)throw new v("INVALID_ARGS",`Missing selector value for key: ${a}`);if(o2.has(a)){let e,t="true"===(e=o7(i).toLowerCase())||"false"!==e&&null;if(null===t)throw new v("INVALID_ARGS",`Invalid boolean value for ${a}: ${i}`);return{key:a,value:t}}return{key:a,value:o7(i)}}function o7(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function se(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function st(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return si(e.identifier,String(t.value));case"role":var a,i;return a=e.type,i=String(t.value),function(e){return oZ(e)}(a??"")===function(e){return oZ(e)}(i);case"label":return si(e.label,String(t.value));case"value":return si(e.value,String(t.value));case"text":{let r=sn(String(t.value));return sn(o0(e))===r}case"visible":return sr(e)===!!t.value;case"hidden":return!sr(e)==!!t.value;case"editable":return sa(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 sr(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function sa(e,t){return oQ(e.type??"",t)&&!1!==e.enabled}function si(e,t){return sn(e??"")===sn(t)}function sn(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function so(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||!st(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=sd(e),n=sd(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 ss(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)&&st(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 sl(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 sd(e){return e.rect?e.rect.width*e.rect.height:1/0}function su(e,t,r={}){let a=[],i=oZ(e.type??""),n=sp(e.identifier),o=sp(e.label),s=sp(e.value),l=sp(o0(e)),d="fill"===r.action;n&&a.push(`id=${sc(n)}`),i&&o&&a.push(d?`role=${sc(i)} label=${sc(o)} editable=true`:`role=${sc(i)} label=${sc(o)}`),o&&a.push(d?`label=${sc(o)} editable=true`:`label=${sc(o)}`),s&&a.push(d?`value=${sc(s)} editable=true`:`value=${sc(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${sc(l)} editable=true`:`text=${sc(l)}`),i&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${sc(i)} editable=true`);let u=tD(a);return 0===u.length&&i&&u.push(d?`role=${sc(i)} editable=true`:`role=${sc(i)}`),0===u.length&&sr(e)&&u.push("visible=true"),u}function sc(e){return JSON.stringify(e)}function sp(e){if(!e)return null;let t=e.trim();return t||null}let sf=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),sm=/https?:\/\/[^\s"'<>\])]+/i,sh=[/\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 sw(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 sg(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return sv(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 sv(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function sA(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function sI(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}let sy="shared_prefs/ReactNativeDevPrefs.xml",sb="debug_http_host",sS="dev_server_https",s_="RCT_jsLocation",sN="RCT_packager_scheme",sD="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.",sE='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function sM(e){return void 0!==sk(e)}function sk(e){if(!e)return;let t=sG(e.metroHost),r=sB(e.metroPort),a="http",i=sG(e.bundleUrl);if(i){var n;let e;try{e=new A(i)}catch(e){throw new v("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=sG(e.hostname),r??=sB(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 sL(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=sk(a);if(i){if("android"===t.platform)return void await sx(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await sT(t,r,i)}}async function sO(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await sC(t,r);"ios"===t.platform&&"simulator"===t.kind&&await s$(t,r)}}async function sx(e,t,r){var a,i,n,o,s,l;let d,u;sj(t);let c=(a=await sP(e,t),i=sb,n=`${r.host}:${r.port}`,d=` <string name="${sq(i)}">${sq(n)}</string>`,sU(sV(a,i),d));o=c,s=sS,l="https"===r.scheme,u=` <boolean name="${sq(s)}" value="${l?"true":"false"}" />`,c=sU(sV(o,s),u),await sR(e,t,c)}async function sC(e,t){sj(t);let r=await sP(e,t),a=sV(r,sb),i=sV(a,sS);i!==r&&await sR(e,t,i)}async function sP(e,t){let r=await f("adb",rk(e,["shell","run-as",t,"cat",sy]),{allowFailure:!0});return 0!==r.exitCode?sE:sF(r.stdout)}async function sR(e,t,r){let a=rk(e,["shell","run-as",t,"id"]),i=await f("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=sH(i.stdout,i.stderr);throw new v("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?sD:"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",rk(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await f("adb",rk(e,["shell","run-as",t,"tee",sy]),{stdin:r.trimEnd()})}catch(a){let e=h(a);if("TOOL_MISSING"===e.code)throw e;let r=sH("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new v("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?sD:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function sT(e,t,r){await f("xcrun",eC(e,["spawn",e.id,"defaults","write",t,s_,"-string",`${r.host}:${r.port}`])),await f("xcrun",eC(e,["spawn",e.id,"defaults","write",t,sN,"-string",r.scheme]))}async function s$(e,t){await f("xcrun",eC(e,["spawn",e.id,"defaults","delete",t,s_]),{allowFailure:!0}),await f("xcrun",eC(e,["spawn",e.id,"defaults","delete",t,sN]),{allowFailure:!0})}function sF(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
34
+ `:sE}function sU(e,t){return sF(e).replace("</map>",`${t}
35
+ </map>`)}function sV(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return sF(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 sG(e){let t=e?.trim();return t&&t.length>0?t:void 0}function sj(e){if("binary"!==r7(e))return;let t=ae(e);throw new v("INVALID_ARGS",t,{package:e,hint:t})}function sB(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function sq(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function sH(e,t){let r=`${e}
36
+ ${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}function sW(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=o5(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 sz(e){return!!e&&!Number.isNaN(Number(e))}let sJ=e_(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),sK=new Map;async function sX(e){let t=await n.mkdtemp(o.join(F.tmpdir(),"agent-device-materialized-"));try{let r=await sQ(e.installablePath,o.join(t,"installable")),a=e.archivePath?await sQ(e.archivePath,o.join(t,"archive")):void 0,i=p.randomUUID(),n=e.ttlMs??sJ,s=Date.now()+n,l=setTimeout(()=>{sY(i)},n);return sK.set(i,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:i,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await n.rm(t,{recursive:!0,force:!0}),e}}async function sY(e,t){let r=sK.get(e);if(!r)throw new v("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new v("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),sK.delete(e),await n.rm(r.rootPath,{recursive:!0,force:!0})}async function sZ(e){let t=Array.from(sK.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await sY(e)}))}async function sQ(e,t){let r=await n.stat(e);await n.mkdir(t,{recursive:!0});let a=o.join(t,o.basename(e));return r.isDirectory()?await n.cp(e,a,{recursive:!0}):await n.copyFile(e,a),a}async function s0(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 v("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await oV(e.session.device),e.session.device}if(!r)throw new v("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await oC(e.flags??{});return await oV(a),a}async function s1(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 v("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new v("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new v("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:t5(s,t.meta?.tenantId)},cleanup:()=>{t6(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 v("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),u=await (i?.resolveInstallDevice??s0)({session:n,flags:t.flags});if(!o$("install",u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let c=(i?.getRequestSignal??eh)(t.meta?.requestId);if("ios"===u.platform){let e,o=i?.installIosInstallablePath??(await Promise.resolve().then(()=>({closeIosApp:nJ,ensureBootedSimulator:i8,installIosApp:nX,installIosInstallablePath:nZ,listIosApps:n3,listSimulatorApps:n4,openIosApp:nW,openIosDevice:nz,parseIosDeviceAppsPayload:iZ,pushIosNotification:n1,readIosClipboardText:nQ,reinstallIosApp:nY,resolveIosApp:nH,screenshotIos:nL,setIosSetting:n2,uninstallIosApp:nK,writeIosClipboardText:n0}))).installIosInstallablePath,s=i?.prepareIosInstallArtifact??(await Promise.resolve().then(()=>({prepareIosInstallArtifact:i7,readIosBundleInfo:ne}))).prepareIosInstallArtifact,p=await s(l.source,{signal:c});try{if(d.enabled&&(e=await sX({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 v("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 sY(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),l.cleanup()}}let p=i?.prepareAndroidInstallArtifact??(await Promise.resolve().then(()=>({prepareAndroidInstallArtifact:ay}))).prepareAndroidInstallArtifact,f=i?.installAndroidInstallablePathAndResolvePackageName??(await Promise.resolve().then(()=>({appSwitcherAndroid:ii,backAndroid:ir,closeAndroidApp:aV,dismissAndroidKeyboard:iy,ensureAdb:rL,fillAndroid:id,focusAndroid:il,getAndroidAppState:aC,getAndroidKeyboardState:iI,getAndroidScreenSize:ip,homeAndroid:ia,inferAndroidAppName:ax,installAndroidApp:aY,installAndroidInstallablePath:aK,installAndroidInstallablePathAndResolvePackageName:aX,isAmStartError:a$,listAndroidApps:aM,longPressAndroid:io,openAndroidApp:aR,openAndroidDevice:aU,parseAndroidLaunchComponent:aF,pressAndroid:ie,pushAndroidNotification:iT,readAndroidClipboardText:ib,reinstallAndroidApp:aZ,resolveAndroidApp:aE,screenshotAndroid:iU,scrollAndroid:iu,scrollIntoViewAndroid:ic,setAndroidSetting:ik,snapshotAndroid:a8,swipeAndroid:it,typeAndroid:is,writeAndroidClipboardText:iS}))).installAndroidInstallablePathAndResolvePackageName,m=await p(l.source,{signal:c});try{d.enabled&&(e=await sX({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 v("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:ii,backAndroid:ir,closeAndroidApp:aV,dismissAndroidKeyboard:iy,ensureAdb:rL,fillAndroid:id,focusAndroid:il,getAndroidAppState:aC,getAndroidKeyboardState:iI,getAndroidScreenSize:ip,homeAndroid:ia,inferAndroidAppName:ax,installAndroidApp:aY,installAndroidInstallablePath:aK,installAndroidInstallablePathAndResolvePackageName:aX,isAmStartError:a$,listAndroidApps:aM,longPressAndroid:io,openAndroidApp:aR,openAndroidDevice:aU,parseAndroidLaunchComponent:aF,pressAndroid:ie,pushAndroidNotification:iT,readAndroidClipboardText:ib,reinstallAndroidApp:aZ,resolveAndroidApp:aE,screenshotAndroid:iU,scrollAndroid:iu,scrollIntoViewAndroid:ic,setAndroidSetting:ik,snapshotAndroid:a8,swipeAndroid:it,typeAndroid:is,writeAndroidClipboardText:iS}))).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 sY(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await m.cleanup(),l.cleanup()}}catch(e){return{ok:!1,error:S(e)}}}async function s2(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new v("INVALID_ARGS","release_materialized_paths requires a materializationId");return await sY(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:S(e)}}}async function s3(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new v("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await s4({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await s8({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await s5(t,u),a=!0)}else t=(await s8({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await s5(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 s4(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await f("xcrun",ex(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:iq});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||s6(a).includes(s6(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 s8(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await f("xcrun",ex(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new v("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 v("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function s5(e,t){let r=await f("xcrun",ex(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:iq});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 s6(e){return e.toLowerCase().replace(/[._-]/g,"")}let s9=e_(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),s7=e_(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function le(e,t,r){return t||lt(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function lt(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function lr(e){return"ios"===e.platform&&"simulator"===e.kind}async function la(e,t){lr(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function li(e){let t=lt(e.flags)||!e.session?await e.resolveTargetDeviceFn(e.flags??{}):await ln(e.session.device,e.resolveTargetDeviceFn);return!1!==e.ensureReady&&await e.ensureReadyFn(t),t}async function ln(e,t){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let r={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await t(r)}catch(e){if(!(e instanceof v)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await t({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function lo(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 ls=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function ll(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function ld(e){let t=e?.trim();return t&&t.length>0?t:void 0}function lu(e,t){if(void 0!==e){if("string"!=typeof e)throw new v("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return ld(e)}}function lc(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new v("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function lp(e){if("ios"===e||"android"===e)return e}function lf(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 v("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!ls.includes(e));if(i)throw new v("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${ls.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new v("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new v("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:lu(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new v("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return lc(e)}}(t.metroPort),bundleUrl:lu(t.bundleUrl,"bundleUrl"),launchUrl:lu(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:lp(i.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let i=r?.platform,n=lp(i);if(a.platform&&r&&!n)throw new v("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new v("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&ll(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=h(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}async function lm(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i,clearRuntimeHints:n}=e;!t||!i?.appBundleId||!sM(r)||sM(a)||await n({device:i.device,appId:i.appBundleId})}async function lh(e){var t,r;let{req:a,sessionName:i,sessionStore:n,clearRuntimeHints:o=sO}=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){sM(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=lp(a.flags?.platform??d?.platform??l?.device.platform);if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first."}};if(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:ld(t?.metroHost),metroPort:lc(t?.metroPort),bundleUrl:ld(t?.bundleUrl),launchUrl:ld(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===ll(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 lw(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return rC(t)?"macos"===e.platform?void 0:"device"===e.kind?rP(r,t):void 0:await lg(e,t)}async function lg(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:nH}));return await r(e,t)}catch{return}}async function lv(e,t){if(!("android"!==e.platform||!t||rC(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:aE})),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function lA(e,t,r,a){return await lw(e,t,r)??await a(e,t)??("android"===e.platform&&t&&rC(t)?r:void 0)}let lI="open-command-roundtrip",ly="Not implemented for this platform in this release.";async function lb(e){let{device:t,closeTarget:r,stopIosRunner:a,dispatch:i,outFlag:n,context:o,settleSimulator:s}=e;"android"!==t.platform&&await a(t.id),await i(t,"close",[r],n,o),await s(t,s9)}async function lS(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||rC(u)||await a(r,"open",[d],i.flags?.out,{...oF(n,i.flags,o,s)})}async function l_(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,v=i.flags?.relaunch===!0,A=g?.trace?.outPath;if(v&&f){let e=h??f;await lb({device:l,closeTarget:e,stopIosRunner:c,dispatch:d,outFlag:i.flags?.out,context:{...oF(s,i.flags,h??g?.appBundleId,A)},settleSimulator:p})}await u({device:l,appId:h,runtime:w});let I=Date.now();await d(l,"open",m,i.flags?.out,{...oF(s,i.flags,h)}),await lS({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()-I),measuredAt:new Date().toISOString(),method:lI,appTarget:f,appBundleId:h}:void 0;await p(l,s7);let b=function(e){let{existingSession:t,sessionName:r,device:a,appBundleId:i,openTarget:n,saveScript:o}=e;return t?{...t,device:a,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===ll(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let S=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&&ll(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 o.recordAction(b,{command:"open",positionals:m,flags:i.flags??{},runtime:void 0!==i.runtime?w:void 0,result:S}),o.set(n,b),{ok:!0,data:S}}async function lN(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n,ensureReady:o,resolveDevice:s,applyRuntimeHints:l=sL,clearRuntimeHints:d=sO,stopIosRunner:u=tw,settleSimulator:c=la,resolveAndroidPackageForOpen:p=lv}=e,f=t.flags?.relaunch===!0;if(i.has(r)){let e=i.get(r),m=t.positionals?.[0],h=m??(f?e?.appName:void 0);if(!e||!h)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&&rC(h))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};if(f&&"android"===e.device.platform&&"binary"===r7(h))return{ok:!1,error:{code:"INVALID_ARGS",message:ae(h)}};let w=await ln(e.device,s);await o(w);let g=await lA(w,h,e.appBundleId,p),v=lf({req:t,sessionStore:i,sessionName:r,device:w});if(!v.ok)return v.response;let{runtime:A,previousRuntime:I,replacedStoredRuntime:y}=v.data;await lm({replacedStoredRuntime:y,previousRuntime:I,runtime:A,session:e,clearRuntimeHints:d});let b=m?t.positionals??[]:[h];return await l_({req:t,sessionName:r,sessionStore:i,logPath:a,device:w,dispatch:n,applyRuntimeHints:l,stopIosRunner:u,settleSimulator:c,openTarget:h,openPositionals:b,appBundleId:g,runtime:A,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&&rC(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"===r7(m))return{ok:!1,error:{code:"INVALID_ARGS",message:ae(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 lA(h,m,void 0,p),v=lf({req:t,sessionStore:i,sessionName:r,device:h});if(!v.ok)return v.response;let{runtime:A}=v.data;return await l_({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 lD(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 lE(e){let{device:t,shutdownRequested:r,shutdownSimulator:a,shutdownAndroidEmulator:i}=e;if(r&&(lr(t)||"android"===t.platform&&"emulator"===t.kind))try{return lr(t)?await a(t):await i(t)}catch(t){let e=S(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function lM(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n,stopIosRunner:o=tw,clearRuntimeHints:s=sO,settleSimulator:l=la,shutdownSimulator:d=i5,shutdownAndroidEmulator:u=lD,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,{...oF(a,t.flags,p.appBundleId,p.trace?.outPath)}),await l(p.device,s9)),"ios"===p.device.platform&&await o(p.device.id),sM(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 sZ(r).catch(()=>{}),i.delete(r);let f=await lE({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 lk={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve().then(()=>({reinstallIosApp:nY}));return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve().then(()=>({reinstallAndroidApp:aZ}));return await a(e,t,r)}},lL={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve().then(()=>({installIosApp:nX})),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:aY})),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function lO(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=le(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?t5(f,t.meta?.tenantId):tV.expandHome(p);if(!T.existsSync(a))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${a}`}};let u=await li({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!1});if(!o$(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&&t6(f)}}let lx=["platform","target","device","udid","serial","verbose","out"];async function lC(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??q;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=W(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await lP(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=h(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function lP(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{},o=e??{};for(let e of lx)void 0===n[e]&&void 0!==o[e]&&(n[e]=o[e]);return n}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}let lR='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',lT='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").',l$=["platform","target","device","udid","serial","verbose","out"],lF=["path","start","stop","doctor","mark","clear"],lU=`logs requires ${lF.slice(0,-1).join(", ")}, or ${lF.at(-1)}`,lV=["dump","log"],lG=`network requires ${lV.join(" or ")}`,lj=["summary","headers","body","all"],lB=`network include mode must be one of: ${lj.join(", ")}`,lq=async({avdName:e,serial:t,headless:r})=>{let{ensureAndroidEmulatorBooted:a}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:r4}));return await a({avdName:e,serial:t,headless:r})};async function lH(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=le(l,p,f);if(m)return m;let h=await li({session:p,flags:f,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!o$(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,{...oF(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??{}}}function lW(e){return e.appLog?e.appLog.backend:"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"}async function lz(e){let{req:t,sessionName:r,sessionStore:a,ensureReady:i,resolveDevice:n}=e,o=a.get(r),s=t.flags??{},l=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=le("appstate",o,s);if(d)return d;let u=(o?.device.platform==="ios"||o?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!lt(e))return!0;let r=e?.platform;return!(r&&!eZ(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(s,o);if("ios"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lR}};if("macos"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lT}};if(u&&o){let e=o.appName??o.appBundleId;if(!o.appName&&!o.appBundleId){let e="macos"===o.device.platform?"macOS":"iOS";return{ok:!1,error:{code:"COMMAND_FAILED",message:`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`}}}return{ok:!0,data:{platform:o.device.platform,appName:e??"unknown",appBundleId:o.appBundleId,source:"session",..."ios"===o.device.platform?{device_udid:o.device.id,ios_simulator_device_set:o.device.simulatorSetPath??null}:{}}}}let c=await li({session:o,flags:s,ensureReadyFn:i,resolveTargetDeviceFn:n,ensureReady:!0});if("ios"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lR}};if("macos"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lT}};let{getAndroidAppState:p}=await Promise.resolve().then(()=>({getAndroidAppState:aC})),f=await p(c);return{ok:!0,data:{platform:"android",package:f.package,activity:f.activity}}}async function lJ(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=le("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 li({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!o$("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,{...oF(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 lK(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,dispatch:o,ensureReady:s,resolveTargetDevice:l,installOps:d=lL,reinstallOps:u=lk,stopIosRunner:c,appLogOps:p={start:tQ,stop:t0},ensureAndroidEmulatorBoot:f=lq,resolveAndroidPackageForOpen:m=lv,applyRuntimeHints:w=sL,clearRuntimeHints:g=sO,settleSimulator:A,shutdownSimulator:I,shutdownAndroidEmulator:y,listAndroidDevices:b,listAppleDevices:_,listAppleApps:N}=e,D=o??oP,E=s??oV,M=l??oC,k=c??tw,L=A??la,O=t.command;if("session_list"===O)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,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("runtime"===O)return await lh({req:t,sessionName:r,sessionStore:i,clearRuntimeHints:g});if("ensure-simulator"===O)try{let e=t.flags??{},r=e.device,a=e.runtime,i=ek(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 s3({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:o,boot:n,ensureReady:E});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=h(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===O)try{let e=[],r=eO(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,i=eQ({simulatorSetPath:ek(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let t=b??(await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:r4,ensureAndroidEmulatorHeadlessBooted:r8,listAndroidDevices:rX,parseAndroidAvdList:rZ,parseAndroidEmulatorAvdNameOutput:rV,parseAndroidFeatureListForTv:rW,parseAndroidTargetFromCharacteristics:rH,resolveAndroidAvdName:rQ,resolveAndroidEmulatorAvdName:rq,waitForAndroidBoot:r5}))).listAndroidDevices;e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let t=_??(await Promise.resolve().then(()=>({findBootableIosSimulator:oL,isAppleProductType:o_,isAppleTvProductType:oN,isSupportedAppleDevicectlDevice:ok,listAppleDevices:oO,listIosDevices:oO,resolveAppleTargetFromDevicectlDevice:oM}))).listAppleDevices;e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let t=b??(await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:r4,ensureAndroidEmulatorHeadlessBooted:r8,listAndroidDevices:rX,parseAndroidAvdList:rZ,parseAndroidEmulatorAvdNameOutput:rV,parseAndroidFeatureListForTv:rW,parseAndroidTargetFromCharacteristics:rH,resolveAndroidAvdName:rQ,resolveAndroidEmulatorAvdName:rq,waitForAndroidBoot:r5}))).listAndroidDevices;try{e.push(...await t({serialAllowlist:r}))}catch{}}let t=_??(await Promise.resolve().then(()=>({findBootableIosSimulator:oL,isAppleProductType:o_,isAppleTvProductType:oN,isSupportedAppleDevicectlDevice:ok,listAppleDevices:oO,listIosDevices:oO,resolveAppleTargetFromDevicectlDevice:oM}))).listAppleDevices;try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=h(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===O){let e=i.get(r),a=t.flags??{},n=le(O,e,a);if(n)return n;let o=await li({session:e,flags:a,ensureReadyFn:E,resolveTargetDeviceFn:M,ensureReady:!0});if(!o$("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(eY(o.platform)){let e=N??(await Promise.resolve().then(()=>({closeIosApp:nJ,ensureBootedSimulator:i8,installIosApp:nX,installIosInstallablePath:nZ,listIosApps:n3,listSimulatorApps:n4,openIosApp:nW,openIosDevice:nz,parseIosDeviceAppsPayload:iZ,pushIosNotification:n1,readIosClipboardText:nQ,reinstallIosApp:nY,resolveIosApp:nH,screenshotIos:nL,setIosSetting:n2,uninstallIosApp:nK,writeIosClipboardText:n0}))).listIosApps;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:aM}));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"===O){let e,a=i.get(r),n=t.flags??{},o=le(O,a,n);if(o)return o;let s="android"===(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=lo({flags:n,sessionDevice:a?.device}),u=s&&!!d,c=!1;try{e=await li({session:a,flags:n,ensureReadyFn:E,resolveTargetDeviceFn:M,ensureReady:!1})}catch(r){let t=h(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 f({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=lo({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 f({avdName:t,serial:n.serial,headless:!0})}await E(e)}else("android"!==e.platform||!0!==e.booted)&&await E(e);return o$("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 lz({req:t,sessionName:r,sessionStore:i,ensureReady:E,resolveDevice:M});if("clipboard"===O)return await lJ({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:M,dispatch:D});if("keyboard"===O)return await lH({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:M,dispatch:D,command:"keyboard",positionals:t.positionals??[]});if("perf"===O){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===lI&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:lI,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:lI,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:lI},{session:n.name,platform:n.device.platform,device:n.device.name,deviceId:n.device.id,metrics:{startup:a,fps:{available:!1,reason:ly},memory:{available:!1,reason:ly},cpu:{available:!1,reason:ly}},sampling:{startup:{method:lI,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 lO({req:t,command:O,sessionName:r,sessionStore:i,ensureReady:E,resolveDevice:M,deployOps:"install"===O?d:u});if("install_source"===O)return await s1({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===O)return await s2({req:t});if("push"===O){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=oc(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tV.expandHome(e,t)})).kind?e.path:e.text;return await lH({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:M,dispatch:D,command:"push",positionals:[n,s],recordPositionals:[n,o]})}if("trigger-app-event"===O)return await lH({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:E,resolveDevice:M,dispatch:D,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await lA(e.device,r,e.appBundleId,m)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}});if("open"===O)return await lN({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:D,ensureReady:E,resolveDevice:M,applyRuntimeHints:w,clearRuntimeHints:g,stopIosRunner:k,settleSimulator:L,resolveAndroidPackageForOpen:m});if("replay"===O){let e=t.positionals?.[0];if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};try{let o=tV.expandHome(e,t.meta?.cwd),s=T.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 v("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=t$(r);return{positionals:i.positionals,flags:a,runtime:(t=i.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?i.flags:void 0}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n.runtime=e.runtime,n}if("runtime"===a){let e=t$(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tL(a)){let e=tT(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 sz(r)&&sz(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=tT(a,i);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}if("record"===a){let e=[];for(let t=0;t<i.length;t+=1){let r=i[t];if("--hide-touches"===r){n.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(n.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return n.positionals=e,n}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:lY(t.flags,s.flags),runtime:s.runtime,meta:t.meta});if(l.ok)continue;if(!u)return lX(l,s,e,o);let p=await lZ({action:s,sessionName:r,logPath:a,sessionStore:i,dispatch:D});if(!p)return lX(l,s,e,o);if(d[e]=p,!(l=await n({token:t.token,session:r,command:p.command,positionals:p.positionals??[],flags:lY(t.flags,p.flags),runtime:p.runtime,meta:t.meta})).ok)return lX(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",tO(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tU(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tx(r));return tP(t,e.flags),t.join(" ")}if("record"===e.command)return tR(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tO(r));return tC(t,e),t.join(" ")}(e));let i=`${a.join("\n")}
37
+ `,n=`${e}.tmp-${process.pid}-${Date.now()}`;T.writeFileSync(n,i),T.renameSync(n,e)}(o,d,e)}return{ok:!0,data:{replayed:d.length,healed:c,session:r}}}catch(t){let e=h(t);return{ok:!1,error:{code:e.code,message:e.message}}}}if("logs"===O){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!o$("logs",e.device))return{ok:!1,error:S(new v("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let a=(t.positionals?.[0]??"path").toLowerCase(),n=!!t.flags?.restart;if(!lF.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:lU}};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(!T.existsSync(e))return{exists:!1,sizeBytes:0};let t=T.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t),n=lW(e);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 t1(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 tZ(n),e=`[agent-device][mark][${new Date().toISOString()}] ${a.trim()||"marker"}
38
+ `,T.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&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let t=i.resolveAppLogPath(r);if(n){e.appLog&&await p.stop(e.appLog);let a=t2(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=S(a);return i.set(r,{...e,appLog:void 0}),{ok:!1,error:t}}}return{ok:!0,data:t2(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"}};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:S(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"===O){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!o$("network",e.device))return{ok:!1,error:S(new v("UNSUPPORTED_OPERATION","network is not supported on this device"))};let a=(t.positionals?.[0]??"dump").toLowerCase();if(!lV.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:lG}};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(!lj.includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:lB}};let l=function(e,t){let r=sI(t?.maxEntries,25,1,200),a=t?.include??"summary",i=sI(t?.maxPayloadChars,2048,64,16384),n=sI(t?.maxScanLines,4e3,100,2e4);if(!T.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}};let o=T.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=sw(i,["method","httpMethod"]),o=sw(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=sf.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(n??d?.[1]??l?.[1])?.toUpperCase(),c=sm.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of sh){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:sA(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 sv(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,i);t&&(f.headers=sA(t,a))}if("body"===r||"all"===r){let t=sg(e,i,["requestBody","body","payload","request"]),r=sg(e,i,["responseBody","response"]);t&&(f.requestBody=sA(t,a)),r&&(f.responseBody=sA(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=lW(e),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"===O?await lC(t,r,n):"close"===O?await lM({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:D,stopIosRunner:k,clearRuntimeHints:g,settleSimulator:L,shutdownSimulator:I??i5,shutdownAndroidEmulator:y,appLogOps:{stop:p.stop}}):null}function lX(e,t,r,a){if(e.ok)return e;let i=r+1,n=function(e){let t;return t=(e.positionals??[]).map(e=>tO(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 lY(e,t){let r={...t??{}},a=e??{};for(let e of l$)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}async function lZ(e){let{action:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n}=e;if(!(tL(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let o=i.get(r);if(!o)return null;let s=tL(t.command)||"fill"===t.command,l=tL(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await lQ(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),tL(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}=o6(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=sW(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 tD(t).filter(e=>e.trim().length>0)}(t)){let r=o8(e);if(!r)continue;let a=so(d.nodes,r,{platform:o.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!a)continue;let i=su(a.node,o.device.platform,{action:tL(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tL(t.command))return{...t,positionals:[i]};if("fill"===t.command){let e=tN(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}=o6(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}=sW(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=o8(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(oZ(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=o0(e).trim();return!!/^\d+$/.test(t)&&(0===n.size||n.has(oZ(e.type??"")))});if(0===s.length||1!==tD(s.map(e=>o0(e).trim())).length)return null;let l=s[0];if(!l)return null;let d=su(l,r.device.platform,{action:"get"});return 0===d.length?null:{...e,positionals:["text",d.join(" || ")]}}(t,d,o);return u||null}async function lQ(e,t,r,a,i,n){let o=await i(e.device,"snapshot",[],t.flags?.out,{...oF(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[],l={nodes:oq(t.flags?.snapshotRaw?s:oY(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend};return e.snapshot=l,n.set(e.name,e),l}function l0(e,t){let r=H(e.type??"Element"),a=J(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 l1(e,t){return t.flatten?e.map(e=>({text:X(e,0,!1),comparable:l0(e,0)})):B(e).map(e=>({text:e.text,comparable:l0(e.node,e.depth)}))}function l2(e,t){return e.get(t)??0}async function l3(e){let{dispatchSnapshotCommand:t,device:r,session:a,req:i,logPath:n,snapshotScope:o}=e;return{snapshot:l4(await t(r,"snapshot",[],i.flags?.out,{...oF(n,{...i.flags,snapshotScope:o},a?.appBundleId,a?.trace?.outPath)}),i.flags?.snapshotRaw)}}function l4(e,t){let r=e?.nodes??[];return{nodes:oq(t?r:oY(r)),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend}}function l8(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=oH(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=oW(t.snapshot.nodes,r),i=a?oK(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 l5(e,t,r){let a=e.get(t),i=a?.device??await oC(r??{});return a||await oV(i),{session:a,device:i}}async function l6(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await tw(t.id)}}function l9(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function l7(e){let{session:t,sessionName:r,device:a,snapshot:i,appBundleId:n}=e;return t?{...t,snapshot:i}:{name:r,device:a,createdAt:Date.now(),appBundleId:n,snapshot:i,actions:[]}}function de(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function dt(e){let{parsed:t,req:r,sessionName:a,logPath:i,sessionStore:n,session:o,device:s}=e,l=e.dispatchSnapshotCommand??oP,d=e.runnerCommand??tS;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),l9(n,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!o$("wait",s))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}};if("selector"===t.kind)return await dr({dispatchSnapshotCommand:l,device:s,logPath:i,parsed:t,req:r,session:o,sessionName:a,sessionStore:n});let u=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}}};let r=oH(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=oW(t.snapshot.nodes,r),i=a?oK(a,t.snapshot.nodes):void 0;return i?{ok:!0,text:i,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return u.ok?await da({device:s,logPath:i,req:r,runnerCommand:d,session:o,sessionStore:n,text:u.text,timeoutMs:u.timeoutMs}):u.response}async function dr(e){let{dispatchSnapshotCommand:t,device:r,logPath:a,parsed:i,req:n,session:o,sessionName:s,sessionStore:l}=e,d=i.timeoutMs??1e4,u=Date.now();for(;Date.now()-u<d;){let e=l4(await t(r,"snapshot",[],n.flags?.out,{...oF(a,{...n.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},o?.appBundleId,o?.trace?.outPath)}),n.flags?.snapshotRaw),d=e.nodes;o&&(o.snapshot=e,l.set(s,o));let c=ss(d,i.selector,{platform:r.platform});if(c)return l9(l,o,n,{selector:c.selector.raw,waitedMs:Date.now()-u}),{ok:!0,data:{selector:c.selector.raw,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${i.selectorExpression}`}}}async function da(e){let{device:t,logPath:r,req:a,runnerCommand:i,session:n,sessionStore:o,text:s,timeoutMs:l}=e,d=l??1e4,u=Date.now();for(;Date.now()-u<d;){if(eY(t.platform)){let e=await i(t,{command:"findText",text:s,appBundleId:n?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return l9(o,n,a,{text:s,waitedMs:Date.now()-u}),{ok:!0,data:{text:s,waitedMs:Date.now()-u}}}else if("android"===t.platform&&oJ(oq((await a8(t,{scope:s})).nodes??[]),s))return l9(o,n,a,{text:s,waitedMs:Date.now()-u}),{ok:!0,data:{text:s,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${s}`}}}async function di(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n}=e,o=e.runnerCommand??tS,s=(t.positionals?.[0]??"get").toLowerCase();if(!o$("alert",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is only supported on iOS simulators"}};if("wait"===s){let e=de(t.positionals?.[1])??1e4,s=Date.now();for(;Date.now()-s<e;){try{let e=await o(n,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return l9(a,i,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let l="accept"===s||"dismiss"===s?s:"get",d={verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await o(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return l9(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let u=await o(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return l9(a,i,t,u),{ok:!0,data:u}}async function dn(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!o$("settings",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};let u=i?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],p=await oP(n,"settings",c,t.flags?.out,{...oF(r,t.flags,u,i?.trace?.outPath)});return l9(a,i,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}async function ds(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=e.dispatchSnapshotCommand??oP,o=e.runnerCommand??tS,s=e.sessionlessRunnerCleanup??l6,l=t.command;if("snapshot"===l){let{session:e,device:o}=await l5(i,r,t.flags);if(!o$("snapshot",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let l=l8(t.flags?.snapshotScope,e);return l.ok?await s(e,o,async()=>{let s=await l3({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:a,snapshotScope:l.scope}),d=l7({session:e,sessionName:r,device:o,snapshot:s.snapshot,appBundleId:e?.appBundleId});return l9(i,d,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),i.set(r,d),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,appName:d.appBundleId?d.appName??d.appBundleId:void 0,appBundleId:d.appBundleId}}}):l.response}if("diff"===l){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 l5(i,r,t.flags);if(!o$("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let l=l8(t.flags?.snapshotScope,e);if(!l.ok)return l.response;let d=t.flags?.snapshotInteractiveOnly===!0;return await s(e,o,async()=>{let s=(await l3({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:a,snapshotScope:l.scope})).snapshot;if(!e?.snapshot){let a=function(e,t={}){return l1(e,t).length}(s.nodes,{flatten:d}),n=l7({session:e,sessionName:r,device:o,snapshot:s,appBundleId:e?.appBundleId});return l9(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 u=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&&l2(n,i-1)<l2(n,i+1)?l2(n,i+1):l2(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&&l2(i,l-1)<l2(i,l+1)?l+1:l-1,u=l2(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[]}(l1(e,r),l1(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,s.nodes,{flatten:d}),c={...e,snapshot:s};return l9(i,c,t,{mode:"snapshot",baselineInitialized:!1,summary:u.summary}),i.set(r,c),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:u.summary,lines:u.lines}}})}if("wait"===l){let{session:e,device:l}=await l5(i,r,t.flags),d=function(e){if(0===e.length)return null;let t=de(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=de(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=de(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=de(e[e.length-1]),a=o5(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=o8(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}};let u=()=>dt({parsed:d,req:t,sessionName:r,logPath:a,sessionStore:i,session:e,device:l,dispatchSnapshotCommand:n,runnerCommand:o});return"sleep"===d.kind?await u():await s(e,l,u)}if("alert"===l){let{session:e,device:n}=await l5(i,r,t.flags);return await s(e,n,async()=>await di({req:t,logPath:a,sessionStore:i,session:e,device:n,runnerCommand:o}))}if("settings"===l){let e,n,o,l=(e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&n&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:n,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:z}}});if(!l.ok)return l.response;let{session:d,device:u}=await l5(i,r,t.flags);return await s(d,u,async()=>await dn({req:t,logPath:a,sessionStore:i,session:d,device:u,parsed:l.parsed}))}return null}function dl(e,t,r,a={}){let i=du(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 dd(e.label,r);case"value":return dd(e.value,r);case"id":return dd(e.identifier,r);default:return Math.max(dd(e.label,r),dd(e.value,r),dd(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 dd(e,t){let r=du(e??"");return r?r===t?2:+!!r.includes(t):0}function du(e){return e.trim().toLowerCase().replace(/\s+/g," ")}async function dc(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=e.dispatch??oP,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 v("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:a,action:"wait",timeoutMs:de(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 v("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 oC(t.flags??{});m||await oV(h);let w=m?.appBundleId,g="role"!==d?u:void 0,A="click"===c||"focus"===c||"fill"===c||"type"===c,I=0,y=null,b=async()=>{let e=Date.now();if(y&&e-I<750)return{nodes:y};let n=await o(h,"snapshot",[],t.flags?.out,{...oF(a,{...t.flags,snapshotScope:g,snapshotInteractiveOnly:A,snapshotCompact:A},w,m?.trace?.outPath)}),s=n?.nodes??[],l=oq(t.flags?.snapshotRaw?s:oY(s));return I=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(dl(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:S}=await b(),_=dl(S,d,u,{requireRect:A});if(A&&_.matches.length>1){let e=_.matches.slice(0,8).map(e=>{let t=o0(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 N=_.matches[0]??null;if(!N)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}(S,N)??N:N,E=`@${D.ref}`,M={...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=o0(N);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:N}}}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:N}};if("click"===c){let e=await n({token:t.token,session:r,command:"click",positionals:[E],flags:M});if(!e.ok)return e;let a=D.rect?oz(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:M});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=N.rect?oz(N.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,{...oF(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=N.rect?oz(N.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,{...oF(a,t.flags,m?.appBundleId,m?.trace?.outPath)});let r=await o(h,"type",[p],t.flags?.out,{...oF(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}let dp=`
39
+ import Foundation
40
+ import AVFoundation
41
+
42
+ let url = URL(fileURLWithPath: CommandLine.arguments[1])
43
+ let asset = AVURLAsset(url: url)
44
+ let semaphore = DispatchSemaphore(value: 0)
45
+ var exitCode: Int32 = 1
46
+
47
+ Task {
48
+ defer { semaphore.signal() }
49
+ do {
50
+ let playable = try await asset.load(.isPlayable)
51
+ let duration = try await asset.load(.duration)
52
+ if playable && duration.isValid && !duration.isIndefinite && CMTimeGetSeconds(duration) > 0 {
53
+ exitCode = 0
54
+ }
55
+ } catch {
56
+ exitCode = 1
57
+ }
58
+ }
59
+
60
+ semaphore.wait()
61
+ exit(exitCode)
62
+ `.trim();async function df(e,t={}){let r,a=t.pollMs??150,i=t.attempts??12,n=0;for(let t=0;t<i;t+=1){let t=0;try{t=T.statSync(e).size}catch{t=0}if(t>0&&t===r){if((n+=1)>=2)return}else n=0;r=t,await new Promise(e=>setTimeout(e,a))}}async function dm(e){try{var t,r;let a,i=await f("swift",["-",e],{stdin:dp,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
63
+ ${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return dw(e);return!1}catch(t){if(t instanceof v&&"TOOL_MISSING"===t.code)return dw(e);throw t}}async function dh(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await dm(e))return;await new Promise(e=>setTimeout(e,r))}}function dw(e){try{let t=T.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=T.openSync(e,"r");try{let e=T.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>T.readSync(t,e,0,8,r))break;let i=e.readUInt32BE(0),n=e.toString("latin1",4,8);if(a.push(n),1===i){let e=Buffer.alloc(8);if(8>T.readSync(t,e,0,8,r+8))break;i=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(i)||i<=0)break;r+=i}return a}finally{T.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function dg(e){let t=o.parse(e);return o.join(t.dir,`${t.name}.gesture-telemetry.json`)}function dv(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function dA(e){var t,r;let a=dg(e.videoPath),i={version:1,generatedAt:new Date().toISOString(),events:(t=e.events,(r=e.trimStartMs??0)>0?dv(t.flatMap(e=>{let t=e.tMs-r,a="durationMs"in e?e.durationMs:void 0;return("number"==typeof a?t+a:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):dv(t))};return T.writeFileSync(a,JSON.stringify(i,null,2)),a}function dI(e){let{recording:t,trimStartMs:r,writeTelemetry:a=dA}=e,i=a({videoPath:t.outPath,events:t.gestureEvents,trimStartMs:r});return t.telemetryPath=i,i}function dy(e){let t=o.dirname(y(import.meta.url)),r=[y(new URL(`./${e}`,import.meta.url)),o.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(T.existsSync(e))return e;throw new v("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}function db(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}async function dS(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:i}=e;await df(t),await dh(t);let n=T.mkdtempSync(o.join(F.tmpdir(),"agent-device-record-overlay-")),s=o.join(n,`input${o.extname(t)||".mp4"}`),l=o.join(n,o.basename(t)),d=o.join(n,"home"),u=o.join(n,"module-cache");T.copyFileSync(t,s),T.mkdirSync(d,{recursive:!0}),T.mkdirSync(u,{recursive:!0});try{await f("xcrun",["swift",r,"--input",s,"--output",l,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:u}}),await dh(l),T.copyFileSync(l,t)}catch(a){let e=a instanceof v?a:new v("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new v("COMMAND_FAILED",i,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{T.rmSync(n,{recursive:!0,force:!0})}}async function d_(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await dS({videoPath:t,scriptPath:a??=dy("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function dN(e){let{videoPath:t,telemetryPath:a,targetLabel:i="recording"}=e;await dS({videoPath:t,scriptPath:r??=dy("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function dD(e){return e instanceof Error?e.message:String(e)}function dE(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function dM(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===a.exitCode&&a.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function dk(e,t,r){for(let a=0;a<40;a+=1){if(!await dM(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await dM(e,t,r)}async function dL(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await new Promise(e=>setTimeout(e,250))}}async function dO(e,t,r,a){for(let i=0;i<8;i+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?Number(n.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await dM(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function dx(e){let t,{deps:r,deviceId:a,remotePath:i,outPath:n}=e;for(let e=0;e<2;e+=1){try{T.rmSync(n,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",a,"pull",i,n],{allowFailure:!0});if(0!==o.exitCode)t=dE(o,"adb pull");else{await r.waitForStableFile(n,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(n);if(O({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1,fileSize:(()=>{try{return T.statSync(n).size}catch{return 0}})(),playable:t}}),t)return;O({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function dC(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function dP(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return O({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await dM(e,t,r))&&await dk(e,t,r)}async function dR(e){var t;let r,{deps:a,device:i,recordingBase:n}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",i.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${dE(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){o="failed to start recording: adb did not return a valid Android screenrecord pid",await dC(a,i.id,e);continue}if(O({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await dO(a,i.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...n,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await dP(a,i.id,r),await dC(a,i.id,e)}return{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}async function dT(e){let t,r,{deps:a,device:i,recording:n}=e;O({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(O({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await dM(a,i.id,n.remotePid)&&!await dP(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${dE(o,"adb shell kill")}`):await dk(a,i.id,n.remotePid)||await dP(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await dL(a,i.id,n.remotePath);let e=await dx({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),{ok:!1,error:{code:"COMMAND_FAILED",message:e}};if(dI({recording:n,writeTelemetry:a.writeRecordingTelemetry}),n.showTouches&&n.telemetryPath){let e=db();if(e)n.overlayWarning=e;else try{await a.overlayRecordingTouches({videoPath:n.outPath,telemetryPath:n.telemetryPath,targetLabel:"Android recording"})}catch(e){n.overlayWarning=`failed to overlay recording touches: ${dD(e)}`}}}if(await s(),t)return{ok:!1,error:{code:"COMMAND_FAILED",message:t}};if(r)return{ok:!1,error:{code:"COMMAND_FAILED",message:r}};return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});O({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:i.id,remotePath:n.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${dE(e,"adb shell rm")}`)}}function d$(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function dF(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function dU(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=d$(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},dF(t,i,r))}catch(e){O({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:dD(e)}})}}async function dV(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=dF(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var w,g;if(!dD(a).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${dD(a)}`}};O({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:dD(a)}});let e=(w=o.id,g=i.name,n.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${e.name}'`}};try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${dD(e)}`}}}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function dG(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},dF(t,i,r))}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${dD(e)}`}}}return{platform:"macos-runner",...s}}async function dj(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=d$(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},dF(t,i,r))}catch(e){O({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:dD(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of e7)if(0===(l=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);d>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:d});let u=dI({recording:o,trimStartMs:d,writeTelemetry:n.writeRecordingTelemetry});if(o.showTouches){let e=db();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:u,targetLabel:"iOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${dD(e)}`}}return null}async function dB(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=d$(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},dF(t,i,r))}catch(e){O({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:dD(e)}})}let l=dI({recording:o,writeTelemetry:n.writeRecordingTelemetry});if(o.showTouches){let e=db();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:l,targetLabel:"macOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${dD(e)}`}}return null}async function dq(e){for(let t=0;t<2;t+=1){try{if(T.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function dH(e){let t,{req:r,sessionName:a,sessionStore:i,activeSession:n,device:s,logPath:l,deps:d}=e;if(n.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let u=r.flags?.fps;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};if(!o$("record",s))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let c=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,p=tV.expandHome(c,r.meta?.cwd),f={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(T.mkdirSync(o.dirname(p),{recursive:!0}),T.rmSync(p,{force:!0}),"ios"===s.platform&&"device"===s.kind){let e=d$(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};t=await dV({req:r,activeSession:n,sessionStore:i,device:s,logPath:l,deps:d,fpsFlag:u,recordingBase:f,appBundleId:e})}else if("macos"===s.platform){let e=d$(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on macOS requires an active app session; run open <app> first"}};t=await dG({req:r,activeSession:n,device:s,logPath:l,deps:d,fpsFlag:u,recordingBase:f,appBundleId:e})}else if("ios"===s.platform){let e,a;await dU({req:r,activeSession:n,device:s,logPath:l,deps:d});let{child:i,wait:o}=d.runCmdBackground("xcrun",eC(s,["io",s.id,"recordVideo",p]),{allowFailure:!0}),u=await dq(p);try{let t=Date.now(),i=await d.runIosRunnerCommand(s,{command:"uptime",appBundleId:d$(n)},{verbose:r.flags?.verbose,logPath:l,traceLogPath:n.trace?.outPath}),o=Date.now();e=Math.round((t+o)/2),a="number"==typeof i.currentUptimeMs?i.currentUptimeMs:void 0}catch{}t={platform:"ios",child:i,wait:o,...f,startedAt:u,gestureClockOriginAtMs:void 0===a?void 0:e,gestureClockOriginUptimeMs:a}}else t=await dR({deps:d,device:s,recordingBase:f});return"ok"in t?t:(n.recording=t,i.set(a,n),i.recordAction(n,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??c,showTouches:t.showTouches}})}async function dW(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await dT({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to stop recording: ${dE(i,"simctl recordVideo")}`}};let n=dI({recording:a,writeTelemetry:t.writeRecordingTelemetry});if(a.showTouches){let e=db();if(e)a.overlayWarning=e;else try{await t.overlayRecordingTouches({videoPath:a.outPath,telemetryPath:n,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to overlay recording touches: ${dD(e)}`}}return null}async function dz(e){var t;let r,{req:a,activeSession:i,device:n,logPath:s,deps:l}=e;if(!i.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let d=i.recording,u=d.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===d.platform?await dj({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:d}):"macos-runner"===d.platform?await dB({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:d}):await dW({deps:l,device:n,recording:d});return c||(u?{ok:!1,error:{code:"COMMAND_FAILED",message:u}}:(r=[{field:"outPath",path:(t=d).outPath,localPath:t.clientOutPath,fileName:o.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return dg(e.clientOutPath)}(t),fileName:o.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function dJ(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:f,runCmdBackground:c,runIosRunnerCommand:tS,waitForStableFile:df,isPlayableVideo:dm,writeRecordingTelemetry:dA,trimRecordingStart:d_,overlayRecordingTouches:dN,...e.deps},o=a.get(r),s=o?.device??await oC(t.flags??{});o||await oV(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};if("start"===d)return dH({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await dz({req:t,activeSession:l,device:s,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function dK(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n=t.command;if("record"===n)return dJ({req:t,sessionName:r,sessionStore:a,logPath:i,deps:e.deps});if("trace"===n){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"trace requires start|stop"}};let i=a.get(r);if(!i)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};if("start"===e){if(i.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"trace already in progress"}};let e=t.positionals?.[1]??a.defaultTracePath(i),r=tV.expandHome(e);return T.mkdirSync(o.dirname(r),{recursive:!0}),T.appendFileSync(r,""),i.trace={outPath:r,startedAt:Date.now()},a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!i.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active trace"}};let s=i.trace.outPath;if(t.positionals?.[1]){let e=tV.expandHome(t.positionals[1]);T.mkdirSync(o.dirname(e),{recursive:!0}),T.existsSync(s)?T.renameSync(s,e):T.appendFileSync(e,""),s=e}return i.trace=void 0,a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:s}}),{ok:!0,data:{trace:"stopped",outPath:s}}}return null}function dX(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function dY(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 dZ(e,t,r){return Math.min(r,Math.max(t,Math.round(e)))}function dQ(e){return"number"==typeof e.gestureClockOriginAtMs&&"number"==typeof e.gestureClockOriginUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureClockOriginAtMs+(e.gestureStartUptimeMs-e.gestureClockOriginUptimeMs)-e.recordingStartedAt):"number"==typeof e.runnerStartedAtUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureStartUptimeMs-e.runnerStartedAtUptimeMs):"number"==typeof e.gestureStartUptimeMs&&"number"==typeof e.gestureEndUptimeMs?Math.max(0,e.fallbackFinishedAtMs-(e.gestureEndUptimeMs-e.gestureStartUptimeMs)-e.recordingStartedAt):Math.max(0,e.fallbackStartedAtMs-e.recordingStartedAt)}let d0=new WeakMap;function d1(e){if(!e)return;let t=d0.get(e);if(t)return t;let r=function(e){let t=function(e){let t=e.filter(e=>(function(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("application")||t.includes("window")})(e.type)&&d2(e.rect)).map(e=>e.rect).sort((e,t)=>(t?.width??0)*(t?.height??0)-(e?.width??0)*(e?.height??0))[0];if(t)return t;let r=e.map(e=>e.rect).filter(d2);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),i=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(i<=0))return{x:0,y:0,width:a,height:i}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return d0.set(e,r),r}function d2(e){return!!e&&e.width>0&&e.height>0}let d3={referenceWidth:1e3,referenceHeight:1e3};function d4(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,p=e.recording;if(!p)return;let f={...i,...a??{}},m=d9(f.effectiveDurationMs)??d9(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:d9(f.gestureStartUptimeMs),gestureEndUptimeMs:d9(f.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:d9(f.gestureStartUptimeMs),gestureEndUptimeMs:d9(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===d9(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=d7(d9(t.count),1)??1,r=!0===t.doubleTap,a=d7(d9(t.holdMs),1);return 1===e&&!r&&void 0===a}default:return!1}}(t,f)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return dQ(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):dQ(h),v=(l=e.snapshot,u=d9((d=f).referenceWidth),c=d9(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:d1(l)),A=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=ut(t,e);if(!i)return[];let{x:n,y:o}=i,s=d7(d9(t.count),1)??1,l=d7(d9(t.intervalMs),0)??0,d=!0===t.doubleTap,u=d7(d9(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(d5(t,n,o,u,a));continue}c.push(d8(t,n,o,a)),d&&c.push(d8(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=ut(t,e);if(!i)return[];let{x:n,y:o}=i;return[d8(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=ut(t,e);if(!n)return[];let{x:o,y:s}=n;return[d5(r,o,s,ua(a,[d9(t.durationMs),d9(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=ur(t,e),o=d6(t.contentDirection)??d6(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=ua(a,[],250),p=d9(t.amount)??d9(e[1]);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=ur(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=ua(a,[d9(t.effectiveDurationMs),d9(t.durationMs),d9(e[4])],250),c=d7(d9(t.count),1)??1,p=d7(d9(t.pauseMs),0)??0,f="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===f&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,w=r+e*(u+p);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=ut(t,e,1),o=d9(t.scale)??d9(e[0]);if(!n||void 0===o||o<=0)return[];let{x:s,y:l}=n;return[{kind:"pinch",tMs:r,x:s,y:l,...i,scale:o,durationMs:ua(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,f,g,w,v);0!==A.length&&(p.gestureEvents.push(...A),O({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:A.length,tMs:g,gestureDurationMs:w,kinds:A.map(e=>e.kind)}}))}function d8(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function d5(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function d6(e){if("string"!=typeof e)return;let t=e.trim().toLowerCase();switch(t){case"up":case"down":case"left":case"right":return t;default:return}}function d9(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e||0===e.trim().length)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function d7(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function ue(e,t,r){return Math.max(t,Math.min(r,e))}function ut(e,t,r=0){let a=d9(e.x)??d9(t[r]),i=d9(e.y)??d9(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function ur(e,t){let r=d9(e.x1)??d9(t[0]),a=d9(e.y1)??d9(t[1]),i=d9(e.x2)??d9(t[2]),n=d9(e.y2)??d9(t[3]);if(void 0!==r&&void 0!==a&&void 0!==i&&void 0!==n)return{x1:r,y1:a,x2:i,y2:n}}function ua(e,t,r){return d7(e,1)??t.map(e=>d7(e,1)).find(e=>void 0!==e)??r}async function ui(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=e.dispatch??oP,d=e.readAndroidScreenSize??ip,u=t.command;if("press"===u||"click"===u){let e="click"===u?"click":"press",c=a.get(r);if(!c)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!o$("press",c.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let p=oi(t.flags),f="primary"===p?{}:{button:p};if("primary"!==p){let r=on({commandLabel:e,platform:c.device.platform,button:p,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(r)return{ok:!1,error:{code:r.code,message:r.message,details:r.details}}}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m){let e=await ul({session:c,flags:t.flags,contextFromFlags:i,dispatch:l,command:"press",positionals:[String(m.x),String(m.y)],outPath:t.flags?.out}),r=await un({session:c,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,dispatch:l,readAndroidScreenSize:d}),o={...e.data??{x:m.x,y:m.y},...r??{},...f};return ud({session:c,sessionStore:a,command:u,positionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,result:o,responseData:o,actionStartedAt:e.actionStartedAt,actionFinishedAt:e.actionFinishedAt})}let h="click",w=t.positionals?.[0]??"";if(w.startsWith("@")){let r=s("press",t.flags);if(r)return r;let d=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",p=o({session:c,refInput:w,fallbackLabel:d,requireRect:!0,invalidRefMessage:`${e} requires a ref like @e2`,notFoundMessage:`Ref ${w} not found or has no bounds`});if(!p.ok)return p.response;let{ref:m}=p.target,g=p.target.node,v=p.target.snapshotNodes,A=uu(g.rect);if(!A){let e=await n(c,t.flags,a,i,{interactiveOnly:!0},l),r=oW(e.nodes,m),o=d.length>0?oJ(e.nodes,d):null,s=uu(o?.rect),u=uu(r?.rect)?r:s?o:r??o,p=uu(u?.rect);u&&p&&(g=u,v=e.nodes,A=p)}if(!A)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${w} not found or has invalid bounds`}};let I=oK(g,v),y=su(g,c.device.platform,{action:h}),{x:b,y:S}=A,_=await ul({session:c,flags:t.flags,contextFromFlags:i,dispatch:l,command:"press",positionals:[String(b),String(S)],outPath:t.flags?.out}),N=us({data:_.data,fallbackX:b,fallbackY:S,referenceFrame:uo(v),extra:{ref:m,refLabel:I,selectorChain:y,...f}});return ud({session:c,sessionStore:a,command:u,positionals:t.positionals??[],flags:t.flags,result:N,responseData:N,actionStartedAt:_.actionStartedAt,actionFinishedAt:_.actionFinishedAt})}let g=(t.positionals??[]).join(" ").trim();if(!g)return{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires @ref, selector expression, or x y coordinates`}};let v=o4(g),A=await n(c,t.flags,a,i,{interactiveOnly:!0},l),I=await k("selector_resolve",()=>so(A.nodes,v,{platform:c.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:u});if(!I||!I.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:sl(v,I?.diagnostics??[],{unique:!0})}};let y=uu(I.node.rect);if(!y)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${I.selector.raw} resolved to invalid bounds`}};let{x:b,y:S}=y,_=await ul({session:c,flags:t.flags,contextFromFlags:i,dispatch:l,command:"press",positionals:[String(b),String(S)],outPath:t.flags?.out}),N=su(I.node,c.device.platform,{action:h}),D=oK(I.node,A.nodes),E=us({data:_.data,fallbackX:b,fallbackY:S,referenceFrame:uo(A.nodes),extra:{selector:I.selector.raw,selectorChain:N,refLabel:D,...f}});return ud({session:c,sessionStore:a,command:u,positionals:t.positionals??[],flags:t.flags,result:E,responseData:E,actionStartedAt:_.actionStartedAt,actionFinishedAt:_.actionFinishedAt})}if("fill"===u){let e=a.get(r);if(e&&!o$("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=s("fill",t.flags);if(r)return r;let n=t.positionals.length>=3?t.positionals[1]:"",d=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let c=o({session:e,refInput:t.positionals[0],fallbackLabel:n,requireRect:!0,invalidRefMessage:"fill requires a ref like @e2",notFoundMessage:`Ref ${t.positionals[0]} not found or has no bounds`});if(!c.ok)return c.response;let{ref:p,node:f,snapshotNodes:m}=c.target;if(!f.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${t.positionals[0]} not found or has no bounds`}};let h=f.type??"",w=h&&!oQ(h,e.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,g=oK(f,m),v=su(f,e.device.platform,{action:"fill"}),{x:A,y:I}=oz(f.rect),y=await ul({session:e,flags:t.flags,contextFromFlags:i,dispatch:l,command:"fill",positionals:[String(A),String(I),d],outPath:t.flags?.out}),b={...y.data??{ref:p,x:A,y:I}};return w&&(b.warning=w),ud({session:e,sessionStore:a,command:u,positionals:t.positionals??[],flags:t.flags,result:{...b,refLabel:g,selectorChain:v},responseData:b,actionStartedAt:y.actionStartedAt,actionFinishedAt:y.actionFinishedAt})}if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let d=o5(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=d.rest.join(" ").trim();if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let o=o4(d.selectorExpression),s=await n(e,t.flags,a,i,{interactiveOnly:!0},l),c=await k("selector_resolve",()=>so(s.nodes,o,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:u});if(!c||!c.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:sl(o,c?.diagnostics??[],{unique:!0})}};let p=c.node,f=p.type??"",m=f&&!oQ(f,e.device.platform)?`fill target ${c.selector.raw} resolved to "${f}", attempting fill anyway.`:void 0,{x:h,y:w}=oz(c.node.rect),g=await ul({session:e,flags:t.flags,contextFromFlags:i,dispatch:l,command:"fill",positionals:[String(h),String(w),r],outPath:t.flags?.out}),v=su(p,e.device.platform,{action:"fill"}),A=us({data:g.data,fallbackX:h,fallbackY:w,referenceFrame:uo(s.nodes),extra:{text:r,selector:c.selector.raw,selectorChain:v,refLabel:oK(p,s.nodes)}});return m&&(A.warning=m),ud({session:e,sessionStore:a,command:u,positionals:t.positionals??[],flags:t.flags,result:A,responseData:A,actionStartedAt:g.actionStartedAt,actionFinishedAt:g.actionFinishedAt})}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}return null}async function un(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,dispatch:o,readAndroidScreenSize:s}=e;if(t.recording?.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await s(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let l=d1(t.snapshot);if(l)return t.recording&&(t.recording.touchReferenceFrame=l),l;if(!t.recording)return;let d=d1(await n(t,r,a,i,{interactiveOnly:!0},o));return d&&t.recording&&(t.recording.touchReferenceFrame=d),d}function uo(e){return d1({nodes:e,createdAt:0})}function us(e){let{data:t,fallbackX:r,fallbackY:a,referenceFrame:i,extra:n}=e;return{x:r,y:a,...i??{},...n??{},...t??{}}}async function ul(e){let{session:t,flags:r,contextFromFlags:a,dispatch:i,command:n,positionals:o,outPath:s}=e,l=Date.now(),d={...a(r,t.appBundleId,t.trace?.outPath)},u=await i(t.device,n,o,s,d);return{data:u&&"object"==typeof u?u:void 0,actionStartedAt:l,actionFinishedAt:Date.now()}}function ud(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),d4(t,a,i,o,n??{},l,d),{ok:!0,data:s}}function uu(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=oz(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}async function uc(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=e.dispatch??oP,o=e.readAndroidScreenSize??ip,s=t.command,l=await ui({req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n,readAndroidScreenSize:o,captureSnapshotForSession:up,resolveRefTarget:uh,refSnapshotFlagGuardResponse:um});if(l)return l;if("get"===s){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 o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!o$("get",o.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=um("get",t.flags);if(r)return r;let i=uh({session:o,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=su(d,o.device.platform,{action:"get"});if("attrs"===e)return a.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:n,selectorChain:u}}),{ok:!0,data:{ref:n,node:d}};let c=o0(d);return a.recordAction(o,{command:s,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=o4(d),c=await up(o,t.flags,a,i,{interactiveOnly:!1},n),p=await k("selector_resolve",()=>so(c.nodes,u,{platform:o.device.platform,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===e}),{command:s});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:sl(u,[],{unique:!0})}};let f=p.node,m=su(f,o.device.platform,{action:"get"});if("attrs"===e)return a.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,node:f}};let h=o0(f);return a.recordAction(o,{command:s,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"===s){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 o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!o$("is",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:l}=o6(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=o4(l.selectorExpression),c=await up(o,t.flags,a,i,{interactiveOnly:!1},n);if("exists"===e){let r=ss(c.nodes,u,{platform:o.device.platform});return r?(a.recordAction(o,{command:s,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:sl(u,[],{unique:!1})}}}let p=await k("selector_resolve",()=>so(c.nodes,u,{platform:o.device.platform,requireUnique:!0}),{command:"is",predicate:e});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:sl(u,[],{unique:!0})}};let f=function(e){let{predicate:t,node:r,expectedText:a,platform:i}=e,n=o0(r),o=!1;switch(t){case"visible":o=sr(r);break;case"hidden":o=!sr(r);break;case"editable":o=sa(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:sr(r),editable:sa(r,i),selected:!0===r.selected})}`;return{pass:o,actualText:n,details:s}}({predicate:e,node:p.node,expectedText:d,platform:o.device.platform});return f.pass?(a.recordAction(o,{command:s,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"===s){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!o$("scrollintoview",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let o=t.positionals?.[0]??"";if(!o.startsWith("@"))return null;let l=um("scrollintoview",t.flags);if(l)return l;let d=uh({session:e,refInput:o,fallbackLabel:t.positionals&&t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${o} 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 ${o} not found or has no bounds`}};let f=function(e,t){let r=oz(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=dY(i.map(e=>e.rect).filter(e=>dX(e,r.x,r.y)));if(n)return n;let o=dY(i.map(e=>e.rect));if(o)return o;let s=dY(a.map(e=>e.rect).filter(e=>dX(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 ${o}`}};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),v=Math.max(1,Math.abs(w-g));return f>c?{x:h,startY:w,endY:g,count:dZ(Math.ceil((f-c)/v),1,50),direction:"down"}:{x:h,startY:g,endY:w,count:dZ(Math.ceil((u-f)/v),1,50),direction:"up"}}(c.rect,f),h=oK(c,p),w=su(c,e.device.platform,{action:"get"});if(!m)return a.recordAction(e,{command:s,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:s,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 up(e,t,r,a,i,n=oP){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:oq(t?.snapshotRaw?s:oY(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend},r.set(e.name,e),e.snapshot}let uf=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function um(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of uf)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 uh(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=oH(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=oW(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=oJ(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 uw(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 ug(e){let{req:t,leaseRegistry:r}=e,a=uw(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 uv(e,t){if(!t)return[];let r=[],a=e.device,i=t.platform;if(i&&!eZ(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=eL(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function uA(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 uI=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],uy=/\bis(?:n't| not)\s+responding\b/i,ub=/^close app$/i;async function uS(e){let{session:t,snapshotAndroidUi:r=a8,reopenAndroidApp:a=aR,readAndroidAppState:i=aC,execCommand:n=f}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await u_(t,r),o=function(e){if(uM(e))return e.find(e=>{let t=uE(e);return t.length>0&&ub.test(t)&&e.rect})}(e);if(!o?.rect)return"absent";let{x:s,y:l}=oz(o.rect),d=await n("adb",rk(t.device,["shell","input","tap",String(Math.round(s)),String(Math.round(l))]),{allowFailure:!0});if(0!==d.exitCode)return O({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:d.exitCode,stdout:d.stdout.trim(),stderr:d.stderr.trim()}}),"failed";if(!await uN(t,r))return O({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await a(t.device,t.appBundleId),!await uD(t,t.appBundleId,i)))return O({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return O({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:s,y:l}}),"recovered"}catch(e){return O({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function u_(e,t){return oq(oY((await t(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function uN(e,t){for(let r=0;r<12;r+=1){if(!uM(await u_(e,t)))return!0;await uk(500)}return!uM(await u_(e,t))}async function uD(e,t,r){for(let a=0;a<12;a+=1){if((await r(e.device)).package===t)return!0;await uk(500)}return(await r(e.device)).package===t}function uE(e){let t=[e.label,e.identifier];return"string"==typeof e.value&&e.value.trim().length>0&&t.push(e.value),t.filter(e=>"string"==typeof e&&e.trim().length>0).join(" ").trim()}function uM(e){return e.some(e=>{let t=uE(e);return t.length>0&&uy.test(t)})}function uk(e){return new Promise(t=>setTimeout(t,e))}let uL=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),uO=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function ux(e,t,r,a){let i=E().requestId;return{...oF(e,t,r,a,i),requestId:i}}function uC(e){T.existsSync(e)&&T.unlinkSync(e)}function uP(e){if(!T.existsSync(e))return null;try{let t=JSON.parse(T.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function uR(e){let t=uP(e);if(!t||t.pid===process.pid)try{T.existsSync(e)&&T.unlinkSync(e)}catch{}}function uT(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:u$,infoPath:uF,lockPath:uU,logPath:uV,sessionsDir:uG}=G(process.env.AGENT_DEVICE_STATE_DIR),uj=V(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var uB=uG;if(T.existsSync(uB))for(let e of T.readdirSync(uB,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=o.join(uB,e.name,"app-log.pid");if(T.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}}(T.readFileSync(t,"utf8"));if(e&&function(e){let t,r=P(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=s(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{tj(t)}}let uq=new tV(uG),uH=new rS({maxActiveSimulatorLeases:uT(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:uT(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:uT(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:uT(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),uW=D(),uz=p.randomBytes(24).toString("hex"),uJ=P(process.pid)??void 0,uK=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=T.statSync(e),r=L(),a=o.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),uX=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:n}=e,s=e.dispatchCommand??oP,d=e.snapshotAndroidUi??a8,u=e.reopenAndroidApp??aR,c=e.readAndroidAppState??aC,p=e.execCommand??f;async function m(e){let f=!!(e.meta?.debug||e.flags?.verbose);return await R({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:f,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:S(new v("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=_(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=l(r);if(r&&!a)throw new v("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new v("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);O({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let f=r.command,h=uw(r);uO.has(f)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:h.tenantId,runId:h.runId,leaseId:h.leaseId,backend:h.leaseBackend});let w=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),g=a.get(w);g&&(!function(e){var t,r;let a,i=e.recording;if(!i||"ios"!==e.device.platform)return;let n=(t=e.device.id,(a=tu.get(t))?{sessionId:a.sessionId,alive:!!(r=a.child.pid)&&C(r)}:null);if(!i.runnerSessionId){n?.alive&&(i.runnerSessionId=n.sessionId);return}if(!n?.alive){i.invalidatedReason??="iOS runner session exited during recording";return}n.sessionId!==i.runnerSessionId&&(i.invalidatedReason??="iOS runner session restarted during recording")}(g),a.set(w,g));let A=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?uv(t,a):function(e,t){var r,a;let i=[];for(let n of(void 0!==e.platform&&t&&(r=e.platform,a=t,r&&a&&r!==a&&("apple"===r?!eY(a):"apple"!==a||!eY(r)))&&i.push({key:"platform",value:e.platform}),uI)){let t=e[n];"string"==typeof t&&t.trim().length>0&&i.push({key:n,value:t})}return i}(a,e.meta?.lockPlatform);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of uI)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new v("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(uA).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,g),I=e=>(function(e,t,r){let a=E();if(!t.ok){O({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=$({force:!0})??void 0;return{ok:!1,error:S(new v(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 O({level:"info",phase:"request_success"}),$(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let s=(a=e,i=t,n=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||n.some(e=>e?.field==="path")||"string"!=typeof i.path||n.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:o.basename(a.meta?.clientArtifactPaths?.path??i.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===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)}})(A,e,n);if(g?.recording?.invalidatedReason&&"record"!==f&&"close"!==f)return I({ok:!1,error:{code:"COMMAND_FAILED",message:g.recording.invalidatedReason}});!g||A.meta?.lockPolicy||uL.has(f)||function(e,t){let r=uv(e,t);if(0!==r.length){var a;let t,i,n;throw new v("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(uA).join(", ")}. Use a different --session name or close this session first.`)}}(g,A.flags);let y=await ug({req:A,leaseRegistry:i});if(y)return I(y);let b=await lK({req:A,sessionName:w,logPath:t,sessionStore:a,invoke:m});if(b)return I(b);let N=await ds({req:A,sessionName:w,logPath:t,sessionStore:a});if(N)return I(N);let D=await dK({req:A,sessionName:w,sessionStore:a,logPath:t});if(D)return I(D);let M=await dc({req:A,sessionName:w,logPath:t,sessionStore:a,invoke:m});if(M)return I(M);let k=await uc({req:A,sessionName:w,sessionStore:a,contextFromFlags:(e,r,a)=>ux(t,e,r,a)});if(k)return I(k);let L=a.get(w);if(!L)return I({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!o$(f,L.device))return I({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${f} is not supported on this device`}});if("android"===L.device.platform&&L.recording&&"record"!==f){let e=await uS({session:L,snapshotAndroidUi:d,reopenAndroidApp:u,readAndroidAppState:c,execCommand:p});if("failed"===e)return I({ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}})}let x=A.positionals??[],P=A.flags?.out,R="screenshot"===f&&x[0]?[tV.expandHome(x[0],A.meta?.cwd),...x.slice(1)]:x,T="screenshot"===f&&P?tV.expandHome(P,A.meta?.cwd):P,F="screenshot"===f?R:x,U="screenshot"===f&&T?{...A.flags??{},out:T}:A.flags??{},V=Date.now(),G={...ux(t,A.flags,L.appBundleId,L.trace?.outPath)},j=await s(L.device,f,R,T,{...G}),B=Date.now(),q=function(e,t,r,a){var i;if("scroll"!==t)return a;let n=d1(e.snapshot),o={...a??{}},s=d6(o.direction)??d6(r[0]);if(!s)return a;let l=d9(o.amount)??d9(r[1]),d=(i=l,void 0===i||!Number.isFinite(i)||i<=0?.4:i<=1?ue(i,.2,.7):ue(i/100,.2,.7)),u=d9(o.referenceWidth),c=d9(o.referenceHeight),p=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:n??d3,{start:f,end:m}=function(e,t,r){let a=Math.round(t.referenceWidth/2),i=Math.round(t.referenceHeight/2),n=Math.round(t.referenceWidth*r/2),o=Math.round(t.referenceHeight*r/2);switch(e){case"up":return{start:{x:a,y:i-o},end:{x:a,y:i+o}};case"down":return{start:{x:a,y:i+o},end:{x:a,y:i-o}};case"left":return{start:{x:a-n,y:i},end:{x:a+n,y:i}};case"right":return{start:{x:a+n,y:i},end:{x:a-n,y:i}}}}(s,p,d);return{...o,x1:f.x,y1:f.y,x2:m.x,y2:m.y,contentDirection:s,amount:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250}}(L,f,R,j);return d4(L,f,R,q,A.flags??{},V,B),a.recordAction(L,{command:f,positionals:F,flags:U,result:j??{}}),I({ok:!0,data:j??{}})}catch(r){O({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=E(),t=$({force:!0})??void 0;return{ok:!1,error:S(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return m}({logPath:uV,token:uz,sessionStore:uq,leaseRegistry:uH,trackDownloadableArtifact:function(e){let t=p.randomUUID(),r=setTimeout(()=>{t4(t)},9e5);return r.unref(),t3.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){T.existsSync(e)||T.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),i=()=>{try{return T.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(i())return!0;let n=uP(t);if(n?.pid&&n.pid!==process.pid&&d(n.pid,n.processStartTime))return!1;try{T.unlinkSync(t)}catch{}return i()}(u$,uU,{pid:process.pid,version:uW,startedAt:Date.now(),processStartTime:uJ})){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"===uj||"dual"===uj){let t=U.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))ep(e);O({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await tg(),!(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=eu(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),ec(o),em(o))throw ew();i=await uX(e)}catch(e){i={ok:!1,error:S(e)}}finally{r-=1,o&&(a.delete(o),ef(o))}e.destroyed||e.write(`${JSON.stringify(i)}
64
+ `),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 v("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===uj||"dual"===uj){let e=await rw({handleRequest:uX,token:uz});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 v("COMMAND_FAILED","Failed to bind HTTP server"))})})}a={socketPort:e,httpPort:t,token:uz,version:uW,codeSignature:uK,processStartTime:uJ},T.existsSync(u$)||T.mkdirSync(u$,{recursive:!0}),T.writeFileSync(uV,""),i=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",T.writeFileSync(uF,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:u$},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
39
65
  `),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
40
- `)}catch(t){let e=f(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
41
- `),r))try{t.close(()=>{})}catch{}dP(dV),d$(dG),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(),dW.toArray()))dW.writeSessionLog(e);await tm(),dP(dV),d$(dG),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}
66
+ `)}catch(t){let e=h(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
67
+ `),r))try{t.close(()=>{})}catch{}uC(uF),uR(uU),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(),uq.toArray()))uq.writeSessionLog(e);await tv(),uC(uF),uR(uU),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof v?e:h(e);process.stderr.write(`Daemon error: ${t.message}
42
68
  `),o()})}();