agent-device 0.7.4 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,34 +1,36 @@
1
- let e;import{isCancel as t,select as r}from"@clack/prompts";import{node_http as i,node_path as n,readProcessCommand as a,validateAndNormalizeBatchSteps as o,isAgentDeviceDaemonProcess as s,runCmdDetached as l,runCmdBackground as d,SETTINGS_INVALID_ARGS_MESSAGE as u,normalizeTenantId as c,runCmd as p,node_crypto as f,displayLabel as m,spawn as h,asAppError as w,pathToFileURL as g,AppError as I,whichCmd as v,buildSnapshotDisplayLines as A,fileURLToPath as y,runCmdStreaming as N,formatRole as S,normalizeError as b,resolveSessionIsolationMode as _,readVersion as D,findProjectRoot as E,getDiagnosticsMeta as k,withDiagnosticTimer as O,emitDiagnostic as M,DEFAULT_BATCH_MAX_STEPS as L,promises as x,isProcessAlive as C,readProcessStartTime as T,node_fs as R,withDiagnosticsScope as P,flushDiagnosticsToSessionFile as $,node_os as F,node_net as V,resolveDaemonServerMode as U,resolveDaemonPaths as G,formatSnapshotLine as B}from"./678.js";function q(e){return"apple"===e?"ios":e}async function j(e,i){let n=e,a=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(i.platform&&(n=n.filter(e=>e.platform===i.platform)),i.target&&(n=n.filter(e=>(e.target??"mobile")===i.target)),i.udid){let e=n.find(e=>e.id===i.udid&&"ios"===e.platform);if(!e)throw new I("DEVICE_NOT_FOUND",`No iOS device with UDID ${i.udid}`);return e}if(i.serial){let e=n.find(e=>e.id===i.serial&&"android"===e.platform);if(!e)throw new I("DEVICE_NOT_FOUND",`No Android device with serial ${i.serial}`);return e}if(i.deviceName){let e=a(i.deviceName),t=n.find(t=>a(t.name)===e);if(!t)throw new I("DEVICE_NOT_FOUND",`No device named ${i.deviceName}`);return t}if(1===n.length)return n[0];if(0===n.length)throw new I("DEVICE_NOT_FOUND","No devices found",{selector:i});let o=n.filter(e=>e.booted);if(1===o.length)return o[0];if(!process.env.CI&&process.stdin.isTTY&&process.stdout.isTTY){let e=await r({message:"Multiple devices available. Choose a device to continue:",options:(o.length>0?o:n).map(e=>({label:`${e.name} (${e.platform}${e.kind?`, ${e.kind}`:""}${e.booted?", booted":""})`,value:e.id}))});if(t(e))throw new I("INVALID_ARGS","Device selection cancelled");if(e){let t=n.find(t=>t.id===e);if(t)return t}}return o[0]??n[0]}let W=H(process.env.AGENT_DEVICE_RETRY_LOGS);function H(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let J=2e4,z=12e4,K=1e4;class X{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new X(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 Y(e,t={},r={}){let i,n={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=n.maxAttempts&&(!r.deadline?.isExpired()||!(t>1));t+=1)try{let i=await e({attempt:t,maxAttempts:n.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),Q({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),i}catch(d){i=d;let e=r.classifyReason?.(d),a={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(a),Q(a),t>=n.maxAttempts||n.shouldRetry&&!n.shouldRetry(d,t))break;let o=function(e,t,r,i){let n=Math.min(t,e*2**(i-1));return Math.max(0,n+n*r*(2*Math.random()-1))}(n.baseDelayMs,n.maxDelayMs,n.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:n.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),Q(l),await function(e){return new Promise(t=>setTimeout(t,e))}(s)}let a={phase:r.phase,event:"exhausted",attempt:n.maxAttempts,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(i)};if(r.onEvent?.(a),Q(a),i)throw i;throw new I("COMMAND_FAILED","retry failed")}async function Z(e,t={}){return Y(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function Q(e){M({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),W&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
1
+ let e;import{isCancel as t,select as r}from"@clack/prompts";import{node_http as i,node_path as n,readProcessCommand as a,validateAndNormalizeBatchSteps as o,isAgentDeviceDaemonProcess as s,runCmdDetached as l,runCmdBackground as d,SETTINGS_INVALID_ARGS_MESSAGE as u,normalizeTenantId as c,runCmd as p,node_crypto as f,displayLabel as m,spawn as h,asAppError as w,pathToFileURL as g,AppError as I,whichCmd as v,buildSnapshotDisplayLines as A,fileURLToPath as y,runCmdStreaming as N,formatRole as b,normalizeError as S,resolveSessionIsolationMode as _,readVersion as D,findProjectRoot as E,getDiagnosticsMeta as k,withDiagnosticTimer as O,emitDiagnostic as L,DEFAULT_BATCH_MAX_STEPS as M,promises as x,isProcessAlive as C,readProcessStartTime as T,node_fs as R,withDiagnosticsScope as P,flushDiagnosticsToSessionFile as $,node_os as F,node_net as V,resolveDaemonServerMode as G,resolveDaemonPaths as U,formatSnapshotLine as B}from"./678.js";function q(e){return"apple"===e?"ios":e}async function j(e,i){let n=e,a=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(i.platform&&(n=n.filter(e=>e.platform===i.platform)),i.target&&(n=n.filter(e=>(e.target??"mobile")===i.target)),i.udid){let e=n.find(e=>e.id===i.udid&&"ios"===e.platform);if(!e)throw new I("DEVICE_NOT_FOUND",`No iOS device with UDID ${i.udid}`);return e}if(i.serial){let e=n.find(e=>e.id===i.serial&&"android"===e.platform);if(!e)throw new I("DEVICE_NOT_FOUND",`No Android device with serial ${i.serial}`);return e}if(i.deviceName){let e=a(i.deviceName),t=n.find(t=>a(t.name)===e);if(!t)throw new I("DEVICE_NOT_FOUND",`No device named ${i.deviceName}`);return t}if(1===n.length)return n[0];if(0===n.length)throw new I("DEVICE_NOT_FOUND","No devices found",{selector:i});let o=n.filter(e=>e.booted);if(1===o.length)return o[0];if(!process.env.CI&&process.stdin.isTTY&&process.stdout.isTTY){let e=await r({message:"Multiple devices available. Choose a device to continue:",options:(o.length>0?o:n).map(e=>({label:`${e.name} (${e.platform}${e.kind?`, ${e.kind}`:""}${e.booted?", booted":""})`,value:e.id}))});if(t(e))throw new I("INVALID_ARGS","Device selection cancelled");if(e){let t=n.find(t=>t.id===e);if(t)return t}}return o[0]??n[0]}let W=H(process.env.AGENT_DEVICE_RETRY_LOGS);function H(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let J=2e4,z=12e4,K=1e4;class X{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new X(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 Y(e,t={},r={}){let i,n={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=n.maxAttempts&&(!r.deadline?.isExpired()||!(t>1));t+=1)try{let i=await e({attempt:t,maxAttempts:n.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),Q({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),i}catch(d){i=d;let e=r.classifyReason?.(d),a={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(a),Q(a),t>=n.maxAttempts||n.shouldRetry&&!n.shouldRetry(d,t))break;let o=function(e,t,r,i){let n=Math.min(t,e*2**(i-1));return Math.max(0,n+n*r*(2*Math.random()-1))}(n.baseDelayMs,n.maxDelayMs,n.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:n.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),Q(l),await function(e){return new Promise(t=>setTimeout(t,e))}(s)}let a={phase:r.phase,event:"exhausted",attempt:n.maxAttempts,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(i)};if(r.onEvent?.(a),Q(a),i)throw i;throw new I("COMMAND_FAILED","retry failed")}async function Z(e,t={}){return Y(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function Q(e){L({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),W&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
2
2
  `)}let ee=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],et=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function er(e){return e?.trim()||void 0}function ei(e,t){for(let r of e){let e=er(t[r]);if(e)return e}}function en(e,t=process.env){return er(e)??ei(ee,t)}function ea(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function eo(e,t=process.env){let r=er(e)??ei(et,t);if(r)return ea(r)}function es(e){let t=e.error?w(e.error):null,r=e.context?.platform,i=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===r?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let n=t?.details??{},a="string"==typeof n.message?n.message:void 0,o="string"==typeof n.stdout?n.stdout:void 0,s="string"==typeof n.stderr?n.stderr:void 0,l=n.boot&&"object"==typeof n.boot?n.boot:null,d=n.bootstatus&&"object"==typeof n.bootstatus?n.bootstatus:null,u=[e.message,t?.message,e.stdout,e.stderr,a,o,s,"string"==typeof l?.stdout?l.stdout:void 0,"string"==typeof l?.stderr?l.stderr:void 0,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===r&&(u.includes("runner did not accept connection")||"connect"===i&&(u.includes("timed out")||u.includes("timeout")||u.includes("econnrefused")||u.includes("connection refused")||u.includes("fetch failed")||u.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===r&&"boot"===i&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===r&&"boot"===i&&(u.includes("timed out")||u.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":u.includes("resource temporarily unavailable")||u.includes("killed: 9")||u.includes("cannot allocate memory")||u.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===r&&(u.includes("device not found")||u.includes("no devices")||u.includes("device offline")||u.includes("offline")||u.includes("unauthorized")||u.includes("not authorized")||u.includes("unable to locate device")||u.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||u.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function el(e){switch(e){case"IOS_BOOT_TIMEOUT":return"Retry simulator boot and inspect simctl bootstatus logs; in CI consider increasing AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS.";case"IOS_RUNNER_CONNECT_TIMEOUT":return"Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.";case"ANDROID_BOOT_TIMEOUT":return"Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.";case"ADB_TRANSPORT_UNAVAILABLE":return"Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.";case"CI_RESOURCE_STARVATION_SUSPECTED":return"CI machine may be resource constrained; reduce parallel jobs or use a larger runner.";case"IOS_TOOL_MISSING":return"Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.";case"BOOT_COMMAND_FAILED":return"Inspect command stderr/stdout for the failing boot phase and retry after environment validation.";default:return"Retry once and inspect verbose logs for the failing phase."}}let ed=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function eu(e){return`${e.stdout}
3
- ${e.stderr}`}function ec(e,t){return["-s",e,...t]}function ep(e){return e.startsWith("emulator-")}function ef(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function em(e,t=K){return p("adb",ec(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function eh(e,t){let r=t.replace(/_/g," ").trim();if(!ep(e))return r||e;let i=await ew(e);return i?i.replace(/_/g," "):r||e}async function ew(e){for(let t of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let r=await p("adb",ec(e,["shell","getprop",t]),{allowFailure:!0,timeoutMs:1500}),i=r.stdout.trim();if(0===r.exitCode&&i.length>0)return i}let t=await p("adb",ec(e,["emu","avd","name"]),{allowFailure:!0,timeoutMs:1500}),r=t.stdout.trim();if(0===t.exitCode&&r.length>0)return r}async function eg(e,t){let r=eu(await p("adb",ec(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:K})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function eI(e){return(await Promise.all(ed.map(async t=>await eg(e,t)))).some(e=>!0===e)}async function ev(e){var t;let r;return"tv"===((r=eu(await p("adb",ec(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:K})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await eI(e)?"tv":(t=eu(await p("adb",ec(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:K})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function eA(e={}){if(!await v("adb"))throw new I("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??eo(void 0),r=(await ey()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,i,n]=await Promise.all([eh(e,t),e_(e),ev(e)]);return{platform:"android",id:e,name:r,kind:ep(e)?"emulator":"device",target:n,booted:i}}))}async function ey(){return(await p("adb",["devices","-l"],{timeoutMs:K})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).filter(e=>"device"===e[1]).map(e=>({serial:e[0],rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}))}async function eN(){let e=await p("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:K});if(0!==e.exitCode)throw new I("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function eS(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await eb(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 I("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 eb(e,t){let r=ef(e);for(let e of(await ey()).filter(e=>(!t||e.serial===t)&&ep(e.serial)))if(ef(e.rawModel)===r||ef(await eh(e.serial,e.rawModel))===r)return e.serial}async function e_(e){try{let t=await em(e);return"1"===t.stdout.trim()}catch{return!1}}async function eD(e){var t,r;let i,n=e.avdName.trim();if(!n)throw new I("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let a=e.timeoutMs??12e4;if(!await v("adb"))throw new I("TOOL_MISSING","adb not found in PATH");if(!await v("emulator"))throw new I("TOOL_MISSING","emulator not found in PATH");let o=await eN(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let i=ef(t);return e.find(e=>ef(e)===i)}(o,n);if(!s)throw new I("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:n,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let d=Date.now(),u=(t=await eA(),r=e.serial,i=ef(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&ef(e.name)===i));if(!u){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),l("emulator",t)}let c=u??await eS({avdName:s,serial:e.serial,timeoutMs:a}),p=Math.max(1e3,a-(Date.now()-d));await eE(c.id,p);let f=(await eA()).find(e=>e.id===c.id);return f?{...f,name:s,booted:!0}:{...c,name:s,booted:!0}}async function eE(e,t=6e4){let r,i=X.fromTimeoutMs(t),n=Math.max(1,Math.ceil(t/1e3)),a=!1;try{await Y(async({deadline:n})=>{if(n?.isExpired())throw a=!0,new I("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:i.elapsedMs(),message:"timeout"});let o=Math.max(1e3,n?.remainingMs()??t),s=await em(e,Math.min(o,K));if(r=s,"1"!==s.stdout.trim())throw new I("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:n,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=es({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:i,phase:"boot",classifyReason:e=>es({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let n=w(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=es({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===n.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:i.elapsedMs(),reason:d,hint:el(d),stdout:o,stderr:s,exitCode:l};if(a||"ANDROID_BOOT_TIMEOUT"===d)throw new I("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===n.code)throw new I("TOOL_MISSING",n.message,{...u,...n.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new I("COMMAND_FAILED",n.message,{...u,...n.details??{}});throw new I(n.code,n.message,{...u,...n.details??{}},n.cause)}}function ek(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let i=r[1]?.toLowerCase(),n=r[2]??"";return"http"!==i&&"https"!==i&&"ws"!==i&&"wss"!==i&&"ftp"!==i&&"ftps"!==i||n.startsWith("//")}function eO(e,t){let r,i=e?.trim();return i?i:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}function eM(e){let t=eL(e),r=e=>{let r=ex(t,e);if(null!==r)return"true"===r};return{text:ex(t,"text"),desc:ex(t,"content-desc"),resourceId:ex(t,"resource-id"),className:ex(t,"class"),bounds:ex(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function eL(e){let t=new Map,r=e.indexOf(" "),i=e.lastIndexOf(">");if(r<0||i<=r)return t;let n=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,a=r;for(;a<i;){for(;a<i;){let t=e[a];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;a+=1}if(a>=i)break;let r=e[a];if("/"===r||">"===r)break;n.lastIndex=a;let o=n.exec(e);if(!o)break;t.set(o[1],o[3]),a=n.lastIndex}return t}function ex(e,t){return e.get(t)??null}function eC(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),i=Number(t[2]);return{x:r,y:i,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-i)}}function eT(e){return e?e.toLowerCase():""}function eR(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}let eP=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function e$(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new I("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function eF(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 I("INVALID_ARGS",`permission setting requires a target: ${eP.join("|")}`)}function eV(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new I("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}let eU={settings:{type:"intent",value:"android.settings.SETTINGS"}},eG="android.intent.category.LAUNCHER",eB="android.intent.category.LEANBACK_LAUNCHER",eq="android.intent.category.DEFAULT";function ej(e,t){return["-s",e.id,...t]}async function eW(e,t){let r=t.trim();if(r.includes("."))return{type:"package",value:r};let i=eU[r.toLowerCase()];if(i)return i;let n=(await p("adb",ej(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===n.length)return{type:"package",value:n[0]};if(n.length>1)throw new I("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:n});throw new I("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function eH(e,t="all"){let r=await eJ(e);return("user-installed"===t?(await eK(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:function(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),i=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let n=r[e];if(!t.has(n)){i=n;break}}return i.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}(e)}))}async function eJ(e){let t=new Set;for(let r of ez(e,{includeFallbackWhenUnknown:!0})){let i=await p("adb",ej(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===i.exitCode&&0!==i.stdout.trim().length)for(let e of i.stdout.split("\n")){let r=e.trim();if(!r)continue;let i=r.split(/\s+/)[0],n=i.includes("/")?i.split("/")[0]:i;n&&t.add(n)}}return t}function ez(e,t={}){return"tv"===e.target?[eB]:"mobile"===e.target?[eG]:t.includeFallbackWhenUnknown?[eG,eB]:[eG]}async function eK(e){return(await p("adb",ej(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}async function eX(e){let t=await eQ(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await eQ(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function eY(e){let t=await p("adb",ej(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new I("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],i=r[2]?.toLowerCase();e&&("true"===i||"false"===i)&&t.set(e,"true"===i)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let i=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),n=i.length>0?i[i.length-1]?.[1]:void 0,a=n?`0x${n.toLowerCase()}`:void 0;return{visible:r,inputType:a,type:a?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let i=4080&t;return 32===i||208===i?"email":128===i||224===i||144===i?"password":"text"}(a):void 0}}(t.stdout)}async function eZ(e){let t=await eY(e),r=t,i=0;for(;r.visible&&i<2;)await e7(e),i+=1,await tT(120),r=await eY(e);return{attempts:i,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function eQ(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 p("adb",ej(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function e0(e,t,r){var i,n;let a;e.booted||await eE(e.id);let o=t.trim();if(ek(o)){if(r)throw new I("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await eW(e,t),l=ez(e)[0]??eG;if("intent"===s.type){if(r)throw new I("INVALID_ARGS","Activity override requires a package name, not an intent");await p("adb",ej(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eq,"-c",l,"-n",t]));return}let d=await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eq,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(i=d.stdout,n=d.stderr,a=`${i}
4
- ${n}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(a)))return;let u=await e1(e,s.value);if(!u)throw new I("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr});await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eq,"-c",l,"-n",u]))}async function e1(e,t){for(let r of Array.from(new Set(ez(e,{includeFallbackWhenUnknown:!0})))){let i=await p("adb",ej(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==i.exitCode)continue;let n=function(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}(i.stdout);if(n)return n}return null}async function e2(e){e.booted||await eE(e.id)}async function e3(e,t){if("settings"===t.trim().toLowerCase())return void await p("adb",ej(e,["shell","am","force-stop","com.android.settings"]));let r=await eW(e,t);if("intent"===r.type)throw new I("INVALID_ARGS","Close requires a package name, not an intent");await p("adb",ej(e,["shell","am","force-stop",r.value]))}async function e4(e,t){let r=await eW(e,t);if("intent"===r.type)throw new I("INVALID_ARGS","reinstall requires a package name, not an intent");let i=await p("adb",ej(e,["uninstall",r.value]),{allowFailure:!0});if(0!==i.exitCode){let e=`${i.stdout}
5
- ${i.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new I("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}return{package:r.value}}async function e8(e,t){await p("adb",ej(e,["install",t]))}async function e5(e,t,r){e.booted||await eE(e.id);let{package:i}=await e4(e,t);return await e8(e,r),{package:i}}async function e6(e,t,r){await p("adb",ej(e,["shell","input","tap",String(t),String(r)]))}async function e9(e,t,r,i,n,a=250){await p("adb",ej(e,["shell","input","swipe",String(t),String(r),String(i),String(n),String(a)]))}async function e7(e){await p("adb",ej(e,["shell","input","keyevent","4"]))}async function te(e){await p("adb",ej(e,["shell","input","keyevent","3"]))}async function tt(e){await p("adb",ej(e,["shell","input","keyevent","187"]))}async function tr(e,t,r,i=800){await p("adb",ej(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(i)]))}async function ti(e,t){let r=tE(t);if(!r||"ok"!==await tk(e,t))try{let r=t.replace(/ /g,"%s");await p("adb",ej(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof I)||"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 I("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 tn(e){let t,r;return(r=(t=(await tM(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 ta(e,t){await tM(e,["shell","cmd","clipboard","set","text",t],"write")}async function to(e,t,r){await e6(e,t,r)}async function ts(e,t,r,i){let n=Array.from(i).length,a=tE(i),o=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];a||(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 a of o){var l,d;await to(e,t,r);let o=(l=n+a.clearPadding,d=a.minClear,Math.max(d,Math.min(a.maxClear,l)));if(await tL(e,o),"input_text"===a.strategy)await ti(e,i);else if("clipboard_paste"===a.strategy){if("ok"!==await tk(e,i))continue}else await tD(e,i,1,15);if((s=await tx(e,t,r))===i)return}throw new I("COMMAND_FAILED","Android fill verification failed",{expected:i,actual:s??null})}async function tl(e,t,r=.6){let{width:i,height:n}=await tw(e),a=Math.floor(i*r),o=Math.floor(n*r),s=Math.floor(i/2),l=Math.floor(n/2),d=s,u=l,c=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(a/2),c=s+Math.floor(a/2);break;case"right":d=s+Math.floor(a/2),c=s-Math.floor(a/2);break;default:throw new I("INVALID_ARGS",`Unknown direction: ${t}`)}await p("adb",ej(e,["shell","input","swipe",String(d),String(u),String(c),String(f),"300"]))}async function td(e,t){for(let r=0;r<8;r+=1){let r="";try{r=await tg(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new I("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(function(e,t){let r=t.toLowerCase(),i=/<node[^>]+>/g,n=i.exec(e);for(;n;){let t=eL(n[0]),a=(ex(t,"text")??"").toLowerCase(),o=(ex(t,"content-desc")??"").toLowerCase();if(a.includes(r)||o.includes(r)){let e=eC(ex(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}}n=i.exec(e)}return null}(r,t))return;await tl(e,"down",.5)}throw new I("COMMAND_FAILED",`Could not find element containing "${t}" after scrolling`)}async function tu(e,t){let r=await p("adb",ej(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new I("COMMAND_FAILED","Failed to capture screenshot");await x.writeFile(t,r.stdoutBuffer)}async function tc(e,t,r,i,n){switch(t.toLowerCase()){case"wifi":{let t=ty(r);await p("adb",ej(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=ty(r);await p("adb",ej(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await p("adb",ej(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=ty(r);await p("adb",ej(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await tN(e,r);await p("adb",ej(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 I("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await tp(e,t);return}case"permission":{if(!i)throw new I("INVALID_ARGS","permission setting requires an active app in session");let t=e$(r),a=function(e,t){let r=eF(e);if(t?.trim())throw new I("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 I("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(n?.permissionTarget,n?.permissionMode);if("notifications"===a.kind)return void await tb(e,i,t,a);let o="grant"===t?"grant":"revoke";if("photos"===a.type)return void await tS(e,i,o);await p("adb",ej(e,["shell","pm",o,i,a.value]));return}default:throw new I("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function tp(e,t){var r;let i,n,a=(r=e,n=[["shell","cmd","fingerprint","touch",i="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",i]],"emulator"===r.kind&&n.push(["emu","finger","touch",i]),n),o=[];for(let t of a){let r=await p("adb",ej(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let i;return t=e.stdout,r=e.stderr,(i=`${t}
6
- ${r}`.toLowerCase()).includes("unknown command")||i.includes("can't find service: fingerprint")||i.includes("service fingerprint was not found")||i.includes("fingerprint cmd unavailable")||i.includes("emu command is not supported")||i.includes("emulator console is not running")||i.includes("fingerprint")&&i.includes("not found")}))throw new I("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 I("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}async function tf(e,t,r){let i="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,n=["shell","am","broadcast","-a",i,"-p",t],a="string"==typeof r.receiver?r.receiver.trim():"";a&&n.push("-n",a);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new I("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 I("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(n,e,t),s+=1);return await p("adb",ej(e,n)),{action:i,extrasCount:s}}async function tm(e,t={}){return function(e,t,r){let i=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],i=/<node\b[^>]*>|<\/node>/g,n=i.exec(e);for(;n;){let t=n[0];if(t.startsWith("</node")){r.length>1&&r.pop(),n=i.exec(e);continue}let a=eM(t),o=eC(a.bounds),s=r[r.length-1],l={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,rect:o,enabled:a.enabled,hittable:a.clickable??a.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),n=i.exec(e)}return t}(e),n=[],a=!1,o=r.depth??1/0,s=r.scope?function(e,t){let r=t.toLowerCase(),i=[...e.children];for(;i.length>0;){let e=i.shift(),t=e.label?.toLowerCase()??"",n=e.value?.toLowerCase()??"",a=e.identifier?.toLowerCase()??"";if(t.includes(r)||n.includes(r)||a.includes(r))return e;i.push(...e.children)}return null}(i,r.scope):null,l=s?[s]:i.children,d=new Map,u=e=>{let t=d.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||u(t))return d.set(e,!0),!0;return d.set(e,!1),!1},c=(e,t,i,s=!1,l=!1)=>{var d,p,f,m,h,w;let g,I,v,A,y,N,S,b;if(n.length>=800){a=!0;return}if(t>o)return;let _=!!r.raw||(d=e,p=r,f=s,m=u(e),h=l,I=eT(d.type),v=!!(d.label&&d.label.trim().length>0),A=!!(d.identifier&&d.identifier.trim().length>0),y=v&&!eR(d.label??""),N=A&&!eR(d.identifier??""),S=(g=(w=I).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,b="imageview"===I||"imagebutton"===I,p.interactiveOnly?!!d.hittable||!!(y||N)&&!b&&(!S||!!h)&&(f||m||h):p.compact?y||N||!!d.hittable:!S&&!b||!!d.hittable||!!y||!!N&&!!m||m),D=i;_&&(D=n.length,n.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:t,parentIndex:i}));let E=s||!!e.hittable,k=l||function(e){if(!e)return!1;let t=eT(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),a)return};for(let e of l)if(c(e,0,void 0,!1,!1),a)break;return a?{nodes:n,truncated:a}:{nodes:n}}(await tg(e),0,t)}async function th(){if(!await v("adb"))throw new I("TOOL_MISSING","adb not found in PATH")}async function tw(e){let t=(await p("adb",ej(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new I("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function tg(e){return Z(()=>tI(e),{shouldRetry:tA})}async function tI(e){var t,r,i;let n,a,o=await p("adb",ej(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=tv(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await p("adb",ej(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,i=l.stderr,n=`${r}
7
- ${i}`,a=/dumped to:\s*(\S+)/i.exec(n),a?.[1]??t),u=await p("adb",ej(e,["shell","cat",d])),c=tv(u.stdout,u.stderr);if(!c)throw new I("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return c}function tv(e,t){let r=`${e}
8
- ${t}`,i=r.indexOf("<?xml"),n=i>=0?i:r.indexOf("<hierarchy");if(n<0)return null;let a=r.lastIndexOf("</hierarchy>");if(a<0||a<n)return null;let o=r.slice(n,a+12).trim();return o.length>0?o:null}function tA(e){if(!(e instanceof I)||"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"))}function ty(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 I("INVALID_ARGS",`Invalid setting state: ${e}`)}async function tN(e,t){let r=eV(t);if("toggle"!==r)return r;let i=await p("adb",ej(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==i.exitCode)throw new I("COMMAND_FAILED","Failed to read current Android appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});let n=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
9
- ${t}`);if(!r)return null;let i=r[1].toLowerCase();return"yes"===i?"dark":"no"===i?"light":"auto"===i?"auto":null}(i.stdout,i.stderr);if(!n)throw new I("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:i.stdout,stderr:i.stderr});return"auto"===n?"dark":"dark"===n?"light":"dark"}async function tS(e,t,r){let i=await t_(e),n=[];for(let a of null!==i&&i>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let i=await p("adb",ej(e,["shell","pm",r,t,a]),{allowFailure:!0});if(0===i.exitCode)return;n.push({permission:a,stderr:i.stderr,exitCode:i.exitCode})}throw new I("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:i,attempts:n})}async function tb(e,t,r,i){"grant"===r?await p("adb",ej(e,["shell","pm","grant",t,i.permission]),{allowFailure:!0}):(await p("adb",ej(e,["shell","pm","revoke",t,i.permission]),{allowFailure:!0}),"reset"===r&&(await p("adb",ej(e,["shell","pm","clear-permission-flags",t,i.permission,"user-set"]),{allowFailure:!0}),await p("adb",ej(e,["shell","pm","clear-permission-flags",t,i.permission,"user-fixed"]),{allowFailure:!0}))),await p("adb",ej(e,["shell","appops","set",t,i.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function t_(e){let t=await p("adb",ej(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 tD(e,t,r,i){let n=Math.max(1,Math.floor(r)),a=Array.from(t);for(let t=0;t<a.length;t+=n){let r=a.slice(t,t+n).join("");await ti(e,r),i>0&&t+n<a.length&&await tT(i)}}function tE(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 tk(e,t){let r=await p("adb",ej(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":tO(r.stdout,r.stderr)?"unsupported":0===(await p("adb",ej(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await p("adb",ej(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}function tO(e,t){let r=`${e}
10
- ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function tM(e,t,r){let i=await p("adb",ej(e,t),{allowFailure:!0});if(tO(i.stdout,i.stderr))throw new I("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==i.exitCode)throw new I("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return i.stdout}async function tL(e,t){let r=Math.max(0,t);await p("adb",ej(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let i=Math.min(24,r-t);await p("adb",ej(e,["shell","input","keyevent",...Array(i).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function tx(e,t,r){let i,n=await tg(e),a=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(i=a.exec(n));){let e=eM(i[0]),n=eC(e.bounds);if(!n)continue;let a=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,n.width*n.height),p=t>=n.x&&t<=n.x+n.width&&r>=n.y&&r<=n.y+n.height;if(u&&tC(a)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&tC(a)){(!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 tC(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function tT(e){await new Promise(t=>setTimeout(t,e))}function tR(e,t,r){if(!e)return t;let i=Number(e);return Number.isFinite(i)?Math.max(r,Math.floor(i)):t}function tP(e,t={}){let r=en(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function t$(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:tP(t,{simulatorSetPath:e.simulatorSetPath})}let tF=tR(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),tV=/^(iphone|ipad|ipod|appletv)/i,tU=/^appletv/i,tG=["apple tv","appletv","tvos"];function tB(e){return(e??"").trim().toLowerCase()}function tq(e){return tB(e.hardwareProperties?.platform)}function tj(e){return e.includes("tvos")}function tW(e){let t=tB(e);return tG.some(e=>t.includes(e))}function tH(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function tJ(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function tz(e={}){if("darwin"!==process.platform)throw new I("UNSUPPORTED_PLATFORM","iOS tools are only available on macOS");if(!await v("xcrun"))throw new I("TOOL_MISSING","xcrun not found in PATH");let t=[],r=en(e.simulatorSetPath),i=await p("xcrun",tP(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(i.stdout);for(let[i,n]of Object.entries(e.devices))if(function(e){let t=tB(e);return t.includes("ios")||t.includes("tvos")}(i))for(let e of n){var a;e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:(a=i,tj(tB(a))?"tv":"mobile"),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}}catch(e){throw new I("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(r)return t;let o=null;try{o=n.join(F.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await p("xcrun",["devicectl","list","devices","--json-output",o],{allowFailure:!0,timeoutMs:tF});if(0!==e.exitCode)return t;let r=await x.readFile(o,"utf8"),i=JSON.parse(r);for(let e of i.result?.devices??[])if(function(e){var t;let r=tq(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=tJ(e),!!tV.test(t.trim())||tH(e).some(tW))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",i=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:i,kind:"device",target:function(e){var t;return tj(tq(e))?"tv":(t=tJ(e),tU.test(t.trim())||tH(e).some(tW))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{o&&await x.rm(o,{force:!0}).catch(()=>{})}return t}let tK=tR(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,z,5e3),tX=tR(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,J,1e3),tY=tR(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),tZ=tR(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3);async function tQ(e,t){let r=["devicectl",...e],i=await p("xcrun",r,{allowFailure:!0,timeoutMs:tZ});if(0===i.exitCode)return;let n=String(i.stdout??""),a=String(i.stderr??"");throw new I("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:i.exitCode,stdout:n,stderr:a,deviceId:t.deviceId,hint:t2(n,a)??t1})}async function t0(e,t){let r=n.join(F.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),i=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],a=await p("xcrun",i,{allowFailure:!0,timeoutMs:tZ});try{var o,s;if(0!==a.exitCode){let t=String(a.stdout??""),r=String(a.stderr??"");throw new I("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:i,exitCode:a.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:t2(t,r)??t1})}let n=await x.readFile(r,"utf8");return o=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let i="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:i})}return r}(JSON.parse(n)),s=t,"user-installed"===s?o.filter(e=>!e.bundleId.startsWith("com.apple.")):o}catch(t){if(t instanceof I)throw t;throw new I("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await x.unlink(r).catch(()=>{})}}let t1="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function t2(e,t){let r=`${e}
11
- ${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}async function t3(e,t,r){let i=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r);return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)})}let t4=new Set;function t8(e){return!!e&&t4.has(e)}function t5(e){return e?.trim()??""}function t6(e=process.env){return t5(e.AGENT_DEVICE_IOS_BUNDLE_ID)||t5(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function t9(e=process.env){let t=t5(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${t6(e)}.uitests`}let t7=function(e=process.env){let t=t6(e),r=t9(e);return Array.from(new Set([t5(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t,"com.myapp.AgentDeviceRunnerUITests.xctrunner","com.myapp.AgentDeviceRunner"].filter(e=>e.length>0)))}(process.env),re=new Map,rt=new Map,rr=new Set,ri=tR(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),rn=tR(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),ra=tR(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),ro=tR(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),rs=tR(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),rl=tR(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),rd=tR(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),ru=tR(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5),rc=n.join(F.homedir(),".agent-device","ios-runner");async function rp(e,t,r={}){var i;return(function(e){if("ios"!==e.platform)throw new I("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new I("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`)}(e),rM(r.requestId),"snapshot"===(i=t.command)||"screenshot"===i||"findText"===i||"alert"===i)?Z(()=>(rM(r.requestId),rf(e,t,r)),{shouldRetry:e=>(rM(r.requestId),function(e){if(!(e instanceof I)||"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"))}(e))}):rf(e,t,r)}async function rf(e,t,r={}){let i;rM(r.requestId);try{let n=(i=await rN(e,r)).ready?rn:ri;return await rm(e,i,t,r.logPath,n)}catch(a){let n=a instanceof I?a:new I("COMMAND_FAILED",String(a));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&rx(n)&&i?.ready){rM(r.requestId),i?await rv(i):await rw(e.id),i=await rN(e,r);let n=await rT(i.device,i.port,t,r.logPath,ri);return await rh(n,i,r.logPath)}throw a}}async function rm(e,t,r,i,n){let a=await rT(e,t.port,r,i,n,t);return await rh(a,t,i)}async function rh(e,t,r){let i=await e.text(),n={};try{n=JSON.parse(i)}catch{throw new I("COMMAND_FAILED","Invalid runner response",{text:i})}if(!n.ok)throw new I("COMMAND_FAILED",n.error?.message??"Runner error",{runner:n,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,n.data??{}}async function rw(e){await t3(rt,e,async()=>{await rA(e)})}async function rg(){let e=Array.from(re.values()),t=Array.from(rr);await Promise.allSettled(e.map(async e=>{await rS(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await rS(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await rS(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await rS(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await rS(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await rS(e.pid,"SIGKILL"),rr.delete(e)}))}async function rI(){await rg();let e=Array.from(re.keys());await Promise.allSettled(e.map(async e=>{await rw(e)})),await r_()}async function rv(e){await t3(rt,e.deviceId,async()=>{await rA(e.deviceId,e)})}async function rA(e,t){let r=t??re.get(e);if(r){try{await rT(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await rS(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await rS(r.child.pid,"SIGKILL"),rG(r.xctestrunPath),rG(r.jsonPath),re.get(e)===r&&re.delete(e)}}async function ry(e){await p("xcrun",t$(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:ri})}async function rN(e,t){return await t3(rt,e.id,async()=>{var r,i,n;let a,o=re.get(e.id);if(o){if((r=o.child.pid)&&C(r))return o;await rA(e.id,o)}await ("simulator"!==(i=e).kind?Promise.resolve():ry(i));let s=await rb(e,t),l=await rV(),{xctestrunPath:u,jsonPath:c}=await rU(s,{AGENT_DEVICE_RUNNER_PORT:String(l)},`session-${e.id}-${l}`),{child:p,wait:f}=d("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",rE(e),"1","-destination-timeout",String(ru),"-xctestrun",u,"-destination",(a=rD(n=e),"simulator"===n.kind?`platform=${a} Simulator,id=${n.id}`:`platform=${a},id=${n.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(l)},detached:!0});p.stdout?.on("data",e=>{rO(e,t.logPath,t.traceLogPath,t.verbose)}),p.stderr?.on("data",e=>{rO(e,t.logPath,t.traceLogPath,t.verbose)});let m={device:e,deviceId:e.id,port:l,xctestrunPath:u,jsonPath:c,testPromise:f,child:p,ready:!1};return re.set(e.id,m),m})}async function rS(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 p("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function rb(e,t){var r,i,a;let o,s=(r=e.kind,(o=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?n.resolve(o):"simulator"===r?n.join(rc,"derived"):n.join(rc,"derived",r));if(H(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)){!function(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return H(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new I("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."})}(s);try{R.rmSync(s,{recursive:!0,force:!0})}catch{}}let l=rk(s);if(l)return l;let d=function(){let e=n.dirname(y(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=n.join(t,"package.json");if(R.existsSync(e))return t;t=n.dirname(t)}return e}(),u=n.join(d,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!R.existsSync(u))throw new I("COMMAND_FAILED","iOS runner project not found",{projectPath:u});let c=function(e=process.env){let t=t6(e),r=t9(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),p=function(e=process.env,t=!1){if(!t)return[];let r=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",a=["CODE_SIGN_STYLE=Automatic"];return r&&a.push(`DEVELOPMENT_TEAM=${r}`),i&&a.push(`CODE_SIGN_IDENTITY=${i}`),n&&a.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),a}(process.env,"device"===e.kind),f="device"===e.kind?["-allowProvisioningUpdates"]:[];try{let r;await N("xcodebuild",["build-for-testing","-project",u,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",rE(e),"1","-destination",(i=e,r=rD(i),"simulator"===i.kind?`platform=${r} Simulator,id=${i.id}`:`generic/platform=${r}`),"-derivedDataPath",s,...c,...f,...p],{detached:!0,onSpawn:e=>{rr.add(e),e.on("close",()=>{rr.delete(e)})},onStdoutChunk:e=>{rO(e,t.logPath,t.traceLogPath,t.verbose)},onStderrChunk:e=>{rO(e,t.logPath,t.traceLogPath,t.verbose)}})}catch(o){let e,r,i=o instanceof I?o:new I("COMMAND_FAILED",String(o)),n=(e=(a=i).details?JSON.stringify(a.details):"",(r=`${a.message}
12
- ${e}`.toLowerCase()).includes("failed registering bundle identifier")||r.includes("app identifier")&&r.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":r.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":r.includes("no profiles for")||r.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":r.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new I("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:i.message,details:i.details,logPath:t.logPath,hint:n})}let m=rk(s);if(!m)throw new I("COMMAND_FAILED","Failed to locate .xctestrun after build");return m}async function r_(){let e=Array.from(rr);await Promise.allSettled(e.map(async e=>{try{await rS(e.pid,"SIGTERM"),await rS(e.pid,"SIGKILL")}finally{rr.delete(e)}}))}function rD(e){if("ios"!==e.platform)throw new I("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"tv"===e.target?"tvOS":"iOS"}function rE(e){return"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function rk(e){if(!R.existsSync(e))return null;let t=[],r=[e];for(;r.length>0;){let e=r.pop();for(let i of R.readdirSync(e,{withFileTypes:!0})){let a=n.join(e,i.name);if(i.isDirectory()){r.push(a);continue}if(i.isFile()&&i.name.endsWith(".xctestrun"))try{let e=R.statSync(a);t.push({path:a,mtimeMs:e.mtimeMs})}catch{}}}return 0===t.length?null:(t.sort((e,t)=>t.mtimeMs-e.mtimeMs),t[0]?.path??null)}function rO(e,t,r,i){t&&R.appendFileSync(t,e),r&&R.appendFileSync(r,e),i&&process.stderr.write(e)}function rM(e){if(t8(e))throw new I("COMMAND_FAILED","request canceled")}function rL(e){let{port:t,endpoints:r,logPath:i,lastError:n}=e,a="Runner did not accept connection";return new I("COMMAND_FAILED",a,{port:t,endpoints:r,logPath:i,lastError:n?String(n):void 0,reason:es({error:n,message:a,context:{platform:"ios",phase:"connect"}}),hint:el("IOS_RUNNER_CONNECT_TIMEOUT")})}function rx(e){return!(e instanceof I)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}async function rC(e){var t,r;let i,{session:n,port:a,logPath:o}=e,s=await n.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=es({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new I("COMMAND_FAILED",l,{port:a,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(i=`${l}
3
+ ${e.stderr}`}function ec(e,t){return["-s",e,...t]}function ep(e){return e.startsWith("emulator-")}function ef(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function em(e,t=K){return p("adb",ec(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function eh(e,t){let r=t.replace(/_/g," ").trim();if(!ep(e))return r||e;let i=await ew(e);return i?i.replace(/_/g," "):r||e}async function ew(e){for(let t of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let r=await p("adb",ec(e,["shell","getprop",t]),{allowFailure:!0,timeoutMs:1500}),i=r.stdout.trim();if(0===r.exitCode&&i.length>0)return i}let t=await p("adb",ec(e,["emu","avd","name"]),{allowFailure:!0,timeoutMs:1500}),r=t.stdout.trim();if(0===t.exitCode&&r.length>0)return r}async function eg(e,t){let r=eu(await p("adb",ec(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:K})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function eI(e){return(await Promise.all(ed.map(async t=>await eg(e,t)))).some(e=>!0===e)}async function ev(e){var t;let r;return"tv"===((r=eu(await p("adb",ec(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:K})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await eI(e)?"tv":(t=eu(await p("adb",ec(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:K})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function eA(e={}){if(!await v("adb"))throw new I("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??eo(void 0),r=(await ey()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,i,n]=await Promise.all([eh(e,t),e_(e),ev(e)]);return{platform:"android",id:e,name:r,kind:ep(e)?"emulator":"device",target:n,booted:i}}))}async function ey(){return(await p("adb",["devices","-l"],{timeoutMs:K})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).filter(e=>"device"===e[1]).map(e=>({serial:e[0],rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}))}async function eN(){let e=await p("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:K});if(0!==e.exitCode)throw new I("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function eb(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await eS(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 I("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 eS(e,t){let r=ef(e);for(let e of(await ey()).filter(e=>(!t||e.serial===t)&&ep(e.serial)))if(ef(e.rawModel)===r||ef(await eh(e.serial,e.rawModel))===r)return e.serial}async function e_(e){try{let t=await em(e);return"1"===t.stdout.trim()}catch{return!1}}async function eD(e){var t,r;let i,n=e.avdName.trim();if(!n)throw new I("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let a=e.timeoutMs??12e4;if(!await v("adb"))throw new I("TOOL_MISSING","adb not found in PATH");if(!await v("emulator"))throw new I("TOOL_MISSING","emulator not found in PATH");let o=await eN(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let i=ef(t);return e.find(e=>ef(e)===i)}(o,n);if(!s)throw new I("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:n,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let d=Date.now(),u=(t=await eA(),r=e.serial,i=ef(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&ef(e.name)===i));if(!u){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),l("emulator",t)}let c=u??await eb({avdName:s,serial:e.serial,timeoutMs:a}),p=Math.max(1e3,a-(Date.now()-d));await eE(c.id,p);let f=(await eA()).find(e=>e.id===c.id);return f?{...f,name:s,booted:!0}:{...c,name:s,booted:!0}}async function eE(e,t=6e4){let r,i=X.fromTimeoutMs(t),n=Math.max(1,Math.ceil(t/1e3)),a=!1;try{await Y(async({deadline:n})=>{if(n?.isExpired())throw a=!0,new I("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:i.elapsedMs(),message:"timeout"});let o=Math.max(1e3,n?.remainingMs()??t),s=await em(e,Math.min(o,K));if(r=s,"1"!==s.stdout.trim())throw new I("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:n,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=es({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:i,phase:"boot",classifyReason:e=>es({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let n=w(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=es({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===n.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:i.elapsedMs(),reason:d,hint:el(d),stdout:o,stderr:s,exitCode:l};if(a||"ANDROID_BOOT_TIMEOUT"===d)throw new I("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===n.code)throw new I("TOOL_MISSING",n.message,{...u,...n.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new I("COMMAND_FAILED",n.message,{...u,...n.details??{}});throw new I(n.code,n.message,{...u,...n.details??{}},n.cause)}}function ek(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let i=r[1]?.toLowerCase(),n=r[2]??"";return"http"!==i&&"https"!==i&&"ws"!==i&&"wss"!==i&&"ftp"!==i&&"ftps"!==i||n.startsWith("//")}function eO(e,t){let r,i=e?.trim();return i?i:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}function eL(e){let t=eM(e),r=e=>{let r=ex(t,e);if(null!==r)return"true"===r};return{text:ex(t,"text"),desc:ex(t,"content-desc"),resourceId:ex(t,"resource-id"),className:ex(t,"class"),bounds:ex(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function eM(e){let t=new Map,r=e.indexOf(" "),i=e.lastIndexOf(">");if(r<0||i<=r)return t;let n=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,a=r;for(;a<i;){for(;a<i;){let t=e[a];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;a+=1}if(a>=i)break;let r=e[a];if("/"===r||">"===r)break;n.lastIndex=a;let o=n.exec(e);if(!o)break;t.set(o[1],o[3]),a=n.lastIndex}return t}function ex(e,t){return e.get(t)??null}function eC(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),i=Number(t[2]);return{x:r,y:i,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-i)}}function eT(e){return e?e.toLowerCase():""}function eR(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}let eP=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function e$(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new I("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function eF(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 I("INVALID_ARGS",`permission setting requires a target: ${eP.join("|")}`)}function eV(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new I("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}let eG={settings:{type:"intent",value:"android.settings.SETTINGS"}},eU="android.intent.category.LAUNCHER",eB="android.intent.category.LEANBACK_LAUNCHER",eq="android.intent.category.DEFAULT";function ej(e,t){return["-s",e.id,...t]}async function eW(e,t){let r=t.trim();if(r.includes("."))return{type:"package",value:r};let i=eG[r.toLowerCase()];if(i)return i;let n=(await p("adb",ej(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===n.length)return{type:"package",value:n[0]};if(n.length>1)throw new I("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:n});throw new I("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function eH(e,t="all"){let r=await eJ(e);return("user-installed"===t?(await eK(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:function(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),i=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let n=r[e];if(!t.has(n)){i=n;break}}return i.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}(e)}))}async function eJ(e){let t=new Set;for(let r of ez(e,{includeFallbackWhenUnknown:!0})){let i=await p("adb",ej(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===i.exitCode&&0!==i.stdout.trim().length)for(let e of i.stdout.split("\n")){let r=e.trim();if(!r)continue;let i=r.split(/\s+/)[0],n=i.includes("/")?i.split("/")[0]:i;n&&t.add(n)}}return t}function ez(e,t={}){return"tv"===e.target?[eB]:"mobile"===e.target?[eU]:t.includeFallbackWhenUnknown?[eU,eB]:[eU]}async function eK(e){return(await p("adb",ej(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}async function eX(e){let t=await eQ(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await eQ(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function eY(e){let t=await p("adb",ej(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new I("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],i=r[2]?.toLowerCase();e&&("true"===i||"false"===i)&&t.set(e,"true"===i)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let i=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),n=i.length>0?i[i.length-1]?.[1]:void 0,a=n?`0x${n.toLowerCase()}`:void 0;return{visible:r,inputType:a,type:a?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let i=4080&t;return 32===i||208===i?"email":128===i||224===i||144===i?"password":"text"}(a):void 0}}(t.stdout)}async function eZ(e){let t=await eY(e),r=t,i=0;for(;r.visible&&i<2;)await tn(e),i+=1,await tV(120),r=await eY(e);return{attempts:i,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function eQ(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 p("adb",ej(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function e0(e,t,r){var i,n;let a;e.booted||await eE(e.id);let o=t.trim();if(ek(o)){if(r)throw new I("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await eW(e,t),l=ez(e)[0]??eU;if("intent"===s.type){if(r)throw new I("INVALID_ARGS","Activity override requires a package name, not an intent");await p("adb",ej(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eq,"-c",l,"-n",t]));return}let d=await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eq,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(i=d.stdout,n=d.stderr,a=`${i}
4
+ ${n}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(a)))return;let u=await e1(e,s.value);if(!u)throw new I("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr});await p("adb",ej(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eq,"-c",l,"-n",u]))}async function e1(e,t){for(let r of Array.from(new Set(ez(e,{includeFallbackWhenUnknown:!0})))){let i=await p("adb",ej(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==i.exitCode)continue;let n=function(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}(i.stdout);if(n)return n}return null}async function e2(e){e.booted||await eE(e.id)}async function e3(e,t){if("settings"===t.trim().toLowerCase())return void await p("adb",ej(e,["shell","am","force-stop","com.android.settings"]));let r=await eW(e,t);if("intent"===r.type)throw new I("INVALID_ARGS","Close requires a package name, not an intent");await p("adb",ej(e,["shell","am","force-stop",r.value]))}async function e4(e,t){let r=await eW(e,t);if("intent"===r.type)throw new I("INVALID_ARGS","App uninstall requires a package name, not an intent");let i=await p("adb",ej(e,["uninstall",r.value]),{allowFailure:!0});if(0!==i.exitCode){let e=`${i.stdout}
5
+ ${i.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new I("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}return{package:r.value}}let e8=null;async function e5(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(e8?.key===e)return e8.invocation;if(await v("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return e8={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new I("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 I("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return e8={key:e,invocation:r},r}async function e6(e){let t=await e5();await p(t.cmd,[...t.prefixArgs,...e])}async function e9(e,t){let r,i=await x.mkdtemp(n.join(F.tmpdir(),"agent-device-aab-")),a=n.join(i,"bundle.apks"),o=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await e6(["build-apks","--bundle",t,"--output",a,"--mode",o]),await e6(["install-apks","--apks",a,"--device-id",e.id])}finally{await x.rm(i,{recursive:!0,force:!0})}}async function e7(e,t){".aab"===n.extname(t).toLowerCase()?await e9(e,t):await p("adb",ej(e,["install","-r",t]))}async function te(e,t){e.booted||await eE(e.id),await e7(e,t)}async function tt(e,t,r){e.booted||await eE(e.id);let{package:i}=await e4(e,t);return await e7(e,r),{package:i}}async function tr(e,t,r){await p("adb",ej(e,["shell","input","tap",String(t),String(r)]))}async function ti(e,t,r,i,n,a=250){await p("adb",ej(e,["shell","input","swipe",String(t),String(r),String(i),String(n),String(a)]))}async function tn(e){await p("adb",ej(e,["shell","input","keyevent","4"]))}async function ta(e){await p("adb",ej(e,["shell","input","keyevent","3"]))}async function to(e){await p("adb",ej(e,["shell","input","keyevent","187"]))}async function ts(e,t,r,i=800){await p("adb",ej(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(i)]))}async function tl(e,t){let r=tx(t);if(!r||"ok"!==await tC(e,t))try{let r=t.replace(/ /g,"%s");await p("adb",ej(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof I)||"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 I("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 td(e){let t,r;return(r=(t=(await tR(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 tu(e,t){await tR(e,["shell","cmd","clipboard","set","text",t],"write")}async function tc(e,t,r){await tr(e,t,r)}async function tp(e,t,r,i){let n=Array.from(i).length,a=tx(i),o=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];a||(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 a of o){var l,d;await tc(e,t,r);let o=(l=n+a.clearPadding,d=a.minClear,Math.max(d,Math.min(a.maxClear,l)));if(await tP(e,o),"input_text"===a.strategy)await tl(e,i);else if("clipboard_paste"===a.strategy){if("ok"!==await tC(e,i))continue}else await tM(e,i,1,15);if((s=await t$(e,t,r))===i)return}throw new I("COMMAND_FAILED","Android fill verification failed",{expected:i,actual:s??null})}async function tf(e,t,r=.6){let{width:i,height:n}=await ty(e),a=Math.floor(i*r),o=Math.floor(n*r),s=Math.floor(i/2),l=Math.floor(n/2),d=s,u=l,c=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(a/2),c=s+Math.floor(a/2);break;case"right":d=s+Math.floor(a/2),c=s-Math.floor(a/2);break;default:throw new I("INVALID_ARGS",`Unknown direction: ${t}`)}await p("adb",ej(e,["shell","input","swipe",String(d),String(u),String(c),String(f),"300"]))}async function tm(e,t){for(let r=0;r<8;r+=1){let r="";try{r=await tN(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new I("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(function(e,t){let r=t.toLowerCase(),i=/<node[^>]+>/g,n=i.exec(e);for(;n;){let t=eM(n[0]),a=(ex(t,"text")??"").toLowerCase(),o=(ex(t,"content-desc")??"").toLowerCase();if(a.includes(r)||o.includes(r)){let e=eC(ex(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}}n=i.exec(e)}return null}(r,t))return;await tf(e,"down",.5)}throw new I("COMMAND_FAILED",`Could not find element containing "${t}" after scrolling`)}async function th(e,t){let r=await p("adb",ej(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new I("COMMAND_FAILED","Failed to capture screenshot");await x.writeFile(t,r.stdoutBuffer)}async function tw(e,t,r,i,n){switch(t.toLowerCase()){case"wifi":{let t=tD(r);await p("adb",ej(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=tD(r);await p("adb",ej(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await p("adb",ej(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=tD(r);await p("adb",ej(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await tE(e,r);await p("adb",ej(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 I("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await tg(e,t);return}case"permission":{if(!i)throw new I("INVALID_ARGS","permission setting requires an active app in session");let t=e$(r),a=function(e,t){let r=eF(e);if(t?.trim())throw new I("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 I("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(n?.permissionTarget,n?.permissionMode);if("notifications"===a.kind)return void await tO(e,i,t,a);let o="grant"===t?"grant":"revoke";if("photos"===a.type)return void await tk(e,i,o);await p("adb",ej(e,["shell","pm",o,i,a.value]));return}default:throw new I("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function tg(e,t){var r;let i,n,a=(r=e,n=[["shell","cmd","fingerprint","touch",i="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",i]],"emulator"===r.kind&&n.push(["emu","finger","touch",i]),n),o=[];for(let t of a){let r=await p("adb",ej(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let i;return t=e.stdout,r=e.stderr,(i=`${t}
6
+ ${r}`.toLowerCase()).includes("unknown command")||i.includes("can't find service: fingerprint")||i.includes("service fingerprint was not found")||i.includes("fingerprint cmd unavailable")||i.includes("emu command is not supported")||i.includes("emulator console is not running")||i.includes("fingerprint")&&i.includes("not found")}))throw new I("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 I("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}async function tI(e,t,r){let i="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,n=["shell","am","broadcast","-a",i,"-p",t],a="string"==typeof r.receiver?r.receiver.trim():"";a&&n.push("-n",a);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new I("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 I("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(n,e,t),s+=1);return await p("adb",ej(e,n)),{action:i,extrasCount:s}}async function tv(e,t={}){return function(e,t,r){let i=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],i=/<node\b[^>]*>|<\/node>/g,n=i.exec(e);for(;n;){let t=n[0];if(t.startsWith("</node")){r.length>1&&r.pop(),n=i.exec(e);continue}let a=eL(t),o=eC(a.bounds),s=r[r.length-1],l={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,rect:o,enabled:a.enabled,hittable:a.clickable??a.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),n=i.exec(e)}return t}(e),n=[],a=!1,o=r.depth??1/0,s=r.scope?function(e,t){let r=t.toLowerCase(),i=[...e.children];for(;i.length>0;){let e=i.shift(),t=e.label?.toLowerCase()??"",n=e.value?.toLowerCase()??"",a=e.identifier?.toLowerCase()??"";if(t.includes(r)||n.includes(r)||a.includes(r))return e;i.push(...e.children)}return null}(i,r.scope):null,l=s?[s]:i.children,d=new Map,u=e=>{let t=d.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||u(t))return d.set(e,!0),!0;return d.set(e,!1),!1},c=(e,t,i,s=!1,l=!1)=>{var d,p,f,m,h,w;let g,I,v,A,y,N,b,S;if(n.length>=800){a=!0;return}if(t>o)return;let _=!!r.raw||(d=e,p=r,f=s,m=u(e),h=l,I=eT(d.type),v=!!(d.label&&d.label.trim().length>0),A=!!(d.identifier&&d.identifier.trim().length>0),y=v&&!eR(d.label??""),N=A&&!eR(d.identifier??""),b=(g=(w=I).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,S="imageview"===I||"imagebutton"===I,p.interactiveOnly?!!d.hittable||!!(y||N)&&!S&&(!b||!!h)&&(f||m||h):p.compact?y||N||!!d.hittable:!b&&!S||!!d.hittable||!!y||!!N&&!!m||m),D=i;_&&(D=n.length,n.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:t,parentIndex:i}));let E=s||!!e.hittable,k=l||function(e){if(!e)return!1;let t=eT(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),a)return};for(let e of l)if(c(e,0,void 0,!1,!1),a)break;return a?{nodes:n,truncated:a}:{nodes:n}}(await tN(e),0,t)}async function tA(){if(!await v("adb"))throw new I("TOOL_MISSING","adb not found in PATH")}async function ty(e){let t=(await p("adb",ej(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new I("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function tN(e){return Z(()=>tb(e),{shouldRetry:t_})}async function tb(e){var t,r,i;let n,a,o=await p("adb",ej(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=tS(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await p("adb",ej(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,i=l.stderr,n=`${r}
7
+ ${i}`,a=/dumped to:\s*(\S+)/i.exec(n),a?.[1]??t),u=await p("adb",ej(e,["shell","cat",d])),c=tS(u.stdout,u.stderr);if(!c)throw new I("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return c}function tS(e,t){let r=`${e}
8
+ ${t}`,i=r.indexOf("<?xml"),n=i>=0?i:r.indexOf("<hierarchy");if(n<0)return null;let a=r.lastIndexOf("</hierarchy>");if(a<0||a<n)return null;let o=r.slice(n,a+12).trim();return o.length>0?o:null}function t_(e){if(!(e instanceof I)||"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"))}function tD(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 I("INVALID_ARGS",`Invalid setting state: ${e}`)}async function tE(e,t){let r=eV(t);if("toggle"!==r)return r;let i=await p("adb",ej(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==i.exitCode)throw new I("COMMAND_FAILED","Failed to read current Android appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});let n=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
9
+ ${t}`);if(!r)return null;let i=r[1].toLowerCase();return"yes"===i?"dark":"no"===i?"light":"auto"===i?"auto":null}(i.stdout,i.stderr);if(!n)throw new I("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:i.stdout,stderr:i.stderr});return"auto"===n?"dark":"dark"===n?"light":"dark"}async function tk(e,t,r){let i=await tL(e),n=[];for(let a of null!==i&&i>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let i=await p("adb",ej(e,["shell","pm",r,t,a]),{allowFailure:!0});if(0===i.exitCode)return;n.push({permission:a,stderr:i.stderr,exitCode:i.exitCode})}throw new I("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:i,attempts:n})}async function tO(e,t,r,i){"grant"===r?await p("adb",ej(e,["shell","pm","grant",t,i.permission]),{allowFailure:!0}):(await p("adb",ej(e,["shell","pm","revoke",t,i.permission]),{allowFailure:!0}),"reset"===r&&(await p("adb",ej(e,["shell","pm","clear-permission-flags",t,i.permission,"user-set"]),{allowFailure:!0}),await p("adb",ej(e,["shell","pm","clear-permission-flags",t,i.permission,"user-fixed"]),{allowFailure:!0}))),await p("adb",ej(e,["shell","appops","set",t,i.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function tL(e){let t=await p("adb",ej(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 tM(e,t,r,i){let n=Math.max(1,Math.floor(r)),a=Array.from(t);for(let t=0;t<a.length;t+=n){let r=a.slice(t,t+n).join("");await tl(e,r),i>0&&t+n<a.length&&await tV(i)}}function tx(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 tC(e,t){let r=await p("adb",ej(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":tT(r.stdout,r.stderr)?"unsupported":0===(await p("adb",ej(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await p("adb",ej(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}function tT(e,t){let r=`${e}
10
+ ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function tR(e,t,r){let i=await p("adb",ej(e,t),{allowFailure:!0});if(tT(i.stdout,i.stderr))throw new I("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==i.exitCode)throw new I("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return i.stdout}async function tP(e,t){let r=Math.max(0,t);await p("adb",ej(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let i=Math.min(24,r-t);await p("adb",ej(e,["shell","input","keyevent",...Array(i).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function t$(e,t,r){let i,n=await tN(e),a=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(i=a.exec(n));){let e=eL(i[0]),n=eC(e.bounds);if(!n)continue;let a=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,n.width*n.height),p=t>=n.x&&t<=n.x+n.width&&r>=n.y&&r<=n.y+n.height;if(u&&tF(a)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&tF(a)){(!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 tF(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function tV(e){await new Promise(t=>setTimeout(t,e))}function tG(e,t,r){if(!e)return t;let i=Number(e);return Number.isFinite(i)?Math.max(r,Math.floor(i)):t}function tU(e,t={}){let r=en(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function tB(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:tU(t,{simulatorSetPath:e.simulatorSetPath})}let tq=tG(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),tj=/^(iphone|ipad|ipod|appletv)/i,tW=/^appletv/i,tH=["apple tv","appletv","tvos"];function tJ(e){return(e??"").trim().toLowerCase()}function tz(e){return tJ(e.hardwareProperties?.platform)}function tK(e){return e.includes("tvos")}function tX(e){let t=tJ(e);return tH.some(e=>t.includes(e))}function tY(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function tZ(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function tQ(e={}){if("darwin"!==process.platform)throw new I("UNSUPPORTED_PLATFORM","iOS tools are only available on macOS");if(!await v("xcrun"))throw new I("TOOL_MISSING","xcrun not found in PATH");let t=[],r=en(e.simulatorSetPath),i=await p("xcrun",tU(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(i.stdout);for(let[i,n]of Object.entries(e.devices))if(function(e){let t=tJ(e);return t.includes("ios")||t.includes("tvos")}(i))for(let e of n){var a;e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:(a=i,tK(tJ(a))?"tv":"mobile"),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}}catch(e){throw new I("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(r)return t;let o=null;try{o=n.join(F.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await p("xcrun",["devicectl","list","devices","--json-output",o],{allowFailure:!0,timeoutMs:tq});if(0!==e.exitCode)return t;let r=await x.readFile(o,"utf8"),i=JSON.parse(r);for(let e of i.result?.devices??[])if(function(e){var t;let r=tz(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=tZ(e),!!tj.test(t.trim())||tY(e).some(tX))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",i=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:i,kind:"device",target:function(e){var t;return tK(tz(e))?"tv":(t=tZ(e),tW.test(t.trim())||tY(e).some(tX))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{o&&await x.rm(o,{force:!0}).catch(()=>{})}return t}let t0=tG(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,z,5e3),t1=tG(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,J,1e3),t2=tG(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),t3=tG(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3);async function t4(e,t){let r=["devicectl",...e],i=await p("xcrun",r,{allowFailure:!0,timeoutMs:t3});if(0===i.exitCode)return;let n=String(i.stdout??""),a=String(i.stderr??"");throw new I("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:i.exitCode,stdout:n,stderr:a,deviceId:t.deviceId,hint:t6(n,a)??t5})}async function t8(e,t){let r=n.join(F.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),i=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],a=await p("xcrun",i,{allowFailure:!0,timeoutMs:t3});try{var o,s;if(0!==a.exitCode){let t=String(a.stdout??""),r=String(a.stderr??"");throw new I("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:i,exitCode:a.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:t6(t,r)??t5})}let n=await x.readFile(r,"utf8");return o=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let i="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:i})}return r}(JSON.parse(n)),s=t,"user-installed"===s?o.filter(e=>!e.bundleId.startsWith("com.apple.")):o}catch(t){if(t instanceof I)throw t;throw new I("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await x.unlink(r).catch(()=>{})}}let t5="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function t6(e,t){let r=`${e}
11
+ ${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}async function t9(e,t,r){let i=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r);return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)})}let t7=new Set;function re(e){return!!e&&t7.has(e)}function rt(e){return e?.trim()??""}function rr(e=process.env){return rt(e.AGENT_DEVICE_IOS_BUNDLE_ID)||rt(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function ri(e=process.env){let t=rt(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${rr(e)}.uitests`}let rn=function(e=process.env){let t=rr(e),r=ri(e);return Array.from(new Set([rt(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env),ra=new Map,ro=new Map,rs=new Map,rl=new Set,rd=tG(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),ru=tG(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),rc=tG(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),rp=tG(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),rf=tG(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),rm=tG(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),rh=tG(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),rw=tG(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5),rg=n.join(F.homedir(),".agent-device","ios-runner");async function rI(e,t,r={}){var i;return(function(e){if("ios"!==e.platform)throw new I("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new I("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`)}(e),rP(r.requestId),"snapshot"===(i=t.command)||"screenshot"===i||"findText"===i||"alert"===i)?Z(()=>(rP(r.requestId),rv(e,t,r)),{shouldRetry:e=>(rP(r.requestId),function(e){if(!(e instanceof I)||"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"))}(e))}):rv(e,t,r)}async function rv(e,t,r={}){let i;rP(r.requestId);try{let n=(i=await rk(e,r)).ready?ru:rd;return await rA(e,i,t,r.logPath,n)}catch(a){let n=a instanceof I?a:new I("COMMAND_FAILED",String(a));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&rF(n)&&i?.ready){rP(r.requestId),i?await r_(i):await rN(e.id),i=await rk(e,r);let n=await rG(i.device,i.port,t,r.logPath,rd);return await ry(n,i,r.logPath)}throw a}}async function rA(e,t,r,i,n){let a=await rG(e,t.port,r,i,n,t);return await ry(a,t,i)}async function ry(e,t,r){let i=await e.text(),n={};try{n=JSON.parse(i)}catch{throw new I("COMMAND_FAILED","Invalid runner response",{text:i})}if(!n.ok)throw new I("COMMAND_FAILED",n.error?.message??"Runner error",{runner:n,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,n.data??{}}async function rN(e){await t9(ro,e,async()=>{await rD(e)})}async function rb(){let e=Array.from(ra.values()),t=Array.from(rl);await Promise.allSettled(e.map(async e=>{await rO(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await rO(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await rO(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await rO(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await rO(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await rO(e.pid,"SIGKILL"),rl.delete(e)}))}async function rS(){await rb();let e=Array.from(ra.keys());await Promise.allSettled(e.map(async e=>{await rN(e)})),await rM()}async function r_(e){await t9(ro,e.deviceId,async()=>{await rD(e.deviceId,e)})}async function rD(e,t){let r=t??ra.get(e);if(r){try{await rG(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await rO(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await rO(r.child.pid,"SIGKILL"),rJ(r.xctestrunPath),rJ(r.jsonPath),ra.get(e)===r&&ra.delete(e)}}async function rE(e){await p("xcrun",tB(e,["bootstatus",e.id,"-b"]),{timeoutMs:rd})}async function rk(e,t){return await t9(ro,e.id,async()=>{var r,i,n;let a,o=ra.get(e.id);if(o){if((r=o.child.pid)&&C(r))return o;await rD(e.id,o)}await ("simulator"!==(i=e).kind?Promise.resolve():rE(i));let s=await rL(e,t),l=await rW(),{xctestrunPath:u,jsonPath:c}=await rH(s,{AGENT_DEVICE_RUNNER_PORT:String(l)},`session-${e.id}-${l}`),{child:p,wait:f}=d("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",rC(e),"1","-destination-timeout",String(rw),"-xctestrun",u,"-destination",(a=rx(n=e),"simulator"===n.kind?`platform=${a} Simulator,id=${n.id}`:`platform=${a},id=${n.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(l)},detached:!0});p.stdout?.on("data",e=>{rR(e,t.logPath,t.traceLogPath,t.verbose)}),p.stderr?.on("data",e=>{rR(e,t.logPath,t.traceLogPath,t.verbose)});let m={device:e,deviceId:e.id,port:l,xctestrunPath:u,jsonPath:c,testPromise:f,child:p,ready:!1};return ra.set(e.id,m),m})}async function rO(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 p("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function rL(e,t){var r;let i,a=(r=e.kind,(i=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?n.resolve(i):"simulator"===r?n.join(rg,"derived"):n.join(rg,"derived",r));return await t9(rs,a,async()=>{var r,i;if(H(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)){!function(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return H(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new I("COMMAND_FAILED","Refusing to clean AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH automatically",{derivedPath:e,hint:"Unset AGENT_DEVICE_IOS_CLEAN_DERIVED, or set AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN=1 if you trust this path."})}(a);try{R.rmSync(a,{recursive:!0,force:!0})}catch{}}let o=rT(a);if(o)return o;let s=function(){let e=n.dirname(y(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=n.join(t,"package.json");if(R.existsSync(e))return t;t=n.dirname(t)}return e}(),l=n.join(s,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!R.existsSync(l))throw new I("COMMAND_FAILED","iOS runner project not found",{projectPath:l});let d=function(e=process.env){let t=rr(e),r=ri(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),u=function(e=process.env,t=!1){if(!t)return[];let r=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",a=["CODE_SIGN_STYLE=Automatic"];return r&&a.push(`DEVELOPMENT_TEAM=${r}`),i&&a.push(`CODE_SIGN_IDENTITY=${i}`),n&&a.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),a}(process.env,"device"===e.kind),c="device"===e.kind?["-allowProvisioningUpdates"]:[];try{let i;await N("xcodebuild",["build-for-testing","-project",l,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",rC(e),"1","-destination",(r=e,i=rx(r),"simulator"===r.kind?`platform=${i} Simulator,id=${r.id}`:`generic/platform=${i}`),"-derivedDataPath",a,"COMPILER_INDEX_STORE_ENABLE=NO",...d,...c,...u],{detached:!0,onSpawn:e=>{rl.add(e),e.on("close",()=>{rl.delete(e)})},onStdoutChunk:e=>{rR(e,t.logPath,t.traceLogPath,t.verbose)},onStderrChunk:e=>{rR(e,t.logPath,t.traceLogPath,t.verbose)}})}catch(o){let e,r,n=o instanceof I?o:new I("COMMAND_FAILED",String(o)),a=(e=(i=n).details?JSON.stringify(i.details):"",(r=`${i.message}
12
+ ${e}`.toLowerCase()).includes("failed registering bundle identifier")||r.includes("app identifier")&&r.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":r.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":r.includes("no profiles for")||r.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":r.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new I("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:n.message,details:n.details,logPath:t.logPath,hint:a})}let p=rT(a);if(!p)throw new I("COMMAND_FAILED","Failed to locate .xctestrun after build");return p})}async function rM(){let e=Array.from(rl);await Promise.allSettled(e.map(async e=>{try{await rO(e.pid,"SIGTERM"),await rO(e.pid,"SIGKILL")}finally{rl.delete(e)}}))}function rx(e){if("ios"!==e.platform)throw new I("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"tv"===e.target?"tvOS":"iOS"}function rC(e){return"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function rT(e){if(!R.existsSync(e))return null;let t=[],r=[e];for(;r.length>0;){let e=r.pop();for(let i of R.readdirSync(e,{withFileTypes:!0})){let a=n.join(e,i.name);if(i.isDirectory()){r.push(a);continue}if(i.isFile()&&i.name.endsWith(".xctestrun"))try{let e=R.statSync(a);t.push({path:a,mtimeMs:e.mtimeMs})}catch{}}}return 0===t.length?null:(t.sort((e,t)=>t.mtimeMs-e.mtimeMs),t[0]?.path??null)}function rR(e,t,r,i){t&&R.appendFileSync(t,e),r&&R.appendFileSync(r,e),i&&process.stderr.write(e)}function rP(e){if(re(e))throw new I("COMMAND_FAILED","request canceled")}function r$(e){let{port:t,endpoints:r,logPath:i,lastError:n}=e,a="Runner did not accept connection";return new I("COMMAND_FAILED",a,{port:t,endpoints:r,logPath:i,lastError:n?String(n):void 0,reason:es({error:n,message:a,context:{platform:"ios",phase:"connect"}}),hint:el("IOS_RUNNER_CONNECT_TIMEOUT")})}function rF(e){return!(e instanceof I)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}async function rV(e){var t,r;let i,{session:n,port:a,logPath:o}=e,s=await n.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=es({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new I("COMMAND_FAILED",l,{port:a,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(i=`${l}
13
13
  ${t}
14
- ${r}`.toLowerCase()).includes("device is busy")&&i.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":el("IOS_RUNNER_CONNECT_TIMEOUT"))})}async function rT(e,t,r,i,n=ri,a){let o=X.fromTimeoutMs(n),s=await rR(e,t,o.remainingMs()),l=null,d=Math.max(1,Math.ceil(n/ra));try{return await Y(async({deadline:o})=>{if(o?.isExpired())throw new I("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:n});if(a&&null!==a.child.exitCode&&void 0!==a.child.exitCode)throw await rC({session:a,port:t,logPath:i});for(let i of("device"===e.kind&&(s=await rR(e,t,o?.remainingMs())),s))try{let e=o?.remainingMs()??n;if(e<=0)throw new I("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:n});return await rP(i,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(rl,e))}catch(e){l=e}throw new I("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:s,lastError:l?String(l):void 0})},{maxAttempts:d,baseDelayMs:ro,maxDelayMs:rs,jitter:.2,shouldRetry:rx},{deadline:o,phase:"ios_runner_connect"})}catch(e){l||(l=e)}if("simulator"===e.kind){let n=o.remainingMs();if(n<=0)throw rL({port:t,endpoints:s,logPath:i,lastError:l});let a=await rF(e,t,r,n);return new Response(a.body,{status:a.status})}throw rL({port:t,endpoints:s,logPath:i,lastError:l})}async function rR(e,t,r){let i=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return i;let n=await r$(e.id,r);return n&&i.unshift(`http://[${n}]:${t}/command`),i}async function rP(e,t,r){let i=new AbortController,n=setTimeout(()=>i.abort(),r);try{return await fetch(e,{...t,signal:i.signal})}finally{clearTimeout(n)}}async function r$(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(rd,t)):rd,i=n.join(F.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),n=await p("xcrun",["devicectl","device","info","details","--device",e,"--json-output",i,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==n.exitCode||!R.existsSync(i))return null;let a=JSON.parse(R.readFileSync(i,"utf8"));if(a.info?.outcome&&"success"!==a.info.outcome)return null;let o=(a.result?.connectionProperties?.tunnelIPAddress??a.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{rG(i)}}async function rF(e,t,r,i){let n=JSON.stringify(r),a=t$(e,["spawn",e.id,"/usr/bin/curl","-s","-X","POST","-H","Content-Type: application/json","--data",n,`http://127.0.0.1:${t}/command`]),o=await p("xcrun",a,{allowFailure:!0,timeoutMs:i}),s=o.stdout;if(0!==o.exitCode){let e=es({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new I("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:el(e)})}return{status:200,body:s}}async function rV(){return await new Promise((e,t)=>{let r=V.createServer();r.listen(0,"127.0.0.1",()=>{let i=r.address();r.close(),"object"==typeof i&&i?.port?e(i.port):t(new I("COMMAND_FAILED","Failed to allocate port"))}),r.on("error",t)})}async function rU(e,t,r){let i,a=n.dirname(e),o=r.replace(/[^a-zA-Z0-9._-]/g,"_"),s=n.join(a,`AgentDeviceRunner.env.${o}.json`),l=n.join(a,`AgentDeviceRunner.env.${o}.xctestrun`),d=await p("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new I("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{i=JSON.parse(d.stdout)}catch(t){throw new I("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},c=i.TestConfigurations;if(Array.isArray(c))for(let e of c){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(i))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),i[e]=t);R.writeFileSync(s,JSON.stringify(i,null,2));let f=await p("plutil",["-convert","xml1","-o",l,s],{allowFailure:!0});if(0!==f.exitCode)throw new I("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:f.stderr});return{xctestrunPath:l,jsonPath:s}}function rG(e){try{R.existsSync(e)&&R.unlinkSync(e)}catch{}}function rB(e,t){if("simulator"!==e.kind)throw new I("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function rq(e){let t,r;if("simulator"!==e.kind||"Booted"===await rj(e))return;let i=X.fromTimeoutMs(tK);try{await Y(async({deadline:i})=>{if(i?.isExpired())throw new I("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:tK});let n=Math.max(1e3,i?.remainingMs()??tK),a=await p("xcrun",t$(e,["boot",e.id]),{allowFailure:!0,timeoutMs:n});t={stdout:String(a.stdout??""),stderr:String(a.stderr??""),exitCode:a.exitCode};let o=`${t.stdout}
15
- ${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new I("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await p("xcrun",t$(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:n});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new I("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await rj(e);if("Booted"!==d)throw new I("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let i=es({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==i&&"CI_RESOURCE_STARVATION_SUSPECTED"!==i}},{deadline:i,phase:"boot",classifyReason:e=>es({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(a){let n=es({error:a,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new I("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:tK,elapsedMs:i.elapsedMs(),reason:n,hint:el(n),boot:t,bootstatus:r})}}async function rj(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?tP(["list","devices","-j"]):t$(e,["list","devices","-j"]),i=await p("xcrun",r,{allowFailure:!0,timeoutMs:tX});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}let rW={settings:"com.apple.Preferences"},rH=null;function rJ(e,t,r){return p("xcrun",t$(e,t),r)}function rz(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function rK(e,t){let r=t.trim();if(r.includes("."))return r;let i=rW[r.toLowerCase()];if(i)return i;let n=("simulator"===e.kind?await r9(e):await t0(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===n.length)return n[0].bundleId;if(n.length>1)throw new I("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:n});throw new I("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function rX(e,t,r){let i=r?.url?.trim();if(i){if(!ek(i))throw new I("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await rq(e),await p("open",["-a","Simulator"],{allowFailure:!0}),await rJ(e,["openurl",e.id,i]);return}let n=eO(r?.appBundleId??await rK(e,t),i);if(!n)throw new I("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await id(e,n,{payloadUrl:i});return}let n=t.trim();if(ek(n)){if("simulator"===e.kind){await rq(e),await p("open",["-a","Simulator"],{allowFailure:!0}),await rJ(e,["openurl",e.id,n]);return}let t=eO(r?.appBundleId,n);if(!t)throw new I("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await id(e,t,{payloadUrl:n});return}let a=r?.appBundleId??await rK(e,t);"simulator"===e.kind?await il(e,a):await id(e,a)}async function rY(e){"simulator"!==e.kind||"Booted"!==await rj(e)&&(await rq(e),await p("open",["-a","Simulator"],{allowFailure:!0}))}async function rZ(e,t){let r=await rK(e,t);if("simulator"===e.kind){await rq(e);let t=t$(e,["terminate",e.id,r]),i=await p("xcrun",t,{allowFailure:!0});if(0!==i.exitCode){if(i.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new I("COMMAND_FAILED",`xcrun exited with code ${i.exitCode}`,{cmd:"xcrun",args:t,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}return}await tQ(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function rQ(e,t){let r=await rK(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],i=await p("xcrun",t,{allowFailure:!0,timeoutMs:tZ});if(0!==i.exitCode){let n=String(i.stdout??""),a=String(i.stderr??"");if(!rz(`${n}
16
- ${a}`.toLowerCase()))throw new I("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:i.exitCode,stdout:n,stderr:a,deviceId:e.id,hint:t2(n,a)??t1})}return{bundleId:r}}await rq(e);let i=await rJ(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==i.exitCode&&!rz(`${i.stdout}
17
- ${i.stderr}`.toLowerCase()))throw new I("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return{bundleId:r}}async function r0(e,t){"simulator"!==e.kind?await tQ(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await rq(e),await rJ(e,["install",e.id,t]))}async function r1(e,t,r){let{bundleId:i}=await rQ(e,t);return await r0(e,r),{bundleId:i}}async function r2(e,t,r){if("simulator"===e.kind){await rq(e),await rJ(e,["io",e.id,"screenshot",t]);return}try{await tQ(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(e){if(!function(e){if(!(e instanceof I)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",i="string"==typeof t.stderr?t.stderr:"",n=`${e.message}
14
+ ${r}`.toLowerCase()).includes("device is busy")&&i.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":el("IOS_RUNNER_CONNECT_TIMEOUT"))})}async function rG(e,t,r,i,n=rd,a){let o=X.fromTimeoutMs(n),s=await rU(e,t,o.remainingMs()),l=null,d=Math.max(1,Math.ceil(n/rc));try{return await Y(async({deadline:o})=>{if(o?.isExpired())throw new I("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:n});if(a&&null!==a.child.exitCode&&void 0!==a.child.exitCode)throw await rV({session:a,port:t,logPath:i});for(let i of("device"===e.kind&&(s=await rU(e,t,o?.remainingMs())),s))try{let e=o?.remainingMs()??n;if(e<=0)throw new I("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:n});return await rB(i,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(rm,e))}catch(e){l=e}throw new I("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:s,lastError:l?String(l):void 0})},{maxAttempts:d,baseDelayMs:rp,maxDelayMs:rf,jitter:.2,shouldRetry:rF},{deadline:o,phase:"ios_runner_connect"})}catch(e){l||(l=e)}if("simulator"===e.kind){let n=o.remainingMs();if(n<=0)throw r$({port:t,endpoints:s,logPath:i,lastError:l});let a=await rj(e,t,r,n);return new Response(a.body,{status:a.status})}throw r$({port:t,endpoints:s,logPath:i,lastError:l})}async function rU(e,t,r){let i=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return i;let n=await rq(e.id,r);return n&&i.unshift(`http://[${n}]:${t}/command`),i}async function rB(e,t,r){let i=new AbortController,n=setTimeout(()=>i.abort(),r);try{return await fetch(e,{...t,signal:i.signal})}finally{clearTimeout(n)}}async function rq(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(rh,t)):rh,i=n.join(F.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),n=await p("xcrun",["devicectl","device","info","details","--device",e,"--json-output",i,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==n.exitCode||!R.existsSync(i))return null;let a=JSON.parse(R.readFileSync(i,"utf8"));if(a.info?.outcome&&"success"!==a.info.outcome)return null;let o=(a.result?.connectionProperties?.tunnelIPAddress??a.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{rJ(i)}}async function rj(e,t,r,i){let n=JSON.stringify(r),a=tB(e,["spawn",e.id,"/usr/bin/curl","-s","-X","POST","-H","Content-Type: application/json","--data",n,`http://127.0.0.1:${t}/command`]),o=await p("xcrun",a,{allowFailure:!0,timeoutMs:i}),s=o.stdout;if(0!==o.exitCode){let e=es({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new I("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:el(e)})}return{status:200,body:s}}async function rW(){return await new Promise((e,t)=>{let r=V.createServer();r.listen(0,"127.0.0.1",()=>{let i=r.address();r.close(),"object"==typeof i&&i?.port?e(i.port):t(new I("COMMAND_FAILED","Failed to allocate port"))}),r.on("error",t)})}async function rH(e,t,r){let i,a=n.dirname(e),o=r.replace(/[^a-zA-Z0-9._-]/g,"_"),s=n.join(a,`AgentDeviceRunner.env.${o}.json`),l=n.join(a,`AgentDeviceRunner.env.${o}.xctestrun`),d=await p("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new I("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{i=JSON.parse(d.stdout)}catch(t){throw new I("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},c=i.TestConfigurations;if(Array.isArray(c))for(let e of c){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(i))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),i[e]=t);R.writeFileSync(s,JSON.stringify(i,null,2));let f=await p("plutil",["-convert","xml1","-o",l,s],{allowFailure:!0});if(0!==f.exitCode)throw new I("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:f.stderr});return{xctestrunPath:l,jsonPath:s}}function rJ(e){try{R.existsSync(e)&&R.unlinkSync(e)}catch{}}function rz(e,t){if("simulator"!==e.kind)throw new I("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function rK(e){let t,r;if("simulator"!==e.kind||"Booted"===await rX(e))return;let i=X.fromTimeoutMs(t0);try{await Y(async({deadline:i})=>{if(i?.isExpired())throw new I("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:t0});let n=Math.max(1e3,i?.remainingMs()??t0),a=await p("xcrun",tB(e,["boot",e.id]),{allowFailure:!0,timeoutMs:n});t={stdout:String(a.stdout??""),stderr:String(a.stderr??""),exitCode:a.exitCode};let o=`${t.stdout}
15
+ ${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new I("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await p("xcrun",tB(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:n});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new I("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await rX(e);if("Booted"!==d)throw new I("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let i=es({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==i&&"CI_RESOURCE_STARVATION_SUSPECTED"!==i}},{deadline:i,phase:"boot",classifyReason:e=>es({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(a){let n=es({error:a,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new I("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:t0,elapsedMs:i.elapsedMs(),reason:n,hint:el(n),boot:t,bootstatus:r})}}async function rX(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?tU(["list","devices","-j"]):tB(e,["list","devices","-j"]),i=await p("xcrun",r,{allowFailure:!0,timeoutMs:t1});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}let rY={settings:"com.apple.Preferences"},rZ=null;function rQ(e,t,r){return p("xcrun",tB(e,t),r)}function r0(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function r1(e){let t=n.join(e,"Info.plist");try{let e=await p("plutil",["-extract","CFBundleIdentifier","raw","-o","-",t],{allowFailure:!0});if(0!==e.exitCode)return;let r=String(e.stdout??"").trim();return r.length>0?r:void 0}catch{return}}function r2(e){return e.bundleId?`${e.bundleName}.app (${e.bundleId})`:`${e.bundleName}.app`}async function r3(e){await Promise.all(e.map(async e=>{void 0===e.bundleId&&(e.bundleId=await r1(e.installPath))}))}async function r4(e,t){if(".ipa"!==n.extname(e).toLowerCase())return{installPath:e,cleanup:async()=>{}};let r=await x.mkdtemp(n.join(F.tmpdir(),"agent-device-ios-ipa-")),i=async()=>{await x.rm(r,{recursive:!0,force:!0})};try{await p("ditto",["-x","-k",e,r]);let a=n.join(r,"Payload"),o=(await x.readdir(a,{withFileTypes:!0}).catch(()=>{throw new I("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:n.join(a,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===o.length)return{installPath:o[0].installPath,cleanup:i};if(0===o.length)throw new I("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await r3(o);let s=t?.appIdentifierHint?.trim();if(s){let e=s.toLowerCase(),t=o.filter(t=>t.bundleName.toLowerCase()===e);if(1===t.length)return{installPath:t[0].installPath,cleanup:i};if(t.length>1)throw new I("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${s}" by name. Use a bundle id hint instead.`);if(s.includes(".")){let t=o.filter(t=>t.bundleId?.toLowerCase()===e);if(1===t.length)return{installPath:t[0].installPath,cleanup:i}}throw new I("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload and none matched "${s}". Available bundles: ${o.map(r2).join(", ")}`)}throw new I("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${o.map(r2).join(", ")}`)}catch(e){throw await i(),e}}async function r8(e,t){let r=t.trim();if(r.includes("."))return r;let i=rY[r.toLowerCase()];if(i)return i;let n=("simulator"===e.kind?await id(e):await t8(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===n.length)return n[0].bundleId;if(n.length>1)throw new I("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:n});throw new I("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function r5(e,t,r){let i=r?.url?.trim();if(i){if(!ek(i))throw new I("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await rK(e),await p("open",["-a","Simulator"],{allowFailure:!0}),await rQ(e,["openurl",e.id,i]);return}let n=eO(r?.appBundleId??await r8(e,t),i);if(!n)throw new I("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await iA(e,n,{payloadUrl:i});return}let n=t.trim();if(ek(n)){if("simulator"===e.kind){await rK(e),await p("open",["-a","Simulator"],{allowFailure:!0}),await rQ(e,["openurl",e.id,n]);return}let t=eO(r?.appBundleId,n);if(!t)throw new I("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await iA(e,t,{payloadUrl:n});return}let a=r?.appBundleId??await r8(e,t);"simulator"===e.kind?await iv(e,a):await iA(e,a)}async function r6(e){"simulator"!==e.kind||"Booted"!==await rX(e)&&(await rK(e),await p("open",["-a","Simulator"],{allowFailure:!0}))}async function r9(e,t){let r=await r8(e,t);if("simulator"===e.kind){await rK(e);let t=tB(e,["terminate",e.id,r]),i=await p("xcrun",t,{allowFailure:!0});if(0!==i.exitCode){if(i.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new I("COMMAND_FAILED",`xcrun exited with code ${i.exitCode}`,{cmd:"xcrun",args:t,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}return}await t4(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function r7(e,t){let r=await r8(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],i=await p("xcrun",t,{allowFailure:!0,timeoutMs:t3});if(0!==i.exitCode){let n=String(i.stdout??""),a=String(i.stderr??"");if(!r0(`${n}
16
+ ${a}`.toLowerCase()))throw new I("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:i.exitCode,stdout:n,stderr:a,deviceId:e.id,hint:t6(n,a)??t5})}return{bundleId:r}}await rK(e);let i=await rQ(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==i.exitCode&&!r0(`${i.stdout}
17
+ ${i.stderr}`.toLowerCase()))throw new I("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return{bundleId:r}}async function ie(e,t,r){let{installPath:i,cleanup:n}=await r4(t,r);try{if("simulator"!==e.kind)return void await t4(["device","install","app","--device",e.id,i],{action:"install iOS app",deviceId:e.id});await rK(e),await rQ(e,["install",e.id,i])}finally{await n()}}async function it(e,t,r){let{bundleId:i}=await r7(e,t);return await ie(e,r,{appIdentifierHint:t}),{bundleId:i}}async function ir(e,t,r){if("simulator"===e.kind){await rK(e),await Y(async()=>{await rQ(e,["io",e.id,"screenshot",t])},{maxAttempts:3,baseDelayMs:700,maxDelayMs:2e3,shouldRetry:e=>(function(e){if(!(e instanceof I)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",i="string"==typeof t.stderr?t.stderr:"",n=`${e.message}
18
18
  ${r}
19
- ${i}`.toLowerCase();return n.includes("unknown option '--device'")||n.includes("unknown subcommand")&&n.includes("screenshot")||n.includes("unrecognized subcommand")&&n.includes("screenshot")}(e))throw e}let i=(await rp(e,{command:"screenshot",appBundleId:r})).message;if(!i)throw new I("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");let n={exitCode:1,stdout:"",stderr:""};for(let r of t7)if(0===(n=await p("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",i,"--destination",t,"--domain-type","appDataContainer","--domain-identifier",r],{allowFailure:!0})).exitCode)break;if(0!==n.exitCode){let e=n.stderr.trim()||n.stdout.trim()||`devicectl exited with code ${n.exitCode}`;throw new I("COMMAND_FAILED",`Failed to capture iOS screenshot: ${e}`)}}async function r3(e){rB(e,"clipboard"),await rq(e);let t=await rJ(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new I("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 r4(e,t){rB(e,"clipboard"),await rq(e);let r=await rJ(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new I("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function r8(e,t,r){rB(e,"push"),await rq(e);let i=await x.mkdtemp(n.join(F.tmpdir(),"agent-device-ios-push-")),a=n.join(i,"payload.apns");try{await x.writeFile(a,`${JSON.stringify(r)}
20
- `,"utf8"),await rJ(e,["push",e.id,t,a])}finally{await x.rm(i,{recursive:!0,force:!0})}}async function r5(e,t,r,i,n){rB(e,"settings"),await rq(e);let a=t.toLowerCase();switch(a){case"wifi":{let t=r7(r);await rJ(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(r7(r)?await rJ(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await rJ(e,["status_bar",e.id,"clear"]));case"location":{let t=r7(r);if(!i)throw new I("INVALID_ARGS","location setting requires an active app in session");await rJ(e,["privacy",e.id,t?"grant":"revoke","location",i]);return}case"faceid":case"touchid":{let t=it[a],i=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new I("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,a);await io(e,i,{settingName:a,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await ie(e,r);await rJ(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!i)throw new I("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=e$(r))?"revoke":o,a=function(e,t){let r=eF(e);if("photos"!==r&&t?.trim())throw new I("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 I("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new I("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(n?.permissionTarget,n?.permissionMode);await ir(e,t,a,i);return}default:throw new I("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function r6(e,t="all"){var r;return"simulator"===e.kind?(r=await r9(e),"user-installed"===t?r.filter(e=>!e.bundleId.startsWith("com.apple.")):r):await t0(e,t)}async function r9(e){let t=(await rJ(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 p("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 r7(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 I("INVALID_ARGS",`Invalid setting state: ${e}`)}async function ie(e,t){let r=eV(t);if("toggle"!==r)return r;let i=await rJ(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==i.exitCode)throw new I("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});let n=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
21
- ${t}`);if(!r)return null;let i=r[1].toLowerCase();return"dark"===i?"dark":"light"===i?"light":null}(i.stdout,i.stderr);if(!n)throw new I("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:i.stdout,stderr:i.stderr});return"dark"===n?"light":"dark"}let it={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function ir(e,t,r,i){let n=await ia(e);if(!n.has(r))throw new I("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(n).sort().join(", ")}`});let a=["privacy",e.id,t,r,i],o="notifications"===r;if(!("reset"===t&&o))try{await rJ(e,a);return}catch(t){if(!(o&&ii(t)))throw t;throw new I("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:i,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await rJ(e,a);return}catch(e){if(!ii(e))throw e}try{await rJ(e,["privacy",e.id,"reset","all",i])}catch(t){throw new I("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:i,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function ii(e){if(!(e instanceof I)||"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 ia(t){let r=en(t.simulatorSetPath),i=`${process.env.PATH??""}::${r??""}`;if(rH&&e===i)return rH;let n=await rJ(t,["privacy","help"],{allowFailure:!0}),a=function(e){let t=new Set,r=!1;for(let i of e.split("\n")){let e=i.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let n=/^([a-z-]+)\s+-\s+/.exec(e);n&&t.add(n[1])}return t}(`${n.stdout}
22
- ${n.stderr}`);if(0===a.size)throw new I("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return rH=a,e=i,a}async function io(e,t,r){let i=function(e,t,r){let i=r.length>0?r:["face"];switch(t){case"match":return i.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return i.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),n=[];for(let t of i){let r=t$(e,t),i=await p("xcrun",r,{allowFailure:!0});if(0===i.exitCode)return;n.push({args:r,stderr:i.stderr,stdout:i.stdout,exitCode:i.exitCode})}let a=n.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(n.length>0&&n.every(e=>{var t,r;let i;return t=e.stdout,r=e.stderr,(i=`${t}
23
- ${r}`.toLowerCase()).includes("unrecognized subcommand")||i.includes("unknown subcommand")||i.includes("not supported")||i.includes("unavailable")||i.includes("biometric")&&i.includes("invalid")}))throw new I("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:a});throw new I("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:a})}function is(e){if(!(e instanceof I)||"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 il(e,t){await rq(e),await p("open",["-a","Simulator"],{allowFailure:!0});let r=X.fromTimeoutMs(tY);await Y(async({deadline:r})=>{if(r?.isExpired())throw new I("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:tY});let i=t$(e,["launch",e.id,t]),n=await p("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new I("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:30,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:is},{deadline:r})}async function id(e,t,r){let i=["device","process","launch","--device",e.id,t];r?.payloadUrl&&i.push("--payload-url",r.payloadUrl),await tQ(i,{action:"launch iOS app",deviceId:e.id})}let iu=/^[A-Za-z0-9_.:-]{1,64}$/;function ic(e,t){let r,i=t?.subject??"Payload",n=e.trim();if(!n)throw new I("INVALID_ARGS",`${i} cannot be empty`);let a=t?.expandPath?t.expandPath(n,t.cwd):n;try{if(!R.statSync(a).isFile())throw new I("INVALID_ARGS",`${i} path is not a file: ${a}`);return{kind:"file",path:a}}catch(t){if(t instanceof I)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new I("INVALID_ARGS",`${i} file is not readable: ${a}`);if(e&&"ENOENT"!==e)throw new I("COMMAND_FAILED",`Unable to read ${i} file: ${a}`,{cause:String(t)})}if((r=n.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:n};throw new I("INVALID_ARGS",`${i} file not found: ${a}`)}async function ip(e){let t=q(e.platform),r=en(e.iosSimulatorDeviceSet),i=eo(e.androidDeviceAllowlist);return await O("resolve_target_device",async()=>{let n={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(n.target&&!n.platform)throw new I("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|android|apple with --target mobile|tv.");if("android"===n.platform){await th();let e=await eA({serialAllowlist:i});return await j(e,n)}if("ios"===n.platform){let e=await tz({simulatorSetPath:r});return await j(e,n)}let a=[];try{a.push(...await eA({serialAllowlist:i}))}catch{}try{a.push(...await tz({simulatorSetPath:r}))}catch{}return await j(a,n)},{platform:t,target:e.target})}async function im(e,t,r,i,a){let o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>e0(e,t,r?.activity),openDevice:()=>e2(e),close:t=>e3(e,t),tap:(t,r)=>e6(e,t,r),doubleTap:async(t,r)=>{await e6(e,t,r),await e6(e,t,r)},swipe:(t,r,i,n,a)=>e9(e,t,r,i,n,a),longPress:(t,r,i)=>tr(e,t,r,i),focus:(t,r)=>to(e,t,r),type:t=>ti(e,t),fill:(t,r,i)=>ts(e,t,r,i),scroll:(t,r)=>tl(e,t,r),scrollIntoView:t=>td(e,t),screenshot:(t,r)=>tu(e,t)};case"ios":var r,i;let n,a;return{open:(t,r)=>rX(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>rY(e),close:t=>rZ(e,t),screenshot:(t,r)=>r2(e,t,r),...(r=e,n={verbose:(i=t).verbose,logPath:i.logPath,traceLogPath:i.traceLogPath,requestId:i.requestId},a=()=>{if(t8(i.requestId))throw new I("COMMAND_FAILED","request canceled")},{tap:async(e,t)=>{await rp(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},n)},doubleTap:async(e,t)=>{await rp(r,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:i.appBundleId},n)},swipe:async(e,t,a,o,s)=>{await rp(r,{command:"drag",x:e,y:t,x2:a,y2:o,durationMs:s,appBundleId:i.appBundleId},n)},longPress:async(e,t,a)=>{await rp(r,{command:"longPress",x:e,y:t,durationMs:a,appBundleId:i.appBundleId},n)},focus:async(e,t)=>{await rp(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},n)},type:async e=>{await rp(r,{command:"type",text:e,appBundleId:i.appBundleId},n)},fill:async(e,t,a)=>{await rp(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},n),await rp(r,{command:"type",text:a,clearFirst:!0,appBundleId:i.appBundleId},n)},scroll:async(e,t)=>{if(!["up","down","left","right"].includes(e))throw new I("INVALID_ARGS",`Unknown direction: ${e}`);let a=function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left"}}(e);await rp(r,{command:"swipe",direction:a,appBundleId:i.appBundleId},n)},scrollIntoView:async e=>{let t=await rp(r,{command:"findText",text:e,appBundleId:i.appBundleId},n);if(t?.found)return{attempts:1};for(let t=0;t<12;t+=1){for(let e=0;e<4;e+=1)a(),await rp(r,{command:"swipe",direction:"up",appBundleId:i.appBundleId},n),await new Promise(e=>setTimeout(e,80));a();let o=await rp(r,{command:"findText",text:e,appBundleId:i.appBundleId},n);if(o?.found)return{attempts:t+2}}throw new I("COMMAND_FAILED",`scrollintoview could not find text: ${e}`)}})};default:throw new I("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,{requestId:a?.requestId,appBundleId:a?.appBundleId,verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath});return M({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await O("platform_command",async()=>{var s,l,d,u,c,p;switch(t){case"open":{let t=r[0],i=r[1];if(r.length>2)throw new I("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null};if(void 0!==i){if("ios"!==e.platform)throw new I("INVALID_ARGS","open <app> <url> is supported only on iOS");if(ek(t))throw new I("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!ek(i))throw new I("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:a?.activity,appBundleId:a?.appBundleId,url:i}),{app:t,url:i}}return await o.open(t,{activity:a?.activity,appBundleId:a?.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,i]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(i))throw new I("INVALID_ARGS","press requires x y");let n=iw(a?.count??1,"count",1,200),c=iw(a?.intervalMs??0,"interval-ms",0,1e4),p=iw(a?.holdMs??0,"hold-ms",0,1e4),f=iw(a?.jitterPx??0,"jitter-px",0,100),m=a?.doubleTap===!0;if(m&&p>0)throw new I("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(m&&f>0)throw new I("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(s=e,l=n,d=p,u=f,"ios"===s.platform&&l>1&&0===d&&0===u)return await rp(e,{command:"tapSeries",x:t,y:i,count:n,intervalMs:c,doubleTap:m,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x:t,y:i,count:n,intervalMs:c,holdMs:p,jitterPx:f,doubleTap:m,timingMode:"runner-series"};return await iv(n,c,async e=>{let[r,n]=function(e,t){if(t<=0)return[0,0];let[r,i]=ih[e%ih.length];return[r*t,i*t]}(e,f),a=t+r,s=i+n;m?await o.doubleTap(a,s):p>0?await o.longPress(a,s,p):await o.tap(a,s)}),{x:t,y:i,count:n,intervalMs:c,holdMs:p,jitterPx:f,doubleTap:m}}case"swipe":{let t=Number(r[0]),i=Number(r[1]),n=Number(r[2]),s=Number(r[3]);if([t,i,n,s].some(Number.isNaN))throw new I("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=iw(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=iw(a?.count??1,"count",1,200),f=iw(a?.pauseMs??0,"pause-ms",0,1e4),m=a?.pattern??"one-way";if("one-way"!==m&&"ping-pong"!==m)throw new I("INVALID_ARGS",`Invalid pattern: ${m}`);if(c=e,p=u,"ios"===c.platform&&p>1)return await rp(e,{command:"dragSeries",x:t,y:i,x2:n,y2:s,durationMs:d,count:u,pauseMs:f,pattern:m,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x1:t,y1:i,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:f,pattern:m};return await iv(u,f,async e=>{"ping-pong"===m&&e%2==1?await o.swipe(n,s,t,i,d):await o.swipe(t,i,n,s,d)}),{x1:t,y1:i,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:f,pattern:m}}case"longpress":{let e=Number(r[0]),t=Number(r[1]),i=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new I("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,i),{x:e,y:t,durationMs:i}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new I("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 I("INVALID_ARGS","type requires text");return await o.type(e),{text:e}}case"fill":{let e=Number(r[0]),t=Number(r[1]),i=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!i)throw new I("INVALID_ARGS","fill requires x y text");return await o.fill(e,t,i),{x:e,y:t,text:i}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0;if(!e)throw new I("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 I("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 I("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");let t=Number(r[0]),i=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new I("INVALID_ARGS","pinch requires scale > 0");return await rp(e,{command:"pinch",scale:t,x:i,y:n,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{scale:t,x:i,y:n}}case"trigger-app-event":{let{eventName:t,payload:i}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new I("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!iu.test(t))throw new I("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 I("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let i=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new I("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let i=JSON.stringify(r);if(Buffer.byteLength(i,"utf8")>8192)throw new I("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof I)throw t;throw new I("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:i}}(r),n=function(e,t,r){let i,n=(i=("ios"===e?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new I("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 a=r?JSON.stringify(r):"",o=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(a)).replaceAll("{platform}",encodeURIComponent(e));if(o.length>4096)throw new I("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:o.length,maxLength:4096});return o}(e.platform,t,i);return await o.open(n,{appBundleId:a?.appBundleId}),{event:t,eventUrl:n,transport:"deep-link"}}case"screenshot":{let e=r[0]??i??`./screenshot-${Date.now()}.png`;return await x.mkdir(n.dirname(e),{recursive:!0}),await o.screenshot(e,a?.appBundleId),{path:e}}case"back":if("ios"===e.platform)return await rp(e,{command:"back",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"back"};return await e7(e),{action:"back"};case"home":if("ios"===e.platform)return await rp(e,{command:"home",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"home"};return await te(e),{action:"home"};case"app-switcher":if("ios"===e.platform)return await rp(e,{command:"appSwitcher",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"app-switcher"};return await tt(e),{action:"app-switcher"};case"clipboard":{let t=(r[0]??"").toLowerCase();if("read"!==t&&"write"!==t)throw new I("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===t){if(1!==r.length)throw new I("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:t,text:"ios"===e.platform?await r3(e):await tn(e)}}if(r.length<2)throw new I("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let i=r.slice(1).join(" ");return"ios"===e.platform?await r4(e,i):await ta(e,i),{action:t,textLength:Array.from(i).length}}case"keyboard":{if("android"!==e.platform)throw new I("UNSUPPORTED_OPERATION","keyboard is currently supported only on Android");let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new I("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new I("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("dismiss"===t){let t=await eZ(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let i=await eY(e);return{platform:"android",action:"status",visible:i.visible,inputType:i.inputType,type:i.type}}case"settings":{let[t,i,n,o,s]=r,l="permission"===t?{permissionTarget:n,permissionMode:o}:void 0;if(M({level:"debug",phase:"settings_apply",data:{setting:t,state:i,target:n,mode:o,platform:e.platform}}),"ios"===e.platform)return await r5(e,t,i,s??a?.appBundleId,l),{setting:t,state:i};return await tc(e,t,i,s??a?.appBundleId,l),{setting:t,state:i}}case"push":{let t=r[0]?.trim(),i=r[1]?.trim();if(!t||!i)throw new I("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let n=await ig(i);if("ios"===e.platform)return await r8(e,t,n),{platform:"ios",bundleId:t};let a=await tf(e,t,n);return{platform:"android",package:t,action:a.action,extrasCount:a.extrasCount}}case"snapshot":{if("ios"===e.platform){let t=await O("snapshot_capture",async()=>await rp(e,{command:"snapshot",appBundleId:a?.appBundleId,interactiveOnly:a?.snapshotInteractiveOnly,compact:a?.snapshotCompact,depth:a?.snapshotDepth,scope:a?.snapshotScope,raw:a?.snapshotRaw},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new I("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await O("snapshot_capture",async()=>await tm(e,{interactiveOnly:a?.snapshotInteractiveOnly,compact:a?.snapshotCompact,depth:a?.snapshotDepth,scope:a?.snapshotScope,raw:a?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}default:throw new I("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}let ih=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function iw(e,t,r,i){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>i)throw new I("INVALID_ARGS",`${t} must be an integer between ${r} and ${i}`);return e}async function ig(e){let t=ic(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await iI(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new I("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof I)throw t;throw new I("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function iI(e){try{return await x.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new I("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new I("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new I("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new I("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}async function iv(e,t,r){for(let i=0;i<e;i+=1)await r(i),i<e-1&&t>0&&await iA(t)}async function iA(e){await new Promise(t=>setTimeout(t,e))}let iy={alert:{ios:{simulator:!0},android:{}},pinch:{ios:{simulator:!0},android:{}},"app-switcher":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},apps:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},click:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},keyboard:{ios:{},android:{emulator:!0,device:!0,unknown:!0}},close:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},logs:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},reinstall:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},press:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},record:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},snapshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function iN(e,t){let r=iy[e];if(!r)return!0;let i=r[t.platform];return!!i&&!0===i[t.kind??"unknown"]}function iS(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 ib(e){let t=new Set,r=[];for(let i of e)t.has(i)||(t.add(i),r.push(i));return r}let i_=/^-?\d+(\.\d+)?$/,iD=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),iE=new Map([["--count","count"],["--pause-ms","pauseMs"]]);function ik(e){return"click"===e||"press"===e}function iO(e){let t=e.trim();return t.startsWith("@")||i_.test(t)?t:JSON.stringify(t)}function iM(e,t){let r=t.flags??{};if(ik(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");return}"swipe"===t.command&&("number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern))}function iL(e,t){let r=[],i={},n=ik(e)?iD:"swipe"===e?iE:void 0;for(let a=0;a<t.length;a+=1){let o=t[a];if(ik(e)&&"--double-tap"===o){i.doubleTap=!0;continue}let s=n?.get(o);if(s&&a+1<t.length){let e=function(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}(t[a+1]);null!==e&&(i[s]=e),a+=1;continue}if("swipe"===e&&"--pattern"===o&&a+1<t.length){let e=t[a+1];("one-way"===e||"ping-pong"===e)&&(i.pattern=e),a+=1;continue}r.push(o)}return{positionals:r,flags:i}}class ix{sessions=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.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=ix.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:i,serial:n,out:a,verbose:o,snapshotInteractiveOnly:s,snapshotCompact:l,snapshotDepth:d,snapshotScope:u,snapshotRaw:c,relaunch:p,saveScript:f,noRecord:m,count:h,intervalMs:w,holdMs:g,jitterPx:I,doubleTap:v,pauseMs:A,pattern:y}=e;return{platform:t,device:r,udid:i,serial:n,out:a,verbose:o,snapshotInteractiveOnly:s,snapshotCompact:l,snapshotDepth:d,snapshotScope:u,snapshotRaw:c,relaunch:p,saveScript:f,noRecord:m,count:h,intervalMs:w,holdMs:g,jitterPx:I,doubleTap:v,pauseMs:A,pattern:y}}(t.flags),result:t.result}),M({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=n.dirname(t);R.existsSync(r)||R.mkdirSync(r,{recursive:!0});let i=function(e,t){let r=[],i=e.device.name.replace(/"/g,'\\"'),n=e.device.kind?` kind=${e.device.kind}`:"";for(let a of(r.push(`context platform=${e.device.platform} device="${i}"${n} theme=unknown`),t))a.flags?.noRecord||r.push(function(e){let t=[e.command];if(ik(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(iO(r));let i=e.result?.refLabel;return"string"==typeof i&&i.trim().length>0&&t.push(iO(i)),iM(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(iO(r)),iM(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(iO(r));let i=e.result?.refLabel,n=e.positionals.slice(1).join(" ");return"string"==typeof i&&i.trim().length>0&&t.push(iO(i)),n&&t.push(iO(n)),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],i=e.positionals?.[1];if(r&&i){if(t.push(iO(r)),t.push(iO(i)),i.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(iO(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",iO(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(iO(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}for(let r of e.positionals??[])t.push(iO(r));return iM(t,e),t.join(" ")}(a));return`${r.join("\n")}
24
- `}(e,this.buildOptimizedActions(e));R.writeFileSync(t,i)}catch{}}defaultTracePath(e){let t=ix.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return n.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return n.join(this.sessionsDir,ix.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return n.join(this.sessionsDir,ix.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return e.startsWith("~/")?n.join(F.homedir(),e.slice(2)):t&&!n.isAbsolute(e)?n.resolve(t,e):n.resolve(e)}resolveScriptPath(e){if(e.saveScriptPath)return ix.expandHome(e.saveScriptPath);R.existsSync(this.sessionsDir)||R.mkdirSync(this.sessionsDir,{recursive:!0});let t=ix.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return n.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let i=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(i.length>0&&(ik(r.command)||"fill"===r.command||"get"===r.command)){let e=i.join(" || ");if(ik(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let i=iS(r);if(i.length>0){t.push({...r,positionals:[e,i]});continue}}if("get"===r.command){let i=r.positionals?.[0];if("text"===i||"attrs"===i){t.push({...r,positionals:[i,e]});continue}}}if(ik(r.command)||"fill"===r.command||"get"===r.command){let i=r.result?.refLabel;"string"==typeof i&&i.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:i.trim()},result:{scope:i.trim()}})}t.push(r)}return t}}function iC(e,t,r,i,n){return{requestId:n??k().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:i,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,count:t?.count,intervalMs:t?.intervalMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,doubleTap:t?.doubleTap,pauseMs:t?.pauseMs,pattern:t?.pattern}}let iT=tR(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function iR(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:rq}));await t(e);return}if("device"===e.kind)return void await iP(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:eE}));await t(e.id)}}async function iP(e){let t=n.join(F.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(iT/1e3));try{let i=await p("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:iT+3e3}),n=String(i.stdout??""),a=String(i.stderr??""),o=await i$(t);if(0===i.exitCode){if(!o.parsed)throw new I("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:n,stderr:a,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 I("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 I("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:n,stderr:a,exitCode:i.exitCode,tunnelState:o?.tunnelState,hint:iF(n,a)})}catch(t){if(t instanceof I&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},i=String(r.stdout??""),n=String(r.stderr??""),a=Number(r.timeoutMs??iT),o=`CoreDevice did not respond within ${a}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new I("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:a,stdout:i,stderr:n,hint:i||n?iF(i,n):o},t)}throw new I("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 i$(e){try{let t=await x.readFile(e,"utf8"),r=JSON.parse(t),i=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,i=t.device?.connectionProperties?.tunnelState,n="string"==typeof r?r:"string"==typeof i?i:void 0;return n?{tunnelState:n}:{}}(r);return{parsed:!0,tunnelState:i.tunnelState}}catch{return{parsed:!1}}}function iF(e,t){let r=t2(e,t);return r||(`${e}
25
- ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":t1)}function iV(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function iU(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function iG(e,t){return e.find(e=>e.ref===t)??null}function iB(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function iq(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),i=(e.value??"").toLowerCase(),n=(e.identifier??"").toLowerCase();return t.includes(r)||i.includes(r)||n.includes(r)})??null}function ij(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&&iW(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,i=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!iW(t))continue;let n=Math.abs(e.rect.y+e.rect.height/2-r);(!i||n<i.distance)&&(i={label:t,distance:n})}return i?.label}(e,t)??(r&&iW(r)?r:void 0)}function iW(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function iH(e){let t=[],r=[];for(let i of e){let e=i.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let n=iJ(i.type??""),a=[i.label,i.value,i.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!a&&iW(a);if(("group"===n||"ioscontentgroup"===n)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...i,depth:s})}return r}function iJ(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 iz(e,t){let r=iJ(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 iK(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let iX=new Set(["id","role","text","label","value"]),iY=new Set(["visible","hidden","editable","selected","enabled","hittable"]),iZ=new Set([...iX,...iY]);function iQ(e){let t=e.trim();if(!t)throw new I("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",i=null;for(let n=0;n<e.length;n+=1){let a=e[n];if(('"'===a||"'"===a)&&!ns(e,n)){i?i===a&&(i=null):i=a,r+=a;continue}if(!i&&"|"===a&&"|"===e[n+1]){let i=r.trim();if(!i)throw new I("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(i),r="",n+=1;continue}r+=a}let n=r.trim();if(!n)throw new I("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(n),t}(t);if(0===r.length)throw new I("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new I("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",i=null;for(let n=0;n<e.length;n+=1){let a=e[n];if(('"'===a||"'"===a)&&!ns(e,n)){i?i===a&&(i=null):i=a,r+=a;continue}if(!i&&/\s/.test(a)){r.trim().length>0&&t.push(r.trim()),r="";continue}r+=a}if(i)throw new I("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim().length>0&&t.push(r.trim()),t}(t);if(0===r.length)throw new I("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(i7)}})(e))}}function i0(e){try{return iQ(e)}catch{return null}}function i1(e,t,r){let i=r.requireRect??!1,n=r.requireUnique??!0,a=r.disambiguateAmbiguous??!1,o=[];for(let s=0;s<t.selectors.length;s+=1){let l=t.selectors[s],d=function(e,t,r){let i=0,n=null,a=null,o=!1;for(let s of e){if(r.requireRect&&!s.rect||!ne(s,t,r.platform))continue;if(i+=1,n||(n=s),!a){a=s;continue}let e=function(e,t){let r=e.depth??0,i=t.depth??0;if(r!==i)return r>i?1:-1;let n=no(e),a=no(t);return n!==a?n<a?1:-1:0}(s,a);if(e>0){a=s,o=!1;continue}0===e&&(o=!0)}return{count:i,firstNode:n,disambiguated:o?null:a}}(e,l,{platform:r.platform,requireRect:i});if(o.push({selector:l.raw,matches:d.count}),0!==d.count&&d.firstNode){if(n&&1!==d.count){if(!a)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 i2(e,t,r){let i=r.requireRect??!1,n=[];for(let a=0;a<t.selectors.length;a+=1){let o=t.selectors[a],s=function(e,t,r){let i=0;for(let n of e)(!r.requireRect||n.rect)&&ne(n,t,r.platform)&&(i+=1);return i}(e,o,{platform:r.platform,requireRect:i});if(n.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:a,selector:o,matches:s,diagnostics:n}}return null}function i3(e,t,r){let i=r.unique??!0;if(0===t.length)return`Selector did not match: ${e.raw}`;let n=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return i?`Selector did not resolve uniquely (${n})`:`Selector did not match (${n})`}function i4(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,i=0,n=[];for(;i<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return iZ.has(e)}return iZ.has(t.toLowerCase())}(e[i]);){i+=1;let t=e.slice(0,i).join(" ").trim();t&&i0(t)&&n.push(i)}if(0===n.length)return null;let a=n[n.length-1];if(r){for(let t=n.length-1;t>=0;t-=1)if(n[t]<e.length){a=n[t];break}}let o=e.slice(0,a).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(a)}:null}function i8(e){let t=e[0]??"",r=i4(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function i5(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function i6(e,t){return iz(e.type??"",t)&&!1!==e.enabled}function i9(e,t,r={}){let i=[],n=iJ(e.type??""),a=na(e.identifier),o=na(e.label),s=na(e.value),l=na(iK(e)),d="fill"===r.action;a&&i.push(`id=${nn(a)}`),n&&o&&i.push(d?`role=${nn(n)} label=${nn(o)} editable=true`:`role=${nn(n)} label=${nn(o)}`),o&&i.push(d?`label=${nn(o)} editable=true`:`label=${nn(o)}`),s&&i.push(d?`value=${nn(s)} editable=true`:`value=${nn(s)}`),l&&l!==o&&l!==s&&i.push(d?`text=${nn(l)} editable=true`:`text=${nn(l)}`),n&&d&&!i.some(e=>e.includes("editable=true"))&&i.push(`role=${nn(n)} editable=true`);let u=ib(i);return 0===u.length&&n&&u.push(d?`role=${nn(n)} editable=true`:`role=${nn(n)}`),0===u.length&&i5(e)&&u.push("visible=true"),u}function i7(e){let t=e.trim();if(!t)throw new I("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!iY.has(r))throw new I("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let i=t.slice(0,r).trim().toLowerCase(),n=t.slice(r+1).trim();if(!iZ.has(i))throw new I("INVALID_ARGS",`Unknown selector key: ${i}`);if(!n)throw new I("INVALID_ARGS",`Missing selector value for key: ${i}`);if(iY.has(i)){let e,t="true"===(e=nt(n).toLowerCase())||"false"!==e&&null;if(null===t)throw new I("INVALID_ARGS",`Invalid boolean value for ${i}: ${n}`);return{key:i,value:t}}return{key:i,value:nt(n)}}function ne(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return nr(e.identifier,String(t.value));case"role":var i,n;return i=e.type,n=String(t.value),function(e){return iJ(e)}(i??"")===function(e){return iJ(e)}(n);case"label":return nr(e.label,String(t.value));case"value":return nr(e.value,String(t.value));case"text":{let r=ni(String(t.value));return ni(iK(e))===r}case"visible":return i5(e)===!!t.value;case"hidden":return!i5(e)==!!t.value;case"editable":return i6(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 nt(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function nr(e,t){return ni(e??"")===ni(t)}function ni(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function nn(e){return JSON.stringify(e)}function na(e){if(!e)return null;let t=e.trim();return t||null}function no(e){return e.rect?e.rect.width*e.rect.height:1/0}function ns(e,t){let r=0;for(let i=t-1;i>=0&&"\\"===e[i];i-=1)r+=1;return r%2==1}function nl(e,t){let r=process.env[e];if(!r)return t;let i=Number.parseInt(r,10);return Number.isInteger(i)&&i>0?i:t}function nd(e,t){if(!e)return;let r=n.dirname(e);R.existsSync(r)||R.mkdirSync(r,{recursive:!0});let i={pid:t,startTime:T(t)??void 0,command:a(t)??void 0};R.writeFileSync(e,`${JSON.stringify(i)}
26
- `)}function nu(e){if(e&&R.existsSync(e))try{R.unlinkSync(e)}catch{}}function nc(e){let t=n.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}`,i=`${e}.${r}`;R.existsSync(t)&&(R.existsSync(i)&&R.unlinkSync(i),R.renameSync(t,i))}}(e,{maxBytes:nl("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:nl("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function np(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function nf(e){await new Promise(t=>setTimeout(t,e))}function nm(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],i="",n=i=>{(!(r.length>0)||r.some(e=>i.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(i,t.redactionPatterns))};return{onChunk:e=>{let t=`${i}${e}`.split("\n");for(let e of(i=t.pop()??"",t))n(`${e}
27
- `)},flush:()=>{i&&(n(i),i="")}}}function nh(e,t,r){let i=e.stdout,n=e.stderr;return i&&n?(i.setEncoding("utf8"),n.setEncoding("utf8"),i.on("data",r.writer.onChunk),n.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(i=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),i({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function nw(e,t){let r=(await p("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function ng(e,t,r,i){let n="active",a=h("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=nm(t,{redactionPatterns:r});"number"==typeof a.pid&&nd(i,a.pid);let s=nh(a,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),nu(i),e));return{backend:"ios-simulator",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{a.killed||a.kill("SIGINT"),await np(s),a.killed||a.kill("SIGKILL"),await np(s),nu(i)}}}async function nI(e,t,r,i){let n="active",a=h("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=nm(t,{redactionPatterns:r});"number"==typeof a.pid&&nd(i,a.pid);let s=nh(a,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),nu(i),e));return{backend:"ios-device",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{a.killed||a.kill("SIGINT"),await np(s),a.killed||a.kill("SIGKILL"),await np(s),nu(i)}}}async function nv(e,t,r,i,n){let a,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await nw(e,t);if(!d){await nf(1e3);continue}let u=h("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});a=u;let c=nm(r,{redactionPatterns:i});o=nh(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&nd(n,u.pid);let p=await o;if(nu(n),a=void 0,o=void 0,l)break;0!==p.exitCode&&(s="failed"),await nf(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),nu(n)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,a&&!a.killed&&a.kill("SIGINT"),o&&await np(o),a&&!a.killed&&a.kill("SIGKILL"),await np(d),nu(n)}}}async function nA(e,t,r,i){nc(r);let n=R.createWriteStream(r,{flags:"a"}),a=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 nI(e.id,n,a,i):await ng(t,n,a,i);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new I("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await nv(e.id,t,n,a,i)}throw n.end(),new I("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function ny(e){await e.stop(),await np(e.wait)}async function nN(e,t){let r={},i=[];if(t||i.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await p("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await p("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 p("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 p("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}return{checks:r,notes:i}}function nS(e){let t=n.dirname(e),r=n.basename(e);R.existsSync(t)||R.mkdirSync(t,{recursive:!0}),R.existsSync(e)?R.truncateSync(e,0):R.writeFileSync(e,"","utf8");let i=0;for(let e of R.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let a=e.slice(r.length+1);if(/^\d+$/.test(a))try{R.unlinkSync(n.join(t,e)),i+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:i}}let nb=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),n_=/https?:\/\/[^\s"'<>\])]+/i,nD=[/\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 nE(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 nk(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return nO(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(i?.[1])return i[1].trim()}}function nO(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function nM(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function nL(e,t,r,i){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(i,e)):t}let nx='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',nC=["platform","target","device","udid","serial","verbose","out"],nT=["platform","target","device","udid","serial","verbose","out"],nR=["path","start","stop","doctor","mark","clear"],nP=`logs requires ${nR.slice(0,-1).join(", ")}, or ${nR.at(-1)}`,n$="Not implemented for this platform in this release.",nF="open-command-roundtrip";function nV(e){let{sessionName:t,appName:r,appBundleId:i,startup:n}=e,a={session:t};return r&&(a.appName=r),i&&(a.appBundleId=i),n&&(a.startup=n),a}function nU(e,t,r){return{durationMs:Math.max(0,Date.now()-e),measuredAt:new Date().toISOString(),method:nF,appTarget:t,appBundleId:r}}let nG=["dump","log"],nB=`network requires ${nG.join(" or ")}`,nq=["summary","headers","body","all"],nj=`network include mode must be one of: ${nq.join(", ")}`;function nW(e,t,r){return t||nH(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function nH(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}async function nJ(e){let t=nH(e.flags)||!e.session?await e.resolveTargetDeviceFn(e.flags??{}):e.session.device;return!1!==e.ensureReady&&await e.ensureReadyFn(t),t}function nz(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 nK=async({avdName:e,serial:t,headless:r})=>{let{ensureAndroidEmulatorBooted:i}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:eD}));return await i({avdName:e,serial:t,headless:r})};async function nX(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:a,resolveDevice:o,dispatch:s,command:l,positionals:d,recordPositionals:u,deriveNextSession:c}=e,p=n.get(r),f=t.flags??{},m=nW(l,p,f);if(m)return m;let h=await nJ({session:p,flags:f,ensureReadyFn:a,resolveTargetDeviceFn:o,ensureReady:!0});if(!iN(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,{...iC(i,t.flags,p?.appBundleId,p?.trace?.outPath)});if(p){let e=c?await c(p,w,h):p;n.recordAction(e,{command:l,positionals:u??d,flags:t.flags??{},result:w??{}}),e!==p&&n.set(r,e)}return{ok:!0,data:w??{}}}let nY={ios:async(e,t,r)=>{let{reinstallIosApp:i}=await Promise.resolve().then(()=>({reinstallIosApp:r1}));return await i(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:i}=await Promise.resolve().then(()=>({reinstallAndroidApp:e5}));return await i(e,t,r)}};async function nZ(e,t,r){if("ios"===e.platform&&t)return ek(t)?"device"===e.kind?eO(r,t):void 0:await nQ(e,t)}async function nQ(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:rK}));return await r(e,t)}catch{return}}async function n0(e,t){if(!("android"!==e.platform||!t||ek(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:eW})),i=await r(e,t);return"package"===i.type?i.value:void 0}catch{return}}async function n1(e,t,r,i){return await nZ(e,t,r)??await i(e,t)??("android"===e.platform&&t&&ek(t)?r:void 0)}async function n2(e){let{req:t,sessionName:r,sessionStore:i,ensureReady:n,resolveDevice:a}=e,o=i.get(r),s=t.flags??{},l=q(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=nW("appstate",o,s);if(d)return d;let u=o?.device.platform==="ios"&&function(e,t){if(!t)return!1;if(!nH(e))return!0;let r=q(e?.platform);return!(r&&r!==t.device.platform||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(s,o);if("ios"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:nx}};if(u){let e=o.appName??o.appBundleId;return o.appName||o.appBundleId?{ok:!0,data:{platform:"ios",appName:e??"unknown",appBundleId:o.appBundleId,source:"session"}}:{ok:!1,error:{code:"COMMAND_FAILED",message:"No foreground app is tracked for this iOS session. Open an app in the session, then retry appstate."}}}let c=await nJ({session:o,flags:s,ensureReadyFn:n,resolveTargetDeviceFn:a,ensureReady:!0});if("ios"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:nx}};let{getAndroidAppState:p}=await Promise.resolve().then(()=>({getAndroidAppState:eX})),f=await p(c);return{ok:!0,data:{platform:"android",package:f.package,activity:f.activity}}}async function n3(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:a,resolveDevice:o,dispatch:s}=e,l=n.get(r),d=t.flags??{},u=nW("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 nJ({session:l,flags:d,ensureReadyFn:a,resolveTargetDeviceFn:o,ensureReady:!0});if(!iN("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,{...iC(i,t.flags,l?.appBundleId,l?.trace?.outPath)});return l&&n.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:f??{}}),{ok:!0,data:{platform:p.platform,...f??{}}}}async function n4(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,invoke:a,dispatch:o,ensureReady:s,resolveTargetDevice:l,reinstallOps:d=nY,stopIosRunner:u,appLogOps:c={start:nA,stop:ny},ensureAndroidEmulatorBoot:p=nK,resolveAndroidPackageForOpen:f=n0}=e,m=o??im,h=s??iR,g=l??ip,v=t.command;if("session_list"===v)return{ok:!0,data:{sessions:n.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",device:e.device.name,id:e.device.id,createdAt:e.createdAt}))}};if("devices"===v)try{let e=[],r=en(t.flags?.iosSimulatorDeviceSet),i=eo(t.flags?.androidDeviceAllowlist),n=q(t.flags?.platform);if("android"===n){let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:eA}));e.push(...await t({serialAllowlist:i}))}else if("ios"===n){let{listIosDevices:t}=await Promise.resolve().then(()=>({listIosDevices:tz}));e.push(...await t({simulatorSetPath:r}))}else{let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:eA})),{listIosDevices:n}=await Promise.resolve().then(()=>({listIosDevices:tz}));try{e.push(...await t({serialAllowlist:i}))}catch{}try{e.push(...await n({simulatorSetPath:r}))}catch{}}let a=(t.flags?.target?e.filter(e=>(e.target??"mobile")===t.flags?.target):e).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:a}}}catch(t){let e=w(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===v){let e=n.get(r),i=t.flags??{},a=nW(v,e,i);if(a)return a;let o=await nJ({session:e,flags:i,ensureReadyFn:h,resolveTargetDeviceFn:g,ensureReady:!0});if(!iN("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if("ios"===o.platform){let{listIosApps:e}=await Promise.resolve().then(()=>({listIosApps:r6}));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:eH}));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"===v){let e,i=n.get(r),a=t.flags??{},o=nW(v,i,a);if(o)return o;let s="android"===(q(a.platform)??i?.device.platform),l=!0===a.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=nz({flags:a,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await nJ({session:i,flags:a,ensureReadyFn:h,resolveTargetDeviceFn:g,ensureReady:!1})}catch(r){let t=w(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 p({avdName:d,serial:a.serial,headless:l}),c=!0}if(a.target&&(e.target??"mobile")!==a.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${a.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=nz({flags:a,sessionDevice:i?.device,resolvedDevice:e});if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await p({avdName:t,serial:a.serial,headless:!0})}await h(e)}else("android"!==e.platform||!0!==e.booted)&&await h(e);return iN("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"===v)return await n2({req:t,sessionName:r,sessionStore:n,ensureReady:h,resolveDevice:g});if("clipboard"===v)return await n3({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:h,resolveDevice:g,dispatch:m});if("keyboard"===v)return await nX({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:h,resolveDevice:g,dispatch:m,command:"keyboard",positionals:t.positionals??[]});if("perf"===v){let e,t,i,a=n.get(r);return a?{ok:!0,data:(i=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===nF&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:nF,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)}(a.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:nF,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:nF},{session:a.name,platform:a.device.platform,device:a.device.name,deviceId:a.device.id,metrics:{startup:i,fps:{available:!1,reason:n$},memory:{available:!1,reason:n$},cpu:{available:!1,reason:n$}},sampling:{startup:{method:nF,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("reinstall"===v){let e,i=n.get(r),a=t.flags??{},o=nW(v,i,a);if(o)return o;let s=t.positionals?.[0]?.trim(),l=t.positionals?.[1]?.trim();if(!s||!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"reinstall requires: reinstall <app> <path-to-app-binary>"}};let u=ix.expandHome(l);if(!R.existsSync(u))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${u}`}};let c=await nJ({session:i,flags:a,ensureReadyFn:h,resolveTargetDeviceFn:g,ensureReady:!1});if(!iN("reinstall",c))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"reinstall is not supported on this device"}};if("ios"===c.platform){let t=await d.ios(c,s,u);e={platform:"ios",appId:t.bundleId,bundleId:t.bundleId}}else{let t=await d.android(c,s,u);e={platform:"android",appId:t.package,package:t.package}}let p={app:s,appPath:u,...e};return i&&n.recordAction(i,{command:v,positionals:t.positionals??[],flags:t.flags??{},result:p}),{ok:!0,data:p}}if("push"===v){let e,a=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();if(!a||!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}};let s="file"===(e=ic(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>ix.expandHome(e,t)})).kind?e.path:e.text;return await nX({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:h,resolveDevice:g,dispatch:m,command:"push",positionals:[a,s],recordPositionals:[a,o]})}if("trigger-app-event"===v)return await nX({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:h,resolveDevice:g,dispatch:m,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,i=r?await n1(e.device,r,e.appBundleId,f)??e.appBundleId:e.appBundleId;return{...e,appBundleId:i}}});if("open"===v){let e=t.flags?.relaunch===!0;if(n.has(r)){let a=n.get(r),o=t.positionals?.[0],s=o??(e?a?.appName:void 0);if(!a||!s)return e?{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app name or an active session app."}}:{ok:!1,error:{code:"INVALID_ARGS",message:"Session already active. Close it first or pass a new --session name."}};if(e&&ek(s))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};await h(a.device);let l=await n1(a.device,s,a.appBundleId,f),d=o?t.positionals??[]:[s];if(e){let e=l??s;await m(a.device,"close",[e],t.flags?.out,{...iC(i,t.flags,l??a.appBundleId,a.trace?.outPath)})}let u=Date.now();await m(a.device,"open",d,t.flags?.out,{...iC(i,t.flags,l)});let c=nU(u,s,l),p={...a,appBundleId:l,appName:s,recordSession:a.recordSession||!!t.flags?.saveScript,snapshot:void 0},w=nV({sessionName:r,appName:s,appBundleId:l,startup:c});return n.recordAction(p,{command:v,positionals:d,flags:t.flags??{},result:w}),n.set(r,p),{ok:!0,data:w}}let a=t.positionals?.[0];if(e&&!a)return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app argument."}};if(e&&a&&ek(a))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};let o=await g(t.flags??{}),s=n.toArray().find(e=>e.device.id===o.id);if(s)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${s.name}".`,details:{session:s.name,deviceId:o.id,deviceName:o.name}}};await h(o);let l=await n1(o,a,void 0,f);if(e&&a){let e=l??a;await m(o,"close",[e],t.flags?.out,{...iC(i,t.flags,l)})}let d=Date.now();await m(o,"open",t.positionals??[],t.flags?.out,{...iC(i,t.flags,l)});let u=a?nU(d,a,l):void 0,c={name:r,device:o,createdAt:Date.now(),appBundleId:l,appName:a,recordSession:!!t.flags?.saveScript,actions:[]},p=nV({sessionName:r,appName:a,appBundleId:l,startup:u});return n.recordAction(c,{command:v,positionals:t.positionals??[],flags:t.flags??{},result:p}),n.set(r,c),{ok:!0,data:p}}if("replay"===v){let e=t.positionals?.[0];if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};try{let o=ix.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 i=r+1,n=!1;for(;i<e.length;){let t=e[i];if('"'===t&&!n)break;n="\\"===t&&!n,"\\"!==t&&(n=!1),i+=1}if(i>=e.length)throw new I("INVALID_ARGS",`Invalid replay script line: ${e}`);let a=e.slice(r,i+1);t.push(JSON.parse(a)),r=i+1;continue}let i=r;for(;i<e.length&&!/\s/.test(e[i]);)i+=1;t.push(e.slice(r,i)),r=i}return t}(t);if(0===r.length)return null;let[i,...n]=r;if("context"===i)return null;let a={ts:Date.now(),command:i,positionals:[],flags:{}};if("snapshot"===i){a.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("-i"===t){a.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){a.flags.snapshotCompact=!0;continue}if("--raw"===t){a.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<n.length){let t=Number(n[e+1]);Number.isFinite(t)&&t>=0&&(a.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<n.length){a.flags.snapshotScope=n[e+1],e+=1;continue}if("--backend"===t&&e+1<n.length){e+=1;continue}}return a}if("open"===i){a.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("--relaunch"===t){a.flags.relaunch=!0;continue}a.positionals.push(t)}return a}if(ik(i)){let e=iL(i,n);if(Object.assign(a.flags,e.flags),0===e.positionals.length)return a;let t=e.positionals[0];if(t.startsWith("@"))return a.positionals=[t],e.positionals[1]&&(a.result={refLabel:e.positionals[1]}),a;let r=e.positionals[0],o=e.positionals[1];return ar(r)&&ar(o)&&e.positionals.length>=2?a.positionals=[r,o]:a.positionals=[e.positionals.join(" ")],a}if("fill"===i){if(n.length<2)return a.positionals=n,a;let e=n[0];return e.startsWith("@")?(n.length>=3?(a.positionals=[e,n.slice(2).join(" ")],a.result={refLabel:n[1]}):a.positionals=[e,n[1]],a):(a.positionals=[e,n.slice(1).join(" ")],a)}if("get"===i){if(n.length<2)return a.positionals=n,a;let e=n[0],t=n[1];return t.startsWith("@")?(a.positionals=[e,t],n[2]&&(a.result={refLabel:n[2]})):a.positionals=[e,n.slice(1).join(" ")],a}if("swipe"===i){let e=iL(i,n);return Object.assign(a.flags,e.flags),a.positionals=e.positionals,a}return a.positionals=n,a}(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 a({token:t.token,session:r,command:s.command,positionals:s.positionals??[],flags:n9(t.flags,s.flags),meta:t.meta});if(l.ok)continue;if(!u)return n6(l,s,e,o);let p=await n7({action:s,sessionName:r,logPath:i,sessionStore:n,dispatch:m});if(!p)return n6(l,s,e,o);if(d[e]=p,!(l=await a({token:t.token,session:r,command:p.command,positionals:p.positionals??[],flags:n9(t.flags,p.flags),meta:t.meta})).ok)return n6(l,p,e,o);c+=1}if(u&&c>0){let e=n.get(r);!function(e,t,r){let i=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",n=r.device.target?` target=${r.device.target}`:"";i.push(`context platform=${r.device.platform}${n} device="${e}"${t} theme=unknown`)}for(let e of t)i.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",iO(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(iO(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}for(let r of e.positionals??[])t.push(iO(r));return iM(t,e),t.join(" ")}(e));let n=`${i.join("\n")}
28
- `,a=`${e}.tmp-${process.pid}-${Date.now()}`;R.writeFileSync(a,n),R.renameSync(a,e)}(o,d,e)}return{ok:!0,data:{replayed:d.length,healed:c,session:r}}}catch(t){let e=w(t);return{ok:!1,error:{code:e.code,message:e.message}}}}if("logs"===v){let e=n.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};let i=(t.positionals?.[0]??"path").toLowerCase(),a=!!t.flags?.restart;if(!nR.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:nP}};if(a&&"clear"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===i){let t=n.resolveAppLogPath(r),i=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),a=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android");return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:a,sizeBytes:i.sizeBytes,modifiedAt:i.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===i){let t=n.resolveAppLogPath(r),i=await nN(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}if("mark"===i){let e,i=t.positionals?.slice(1).join(" ")??"",a=n.resolveAppLogPath(r);return nc(a),e=`[agent-device][mark][${new Date().toISOString()}] ${i.trim()||"marker"}
29
- `,R.appendFileSync(a,e,"utf8"),{ok:!0,data:{path:a,marked:!0}}}if("clear"===i){if(e.appLog&&!a)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(a){if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};if(!iN("logs",e.device))return{ok:!1,error:b(new I("UNSUPPORTED_OPERATION","logs is not supported on this device"))}}let t=n.resolveAppLogPath(r);if(a){e.appLog&&await c.stop(e.appLog);let i=nS(t),a=n.resolveAppLogPidPath(r);try{let o=await c.start(e.device,e.appBundleId,t,a),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 n.set(r,s),{ok:!0,data:{...i,restarted:!0}}}catch(i){let t=b(i);return n.set(r,{...e,appLog:void 0}),{ok:!1,error:t}}}return{ok:!0,data:nS(t)}}if("start"===i){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};if(!iN("logs",e.device))return{ok:!1,error:b(new I("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let t=n.resolveAppLogPath(r),i=n.resolveAppLogPidPath(r);try{let a=await c.start(e.device,e.appBundleId,t,i),o={...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:t,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}};return n.set(r,o),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:b(e)}}}if("stop"===i){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await c.stop(e.appLog),n.set(r,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===v){let e=n.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};let i=(t.positionals?.[0]??"dump").toLowerCase();if(!nG.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:nB}};let a=t.positionals?.[1],o=a?Number.parseInt(a,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(!nq.includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:nj}};let l=function(e,t){let r=nL(t?.maxEntries,25,1,200),i=t?.include??"summary",n=nL(t?.maxPayloadChars,2048,64,16384),a=nL(t?.maxScanLines,4e3,100,2e4);if(!R.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:a}};let o=R.readFileSync(e,"utf8").split("\n"),s=Math.max(0,o.length-a),l=o.slice(s),d=[];for(let e=l.length-1;e>=0&&d.length<r;e-=1){let t=l[e]?.trim();if(!t)continue;let r=function(e,t,r,i){let n=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let i=e.slice(t,r+1);try{let e=JSON.parse(i);return e&&"object"==typeof e?e:null}catch{return null}}(e),a=nE(n,["method","httpMethod"]),o=nE(n,["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}(n,["status","statusCode","responseCode"]),l=nb.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(a??d?.[1]??l?.[1])?.toUpperCase(),c=n_.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of nD){let r=t.exec(e);if(!r)continue;let i=Number.parseInt(r[1]??"",10);if(Number.isInteger(i))return i}return null}(e)??void 0,timestamp:function(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);return t?.[0]}(e),raw:nM(e,i),line:t};if("headers"===r||"all"===r){let t=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return nO(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,n);t&&(f.headers=nM(t,i))}if("body"===r||"all"===r){let t=nk(e,n,["requestBody","body","payload","request"]),r=nk(e,n,["responseBody","response"]);t&&(f.requestBody=nM(t,i)),r&&(f.responseBody=nM(r,i))}return f}(t,s+e+1,i,n);r&&d.push(r)}return{path:e,exists:!0,scannedLines:l.length,matchedLines:d.length,entries:d,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:a}}}(n.resolveAppLogPath(r),{maxEntries:o,include:s,maxPayloadChars:2048,maxScanLines:4e3}),d=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"),u=[];return e.appLog||u.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===l.entries.length&&u.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...l,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:d,notes:u}}}if("batch"===v)return await n8(t,r,a);if("close"===v){let e=n.get(r);return e?(e.appLog&&await c.stop(e.appLog),t.positionals&&t.positionals.length>0&&await m(e.device,"close",t.positionals??[],t.flags?.out,{...iC(i,t.flags,e.appBundleId,e.trace?.outPath)}),"ios"===e.device.platform&&await (u??rw)(e.device.id),n.recordAction(e,{command:v,positionals:t.positionals??[],flags:t.flags??{},result:{session:r}}),t.flags?.saveScript&&(e.recordSession=!0),n.writeSessionLog(e),n.delete(r),{ok:!0,data:{session:r}}):{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}}}return null}async function n8(e,t,r){let i=e.flags?.batchOnError??"stop";if("stop"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${i}.`}};let n=e.flags?.batchMaxSteps??L;if(!Number.isInteger(n)||n<1||n>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let i=o(e.flags?.batchSteps,n),a=Date.now(),s=[];for(let n=0;n<i.length;n+=1){let a=i[n],o=await n5(e,t,a,r,n+1);if(!o.ok)return{ok:!1,error:{code:o.error.code,message:`Batch failed at step ${o.step} (${a.command}): ${o.error.message}`,hint:o.error.hint,diagnosticId:o.error.diagnosticId,logPath:o.error.logPath,details:{...o.error.details??{},step:o.step,command:a.command,positionals:a.positionals,executed:n,total:i.length,partialResults:s}}};s.push(o.result)}return{ok:!0,data:{total:i.length,executed:i.length,totalDurationMs:Date.now()-a,results:s}}}catch(t){let e=w(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function n5(e,t,r,i,n){let a=Date.now(),o=await i({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:function(e,t){let r={...t??{}};delete r.batchSteps,delete r.batchOnError,delete r.batchMaxSteps;let i=e??{};for(let e of nC)void 0===r[e]&&void 0!==i[e]&&(r[e]=i[e]);return r}(e.flags,r.flags),meta:e.meta}),s=Date.now()-a;return o.ok?{ok:!0,step:n,result:{step:n,command:r.command,ok:!0,data:o.data??{},durationMs:s}}:{ok:!1,step:n,error:o.error}}function n6(e,t,r,i){if(e.ok)return e;let n=r+1,a=function(e){let t;return t=(e.positionals??[]).map(e=>iO(e)),[e.command,...t].join(" ")}(t),o={...e.error.details??{},replayPath:i,step:n,action:t.command,positionals:t.positionals??[]};return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${n} (${a}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:o}}}function n9(e,t){let r={...t??{}},i=e??{};for(let e of nT)void 0===r[e]&&void 0!==i[e]&&(r[e]=i[e]);return r}async function n7(e){let{action:t,sessionName:r,logPath:i,sessionStore:n,dispatch:a}=e;if(!(ik(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let o=n.get(r);if(!o)return null;let s=ik(t.command)||"fill"===t.command,l=ik(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await ae(o,t,i,s,a,n);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),ik(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}=i8(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=at(e.positionals??[]);r&&t.push(r)}let i="string"==typeof e.result?.refLabel?e.result.refLabel.trim():"";if(i.length>0){let r=JSON.stringify(i);"fill"===e.command?(t.push(`id=${r} editable=true`),t.push(`label=${r} editable=true`),t.push(`text=${r} editable=true`),t.push(`value=${r} editable=true`)):(t.push(`id=${r}`),t.push(`label=${r}`),t.push(`text=${r}`),t.push(`value=${r}`))}return ib(t).filter(e=>e.trim().length>0)}(t)){let r=i0(e);if(!r)continue;let i=i1(d.nodes,r,{platform:o.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!i)continue;let n=i9(i.node,o.device.platform,{action:ik(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(ik(t.command))return{...t,positionals:[n]};if("fill"===t.command){let e=iS(t);if(!e)continue;return{...t,positionals:[n,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,n]}}if("is"===t.command){let{predicate:e,split:r}=i8(t.positionals);if(!e)continue;let i=r?.rest.join(" ").trim()??"",a=[e,n];return"text"===e&&i.length>0&&a.push(i),{...t,positionals:a}}if("wait"===t.command){let{selectorTimeout:e}=at(t.positionals??[]),r=[n];return e&&r.push(e),{...t,positionals:r}}}let u=function(e,t,r){if("get"!==e.command||e.positionals?.[0]!=="text")return null;let i=e.positionals?.[1];if(!i)return null;let n=i0(i);if(!n)return null;let a=new Set,o=!1;for(let e of n.selectors)for(let t of e.terms)"role"===t.key&&"string"==typeof t.value&&a.add(iJ(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=iK(e).trim();return!!/^\d+$/.test(t)&&(0===a.size||a.has(iJ(e.type??"")))});if(0===s.length||1!==ib(s.map(e=>iK(e).trim())).length)return null;let l=s[0];if(!l)return null;let d=i9(l,r.device.platform,{action:"get"});return 0===d.length?null:{...e,positionals:["text",d.join(" || ")]}}(t,d,o);return u||null}async function ae(e,t,r,i,n,a){let o=await n(e.device,"snapshot",[],t.flags?.out,{...iC(r,{...t.flags??{},snapshotInteractiveOnly:i,snapshotCompact:i},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[],l={nodes:iV(t.flags?.snapshotRaw?s:iH(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend};return e.snapshot=l,a.set(e.name,e),l}function at(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),i=i4(r?e.slice(0,-1):e.slice());return!i||i.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:i.selectorExpression,selectorTimeout:r?t:null}}function ar(e){return!!e&&!Number.isNaN(Number(e))}function ai(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}function an(e,t){let r=S(e.type??"Element"),i=m(e,r),n=!1===e.enabled?"disabled":"enabled",a=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,i,n,a,o].join("|")}function aa(e,t){return t.flatten?e.map(e=>({text:B(e,0,!1),comparable:an(e,0)})):A(e).map(e=>({text:e.text,comparable:an(e.node,e.depth)}))}function ao(e,t){return e.get(t)??0}async function as(e){let{req:t,sessionName:r,logPath:i,sessionStore:n}=e,a=e.dispatchSnapshotCommand??im,o=t.command;if("snapshot"===o){let{session:e,device:o}=await au(n,r,t.flags);if(!iN("snapshot",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let s=ad(t.flags?.snapshotScope,e);return s.ok?await ac(e,o,async()=>{let l=e?.appBundleId,d=await al({dispatchSnapshotCommand:a,device:o,session:e,req:t,logPath:i,snapshotScope:s.scope}),u=e?{...e,snapshot:d.snapshot}:{name:r,device:o,createdAt:Date.now(),appBundleId:l,snapshot:d.snapshot,actions:[]};return ap(n,u,t,{nodes:d.snapshot.nodes.length,truncated:d.snapshot.truncated??!1}),n.set(r,u),{ok:!0,data:{nodes:d.snapshot.nodes,truncated:d.snapshot.truncated??!1,appName:u.appBundleId?u.appName??u.appBundleId:void 0,appBundleId:u.appBundleId}}}):s.response}if("diff"===o){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 au(n,r,t.flags);if(!iN("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let s=ad(t.flags?.snapshotScope,e);if(!s.ok)return s.response;let l=t.flags?.snapshotInteractiveOnly===!0;return await ac(e,o,async()=>{let d=e?.appBundleId,u=(await al({dispatchSnapshotCommand:a,device:o,session:e,req:t,logPath:i,snapshotScope:s.scope})).snapshot;if(!e?.snapshot){let i=function(e,t={}){return aa(e,t).length}(u.nodes,{flatten:l}),a=e?{...e,snapshot:u}:{name:r,device:o,createdAt:Date.now(),appBundleId:d,snapshot:u,actions:[]};return ap(n,a,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:i}}),n.set(r,a),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:i},lines:[]}}}let c=function(e,t,r={}){let i=function(e,t){let r=e.length,i=t.length,n=r+i,a=new Map,o=[];a.set(1,0);for(let s=0;s<=n;s+=1){o.push(new Map(a));for(let n=-s;n<=s;n+=2){let l=n===-s||n!==s&&ao(a,n-1)<ao(a,n+1)?ao(a,n+1):ao(a,n-1)+1,d=l-n;for(;l<r&&d<i&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(a.set(n,l),l>=r&&d>=i)return function(e,t,r,i,n){let a=[],o=i,s=n;for(let i=e.length-1;i>=0;i-=1){let n=e[i],l=o-s,d=l===-i||l!==i&&ao(n,l-1)<ao(n,l+1)?l+1:l-1,u=ao(n,d),c=u-d;for(;o>u&&s>c;)a.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===i)break;o===u?(a.push({kind:"added",text:r[c].text}),s=c):(a.push({kind:"removed",text:t[u].text}),o=u)}return a.reverse(),a}(o,e,t,r,i)}}return[]}(aa(e,r),aa(t,r)),n={additions:0,removals:0,unchanged:0};for(let e of i)"added"===e.kind&&(n.additions+=1),"removed"===e.kind&&(n.removals+=1),"unchanged"===e.kind&&(n.unchanged+=1);return{summary:n,lines:i}}(e.snapshot.nodes,u.nodes,{flatten:l}),p={...e,snapshot:u};return ap(n,p,t,{mode:"snapshot",baselineInitialized:!1,summary:c.summary}),n.set(r,p),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:c.summary,lines:c.lines}}})}if("wait"===o){let{session:e,device:o}=await au(n,r,t.flags),s=function(e){if(0===e.length)return null;let t=ai(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=ai(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=ai(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=ai(e[e.length-1]),i=i4(null!==r?e.slice(0,-1):e.slice());if(i&&0===i.rest.length){let e=i0(i.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:i.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);return s?"sleep"===s.kind?(await new Promise(e=>setTimeout(e,s.durationMs)),ap(n,e,t,{waitedMs:s.durationMs}),{ok:!0,data:{waitedMs:s.durationMs}}):iN("wait",o)?await ac(e,o,async()=>{let l,d;if("selector"===s.kind){let l=s.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let l=await a(o,"snapshot",[],t.flags?.out,{...iC(i,{...t.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},e?.appBundleId,e?.trace?.outPath)}),u=l?.nodes??[],c=iV(t.flags?.snapshotRaw?u:iH(u));e&&(e.snapshot={nodes:c,truncated:l?.truncated,createdAt:Date.now(),backend:l?.backend},n.set(r,e));let p=i2(c,s.selector,{platform:o.platform});if(p)return ap(n,e,t,{selector:p.selector.raw,waitedMs:Date.now()-d}),{ok:!0,data:{selector:p.selector.raw,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${s.selectorExpression}`}}}if("ref"===s.kind){if(!e?.snapshot)return{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}};let t=iU(s.rawRef);if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${s.rawRef}`}};let r=iG(e.snapshot.nodes,t),i=r?ij(r,e.snapshot.nodes):void 0;if(!i)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s.rawRef} not found or has no label`}};l=i,d=s.timeoutMs}else l=s.text,d=s.timeoutMs;if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}};let u=d??1e4,c=Date.now();for(;Date.now()-c<u;){if("ios"===o.platform){let r=await rp(o,{command:"findText",text:l,appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});if(r?.found)return ap(n,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}}}else if("android"===o.platform&&iq(iV((await tm(o,{scope:l})).nodes??[]),l))return ap(n,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${l}`}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}}:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}}}if("alert"===o){let{session:e,device:a}=await au(n,r,t.flags),o=(t.positionals?.[0]??"get").toLowerCase();return iN("alert",a)?await ac(e,a,async()=>{if("wait"===o){let r=ai(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<r;){try{let r=await rp(a,{command:"alert",action:"get",appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});return ap(n,e,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r=await rp(a,{command:"alert",action:"accept"===o||"dismiss"===o?o:"get",appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});return ap(n,e,t,r),{ok:!0,data:r}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is only supported on iOS simulators"}}}if("settings"===o){let e=t.positionals?.[0]?.toLowerCase(),a=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase();if(!e||!a||"permission"===e&&!o)return{ok:!1,error:{code:"INVALID_ARGS",message:u}};let{session:s,device:l}=await au(n,r,t.flags);return iN("settings",l)?await ac(s,l,async()=>{let r=s?.appBundleId,d="permission"===e?[e,a,o,t.positionals?.[3]??"",r??""]:[e,a,r??""],u=await im(l,"settings",d,t.flags?.out,{...iC(i,t.flags,r,s?.trace?.outPath)});return ap(n,s,t,u??{setting:e,state:a}),{ok:!0,data:u??{setting:e,state:a}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}}}return null}async function al(e){let{dispatchSnapshotCommand:t,device:r,session:i,req:n,logPath:a,snapshotScope:o}=e,s=await t(r,"snapshot",[],n.flags?.out,{...iC(a,{...n.flags,snapshotScope:o},i?.appBundleId,i?.trace?.outPath)}),l=s?.nodes??[];return{snapshot:{nodes:iV(n.flags?.snapshotRaw?l:iH(l)),truncated:s?.truncated,createdAt:Date.now(),backend:s?.backend}}}function ad(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=iU(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let i=iG(t.snapshot.nodes,r),n=i?ij(i,t.snapshot.nodes):void 0;return n?{ok:!0,scope:n}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function au(e,t,r){let i=e.get(t),n=i?.device??await ip(r??{});return i||await iR(n),{session:i,device:n}}async function ac(e,t,r){let i=!e&&"ios"===t.platform;try{return await r()}finally{i&&await rw(t.id)}}function ap(e,t,r,i){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:i})}function af(e,t,r,i={}){let n=ah(r);if(!n)return{matches:[],score:0};let a=0,o=[];for(let r of e){if(i.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return am(e.label,r);case"value":return am(e.value,r);case"id":return am(e.identifier,r);default:return Math.max(am(e.label,r),am(e.value,r),am(e.identifier,r))}}(r,t,n);if(!(e<=0)){if(e>a){a=e,o.length=0,o.push(r);continue}e===a&&o.push(r)}}return{matches:o,score:a}}function am(e,t){let r=ah(e??"");return r?r===t?2:+!!r.includes(t):0}function ah(e){return e.trim().toLowerCase().replace(/\s+/g," ")}async function aw(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,invoke:a}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a locator or text"}};let{locator:l,query:d,action:u,value:c,timeoutMs:p}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let i=e[r]??"",n=e.slice(r+1);if(0===n.length)return{locator:t,query:i,action:"click"};let a=n[0].toLowerCase();if("get"===a){let e=n[1]?.toLowerCase();if("text"===e)return{locator:t,query:i,action:"get_text"};if("attrs"===e)return{locator:t,query:i,action:"get_attrs"};throw new I("INVALID_ARGS","find get only supports text or attrs")}if("wait"===a)return{locator:t,query:i,action:"wait",timeoutMs:ai(n[1])??void 0};if("exists"===a)return{locator:t,query:i,action:"exists"};if("click"===a)return{locator:t,query:i,action:"click"};if("focus"===a)return{locator:t,query:i,action:"focus"};if("fill"===a)return{locator:t,query:i,action:"fill",value:n.slice(1).join(" ")};if("type"===a)return{locator:t,query:i,action:"type",value:n.slice(1).join(" ")};throw new I("INVALID_ARGS",`Unsupported find action: ${n[0]}`)}(s);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a value"}};let f=n.get(r);if(!f&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let m=f?.device??await ip(t.flags??{});f||await iR(m);let h=f?.appBundleId,w="role"!==l?d:void 0,g="click"===u||"focus"===u||"fill"===u||"type"===u,v=0,A=null,y=async()=>{let e=Date.now();if(A&&e-v<750)return{nodes:A};let a=await im(m,"snapshot",[],t.flags?.out,{...iC(i,{...t.flags,snapshotScope:w,snapshotInteractiveOnly:g,snapshotCompact:g},h,f?.trace?.outPath)}),o=a?.nodes??[],s=iV(t.flags?.snapshotRaw?o:iH(o));return v=e,A=s,f&&(f.snapshot={nodes:s,truncated:a?.truncated,createdAt:Date.now(),backend:a?.backend},n.set(r,f)),{nodes:s,truncated:a?.truncated,backend:a?.backend}};if("wait"===u){let e=p??1e4,r=Date.now();for(;Date.now()-r<e;){let{nodes:e}=await y();if(af(e,l,d,{requireRect:!1}).matches[0])return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0,waitedMs:Date.now()-r}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-r}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}let{nodes:N}=await y(),S=af(N,l,d,{requireRect:g});if(g&&S.matches.length>1){let e=S.matches.slice(0,8).map(e=>{let t=iK(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`});return{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${S.matches.length} elements for ${l} "${d}". Use a more specific locator or selector.`,details:{locator:l,query:d,matches:S.matches.length,candidates:e}}}}let b=S.matches[0]??null;if(!b)return{ok:!1,error:{code:"COMMAND_FAILED",message:"find did not match any element"}};let _="click"===u||"focus"===u||"fill"===u||"type"===u?function(e,t){if(t.hittable)return t;let r=t,i=new Set;for(;void 0!==r.parentIndex&&!i.has(r.ref);){i.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}(N,b)??b:b,D=`@${_.ref}`,E={...t.flags??{},noRecord:!0};if("exists"===u)return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}};if("get_text"===u){let e=iK(b);return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"get text",text:e}}),{ok:!0,data:{ref:D,text:e,node:b}}}if("get_attrs"===u)return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"get attrs"}}),{ok:!0,data:{ref:D,node:b}};if("click"===u){let e=await a({token:t.token,session:r,command:"click",positionals:[D],flags:E});return e.ok&&f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"click"}}),e}if("fill"===u){if(!c)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let e=await a({token:t.token,session:r,command:"fill",positionals:[D,c],flags:E});return e.ok&&f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"fill"}}),e}if("focus"===u){let e=b.rect?iB(b.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let r=await im(m,"focus",[String(e.x),String(e.y)],t.flags?.out,{...iC(i,t.flags,f?.appBundleId,f?.trace?.outPath)});return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"focus"}}),{ok:!0,data:r??{ref:D}}}if("type"===u){if(!c)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let e=b.rect?iB(b.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await im(m,"focus",[String(e.x),String(e.y)],t.flags?.out,{...iC(i,t.flags,f?.appBundleId,f?.trace?.outPath)});let r=await im(m,"type",[c],t.flags?.out,{...iC(i,t.flags,f?.appBundleId,f?.trace?.outPath)});return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"type"}}),{ok:!0,data:r??{ref:D}}}return null}function ag(e){return e instanceof Error?e.message:String(e)}function aI(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function av(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function aA(e){let{req:t,sessionName:r,sessionStore:i,logPath:a}=e,o=e.deps??{runCmd:p,runCmdBackground:d,runIosRunnerCommand:rp},s=t.command;if("record"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};let d=i.get(r),c=d?.device??await ip(t.flags??{});d||await iR(c);let p=d??{name:r,device:c,createdAt:Date.now(),actions:[]};if("start"===e){if(p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let e=t.flags?.fps;if(void 0!==e&&(!Number.isInteger(e)||e<1||e>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};let d=t.positionals?.[1]??`./recording-${Date.now()}.mp4`;if(!iN("record",c))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let f="ios"===c.platform&&"device"===c.kind?aI(p):void 0;if("ios"===c.platform&&"device"===c.kind&&!f)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};let m=ix.expandHome(d,t.meta?.cwd);R.mkdirSync(n.dirname(m),{recursive:!0});let h=av(t,a,p);if("ios"===c.platform&&"device"===c.kind){let t=`agent-device-recording-${Date.now()}.mp4`,r=`tmp/${t}`,n=async()=>{await o.runIosRunnerCommand(c,{command:"recordStart",outPath:t,fps:e,appBundleId:f},h)};try{await n()}catch(e){if(!ag(e).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${ag(e)}`}};{var l,u;M({level:"warn",phase:"record_start_runner_desynced",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:ag(e)}});let t=(l=c.id,u=p.name,i.toArray().find(e=>e.name!==u&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===l&&e.recording?.platform==="ios-device-runner"));if(t)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${t.name}'`}};try{await o.runIosRunnerCommand(c,{command:"recordStop",appBundleId:f},h)}catch{}try{await n()}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${ag(e)}`}}}}}p.recording={platform:"ios-device-runner",outPath:m,remotePath:r}}else if("ios"===c.platform){let{child:e,wait:t}=o.runCmdBackground("xcrun",t$(c,["io",c.id,"recordVideo",m]),{allowFailure:!0});p.recording={platform:"ios",outPath:m,child:e,wait:t}}else{let e=`/sdcard/agent-device-recording-${Date.now()}.mp4`,{child:t,wait:r}=o.runCmdBackground("adb",["-s",c.id,"shell","screenrecord",e],{allowFailure:!0});p.recording={platform:"android",outPath:m,remotePath:e,child:t,wait:r}}return i.set(r,p),i.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start"}}),{ok:!0,data:{recording:"started",outPath:d}}}if(!p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let f=p.recording;if("ios-device-runner"===f.platform){let e=aI(p);try{await o.runIosRunnerCommand(c,{command:"recordStop",appBundleId:e},av(t,a,p))}catch(e){M({level:"warn",phase:"record_stop_runner_failed",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:ag(e)}})}let r={stdout:"",stderr:"",exitCode:1};for(let e of t7)if(0===(r=await o.runCmd("xcrun",["devicectl","device","copy","from","--device",c.id,"--source",f.remotePath,"--destination",f.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(p.recording=void 0,0!==r.exitCode){let e=r.stderr.trim()||r.stdout.trim()||`devicectl exited with code ${r.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}}else{f.child.kill("SIGINT");try{await f.wait}catch{}if("android"===f.platform&&f.remotePath)try{await o.runCmd("adb",["-s",c.id,"pull",f.remotePath,f.outPath],{allowFailure:!0}),await o.runCmd("adb",["-s",c.id,"shell","rm","-f",f.remotePath],{allowFailure:!0})}catch{}p.recording=void 0}return i.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:f.outPath}}),{ok:!0,data:{recording:"stopped",outPath:f.outPath}}}if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"trace requires start|stop"}};let a=i.get(r);if(!a)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};if("start"===e){if(a.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"trace already in progress"}};let e=t.positionals?.[1]??i.defaultTracePath(a),r=ix.expandHome(e);return R.mkdirSync(n.dirname(r),{recursive:!0}),R.appendFileSync(r,""),a.trace={outPath:r,startedAt:Date.now()},i.recordAction(a,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!a.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active trace"}};let o=a.trace.outPath;if(t.positionals?.[1]){let e=ix.expandHome(t.positionals[1]);R.mkdirSync(n.dirname(e),{recursive:!0}),R.existsSync(o)?R.renameSync(o,e):R.appendFileSync(e,""),o=e}return a.trace=void 0,i.recordAction(a,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function ay(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function aN(e){let t=null,r=-1;for(let i of e){let e=i.width*i.height;e>r&&(t=i,r=e)}return t}function aS(e,t,r){return Math.min(r,Math.max(t,Math.round(e)))}async function ab(e){let{req:t,sessionName:r,sessionStore:i,contextFromFlags:n}=e,a=e.dispatch??im,o=t.command;if("press"===o){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!iN("press",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let s=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(s){let r=await a(e.device,"press",[String(s.x),String(s.y)],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)});return i.recordAction(e,{command:o,positionals:t.positionals??[String(s.x),String(s.y)],flags:t.flags??{},result:r??{x:s.x,y:s.y}}),{ok:!0,data:r??{x:s.x,y:s.y}}}let l="click",d=t.positionals?.[0]??"";if(d.startsWith("@")){let r=aE("press",t.flags);if(r)return r;let s=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",u=ak({session:e,refInput:d,fallbackLabel:s,requireRect:!0,invalidRefMessage:`${o} requires a ref like @e2`,notFoundMessage:`Ref ${d} not found or has no bounds`});if(!u.ok)return u.response;let{ref:c}=u.target,p=u.target.node,f=u.target.snapshotNodes,m=aO(p.rect);if(!m){let r=await a_(e,t.flags,i,n,{interactiveOnly:!0},a),o=iG(r.nodes,c),l=s.length>0?iq(r.nodes,s):null,d=aO(l?.rect),u=aO(o?.rect)?o:d?l:o??l,h=aO(u?.rect);u&&h&&(p=u,f=r.nodes,m=h)}if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${d} not found or has invalid bounds`}};let h=ij(p,f),w=i9(p,e.device.platform,{action:l}),{x:g,y:I}=m,v=await a(e.device,"press",[String(g),String(I)],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)});return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:c,x:g,y:I,refLabel:h,selectorChain:w}}),{ok:!0,data:{...v??{},ref:c,x:g,y:I}}}let u=(t.positionals??[]).join(" ").trim();if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:`${o} requires @ref, selector expression, or x y coordinates`}};let c=iQ(u),p=await a_(e,t.flags,i,n,{interactiveOnly:!0},a),f=await O("selector_resolve",()=>i1(p.nodes,c,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!f||!f.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:i3(c,f?.diagnostics??[],{unique:!0})}};let m=aO(f.node.rect);if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${f.selector.raw} resolved to invalid bounds`}};let{x:h,y:w}=m,g=await a(e.device,"press",[String(h),String(w)],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)}),I=i9(f.node,e.device.platform,{action:l}),v=ij(f.node,p.nodes);return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{x:h,y:w,selector:f.selector.raw,selectorChain:I,refLabel:v}}),{ok:!0,data:{...g??{},selector:f.selector.raw,x:h,y:w}}}if("fill"===o){let e=i.get(r);if(e&&!iN("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=aE("fill",t.flags);if(r)return r;let s=t.positionals.length>=3?t.positionals[1]:"",l=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let d=ak({session:e,refInput:t.positionals[0],fallbackLabel:s,requireRect:!0,invalidRefMessage:"fill requires a ref like @e2",notFoundMessage:`Ref ${t.positionals[0]} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${t.positionals[0]} not found or has no bounds`}};let f=c.type??"",m=f&&!iz(f,e.device.platform)?`fill target ${t.positionals[0]} resolved to "${f}", attempting fill anyway.`:void 0,h=ij(c,p),w=i9(c,e.device.platform,{action:"fill"}),{x:g,y:I}=iB(c.rect),v={...await a(e.device,"fill",[String(g),String(I),l],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)})??{ref:u,x:g,y:I}};return m&&(v.warning=m),i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...v,refLabel:h,selectorChain:w}}),{ok:!0,data:v}}if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let s=i4(t.positionals??[],{preferTrailingValue:!0});if(s){if(0===s.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=s.rest.join(" ").trim();if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let l=iQ(s.selectorExpression),d=await a_(e,t.flags,i,n,{interactiveOnly:!0},a),u=await O("selector_resolve",()=>i1(d.nodes,l,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!u||!u.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:i3(l,u?.diagnostics??[],{unique:!0})}};let c=u.node,p=c.type??"",f=p&&!iz(p,e.device.platform)?`fill target ${u.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=iB(u.node.rect),w=await a(e.device,"fill",[String(m),String(h),r],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)}),g=i9(c,e.device.platform,{action:"fill"}),I={...w??{x:m,y:h,text:r},selector:u.selector.raw,selectorChain:g,refLabel:ij(c,d.nodes)};return f&&(I.warning=f),i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:I}),{ok:!0,data:I}}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}if("get"===o){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let s=i.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!iN("get",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let l=t.positionals?.[1]??"";if(l.startsWith("@")){let r=aE("get",t.flags);if(r)return r;let n=ak({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(!n.ok)return n.response;let{ref:a,node:d}=n.target,u=i9(d,s.device.platform,{action:"get"});if("attrs"===e)return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:a,selectorChain:u}}),{ok:!0,data:{ref:a,node:d}};let c=iK(d);return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:a,text:c,refLabel:c||void 0,selectorChain:u}}),{ok:!0,data:{ref:a,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=iQ(d),c=await a_(s,t.flags,i,n,{interactiveOnly:!1},a),p=await O("selector_resolve",()=>i1(c.nodes,u,{platform:s.device.platform,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===e}),{command:o});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:i3(u,[],{unique:!0})}};let f=p.node,m=i9(f,s.device.platform,{action:"get"});if("attrs"===e)return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,node:f}};let h=iK(f);return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{text:h,refLabel:h||void 0,selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,text:h,node:f}}}if("is"===o){let e=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let s=i.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!iN("is",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:l}=i8(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=iQ(l.selectorExpression),c=await a_(s,t.flags,i,n,{interactiveOnly:!1},a);if("exists"===e){let r=i2(c.nodes,u,{platform:s.device.platform});return r?(i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:r.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,matches:r.matches}}),{ok:!0,data:{predicate:e,pass:!0,selector:r.selector.raw,matches:r.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:i3(u,[],{unique:!1})}}}let p=await O("selector_resolve",()=>i1(c.nodes,u,{platform:s.device.platform,requireUnique:!0}),{command:"is",predicate:e});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:i3(u,[],{unique:!0})}};let f=function(e){let{predicate:t,node:r,expectedText:i,platform:n}=e,a=iK(r),o=!1;switch(t){case"visible":o=i5(r);break;case"hidden":o=!i5(r);break;case"editable":o=i6(r,n);break;case"selected":o=!0===r.selected;break;case"text":o=a===(i??"")}let s="text"===t?`expected="${i??""}" actual="${a}"`:`actual=${JSON.stringify({visible:i5(r),editable:i6(r,n),selected:!0===r.selected})}`;return{pass:o,actualText:a,details:s}}({predicate:e,node:p.node,expectedText:d,platform:s.device.platform});return f.pass?(i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:p.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,text:"text"===e?f.actualText:void 0}}),{ok:!0,data:{predicate:e,pass:!0,selector:p.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${e} failed for selector ${p.selector.raw}: ${f.details}`}}}if("scrollintoview"===o){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!iN("scrollintoview",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let s=t.positionals?.[0]??"";if(!s.startsWith("@"))return null;let l=aE("scrollintoview",t.flags);if(l)return l;let d=ak({session:e,refInput:s,fallbackLabel:t.positionals&&t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${s} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s} not found or has no bounds`}};let f=function(e,t){let r=iB(t),i=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),n=i.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),a=aN(n.map(e=>e.rect).filter(e=>ay(e,r.x,r.y)));if(a)return a;let o=aN(n.map(e=>e.rect));if(o)return o;let s=aN(i.map(e=>e.rect).filter(e=>ay(e,r.x,r.y)));return s||null}(p,c.rect);if(!f)return{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${s}`}};let m=function(e,t){var r,i;let n=Math.max(1,t.height),a=Math.max(1,t.width),o=t.y,s=t.y+n,l=t.x,d=t.x+a,u=o+.25*n,c=s-.25*n,p=Math.max(8,.1*a),f=e.y+e.height/2,m=e.x+e.width/2;if(f>=u&&f<=c)return null;let h=Math.round((r=m,i=l+p,Math.min(d-p,Math.max(i,r)))),w=Math.round(o+.86*n),g=Math.round(o+.14*n),I=Math.max(1,Math.abs(w-g));return f>c?{x:h,startY:w,endY:g,count:aS(Math.ceil((f-c)/I),1,50),direction:"down"}:{x:h,startY:g,endY:w,count:aS(Math.ceil((u-f)/I),1,50),direction:"up"}}(c.rect,f),h=ij(c,p),w=i9(c,e.device.platform,{action:"get"});if(!m)return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:u,attempts:0,alreadyVisible:!0,refLabel:h,selectorChain:w}}),{ok:!0,data:{ref:u,attempts:0,alreadyVisible:!0}};let g=await a(e.device,"swipe",[String(m.x),String(m.startY),String(m.x),String(m.endY),"16"],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath),count:m.count,pauseMs:0,pattern:"one-way"});return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...g??{},ref:u,attempts:m.count,direction:m.direction,refLabel:h,selectorChain:w}}),{ok:!0,data:{...g??{},ref:u,attempts:m.count,direction:m.direction}}}return null}async function a_(e,t,r,i,n,a=im){let o=await a(e.device,"snapshot",[],t?.out,{...i({...t??{},snapshotInteractiveOnly:n.interactiveOnly,snapshotCompact:n.interactiveOnly},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[];return e.snapshot={nodes:iV(t?.snapshotRaw?s:iH(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend},r.set(e.name,e),e.snapshot}let aD=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function aE(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,i]of aD)void 0!==e[r]&&t.push(i);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}function ak(e){let{session:t,refInput:r,fallbackLabel:i,requireRect:n,invalidRefMessage:a,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=iU(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:a}}};let l=iG(t.snapshot.nodes,s);return((!l||n&&!l.rect)&&i.length>0&&(l=iq(t.snapshot.nodes,i)),l&&(!n||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 aO(e){let t=function(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),i=Number(e.width),n=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(i)&&Number.isFinite(n)&&!(i<0)&&!(n<0)?{x:t,y:r,width:i,height:n}:null}(e);if(!t)return null;let r=iB(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function aM(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 aL(e){let{req:t,leaseRegistry:r}=e,i=aM(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:i.tenantId??"",runId:i.runId??"",backend:i.leaseBackend,ttlMs:i.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:i.leaseId??"",tenantId:i.tenantId,runId:i.runId,ttlMs:i.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:i.leaseId??"",tenantId:i.tenantId,runId:i.runId})};default:return null}}let ax=new Set(["agent_device.command","agent-device.command"]),aC={"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"},aT=new Set([...ax,...Object.keys(aC)]);function aR(e,t,r,i){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:i}}}function aP(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function a$(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function aF(e,t){let r="string"==typeof t.authorization?t.authorization:"",i=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,n="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??n??i??""}function aV(e,t){let r=e[t];return"string"==typeof r?r:void 0}async function aU(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=b(new I("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:aR(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=b(new I(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:aR(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=c(r.tenantId);if(!e){let e=b(new I("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:aR(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function aG(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",i=n.isAbsolute(t)?t:n.resolve(t);try{e=await import(g(i).href)}catch(e){throw new I("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:i,error:e instanceof Error?e.message:String(e)})}let a=e[r];if("function"!=typeof a)throw new I("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:i,exportName:r});return a}async function aB(e){let t=await aG(),{handleRequest:r}=e;return i.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||"/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||aP(i,aR(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a;try{a=JSON.parse(n)}catch{aP(i,aR(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void aP(i,aR(a.id??null,-32600,"Invalid Request"),400);if(!aT.has(a.method))return void aP(i,aR(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void aP(i,aR(a.id??null,-32602,"Invalid params"),400);try{var o;let n=a.params,s=function(e,t,r){if(ax.has(e))return{token:aF(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,meta:t.meta};let i=aC[e];if(i){let e;return{token:aF(t,r),session:aV(t,"session")??"default",command:i,positionals:[],meta:{tenantId:aV(t,"tenantId")??aV(t,"tenant"),runId:aV(t,"runId"),leaseId:aV(t,"leaseId"),leaseTtlMs:(e=t.ttlMs,Number.isInteger(e)?Number(e):void 0),leaseBackend:aV(t,"backend")}}}throw new I("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(o=a.method,ax.has(o)&&("string"!=typeof s.command||0===s.command.length))return void aP(i,aR(a.id??null,-32602,"Invalid params: command is required"),400);let l=await aU(t,{headers:e.headers,rpcRequest:a,daemonRequest:s});if(!l.ok)return void aP(i,l.response,l.statusCode);l.tenantId&&(s.meta={...s.meta,tenantId:l.tenantId,sessionIsolation:s.meta?.sessionIsolation??s.flags?.sessionIsolation??"tenant"});let d=await r(s);if(d.ok)return void aP(i,{jsonrpc:"2.0",id:a.id??null,result:d});aP(i,aR(a.id??null,-32e3,d.error.message,d.error),a$(d.error.code))}catch(t){let e=b(t);aP(i,aR(a.id??null,-32e3,e.message,e),a$(e.code))}})})}function aq(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function aj(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function aW(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new I("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class aH{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=aW(e.backend),r=c(e.tenantId);if(!r)throw new I("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=aq(e.runId);if(!i)throw new I("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),a=this.bindingKey(r,i,t),o=this.runBindings.get(a);if(o){let e=this.leases.get(o);if(e)return this.refreshLease(e,n);this.runBindings.delete(a)}this.enforceCapacity(t);let s=this.now(),l={leaseId:f.randomBytes(16).toString("hex"),tenantId:r,runId:i,backend:t,createdAt:s,heartbeatAt:s,expiresAt:s+n};return this.leases.set(l.leaseId,l),this.runBindings.set(a,l.leaseId),{...l}}heartbeatLease(e){let t=aj(e.leaseId);if(!t)throw new I("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new I("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let i=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,i)}releaseLease(e){let t=aj(e.leaseId);if(!t)throw new I("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=aW(e.backend),r=c(e.tenantId);if(!r)throw new I("INVALID_ARGS","tenant isolation requires tenant id.");let i=aq(e.runId);if(!i)throw new I("INVALID_ARGS","tenant isolation requires run id.");let n=aj(e.leaseId);if(!n)throw new I("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let a=this.leases.get(n);if(!a)throw new I("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(a.backend!==t||a.tenantId!==r||a.runId!==i)throw new I("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 I("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 I("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),i={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(i.leaseId,i),this.runBindings.set(this.bindingKey(i.tenantId,i.runId,i.backend),i.leaseId),{...i}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let i=c(t),n=aq(r);if(t&&!i)throw new I("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!n)throw new I("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(i&&e.tenantId!==i||n&&e.runId!==n)throw new I("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let{baseDir:aJ,infoPath:az,lockPath:aK,logPath:aX,sessionsDir:aY}=G(process.env.AGENT_DEVICE_STATE_DIR),aZ=U(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var aQ=aY;if(R.existsSync(aQ))for(let e of R.readdirSync(aQ,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=n.join(aQ,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=T(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let i=a(e.pid);return!!i&&!!((t=i.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||i===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{nu(t)}}let a0=new ix(aY),a1=new aH({maxActiveSimulatorLeases:on(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:on(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:on(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:on(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),a2=D(),a3=f.randomBytes(24).toString("hex"),a4=new Set(["session_list","devices"]),a8=new Set(["session_list","devices","lease_allocate","lease_heartbeat","lease_release"]),a5=T(process.pid)??void 0,a6=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=R.statSync(e),r=E(),i=n.relative(r,e)||e;return`${i}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}();function a9(e,t,r){let i=k().requestId;return{...iC(aX,e,t,r,i),requestId:i}}async function a7(e){var t;let r="click"===(t=e).command?{...t,command:"press"}:t,i=!!(r.meta?.debug||r.flags?.verbose);return await P({session:r.session,requestId:r.meta?.requestId,command:r.command,debug:i,logPath:aX},async()=>{if(r.token!==a3)return{ok:!1,error:b(new I("UNAUTHORIZED","Invalid token"))};try{let e=function(e){let t=_(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,i=c(r);if(r&&!i)throw new I("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!i)throw new I("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");return{...e,session:`${i}:${e.session||"default"}`,meta:{...e.meta,tenantId:i,sessionIsolation:t}}}(r);M({level:"info",phase:"request_start",data:{session:e.session,command:e.command,tenant:e.meta?.tenantId,isolation:e.meta?.sessionIsolation}});let t=e.command,i=aM(e);a8.has(t)||e.meta?.sessionIsolation!=="tenant"||a1.assertLeaseAdmission({tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId,backend:i.leaseBackend});let n=function(e,t){var r;let i,n=e.session||"default";if(r=e,i=r.flags?.session,"string"==typeof i&&i.trim().length>0||"default"!==n||t.has(n))return n;let a=t.toArray();return 1===a.length?a[0].name:n}(e,a0),a=a0.get(n);a&&!a4.has(t)&&function(e,t){if(!t)return;let r=[],i=e.device,n=q(t.platform);if(n&&n!==i.platform&&r.push(`--platform=${t.platform}`),t.target&&t.target!==(i.target??"mobile")&&r.push(`--target=${t.target}`),t.udid&&("ios"!==i.platform||t.udid!==i.id)&&r.push(`--udid=${t.udid}`),t.serial&&("android"!==i.platform||t.serial!==i.id)&&r.push(`--serial=${t.serial}`),t.device&&t.device.trim().toLowerCase()!==i.name.trim().toLowerCase()&&r.push(`--device=${t.device}`),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),n=i.simulatorSetPath?.trim();("ios"!==i.platform||"simulator"!==i.kind||e!==n)&&r.push(`--ios-simulator-device-set=${t.iosSimulatorDeviceSet}`)}if(t.androidDeviceAllowlist){let e=ea(t.androidDeviceAllowlist);"android"===i.platform&&e.has(i.id)||r.push(`--android-device-allowlist=${t.androidDeviceAllowlist}`)}if(0!==r.length){var a;let t,i,n;throw new I("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.join(", ")}. Use a different --session name or close this session first.`)}}(a,e.flags);let o=await aL({req:e,leaseRegistry:a1});if(o)return oe(o);let s=await n4({req:e,sessionName:n,logPath:aX,sessionStore:a0,invoke:a7});if(s)return oe(s);let l=await as({req:e,sessionName:n,logPath:aX,sessionStore:a0});if(l)return oe(l);let d=await aA({req:e,sessionName:n,sessionStore:a0,logPath:aX});if(d)return oe(d);let u=await aw({req:e,sessionName:n,logPath:aX,sessionStore:a0,invoke:a7});if(u)return oe(u);let p=await ab({req:e,sessionName:n,sessionStore:a0,contextFromFlags:a9});if(p)return oe(p);let f=a0.get(n);if(!f)return oe({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!iN(t,f.device))return oe({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${t} is not supported on this device`}});let m=await im(f.device,t,e.positionals??[],e.flags?.out,{...a9(e.flags,f.appBundleId,f.trace?.outPath)});return a0.recordAction(f,{command:t,positionals:e.positionals??[],flags:e.flags??{},result:m??{}}),oe({ok:!0,data:m??{}})}catch(r){M({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=k(),t=$({force:!0})??void 0;return{ok:!1,error:b(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}function oe(e){let t=k();if(!e.ok){M({level:"error",phase:"request_failed",data:{code:e.error.code,message:e.error.message}});let r=$({force:!0})??void 0;return{ok:!1,error:b(new I(e.error.code,e.error.message,{...e.error.details??{},hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath}),{diagnosticId:t.diagnosticId,logPath:r})}}return M({level:"info",phase:"request_success"}),$(),e}function ot(){R.existsSync(az)&&R.unlinkSync(az)}function or(){if(!R.existsSync(aK))return null;try{let e=JSON.parse(R.readFileSync(aK,"utf8"));if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}function oi(){let e=or();if(!e||e.pid===process.pid)try{R.existsSync(aK)&&R.unlinkSync(aK)}catch{}}function on(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}(async function e(){let e,t;if(!function(){R.existsSync(aJ)||R.mkdirSync(aJ,{recursive:!0});let e=JSON.stringify({pid:process.pid,version:a2,startedAt:Date.now(),processStartTime:a5},null,2),t=()=>{try{return R.writeFileSync(aK,e,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(t())return!0;let r=or();if(r?.pid&&r.pid!==process.pid&&s(r.pid,r.processStartTime))return!1;try{R.unlinkSync(aK)}catch{}return t()}()){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var i;let n;if("socket"===aZ||"dual"===aZ){let t=V.createServer(e=>{let t="",r=0,i=new Set,n=!1,a=()=>{if(!n&&0!==r){for(let e of(n=!0,i))e&&t4.add(e);M({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await rg(),!(r<=0));)await new Promise(e=>setTimeout(e,200))})()}};e.setEncoding("utf8"),e.on("close",a),e.on("error",a),e.on("data",async n=>{let a=(t+=n).indexOf("\n");for(;-1!==a;){let n,s,l=t.slice(0,a).trim();if(t=t.slice(a+1),0===l.length){a=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(l);if((s=e.meta?.requestId)&&(i.add(s),t8(s)))throw new I("COMMAND_FAILED","request canceled");n=await a7(e)}catch(e){n={ok:!1,error:b(e)}}finally{if(r-=1,s){var o;i.delete(s),(o=s)&&t4.delete(o)}}e.destroyed||e.write(`${JSON.stringify(n)}
30
- `),a=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let i=t.address();"object"==typeof i&&i?.port?e(i.port):r(new I("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===aZ||"dual"===aZ){let e=await aB({handleRequest:a7});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let i=e.address();"object"==typeof i&&i?.port?t(i.port):r(new I("COMMAND_FAILED","Failed to bind HTTP server"))})})}i={socketPort:e,httpPort:t},R.existsSync(aJ)||R.mkdirSync(aJ,{recursive:!0}),R.writeFileSync(aX,""),n=i.httpPort&&i.socketPort?"dual":i.httpPort?"http":"socket",R.writeFileSync(az,JSON.stringify({port:i.socketPort,httpPort:i.httpPort,transport:n,token:a3,pid:process.pid,version:a2,codeSignature:a6,processStartTime:a5,stateDir:aJ},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
19
+ ${i}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")})(e)},{phase:"ios_simulator_screenshot"});return}try{await t4(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(e){if(!function(e){if(!(e instanceof I)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",i="string"==typeof t.stderr?t.stderr:"",n=`${e.message}
20
+ ${r}
21
+ ${i}`.toLowerCase();return n.includes("unknown option '--device'")||n.includes("unknown subcommand")&&n.includes("screenshot")||n.includes("unrecognized subcommand")&&n.includes("screenshot")}(e))throw e}let i=(await rI(e,{command:"screenshot",appBundleId:r})).message;if(!i)throw new I("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");let n={exitCode:1,stdout:"",stderr:""};for(let r of rn)if(0===(n=await p("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",i,"--destination",t,"--domain-type","appDataContainer","--domain-identifier",r],{allowFailure:!0})).exitCode)break;if(0!==n.exitCode){let e=n.stderr.trim()||n.stdout.trim()||`devicectl exited with code ${n.exitCode}`;throw new I("COMMAND_FAILED",`Failed to capture iOS screenshot: ${e}`)}}async function ii(e){rz(e,"clipboard"),await rK(e);let t=await rQ(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new I("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 ia(e,t){rz(e,"clipboard"),await rK(e);let r=await rQ(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new I("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function io(e,t,r){rz(e,"push"),await rK(e);let i=await x.mkdtemp(n.join(F.tmpdir(),"agent-device-ios-push-")),a=n.join(i,"payload.apns");try{await x.writeFile(a,`${JSON.stringify(r)}
22
+ `,"utf8"),await rQ(e,["push",e.id,t,a])}finally{await x.rm(i,{recursive:!0,force:!0})}}async function is(e,t,r,i,n){rz(e,"settings"),await rK(e);let a=t.toLowerCase();switch(a){case"wifi":{let t=iu(r);await rQ(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(iu(r)?await rQ(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await rQ(e,["status_bar",e.id,"clear"]));case"location":{let t=iu(r);if(!i)throw new I("INVALID_ARGS","location setting requires an active app in session");await rQ(e,["privacy",e.id,t?"grant":"revoke","location",i]);return}case"faceid":case"touchid":{let t=ip[a],i=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new I("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,a);await ig(e,i,{settingName:a,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await ic(e,r);await rQ(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!i)throw new I("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=e$(r))?"revoke":o,a=function(e,t){let r=eF(e);if("photos"!==r&&t?.trim())throw new I("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 I("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new I("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(n?.permissionTarget,n?.permissionMode);await im(e,t,a,i);return}default:throw new I("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function il(e,t="all"){var r;return"simulator"===e.kind?(r=await id(e),"user-installed"===t?r.filter(e=>!e.bundleId.startsWith("com.apple.")):r):await t8(e,t)}async function id(e){let t=(await rQ(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 p("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 iu(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 I("INVALID_ARGS",`Invalid setting state: ${e}`)}async function ic(e,t){let r=eV(t);if("toggle"!==r)return r;let i=await rQ(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==i.exitCode)throw new I("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});let n=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
23
+ ${t}`);if(!r)return null;let i=r[1].toLowerCase();return"dark"===i?"dark":"light"===i?"light":null}(i.stdout,i.stderr);if(!n)throw new I("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:i.stdout,stderr:i.stderr});return"dark"===n?"light":"dark"}let ip={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function im(e,t,r,i){let n=await iw(e);if(!n.has(r))throw new I("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(n).sort().join(", ")}`});let a=["privacy",e.id,t,r,i],o="notifications"===r;if(!("reset"===t&&o))try{await rQ(e,a);return}catch(t){if(!(o&&ih(t)))throw t;throw new I("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:i,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await rQ(e,a);return}catch(e){if(!ih(e))throw e}try{await rQ(e,["privacy",e.id,"reset","all",i])}catch(t){throw new I("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:i,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function ih(e){if(!(e instanceof I)||"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 iw(t){let r=en(t.simulatorSetPath),i=`${process.env.PATH??""}::${r??""}`;if(rZ&&e===i)return rZ;let n=await rQ(t,["privacy","help"],{allowFailure:!0}),a=function(e){let t=new Set,r=!1;for(let i of e.split("\n")){let e=i.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let n=/^([a-z-]+)\s+-\s+/.exec(e);n&&t.add(n[1])}return t}(`${n.stdout}
24
+ ${n.stderr}`);if(0===a.size)throw new I("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return rZ=a,e=i,a}async function ig(e,t,r){let i=function(e,t,r){let i=r.length>0?r:["face"];switch(t){case"match":return i.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return i.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),n=[];for(let t of i){let r=tB(e,t),i=await p("xcrun",r,{allowFailure:!0});if(0===i.exitCode)return;n.push({args:r,stderr:i.stderr,stdout:i.stdout,exitCode:i.exitCode})}let a=n.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(n.length>0&&n.every(e=>{var t,r;let i;return t=e.stdout,r=e.stderr,(i=`${t}
25
+ ${r}`.toLowerCase()).includes("unrecognized subcommand")||i.includes("unknown subcommand")||i.includes("not supported")||i.includes("unavailable")||i.includes("biometric")&&i.includes("invalid")}))throw new I("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:a});throw new I("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:a})}function iI(e){if(!(e instanceof I)||"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 iv(e,t){await rK(e),await p("open",["-a","Simulator"],{allowFailure:!0});let r=X.fromTimeoutMs(t2);await Y(async({deadline:r})=>{if(r?.isExpired())throw new I("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:t2});let i=tB(e,["launch",e.id,t]),n=await p("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new I("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:30,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:iI},{deadline:r})}async function iA(e,t,r){let i=["device","process","launch","--device",e.id,t];r?.payloadUrl&&i.push("--payload-url",r.payloadUrl),await t4(i,{action:"launch iOS app",deviceId:e.id})}let iy=/^[A-Za-z0-9_.:-]{1,64}$/;function iN(e,t){let r,i=t?.subject??"Payload",n=e.trim();if(!n)throw new I("INVALID_ARGS",`${i} cannot be empty`);let a=t?.expandPath?t.expandPath(n,t.cwd):n;try{if(!R.statSync(a).isFile())throw new I("INVALID_ARGS",`${i} path is not a file: ${a}`);return{kind:"file",path:a}}catch(t){if(t instanceof I)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new I("INVALID_ARGS",`${i} file is not readable: ${a}`);if(e&&"ENOENT"!==e)throw new I("COMMAND_FAILED",`Unable to read ${i} file: ${a}`,{cause:String(t)})}if((r=n.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:n};throw new I("INVALID_ARGS",`${i} file not found: ${a}`)}async function ib(e){let t=q(e.platform),r=en(e.iosSimulatorDeviceSet),i=eo(e.androidDeviceAllowlist);return await O("resolve_target_device",async()=>{let n={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(n.target&&!n.platform)throw new I("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|android|apple with --target mobile|tv.");if("android"===n.platform){await tA();let e=await eA({serialAllowlist:i});return await j(e,n)}if("ios"===n.platform){let e=await tQ({simulatorSetPath:r});return await j(e,n)}let a=[];try{a.push(...await eA({serialAllowlist:i}))}catch{}try{a.push(...await tQ({simulatorSetPath:r}))}catch{}return await j(a,n)},{platform:t,target:e.target})}async function iS(e,t,r,i,a){let o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>e0(e,t,r?.activity),openDevice:()=>e2(e),close:t=>e3(e,t),tap:(t,r)=>tr(e,t,r),doubleTap:async(t,r)=>{await tr(e,t,r),await tr(e,t,r)},swipe:(t,r,i,n,a)=>ti(e,t,r,i,n,a),longPress:(t,r,i)=>ts(e,t,r,i),focus:(t,r)=>tc(e,t,r),type:t=>tl(e,t),fill:(t,r,i)=>tp(e,t,r,i),scroll:(t,r)=>tf(e,t,r),scrollIntoView:t=>tm(e,t),screenshot:(t,r)=>th(e,t)};case"ios":var r,i;let n,a;return{open:(t,r)=>r5(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>r6(e),close:t=>r9(e,t),screenshot:(t,r)=>ir(e,t,r),...(r=e,n={verbose:(i=t).verbose,logPath:i.logPath,traceLogPath:i.traceLogPath,requestId:i.requestId},a=()=>{if(re(i.requestId))throw new I("COMMAND_FAILED","request canceled")},{tap:async(e,t)=>{await rI(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},n)},doubleTap:async(e,t)=>{await rI(r,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:i.appBundleId},n)},swipe:async(e,t,a,o,s)=>{await rI(r,{command:"drag",x:e,y:t,x2:a,y2:o,durationMs:s,appBundleId:i.appBundleId},n)},longPress:async(e,t,a)=>{await rI(r,{command:"longPress",x:e,y:t,durationMs:a,appBundleId:i.appBundleId},n)},focus:async(e,t)=>{await rI(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},n)},type:async e=>{await rI(r,{command:"type",text:e,appBundleId:i.appBundleId},n)},fill:async(e,t,a)=>{await rI(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},n),await rI(r,{command:"type",text:a,clearFirst:!0,appBundleId:i.appBundleId},n)},scroll:async(e,t)=>{if(!["up","down","left","right"].includes(e))throw new I("INVALID_ARGS",`Unknown direction: ${e}`);let a=function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left"}}(e);await rI(r,{command:"swipe",direction:a,appBundleId:i.appBundleId},n)},scrollIntoView:async e=>{let t=await rI(r,{command:"findText",text:e,appBundleId:i.appBundleId},n);if(t?.found)return{attempts:1};for(let t=0;t<12;t+=1){for(let e=0;e<4;e+=1)a(),await rI(r,{command:"swipe",direction:"up",appBundleId:i.appBundleId},n),await new Promise(e=>setTimeout(e,80));a();let o=await rI(r,{command:"findText",text:e,appBundleId:i.appBundleId},n);if(o?.found)return{attempts:t+2}}throw new I("COMMAND_FAILED",`scrollintoview could not find text: ${e}`)}})};default:throw new I("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,{requestId:a?.requestId,appBundleId:a?.appBundleId,verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath});return L({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await O("platform_command",async()=>{var s,l,d,u,c,p;switch(t){case"open":{let t=r[0],i=r[1];if(r.length>2)throw new I("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null};if(void 0!==i){if("ios"!==e.platform)throw new I("INVALID_ARGS","open <app> <url> is supported only on iOS");if(ek(t))throw new I("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!ek(i))throw new I("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:a?.activity,appBundleId:a?.appBundleId,url:i}),{app:t,url:i}}return await o.open(t,{activity:a?.activity,appBundleId:a?.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,i]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(i))throw new I("INVALID_ARGS","press requires x y");let n=iD(a?.count??1,"count",1,200),c=iD(a?.intervalMs??0,"interval-ms",0,1e4),p=iD(a?.holdMs??0,"hold-ms",0,1e4),f=iD(a?.jitterPx??0,"jitter-px",0,100),m=a?.doubleTap===!0;if(m&&p>0)throw new I("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(m&&f>0)throw new I("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(s=e,l=n,d=p,u=f,"ios"===s.platform&&l>1&&0===d&&0===u)return await rI(e,{command:"tapSeries",x:t,y:i,count:n,intervalMs:c,doubleTap:m,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x:t,y:i,count:n,intervalMs:c,holdMs:p,jitterPx:f,doubleTap:m,timingMode:"runner-series"};return await iO(n,c,async e=>{let[r,n]=function(e,t){if(t<=0)return[0,0];let[r,i]=i_[e%i_.length];return[r*t,i*t]}(e,f),a=t+r,s=i+n;m?await o.doubleTap(a,s):p>0?await o.longPress(a,s,p):await o.tap(a,s)}),{x:t,y:i,count:n,intervalMs:c,holdMs:p,jitterPx:f,doubleTap:m}}case"swipe":{let t=Number(r[0]),i=Number(r[1]),n=Number(r[2]),s=Number(r[3]);if([t,i,n,s].some(Number.isNaN))throw new I("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=iD(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=iD(a?.count??1,"count",1,200),f=iD(a?.pauseMs??0,"pause-ms",0,1e4),m=a?.pattern??"one-way";if("one-way"!==m&&"ping-pong"!==m)throw new I("INVALID_ARGS",`Invalid pattern: ${m}`);if(c=e,p=u,"ios"===c.platform&&p>1)return await rI(e,{command:"dragSeries",x:t,y:i,x2:n,y2:s,durationMs:d,count:u,pauseMs:f,pattern:m,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x1:t,y1:i,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:f,pattern:m};return await iO(u,f,async e=>{"ping-pong"===m&&e%2==1?await o.swipe(n,s,t,i,d):await o.swipe(t,i,n,s,d)}),{x1:t,y1:i,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:f,pattern:m}}case"longpress":{let e=Number(r[0]),t=Number(r[1]),i=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new I("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,i),{x:e,y:t,durationMs:i}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new I("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 I("INVALID_ARGS","type requires text");return await o.type(e),{text:e}}case"fill":{let e=Number(r[0]),t=Number(r[1]),i=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!i)throw new I("INVALID_ARGS","fill requires x y text");return await o.fill(e,t,i),{x:e,y:t,text:i}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0;if(!e)throw new I("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 I("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 I("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");let t=Number(r[0]),i=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new I("INVALID_ARGS","pinch requires scale > 0");return await rI(e,{command:"pinch",scale:t,x:i,y:n,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{scale:t,x:i,y:n}}case"trigger-app-event":{let{eventName:t,payload:i}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new I("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!iy.test(t))throw new I("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 I("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let i=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new I("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let i=JSON.stringify(r);if(Buffer.byteLength(i,"utf8")>8192)throw new I("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof I)throw t;throw new I("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:i}}(r),n=function(e,t,r){let i,n=(i=("ios"===e?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new I("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 a=r?JSON.stringify(r):"",o=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(a)).replaceAll("{platform}",encodeURIComponent(e));if(o.length>4096)throw new I("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:o.length,maxLength:4096});return o}(e.platform,t,i);return await o.open(n,{appBundleId:a?.appBundleId}),{event:t,eventUrl:n,transport:"deep-link"}}case"screenshot":{let e=r[0]??i??`./screenshot-${Date.now()}.png`;return await x.mkdir(n.dirname(e),{recursive:!0}),await o.screenshot(e,a?.appBundleId),{path:e}}case"back":if("ios"===e.platform)return await rI(e,{command:"back",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"back"};return await tn(e),{action:"back"};case"home":if("ios"===e.platform)return await rI(e,{command:"home",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"home"};return await ta(e),{action:"home"};case"app-switcher":if("ios"===e.platform)return await rI(e,{command:"appSwitcher",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"app-switcher"};return await to(e),{action:"app-switcher"};case"clipboard":{let t=(r[0]??"").toLowerCase();if("read"!==t&&"write"!==t)throw new I("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===t){if(1!==r.length)throw new I("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:t,text:"ios"===e.platform?await ii(e):await td(e)}}if(r.length<2)throw new I("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let i=r.slice(1).join(" ");return"ios"===e.platform?await ia(e,i):await tu(e,i),{action:t,textLength:Array.from(i).length}}case"keyboard":{if("android"!==e.platform)throw new I("UNSUPPORTED_OPERATION","keyboard is currently supported only on Android");let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new I("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new I("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("dismiss"===t){let t=await eZ(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let i=await eY(e);return{platform:"android",action:"status",visible:i.visible,inputType:i.inputType,type:i.type}}case"settings":{let[t,i,n,o,s]=r,l="permission"===t?{permissionTarget:n,permissionMode:o}:void 0;if(L({level:"debug",phase:"settings_apply",data:{setting:t,state:i,target:n,mode:o,platform:e.platform}}),"ios"===e.platform)return await is(e,t,i,s??a?.appBundleId,l),{setting:t,state:i};return await tw(e,t,i,s??a?.appBundleId,l),{setting:t,state:i}}case"push":{let t=r[0]?.trim(),i=r[1]?.trim();if(!t||!i)throw new I("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let n=await iE(i);if("ios"===e.platform)return await io(e,t,n),{platform:"ios",bundleId:t};let a=await tI(e,t,n);return{platform:"android",package:t,action:a.action,extrasCount:a.extrasCount}}case"snapshot":{if("ios"===e.platform){let t=await O("snapshot_capture",async()=>await rI(e,{command:"snapshot",appBundleId:a?.appBundleId,interactiveOnly:a?.snapshotInteractiveOnly,compact:a?.snapshotCompact,depth:a?.snapshotDepth,scope:a?.snapshotScope,raw:a?.snapshotRaw},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new I("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await O("snapshot_capture",async()=>await tv(e,{interactiveOnly:a?.snapshotInteractiveOnly,compact:a?.snapshotCompact,depth:a?.snapshotDepth,scope:a?.snapshotScope,raw:a?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}default:throw new I("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}let i_=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function iD(e,t,r,i){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>i)throw new I("INVALID_ARGS",`${t} must be an integer between ${r} and ${i}`);return e}async function iE(e){let t=iN(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await ik(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new I("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof I)throw t;throw new I("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function ik(e){try{return await x.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new I("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new I("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new I("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new I("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}async function iO(e,t,r){for(let i=0;i<e;i+=1)await r(i),i<e-1&&t>0&&await iL(t)}async function iL(e){await new Promise(t=>setTimeout(t,e))}let iM={alert:{ios:{simulator:!0},android:{}},pinch:{ios:{simulator:!0},android:{}},"app-switcher":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},apps:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},click:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},keyboard:{ios:{},android:{emulator:!0,device:!0,unknown:!0}},close:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},logs:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},reinstall:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},press:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},record:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},snapshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function ix(e,t){let r=iM[e];if(!r)return!0;let i=r[t.platform];return!!i&&!0===i[t.kind??"unknown"]}function iC(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 iT(e){let t=new Set,r=[];for(let i of e)t.has(i)||(t.add(i),r.push(i));return r}let iR=/^-?\d+(\.\d+)?$/,iP=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),i$=new Map([["--count","count"],["--pause-ms","pauseMs"]]);function iF(e){return"click"===e||"press"===e}function iV(e){let t=e.trim();return t.startsWith("@")||iR.test(t)?t:JSON.stringify(t)}function iG(e,t){let r=t.flags??{};if(iF(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");return}"swipe"===t.command&&("number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern))}function iU(e,t){let r=[],i={},n=iF(e)?iP:"swipe"===e?i$:void 0;for(let a=0;a<t.length;a+=1){let o=t[a];if(iF(e)&&"--double-tap"===o){i.doubleTap=!0;continue}let s=n?.get(o);if(s&&a+1<t.length){let e=function(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}(t[a+1]);null!==e&&(i[s]=e),a+=1;continue}if("swipe"===e&&"--pattern"===o&&a+1<t.length){let e=t[a+1];("one-way"===e||"ping-pong"===e)&&(i.pattern=e),a+=1;continue}r.push(o)}return{positionals:r,flags:i}}class iB{sessions=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.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=iB.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:i,serial:n,out:a,verbose:o,snapshotInteractiveOnly:s,snapshotCompact:l,snapshotDepth:d,snapshotScope:u,snapshotRaw:c,relaunch:p,saveScript:f,noRecord:m,count:h,intervalMs:w,holdMs:g,jitterPx:I,doubleTap:v,pauseMs:A,pattern:y}=e;return{platform:t,device:r,udid:i,serial:n,out:a,verbose:o,snapshotInteractiveOnly:s,snapshotCompact:l,snapshotDepth:d,snapshotScope:u,snapshotRaw:c,relaunch:p,saveScript:f,noRecord:m,count:h,intervalMs:w,holdMs:g,jitterPx:I,doubleTap:v,pauseMs:A,pattern:y}}(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=n.dirname(t);R.existsSync(r)||R.mkdirSync(r,{recursive:!0});let i=function(e,t){let r=[],i=e.device.name.replace(/"/g,'\\"'),n=e.device.kind?` kind=${e.device.kind}`:"";for(let a of(r.push(`context platform=${e.device.platform} device="${i}"${n} theme=unknown`),t))a.flags?.noRecord||r.push(function(e){let t=[e.command];if(iF(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(iV(r));let i=e.result?.refLabel;return"string"==typeof i&&i.trim().length>0&&t.push(iV(i)),iG(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(iV(r)),iG(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(iV(r));let i=e.result?.refLabel,n=e.positionals.slice(1).join(" ");return"string"==typeof i&&i.trim().length>0&&t.push(iV(i)),n&&t.push(iV(n)),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],i=e.positionals?.[1];if(r&&i){if(t.push(iV(r)),t.push(iV(i)),i.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(iV(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",iV(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(iV(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}for(let r of e.positionals??[])t.push(iV(r));return iG(t,e),t.join(" ")}(a));return`${r.join("\n")}
26
+ `}(e,this.buildOptimizedActions(e));R.writeFileSync(t,i)}catch{}}defaultTracePath(e){let t=iB.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return n.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return n.join(this.sessionsDir,iB.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return n.join(this.sessionsDir,iB.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return e.startsWith("~/")?n.join(F.homedir(),e.slice(2)):t&&!n.isAbsolute(e)?n.resolve(t,e):n.resolve(e)}resolveScriptPath(e){if(e.saveScriptPath)return iB.expandHome(e.saveScriptPath);R.existsSync(this.sessionsDir)||R.mkdirSync(this.sessionsDir,{recursive:!0});let t=iB.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return n.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let i=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(i.length>0&&(iF(r.command)||"fill"===r.command||"get"===r.command)){let e=i.join(" || ");if(iF(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let i=iC(r);if(i.length>0){t.push({...r,positionals:[e,i]});continue}}if("get"===r.command){let i=r.positionals?.[0];if("text"===i||"attrs"===i){t.push({...r,positionals:[i,e]});continue}}}if(iF(r.command)||"fill"===r.command||"get"===r.command){let i=r.result?.refLabel;"string"==typeof i&&i.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:i.trim()},result:{scope:i.trim()}})}t.push(r)}return t}}function iq(e,t,r,i,n){return{requestId:n??k().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:i,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,count:t?.count,intervalMs:t?.intervalMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,doubleTap:t?.doubleTap,pauseMs:t?.pauseMs,pattern:t?.pattern}}let ij=tG(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function iW(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:rK}));await t(e);return}if("device"===e.kind)return void await iH(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:eE}));await t(e.id)}}async function iH(e){let t=n.join(F.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(ij/1e3));try{let i=await p("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:ij+3e3}),n=String(i.stdout??""),a=String(i.stderr??""),o=await iJ(t);if(0===i.exitCode){if(!o.parsed)throw new I("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:n,stderr:a,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 I("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 I("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:n,stderr:a,exitCode:i.exitCode,tunnelState:o?.tunnelState,hint:iz(n,a)})}catch(t){if(t instanceof I&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},i=String(r.stdout??""),n=String(r.stderr??""),a=Number(r.timeoutMs??ij),o=`CoreDevice did not respond within ${a}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new I("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:a,stdout:i,stderr:n,hint:i||n?iz(i,n):o},t)}throw new I("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 iJ(e){try{let t=await x.readFile(e,"utf8"),r=JSON.parse(t),i=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,i=t.device?.connectionProperties?.tunnelState,n="string"==typeof r?r:"string"==typeof i?i:void 0;return n?{tunnelState:n}:{}}(r);return{parsed:!0,tunnelState:i.tunnelState}}catch{return{parsed:!1}}}function iz(e,t){let r=t6(e,t);return r||(`${e}
27
+ ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":t5)}function iK(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function iX(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function iY(e,t){return e.find(e=>e.ref===t)??null}function iZ(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function iQ(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),i=(e.value??"").toLowerCase(),n=(e.identifier??"").toLowerCase();return t.includes(r)||i.includes(r)||n.includes(r)})??null}function i0(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&&i1(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,i=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!i1(t))continue;let n=Math.abs(e.rect.y+e.rect.height/2-r);(!i||n<i.distance)&&(i={label:t,distance:n})}return i?.label}(e,t)??(r&&i1(r)?r:void 0)}function i1(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function i2(e){let t=[],r=[];for(let i of e){let e=i.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let n=i3(i.type??""),a=[i.label,i.value,i.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!a&&i1(a);if(("group"===n||"ioscontentgroup"===n)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...i,depth:s})}return r}function i3(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 i4(e,t){let r=i3(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 i8(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let i5=new Set(["id","role","text","label","value"]),i6=new Set(["visible","hidden","editable","selected","enabled","hittable"]),i9=new Set([...i5,...i6]);function i7(e){let t=e.trim();if(!t)throw new I("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",i=null;for(let n=0;n<e.length;n+=1){let a=e[n];if(('"'===a||"'"===a)&&!ng(e,n)){i?i===a&&(i=null):i=a,r+=a;continue}if(!i&&"|"===a&&"|"===e[n+1]){let i=r.trim();if(!i)throw new I("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(i),r="",n+=1;continue}r+=a}let n=r.trim();if(!n)throw new I("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(n),t}(t);if(0===r.length)throw new I("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new I("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",i=null;for(let n=0;n<e.length;n+=1){let a=e[n];if(('"'===a||"'"===a)&&!ng(e,n)){i?i===a&&(i=null):i=a,r+=a;continue}if(!i&&/\s/.test(a)){r.trim().length>0&&t.push(r.trim()),r="";continue}r+=a}if(i)throw new I("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim().length>0&&t.push(r.trim()),t}(t);if(0===r.length)throw new I("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(nd)}})(e))}}function ne(e){try{return i7(e)}catch{return null}}function nt(e,t,r){let i=r.requireRect??!1,n=r.requireUnique??!0,a=r.disambiguateAmbiguous??!1,o=[];for(let s=0;s<t.selectors.length;s+=1){let l=t.selectors[s],d=function(e,t,r){let i=0,n=null,a=null,o=!1;for(let s of e){if(r.requireRect&&!s.rect||!nu(s,t,r.platform))continue;if(i+=1,n||(n=s),!a){a=s;continue}let e=function(e,t){let r=e.depth??0,i=t.depth??0;if(r!==i)return r>i?1:-1;let n=nw(e),a=nw(t);return n!==a?n<a?1:-1:0}(s,a);if(e>0){a=s,o=!1;continue}0===e&&(o=!0)}return{count:i,firstNode:n,disambiguated:o?null:a}}(e,l,{platform:r.platform,requireRect:i});if(o.push({selector:l.raw,matches:d.count}),0!==d.count&&d.firstNode){if(n&&1!==d.count){if(!a)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 nr(e,t,r){let i=r.requireRect??!1,n=[];for(let a=0;a<t.selectors.length;a+=1){let o=t.selectors[a],s=function(e,t,r){let i=0;for(let n of e)(!r.requireRect||n.rect)&&nu(n,t,r.platform)&&(i+=1);return i}(e,o,{platform:r.platform,requireRect:i});if(n.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:a,selector:o,matches:s,diagnostics:n}}return null}function ni(e,t,r){let i=r.unique??!0;if(0===t.length)return`Selector did not match: ${e.raw}`;let n=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return i?`Selector did not resolve uniquely (${n})`:`Selector did not match (${n})`}function nn(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,i=0,n=[];for(;i<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return i9.has(e)}return i9.has(t.toLowerCase())}(e[i]);){i+=1;let t=e.slice(0,i).join(" ").trim();t&&ne(t)&&n.push(i)}if(0===n.length)return null;let a=n[n.length-1];if(r){for(let t=n.length-1;t>=0;t-=1)if(n[t]<e.length){a=n[t];break}}let o=e.slice(0,a).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(a)}:null}function na(e){let t=e[0]??"",r=nn(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function no(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function ns(e,t){return i4(e.type??"",t)&&!1!==e.enabled}function nl(e,t,r={}){let i=[],n=i3(e.type??""),a=nh(e.identifier),o=nh(e.label),s=nh(e.value),l=nh(i8(e)),d="fill"===r.action;a&&i.push(`id=${nm(a)}`),n&&o&&i.push(d?`role=${nm(n)} label=${nm(o)} editable=true`:`role=${nm(n)} label=${nm(o)}`),o&&i.push(d?`label=${nm(o)} editable=true`:`label=${nm(o)}`),s&&i.push(d?`value=${nm(s)} editable=true`:`value=${nm(s)}`),l&&l!==o&&l!==s&&i.push(d?`text=${nm(l)} editable=true`:`text=${nm(l)}`),n&&d&&!i.some(e=>e.includes("editable=true"))&&i.push(`role=${nm(n)} editable=true`);let u=iT(i);return 0===u.length&&n&&u.push(d?`role=${nm(n)} editable=true`:`role=${nm(n)}`),0===u.length&&no(e)&&u.push("visible=true"),u}function nd(e){let t=e.trim();if(!t)throw new I("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!i6.has(r))throw new I("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let i=t.slice(0,r).trim().toLowerCase(),n=t.slice(r+1).trim();if(!i9.has(i))throw new I("INVALID_ARGS",`Unknown selector key: ${i}`);if(!n)throw new I("INVALID_ARGS",`Missing selector value for key: ${i}`);if(i6.has(i)){let e,t="true"===(e=nc(n).toLowerCase())||"false"!==e&&null;if(null===t)throw new I("INVALID_ARGS",`Invalid boolean value for ${i}: ${n}`);return{key:i,value:t}}return{key:i,value:nc(n)}}function nu(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return np(e.identifier,String(t.value));case"role":var i,n;return i=e.type,n=String(t.value),function(e){return i3(e)}(i??"")===function(e){return i3(e)}(n);case"label":return np(e.label,String(t.value));case"value":return np(e.value,String(t.value));case"text":{let r=nf(String(t.value));return nf(i8(e))===r}case"visible":return no(e)===!!t.value;case"hidden":return!no(e)==!!t.value;case"editable":return ns(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 nc(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function np(e,t){return nf(e??"")===nf(t)}function nf(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function nm(e){return JSON.stringify(e)}function nh(e){if(!e)return null;let t=e.trim();return t||null}function nw(e){return e.rect?e.rect.width*e.rect.height:1/0}function ng(e,t){let r=0;for(let i=t-1;i>=0&&"\\"===e[i];i-=1)r+=1;return r%2==1}function nI(e,t){let r=process.env[e];if(!r)return t;let i=Number.parseInt(r,10);return Number.isInteger(i)&&i>0?i:t}function nv(e,t){if(!e)return;let r=n.dirname(e);R.existsSync(r)||R.mkdirSync(r,{recursive:!0});let i={pid:t,startTime:T(t)??void 0,command:a(t)??void 0};R.writeFileSync(e,`${JSON.stringify(i)}
28
+ `)}function nA(e){if(e&&R.existsSync(e))try{R.unlinkSync(e)}catch{}}function ny(e){let t=n.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}`,i=`${e}.${r}`;R.existsSync(t)&&(R.existsSync(i)&&R.unlinkSync(i),R.renameSync(t,i))}}(e,{maxBytes:nI("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:nI("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function nN(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function nb(e){await new Promise(t=>setTimeout(t,e))}function nS(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],i="",n=i=>{(!(r.length>0)||r.some(e=>i.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(i,t.redactionPatterns))};return{onChunk:e=>{let t=`${i}${e}`.split("\n");for(let e of(i=t.pop()??"",t))n(`${e}
29
+ `)},flush:()=>{i&&(n(i),i="")}}}function n_(e,t,r){let i=e.stdout,n=e.stderr;return i&&n?(i.setEncoding("utf8"),n.setEncoding("utf8"),i.on("data",r.writer.onChunk),n.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(i=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),i({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function nD(e,t){let r=(await p("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function nE(e,t,r,i){let n="active",a=h("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=nS(t,{redactionPatterns:r});"number"==typeof a.pid&&nv(i,a.pid);let s=n_(a,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),nA(i),e));return{backend:"ios-simulator",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{a.killed||a.kill("SIGINT"),await nN(s),a.killed||a.kill("SIGKILL"),await nN(s),nA(i)}}}async function nk(e,t,r,i){let n="active",a=h("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=nS(t,{redactionPatterns:r});"number"==typeof a.pid&&nv(i,a.pid);let s=n_(a,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),nA(i),e));return{backend:"ios-device",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{a.killed||a.kill("SIGINT"),await nN(s),a.killed||a.kill("SIGKILL"),await nN(s),nA(i)}}}async function nO(e,t,r,i,n){let a,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await nD(e,t);if(!d){await nb(1e3);continue}let u=h("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});a=u;let c=nS(r,{redactionPatterns:i});o=n_(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&nv(n,u.pid);let p=await o;if(nA(n),a=void 0,o=void 0,l)break;0!==p.exitCode&&(s="failed"),await nb(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),nA(n)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,a&&!a.killed&&a.kill("SIGINT"),o&&await nN(o),a&&!a.killed&&a.kill("SIGKILL"),await nN(d),nA(n)}}}async function nL(e,t,r,i){ny(r);let n=R.createWriteStream(r,{flags:"a"}),a=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 nk(e.id,n,a,i):await nE(t,n,a,i);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new I("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await nO(e.id,t,n,a,i)}throw n.end(),new I("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function nM(e){await e.stop(),await nN(e.wait)}async function nx(e,t){let r={},i=[];if(t||i.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await p("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await p("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 p("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 p("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}return{checks:r,notes:i}}function nC(e){let t=n.dirname(e),r=n.basename(e);R.existsSync(t)||R.mkdirSync(t,{recursive:!0}),R.existsSync(e)?R.truncateSync(e,0):R.writeFileSync(e,"","utf8");let i=0;for(let e of R.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let a=e.slice(r.length+1);if(/^\d+$/.test(a))try{R.unlinkSync(n.join(t,e)),i+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:i}}let nT=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),nR=/https?:\/\/[^\s"'<>\])]+/i,nP=[/\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 n$(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 nF(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return nV(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(i?.[1])return i[1].trim()}}function nV(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function nG(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function nU(e,t,r,i){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(i,e)):t}let nB='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',nq=["platform","target","device","udid","serial","verbose","out"],nj=["platform","target","device","udid","serial","verbose","out"],nW=["path","start","stop","doctor","mark","clear"],nH=`logs requires ${nW.slice(0,-1).join(", ")}, or ${nW.at(-1)}`,nJ="Not implemented for this platform in this release.",nz="open-command-roundtrip",nK=tG(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),nX=tG(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function nY(e){let{sessionName:t,appName:r,appBundleId:i,startup:n}=e,a={session:t};return r&&(a.appName=r),i&&(a.appBundleId=i),n&&(a.startup=n),a}function nZ(e,t,r){return{durationMs:Math.max(0,Date.now()-e),measuredAt:new Date().toISOString(),method:nz,appTarget:t,appBundleId:r}}let nQ=["dump","log"],n0=`network requires ${nQ.join(" or ")}`,n1=["summary","headers","body","all"],n2=`network include mode must be one of: ${n1.join(", ")}`;function n3(e,t,r){return t||n4(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function n4(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}async function n8(e,t){"ios"!==e.platform||"simulator"!==e.kind||t<=0||await new Promise(e=>setTimeout(e,t))}async function n5(e){let{device:t,closeTarget:r,stopIosRunner:i,dispatch:n,outFlag:a,context:o,settleSimulator:s}=e;"ios"===t.platform&&await i(t.id),await n(t,"close",[r],a,o),await s(t,nK)}async function n6(e){let t=n4(e.flags)||!e.session?await e.resolveTargetDeviceFn(e.flags??{}):e.session.device;return!1!==e.ensureReady&&await e.ensureReadyFn(t),t}function n9(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 n7=async({avdName:e,serial:t,headless:r})=>{let{ensureAndroidEmulatorBooted:i}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:eD}));return await i({avdName:e,serial:t,headless:r})};async function ae(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:a,resolveDevice:o,dispatch:s,command:l,positionals:d,recordPositionals:u,deriveNextSession:c}=e,p=n.get(r),f=t.flags??{},m=n3(l,p,f);if(m)return m;let h=await n6({session:p,flags:f,ensureReadyFn:a,resolveTargetDeviceFn:o,ensureReady:!0});if(!ix(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,{...iq(i,t.flags,p?.appBundleId,p?.trace?.outPath)});if(p){let e=c?await c(p,w,h):p;n.recordAction(e,{command:l,positionals:u??d,flags:t.flags??{},result:w??{}}),e!==p&&n.set(r,e)}return{ok:!0,data:w??{}}}let at={ios:async(e,t,r)=>{let{reinstallIosApp:i}=await Promise.resolve().then(()=>({reinstallIosApp:it}));return await i(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:i}=await Promise.resolve().then(()=>({reinstallAndroidApp:tt}));return await i(e,t,r)}},ar={ios:async(e,t,r)=>{let{installIosApp:i}=await Promise.resolve().then(()=>({installIosApp:ie}));await i(e,r,{appIdentifierHint:t});let{bundleId:n}=await as(e,t);return n?{bundleId:n}:{}},android:async(e,t,r)=>{let{installAndroidApp:i}=await Promise.resolve().then(()=>({installAndroidApp:te}));await i(e,r);let{package:n}=await as(e,t);return n?{package:n}:{}}};async function ai(e){let t,{req:r,command:i,sessionName:n,sessionStore:a,ensureReady:o,resolveDevice:s,deployOps:l}=e,d=a.get(n),u=r.flags??{},c=n3(i,d,u);if(c)return c;let p=r.positionals?.[0]?.trim(),f=r.positionals?.[1]?.trim();if(!p||!f)return{ok:!1,error:{code:"INVALID_ARGS",message:`${i} requires: ${i} <app> <path-to-app-binary>`}};let m=iB.expandHome(f);if(!R.existsSync(m))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${m}`}};let h=await n6({session:d,flags:u,ensureReadyFn:o,resolveTargetDeviceFn:s,ensureReady:!1});if(!ix(i,h))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${i} is not supported on this device`}};if("ios"===h.platform){let e=(await l.ios(h,p,m)).bundleId;t=e?{app:p,appPath:m,platform:"ios",appId:e,bundleId:e}:{app:p,appPath:m,platform:"ios"}}else{let e=(await l.android(h,p,m)).package;t=e?{app:p,appPath:m,platform:"android",appId:e,package:e}:{app:p,appPath:m,platform:"android"}}return d&&a.recordAction(d,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:t}),{ok:!0,data:t}}async function an(e,t,r){if("ios"===e.platform&&t)return ek(t)?"device"===e.kind?eO(r,t):void 0:await aa(e,t)}async function aa(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:r8}));return await r(e,t)}catch{return}}async function ao(e,t){if(!("android"!==e.platform||!t||ek(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:eW})),i=await r(e,t);return"package"===i.type?i.value:void 0}catch{return}}async function as(e,t){return"ios"===e.platform?{bundleId:await aa(e,t)}:{package:await ao(e,t)}}async function al(e,t,r,i){return await an(e,t,r)??await i(e,t)??("android"===e.platform&&t&&ek(t)?r:void 0)}async function ad(e){let{req:t,sessionName:r,sessionStore:i,ensureReady:n,resolveDevice:a}=e,o=i.get(r),s=t.flags??{},l=q(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=n3("appstate",o,s);if(d)return d;let u=o?.device.platform==="ios"&&function(e,t){if(!t)return!1;if(!n4(e))return!0;let r=q(e?.platform);return!(r&&r!==t.device.platform||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(s,o);if("ios"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:nB}};if(u){let e=o.appName??o.appBundleId;return o.appName||o.appBundleId?{ok:!0,data:{platform:"ios",appName:e??"unknown",appBundleId:o.appBundleId,source:"session"}}:{ok:!1,error:{code:"COMMAND_FAILED",message:"No foreground app is tracked for this iOS session. Open an app in the session, then retry appstate."}}}let c=await n6({session:o,flags:s,ensureReadyFn:n,resolveTargetDeviceFn:a,ensureReady:!0});if("ios"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:nB}};let{getAndroidAppState:p}=await Promise.resolve().then(()=>({getAndroidAppState:eX})),f=await p(c);return{ok:!0,data:{platform:"android",package:f.package,activity:f.activity}}}async function au(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:a,resolveDevice:o,dispatch:s}=e,l=n.get(r),d=t.flags??{},u=n3("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 n6({session:l,flags:d,ensureReadyFn:a,resolveTargetDeviceFn:o,ensureReady:!0});if(!ix("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,{...iq(i,t.flags,l?.appBundleId,l?.trace?.outPath)});return l&&n.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:f??{}}),{ok:!0,data:{platform:p.platform,...f??{}}}}async function ac(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,invoke:a,dispatch:o,ensureReady:s,resolveTargetDevice:l,installOps:d=ar,reinstallOps:u=at,stopIosRunner:c,appLogOps:p={start:nL,stop:nM},ensureAndroidEmulatorBoot:f=n7,resolveAndroidPackageForOpen:m=ao,settleSimulator:h}=e,g=o??iS,v=s??iW,A=l??ib,y=c??rN,N=h??n8,b=t.command;if("session_list"===b)return{ok:!0,data:{sessions:n.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",device:e.device.name,id:e.device.id,createdAt:e.createdAt}))}};if("devices"===b)try{let e=[],r=en(t.flags?.iosSimulatorDeviceSet),i=eo(t.flags?.androidDeviceAllowlist),n=q(t.flags?.platform);if("android"===n){let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:eA}));e.push(...await t({serialAllowlist:i}))}else if("ios"===n){let{listIosDevices:t}=await Promise.resolve().then(()=>({listIosDevices:tQ}));e.push(...await t({simulatorSetPath:r}))}else{let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:eA})),{listIosDevices:n}=await Promise.resolve().then(()=>({listIosDevices:tQ}));try{e.push(...await t({serialAllowlist:i}))}catch{}try{e.push(...await n({simulatorSetPath:r}))}catch{}}let a=(t.flags?.target?e.filter(e=>(e.target??"mobile")===t.flags?.target):e).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:a}}}catch(t){let e=w(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===b){let e=n.get(r),i=t.flags??{},a=n3(b,e,i);if(a)return a;let o=await n6({session:e,flags:i,ensureReadyFn:v,resolveTargetDeviceFn:A,ensureReady:!0});if(!ix("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if("ios"===o.platform){let{listIosApps:e}=await Promise.resolve().then(()=>({listIosApps:il}));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:eH}));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"===b){let e,i=n.get(r),a=t.flags??{},o=n3(b,i,a);if(o)return o;let s="android"===(q(a.platform)??i?.device.platform),l=!0===a.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=n9({flags:a,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await n6({session:i,flags:a,ensureReadyFn:v,resolveTargetDeviceFn:A,ensureReady:!1})}catch(r){let t=w(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:a.serial,headless:l}),c=!0}if(a.target&&(e.target??"mobile")!==a.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${a.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=n9({flags:a,sessionDevice:i?.device,resolvedDevice:e});if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await f({avdName:t,serial:a.serial,headless:!0})}await v(e)}else("android"!==e.platform||!0!==e.booted)&&await v(e);return ix("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"===b)return await ad({req:t,sessionName:r,sessionStore:n,ensureReady:v,resolveDevice:A});if("clipboard"===b)return await au({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:v,resolveDevice:A,dispatch:g});if("keyboard"===b)return await ae({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:v,resolveDevice:A,dispatch:g,command:"keyboard",positionals:t.positionals??[]});if("perf"===b){let e,t,i,a=n.get(r);return a?{ok:!0,data:(i=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===nz&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:nz,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)}(a.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:nz,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:nz},{session:a.name,platform:a.device.platform,device:a.device.name,deviceId:a.device.id,metrics:{startup:i,fps:{available:!1,reason:nJ},memory:{available:!1,reason:nJ},cpu:{available:!1,reason:nJ}},sampling:{startup:{method:nz,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"===b||"reinstall"===b)return await ai({req:t,command:b,sessionName:r,sessionStore:n,ensureReady:v,resolveDevice:A,deployOps:"install"===b?d:u});if("push"===b){let e,a=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();if(!a||!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}};let s="file"===(e=iN(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>iB.expandHome(e,t)})).kind?e.path:e.text;return await ae({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:v,resolveDevice:A,dispatch:g,command:"push",positionals:[a,s],recordPositionals:[a,o]})}if("trigger-app-event"===b)return await ae({req:t,sessionName:r,logPath:i,sessionStore:n,ensureReady:v,resolveDevice:A,dispatch:g,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,i=r?await al(e.device,r,e.appBundleId,m)??e.appBundleId:e.appBundleId;return{...e,appBundleId:i}}});if("open"===b){let e=t.flags?.relaunch===!0;if(n.has(r)){let a=n.get(r),o=t.positionals?.[0],s=o??(e?a?.appName:void 0);if(!a||!s)return e?{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app name or an active session app."}}:{ok:!1,error:{code:"INVALID_ARGS",message:"Session already active. Close it first or pass a new --session name."}};if(e&&ek(s))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};await v(a.device);let l=await al(a.device,s,a.appBundleId,m),d=o?t.positionals??[]:[s];if(e){let e=l??s;await n5({device:a.device,closeTarget:e,stopIosRunner:y,dispatch:g,outFlag:t.flags?.out,context:{...iq(i,t.flags,l??a.appBundleId,a.trace?.outPath)},settleSimulator:N})}let u=Date.now();await g(a.device,"open",d,t.flags?.out,{...iq(i,t.flags,l)});let c=nZ(u,s,l);await N(a.device,nX);let p={...a,appBundleId:l,appName:s,recordSession:a.recordSession||!!t.flags?.saveScript,snapshot:void 0},f=nY({sessionName:r,appName:s,appBundleId:l,startup:c});return n.recordAction(p,{command:b,positionals:d,flags:t.flags??{},result:f}),n.set(r,p),{ok:!0,data:f}}let a=t.positionals?.[0];if(e&&!a)return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app argument."}};if(e&&a&&ek(a))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};let o=await A(t.flags??{}),s=n.toArray().find(e=>e.device.id===o.id);if(s)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${s.name}".`,details:{session:s.name,deviceId:o.id,deviceName:o.name}}};await v(o);let l=await al(o,a,void 0,m);if(e&&a){let e=l??a;await n5({device:o,closeTarget:e,stopIosRunner:y,dispatch:g,outFlag:t.flags?.out,context:{...iq(i,t.flags,l)},settleSimulator:N})}let d=Date.now();await g(o,"open",t.positionals??[],t.flags?.out,{...iq(i,t.flags,l)});let u=a?nZ(d,a,l):void 0;await N(o,nX);let c={name:r,device:o,createdAt:Date.now(),appBundleId:l,appName:a,recordSession:!!t.flags?.saveScript,actions:[]},p=nY({sessionName:r,appName:a,appBundleId:l,startup:u});return n.recordAction(c,{command:b,positionals:t.positionals??[],flags:t.flags??{},result:p}),n.set(r,c),{ok:!0,data:p}}if("replay"===b){let e=t.positionals?.[0];if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};try{let o=iB.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 i=r+1,n=!1;for(;i<e.length;){let t=e[i];if('"'===t&&!n)break;n="\\"===t&&!n,"\\"!==t&&(n=!1),i+=1}if(i>=e.length)throw new I("INVALID_ARGS",`Invalid replay script line: ${e}`);let a=e.slice(r,i+1);t.push(JSON.parse(a)),r=i+1;continue}let i=r;for(;i<e.length&&!/\s/.test(e[i]);)i+=1;t.push(e.slice(r,i)),r=i}return t}(t);if(0===r.length)return null;let[i,...n]=r;if("context"===i)return null;let a={ts:Date.now(),command:i,positionals:[],flags:{}};if("snapshot"===i){a.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("-i"===t){a.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){a.flags.snapshotCompact=!0;continue}if("--raw"===t){a.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<n.length){let t=Number(n[e+1]);Number.isFinite(t)&&t>=0&&(a.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<n.length){a.flags.snapshotScope=n[e+1],e+=1;continue}if("--backend"===t&&e+1<n.length){e+=1;continue}}return a}if("open"===i){a.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("--relaunch"===t){a.flags.relaunch=!0;continue}a.positionals.push(t)}return a}if(iF(i)){let e=iU(i,n);if(Object.assign(a.flags,e.flags),0===e.positionals.length)return a;let t=e.positionals[0];if(t.startsWith("@"))return a.positionals=[t],e.positionals[1]&&(a.result={refLabel:e.positionals[1]}),a;let r=e.positionals[0],o=e.positionals[1];return av(r)&&av(o)&&e.positionals.length>=2?a.positionals=[r,o]:a.positionals=[e.positionals.join(" ")],a}if("fill"===i){if(n.length<2)return a.positionals=n,a;let e=n[0];return e.startsWith("@")?(n.length>=3?(a.positionals=[e,n.slice(2).join(" ")],a.result={refLabel:n[1]}):a.positionals=[e,n[1]],a):(a.positionals=[e,n.slice(1).join(" ")],a)}if("get"===i){if(n.length<2)return a.positionals=n,a;let e=n[0],t=n[1];return t.startsWith("@")?(a.positionals=[e,t],n[2]&&(a.result={refLabel:n[2]})):a.positionals=[e,n.slice(1).join(" ")],a}if("swipe"===i){let e=iU(i,n);return Object.assign(a.flags,e.flags),a.positionals=e.positionals,a}return a.positionals=n,a}(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 a({token:t.token,session:r,command:s.command,positionals:s.positionals??[],flags:ah(t.flags,s.flags),meta:t.meta});if(l.ok)continue;if(!u)return am(l,s,e,o);let p=await aw({action:s,sessionName:r,logPath:i,sessionStore:n,dispatch:g});if(!p)return am(l,s,e,o);if(d[e]=p,!(l=await a({token:t.token,session:r,command:p.command,positionals:p.positionals??[],flags:ah(t.flags,p.flags),meta:t.meta})).ok)return am(l,p,e,o);c+=1}if(u&&c>0){let e=n.get(r);!function(e,t,r){let i=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",n=r.device.target?` target=${r.device.target}`:"";i.push(`context platform=${r.device.platform}${n} device="${e}"${t} theme=unknown`)}for(let e of t)i.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",iV(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(iV(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}for(let r of e.positionals??[])t.push(iV(r));return iG(t,e),t.join(" ")}(e));let n=`${i.join("\n")}
30
+ `,a=`${e}.tmp-${process.pid}-${Date.now()}`;R.writeFileSync(a,n),R.renameSync(a,e)}(o,d,e)}return{ok:!0,data:{replayed:d.length,healed:c,session:r}}}catch(t){let e=w(t);return{ok:!1,error:{code:e.code,message:e.message}}}}if("logs"===b){let e=n.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};let i=(t.positionals?.[0]??"path").toLowerCase(),a=!!t.flags?.restart;if(!nW.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:nH}};if(a&&"clear"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===i){let t=n.resolveAppLogPath(r),i=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),a=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android");return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:a,sizeBytes:i.sizeBytes,modifiedAt:i.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===i){let t=n.resolveAppLogPath(r),i=await nx(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}if("mark"===i){let e,i=t.positionals?.slice(1).join(" ")??"",a=n.resolveAppLogPath(r);return ny(a),e=`[agent-device][mark][${new Date().toISOString()}] ${i.trim()||"marker"}
31
+ `,R.appendFileSync(a,e,"utf8"),{ok:!0,data:{path:a,marked:!0}}}if("clear"===i){if(e.appLog&&!a)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(a){if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};if(!ix("logs",e.device))return{ok:!1,error:S(new I("UNSUPPORTED_OPERATION","logs is not supported on this device"))}}let t=n.resolveAppLogPath(r);if(a){e.appLog&&await p.stop(e.appLog);let i=nC(t),a=n.resolveAppLogPidPath(r);try{let o=await p.start(e.device,e.appBundleId,t,a),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 n.set(r,s),{ok:!0,data:{...i,restarted:!0}}}catch(i){let t=S(i);return n.set(r,{...e,appLog:void 0}),{ok:!1,error:t}}}return{ok:!0,data:nC(t)}}if("start"===i){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};if(!ix("logs",e.device))return{ok:!1,error:S(new I("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let t=n.resolveAppLogPath(r),i=n.resolveAppLogPidPath(r);try{let a=await p.start(e.device,e.appBundleId,t,i),o={...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:t,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}};return n.set(r,o),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:S(e)}}}if("stop"===i){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await p.stop(e.appLog),n.set(r,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===b){let e=n.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};let i=(t.positionals?.[0]??"dump").toLowerCase();if(!nQ.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:n0}};let a=t.positionals?.[1],o=a?Number.parseInt(a,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(!n1.includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:n2}};let l=function(e,t){let r=nU(t?.maxEntries,25,1,200),i=t?.include??"summary",n=nU(t?.maxPayloadChars,2048,64,16384),a=nU(t?.maxScanLines,4e3,100,2e4);if(!R.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:a}};let o=R.readFileSync(e,"utf8").split("\n"),s=Math.max(0,o.length-a),l=o.slice(s),d=[];for(let e=l.length-1;e>=0&&d.length<r;e-=1){let t=l[e]?.trim();if(!t)continue;let r=function(e,t,r,i){let n=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let i=e.slice(t,r+1);try{let e=JSON.parse(i);return e&&"object"==typeof e?e:null}catch{return null}}(e),a=n$(n,["method","httpMethod"]),o=n$(n,["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}(n,["status","statusCode","responseCode"]),l=nT.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(a??d?.[1]??l?.[1])?.toUpperCase(),c=nR.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of nP){let r=t.exec(e);if(!r)continue;let i=Number.parseInt(r[1]??"",10);if(Number.isInteger(i))return i}return null}(e)??void 0,timestamp:function(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);return t?.[0]}(e),raw:nG(e,i),line:t};if("headers"===r||"all"===r){let t=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return nV(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,n);t&&(f.headers=nG(t,i))}if("body"===r||"all"===r){let t=nF(e,n,["requestBody","body","payload","request"]),r=nF(e,n,["responseBody","response"]);t&&(f.requestBody=nG(t,i)),r&&(f.responseBody=nG(r,i))}return f}(t,s+e+1,i,n);r&&d.push(r)}return{path:e,exists:!0,scannedLines:l.length,matchedLines:d.length,entries:d,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:a}}}(n.resolveAppLogPath(r),{maxEntries:o,include:s,maxPayloadChars:2048,maxScanLines:4e3}),d=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"),u=[];return e.appLog||u.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===l.entries.length&&u.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...l,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:d,notes:u}}}if("batch"===b)return await ap(t,r,a);if("close"===b){let e=n.get(r);return e?(e.appLog&&await p.stop(e.appLog),t.positionals&&t.positionals.length>0&&("ios"===e.device.platform&&await y(e.device.id),await g(e.device,"close",t.positionals,t.flags?.out,{...iq(i,t.flags,e.appBundleId,e.trace?.outPath)}),await N(e.device,nK)),"ios"===e.device.platform&&await y(e.device.id),n.recordAction(e,{command:b,positionals:t.positionals??[],flags:t.flags??{},result:{session:r}}),t.flags?.saveScript&&(e.recordSession=!0),n.writeSessionLog(e),n.delete(r),{ok:!0,data:{session:r}}):{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}}}return null}async function ap(e,t,r){let i=e.flags?.batchOnError??"stop";if("stop"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${i}.`}};let n=e.flags?.batchMaxSteps??M;if(!Number.isInteger(n)||n<1||n>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let i=o(e.flags?.batchSteps,n),a=Date.now(),s=[];for(let n=0;n<i.length;n+=1){let a=i[n],o=await af(e,t,a,r,n+1);if(!o.ok)return{ok:!1,error:{code:o.error.code,message:`Batch failed at step ${o.step} (${a.command}): ${o.error.message}`,hint:o.error.hint,diagnosticId:o.error.diagnosticId,logPath:o.error.logPath,details:{...o.error.details??{},step:o.step,command:a.command,positionals:a.positionals,executed:n,total:i.length,partialResults:s}}};s.push(o.result)}return{ok:!0,data:{total:i.length,executed:i.length,totalDurationMs:Date.now()-a,results:s}}}catch(t){let e=w(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function af(e,t,r,i,n){let a=Date.now(),o=await i({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:function(e,t){let r={...t??{}};delete r.batchSteps,delete r.batchOnError,delete r.batchMaxSteps;let i=e??{};for(let e of nq)void 0===r[e]&&void 0!==i[e]&&(r[e]=i[e]);return r}(e.flags,r.flags),meta:e.meta}),s=Date.now()-a;return o.ok?{ok:!0,step:n,result:{step:n,command:r.command,ok:!0,data:o.data??{},durationMs:s}}:{ok:!1,step:n,error:o.error}}function am(e,t,r,i){if(e.ok)return e;let n=r+1,a=function(e){let t;return t=(e.positionals??[]).map(e=>iV(e)),[e.command,...t].join(" ")}(t),o={...e.error.details??{},replayPath:i,step:n,action:t.command,positionals:t.positionals??[]};return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${n} (${a}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:o}}}function ah(e,t){let r={...t??{}},i=e??{};for(let e of nj)void 0===r[e]&&void 0!==i[e]&&(r[e]=i[e]);return r}async function aw(e){let{action:t,sessionName:r,logPath:i,sessionStore:n,dispatch:a}=e;if(!(iF(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let o=n.get(r);if(!o)return null;let s=iF(t.command)||"fill"===t.command,l=iF(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await ag(o,t,i,s,a,n);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),iF(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}=na(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=aI(e.positionals??[]);r&&t.push(r)}let i="string"==typeof e.result?.refLabel?e.result.refLabel.trim():"";if(i.length>0){let r=JSON.stringify(i);"fill"===e.command?(t.push(`id=${r} editable=true`),t.push(`label=${r} editable=true`),t.push(`text=${r} editable=true`),t.push(`value=${r} editable=true`)):(t.push(`id=${r}`),t.push(`label=${r}`),t.push(`text=${r}`),t.push(`value=${r}`))}return iT(t).filter(e=>e.trim().length>0)}(t)){let r=ne(e);if(!r)continue;let i=nt(d.nodes,r,{platform:o.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!i)continue;let n=nl(i.node,o.device.platform,{action:iF(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(iF(t.command))return{...t,positionals:[n]};if("fill"===t.command){let e=iC(t);if(!e)continue;return{...t,positionals:[n,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,n]}}if("is"===t.command){let{predicate:e,split:r}=na(t.positionals);if(!e)continue;let i=r?.rest.join(" ").trim()??"",a=[e,n];return"text"===e&&i.length>0&&a.push(i),{...t,positionals:a}}if("wait"===t.command){let{selectorTimeout:e}=aI(t.positionals??[]),r=[n];return e&&r.push(e),{...t,positionals:r}}}let u=function(e,t,r){if("get"!==e.command||e.positionals?.[0]!=="text")return null;let i=e.positionals?.[1];if(!i)return null;let n=ne(i);if(!n)return null;let a=new Set,o=!1;for(let e of n.selectors)for(let t of e.terms)"role"===t.key&&"string"==typeof t.value&&a.add(i3(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=i8(e).trim();return!!/^\d+$/.test(t)&&(0===a.size||a.has(i3(e.type??"")))});if(0===s.length||1!==iT(s.map(e=>i8(e).trim())).length)return null;let l=s[0];if(!l)return null;let d=nl(l,r.device.platform,{action:"get"});return 0===d.length?null:{...e,positionals:["text",d.join(" || ")]}}(t,d,o);return u||null}async function ag(e,t,r,i,n,a){let o=await n(e.device,"snapshot",[],t.flags?.out,{...iq(r,{...t.flags??{},snapshotInteractiveOnly:i,snapshotCompact:i},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[],l={nodes:iK(t.flags?.snapshotRaw?s:i2(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend};return e.snapshot=l,a.set(e.name,e),l}function aI(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),i=nn(r?e.slice(0,-1):e.slice());return!i||i.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:i.selectorExpression,selectorTimeout:r?t:null}}function av(e){return!!e&&!Number.isNaN(Number(e))}function aA(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}function ay(e,t){let r=b(e.type??"Element"),i=m(e,r),n=!1===e.enabled?"disabled":"enabled",a=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,i,n,a,o].join("|")}function aN(e,t){return t.flatten?e.map(e=>({text:B(e,0,!1),comparable:ay(e,0)})):A(e).map(e=>({text:e.text,comparable:ay(e.node,e.depth)}))}function ab(e,t){return e.get(t)??0}async function aS(e){let{req:t,sessionName:r,logPath:i,sessionStore:n}=e,a=e.dispatchSnapshotCommand??iS,o=t.command;if("snapshot"===o){let{session:e,device:o}=await aE(n,r,t.flags);if(!ix("snapshot",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let s=aD(t.flags?.snapshotScope,e);return s.ok?await ak(e,o,async()=>{let l=e?.appBundleId,d=await a_({dispatchSnapshotCommand:a,device:o,session:e,req:t,logPath:i,snapshotScope:s.scope}),u=e?{...e,snapshot:d.snapshot}:{name:r,device:o,createdAt:Date.now(),appBundleId:l,snapshot:d.snapshot,actions:[]};return aO(n,u,t,{nodes:d.snapshot.nodes.length,truncated:d.snapshot.truncated??!1}),n.set(r,u),{ok:!0,data:{nodes:d.snapshot.nodes,truncated:d.snapshot.truncated??!1,appName:u.appBundleId?u.appName??u.appBundleId:void 0,appBundleId:u.appBundleId}}}):s.response}if("diff"===o){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 aE(n,r,t.flags);if(!ix("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let s=aD(t.flags?.snapshotScope,e);if(!s.ok)return s.response;let l=t.flags?.snapshotInteractiveOnly===!0;return await ak(e,o,async()=>{let d=e?.appBundleId,u=(await a_({dispatchSnapshotCommand:a,device:o,session:e,req:t,logPath:i,snapshotScope:s.scope})).snapshot;if(!e?.snapshot){let i=function(e,t={}){return aN(e,t).length}(u.nodes,{flatten:l}),a=e?{...e,snapshot:u}:{name:r,device:o,createdAt:Date.now(),appBundleId:d,snapshot:u,actions:[]};return aO(n,a,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:i}}),n.set(r,a),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:i},lines:[]}}}let c=function(e,t,r={}){let i=function(e,t){let r=e.length,i=t.length,n=r+i,a=new Map,o=[];a.set(1,0);for(let s=0;s<=n;s+=1){o.push(new Map(a));for(let n=-s;n<=s;n+=2){let l=n===-s||n!==s&&ab(a,n-1)<ab(a,n+1)?ab(a,n+1):ab(a,n-1)+1,d=l-n;for(;l<r&&d<i&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(a.set(n,l),l>=r&&d>=i)return function(e,t,r,i,n){let a=[],o=i,s=n;for(let i=e.length-1;i>=0;i-=1){let n=e[i],l=o-s,d=l===-i||l!==i&&ab(n,l-1)<ab(n,l+1)?l+1:l-1,u=ab(n,d),c=u-d;for(;o>u&&s>c;)a.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===i)break;o===u?(a.push({kind:"added",text:r[c].text}),s=c):(a.push({kind:"removed",text:t[u].text}),o=u)}return a.reverse(),a}(o,e,t,r,i)}}return[]}(aN(e,r),aN(t,r)),n={additions:0,removals:0,unchanged:0};for(let e of i)"added"===e.kind&&(n.additions+=1),"removed"===e.kind&&(n.removals+=1),"unchanged"===e.kind&&(n.unchanged+=1);return{summary:n,lines:i}}(e.snapshot.nodes,u.nodes,{flatten:l}),p={...e,snapshot:u};return aO(n,p,t,{mode:"snapshot",baselineInitialized:!1,summary:c.summary}),n.set(r,p),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:c.summary,lines:c.lines}}})}if("wait"===o){let{session:e,device:o}=await aE(n,r,t.flags),s=function(e){if(0===e.length)return null;let t=aA(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=aA(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=aA(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=aA(e[e.length-1]),i=nn(null!==r?e.slice(0,-1):e.slice());if(i&&0===i.rest.length){let e=ne(i.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:i.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);return s?"sleep"===s.kind?(await new Promise(e=>setTimeout(e,s.durationMs)),aO(n,e,t,{waitedMs:s.durationMs}),{ok:!0,data:{waitedMs:s.durationMs}}):ix("wait",o)?await ak(e,o,async()=>{let l,d;if("selector"===s.kind){let l=s.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let l=await a(o,"snapshot",[],t.flags?.out,{...iq(i,{...t.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},e?.appBundleId,e?.trace?.outPath)}),u=l?.nodes??[],c=iK(t.flags?.snapshotRaw?u:i2(u));e&&(e.snapshot={nodes:c,truncated:l?.truncated,createdAt:Date.now(),backend:l?.backend},n.set(r,e));let p=nr(c,s.selector,{platform:o.platform});if(p)return aO(n,e,t,{selector:p.selector.raw,waitedMs:Date.now()-d}),{ok:!0,data:{selector:p.selector.raw,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${s.selectorExpression}`}}}if("ref"===s.kind){if(!e?.snapshot)return{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}};let t=iX(s.rawRef);if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${s.rawRef}`}};let r=iY(e.snapshot.nodes,t),i=r?i0(r,e.snapshot.nodes):void 0;if(!i)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s.rawRef} not found or has no label`}};l=i,d=s.timeoutMs}else l=s.text,d=s.timeoutMs;if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}};let u=d??1e4,c=Date.now();for(;Date.now()-c<u;){if("ios"===o.platform){let r=await rI(o,{command:"findText",text:l,appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});if(r?.found)return aO(n,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}}}else if("android"===o.platform&&iQ(iK((await tv(o,{scope:l})).nodes??[]),l))return aO(n,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${l}`}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}}:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}}}if("alert"===o){let{session:e,device:a}=await aE(n,r,t.flags),o=(t.positionals?.[0]??"get").toLowerCase();return ix("alert",a)?await ak(e,a,async()=>{if("wait"===o){let r=aA(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<r;){try{let r=await rI(a,{command:"alert",action:"get",appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});return aO(n,e,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r=await rI(a,{command:"alert",action:"accept"===o||"dismiss"===o?o:"get",appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});return aO(n,e,t,r),{ok:!0,data:r}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is only supported on iOS simulators"}}}if("settings"===o){let e=t.positionals?.[0]?.toLowerCase(),a=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase();if(!e||!a||"permission"===e&&!o)return{ok:!1,error:{code:"INVALID_ARGS",message:u}};let{session:s,device:l}=await aE(n,r,t.flags);return ix("settings",l)?await ak(s,l,async()=>{let r=s?.appBundleId,d="permission"===e?[e,a,o,t.positionals?.[3]??"",r??""]:[e,a,r??""],u=await iS(l,"settings",d,t.flags?.out,{...iq(i,t.flags,r,s?.trace?.outPath)});return aO(n,s,t,u??{setting:e,state:a}),{ok:!0,data:u??{setting:e,state:a}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}}}return null}async function a_(e){let{dispatchSnapshotCommand:t,device:r,session:i,req:n,logPath:a,snapshotScope:o}=e,s=await t(r,"snapshot",[],n.flags?.out,{...iq(a,{...n.flags,snapshotScope:o},i?.appBundleId,i?.trace?.outPath)}),l=s?.nodes??[];return{snapshot:{nodes:iK(n.flags?.snapshotRaw?l:i2(l)),truncated:s?.truncated,createdAt:Date.now(),backend:s?.backend}}}function aD(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=iX(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let i=iY(t.snapshot.nodes,r),n=i?i0(i,t.snapshot.nodes):void 0;return n?{ok:!0,scope:n}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function aE(e,t,r){let i=e.get(t),n=i?.device??await ib(r??{});return i||await iW(n),{session:i,device:n}}async function ak(e,t,r){let i=!e&&"ios"===t.platform;try{return await r()}finally{i&&await rN(t.id)}}function aO(e,t,r,i){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:i})}function aL(e,t,r,i={}){let n=ax(r);if(!n)return{matches:[],score:0};let a=0,o=[];for(let r of e){if(i.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return aM(e.label,r);case"value":return aM(e.value,r);case"id":return aM(e.identifier,r);default:return Math.max(aM(e.label,r),aM(e.value,r),aM(e.identifier,r))}}(r,t,n);if(!(e<=0)){if(e>a){a=e,o.length=0,o.push(r);continue}e===a&&o.push(r)}}return{matches:o,score:a}}function aM(e,t){let r=ax(e??"");return r?r===t?2:+!!r.includes(t):0}function ax(e){return e.trim().toLowerCase().replace(/\s+/g," ")}async function aC(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,invoke:a}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a locator or text"}};let{locator:l,query:d,action:u,value:c,timeoutMs:p}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let i=e[r]??"",n=e.slice(r+1);if(0===n.length)return{locator:t,query:i,action:"click"};let a=n[0].toLowerCase();if("get"===a){let e=n[1]?.toLowerCase();if("text"===e)return{locator:t,query:i,action:"get_text"};if("attrs"===e)return{locator:t,query:i,action:"get_attrs"};throw new I("INVALID_ARGS","find get only supports text or attrs")}if("wait"===a)return{locator:t,query:i,action:"wait",timeoutMs:aA(n[1])??void 0};if("exists"===a)return{locator:t,query:i,action:"exists"};if("click"===a)return{locator:t,query:i,action:"click"};if("focus"===a)return{locator:t,query:i,action:"focus"};if("fill"===a)return{locator:t,query:i,action:"fill",value:n.slice(1).join(" ")};if("type"===a)return{locator:t,query:i,action:"type",value:n.slice(1).join(" ")};throw new I("INVALID_ARGS",`Unsupported find action: ${n[0]}`)}(s);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a value"}};let f=n.get(r);if(!f&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let m=f?.device??await ib(t.flags??{});f||await iW(m);let h=f?.appBundleId,w="role"!==l?d:void 0,g="click"===u||"focus"===u||"fill"===u||"type"===u,v=0,A=null,y=async()=>{let e=Date.now();if(A&&e-v<750)return{nodes:A};let a=await iS(m,"snapshot",[],t.flags?.out,{...iq(i,{...t.flags,snapshotScope:w,snapshotInteractiveOnly:g,snapshotCompact:g},h,f?.trace?.outPath)}),o=a?.nodes??[],s=iK(t.flags?.snapshotRaw?o:i2(o));return v=e,A=s,f&&(f.snapshot={nodes:s,truncated:a?.truncated,createdAt:Date.now(),backend:a?.backend},n.set(r,f)),{nodes:s,truncated:a?.truncated,backend:a?.backend}};if("wait"===u){let e=p??1e4,r=Date.now();for(;Date.now()-r<e;){let{nodes:e}=await y();if(aL(e,l,d,{requireRect:!1}).matches[0])return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0,waitedMs:Date.now()-r}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-r}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}let{nodes:N}=await y(),b=aL(N,l,d,{requireRect:g});if(g&&b.matches.length>1){let e=b.matches.slice(0,8).map(e=>{let t=i8(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`});return{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${b.matches.length} elements for ${l} "${d}". Use a more specific locator or selector.`,details:{locator:l,query:d,matches:b.matches.length,candidates:e}}}}let S=b.matches[0]??null;if(!S)return{ok:!1,error:{code:"COMMAND_FAILED",message:"find did not match any element"}};let _="click"===u||"focus"===u||"fill"===u||"type"===u?function(e,t){if(t.hittable)return t;let r=t,i=new Set;for(;void 0!==r.parentIndex&&!i.has(r.ref);){i.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}(N,S)??S:S,D=`@${_.ref}`,E={...t.flags??{},noRecord:!0};if("exists"===u)return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}};if("get_text"===u){let e=i8(S);return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"get text",text:e}}),{ok:!0,data:{ref:D,text:e,node:S}}}if("get_attrs"===u)return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"get attrs"}}),{ok:!0,data:{ref:D,node:S}};if("click"===u){let e=await a({token:t.token,session:r,command:"click",positionals:[D],flags:E});return e.ok&&f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"click"}}),e}if("fill"===u){if(!c)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let e=await a({token:t.token,session:r,command:"fill",positionals:[D,c],flags:E});return e.ok&&f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"fill"}}),e}if("focus"===u){let e=S.rect?iZ(S.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let r=await iS(m,"focus",[String(e.x),String(e.y)],t.flags?.out,{...iq(i,t.flags,f?.appBundleId,f?.trace?.outPath)});return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"focus"}}),{ok:!0,data:r??{ref:D}}}if("type"===u){if(!c)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let e=S.rect?iZ(S.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await iS(m,"focus",[String(e.x),String(e.y)],t.flags?.out,{...iq(i,t.flags,f?.appBundleId,f?.trace?.outPath)});let r=await iS(m,"type",[c],t.flags?.out,{...iq(i,t.flags,f?.appBundleId,f?.trace?.outPath)});return f&&n.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"type"}}),{ok:!0,data:r??{ref:D}}}return null}function aT(e){return e instanceof Error?e.message:String(e)}function aR(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function aP(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function a$(e){let{req:t,sessionName:r,sessionStore:i,logPath:a}=e,o=e.deps??{runCmd:p,runCmdBackground:d,runIosRunnerCommand:rI},s=t.command;if("record"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};let d=i.get(r),c=d?.device??await ib(t.flags??{});d||await iW(c);let p=d??{name:r,device:c,createdAt:Date.now(),actions:[]};if("start"===e){if(p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let e=t.flags?.fps;if(void 0!==e&&(!Number.isInteger(e)||e<1||e>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};let d=t.positionals?.[1]??`./recording-${Date.now()}.mp4`;if(!ix("record",c))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let f="ios"===c.platform&&"device"===c.kind?aR(p):void 0;if("ios"===c.platform&&"device"===c.kind&&!f)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};let m=iB.expandHome(d,t.meta?.cwd);R.mkdirSync(n.dirname(m),{recursive:!0});let h=aP(t,a,p);if("ios"===c.platform&&"device"===c.kind){let t=`agent-device-recording-${Date.now()}.mp4`,r=`tmp/${t}`,n=async()=>{await o.runIosRunnerCommand(c,{command:"recordStart",outPath:t,fps:e,appBundleId:f},h)};try{await n()}catch(e){if(!aT(e).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${aT(e)}`}};{var l,u;L({level:"warn",phase:"record_start_runner_desynced",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:aT(e)}});let t=(l=c.id,u=p.name,i.toArray().find(e=>e.name!==u&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===l&&e.recording?.platform==="ios-device-runner"));if(t)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${t.name}'`}};try{await o.runIosRunnerCommand(c,{command:"recordStop",appBundleId:f},h)}catch{}try{await n()}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${aT(e)}`}}}}}p.recording={platform:"ios-device-runner",outPath:m,remotePath:r}}else if("ios"===c.platform){let{child:e,wait:t}=o.runCmdBackground("xcrun",tB(c,["io",c.id,"recordVideo",m]),{allowFailure:!0});p.recording={platform:"ios",outPath:m,child:e,wait:t}}else{let e=`/sdcard/agent-device-recording-${Date.now()}.mp4`,{child:t,wait:r}=o.runCmdBackground("adb",["-s",c.id,"shell","screenrecord",e],{allowFailure:!0});p.recording={platform:"android",outPath:m,remotePath:e,child:t,wait:r}}return i.set(r,p),i.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start"}}),{ok:!0,data:{recording:"started",outPath:d}}}if(!p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let f=p.recording;if("ios-device-runner"===f.platform){let e=aR(p);try{await o.runIosRunnerCommand(c,{command:"recordStop",appBundleId:e},aP(t,a,p))}catch(e){L({level:"warn",phase:"record_stop_runner_failed",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:aT(e)}})}let r={stdout:"",stderr:"",exitCode:1};for(let e of rn)if(0===(r=await o.runCmd("xcrun",["devicectl","device","copy","from","--device",c.id,"--source",f.remotePath,"--destination",f.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(p.recording=void 0,0!==r.exitCode){let e=r.stderr.trim()||r.stdout.trim()||`devicectl exited with code ${r.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}}else{f.child.kill("SIGINT");try{await f.wait}catch{}if("android"===f.platform&&f.remotePath)try{await o.runCmd("adb",["-s",c.id,"pull",f.remotePath,f.outPath],{allowFailure:!0}),await o.runCmd("adb",["-s",c.id,"shell","rm","-f",f.remotePath],{allowFailure:!0})}catch{}p.recording=void 0}return i.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:f.outPath}}),{ok:!0,data:{recording:"stopped",outPath:f.outPath}}}if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"trace requires start|stop"}};let a=i.get(r);if(!a)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};if("start"===e){if(a.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"trace already in progress"}};let e=t.positionals?.[1]??i.defaultTracePath(a),r=iB.expandHome(e);return R.mkdirSync(n.dirname(r),{recursive:!0}),R.appendFileSync(r,""),a.trace={outPath:r,startedAt:Date.now()},i.recordAction(a,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!a.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active trace"}};let o=a.trace.outPath;if(t.positionals?.[1]){let e=iB.expandHome(t.positionals[1]);R.mkdirSync(n.dirname(e),{recursive:!0}),R.existsSync(o)?R.renameSync(o,e):R.appendFileSync(e,""),o=e}return a.trace=void 0,i.recordAction(a,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function aF(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function aV(e){let t=null,r=-1;for(let i of e){let e=i.width*i.height;e>r&&(t=i,r=e)}return t}function aG(e,t,r){return Math.min(r,Math.max(t,Math.round(e)))}async function aU(e){let{req:t,sessionName:r,sessionStore:i,contextFromFlags:n}=e,a=e.dispatch??iS,o=t.command;if("press"===o){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!ix("press",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let s=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(s){let r=await a(e.device,"press",[String(s.x),String(s.y)],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)});return i.recordAction(e,{command:o,positionals:t.positionals??[String(s.x),String(s.y)],flags:t.flags??{},result:r??{x:s.x,y:s.y}}),{ok:!0,data:r??{x:s.x,y:s.y}}}let l="click",d=t.positionals?.[0]??"";if(d.startsWith("@")){let r=aj("press",t.flags);if(r)return r;let s=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",u=aW({session:e,refInput:d,fallbackLabel:s,requireRect:!0,invalidRefMessage:`${o} requires a ref like @e2`,notFoundMessage:`Ref ${d} not found or has no bounds`});if(!u.ok)return u.response;let{ref:c}=u.target,p=u.target.node,f=u.target.snapshotNodes,m=aH(p.rect);if(!m){let r=await aB(e,t.flags,i,n,{interactiveOnly:!0},a),o=iY(r.nodes,c),l=s.length>0?iQ(r.nodes,s):null,d=aH(l?.rect),u=aH(o?.rect)?o:d?l:o??l,h=aH(u?.rect);u&&h&&(p=u,f=r.nodes,m=h)}if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${d} not found or has invalid bounds`}};let h=i0(p,f),w=nl(p,e.device.platform,{action:l}),{x:g,y:I}=m,v=await a(e.device,"press",[String(g),String(I)],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)});return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:c,x:g,y:I,refLabel:h,selectorChain:w}}),{ok:!0,data:{...v??{},ref:c,x:g,y:I}}}let u=(t.positionals??[]).join(" ").trim();if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:`${o} requires @ref, selector expression, or x y coordinates`}};let c=i7(u),p=await aB(e,t.flags,i,n,{interactiveOnly:!0},a),f=await O("selector_resolve",()=>nt(p.nodes,c,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!f||!f.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:ni(c,f?.diagnostics??[],{unique:!0})}};let m=aH(f.node.rect);if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${f.selector.raw} resolved to invalid bounds`}};let{x:h,y:w}=m,g=await a(e.device,"press",[String(h),String(w)],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)}),I=nl(f.node,e.device.platform,{action:l}),v=i0(f.node,p.nodes);return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{x:h,y:w,selector:f.selector.raw,selectorChain:I,refLabel:v}}),{ok:!0,data:{...g??{},selector:f.selector.raw,x:h,y:w}}}if("fill"===o){let e=i.get(r);if(e&&!ix("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=aj("fill",t.flags);if(r)return r;let s=t.positionals.length>=3?t.positionals[1]:"",l=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let d=aW({session:e,refInput:t.positionals[0],fallbackLabel:s,requireRect:!0,invalidRefMessage:"fill requires a ref like @e2",notFoundMessage:`Ref ${t.positionals[0]} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${t.positionals[0]} not found or has no bounds`}};let f=c.type??"",m=f&&!i4(f,e.device.platform)?`fill target ${t.positionals[0]} resolved to "${f}", attempting fill anyway.`:void 0,h=i0(c,p),w=nl(c,e.device.platform,{action:"fill"}),{x:g,y:I}=iZ(c.rect),v={...await a(e.device,"fill",[String(g),String(I),l],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)})??{ref:u,x:g,y:I}};return m&&(v.warning=m),i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...v,refLabel:h,selectorChain:w}}),{ok:!0,data:v}}if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let s=nn(t.positionals??[],{preferTrailingValue:!0});if(s){if(0===s.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=s.rest.join(" ").trim();if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let l=i7(s.selectorExpression),d=await aB(e,t.flags,i,n,{interactiveOnly:!0},a),u=await O("selector_resolve",()=>nt(d.nodes,l,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!u||!u.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:ni(l,u?.diagnostics??[],{unique:!0})}};let c=u.node,p=c.type??"",f=p&&!i4(p,e.device.platform)?`fill target ${u.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=iZ(u.node.rect),w=await a(e.device,"fill",[String(m),String(h),r],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath)}),g=nl(c,e.device.platform,{action:"fill"}),I={...w??{x:m,y:h,text:r},selector:u.selector.raw,selectorChain:g,refLabel:i0(c,d.nodes)};return f&&(I.warning=f),i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:I}),{ok:!0,data:I}}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}if("get"===o){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let s=i.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!ix("get",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let l=t.positionals?.[1]??"";if(l.startsWith("@")){let r=aj("get",t.flags);if(r)return r;let n=aW({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(!n.ok)return n.response;let{ref:a,node:d}=n.target,u=nl(d,s.device.platform,{action:"get"});if("attrs"===e)return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:a,selectorChain:u}}),{ok:!0,data:{ref:a,node:d}};let c=i8(d);return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:a,text:c,refLabel:c||void 0,selectorChain:u}}),{ok:!0,data:{ref:a,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=i7(d),c=await aB(s,t.flags,i,n,{interactiveOnly:!1},a),p=await O("selector_resolve",()=>nt(c.nodes,u,{platform:s.device.platform,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===e}),{command:o});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:ni(u,[],{unique:!0})}};let f=p.node,m=nl(f,s.device.platform,{action:"get"});if("attrs"===e)return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,node:f}};let h=i8(f);return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{text:h,refLabel:h||void 0,selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,text:h,node:f}}}if("is"===o){let e=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let s=i.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!ix("is",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:l}=na(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=i7(l.selectorExpression),c=await aB(s,t.flags,i,n,{interactiveOnly:!1},a);if("exists"===e){let r=nr(c.nodes,u,{platform:s.device.platform});return r?(i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:r.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,matches:r.matches}}),{ok:!0,data:{predicate:e,pass:!0,selector:r.selector.raw,matches:r.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:ni(u,[],{unique:!1})}}}let p=await O("selector_resolve",()=>nt(c.nodes,u,{platform:s.device.platform,requireUnique:!0}),{command:"is",predicate:e});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:ni(u,[],{unique:!0})}};let f=function(e){let{predicate:t,node:r,expectedText:i,platform:n}=e,a=i8(r),o=!1;switch(t){case"visible":o=no(r);break;case"hidden":o=!no(r);break;case"editable":o=ns(r,n);break;case"selected":o=!0===r.selected;break;case"text":o=a===(i??"")}let s="text"===t?`expected="${i??""}" actual="${a}"`:`actual=${JSON.stringify({visible:no(r),editable:ns(r,n),selected:!0===r.selected})}`;return{pass:o,actualText:a,details:s}}({predicate:e,node:p.node,expectedText:d,platform:s.device.platform});return f.pass?(i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:p.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,text:"text"===e?f.actualText:void 0}}),{ok:!0,data:{predicate:e,pass:!0,selector:p.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${e} failed for selector ${p.selector.raw}: ${f.details}`}}}if("scrollintoview"===o){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!ix("scrollintoview",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let s=t.positionals?.[0]??"";if(!s.startsWith("@"))return null;let l=aj("scrollintoview",t.flags);if(l)return l;let d=aW({session:e,refInput:s,fallbackLabel:t.positionals&&t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${s} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s} not found or has no bounds`}};let f=function(e,t){let r=iZ(t),i=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),n=i.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),a=aV(n.map(e=>e.rect).filter(e=>aF(e,r.x,r.y)));if(a)return a;let o=aV(n.map(e=>e.rect));if(o)return o;let s=aV(i.map(e=>e.rect).filter(e=>aF(e,r.x,r.y)));return s||null}(p,c.rect);if(!f)return{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${s}`}};let m=function(e,t){var r,i;let n=Math.max(1,t.height),a=Math.max(1,t.width),o=t.y,s=t.y+n,l=t.x,d=t.x+a,u=o+.25*n,c=s-.25*n,p=Math.max(8,.1*a),f=e.y+e.height/2,m=e.x+e.width/2;if(f>=u&&f<=c)return null;let h=Math.round((r=m,i=l+p,Math.min(d-p,Math.max(i,r)))),w=Math.round(o+.86*n),g=Math.round(o+.14*n),I=Math.max(1,Math.abs(w-g));return f>c?{x:h,startY:w,endY:g,count:aG(Math.ceil((f-c)/I),1,50),direction:"down"}:{x:h,startY:g,endY:w,count:aG(Math.ceil((u-f)/I),1,50),direction:"up"}}(c.rect,f),h=i0(c,p),w=nl(c,e.device.platform,{action:"get"});if(!m)return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:u,attempts:0,alreadyVisible:!0,refLabel:h,selectorChain:w}}),{ok:!0,data:{ref:u,attempts:0,alreadyVisible:!0}};let g=await a(e.device,"swipe",[String(m.x),String(m.startY),String(m.x),String(m.endY),"16"],t.flags?.out,{...n(t.flags,e.appBundleId,e.trace?.outPath),count:m.count,pauseMs:0,pattern:"one-way"});return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...g??{},ref:u,attempts:m.count,direction:m.direction,refLabel:h,selectorChain:w}}),{ok:!0,data:{...g??{},ref:u,attempts:m.count,direction:m.direction}}}return null}async function aB(e,t,r,i,n,a=iS){let o=await a(e.device,"snapshot",[],t?.out,{...i({...t??{},snapshotInteractiveOnly:n.interactiveOnly,snapshotCompact:n.interactiveOnly},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[];return e.snapshot={nodes:iK(t?.snapshotRaw?s:i2(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend},r.set(e.name,e),e.snapshot}let aq=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function aj(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,i]of aq)void 0!==e[r]&&t.push(i);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}function aW(e){let{session:t,refInput:r,fallbackLabel:i,requireRect:n,invalidRefMessage:a,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=iX(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:a}}};let l=iY(t.snapshot.nodes,s);return((!l||n&&!l.rect)&&i.length>0&&(l=iQ(t.snapshot.nodes,i)),l&&(!n||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 aH(e){let t=function(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),i=Number(e.width),n=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(i)&&Number.isFinite(n)&&!(i<0)&&!(n<0)?{x:t,y:r,width:i,height:n}:null}(e);if(!t)return null;let r=iZ(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function aJ(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 az(e){let{req:t,leaseRegistry:r}=e,i=aJ(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:i.tenantId??"",runId:i.runId??"",backend:i.leaseBackend,ttlMs:i.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:i.leaseId??"",tenantId:i.tenantId,runId:i.runId,ttlMs:i.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:i.leaseId??"",tenantId:i.tenantId,runId:i.runId})};default:return null}}let aK=new Set(["agent_device.command","agent-device.command"]),aX={"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"},aY=new Set([...aK,...Object.keys(aX)]);function aZ(e,t,r,i){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:i}}}function aQ(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function a0(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function a1(e,t){let r="string"==typeof t.authorization?t.authorization:"",i=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,n="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??n??i??""}function a2(e,t){let r=e[t];return"string"==typeof r?r:void 0}async function a3(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 I("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:aZ(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=S(new I(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:aZ(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=c(r.tenantId);if(!e){let e=S(new I("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:aZ(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function a4(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",i=n.isAbsolute(t)?t:n.resolve(t);try{e=await import(g(i).href)}catch(e){throw new I("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:i,error:e instanceof Error?e.message:String(e)})}let a=e[r];if("function"!=typeof a)throw new I("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:i,exportName:r});return a}async function a8(e){let t=await a4(),{handleRequest:r}=e;return i.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||"/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||aQ(i,aZ(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a;try{a=JSON.parse(n)}catch{aQ(i,aZ(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void aQ(i,aZ(a.id??null,-32600,"Invalid Request"),400);if(!aY.has(a.method))return void aQ(i,aZ(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void aQ(i,aZ(a.id??null,-32602,"Invalid params"),400);try{var o;let n=a.params,s=function(e,t,r){if(aK.has(e))return{token:a1(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,meta:t.meta};let i=aX[e];if(i){let e;return{token:a1(t,r),session:a2(t,"session")??"default",command:i,positionals:[],meta:{tenantId:a2(t,"tenantId")??a2(t,"tenant"),runId:a2(t,"runId"),leaseId:a2(t,"leaseId"),leaseTtlMs:(e=t.ttlMs,Number.isInteger(e)?Number(e):void 0),leaseBackend:a2(t,"backend")}}}throw new I("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(o=a.method,aK.has(o)&&("string"!=typeof s.command||0===s.command.length))return void aQ(i,aZ(a.id??null,-32602,"Invalid params: command is required"),400);let l=await a3(t,{headers:e.headers,rpcRequest:a,daemonRequest:s});if(!l.ok)return void aQ(i,l.response,l.statusCode);l.tenantId&&(s.meta={...s.meta,tenantId:l.tenantId,sessionIsolation:s.meta?.sessionIsolation??s.flags?.sessionIsolation??"tenant"});let d=await r(s);if(d.ok)return void aQ(i,{jsonrpc:"2.0",id:a.id??null,result:d});aQ(i,aZ(a.id??null,-32e3,d.error.message,d.error),a0(d.error.code))}catch(t){let e=S(t);aQ(i,aZ(a.id??null,-32e3,e.message,e),a0(e.code))}})})}function a5(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function a6(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function a9(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new I("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class a7{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=a9(e.backend),r=c(e.tenantId);if(!r)throw new I("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=a5(e.runId);if(!i)throw new I("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),a=this.bindingKey(r,i,t),o=this.runBindings.get(a);if(o){let e=this.leases.get(o);if(e)return this.refreshLease(e,n);this.runBindings.delete(a)}this.enforceCapacity(t);let s=this.now(),l={leaseId:f.randomBytes(16).toString("hex"),tenantId:r,runId:i,backend:t,createdAt:s,heartbeatAt:s,expiresAt:s+n};return this.leases.set(l.leaseId,l),this.runBindings.set(a,l.leaseId),{...l}}heartbeatLease(e){let t=a6(e.leaseId);if(!t)throw new I("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new I("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let i=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,i)}releaseLease(e){let t=a6(e.leaseId);if(!t)throw new I("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=a9(e.backend),r=c(e.tenantId);if(!r)throw new I("INVALID_ARGS","tenant isolation requires tenant id.");let i=a5(e.runId);if(!i)throw new I("INVALID_ARGS","tenant isolation requires run id.");let n=a6(e.leaseId);if(!n)throw new I("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let a=this.leases.get(n);if(!a)throw new I("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(a.backend!==t||a.tenantId!==r||a.runId!==i)throw new I("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 I("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 I("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),i={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(i.leaseId,i),this.runBindings.set(this.bindingKey(i.tenantId,i.runId,i.backend),i.leaseId),{...i}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let i=c(t),n=a5(r);if(t&&!i)throw new I("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!n)throw new I("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(i&&e.tenantId!==i||n&&e.runId!==n)throw new I("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let{baseDir:oe,infoPath:ot,lockPath:or,logPath:oi,sessionsDir:on}=U(process.env.AGENT_DEVICE_STATE_DIR),oa=G(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var oo=on;if(R.existsSync(oo))for(let e of R.readdirSync(oo,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=n.join(oo,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=T(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let i=a(e.pid);return!!i&&!!((t=i.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||i===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{nA(t)}}let os=new iB(on),ol=new a7({maxActiveSimulatorLeases:oy(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:oy(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:oy(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:oy(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),od=D(),ou=f.randomBytes(24).toString("hex"),oc=new Set(["session_list","devices"]),op=new Set(["session_list","devices","lease_allocate","lease_heartbeat","lease_release"]),of=T(process.pid)??void 0,om=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=R.statSync(e),r=E(),i=n.relative(r,e)||e;return`${i}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}();function oh(e,t,r){let i=k().requestId;return{...iq(oi,e,t,r,i),requestId:i}}async function ow(e){var t;let r="click"===(t=e).command?{...t,command:"press"}:t,i=!!(r.meta?.debug||r.flags?.verbose);return await P({session:r.session,requestId:r.meta?.requestId,command:r.command,debug:i,logPath:oi},async()=>{if(r.token!==ou)return{ok:!1,error:S(new I("UNAUTHORIZED","Invalid token"))};try{let e=function(e){let t=_(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,i=c(r);if(r&&!i)throw new I("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!i)throw new I("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");return{...e,session:`${i}:${e.session||"default"}`,meta:{...e.meta,tenantId:i,sessionIsolation:t}}}(r);L({level:"info",phase:"request_start",data:{session:e.session,command:e.command,tenant:e.meta?.tenantId,isolation:e.meta?.sessionIsolation}});let t=e.command,i=aJ(e);op.has(t)||e.meta?.sessionIsolation!=="tenant"||ol.assertLeaseAdmission({tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId,backend:i.leaseBackend});let n=function(e,t){var r;let i,n=e.session||"default";if(r=e,i=r.flags?.session,"string"==typeof i&&i.trim().length>0||"default"!==n||t.has(n))return n;let a=t.toArray();return 1===a.length?a[0].name:n}(e,os),a=os.get(n);a&&!oc.has(t)&&function(e,t){if(!t)return;let r=[],i=e.device,n=q(t.platform);if(n&&n!==i.platform&&r.push(`--platform=${t.platform}`),t.target&&t.target!==(i.target??"mobile")&&r.push(`--target=${t.target}`),t.udid&&("ios"!==i.platform||t.udid!==i.id)&&r.push(`--udid=${t.udid}`),t.serial&&("android"!==i.platform||t.serial!==i.id)&&r.push(`--serial=${t.serial}`),t.device&&t.device.trim().toLowerCase()!==i.name.trim().toLowerCase()&&r.push(`--device=${t.device}`),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),n=i.simulatorSetPath?.trim();("ios"!==i.platform||"simulator"!==i.kind||e!==n)&&r.push(`--ios-simulator-device-set=${t.iosSimulatorDeviceSet}`)}if(t.androidDeviceAllowlist){let e=ea(t.androidDeviceAllowlist);"android"===i.platform&&e.has(i.id)||r.push(`--android-device-allowlist=${t.androidDeviceAllowlist}`)}if(0!==r.length){var a;let t,i,n;throw new I("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.join(", ")}. Use a different --session name or close this session first.`)}}(a,e.flags);let o=await az({req:e,leaseRegistry:ol});if(o)return og(o);let s=await ac({req:e,sessionName:n,logPath:oi,sessionStore:os,invoke:ow});if(s)return og(s);let l=await aS({req:e,sessionName:n,logPath:oi,sessionStore:os});if(l)return og(l);let d=await a$({req:e,sessionName:n,sessionStore:os,logPath:oi});if(d)return og(d);let u=await aC({req:e,sessionName:n,logPath:oi,sessionStore:os,invoke:ow});if(u)return og(u);let p=await aU({req:e,sessionName:n,sessionStore:os,contextFromFlags:oh});if(p)return og(p);let f=os.get(n);if(!f)return og({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!ix(t,f.device))return og({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${t} is not supported on this device`}});let m=await iS(f.device,t,e.positionals??[],e.flags?.out,{...oh(e.flags,f.appBundleId,f.trace?.outPath)});return os.recordAction(f,{command:t,positionals:e.positionals??[],flags:e.flags??{},result:m??{}}),og({ok:!0,data:m??{}})}catch(r){L({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=k(),t=$({force:!0})??void 0;return{ok:!1,error:S(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}function og(e){let t=k();if(!e.ok){L({level:"error",phase:"request_failed",data:{code:e.error.code,message:e.error.message}});let r=$({force:!0})??void 0;return{ok:!1,error:S(new I(e.error.code,e.error.message,{...e.error.details??{},hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath}),{diagnosticId:t.diagnosticId,logPath:r})}}return L({level:"info",phase:"request_success"}),$(),e}function oI(){R.existsSync(ot)&&R.unlinkSync(ot)}function ov(){if(!R.existsSync(or))return null;try{let e=JSON.parse(R.readFileSync(or,"utf8"));if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}function oA(){let e=ov();if(!e||e.pid===process.pid)try{R.existsSync(or)&&R.unlinkSync(or)}catch{}}function oy(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}(async function e(){let e,t;if(!function(){R.existsSync(oe)||R.mkdirSync(oe,{recursive:!0});let e=JSON.stringify({pid:process.pid,version:od,startedAt:Date.now(),processStartTime:of},null,2),t=()=>{try{return R.writeFileSync(or,e,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(t())return!0;let r=ov();if(r?.pid&&r.pid!==process.pid&&s(r.pid,r.processStartTime))return!1;try{R.unlinkSync(or)}catch{}return t()}()){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var i;let n;if("socket"===oa||"dual"===oa){let t=V.createServer(e=>{let t="",r=0,i=new Set,n=!1,a=()=>{if(!n&&0!==r){for(let e of(n=!0,i))e&&t7.add(e);L({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await rb(),!(r<=0));)await new Promise(e=>setTimeout(e,200))})()}};e.setEncoding("utf8"),e.on("close",a),e.on("error",a),e.on("data",async n=>{let a=(t+=n).indexOf("\n");for(;-1!==a;){let n,s,l=t.slice(0,a).trim();if(t=t.slice(a+1),0===l.length){a=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(l);if((s=e.meta?.requestId)&&(i.add(s),re(s)))throw new I("COMMAND_FAILED","request canceled");n=await ow(e)}catch(e){n={ok:!1,error:S(e)}}finally{if(r-=1,s){var o;i.delete(s),(o=s)&&t7.delete(o)}}e.destroyed||e.write(`${JSON.stringify(n)}
32
+ `),a=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let i=t.address();"object"==typeof i&&i?.port?e(i.port):r(new I("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===oa||"dual"===oa){let e=await a8({handleRequest:ow});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let i=e.address();"object"==typeof i&&i?.port?t(i.port):r(new I("COMMAND_FAILED","Failed to bind HTTP server"))})})}i={socketPort:e,httpPort:t},R.existsSync(oe)||R.mkdirSync(oe,{recursive:!0}),R.writeFileSync(oi,""),n=i.httpPort&&i.socketPort?"dual":i.httpPort?"http":"socket",R.writeFileSync(ot,JSON.stringify({port:i.socketPort,httpPort:i.httpPort,transport:n,token:ou,pid:process.pid,version:od,codeSignature:om,processStartTime:of,stateDir:oe},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
31
33
  `),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
32
34
  `)}catch(t){let e=w(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
33
- `),r))try{t.close(()=>{})}catch{}ot(),oi(),process.exit(1);return}let n=!1,a=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},o=async()=>{if(!n){for(let e of(n=!0,await a(),a0.toArray()))a0.writeSessionLog(e);await rI(),ot(),oi(),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof I?e:w(e);process.stderr.write(`Daemon error: ${t.message}
35
+ `),r))try{t.close(()=>{})}catch{}oI(),oA(),process.exit(1);return}let n=!1,a=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},o=async()=>{if(!n){for(let e of(n=!0,await a(),os.toArray()))os.writeSessionLog(e);await rS(),oI(),oA(),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof I?e:w(e);process.stderr.write(`Daemon error: ${t.message}
34
36
  `),o()})})();