agent-device 0.11.7 → 0.11.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/bin.js +1 -1
- package/dist/src/daemon.js +45 -45
- package/dist/src/index.d.ts +2 -2
- package/package.json +4 -2
- package/src/platforms/linux/atspi-dump.py +285 -0
package/dist/src/daemon.js
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
let e,t,r,a;import{__webpack_require__ as n}from"./1~rslib-runtime.js";import i,{createHash as o}from"node:crypto";import s,{existsSync as l,promises as d}from"node:fs";import u from"node:os";import
|
|
2
|
-
`)}let eV=new Set,
|
|
1
|
+
let e,t,r,a;import{__webpack_require__ as n}from"./1~rslib-runtime.js";import i,{createHash as o}from"node:crypto";import s,{existsSync as l,promises as d}from"node:fs";import u,{hostname as c}from"node:os";import p from"node:path";import f from"node:net";import{AsyncLocalStorage as m}from"node:async_hooks";import{URL as h,fileURLToPath as w,pathToFileURL as g}from"node:url";import{spawn as y}from"node:child_process";import v from"node:http";import"node:https";import I from"node:dns/promises";import b from"node:fs/promises";import{TextDecoder as A}from"node:util";import{setTimeout as S}from"node:timers/promises";import{PNG as _}from"pngjs";import{formatSnapshotLine as N,decodePng as x,readProcessCommand as D,isNodeVisibleInEffectiveViewport as k,isMacOsSettingSupported as M,normalizeTenantId as E,isAgentDeviceDaemonProcess as O,runCmdDetached as L,runCmdBackground as C,SETTINGS_INVALID_ARGS_MESSAGE as P,validateAndNormalizeBatchSteps as R,runCmd as T,containsPoint as $,resolveDeployResultTarget as F,isScrollableType as U,displayLabel as G,distanceFromSafeViewportBand as V,asAppError as B,expandUserHomePath as j,withSuccessText as q,AppError as H,extractReadableText as W,resolveEffectiveViewportRect as z,getUnsupportedMacOsSettingMessage as J,whichCmd as X,buildSnapshotDisplayLines as K,buildMobileSnapshotPresentation as Y,resolveViewportRect as Z,runCmdStreaming as Q,formatRole as ee,normalizeError as et,resolveSessionIsolationMode as er,resolveUserPath as ea,readVersion as en,getDiagnosticsMeta as ei,runCmdSync as eo,withDiagnosticTimer as es,findNodeByRef as el,successText as ed,emitDiagnostic as eu,normalizeSnapshotTree as ec,pickLargestRect as ep,normalizeRef as ef,DEFAULT_BATCH_MAX_STEPS as em,findProjectRoot as eh,isProcessAlive as ew,readProcessStartTime as eg,withDiagnosticsScope as ey,resolveDaemonPaths as ev,flushDiagnosticsToSessionFile as eI,resolveDaemonServerMode as eb,centerOfRect as eA,resolveInstallFromSourceResultTarget as eS,attachRefs as e_,parseSessionSurface as eN}from"./168.js";var ex={};n.r(ex),n.d(ex,{ensureAndroidEmulatorBooted:()=>a7,listAndroidDevices:()=>a3,waitForAndroidBoot:()=>ne});var eD={};n.r(eD),n.d(eD,{oI:()=>iS,X$:()=>iI,bV:()=>nz,NX:()=>iV,Mh:()=>aG,fK:()=>ik,w8:()=>iD,getAndroidAppState:()=>nF,K0:()=>iG,PW:()=>iC,V0:()=>ib,inferAndroidAppName:()=>n$,installAndroidApp:()=>n4,installAndroidInstallablePathAndResolvePackageName:()=>n3,listAndroidApps:()=>nC,pw:()=>i_,vU:()=>nG,gy:()=>nW,Nd:()=>iy,hF:()=>i2,$f:()=>iB,gh:()=>iF,reinstallAndroidApp:()=>n5,resolveAndroidApp:()=>nL,Tz:()=>iA,UB:()=>i4,VJ:()=>iO,m1:()=>iL,GZ:()=>iX,kt:()=>iu,sP:()=>iv,wb:()=>iN,ac:()=>ij});var ek={};n.r(ek),n.d(ek,{prepareAndroidInstallArtifact:()=>nN});var eM={};n.r(eM),n.d(eM,{hp:()=>lq,listAppleDevices:()=>lX});var eE={};n.r(eE),n.d(eE,{TM:()=>sA,ensureBootedSimulator:()=>om,installIosApp:()=>s_,installIosInstallablePath:()=>sx,listIosApps:()=>sO,L5:()=>sI,IJ:()=>sb,TJ:()=>sM,J7:()=>sD,reinstallIosApp:()=>sN,resolveIosApp:()=>sv,kc:()=>sn,Cm:()=>sE,ap:()=>sk});var eO={};n.r(eO),n.d(eO,{prepareIosInstallArtifact:()=>oy});let eL=eC(process.env.AGENT_DEVICE_RETRY_LOGS);function eC(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let eP=2e4,eR=12e4,eT=1e4;class e${startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new e$(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 eF(e,t={},r={}){let a,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;t+=1){if(r.signal?.aborted)throw new H("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(r.deadline?.isExpired()&&t>1)break;try{let a=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()}),eG({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),a}catch(d){a=d;let e=r.classifyReason?.(d),i={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(i),eG(i),t>=n.maxAttempts||n.shouldRetry&&!n.shouldRetry(d,t))break;let o=function(e,t,r,a){let n=Math.min(t,e*2**(a-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),eG(l),await function(e,t){return new Promise(r=>{if(t?.aborted)return void r();let a=!1,n=()=>{a||(a=!0,t&&t.removeEventListener("abort",o),r())},i=setTimeout(n,e);function o(){clearTimeout(i),n()}t&&t.addEventListener("abort",o,{once:!0})})}(s,r.signal)}}let i={phase:r.phase,event:"exhausted",attempt:n.maxAttempts,maxAttempts:n.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(a)};if(r.onEvent?.(i),eG(i),a)throw a;throw new H("COMMAND_FAILED","retry failed")}async function eU(e,t={}){return eF(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function eG(e){eu({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),eL&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
|
|
2
|
+
`)}let eV=new Set,eB=new Map,ej="request_canceled",eq="request canceled";function eH(e,t){if("string"==typeof e&&e.length>0)return e;let r=("string"==typeof t?t:"number"==typeof t&&Number.isFinite(t)?String(t):"generated").trim().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,32)||"generated",a=Math.random().toString(36).slice(2,10);return`req:${r}:${process.pid}:${Date.now()}:${a}`}function eW(e){if(!e)return;!function(e){if(e.size<=5e4)return;let t=0;for(let r of e.keys()){if(t>=1e4)break;e.delete(r),t++}}(eB);let t=new AbortController;eB.set(e,t),eV.has(e)&&t.abort()}function ez(e){e&&(!function(e){if(e.size<=5e4)return;let t=0;for(let r of e){if(t>=1e4)break;e.delete(r),t++}}(eV),eV.add(e),eB.get(e)?.abort())}function eJ(e){e&&(eV.delete(e),eB.delete(e))}function eX(e){return!!e&&eV.has(e)}function eK(e){if(e)return eB.get(e)?.signal}function eY(){return new H("COMMAND_FAILED",eq,{reason:ej})}function eZ(e){return e instanceof H&&"COMMAND_FAILED"===e.code&&(e.details?.reason===ej||e.message===eq)}function eQ(e,t,r){if(!e)return t;let a=Number(e);return Number.isFinite(a)?Math.max(r,Math.floor(a)):t}function e0(e){let t=e.error?B(e.error):null,r=e.context?.platform,a=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===r?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let n=t?.details??{},i="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,i,o,s,"string"==typeof l?.stdout?l.stdout:void 0,"string"==typeof l?.stderr?l.stderr:void 0,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===r&&(u.includes("runner did not accept connection")||"connect"===a&&(u.includes("timed out")||u.includes("timeout")||u.includes("econnrefused")||u.includes("connection refused")||u.includes("fetch failed")||u.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":u.includes("resource temporarily unavailable")||u.includes("killed: 9")||u.includes("cannot allocate memory")||u.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===r&&(u.includes("device not found")||u.includes("no devices")||u.includes("device offline")||u.includes("offline")||u.includes("unauthorized")||u.includes("not authorized")||u.includes("unable to locate device")||u.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||u.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function e1(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 e2=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],e3=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function e4(e){return e?.trim()||void 0}function e5(e,t){for(let r of e){let e=e4(t[r]);if(e)return e}}function e8(e,t=process.env){return e4(e)??e5(e2,t)}function e6(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function e9(e,t=process.env){let r=e4(e)??e5(e3,t);if(r)return e6(r)}function e7(e,t={}){let r=e8(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function te(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:e7(t,{simulatorSetPath:e.simulatorSetPath})}function tt(e){return!(e instanceof H)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function tr(e){let{port:t,endpoints:r,logPath:a,lastError:n}=e,i="Runner did not accept connection";return new H("COMMAND_FAILED",i,{port:t,endpoints:r,logPath:a,lastError:n?String(n):void 0,reason:e0({error:n,message:i,context:{platform:"ios",phase:"connect"}}),hint:e1("IOS_RUNNER_CONNECT_TIMEOUT")})}async function ta(e){var t,r;let a,{session:n,port:i,logPath:o}=e,s=await n.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=e0({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new H("COMMAND_FAILED",l,{port:i,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(a=`${l}
|
|
3
3
|
${t}
|
|
4
|
-
${r}`.toLowerCase()).includes("device is busy")&&a.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":
|
|
5
|
-
xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new q("DEVICE_NOT_FOUND","No devices found",{selector:t})}let o=a.filter(e=>"device"!==e.kind);o.length>0&&(a=o);let s=a.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??a[0]}let tD=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function tx(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new q("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:r});let a=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of a)if(!s.existsSync(e))throw new q("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==ei("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await R("codesign",["--remove-signature",e],{allowFailure:!0});try{await R("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof q?a:new q("COMMAND_FAILED",String(a));throw new q("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}let tk=c.join(u.homedir(),".agent-device","ios-runner"),tM=new Map,tE=new Set;function tO(e){return e?.trim()??""}function tL(e=process.env){return tO(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tO(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tC(e=process.env){let t=tO(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tL(e)}.uitests`}let tP=function(e=process.env){let t=tL(e),r=tC(e);return Array.from(new Set([tO(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);async function tR(e,t){var r;let a,n=(r=e,(a=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?c.resolve(a):"macos"===r.platform?c.join(tk,"derived","macos"):"simulator"===r.kind?c.join(tk,"derived"):c.join(tk,"derived",r.kind)),i=function(){let e=c.dirname(h(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=c.join(t,"package.json");if(s.existsSync(e))return t;t=c.dirname(t)}return e}();return await tA(tM,n,async()=>{eL(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(tz("clean","forced_clean",{derived:n}),tW(n),tT(n));let r=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let r=e.resolveExistingXctestrunProductPaths(t);return r?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:r}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:r}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:n,projectRoot:i,findXctestrun:t=>tF(t,e),xctestrunReferencesProjectRoot:tV,resolveExistingXctestrunProductPaths:tJ});if("reuse_ready"!==r.reason&&tz("rebuild",r.reason,{derived:n,xctestrunPath:r.xctestrunPath}),"reuse_ready"===r.reason)try{return await tx(e,r.productPaths,r.xctestrunPath),tz("reuse","reuse_ready",{derived:n,xctestrunPath:r.xctestrunPath}),r.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof q))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&tD.has(t)}(e))throw e;tz("rebuild","repair_failed",{derived:n,xctestrunPath:r.xctestrunPath})}r.xctestrunPath&&(tW(n),tT(n));let a=c.join(i,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!s.existsSync(a))throw new q("COMMAND_FAILED","iOS runner project not found",{projectPath:a});await tB(e,a,n,t);let o=tF(n,e);if(!o)throw new q("COMMAND_FAILED","Failed to locate .xctestrun after build");let l=tJ(o);if(!l)throw new q("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:o});return await tx(e,l,o),tz("build","built_new",{derived:n,xctestrunPath:o}),o})}function tT(e){try{if(!s.existsSync(e))return;if("derived"!==c.basename(e))return void s.rmSync(e,{recursive:!0,force:!0});for(let r of s.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,t$.has(t)&&s.rmSync(c.join(e,r.name),{recursive:!0,force:!0})}}catch{}}let t$=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function tF(e,t){if(!s.existsSync(e))return null;let r=[],a=[e];for(;a.length>0;){let e=a.pop();for(let t of s.readdirSync(e,{withFileTypes:!0})){let n=c.join(e,t.name);if(t.isDirectory()){a.push(n);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=s.statSync(n);r.push({path:n,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let a=tU(r.path,t)-tU(e.path,t);if(0!==a)return a}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)}function tU(e,t){var r;let a=0,n=e.toLowerCase();c.basename(n).startsWith("agentdevicerunner.env.")&&(a-=1e3),n.includes(`${c.sep}macos${c.sep}`)&&(a-=5e3);let i="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return i.preferred.length>0&&(i.preferred.some(e=>n.includes(e))?a+=2e3:a-=500),i.disallowed.some(e=>n.includes(e))&&(a-=2500),a}function tV(e,t){try{let r=s.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(s.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}}async function tG(e,t,r){let a,n=c.dirname(e),i=r.replace(/[^a-zA-Z0-9._-]/g,"_"),o=c.join(n,`AgentDeviceRunner.env.${i}.json`),l=c.join(n,`AgentDeviceRunner.env.${i}.xctestrun`),d=await R("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new q("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new q("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},p=a.TestConfigurations;if(Array.isArray(p))for(let e of p){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(a))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),a[e]=t);s.writeFileSync(o,JSON.stringify(a,null,2));let f=await R("plutil",["-convert","xml1","-o",l,o],{allowFailure:!0});if(0!==f.exitCode)throw new q("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:f.stderr});return{xctestrunPath:l,jsonPath:o}}async function tB(e,t,r,a){let n=function(e=process.env){let t=tL(e),r=tC(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),i=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",n=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",i=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),n&&o.push(`CODE_SIGN_IDENTITY=${n}`),i&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${i}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var s;let l;await Z("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",tH(e),"1","-destination",(s=e,l=tj(s),"macOS"===l?`platform=macOS,arch=${tq()}`:"simulator"===s.kind?`platform=${l} Simulator,id=${s.id}`:`generic/platform=${l}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...n,...o,...i],{detached:!0,onSpawn:e=>{tE.add(e),e.on("close",()=>{tE.delete(e)})},onStdoutChunk:e=>{ty(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{ty(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(i){let e,t,r=i instanceof q?i:new q("COMMAND_FAILED",String(i)),n=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
|
|
6
|
-
${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new
|
|
7
|
-
${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found nothing")&&!e.includes("no such file")&&!e.includes("invalid device")&&!e.includes("could not find"))continue}}}async function tQ(e){await tA(tX,e.deviceId,async()=>{await t0(e.deviceId,e)})}async function t0(e,t){let r=t??tK.get(e);if(r){try{await tp(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await t4(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await t4(r.child.pid,"SIGKILL"),tv(r.xctestrunPath),tv(r.jsonPath),tK.get(e)===r&&tK.delete(e)}}async function t1(e){await tA(tX,e,async()=>{await t0(e)})}async function t2(){let e=Array.from(tK.values()),t=Array.from(tE);await Promise.allSettled(e.map(async e=>{await t4(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await t4(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await t4(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await t4(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await t4(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await t4(e.pid,"SIGKILL"),tE.delete(e)}))}async function t3(){await t2();let e=Array.from(tK.keys());await Promise.allSettled(e.map(async e=>{await t1(e)}));let t=Array.from(tE);await Promise.allSettled(t.map(async e=>{try{await t4(e.pid,"SIGTERM"),await t4(e.pid,"SIGKILL")}finally{tE.delete(e)}}))}async function t4(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 R("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function t8(e){await R("xcrun",e7(e,["bootstatus",e.id,"-b"]),{timeoutMs:tn})}async function t5(e,t,r,a,n,i){let o=await tp(e,t.port,r,a,n,t,i);return await t6(o,t,a)}async function t6(e,t,r){let a=await e.text(),n={};try{n=JSON.parse(a)}catch{throw new q("COMMAND_FAILED","Invalid runner response",{text:a})}if(!n.ok)throw new q("string"==typeof n.error?.code&&n.error.code.trim().length>0?n.error.code:"COMMAND_FAILED",n.error?.message??"Runner error",{runner:n,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,n.data??{}}async function t9(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new q("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new q("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(ta(r.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?eF(()=>(ta(r.requestId),t7(e,t,r)),{shouldRetry:e=>{ta(r.requestId);if(!(e instanceof q)||"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"))}}):t7(e,t,r)}async function t7(e,t,r={}){let a;ta(r.requestId);let n=eK(r.requestId);try{let i=(a=await tY(e,r)).ready?ti:tn;return await t5(e,a,t,r.logPath,i,n)}catch(o){let i=o instanceof q?o:new q("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===i.code&&"string"==typeof i.message&&i.message.includes("Runner did not accept connection")&&te(i)&&a?.ready){ta(r.requestId),a?await tQ(a):await t1(e.id),a=await tY(e,r);let i=await tp(a.device,a.port,t,r.logPath,tn,void 0,n);return await t6(i,a,r.logPath)}throw o}}function re(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 rt(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let rr=/^-?\d+(\.\d+)?$/,ra=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),rn=new Map([["--count","count"],["--pause-ms","pauseMs"]]),ri=new Map([["--delay-ms","delayMs"]]);function ro(e){return"click"===e||"press"===e}function rs(e){return"type"===e||"fill"===e}function rl(e){let t=e.trim();return t.startsWith("@")||rr.test(t)?t:JSON.stringify(t)}function rd(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function ru(e,t){let r=t.flags??{};if(ro(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}if("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);return}rs(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function rc(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",rd(t.metroHost)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",rd(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",rd(t.launchUrl)))}function rp(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(rd(r)),a))e.push(rl(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function rf(e,t){let r=[],a={},n=ro(e)?ra:"swipe"===e?rn:rs(e)?ri:void 0;for(let i=0;i<t.length;i+=1){let o=t[i];if(ro(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(ro(e)&&"--button"===o&&i+1<t.length){let e=t[i+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),i+=1;continue}let s=n?.get(o);if(s&&i+1<t.length){let e=rh(t[i+1]);if(null!==e){a[s]=e,i+=1;continue}}if("swipe"===e&&"--pattern"===o&&i+1<t.length){let e=t[i+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),i+=1;continue}r.push(o)}return{positionals:r,flags:a}}function rm(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let n=e[a];if("--platform"===n&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===n&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===n&&a+1<e.length){let t=rh(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===n&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===n&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(n)}return{positionals:t,flags:r}}function rh(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function rw(e,t){for(let r of t.positionals??[])e.push(rl(r));t.flags?.relaunch&&e.push("--relaunch"),rc(e,t.runtime)}class rg{sessions=new Map;runtimeHints=new Map;sessionsDir;constructor(e){this.sessionsDir=e}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=rg.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:n,out:i,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:y,noRecord:v,fps:I,hideTouches:A,count:b,intervalMs:S,delayMs:_,holdMs:N,jitterPx:D,doubleTap:x,clickButton:k,pauseMs:M,pattern:E}=e;return{platform:t,device:r,udid:a,serial:n,out:i,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:y,noRecord:v,fps:I,hideTouches:A,count:b,intervalMs:S,delayMs:_,holdMs:N,jitterPx:D,doubleTap:x,clickButton:k,pauseMs:M,pattern:E}}(t.flags),result:t.result}),ed({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=c.dirname(t);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.name.replace(/"/g,'\\"'),n=e.device.kind?` kind=${e.device.kind}`:"";for(let i of(r.push(`context platform=${e.device.platform} device="${a}"${n} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(ro(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(rl(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(rl(a)),ru(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(rl(r)),ru(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(rl(r));let a=e.result?.refLabel,n=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(rl(a)),n&&t.push(rl(n)),ru(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(rl(r)),t.push(rl(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(rl(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",rl(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(rl(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}if("open"===e.command)return rw(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(rd(r)),rc(t,e.flags),t.join(" ")}if("record"===e.command)return rp(t,e),t.join(" ");for(let r of e.positionals??[])t.push(rl(r));return ru(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
8
|
-
`}(e,this.buildOptimizedActions(e));s.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=
|
|
9
|
-
`)}function
|
|
10
|
-
`)},flush:()=>{a&&(n(a),a="")}}}function
|
|
11
|
-
`,recoveredLineCount:s.length}}async function rE(e,t,r,a,n,i){let o="active",s=g("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return e9(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",rk(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:n}),{stdio:["ignore","pipe","pipe"]}),l=rb(r,{redactionPatterns:a});"number"==typeof s.pid&&ry(i,s.pid);let d=rS(s,r,{endStreamOnClose:!0,writer:l}).then(e=>(0!==e.exitCode&&(o="failed"),rv(i),e));return{backend:"ios-simulator",getState:()=>o,startedAt:Date.now(),wait:d,stop:async()=>{s.killed||s.kill("SIGINT"),await rI(d),s.killed||s.kill("SIGKILL"),await rI(d),rv(i)}}}async function rO(e,t,r,a){let n="active",i=g("log",["stream","--style","compact","--predicate",rk(e)],{stdio:["ignore","pipe","pipe"]}),o=rb(t,{redactionPatterns:r});"number"==typeof i.pid&&ry(a,i.pid);let s=rS(i,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),rv(a),e));return{backend:"macos",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{i.killed||i.kill("SIGINT"),await rI(s),i.killed||i.kill("SIGKILL"),await rI(s),rv(a)}}}async function rL(e,t,r,a){let n="active",i=g("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=rb(t,{redactionPatterns:r});"number"==typeof i.pid&&ry(a,i.pid);let s=rS(i,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),rv(a),e));return{backend:"ios-device",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{i.killed||i.kill("SIGINT"),await rI(s),i.killed||i.kill("SIGKILL"),await rI(s),rv(a)}}}let rC=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),rP=/https?:\/\/[^\s"'<>\])]+/i,rR=[/\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 rT(e,t,r=e.limits.maxEntries){let a=[...e.entries],n=new Set(a.map(e=>rF(e)));for(let e of t.entries){let t=rF(e);if(!n.has(t)&&(n.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function r$(e,t){let r=rJ(t?.maxEntries,25,1,200),a=t?.backend,n=t?.include??"summary",i=rJ(t?.maxPayloadChars,2048,64,16384),o=rJ(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),d=s.slice(l),u=[];for(let e=d.length-1;e>=0&&u.length<r;e-=1){let t=d[e];if(!t?.trim())continue;let r=function(e,t,r,a,n,i){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=rq(s,["method","httpMethod"]),d=rq(s,["url","requestUrl"]),u=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}(s,["status","statusCode","responseCode"]),c=rC.exec(o),p=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),f=(l??p?.[1]??c?.[1])?.toUpperCase(),m=rP.exec(o),h=d??m?.[0];if(!h)return null;let w=u??rV(o)??void 0;if(!(l||p?.[1]||c?.[1]||void 0!==w||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let g={method:f,url:h,status:w,timestamp:rG(o),packetId:rB(o)??void 0,durationMs:rj(o)??void 0,raw:rz(o,i),line:r};if("android"===a&&function(e,t,r){let a=rU(t,r,5),n=e.packetId??a.map(e=>rB(e)).find(e=>"string"==typeof e&&e.length>0);n&&(e.packetId=n);let i=n?rU(t,r,12).filter(e=>rB(e)===n):a;e.timestamp||(e.timestamp=i.map(e=>rG(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=i.map(e=>rV(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=i.map(e=>rj(e)).find(e=>"number"==typeof e))}(g,e,t),"headers"===n||"all"===n){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return rW(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(g.headers=rz(e,i))}if("body"===n||"all"===n){let e=rH(o,s,["requestBody","body","payload","request"]),t=rH(o,s,["responseBody","response"]);e&&(g.requestBody=rz(e,i)),t&&(g.responseBody=rz(t,i))}return g}(d,e,l+e+1,a,n,i);r&&u.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:d.length,matchedLines:u.length,entries:u,include:n,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:o}}}function rF(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function rU(e,t,r){let a=[],n=Math.max(0,t-r),i=Math.min(e.length-1,t+r);for(let t=n;t<=i;t+=1){let r=e[t]?.trim();r&&a.push(r)}return a}function rV(e){for(let t of rR){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function rG(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function rB(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function rj(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function rq(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 rH(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return rW(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function rW(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function rz(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function rJ(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function rK(e,t){let r=process.env[e];if(!r)return t;let a=Number.parseInt(r,10);return Number.isInteger(a)&&a>0?a:t}function rX(e){let t=c.dirname(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),function(e,t){if(s.existsSync(e)&&!(s.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,a=`${e}.${r}`;s.existsSync(t)&&(s.existsSync(a)&&s.unlinkSync(a),s.renameSync(t,a))}}(e,{maxBytes:rK("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rK("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rY(e){var t,r;let a,n,i,o,{device:l,appBundleId:d,appLogState:u,appLogStartedAt:c,appLogPath:p,maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w}=e,g="macos"===l.platform?"macos":"ios"===l.platform?"device"===l.kind?"ios-device":"ios-simulator":"android",y=(t={backend:g,maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w},a=rJ(t?.maxEntries,25,1,200),n=t?.include??"summary",i=rJ(t?.maxPayloadChars,2048,64,16384),o=rJ(t?.maxScanLines,4e3,100,2e4),s.existsSync(p)?r$(s.readFileSync(p,"utf8"),{...t,path:p}):{path:p,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:n,limits:{maxEntries:a,maxPayloadChars:i,maxScanLines:o}}),v=[];if("android"===l.platform&&void 0!==u&&"active"!==u&&d){let e=await rD(l.id,d);if(e){let t=r$(e.text,{path:`${p} (adb logcat recovery)`,backend:"android",maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w});t.entries.length>0&&(y=rT(t,y,f),v.push(`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${e.recoveredPids.join(", ")}.`))}}if("ios"===l.platform&&"simulator"===l.kind&&d&&0===y.entries.length){let e=await rQ({deviceId:l.id,appBundleId:d,startedAt:c,simulatorSetPath:l.simulatorSetPath,appLogPath:p,maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w});e&&(e.dump.entries.length>0?(y=rT(e.dump,y,f),v.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&v.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===u?v.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==u&&0===v.length&&("ios"===l.platform&&"simulator"===l.kind?v.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):v.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===y.entries.length&&v.push("ios"===(r=l).platform&&"simulator"===r.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===r.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:g,dump:y,notes:v}}async function rZ(e,t,r,a){rX(r);let n=s.createWriteStream(r,{flags:"a"}),i=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 rL(e.id,n,i,a):await rE(e.id,t,n,i,e.simulatorSetPath,a);if("android"===e.platform)return r_(t),await rx(e.id,t,n,i,a);if("macos"===e.platform)return await rO(t,n,i,a);throw n.end(),new q("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rQ(e){let t=await rM({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:r$(t.text,{path:`${e.appLogPath} (simctl log show recovery)`,backend:"ios-simulator",maxEntries:e.maxEntries,include:e.include,maxPayloadChars:e.maxPayloadChars,maxScanLines:e.maxScanLines}),recoveredLineCount:t.recoveredLineCount}:null}async function r0(e){await e.stop(),await rI(e.wait)}async function r1(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await R("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await R("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 R("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 R("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await R("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function r2(e){let t=c.dirname(e),r=c.basename(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),s.existsSync(e)?s.truncateSync(e,0):s.writeFileSync(e,"","utf8");let a=0;for(let e of s.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let n=e.slice(r.length+1);if(/^\d+$/.test(n))try{s.unlinkSync(c.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let r3=new Map;function r4(e){let t=r3.get(e);if(t&&(clearTimeout(t.timer),r3.delete(e),t.deleteAfterDownload))try{s.rmSync(t.artifactPath,{force:!0})}catch{}}let r8=new Map;function r5(e,t){let r=r8.get(e);if(!r)throw new q("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new q("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function r6(e){let t=r8.get(e);t&&(clearTimeout(t.timer),r8.delete(e),s.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function r9(e){let t=await r7(e);await R("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=c.join(e.tempDir,t);if(!s.existsSync(r))throw new q("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function r7(e){let t=await R("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new q("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new q("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(ae),n=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new q("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new q("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===a.length)return a[0];throw new q("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===n||e.startsWith(`${n}/`)))throw new q("INVALID_ARGS",`Uploaded archive must contain a top-level "${n}" bundle`);for(let e of a){var i=e,o=n;if(i!==o&&!i.startsWith(`${o}/`))throw new q("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${i}`)}for(let t of(await R("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new q("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return n}function ae(e){if(e.includes("\0"))throw new q("INVALID_ARGS",`Invalid archive entry: ${e}`);if(c.posix.isAbsolute(e))throw new q("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=c.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new q("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let at=eZ(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function ar(e,t){return new Promise((r,a)=>{let n,i=s.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,u=e=>{if(!l){if(l=!0,n&&clearTimeout(n),e){i.destroy(),s.rmSync(t,{force:!0}),a(e);return}r()}},c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let e=new q("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:at});o(e),i.destroy(e),u(e)},at)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new q("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),i.destroy(e),u(e)}}),e.on("error",u),e.on("aborted",()=>{u(new q("COMMAND_FAILED","Artifact transfer was interrupted"))}),i.on("error",u),i.on("finish",()=>u()),c(),e.pipe(i)})}async function aa(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new q("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new q("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new q("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let n=function(e){let t=e.trim(),r=c.basename(t);if(!r||"."===r||".."===r)throw new q("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),i=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),s.mkdtempSync(c.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=c.join(i,n);return await ar(e,t),{artifactPath:t,tempDir:i}}let t=c.join(i,"artifact.tar");await ar(e,t);let a=await r9({archivePath:t,tempDir:i,platform:"ios",expectedRootName:n});return s.rmSync(t,{force:!0}),{artifactPath:a,tempDir:i}}catch(e){throw s.rmSync(i,{recursive:!0,force:!0}),e}}let an=new Set(["agent_device.command","agent-device.command"]),ai=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),ao=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),as={"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"},al=new Set([...an,...ai,...ao,...Object.keys(as)]);function ad(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function au(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function ac(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function ap(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=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??a??""}function af(e,t){let r=e[t];return"string"==typeof r?r:void 0}function am(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function ah(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=ee(new q("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:ad(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=ee(new q(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:ad(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=M(r.tenantId);if(!e){let e=ee(new q("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:ad(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function aw(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",a=c.isAbsolute(t)?t:c.resolve(t);try{e=await import(w(a).href)}catch(e){throw new q("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let n=e[r];if("function"!=typeof n)throw new q("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return n}async function ag(e){let t=await aw(),{handleRequest:r,token:a}=e;return y.createServer((e,n)=>{if("GET"===e.method&&"/health"===e.url){n.statusCode=200,n.setHeader("content-type","application/json"),n.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void ay(e,n,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void av(e,n,t,a);if("POST"!==e.method||"/rpc"!==e.url){n.statusCode=404,n.end("Not found");return}let i="";e.setEncoding("utf8"),e.on("data",t=>{(i+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{n.headersSent||au(n,ad(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(i)}catch{au(n,ad(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void au(n,ad(a.id??null,-32600,"Invalid Request"),400);if(!al.has(a.method))return void au(n,ad(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void au(n,ad(a.id??null,-32602,"Invalid params"),400);try{var s;let i=a.params,l=function(e,t,r){if(an.has(e))return{token:ap(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(ai.has(e)){let e,a=af(t,"platform");if("ios"!==a&&"android"!==a)throw new q("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:ap(t,r),session:af(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:af(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new q("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new q("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,a={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new q("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new q("INVALID_ARGS","Invalid params: source.headers values must be strings");a[e]=t}}return Object.keys(a).length>0?{kind:"url",url:e,headers:a}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new q("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new q("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:am(t,"retentionMs")}}}if(ao.has(e)){let e=af(t,"materializationId")?.trim();if(!e)throw new q("INVALID_ARGS","Invalid params: materializationId is required");return{token:ap(t,r),session:af(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:af(t,"requestId"),materializationId:e}}}let a=as[e];if(a)return{token:ap(t,r),session:af(t,"session")??"default",command:a,positionals:[],meta:{tenantId:af(t,"tenantId")??af(t,"tenant"),runId:af(t,"runId"),leaseId:af(t,"leaseId"),leaseTtlMs:am(t,"ttlMs"),leaseBackend:af(t,"backend")}};throw new q("INVALID_ARGS",`Method not found: ${e}`)}(a.method,i,e.headers);if(s=a.method,an.has(s)&&("string"!=typeof l.command||0===l.command.length))return void au(n,ad(a.id??null,-32602,"Invalid params: command is required"),400);o=eq(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},eH(o);let d=()=>{n.writableFinished||eW(o)};e.on("aborted",d),n.on("close",d);let u=await ah(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void au(n,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void au(n,{jsonrpc:"2.0",id:a.id??null,result:c});au(n,ad(a.id??null,-32e3,c.error.message,c.error),ac(c.error.code))}catch(t){let e=ee(t);au(n,ad(a.id??null,-32e3,e.message,e),ac(e.code))}finally{ez(o)}})})}async function ay(e,t,r,a){try{var n;let o,s,l=ap({},e.headers),d=aI(l,a);if(d){t.statusCode=ac(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await ah(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await aa(e),p=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},o=i.randomUUID(),(s=setTimeout(()=>{r6(o)},3e5)).unref(),r8.set(o,{artifactPath:n.artifactPath,tempDir:n.tempDir,tenantId:n.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:p}))}catch(r){let e=ee(r);t.statusCode=ac(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function av(e,t,r,a){let n=e.url?.slice("/upload/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let i=ap({},e.headers),o=aI(i,a);if(o){t.statusCode=ac(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let l=await ah(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:i,session:"default",command:"download_artifact",positionals:[n]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let d=function(e,t){let r=r3.get(e);if(!r)throw new q("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new q("UNAUTHORIZED","Artifact belongs to a different tenant");if(!s.existsSync(r.artifactPath))throw r4(e),new q("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),u=s.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=ee(e);t.statusCode=ac(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&r4(n)}),u.pipe(t)}catch(r){let e=ee(r);t.statusCode=ac(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function aI(e,t){return t&&e!==t?ee(new q("UNAUTHORIZED","Invalid token")):null}function aA(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function ab(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function aS(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new q("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class a_{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=aS(e.backend),r=M(e.tenantId);if(!r)throw new q("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=aA(e.runId);if(!a)throw new q("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(r,a,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,n);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),d={leaseId:i.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+n};return this.leases.set(d.leaseId,d),this.runBindings.set(o,d.leaseId),{...d}}heartbeatLease(e){let t=ab(e.leaseId);if(!t)throw new q("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new q("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=ab(e.leaseId);if(!t)throw new q("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=aS(e.backend),r=M(e.tenantId);if(!r)throw new q("INVALID_ARGS","tenant isolation requires tenant id.");let a=aA(e.runId);if(!a)throw new q("INVALID_ARGS","tenant isolation requires run id.");let n=ab(e.leaseId);if(!n)throw new q("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let i=this.leases.get(n);if(!i)throw new q("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(i.backend!==t||i.tenantId!==r||i.runId!==a)throw new q("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 q("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 q("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),a={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(a.leaseId,a),this.runBindings.set(this.bindingKey(a.tenantId,a.runId,a.backend),a.leaseId),{...a}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let a=M(t),n=aA(r);if(t&&!a)throw new q("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!n)throw new q("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||n&&e.runId!==n)throw new q("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let aN=["emulator","platform-tools",c.join("cmdline-tools","latest","bin"),c.join("cmdline-tools","tools","bin")];function aD(e){let t=new Set,r=[];for(let a of e){let e=a.trim();!e||t.has(e)||(t.add(e),r.push(e))}return r}function ax(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||u.homedir();return aD([t??"",r??"",a?c.join(a,"Android","Sdk"):""])}async function ak(e){try{return await d.access(e,d.constants.X_OK),!0}catch{return!1}}async function aM(e=process.env){let t,r=[];for(let a of ax(e)){let e=[];for(let t of aN){let r=c.join(a,t);await ak(r)&&e.push(r)}0!==e.length&&(t||(t=a),r.push(...e))}if(t&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||t,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||t),0===r.length)return;let a=(e.PATH??"").split(c.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=aD([...r,...a]).join(c.delimiter)}function aE(e,t){return["-s",e.id,...t]}async function aO(){if(await aM(),!await J("adb"))throw new q("TOOL_MISSING","adb not found in PATH")}function aL(e,t){let r=`${e}
|
|
12
|
-
${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function
|
|
13
|
-
${e.stderr}`}function aF(e,t){return["-s",e,...t]}function aU(e){return e.startsWith("emulator-")}function aV(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function aG(e,t=eR){return R("adb",aF(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function aB(e,t){let r=t.replace(/_/g," ").trim();if(!aU(e))return r||e;let a=await aq(e);return a?a.replace(/_/g," "):r||e}async function aj(e,t,r){try{return await r("adb",aF(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=G(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function aq(e,t=R){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await aj(e,["shell","getprop",r],t);if(!a)continue;let n=a.stdout.trim();if(0===a.exitCode&&n.length>0)return n}let r=await aj(e,["emu","avd","name"],t);if(!r)return;let a=function(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}(r.stdout);if(0===r.exitCode&&a)return a}async function aH(e,t){let r=a$(await R("adb",aF(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eR})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function aW(e){return(await Promise.all(aT.map(async t=>await aH(e,t)))).some(e=>!0===e)}async function az(e){var t;let r;return"tv"===((r=a$(await R("adb",aF(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eR})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await aW(e)?"tv":(t=a$(await R("adb",aF(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eR})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function aJ(e={}){if(await aM(),!await J("adb"))throw new q("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??e6(void 0),r=(await aK()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,n]=await Promise.all([aB(e,t),aQ(e),az(e)]);return{platform:"android",id:e,name:r,kind:aU(e)?"emulator":"device",target:n,booted:a}}))}async function aK(){return(await R("adb",["devices","-l"],{timeoutMs:eR})).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 aX(){let e=await R("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eR});if(0!==e.exitCode)throw new q("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 aY(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await aZ(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 q("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 aZ(e,t){let r=aV(e);for(let e of(await aK()).filter(e=>(!t||e.serial===t)&&aU(e.serial)))if(aV(e.rawModel)===r||aV(await aB(e.serial,e.rawModel))===r)return e.serial}async function aQ(e){try{let t=await aG(e);return"1"===t.stdout.trim()}catch{return!1}}async function a0(e){var t,r;let a;await aM();let n=e.avdName.trim();if(!n)throw new q("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let i=e.timeoutMs??12e4;if(!await J("adb"))throw new q("TOOL_MISSING","adb not found in PATH");if(!await J("emulator"))throw new q("TOOL_MISSING","emulator not found in PATH");let o=await aX(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let a=aV(t);return e.find(e=>aV(e)===a)}(o,n);if(!s)throw new q("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 l=Date.now(),d=(t=await aJ(),r=e.serial,a=aV(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&aV(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),O("emulator",t)}let u=d??await aY({avdName:s,serial:e.serial,timeoutMs:i}),c=Math.max(1e3,i-(Date.now()-l));await a1(u.id,c);let p=(await aJ()).find(e=>e.id===u.id);return p?{...p,name:s,booted:!0}:{...u,name:s,booted:!0}}async function a1(e,t=6e4){let r,a=eT.fromTimeoutMs(t),n=Math.max(1,Math.ceil(t/1e3)),i=!1;try{await e$(async({deadline:n})=>{if(n?.isExpired())throw i=!0,new q("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),message:"timeout"});let o=Math.max(1e3,n?.remainingMs()??t),s=await aG(e,Math.min(o,eR));if(r=s,"1"!==s.stdout.trim())throw new q("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=eQ({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>eQ({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let n=G(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eQ({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:a.elapsedMs(),reason:d,hint:e0(d),stdout:o,stderr:s,exitCode:l};if(i||"ANDROID_BOOT_TIMEOUT"===d)throw new q("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===n.code)throw new q("TOOL_MISSING",n.message,{...u,...n.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new q("COMMAND_FAILED",n.message,{...u,...n.details??{}});throw new q(n.code,n.message,{...u,...n.details??{}},n.cause)}}let a2=/\.(?:apk|aab)$/i,a3=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function a4(e){var t,r;let a=e.trim();return 0===a.length?"other":a2.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!a3.test(t))?"binary":"package":(r=a,a3.test(r))?"package":"other"}function a8(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let a5=[".zip",".tar",".tar.gz",".tgz"],a6=eZ(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),a9=["1","true","yes","on"];async function a7(e){let t=[];try{let r=await ne(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await ni(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:a.archivePath,installablePath:a.installablePath,cleanup:async()=>{await nd(t)}}}catch(e){throw await nd(t),e}}async function ne(e,t){if("path"===e.kind)return{localPath:B(e.path),cleanup:async()=>{}};let r=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-source-"));try{return{localPath:await nt(r,e.url,e.headers,t),cleanup:async()=>{await d.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(r,{recursive:!0,force:!0}),e}}async function nt(e,t,r,a){let n;try{n=new URL(t)}catch{throw new q("INVALID_ARGS",`Invalid source URL: ${t}`)}await nr(n);let i=a?.signal;if(i?.aborted)throw new q("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,s=()=>{o.abort(i?.reason)};i?.addEventListener("abort",s,{once:!0});let l=a?.downloadTimeoutMs??a6,u=setTimeout(()=>{o.abort(Error("download timeout"))},l);try{let t=await fetch(n,{headers:r,redirect:"follow",signal:o.signal});if(!t.ok)throw new q("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:n.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),n=a?.[1]?.trim();if(n)return c.basename(n);let i=c.basename(t.pathname);return i||"downloaded-artifact.bin"}(t,n),i=c.join(e,a),s=t.body;if(!s)throw new q("COMMAND_FAILED","Download response body was empty",{url:n.toString()});let l=await d.open(i,"w");try{for await(let e of s)await l.write(e)}finally{await l.close()}return i}catch(e){if(i?.aborted)throw new q("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new q("COMMAND_FAILED",`App source download timed out after ${l}ms`,{timeoutMs:l,url:n.toString()},e);throw e}finally{i?.removeEventListener("abort",s),clearTimeout(u)}}async function nr(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new q("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!a9.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||nn(t))throw new q("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await v.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>nn(e.address)))throw new q("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function na(e){var t,r,a,n;let i=e instanceof URL?e:new URL(e),o=i.hostname.toLowerCase();if(!o)return!1;let s=i.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,n=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(n))}function nn(e){let t,r=p.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,a]=t;return 10===r||127===r||169===r&&254===a||172===r&&!!(a>=16)&&!!(a<=31)||192===r&&168===a}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function ni(e,t){let r=await d.stat(e).catch(()=>null);if(!r)throw new q("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&nl(e)){if(!t.allowArchiveExtraction)throw new q("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await ns(e);return t.registerCleanup(r.cleanup),await ni(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await no(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new q("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await no(e,(e,t)=>t.isFile()&&nl(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new q("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await ns(a[0]);return t.registerCleanup(e.cleanup),await ni(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new q("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new q("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function no(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let n=await d.readdir(e.path,{withFileTypes:!0});for(let i of(n.sort((e,t)=>e.name.localeCompare(t.name)),n)){let n=c.join(e.path,i.name);if(t(n,i)){r.push(n);continue}i.isDirectory()&&e.depth<5&&a.push({path:n,depth:e.depth+1})}}return r}async function ns(e){let t=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await R("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await R("tar",["-xzf",e,"-C",t]):await R("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await d.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(t,{recursive:!0,force:!0}),e}}function nl(e){let t=e.toLowerCase();return a5.some(e=>t.endsWith(e))}async function nd(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let nu=new A("utf-16le");async function nc(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await np(e,r);if(!a)continue;let n=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),n=e.readUInt16LE(r+2),i=e.readUInt32LE(r+4);if(i<=0||r+i>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),n=(256&r)!=0,i=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);i.push(n?function(e,t){let[,r]=nf(e,t),[a,n]=nf(e,t+r),i=t+r+n;return e.subarray(i,i+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),n=t+a;return nu.decode(e.subarray(n,n+2*r))}(e,o))}return i}(e.subarray(r,r+i));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let n=e.readUInt16LE(t+24),i=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+n;for(let t=0;t<o;t+=1){let r=s+t*i;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let n=e.readUInt32LE(r+8);if(0xffffffff!==n)return a[n];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,n,t);if(a)return a}r+=i}}(t);if(n)return n}return await nm(e)}async function np(e,t){try{let r=await R("unzip",["-p",e,t],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function nf(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function nm(e){let t=await nh();if(!t)return;let r=await R(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function nh(){if(void 0!==e)return e??void 0;try{for(let t of ax()){let r=c.join(t,"build-tools");try{for(let t of(await I.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=c.join(r,t,"aapt");try{return await I.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function nw(e,t){let r="url"===e.kind&&na(e.url),a=await a7({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=c.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),n=t?.resolveIdentity===!1?{}:await ng(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:n.packageName,cleanup:a.cleanup}}async function ng(e){let t=c.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await nc(e)}}let ny={settings:{type:"intent",value:"android.settings.SETTINGS"}},nv="android.intent.category.LAUNCHER",nI="android.intent.category.LEANBACK_LAUNCHER",nA="android.intent.category.DEFAULT",nb="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.";async function nS(e,t){let r=t.trim();if("package"===a4(r))return{type:"package",value:r};let a=ny[r.toLowerCase()];if(a)return a;let n=(await R("adb",aE(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 q("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:n,hint:"Run agent-device apps --platform android to see the exact installed package names before retrying open."});throw new q("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:nb})}async function n_(e,t="all"){let r=await nN(e);return("user-installed"===t?(await nx(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:nk(e)}))}async function nN(e){let t=new Set;for(let r of nD(e,{includeFallbackWhenUnknown:!0})){let a=await R("adb",aE(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],n=a.includes("/")?a.split("/")[0]:a;n&&t.add(n)}}return t}function nD(e,t={}){return"tv"===e.target?[nI]:"mobile"===e.target?[nv]:t.includeFallbackWhenUnknown?[nv,nI]:[nv]}async function nx(e){return(await R("adb",aE(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function nk(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let n=r[e];if(!t.has(n)){a=n;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function nM(e){let t=await nE(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await nE(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function nE(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 R("adb",aE(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function nO(e,t,r){var a,n;let i;e.booted||await a1(e.id);let o=t.trim();if(aP(o)){if(r)throw new q("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await R("adb",aE(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await nS(e,t),l=nD(e)[0]??nv;if("intent"===s.type){if(r)throw new q("INVALID_ARGS","Activity override requires a package name, not an intent");await R("adb",aE(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;try{await R("adb",aE(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nA,"-c",l,"-n",t]))}catch(t){throw await nP(e,s.value,t),t}return}let d=await R("adb",aE(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nA,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,n=d.stderr,i=`${a}
|
|
14
|
-
${n}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(i)))return;let u=await
|
|
15
|
-
${r.stderr}`;return!!(0===r.exitCode&&/\bpackage:/i.test(a))||(
|
|
16
|
-
${String(r.details?.stderr??"")}`:"")||!await
|
|
17
|
-
${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new q("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let nV=null;async function nG(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(nV?.key===e)return nV.invocation;if(await J("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return nV={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new q("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await d.access(t)}catch{throw new q("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return nV={key:e,invocation:r},r}async function nB(e){let t=await nG();await R(t.cmd,[...t.prefixArgs,...e])}async function nj(e,t){let r,a=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-aab-")),n=c.join(a,"bundle.apks"),i=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await nB(["build-apks","--bundle",t,"--output",n,"--mode",i]),await nB(["install-apks","--apks",n,"--device-id",e.id])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function nq(e,t){".aab"===c.extname(t).toLowerCase()?await nj(e,t):await R("adb",aE(e,["install","-r",t]))}async function nH(e){return new Set((await R("adb",aE(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function nW(e,t){let r=Array.from(await nH(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function nz(e,t){e.booted||await a1(e.id),await nq(e,t)}async function nJ(e,t,r){let a=r?void 0:await nH(e);return await nz(e,t),r??(a?await nW(e,a):void 0)}async function nK(e,t){e.booted||await a1(e.id);let r=await nw({kind:"path",path:t});try{let t=await nJ(e,r.installablePath,r.packageName),a=t?nk(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function nX(e,t,r){e.booted||await a1(e.id);let{package:a}=await nU(e,t),n=await nw({kind:"path",path:r},{resolveIdentity:!1});try{return await nz(e,n.installablePath),{package:a}}finally{await n.cleanup()}}function nY(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,a=function(e){if(void 0===e)return .6;if(!Number.isFinite(e)||e<=0)throw new q("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),n=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new q("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*a),i=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(n,Math.max(1,r-2*i))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(r,a,n,i)=>({direction:t,x1:r,y1:a,x2:n,y2:i,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return u(l,d-s,l,d+s);case"down":return u(l,d+s,l,d-s);case"left":return u(l-s,d,l+s,d);case"right":return u(l+s,d,l-s,d)}}function nZ(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,n=a.exec(e);for(;n;){let t=n1(n[0]),i=(n2(t,"text")??"").toLowerCase(),o=(n2(t,"content-desc")??"").toLowerCase();if(i.includes(r)||o.includes(r)){let e=n3(n2(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=a.exec(e)}return null}function nQ(e,t,r){let a=function(e){let t=0,r=0,a=[...e.children];for(;a.length>0;){let e=a.pop();t+=1,r=Math.max(r,e.depth),a.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(e),n=[],i=[],o=!1,s=r.depth??1/0,l=r.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children],n=0;for(;n<a.length;){let e=a[n++],t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",o=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||o.includes(r))return e;a.push(...e.children)}return null}(e,r.scope):null,d=l?[l]:e.children,u=new Map,c=e=>{let t=u.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||c(t))return u.set(e,!0),!0;return u.set(e,!1),!1},p=(e,a,l,d=!1,u=!1)=>{if(n.length>=t){o=!0;return}if(a>s)return;let f=!!r.raw||function(e,t,r,a,n){var i;let o,s=n8(e.type),l=!!(e.label&&e.label.trim().length>0),d=!!(e.identifier&&e.identifier.trim().length>0),u=l&&!n5(e.label??""),c=d&&!n5(e.identifier??""),p=(o=(i=s).split(".").pop()??i).includes("layout")||"viewgroup"===o||"view"===o,f="imageview"===s||"imagebutton"===s;if(t.interactiveOnly)return!!(e.hittable||F(s)&&a)||!!(u||c)&&!f&&(!p||!!n)&&(r||a||n);return t.compact?u||c||!!e.hittable:!p&&!f||!!e.hittable||!!u||!!c&&!!a||a}(e,r,d,c(e),u),m=l;f&&(m=n.length,i.push(e),n.push({index:m,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:a,parentIndex:l,...e.hiddenContentAbove?{hiddenContentAbove:!0}:{},...e.hiddenContentBelow?{hiddenContentBelow:!0}:{}}));let h=d||!!e.hittable,w=u||function(e){if(!e)return!1;let t=n8(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(p(t,a+1,m,h,w),o)return};for(let e of d)if(p(e,0,void 0,!1,!1),o)break;return o?{nodes:n,sourceNodes:i,truncated:o,analysis:a}:{nodes:n,sourceNodes:i,analysis:a}}function n0(e){let t=n1(e),r=e=>{let r=n2(t,e);if(null!==r)return"true"===r};return{text:n2(t,"text"),desc:n2(t,"content-desc"),resourceId:n2(t,"resource-id"),className:n2(t,"class"),bounds:n2(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function n1(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let n=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,i=r;for(;i<a;){for(;i<a;){let t=e[i];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;i+=1}if(i>=a)break;let r=e[i];if("/"===r||">"===r)break;n.lastIndex=i;let o=n.exec(e);if(!o)break;t.set(o[1],o[3]),i=n.lastIndex}return t}function n2(e,t){return e.get(t)??null}function n3(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),a=Number(t[2]);return{x:r,y:a,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-a)}}function n4(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,n=a.exec(e);for(;n;){let t=n[0];if(t.startsWith("</node")){r.length>1&&r.pop(),n=a.exec(e);continue}let i=n0(t),o=n3(i.bounds),s=r[r.length-1],l={type:i.className,label:i.text||i.desc,value:i.text,identifier:i.resourceId,rect:o,enabled:i.enabled,hittable:i.clickable??i.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),n=a.exec(e)}return t}function n8(e){return e?e.toLowerCase():""}function n5(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}function n6(e){if(0===e.length)return null;let t=[...e].sort((e,t)=>e-t);return t[Math.floor(t.length/2)]??null}function n9(e,t){let r=Math.max(24,Math.round(.2*Math.min(e.size,t.size))),a=Math.max(48,Math.round(.15*Math.min(e.crossSize,t.crossSize)));return Math.abs(e.size-t.size)<=r&&Math.abs(e.crossSize-t.crossSize)<=a}function n7(e,t){return{start:e.y-t.y,size:e.height,crossSize:e.width}}async function ie(e,t={}){let r=await ir(e);if(!t.interactiveOnly){let a=function(e,t){let{sourceNodes:r,...a}=nQ(n4(e),800,t);return a}(r,t);return await it(e,a.nodes),a}let a=n4(r),n=nQ(a,800,{...t,interactiveOnly:!1});await it(e,n.nodes),function(e){if(0===e.length||e.some(e=>e.hiddenContentAbove||e.hiddenContentBelow))return;let t=new Map(X(eS(e)).nodes.filter(e=>e.hiddenContentAbove||e.hiddenContentBelow).map(e=>[e.index,e]));for(let r of e){let e=t.get(r.index);e&&(e.hiddenContentAbove&&(r.hiddenContentAbove=!0),e.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}(n.nodes),function(e){for(let[t,r]of e.sourceNodes.entries()){let a=e.nodes[t];a&&(a.hiddenContentAbove&&(r.hiddenContentAbove=!0),a.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}(n);let{sourceNodes:i,...o}=nQ(a,800,t);return o}async function it(e,t){if(!t.some(e=>F(e.type)))return;let r=await is(e);r&&function(e,t){let r=function(e){let t={className:"root",rect:{x:0,y:0,width:0,height:0},children:[]},r=[{indent:-1,node:t}],a=/^(\s*)([\w.$]+)\{[^}]* (-?\d+),(-?\d+)-(-?\d+),(-?\d+) #/;for(let t of e.split("\n")){let e=a.exec(t);if(!e)continue;let n=e[1].length,i=Number(e[3]),o=Number(e[4]),s=Number(e[5]),l=Number(e[6]),d={className:e[2],rect:{x:i,y:o,width:Math.max(0,s-i),height:Math.max(0,l-o)},children:[]};for(;r.length>1&&n<=r[r.length-1].indent;)r.pop();r[r.length-1].node.children.push(d),r.push({indent:n,node:d})}return t.children.length>0?t:null}(t);if(!r)return;let a=function(e){let t=[],r=[e];for(;r.length>0;){let e=r.pop();if(F(e.className)){let r=function(e){let t=e.children[0];if(!t)return null;let r=Math.max(t.rect.height,...t.children.map(e=>e.rect.y+e.rect.height)),a=t.children.filter(e=>e.rect.height>0).map(t=>n7(t.rect,e.rect)).sort((e,t)=>e.start-t.start);return 0===a.length?null:{rect:e.rect,contentExtent:r,contentBlocks:a}}(e);r&&t.push(r)}r.push(...e.children)}return t}(r);if(0!==a.length)for(let t of e){if(!t.rect||!F(t.type))continue;let r=function(e,t){let r=null,a=1/0;for(let n of t){let t=Math.abs(n.rect.width-e.width)+Math.abs(n.rect.height-e.height);if(t>32)continue;let i=4*t+(Math.abs(n.rect.x-e.x)+Math.abs(n.rect.y-e.y));i<a&&(r=n,a=i)}return r}(t.rect,a);if(!r)continue;let n=function(e,t){let r=function(e,t){let r=t,a=new Set;for(;!a.has(r.index);){var n,i;a.add(r.index);let o=e.filter(e=>e.parentIndex===r.index&&e.rect);if(1!==o.length)return r;let s=o[0];if(n=s.rect,i=t.rect,n.x!==i.x||n.y!==i.y||n.width!==i.width||n.height!==i.height)return r;r=s}return t}(e,t);return e.filter(e=>e.parentIndex===r.index&&e.rect).map(e=>e.rect).filter(e=>e.height>0).sort((e,t)=>e.y-t.y).map(e=>n7(e,t.rect))}(e,t),i=function(e){let{viewportRect:t,visibleBlocks:r,nativeScrollView:a}=e;if(0===r.length||0===a.contentBlocks.length)return null;let n=function(e){if(0===e.contentBlocks.length)return null;let t=e.contentBlocks[0],r=e.contentBlocks[e.contentBlocks.length-1];if(!t||!r)return null;let a=n6(e.contentBlocks.map(e=>e.size))??e.rect.height,n=Math.max(48,Math.round(.5*a)),i=Math.max(24,Math.round(.25*a)),o=t.start>=n,s=e.contentExtent-(r.start+r.size)>=i;return o||s?{above:o,below:s}:null}(a),i=function(e,t){let r=new Map;for(let a of e)for(let e of t){if(!n9(a,e))continue;let t=a.start-e.start,n=8*Math.round(t/8),i=r.get(n)??[];i.push(t),r.set(n,i)}let a=null;for(let e of r.values())(!a||e.length>a.length)&&(a=e);if(!a||a.length<2)return null;let n=[...a].sort((e,t)=>e-t);return n[Math.floor(n.length/2)]??null}(a.contentBlocks,r)??function(e){let{nativeBlocks:t,visibleBlocks:r,viewportExtent:a,contentExtent:n}=e,i=[],o=[];for(let e of t)for(let t of r){if(!n9(e,t))continue;let r=e.start-t.start;16>=Math.abs(r)&&i.push(r),16>=Math.abs(r+a-n)&&o.push(r)}return o.length>0?n6(o):i.length>0?n6(i):null}({nativeBlocks:a.contentBlocks,visibleBlocks:r,viewportExtent:t.height,contentExtent:a.contentExtent});if(null===i)return n;let o=t.height;return{above:(n?.above??!1)||i>16,below:(n?.below??!1)||i+o<a.contentExtent-16}}({viewportRect:t.rect,visibleBlocks:n,nativeScrollView:r});i&&(i.above&&(t.hiddenContentAbove=!0),i.below&&(t.hiddenContentBelow=!0))}}(t,r)}async function ir(e){return eF(()=>ia(e),{shouldRetry:io})}async function ia(e){var t,r,a;let n,i,o=await R("adb",aE(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0}),s=ii(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",d=await R("adb",aE(e,["shell","uiautomator","dump",l]),{allowFailure:!0}),u=(t=l,r=d.stdout,a=d.stderr,n=`${r}
|
|
18
|
-
${a}`,i=/dumped to:\s*(\S+)/i.exec(n),i?.[1]??t),c=await
|
|
19
|
-
${t}`,a=r.indexOf("<?xml"),n=a>=0?a:r.indexOf("<hierarchy");if(n<0)return null;let i=r.lastIndexOf("</hierarchy>");if(i<0||i<n)return null;let o=r.slice(n,i+12).trim();return o.length>0?o:null}function
|
|
20
|
-
${t.stderr}`.trim();return r.length>0?r:null}catch{return null}}async function il(e,t,r){await R("adb",aE(e,["shell","input","tap",String(t),String(r)]))}async function id(e,t,r,a,n,i=250){await R("adb",aE(e,["shell","input","swipe",String(t),String(r),String(a),String(n),String(i)]))}async function iu(e){await R("adb",aE(e,["shell","input","keyevent","4"]))}async function ic(e){await R("adb",aE(e,["shell","input","keyevent","3"]))}async function ip(e,t){let r=function(e){switch(e){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new q("INVALID_ARGS",`Unsupported Android rotation: ${e}`)}}(t);await R("adb",aE(e,["shell","settings","put","system","accelerometer_rotation","0"])),await R("adb",aE(e,["shell","settings","put","system","user_rotation",r]))}async function im(e){await R("adb",aE(e,["shell","input","keyevent","187"]))}async function ih(e,t,r,a=800){await R("adb",aE(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function iw(e,t,r=0){r>0&&Array.from(t).length>1?await iN(e,t,1,r):await ig(e,t)}async function ig(e,t){let r=iD(t);if(!r||"ok"!==await ix(e,t))try{let r=t.replace(/ /g,"%s");await R("adb",aE(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof q)||"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 q("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 iy(e,t,r){await il(e,t,r)}async function iv(e,t,r,a,n=0){let i=Array.from(a).length,o=iD(a),s=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];!o&&n<=0&&s.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),(!o||n>0)&&s.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96});let l=null;for(let o of s){var d,u;await iy(e,t,r);let s=(d=i+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await ik(e,s),"input_text"===o.strategy)await iw(e,a,n);else if("clipboard_paste"===o.strategy){if("ok"!==await ix(e,a))continue}else await iN(e,a,1,n>0?n:15);let c=await iI(e,t,r,a);if(l=c.actual,c.ok)return}throw new q("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function iI(e,t,r,a){let n=null;for(let i of[0,150,350])if(i>0&&await aC(i),function(e,t){if(e===t)return!0;let r=iA(e),a=iA(t);return!!r&&!!a&&(!!(r===a||r.includes(a))||a.includes(r)&&r.length>=Math.max(4,Math.floor(.8*a.length)))}(n=await iM(e,t,r),a))return{ok:!0,actual:n};return{ok:!1,actual:n}}function iA(e){return(e??"").replace(/\s+/g," ").trim()}async function ib(e,t,r){let a=await i_(e),n=nY({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await R("adb",aE(e,["shell","input","swipe",String(n.x1),String(n.y1),String(n.x2),String(n.y2),"300"])),n}async function iS(e,t,r){let a=r?.maxScrolls??8,n="";try{n=await ir(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new q("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(nZ(n,t))return{attempts:0};for(let r=1;r<=a;r+=1){await ib(e,"down",{amount:.5});let a="";try{a=await ir(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new q("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(nZ(a,t))return{attempts:r};if(a===n)throw new q("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:r,stalled:!0});n=a}throw new q("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:a})}async function i_(e){let t=(await R("adb",aE(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new q("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iN(e,t,r,a){let n=Math.max(1,Math.floor(r)),i=Array.from(t);for(let t=0;t<i.length;t+=n){let r=i.slice(t,t+n).join("");await ig(e,r),a>0&&t+n<i.length&&await aC(a)}}function iD(e){for(let t of e){let e=t.codePointAt(0);if(void 0!==e&&(e<32||e>126))return!0}return!1}async function ix(e,t){let r=await R("adb",aE(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":aL(r.stdout,r.stderr)?"unsupported":0===(await R("adb",aE(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await R("adb",aE(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function ik(e,t){let r=Math.max(0,t);await R("adb",aE(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let a=Math.min(24,r-t);await R("adb",aE(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function iM(e,t,r){let a,n=await ir(e),i=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=i.exec(n));){let e=n0(a[0]),n=n3(e.bounds);if(!n)continue;let i=e.className??"",d=(e.text??"").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/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&&iE(i)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&iE(i)){(!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 iE(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iO(e){let t=await R("adb",aE(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new q("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),n=a.length>0?a[a.length-1]?.[1]:void 0,i=n?`0x${n.toLowerCase()}`:void 0;return{visible:r,inputType:i,type:i?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(i):void 0}}(t.stdout)}async function iL(e){let t=await iO(e),r=t,a=0;for(;r.visible&&a<2;)await R("adb",aE(e,["shell","input","keyevent","111"])),a+=1,await aC(120),r=await iO(e);if(t.visible&&r.visible)throw new q("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:a,inputType:r.inputType,type:r.type});return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function iC(e){let t,r;return(r=(t=(await iR(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 iP(e,t){await iR(e,["shell","cmd","clipboard","set","text",t],"write")}async function iR(e,t,r){let a=await R("adb",aE(e,t),{allowFailure:!0});if(aL(a.stdout,a.stderr))throw new q("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new q("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let iT=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function i$(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new q("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iF(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 q("INVALID_ARGS",`permission setting requires a target: ${iT.join("|")}`)}function iU(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new q("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function iV(e,t,r,a,n){switch(t.toLowerCase()){case"wifi":{let t=iB(r);await R("adb",aE(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=iB(r);await R("adb",aE(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await R("adb",aE(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=iB(r);await R("adb",aE(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await ij(e,r);await R("adb",aE(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 q("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await iG(e,t);return}case"permission":{if(!a)throw new q("INVALID_ARGS","permission setting requires an active app in session");let t=i$(r),i=function(e,t){let r=iF(e);if(t?.trim())throw new q("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 q("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(n?.permissionTarget,n?.permissionMode);if("notifications"===i.kind)return void await iH(e,a,t,i);let o="grant"===t?"grant":"revoke";if("photos"===i.type)return void await iq(e,a,o);await R("adb",aE(e,["shell","pm",o,a,i.value]));return}default:throw new q("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function iG(e,t){var r;let a,n,i=(r=e,n=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&n.push(["emu","finger","touch",a]),n),o=[];for(let t of i){let r=await R("adb",aE(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
|
|
21
|
-
${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new
|
|
22
|
-
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!n)throw new
|
|
23
|
-
${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function
|
|
24
|
-
${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new
|
|
25
|
-
`,"utf8"),a}async function
|
|
4
|
+
${r}`.toLowerCase()).includes("device is busy")&&a.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":e1("IOS_RUNNER_CONNECT_TIMEOUT"))})}function tn(e){if(eX(e))throw eY()}let ti=eQ(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),to=eQ(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),ts=eQ(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),tl=eQ(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),td=eQ(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),tu=eQ(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),tc=eQ(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),tp=eQ(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function tf(e,t,r,a,n=ti,i,o){let s=e$.fromTimeoutMs(n),l=await tm(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(n/ts));try{return await eF(async({deadline:s})=>{if(s?.isExpired())throw new H("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:n});if(i&&null!==i.child.exitCode&&void 0!==i.child.exitCode)throw await ta({session:i,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await tm(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??n;if(e<=0)throw new H("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:n});return await th(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(tu,e),o)}catch(e){if(o?.aborted||eZ(e))throw eY();d=e}throw new H("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:tl,maxDelayMs:td,jitter:.2,shouldRetry:tt},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||eZ(e))throw eY();d||(d=e)}if(o?.aborted)throw eY();if("simulator"===e.kind){let n=s.remainingMs();if(n<=0)throw tr({port:t,endpoints:l,logPath:a,lastError:d});let i=await tg(e,t,r,n);return new Response(i.body,{status:i.status})}throw tr({port:t,endpoints:l,logPath:a,lastError:d})}async function tm(e,t,r){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let n=await tw(e.id,r);return n&&a.unshift(`http://[${n}]:${t}/command`),a}async function th(e,t,r,a){let n,i=new AbortController,o=setTimeout(()=>i.abort(),r);a&&(a.aborted?(clearTimeout(o),i.abort()):(n=()=>i.abort(),a.addEventListener("abort",n,{once:!0})));try{return await fetch(e,{...t,signal:i.signal})}finally{clearTimeout(o),n&&a&&a.removeEventListener("abort",n)}}async function tw(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(tc,t)):tc,a=p.join(u.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),n=await T("xcrun",["devicectl","device","info","details","--device",e,"--json-output",a,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==n.exitCode||!s.existsSync(a))return null;let i=JSON.parse(s.readFileSync(a,"utf8"));if(i.info?.outcome&&"success"!==i.info.outcome)return null;let o=(i.result?.connectionProperties?.tunnelIPAddress??i.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{tI(a)}}async function tg(e,t,r,a){let n=JSON.stringify(r),i=te(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 T("xcrun",i,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=e0({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new H("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:e1(e)})}return{status:200,body:s}}async function ty(){return await new Promise((e,t)=>{let r=f.createServer();r.listen(0,"127.0.0.1",()=>{let a=r.address();if("object"==typeof a&&a?.port){let t=a.port;r.close(()=>e(t))}else r.close(()=>t(new H("COMMAND_FAILED","Failed to allocate port")))}),r.on("error",t)})}function tv(e,t,r,a){t&&s.appendFile(t,e,()=>{}),r&&s.appendFile(r,e,()=>{}),a&&process.stderr.write(e)}function tI(e){try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}let tb=new m;async function tA(e,t,r){let a=tb.getStore()??[];if(a.some(r=>r.locks===e&&r.key===t))return await r();let n=(e.get(t)??Promise.resolve()).catch(()=>{}).then(()=>tb.run([...a,{locks:e,key:t}],r));return e.set(t,n),n.finally(()=>{e.get(t)===n&&e.delete(t)})}function tS(e){return"apple"===e||"ios"===e||"macos"===e}function t_(e,t){return!t||("apple"===t?tS(e):e===t)}function tN(e){let{simulatorSetPath:t,platform:r,target:a}=e;if(t&&"macos"!==r&&"desktop"!==a)return t}async function tx(e,t,r={}){let a=e,n=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>t_(e.platform,t.platform))),t.target&&(a=a.filter(e=>(e.target??"mobile")===t.target)),t.udid){let e=a.find(e=>e.id===t.udid&&tS(e.platform));if(!e)throw new H("DEVICE_NOT_FOUND",`No Apple device with UDID ${t.udid}`);return e}if(t.serial){let e=a.find(e=>e.id===t.serial&&"android"===e.platform);if(!e)throw new H("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=n(t.deviceName),r=a.find(t=>n(t.name)===e);if(!r)throw new H("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===a.length)return a[0];if(0===a.length){var i;let e=r.simulatorSetPath;if(e&&(!(i=t.platform)||"apple"===i||"ios"===i))throw new H("DEVICE_NOT_FOUND","No devices found in the scoped simulator set",{simulatorSetPath:e,hint:`The simulator set at "${e}" appears to be empty. Create a simulator first:
|
|
5
|
+
xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new H("DEVICE_NOT_FOUND","No devices found",{selector:t})}let o=a.filter(e=>"device"!==e.kind);o.length>0&&(a=o);let s=a.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??a[0]}let tD=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function tk(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new H("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:r});let a=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of a)if(!s.existsSync(e))throw new H("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==eo("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await T("codesign",["--remove-signature",e],{allowFailure:!0});try{await T("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof H?a:new H("COMMAND_FAILED",String(a));throw new H("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}let tM="XCTestDevices",tE=".agent-device-backup",tO=".agent-device-xctestdevices-backup-",tL=p.join(u.homedir(),".agent-device","ios-runner"),tC=new Map,tP=new Set;function tR(e){return e?.trim()??""}function tT(e=process.env){return tR(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tR(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function t$(e=process.env){let t=tR(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tT(e)}.uitests`}let tF=function(e=process.env){let t=tT(e),r=t$(e);return Array.from(new Set([tR(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);function tU(e=u.homedir()){return p.join(e,"Library","Developer","XCTestDevices")}async function tG(e,t={}){if("ios"!==e.platform||"simulator"!==e.kind)return null;let r=e8(e.simulatorSetPath);if(!r)return null;let a=p.resolve(r),n=p.resolve(t.xctestDeviceSetPath??tU()),i=p.resolve(t.backupPath??function(e=tU()){return`${e}${tE}`}(n)),o=p.resolve(t.lockDirPath??function(e=u.homedir()){return p.join(e,".agent-device","xctest-device-set.lock")}()),l=t.ownerStartTime??eg(process.pid),d=await tj({lockDirPath:o,owner:{pid:t.ownerPid??process.pid,startTime:l,acquiredAtMs:t.nowMs??Date.now()}});try{if(tV({xctestDeviceSetPath:n,backupPath:i}),function(e,t){if(p.resolve(e)===p.resolve(t))return!0;try{return s.realpathSync.native(e)===s.realpathSync.native(t)}catch{return!1}}(a,n))return await d(),null;s.mkdirSync(a,{recursive:!0}),s.existsSync(n)&&s.renameSync(n,i),function(e){let{requestedSetPath:t,xctestDeviceSetPath:r}=e,a=p.dirname(r),n=p.join(a,`${tM}.agent-device-link-${process.pid}-${Date.now()}`);s.mkdirSync(a,{recursive:!0});try{s.symlinkSync(t,n,"dir"),s.renameSync(n,r)}catch(e){throw s.existsSync(n)&&tB(n),e}}({requestedSetPath:a,xctestDeviceSetPath:n})}catch(e){throw tV({xctestDeviceSetPath:n,backupPath:i}),await d(),new H("COMMAND_FAILED","Failed to redirect XCTest device set path",{requestedSetPath:a,xctestDeviceSetPath:n,backupPath:i,error:String(e)})}let c=!1;return{release:async()=>{if(!c){c=!0;try{tV({xctestDeviceSetPath:n,backupPath:i})}finally{await d()}}}}}function tV(e){let{xctestDeviceSetPath:t,backupPath:r}=e,a=[r,...function(e){let t=p.dirname(e),r=p.basename(e).replace(tE,""),a=r===tM?tO:`${r}${tO}`;try{return s.readdirSync(t).filter(e=>e.startsWith(a)).sort().map(e=>p.join(t,e))}catch{return[]}}(r)],n=a.find(e=>s.existsSync(e)),i=s.existsSync(t)&&s.lstatSync(t).isSymbolicLink();if(n){if(i&&tB(t),s.existsSync(t))if(!i)return void eu({level:"warn",phase:"ios_runner_xctest_device_set_restore_collision",data:{xctestDeviceSetPath:t,activeBackupPath:n}});else n!==r?s.rmSync(n,{recursive:!0,force:!0}):s.rmSync(r,{recursive:!0,force:!0});else s.mkdirSync(p.dirname(t),{recursive:!0}),s.renameSync(n,t);for(let e of a)e!==n&&s.existsSync(e)&&s.rmSync(e,{recursive:!0,force:!0});return}i&&(eu({level:"warn",phase:"ios_runner_xctest_device_set_orphaned_symlink",data:{xctestDeviceSetPath:t}}),tB(t))}function tB(e){!s.existsSync(e)||s.lstatSync(e).isSymbolicLink()&&s.unlinkSync(e)}async function tj(e){let{lockDirPath:t,owner:r}=e,a=p.join(t,"owner.json"),n=Date.now()+3e4;for(s.mkdirSync(p.dirname(t),{recursive:!0});Date.now()<n;)try{s.mkdirSync(t),function(e,t){let r=`${e}.${process.pid}.${Date.now()}.tmp`;s.writeFileSync(r,JSON.stringify(t),"utf8"),s.renameSync(r,e)}(a,r);let e=!1;return async()=>{e||(e=!0,s.rmSync(t,{recursive:!0,force:!0}))}}catch(e){if("EEXIST"!==e.code)throw e;if(function(e,t){let r=null;try{r=s.statSync(e)}catch{return!0}let a=function(e){try{return JSON.parse(s.readFileSync(e,"utf8"))}catch{return null}}(t);if(a){var n;return!(Number.isInteger((n=a).pid)&&!(n.pid<=0)&&ew(n.pid)&&(!n.startTime||eg(n.pid)===n.startTime))&&(s.rmSync(e,{recursive:!0,force:!0}),!0)}return!(Date.now()-r.mtimeMs<5e3)&&(s.rmSync(e,{recursive:!0,force:!0}),!0)}(t,a))continue;await new Promise(e=>setTimeout(e,100))}throw new H("COMMAND_FAILED","Timed out waiting for XCTest device set lock",{lockDirPath:t})}async function tq(e,t){var r;let a,n=(r=e,(a=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?p.resolve(a):"macos"===r.platform?p.join(tL,"derived","macos"):"simulator"===r.kind?p.join(tL,"derived"):p.join(tL,"derived",r.kind)),i=function(){let e=p.dirname(w(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=p.join(t,"package.json");if(s.existsSync(e))return t;t=p.dirname(t)}return e}();return await tA(tC,n,async()=>{eC(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(t2("clean","forced_clean",{derived:n}),t1(n),tH(n));let r=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let r=e.resolveExistingXctestrunProductPaths(t);return r?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:r}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:r}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:n,projectRoot:i,findXctestrun:t=>tz(t,e),xctestrunReferencesProjectRoot:tX,resolveExistingXctestrunProductPaths:t3});if("reuse_ready"!==r.reason&&t2("rebuild",r.reason,{derived:n,xctestrunPath:r.xctestrunPath}),"reuse_ready"===r.reason)try{return await tk(e,r.productPaths,r.xctestrunPath),t2("reuse","reuse_ready",{derived:n,xctestrunPath:r.xctestrunPath}),r.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof H))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&tD.has(t)}(e))throw e;t2("rebuild","repair_failed",{derived:n,xctestrunPath:r.xctestrunPath})}r.xctestrunPath&&(t1(n),tH(n));let a=p.join(i,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!s.existsSync(a))throw new H("COMMAND_FAILED","iOS runner project not found",{projectPath:a});await tY(e,a,n,t);let o=tz(n,e);if(!o)throw new H("COMMAND_FAILED","Failed to locate .xctestrun after build");let l=t3(o);if(!l)throw new H("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:o});return await tk(e,l,o),t2("build","built_new",{derived:n,xctestrunPath:o}),o})}function tH(e){try{if(!s.existsSync(e))return;if("derived"!==p.basename(e))return void s.rmSync(e,{recursive:!0,force:!0});for(let r of s.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,tW.has(t)&&s.rmSync(p.join(e,r.name),{recursive:!0,force:!0})}}catch{}}let tW=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function tz(e,t){if(!s.existsSync(e))return null;let r=[],a=[e];for(;a.length>0;){let e=a.pop();for(let t of s.readdirSync(e,{withFileTypes:!0})){let n=p.join(e,t.name);if(t.isDirectory()){a.push(n);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=s.statSync(n);r.push({path:n,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let a=tJ(r.path,t)-tJ(e.path,t);if(0!==a)return a}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)}function tJ(e,t){var r;let a=0,n=e.toLowerCase();p.basename(n).startsWith("agentdevicerunner.env.")&&(a-=1e3),n.includes(`${p.sep}macos${p.sep}`)&&(a-=5e3);let i="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return i.preferred.length>0&&(i.preferred.some(e=>n.includes(e))?a+=2e3:a-=500),i.disallowed.some(e=>n.includes(e))&&(a-=2500),a}function tX(e,t){try{let r=s.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(s.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}}async function tK(e,t,r){let a,n=p.dirname(e),i=r.replace(/[^a-zA-Z0-9._-]/g,"_"),o=p.join(n,`AgentDeviceRunner.env.${i}.json`),l=p.join(n,`AgentDeviceRunner.env.${i}.xctestrun`),d=await T("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new H("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new H("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},c=a.TestConfigurations;if(Array.isArray(c))for(let e of c){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(a))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),a[e]=t);s.writeFileSync(o,JSON.stringify(a,null,2));let f=await T("plutil",["-convert","xml1","-o",l,o],{allowFailure:!0});if(0!==f.exitCode)throw new H("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:f.stderr});return{xctestrunPath:l,jsonPath:o}}async function tY(e,t,r,a){let n=function(e=process.env){let t=tT(e),r=t$(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),i=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",n=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",i=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),n&&o.push(`CODE_SIGN_IDENTITY=${n}`),i&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${i}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[],s=await tG(e);try{var l;let s;await Q("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",t0(e),"1","-destination",(l=e,s=tZ(l),"macOS"===s?`platform=macOS,arch=${tQ()}`:"simulator"===l.kind?`platform=${s} Simulator,id=${l.id}`:`generic/platform=${s}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...n,...o,...i],{detached:!0,onSpawn:e=>{tP.add(e),e.on("close",()=>{tP.delete(e)})},onStdoutChunk:e=>{tv(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{tv(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(i){let e,t,r=i instanceof H?i:new H("COMMAND_FAILED",String(i)),n=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
|
|
6
|
+
${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new H("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:r.message,details:r.details,logPath:a.logPath,hint:n})}finally{await s?.release()}}function tZ(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new H("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"macos"===e.platform?"macOS":"macos"===(t=e.target)||"desktop"===t?"macOS":"tv"===t?"tvOS":"iOS"}function tQ(){return"arm64"===process.arch?"arm64":"x86_64"}function t0(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function t1(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return eC(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new H("COMMAND_FAILED","Refusing to clean AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH automatically",{derivedPath:e,hint:"Unset AGENT_DEVICE_IOS_CLEAN_DERIVED, or set AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN=1 if you trust this path."})}function t2(e,t,r){eu({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}function t3(e){let t=function(e){let t=function(e){try{let t=eo("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())return null;return JSON.parse(t.stdout)}catch{return null}}(e);if(t){var r,a=t;let e=new Set,n=t=>{if(t&&"object"==typeof t)for(let r of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),r=new Set;for(let[a,n]of Object.entries(e))if(t.has(a)){if("string"==typeof n){r.add(n);continue}if(Array.isArray(n))for(let e of n)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};n(a);let i=a.TestConfigurations;if(Array.isArray(i))for(let e of i){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)n(e)}for(let e of Object.values(a))e&&"object"==typeof e&&"TestBundlePath"in e&&n(e);return Array.from(e)}if("darwin"===process.platform)return null;try{return r=s.readFileSync(e,"utf8"),Array.from(new Set([...["ProductPaths","DependentProductPaths"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<array>([\\s\\S]*?)</array>`,"g"),n=/<string>([\s\S]*?)<\/string>/g,i=new Set;for(;null!==(r=a.exec(e));){let e,t=r[1]??"";for(;null!==(e=n.exec(t));){let t=e[1]?.trim();t&&i.add(t)}}return Array.from(i)})(r,e)),...["TestHostPath","TestBundlePath","UITargetAppPath"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<string>([\\s\\S]*?)</string>`,"g"),n=new Set;for(;null!==(r=a.exec(e));){let e=r[1]?.trim();e&&n.add(e)}return Array.from(n)})(r,e))]))}catch{return null}}(e);if(!t||0===t.length)return null;let r=p.dirname(e),a=new Set,n=new Set,i=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),i=p.join(r,t);if(!s.existsSync(i))return null;a.add(i);let o=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);o&&n.add(p.join(r,o));continue}e.startsWith("__TESTHOST__/")&&i.push(e.slice(13))}for(let e of i){let t=Array.from(n).find(t=>s.existsSync(p.join(t,e)));if(!t)return null;a.add(p.join(t,e))}return Array.from(a)}let t4=new Map,t5=new Map;async function t8(e,t){return await tA(t5,e.id,async()=>{var r;let a,n,i=t4.get(e.id);if(i){if(function(e){return!!e&&ew(e)}(i.child.pid))return i;await t7(e.id,i)}await ("simulator"!==(r=e).kind?Promise.resolve():rn(r)),await t6(e);let o=await tq(e,t),s=await ty(),{xctestrunPath:l,jsonPath:d}=await tK(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`),u=await tG(e);try{let t;({child:a,wait:n}=C("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",t0(e),"1","-destination-timeout",String(tp),"-xctestrun",l,"-destination",(t=tZ(e),"macOS"===t?`platform=macOS,arch=${tQ()}`:"simulator"===e.kind?`platform=${t} Simulator,id=${e.id}`:`platform=${t},id=${e.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(s)},detached:!0}))}catch(e){throw await u?.release(),e}a.stdout?.on("data",e=>{tv(e,t.logPath,t.traceLogPath,t.verbose)}),a.stderr?.on("data",e=>{tv(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${s}:${Date.now()}`,device:e,deviceId:e.id,port:s,xctestrunPath:l,jsonPath:d,testPromise:n,child:a,ready:!1,simulatorSetRedirect:u??void 0};return t4.set(e.id,c),c})}async function t6(e){if("simulator"===e.kind)for(let t of tF){let r=await T("xcrun",te(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==r.exitCode){let e=`${r.stdout}
|
|
7
|
+
${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found nothing")&&!e.includes("no such file")&&!e.includes("invalid device")&&!e.includes("could not find"))continue}}}async function t9(e){await tA(t5,e.deviceId,async()=>{await t7(e.deviceId,e)})}async function t7(e,t){let r=t??t4.get(e);if(r){try{await tf(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await ra(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await ra(r.child.pid,"SIGKILL"),tI(r.xctestrunPath),tI(r.jsonPath),await r.simulatorSetRedirect?.release(),t4.get(e)===r&&t4.delete(e)}}async function re(e){await tA(t5,e,async()=>{await t7(e)})}async function rt(){let e=Array.from(t4.values()),t=Array.from(tP);await Promise.allSettled(e.map(async e=>{await ra(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await ra(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await ra(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await ra(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await ra(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await ra(e.pid,"SIGKILL"),tP.delete(e)})),await Promise.allSettled(e.map(async e=>{await e.simulatorSetRedirect?.release()}))}async function rr(){await rt();let e=Array.from(t4.keys());await Promise.allSettled(e.map(async e=>{await re(e)}));let t=Array.from(tP);await Promise.allSettled(t.map(async e=>{try{await ra(e.pid,"SIGTERM"),await ra(e.pid,"SIGKILL")}finally{tP.delete(e)}}))}async function ra(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 T("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function rn(e){await T("xcrun",te(e,["bootstatus",e.id,"-b"]),{timeoutMs:ti})}async function ri(e,t,r,a,n,i){let o=await tf(e,t.port,r,a,n,t,i);return await ro(o,t,a)}async function ro(e,t,r){let a=await e.text(),n={};try{n=JSON.parse(a)}catch{throw new H("COMMAND_FAILED","Invalid runner response",{text:a})}if(!n.ok)throw new H("string"==typeof n.error?.code&&n.error.code.trim().length>0?n.error.code:"COMMAND_FAILED",n.error?.message??"Runner error",{runner:n,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,n.data??{}}async function rs(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new H("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new H("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(tn(r.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?eU(()=>(tn(r.requestId),rl(e,t,r)),{shouldRetry:e=>{tn(r.requestId);if(!(e instanceof H)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.message??""}`.toLowerCase();return!(t.includes("xcodebuild exited early")||t.includes("device is busy")&&t.includes("connecting"))&&!!(t.includes("runner did not accept connection")||t.includes("fetch failed")||t.includes("econnrefused")||t.includes("socket hang up"))}}):rl(e,t,r)}async function rl(e,t,r={}){let a;tn(r.requestId);let n=eK(r.requestId);try{let i=(a=await t8(e,r)).ready?to:ti;return await ri(e,a,t,r.logPath,i,n)}catch(o){let i=o instanceof H?o:new H("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===i.code&&"string"==typeof i.message&&i.message.includes("Runner did not accept connection")&&tt(i)&&a?.ready){tn(r.requestId),a?await t9(a):await re(e.id),a=await t8(e,r);let i=await tf(a.device,a.port,t,r.logPath,ti,void 0,n);return await ro(i,a,r.logPath)}throw o}}function rd(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 ru(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let rc=/^-?\d+(\.\d+)?$/,rp=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),rf=new Map([["--count","count"],["--pause-ms","pauseMs"]]),rm=new Map([["--delay-ms","delayMs"]]);function rh(e){return"click"===e||"press"===e}function rw(e){return"type"===e||"fill"===e}function rg(e){let t=e.trim();return t.startsWith("@")||rc.test(t)?t:JSON.stringify(t)}function ry(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function rv(e,t){let r=t.flags??{};if(rh(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}if("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);return}rw(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function rI(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",ry(t.metroHost)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",ry(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",ry(t.launchUrl)))}function rb(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(ry(r)),a))e.push(rg(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function rA(e,t){let r=[],a={},n=rh(e)?rp:"swipe"===e?rf:rw(e)?rm:void 0;for(let i=0;i<t.length;i+=1){let o=t[i];if(rh(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(rh(e)&&"--button"===o&&i+1<t.length){let e=t[i+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),i+=1;continue}let s=n?.get(o);if(s&&i+1<t.length){let e=r_(t[i+1]);if(null!==e){a[s]=e,i+=1;continue}}if("swipe"===e&&"--pattern"===o&&i+1<t.length){let e=t[i+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),i+=1;continue}r.push(o)}return{positionals:r,flags:a}}function rS(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let n=e[a];if("--platform"===n&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===n&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===n&&a+1<e.length){let t=r_(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===n&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===n&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(n)}return{positionals:t,flags:r}}function r_(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function rN(e,t){for(let r of t.positionals??[])e.push(rg(r));t.flags?.relaunch&&e.push("--relaunch"),rI(e,t.runtime)}class rx{sessions=new Map;runtimeHints=new Map;sessionsDir;constructor(e){this.sessionsDir=e}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=rx.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:n,out:i,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:y,noRecord:v,fps:I,hideTouches:b,count:A,intervalMs:S,delayMs:_,holdMs:N,jitterPx:x,doubleTap:D,clickButton:k,pauseMs:M,pattern:E}=e;return{platform:t,device:r,udid:a,serial:n,out:i,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:y,noRecord:v,fps:I,hideTouches:b,count:A,intervalMs:S,delayMs:_,holdMs:N,jitterPx:x,doubleTap:D,clickButton:k,pauseMs:M,pattern:E}}(t.flags),result:t.result}),eu({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=p.dirname(t);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.name.replace(/"/g,'\\"'),n=e.device.kind?` kind=${e.device.kind}`:"";for(let i of(r.push(`context platform=${e.device.platform} device="${a}"${n} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(rh(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(rg(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(rg(a)),rv(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(rg(r)),rv(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(rg(r));let a=e.result?.refLabel,n=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(rg(a)),n&&t.push(rg(n)),rv(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(rg(r)),t.push(rg(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(rg(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",rg(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(rg(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}if("open"===e.command)return rN(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(ry(r)),rI(t,e.flags),t.join(" ")}if("record"===e.command)return rb(t,e),t.join(" ");for(let r of e.positionals??[])t.push(rg(r));return rv(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
8
|
+
`}(e,this.buildOptimizedActions(e));s.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=rx.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return p.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return p.join(this.sessionsDir,rx.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return p.join(this.sessionsDir,rx.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return ea(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return rx.expandHome(e.saveScriptPath);s.existsSync(this.sessionsDir)||s.mkdirSync(this.sessionsDir,{recursive:!0});let t=rx.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return p.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let a=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(a.length>0&&(rh(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(rh(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=rd(r);if(a.length>0){t.push({...r,positionals:[e,a]});continue}}if("get"===r.command){let a=r.positionals?.[0];if("text"===a||"attrs"===a){t.push({...r,positionals:[a,e]});continue}}}if(rh(r.command)||"fill"===r.command||"get"===r.command){let a=r.result?.refLabel;"string"==typeof a&&a.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:a.trim()},result:{scope:a.trim()}})}t.push(r)}return t}}function rD(e,t){if(!e)return;let r=p.dirname(e);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:eg(t)??void 0,command:D(t)??void 0};s.writeFileSync(e,`${JSON.stringify(a)}
|
|
9
|
+
`)}function rk(e){if(e&&s.existsSync(e))try{s.unlinkSync(e)}catch{}}async function rM(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function rE(e){await new Promise(t=>setTimeout(t,e))}function rO(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],a="",n=a=>{(!(r.length>0)||r.some(e=>a.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(a,t.redactionPatterns))};return{onChunk:e=>{let t=`${a}${e}`.split("\n");for(let e of(a=t.pop()??"",t))n(`${e}
|
|
10
|
+
`)},flush:()=>{a&&(n(a),a="")}}}function rL(e,t,r){let a=e.stdout,n=e.stderr;return a&&n?(a.setEncoding("utf8"),n.setEncoding("utf8"),a.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(a=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),a({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}function rC(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new H("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function rP(e,t){let r=(await T("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function rR(e,t){var r,a;let n;rC(t);let i=await rP(e,t),o=await T("adb",["-s",e,"logcat","-d","-v","time","-t","4000"],{allowFailure:!0,timeoutMs:3e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=function(e,t,r){let a=new Set;for(let n of(r&&a.add(r),e.split("\n")))if(n.includes(t))for(let e of function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=[RegExp(`\\bStart proc\\s+(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`\\b(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`${r}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,"i"),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${r}`,"i")],n=[];for(let t of a){let r=t.exec(e),a=r?.[1];a&&/^\d+$/.test(a)&&n.push(a)}return n}(n,t))a.add(e);return[...a]}(o.stdout,t,i);if(0===s.length)return null;let l=(r=o.stdout,a=t,n=new Set(s),r.split("\n").filter(e=>{var t;let r;if(!e.trim())return!1;if(e.includes(a))return!0;let i=(t=e,r=/\(\s*(\d+)\)\s*:/.exec(t),r?.[1]??null);return!!i&&n.has(i)}).join("\n"));return 0===l.trim().length?null:{pid:i,text:l,recoveredPids:s}}async function rT(e,t,r,a,n){let i,o,s="recovering",l=!1,d=(async()=>{try{for(;!l;){let d=await rP(e,t);if(!d){s="recovering",await rE(1e3);continue}let u=y("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});i=u;let c=rO(r,{redactionPatterns:a});if(o=rL(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&(rD(n,u.pid),s="active"),await o,rk(n),i=void 0,o=void 0,l)break;s="recovering",await rE(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),rk(n)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,i&&!i.killed&&i.kill("SIGINT"),o&&await rM(o),i&&!i.killed&&i.kill("SIGKILL"),await rM(d),rk(n)}}}function r$(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}"`}async function rF(e){let{deviceId:t,appBundleId:r,startedAt:a,simulatorSetPath:n}=e,i=e7(["spawn",t,"log","show","--style","compact","--info","--predicate",r$(r)],{simulatorSetPath:n});"number"==typeof a&&Number.isFinite(a)&&a>0?i.push("--start",`@${Math.floor(a/1e3)}`):i.push("--last","5m");let o=await T("xcrun",i,{allowFailure:!0,timeoutMs:4e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=o.stdout.split("\n").map(e=>e.trimEnd()).filter(e=>{let t=e.trim();return t.length>0&&!t.startsWith("Timestamp Ty Process[PID:TID]")});return 0===s.length?null:{text:`${s.join("\n")}
|
|
11
|
+
`,recoveredLineCount:s.length}}async function rU(e,t,r,a,n,i){let o="active",s=y("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return e7(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",r$(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:n}),{stdio:["ignore","pipe","pipe"]}),l=rO(r,{redactionPatterns:a});"number"==typeof s.pid&&rD(i,s.pid);let d=rL(s,r,{endStreamOnClose:!0,writer:l}).then(e=>(0!==e.exitCode&&(o="failed"),rk(i),e));return{backend:"ios-simulator",getState:()=>o,startedAt:Date.now(),wait:d,stop:async()=>{s.killed||s.kill("SIGINT"),await rM(d),s.killed||s.kill("SIGKILL"),await rM(d),rk(i)}}}async function rG(e,t,r,a){let n="active",i=y("log",["stream","--style","compact","--predicate",r$(e)],{stdio:["ignore","pipe","pipe"]}),o=rO(t,{redactionPatterns:r});"number"==typeof i.pid&&rD(a,i.pid);let s=rL(i,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),rk(a),e));return{backend:"macos",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{i.killed||i.kill("SIGINT"),await rM(s),i.killed||i.kill("SIGKILL"),await rM(s),rk(a)}}}async function rV(e,t,r,a){let n="active",i=y("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=rO(t,{redactionPatterns:r});"number"==typeof i.pid&&rD(a,i.pid);let s=rL(i,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(n="failed"),rk(a),e));return{backend:"ios-device",getState:()=>n,startedAt:Date.now(),wait:s,stop:async()=>{i.killed||i.kill("SIGINT"),await rM(s),i.killed||i.kill("SIGKILL"),await rM(s),rk(a)}}}let rB=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),rj=/https?:\/\/[^\s"'<>\])]+/i,rq=[/\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 rH(e,t,r=e.limits.maxEntries){let a=[...e.entries],n=new Set(a.map(e=>rz(e)));for(let e of t.entries){let t=rz(e);if(!n.has(t)&&(n.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function rW(e,t){let r=r3(t?.maxEntries,25,1,200),a=t?.backend,n=t?.include??"summary",i=r3(t?.maxPayloadChars,2048,64,16384),o=r3(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),d=s.slice(l),u=[];for(let e=d.length-1;e>=0&&u.length<r;e-=1){let t=d[e];if(!t?.trim())continue;let r=function(e,t,r,a,n,i){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=rQ(s,["method","httpMethod"]),d=rQ(s,["url","requestUrl"]),u=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}(s,["status","statusCode","responseCode"]),c=rB.exec(o),p=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),f=(l??p?.[1]??c?.[1])?.toUpperCase(),m=rj.exec(o),h=d??m?.[0];if(!h)return null;let w=u??rX(o)??void 0;if(!(l||p?.[1]||c?.[1]||void 0!==w||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let g={method:f,url:h,status:w,timestamp:rK(o),packetId:rY(o)??void 0,durationMs:rZ(o)??void 0,raw:r2(o,i),line:r};if("android"===a&&function(e,t,r){let a=rJ(t,r,5),n=e.packetId??a.map(e=>rY(e)).find(e=>"string"==typeof e&&e.length>0);n&&(e.packetId=n);let i=n?rJ(t,r,12).filter(e=>rY(e)===n):a;e.timestamp||(e.timestamp=i.map(e=>rK(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=i.map(e=>rX(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=i.map(e=>rZ(e)).find(e=>"number"==typeof e))}(g,e,t),"headers"===n||"all"===n){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return r1(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(g.headers=r2(e,i))}if("body"===n||"all"===n){let e=r0(o,s,["requestBody","body","payload","request"]),t=r0(o,s,["responseBody","response"]);e&&(g.requestBody=r2(e,i)),t&&(g.responseBody=r2(t,i))}return g}(d,e,l+e+1,a,n,i);r&&u.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:d.length,matchedLines:u.length,entries:u,include:n,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:o}}}function rz(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function rJ(e,t,r){let a=[],n=Math.max(0,t-r),i=Math.min(e.length-1,t+r);for(let t=n;t<=i;t+=1){let r=e[t]?.trim();r&&a.push(r)}return a}function rX(e){for(let t of rq){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function rK(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function rY(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function rZ(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function rQ(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 r0(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return r1(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function r1(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function r2(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function r3(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function r4(e,t){let r=process.env[e];if(!r)return t;let a=Number.parseInt(r,10);return Number.isInteger(a)&&a>0?a:t}function r5(e){let t=p.dirname(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),function(e,t){if(s.existsSync(e)&&!(s.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,a=`${e}.${r}`;s.existsSync(t)&&(s.existsSync(a)&&s.unlinkSync(a),s.renameSync(t,a))}}(e,{maxBytes:r4("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:r4("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function r8(e){var t,r;let a,n,i,o,{device:l,appBundleId:d,appLogState:u,appLogStartedAt:c,appLogPath:p,maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w}=e,g="macos"===l.platform?"macos":"ios"===l.platform?"device"===l.kind?"ios-device":"ios-simulator":"android",y=(t={backend:g,maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w},a=r3(t?.maxEntries,25,1,200),n=t?.include??"summary",i=r3(t?.maxPayloadChars,2048,64,16384),o=r3(t?.maxScanLines,4e3,100,2e4),s.existsSync(p)?rW(s.readFileSync(p,"utf8"),{...t,path:p}):{path:p,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:n,limits:{maxEntries:a,maxPayloadChars:i,maxScanLines:o}}),v=[];if("android"===l.platform&&void 0!==u&&"active"!==u&&d){let e=await rR(l.id,d);if(e){let t=rW(e.text,{path:`${p} (adb logcat recovery)`,backend:"android",maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w});t.entries.length>0&&(y=rH(t,y,f),v.push(`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${e.recoveredPids.join(", ")}.`))}}if("ios"===l.platform&&"simulator"===l.kind&&d&&0===y.entries.length){let e=await r9({deviceId:l.id,appBundleId:d,startedAt:c,simulatorSetPath:l.simulatorSetPath,appLogPath:p,maxEntries:f,include:m,maxPayloadChars:h,maxScanLines:w});e&&(e.dump.entries.length>0?(y=rH(e.dump,y,f),v.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&v.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===u?v.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==u&&0===v.length&&("ios"===l.platform&&"simulator"===l.kind?v.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):v.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===y.entries.length&&v.push("ios"===(r=l).platform&&"simulator"===r.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===r.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:g,dump:y,notes:v}}async function r6(e,t,r,a){r5(r);let n=s.createWriteStream(r,{flags:"a"}),i=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 rV(e.id,n,i,a):await rU(e.id,t,n,i,e.simulatorSetPath,a);if("android"===e.platform)return rC(t),await rT(e.id,t,n,i,a);if("macos"===e.platform)return await rG(t,n,i,a);throw n.end(),new H("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function r9(e){let t=await rF({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:rW(t.text,{path:`${e.appLogPath} (simctl log show recovery)`,backend:"ios-simulator",maxEntries:e.maxEntries,include:e.include,maxPayloadChars:e.maxPayloadChars,maxScanLines:e.maxScanLines}),recoveredLineCount:t.recoveredLineCount}:null}async function r7(e){await e.stop(),await rM(e.wait)}async function ae(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await T("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await T("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 T("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 T("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await T("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function at(e){let t=p.dirname(e),r=p.basename(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),s.existsSync(e)?s.truncateSync(e,0):s.writeFileSync(e,"","utf8");let a=0;for(let e of s.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let n=e.slice(r.length+1);if(/^\d+$/.test(n))try{s.unlinkSync(p.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let ar=new Map;function aa(e){let t=ar.get(e);if(t&&(clearTimeout(t.timer),ar.delete(e),t.deleteAfterDownload))try{s.rmSync(t.artifactPath,{force:!0})}catch{}}let an=new Map;function ai(e,t){let r=an.get(e);if(!r)throw new H("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new H("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function ao(e){let t=an.get(e);t&&(clearTimeout(t.timer),an.delete(e),s.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function as(e){let t=await al(e);await T("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=p.join(e.tempDir,t);if(!s.existsSync(r))throw new H("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function al(e){let t=await T("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new H("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new H("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(ad),n=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new H("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new H("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===a.length)return a[0];throw new H("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===n||e.startsWith(`${n}/`)))throw new H("INVALID_ARGS",`Uploaded archive must contain a top-level "${n}" bundle`);for(let e of a){var i=e,o=n;if(i!==o&&!i.startsWith(`${o}/`))throw new H("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${i}`)}for(let t of(await T("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new H("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return n}function ad(e){if(e.includes("\0"))throw new H("INVALID_ARGS",`Invalid archive entry: ${e}`);if(p.posix.isAbsolute(e))throw new H("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=p.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new H("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let au=eQ(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function ac(e,t){return new Promise((r,a)=>{let n,i=s.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,u=e=>{if(!l){if(l=!0,n&&clearTimeout(n),e){i.destroy(),s.rmSync(t,{force:!0}),a(e);return}r()}},c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let e=new H("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:au});o(e),i.destroy(e),u(e)},au)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new H("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),i.destroy(e),u(e)}}),e.on("error",u),e.on("aborted",()=>{u(new H("COMMAND_FAILED","Artifact transfer was interrupted"))}),i.on("error",u),i.on("finish",()=>u()),c(),e.pipe(i)})}async function ap(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new H("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new H("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new H("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let n=function(e){let t=e.trim(),r=p.basename(t);if(!r||"."===r||".."===r)throw new H("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),i=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),s.mkdtempSync(p.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=p.join(i,n);return await ac(e,t),{artifactPath:t,tempDir:i}}let t=p.join(i,"artifact.tar");await ac(e,t);let a=await as({archivePath:t,tempDir:i,platform:"ios",expectedRootName:n});return s.rmSync(t,{force:!0}),{artifactPath:a,tempDir:i}}catch(e){throw s.rmSync(i,{recursive:!0,force:!0}),e}}let af=new Set(["agent_device.command","agent-device.command"]),am=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),ah=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),aw={"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"},ag=new Set([...af,...am,...ah,...Object.keys(aw)]);function ay(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function av(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function aI(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function ab(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=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??a??""}function aA(e,t){let r=e[t];return"string"==typeof r?r:void 0}function aS(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function a_(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=et(new H("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:ay(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=et(new H(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:ay(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=E(r.tenantId);if(!e){let e=et(new H("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:ay(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function aN(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",a=p.isAbsolute(t)?t:p.resolve(t);try{e=await import(g(a).href)}catch(e){throw new H("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let n=e[r];if("function"!=typeof n)throw new H("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return n}async function ax(e){let t=await aN(),{handleRequest:r,token:a}=e;return v.createServer((e,n)=>{if("GET"===e.method&&"/health"===e.url){n.statusCode=200,n.setHeader("content-type","application/json"),n.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void aD(e,n,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void ak(e,n,t,a);if("POST"!==e.method||"/rpc"!==e.url){n.statusCode=404,n.end("Not found");return}let i="";e.setEncoding("utf8"),e.on("data",t=>{(i+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{n.headersSent||av(n,ay(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(i)}catch{av(n,ay(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void av(n,ay(a.id??null,-32600,"Invalid Request"),400);if(!ag.has(a.method))return void av(n,ay(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void av(n,ay(a.id??null,-32602,"Invalid params"),400);try{var s;let i=a.params,l=function(e,t,r){if(af.has(e))return{token:ab(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(am.has(e)){let e,a=aA(t,"platform");if("ios"!==a&&"android"!==a)throw new H("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:ab(t,r),session:aA(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:aA(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new H("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new H("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,a={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new H("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new H("INVALID_ARGS","Invalid params: source.headers values must be strings");a[e]=t}}return Object.keys(a).length>0?{kind:"url",url:e,headers:a}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new H("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new H("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:aS(t,"retentionMs")}}}if(ah.has(e)){let e=aA(t,"materializationId")?.trim();if(!e)throw new H("INVALID_ARGS","Invalid params: materializationId is required");return{token:ab(t,r),session:aA(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:aA(t,"requestId"),materializationId:e}}}let a=aw[e];if(a)return{token:ab(t,r),session:aA(t,"session")??"default",command:a,positionals:[],meta:{tenantId:aA(t,"tenantId")??aA(t,"tenant"),runId:aA(t,"runId"),leaseId:aA(t,"leaseId"),leaseTtlMs:aS(t,"ttlMs"),leaseBackend:aA(t,"backend")}};throw new H("INVALID_ARGS",`Method not found: ${e}`)}(a.method,i,e.headers);if(s=a.method,af.has(s)&&("string"!=typeof l.command||0===l.command.length))return void av(n,ay(a.id??null,-32602,"Invalid params: command is required"),400);o=eH(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},eW(o);let d=()=>{n.writableFinished||ez(o)};e.on("aborted",d),n.on("close",d);let u=await a_(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void av(n,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void av(n,{jsonrpc:"2.0",id:a.id??null,result:c});av(n,ay(a.id??null,-32e3,c.error.message,c.error),aI(c.error.code))}catch(t){let e=et(t);av(n,ay(a.id??null,-32e3,e.message,e),aI(e.code))}finally{eJ(o)}})})}async function aD(e,t,r,a){try{var n;let o,s,l=ab({},e.headers),d=aM(l,a);if(d){t.statusCode=aI(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await a_(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await ap(e),p=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},o=i.randomUUID(),(s=setTimeout(()=>{ao(o)},3e5)).unref(),an.set(o,{artifactPath:n.artifactPath,tempDir:n.tempDir,tenantId:n.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:p}))}catch(r){let e=et(r);t.statusCode=aI(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function ak(e,t,r,a){let n=e.url?.slice("/upload/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let i=ab({},e.headers),o=aM(i,a);if(o){t.statusCode=aI(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let l=await a_(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:i,session:"default",command:"download_artifact",positionals:[n]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let d=function(e,t){let r=ar.get(e);if(!r)throw new H("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new H("UNAUTHORIZED","Artifact belongs to a different tenant");if(!s.existsSync(r.artifactPath))throw aa(e),new H("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),u=s.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=et(e);t.statusCode=aI(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&aa(n)}),u.pipe(t)}catch(r){let e=et(r);t.statusCode=aI(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function aM(e,t){return t&&e!==t?et(new H("UNAUTHORIZED","Invalid token")):null}function aE(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function aO(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function aL(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new H("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class aC{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=aL(e.backend),r=E(e.tenantId);if(!r)throw new H("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=aE(e.runId);if(!a)throw new H("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(r,a,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,n);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),d={leaseId:i.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+n};return this.leases.set(d.leaseId,d),this.runBindings.set(o,d.leaseId),{...d}}heartbeatLease(e){let t=aO(e.leaseId);if(!t)throw new H("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new H("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=aO(e.leaseId);if(!t)throw new H("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=aL(e.backend),r=E(e.tenantId);if(!r)throw new H("INVALID_ARGS","tenant isolation requires tenant id.");let a=aE(e.runId);if(!a)throw new H("INVALID_ARGS","tenant isolation requires run id.");let n=aO(e.leaseId);if(!n)throw new H("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let i=this.leases.get(n);if(!i)throw new H("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(i.backend!==t||i.tenantId!==r||i.runId!==a)throw new H("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 H("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 H("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),a={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(a.leaseId,a),this.runBindings.set(this.bindingKey(a.tenantId,a.runId,a.backend),a.leaseId),{...a}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let a=E(t),n=aE(r);if(t&&!a)throw new H("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!n)throw new H("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||n&&e.runId!==n)throw new H("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let aP=["emulator","platform-tools",p.join("cmdline-tools","latest","bin"),p.join("cmdline-tools","tools","bin")];function aR(e){let t=new Set,r=[];for(let a of e){let e=a.trim();!e||t.has(e)||(t.add(e),r.push(e))}return r}function aT(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||u.homedir();return aR([t??"",r??"",a?p.join(a,"Android","Sdk"):""])}async function a$(e){try{return await d.access(e,d.constants.X_OK),!0}catch{return!1}}async function aF(e=process.env){let t,r=[];for(let a of aT(e)){let e=[];for(let t of aP){let r=p.join(a,t);await a$(r)&&e.push(r)}0!==e.length&&(t||(t=a),r.push(...e))}if(t&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||t,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||t),0===r.length)return;let a=(e.PATH??"").split(p.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=aR([...r,...a]).join(p.delimiter)}function aU(e,t){return["-s",e.id,...t]}async function aG(){if(await aF(),!await X("adb"))throw new H("TOOL_MISSING","adb not found in PATH")}function aV(e,t){let r=`${e}
|
|
12
|
+
${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function aB(e){await new Promise(t=>setTimeout(t,e))}function aj(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let a=r[1]?.toLowerCase(),n=r[2]??"";return"http"!==a&&"https"!==a&&"ws"!==a&&"wss"!==a&&"ftp"!==a&&"ftps"!==a||n.startsWith("//")}function aq(e,t){let r,a=e?.trim();return a?a:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}let aH=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function aW(e){return`${e.stdout}
|
|
13
|
+
${e.stderr}`}function az(e,t){return["-s",e,...t]}function aJ(e){return e.startsWith("emulator-")}function aX(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function aK(e,t=eT){return T("adb",az(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function aY(e,t){let r=t.replace(/_/g," ").trim();if(!aJ(e))return r||e;let a=await aQ(e);return a?a.replace(/_/g," "):r||e}async function aZ(e,t,r){try{return await r("adb",az(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=B(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function aQ(e,t=T){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await aZ(e,["shell","getprop",r],t);if(!a)continue;let n=a.stdout.trim();if(0===a.exitCode&&n.length>0)return n}let r=await aZ(e,["emu","avd","name"],t);if(!r)return;let a=function(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}(r.stdout);if(0===r.exitCode&&a)return a}async function a0(e,t){let r=aW(await T("adb",az(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eT})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function a1(e){return(await Promise.all(aH.map(async t=>await a0(e,t)))).some(e=>!0===e)}async function a2(e){var t;let r;return"tv"===((r=aW(await T("adb",az(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eT})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await a1(e)?"tv":(t=aW(await T("adb",az(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eT})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function a3(e={}){if(await aF(),!await X("adb"))throw new H("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??e9(void 0),r=(await a4()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,n]=await Promise.all([aY(e,t),a9(e),a2(e)]);return{platform:"android",id:e,name:r,kind:aJ(e)?"emulator":"device",target:n,booted:a}}))}async function a4(){return(await T("adb",["devices","-l"],{timeoutMs:eT})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).filter(e=>"device"===e[1]).map(e=>({serial:e[0],rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}))}async function a5(){let e=await T("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eT});if(0!==e.exitCode)throw new H("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function a8(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await a6(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 H("COMMAND_FAILED","Android emulator did not appear in time",{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:"Check emulator logs and verify the AVD can start from command line."})}async function a6(e,t){let r=aX(e);for(let e of(await a4()).filter(e=>(!t||e.serial===t)&&aJ(e.serial)))if(aX(e.rawModel)===r||aX(await aY(e.serial,e.rawModel))===r)return e.serial}async function a9(e){try{let t=await aK(e);return"1"===t.stdout.trim()}catch{return!1}}async function a7(e){var t,r;let a;await aF();let n=e.avdName.trim();if(!n)throw new H("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let i=e.timeoutMs??12e4;if(!await X("adb"))throw new H("TOOL_MISSING","adb not found in PATH");if(!await X("emulator"))throw new H("TOOL_MISSING","emulator not found in PATH");let o=await a5(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let a=aX(t);return e.find(e=>aX(e)===a)}(o,n);if(!s)throw new H("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 l=Date.now(),d=(t=await a3(),r=e.serial,a=aX(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&aX(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),L("emulator",t)}let u=d??await a8({avdName:s,serial:e.serial,timeoutMs:i}),c=Math.max(1e3,i-(Date.now()-l));await ne(u.id,c);let p=(await a3()).find(e=>e.id===u.id);return p?{...p,name:s,booted:!0}:{...u,name:s,booted:!0}}async function ne(e,t=6e4){let r,a=e$.fromTimeoutMs(t),n=Math.max(1,Math.ceil(t/1e3)),i=!1;try{await eF(async({deadline:n})=>{if(n?.isExpired())throw i=!0,new H("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),message:"timeout"});let o=Math.max(1e3,n?.remainingMs()??t),s=await aK(e,Math.min(o,eT));if(r=s,"1"!==s.stdout.trim())throw new H("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:n,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=e0({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>e0({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let n=B(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=e0({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:a.elapsedMs(),reason:d,hint:e1(d),stdout:o,stderr:s,exitCode:l};if(i||"ANDROID_BOOT_TIMEOUT"===d)throw new H("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===n.code)throw new H("TOOL_MISSING",n.message,{...u,...n.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new H("COMMAND_FAILED",n.message,{...u,...n.details??{}});throw new H(n.code,n.message,{...u,...n.details??{}},n.cause)}}let nt=/\.(?:apk|aab)$/i,nr=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function na(e){var t,r;let a=e.trim();return 0===a.length?"other":nt.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!nr.test(t))?"binary":"package":(r=a,nr.test(r))?"package":"other"}function nn(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let ni=[".zip",".tar",".tar.gz",".tgz"],no=eQ(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),ns=["1","true","yes","on"];async function nl(e){let t=[];try{let r=await nd(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await nm(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:a.archivePath,installablePath:a.installablePath,cleanup:async()=>{await ny(t)}}}catch(e){throw await ny(t),e}}async function nd(e,t){if("path"===e.kind)return{localPath:j(e.path),cleanup:async()=>{}};let r=await d.mkdtemp(p.join(u.tmpdir(),"agent-device-source-"));try{return{localPath:await nu(r,e.url,e.headers,t),cleanup:async()=>{await d.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(r,{recursive:!0,force:!0}),e}}async function nu(e,t,r,a){let n;try{n=new URL(t)}catch{throw new H("INVALID_ARGS",`Invalid source URL: ${t}`)}await nc(n);let i=a?.signal;if(i?.aborted)throw new H("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,s=()=>{o.abort(i?.reason)};i?.addEventListener("abort",s,{once:!0});let l=a?.downloadTimeoutMs??no,u=setTimeout(()=>{o.abort(Error("download timeout"))},l);try{let t=await fetch(n,{headers:r,redirect:"follow",signal:o.signal});if(!t.ok)throw new H("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:n.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),n=a?.[1]?.trim();if(n)return p.basename(n);let i=p.basename(t.pathname);return i||"downloaded-artifact.bin"}(t,n),i=p.join(e,a),s=t.body;if(!s)throw new H("COMMAND_FAILED","Download response body was empty",{url:n.toString()});let l=await d.open(i,"w");try{for await(let e of s)await l.write(e)}finally{await l.close()}return i}catch(e){if(i?.aborted)throw new H("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new H("COMMAND_FAILED",`App source download timed out after ${l}ms`,{timeoutMs:l,url:n.toString()},e);throw e}finally{i?.removeEventListener("abort",s),clearTimeout(u)}}async function nc(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new H("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!ns.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||nf(t))throw new H("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await I.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>nf(e.address)))throw new H("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function np(e){var t,r,a,n;let i=e instanceof URL?e:new URL(e),o=i.hostname.toLowerCase();if(!o)return!1;let s=i.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,n=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(n))}function nf(e){let t,r=f.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,a]=t;return 10===r||127===r||169===r&&254===a||172===r&&!!(a>=16)&&!!(a<=31)||192===r&&168===a}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function nm(e,t){let r=await d.stat(e).catch(()=>null);if(!r)throw new H("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&ng(e)){if(!t.allowArchiveExtraction)throw new H("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await nw(e);return t.registerCleanup(r.cleanup),await nm(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await nh(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new H("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await nh(e,(e,t)=>t.isFile()&&ng(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new H("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await nw(a[0]);return t.registerCleanup(e.cleanup),await nm(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new H("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new H("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function nh(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let n=await d.readdir(e.path,{withFileTypes:!0});for(let i of(n.sort((e,t)=>e.name.localeCompare(t.name)),n)){let n=p.join(e.path,i.name);if(t(n,i)){r.push(n);continue}i.isDirectory()&&e.depth<5&&a.push({path:n,depth:e.depth+1})}}return r}async function nw(e){let t=await d.mkdtemp(p.join(u.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await T("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await T("tar",["-xzf",e,"-C",t]):await T("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await d.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(t,{recursive:!0,force:!0}),e}}function ng(e){let t=e.toLowerCase();return ni.some(e=>t.endsWith(e))}async function ny(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let nv=new A("utf-16le");async function nI(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await nb(e,r);if(!a)continue;let n=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),n=e.readUInt16LE(r+2),i=e.readUInt32LE(r+4);if(i<=0||r+i>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),n=(256&r)!=0,i=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);i.push(n?function(e,t){let[,r]=nA(e,t),[a,n]=nA(e,t+r),i=t+r+n;return e.subarray(i,i+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),n=t+a;return nv.decode(e.subarray(n,n+2*r))}(e,o))}return i}(e.subarray(r,r+i));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let n=e.readUInt16LE(t+24),i=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+n;for(let t=0;t<o;t+=1){let r=s+t*i;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let n=e.readUInt32LE(r+8);if(0xffffffff!==n)return a[n];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,n,t);if(a)return a}r+=i}}(t);if(n)return n}return await nS(e)}async function nb(e,t){try{let r=await T("unzip",["-p",e,t],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function nA(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function nS(e){let t=await n_();if(!t)return;let r=await T(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function n_(){if(void 0!==e)return e??void 0;try{for(let t of aT()){let r=p.join(t,"build-tools");try{for(let t of(await b.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=p.join(r,t,"aapt");try{return await b.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function nN(e,t){let r="url"===e.kind&&np(e.url),a=await nl({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=p.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),n=t?.resolveIdentity===!1?{}:await nx(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:n.packageName,cleanup:a.cleanup}}async function nx(e){let t=p.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await nI(e)}}let nD={settings:{type:"intent",value:"android.settings.SETTINGS"}},nk="android.intent.category.LAUNCHER",nM="android.intent.category.LEANBACK_LAUNCHER",nE="android.intent.category.DEFAULT",nO="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.";async function nL(e,t){let r=t.trim();if("package"===na(r))return{type:"package",value:r};let a=nD[r.toLowerCase()];if(a)return a;let n=(await T("adb",aU(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 H("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:n,hint:"Run agent-device apps --platform android to see the exact installed package names before retrying open."});throw new H("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:nO})}async function nC(e,t="all"){let r=await nP(e);return("user-installed"===t?(await nT(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:n$(e)}))}async function nP(e){let t=new Set;for(let r of nR(e,{includeFallbackWhenUnknown:!0})){let a=await T("adb",aU(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],n=a.includes("/")?a.split("/")[0]:a;n&&t.add(n)}}return t}function nR(e,t={}){return"tv"===e.target?[nM]:"mobile"===e.target?[nk]:t.includeFallbackWhenUnknown?[nk,nM]:[nk]}async function nT(e){return(await T("adb",aU(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function n$(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let n=r[e];if(!t.has(n)){a=n;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function nF(e){let t=await nU(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await nU(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function nU(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 T("adb",aU(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function nG(e,t,r){var a,n;let i;e.booted||await ne(e.id);let o=t.trim();if(aj(o)){if(r)throw new H("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await T("adb",aU(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await nL(e,t),l=nR(e)[0]??nk;if("intent"===s.type){if(r)throw new H("INVALID_ARGS","Activity override requires a package name, not an intent");await T("adb",aU(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;try{await T("adb",aU(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nE,"-c",l,"-n",t]))}catch(t){throw await nj(e,s.value,t),t}return}let d=await T("adb",aU(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nE,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,n=d.stderr,i=`${a}
|
|
14
|
+
${n}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(i)))return;let u=await nH(e,s.value);if(!u){if(!await nB(e,s.value))throw nV(s.value);throw new H("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr})}await T("adb",aU(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nE,"-c",l,"-n",u]))}function nV(e){return new H("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:nO})}async function nB(e,t){let r=await T("adb",aU(e,["shell","pm","path",t]),{allowFailure:!0}),a=`${r.stdout}
|
|
15
|
+
${r.stderr}`;return!!(0===r.exitCode&&/\bpackage:/i.test(a))||(nq(a),!1)}async function nj(e,t,r){if(nq(r instanceof H?`${String(r.details?.stdout??"")}
|
|
16
|
+
${String(r.details?.stderr??"")}`:"")||!await nB(e,t))throw nV(t)}function nq(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function nH(e,t){for(let r of Array.from(new Set(nR(e,{includeFallbackWhenUnknown:!0})))){let a=await T("adb",aU(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.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}(a.stdout);if(n)return n}return null}async function nW(e){e.booted||await ne(e.id)}async function nz(e,t){if("settings"===t.trim().toLowerCase())return void await T("adb",aU(e,["shell","am","force-stop","com.android.settings"]));let r=await nL(e,t);if("intent"===r.type)throw new H("INVALID_ARGS","Close requires a package name, not an intent");await T("adb",aU(e,["shell","am","force-stop",r.value]))}async function nJ(e,t){let r=await nL(e,t);if("intent"===r.type)throw new H("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await T("adb",aU(e,["uninstall",r.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
|
|
17
|
+
${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new H("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let nX=null;async function nK(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(nX?.key===e)return nX.invocation;if(await X("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return nX={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new H("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await d.access(t)}catch{throw new H("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return nX={key:e,invocation:r},r}async function nY(e){let t=await nK();await T(t.cmd,[...t.prefixArgs,...e])}async function nZ(e,t){let r,a=await d.mkdtemp(p.join(u.tmpdir(),"agent-device-aab-")),n=p.join(a,"bundle.apks"),i=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await nY(["build-apks","--bundle",t,"--output",n,"--mode",i]),await nY(["install-apks","--apks",n,"--device-id",e.id])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function nQ(e,t){".aab"===p.extname(t).toLowerCase()?await nZ(e,t):await T("adb",aU(e,["install","-r",t]))}async function n0(e){return new Set((await T("adb",aU(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function n1(e,t){let r=Array.from(await n0(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function n2(e,t){e.booted||await ne(e.id),await nQ(e,t)}async function n3(e,t,r){let a=r?void 0:await n0(e);return await n2(e,t),r??(a?await n1(e,a):void 0)}async function n4(e,t){e.booted||await ne(e.id);let r=await nN({kind:"path",path:t});try{let t=await n3(e,r.installablePath,r.packageName),a=t?n$(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function n5(e,t,r){e.booted||await ne(e.id);let{package:a}=await nJ(e,t),n=await nN({kind:"path",path:r},{resolveIdentity:!1});try{return await n2(e,n.installablePath),{package:a}}finally{await n.cleanup()}}function n8(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,a=function(e){if(void 0===e)return .6;if(!Number.isFinite(e)||e<=0)throw new H("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),n=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new H("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*a),i=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(n,Math.max(1,r-2*i))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(r,a,n,i)=>({direction:t,x1:r,y1:a,x2:n,y2:i,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return u(l,d-s,l,d+s);case"down":return u(l,d+s,l,d-s);case"left":return u(l-s,d,l+s,d);case"right":return u(l+s,d,l-s,d)}}function n6(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,n=a.exec(e);for(;n;){let t=ie(n[0]),i=(it(t,"text")??"").toLowerCase(),o=(it(t,"content-desc")??"").toLowerCase();if(i.includes(r)||o.includes(r)){let e=ir(it(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=a.exec(e)}return null}function n9(e,t,r){let a=function(e){let t=0,r=0,a=[...e.children];for(;a.length>0;){let e=a.pop();t+=1,r=Math.max(r,e.depth),a.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(e),n=[],i=[],o=!1,s=r.depth??1/0,l=r.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children],n=0;for(;n<a.length;){let e=a[n++],t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",o=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||o.includes(r))return e;a.push(...e.children)}return null}(e,r.scope):null,d=l?[l]:e.children,u=new Map,c=e=>{let t=u.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||c(t))return u.set(e,!0),!0;return u.set(e,!1),!1},p=(e,a,l,d=!1,u=!1)=>{if(n.length>=t){o=!0;return}if(a>s)return;let f=!!r.raw||function(e,t,r,a,n){var i;let o,s=ii(e.type),l=!!(e.label&&e.label.trim().length>0),d=!!(e.identifier&&e.identifier.trim().length>0),u=l&&!io(e.label??""),c=d&&!io(e.identifier??""),p=(o=(i=s).split(".").pop()??i).includes("layout")||"viewgroup"===o||"view"===o,f="imageview"===s||"imagebutton"===s;if(t.interactiveOnly)return!!(e.hittable||U(s)&&a)||!!(u||c)&&!f&&(!p||!!n)&&(r||a||n);return t.compact?u||c||!!e.hittable:!p&&!f||!!e.hittable||!!u||!!c&&!!a||a}(e,r,d,c(e),u),m=l;f&&(m=n.length,i.push(e),n.push({index:m,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:a,parentIndex:l,...e.hiddenContentAbove?{hiddenContentAbove:!0}:{},...e.hiddenContentBelow?{hiddenContentBelow:!0}:{}}));let h=d||!!e.hittable,w=u||function(e){if(!e)return!1;let t=ii(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(p(t,a+1,m,h,w),o)return};for(let e of d)if(p(e,0,void 0,!1,!1),o)break;return o?{nodes:n,sourceNodes:i,truncated:o,analysis:a}:{nodes:n,sourceNodes:i,analysis:a}}function n7(e){let t=ie(e),r=e=>{let r=it(t,e);if(null!==r)return"true"===r};return{text:it(t,"text"),desc:it(t,"content-desc"),resourceId:it(t,"resource-id"),className:it(t,"class"),bounds:it(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function ie(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let n=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,i=r;for(;i<a;){for(;i<a;){let t=e[i];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;i+=1}if(i>=a)break;let r=e[i];if("/"===r||">"===r)break;n.lastIndex=i;let o=n.exec(e);if(!o)break;t.set(o[1],o[3]),i=n.lastIndex}return t}function it(e,t){return e.get(t)??null}function ir(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),a=Number(t[2]);return{x:r,y:a,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-a)}}function ia(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,n=a.exec(e);for(;n;){let t=n[0];if(t.startsWith("</node")){r.length>1&&r.pop(),n=a.exec(e);continue}let i=n7(t),o=ir(i.bounds),s=r[r.length-1],l={type:i.className,label:i.text||i.desc,value:i.text,identifier:i.resourceId,rect:o,enabled:i.enabled,hittable:i.clickable??i.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),n=a.exec(e)}return t}function ii(e){return e?e.toLowerCase():""}function io(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}function is(e){if(0===e.length)return null;let t=[...e].sort((e,t)=>e-t);return t[Math.floor(t.length/2)]??null}function il(e,t){let r=Math.max(24,Math.round(.2*Math.min(e.size,t.size))),a=Math.max(48,Math.round(.15*Math.min(e.crossSize,t.crossSize)));return Math.abs(e.size-t.size)<=r&&Math.abs(e.crossSize-t.crossSize)<=a}function id(e,t){return{start:e.y-t.y,size:e.height,crossSize:e.width}}async function iu(e,t={}){let r=await ip(e);if(!t.interactiveOnly){let a=function(e,t){let{sourceNodes:r,...a}=n9(ia(e),800,t);return a}(r,t);return await ic(e,a.nodes),a}let a=ia(r),n=n9(a,800,{...t,interactiveOnly:!1});await ic(e,n.nodes),function(e){if(0===e.length||e.some(e=>e.hiddenContentAbove||e.hiddenContentBelow))return;let t=new Map(Y(e_(e)).nodes.filter(e=>e.hiddenContentAbove||e.hiddenContentBelow).map(e=>[e.index,e]));for(let r of e){let e=t.get(r.index);e&&(e.hiddenContentAbove&&(r.hiddenContentAbove=!0),e.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}(n.nodes),function(e){for(let[t,r]of e.sourceNodes.entries()){let a=e.nodes[t];a&&(a.hiddenContentAbove&&(r.hiddenContentAbove=!0),a.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}(n);let{sourceNodes:i,...o}=n9(a,800,t);return o}async function ic(e,t){if(!t.some(e=>U(e.type)))return;let r=await ig(e);r&&function(e,t){let r=function(e){let t={className:"root",rect:{x:0,y:0,width:0,height:0},children:[]},r=[{indent:-1,node:t}],a=/^(\s*)([\w.$]+)\{[^}]* (-?\d+),(-?\d+)-(-?\d+),(-?\d+) #/;for(let t of e.split("\n")){let e=a.exec(t);if(!e)continue;let n=e[1].length,i=Number(e[3]),o=Number(e[4]),s=Number(e[5]),l=Number(e[6]),d={className:e[2],rect:{x:i,y:o,width:Math.max(0,s-i),height:Math.max(0,l-o)},children:[]};for(;r.length>1&&n<=r[r.length-1].indent;)r.pop();r[r.length-1].node.children.push(d),r.push({indent:n,node:d})}return t.children.length>0?t:null}(t);if(!r)return;let a=function(e){let t=[],r=[e];for(;r.length>0;){let e=r.pop();if(U(e.className)){let r=function(e){let t=e.children[0];if(!t)return null;let r=Math.max(t.rect.height,...t.children.map(e=>e.rect.y+e.rect.height)),a=t.children.filter(e=>e.rect.height>0).map(t=>id(t.rect,e.rect)).sort((e,t)=>e.start-t.start);return 0===a.length?null:{rect:e.rect,contentExtent:r,contentBlocks:a}}(e);r&&t.push(r)}r.push(...e.children)}return t}(r);if(0!==a.length)for(let t of e){if(!t.rect||!U(t.type))continue;let r=function(e,t){let r=null,a=1/0;for(let n of t){let t=Math.abs(n.rect.width-e.width)+Math.abs(n.rect.height-e.height);if(t>32)continue;let i=4*t+(Math.abs(n.rect.x-e.x)+Math.abs(n.rect.y-e.y));i<a&&(r=n,a=i)}return r}(t.rect,a);if(!r)continue;let n=function(e,t){let r=function(e,t){let r=t,a=new Set;for(;!a.has(r.index);){var n,i;a.add(r.index);let o=e.filter(e=>e.parentIndex===r.index&&e.rect);if(1!==o.length)return r;let s=o[0];if(n=s.rect,i=t.rect,n.x!==i.x||n.y!==i.y||n.width!==i.width||n.height!==i.height)return r;r=s}return t}(e,t);return e.filter(e=>e.parentIndex===r.index&&e.rect).map(e=>e.rect).filter(e=>e.height>0).sort((e,t)=>e.y-t.y).map(e=>id(e,t.rect))}(e,t),i=function(e){let{viewportRect:t,visibleBlocks:r,nativeScrollView:a}=e;if(0===r.length||0===a.contentBlocks.length)return null;let n=function(e){if(0===e.contentBlocks.length)return null;let t=e.contentBlocks[0],r=e.contentBlocks[e.contentBlocks.length-1];if(!t||!r)return null;let a=is(e.contentBlocks.map(e=>e.size))??e.rect.height,n=Math.max(48,Math.round(.5*a)),i=Math.max(24,Math.round(.25*a)),o=t.start>=n,s=e.contentExtent-(r.start+r.size)>=i;return o||s?{above:o,below:s}:null}(a),i=function(e,t){let r=new Map;for(let a of e)for(let e of t){if(!il(a,e))continue;let t=a.start-e.start,n=8*Math.round(t/8),i=r.get(n)??[];i.push(t),r.set(n,i)}let a=null;for(let e of r.values())(!a||e.length>a.length)&&(a=e);if(!a||a.length<2)return null;let n=[...a].sort((e,t)=>e-t);return n[Math.floor(n.length/2)]??null}(a.contentBlocks,r)??function(e){let{nativeBlocks:t,visibleBlocks:r,viewportExtent:a,contentExtent:n}=e,i=[],o=[];for(let e of t)for(let t of r){if(!il(e,t))continue;let r=e.start-t.start;16>=Math.abs(r)&&i.push(r),16>=Math.abs(r+a-n)&&o.push(r)}return o.length>0?is(o):i.length>0?is(i):null}({nativeBlocks:a.contentBlocks,visibleBlocks:r,viewportExtent:t.height,contentExtent:a.contentExtent});if(null===i)return n;let o=t.height;return{above:(n?.above??!1)||i>16,below:(n?.below??!1)||i+o<a.contentExtent-16}}({viewportRect:t.rect,visibleBlocks:n,nativeScrollView:r});i&&(i.above&&(t.hiddenContentAbove=!0),i.below&&(t.hiddenContentBelow=!0))}}(t,r)}async function ip(e){return eU(()=>im(e),{shouldRetry:iw})}async function im(e){var t,r,a;let n,i,o=await T("adb",aU(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0}),s=ih(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",d=await T("adb",aU(e,["shell","uiautomator","dump",l]),{allowFailure:!0}),u=(t=l,r=d.stdout,a=d.stderr,n=`${r}
|
|
18
|
+
${a}`,i=/dumped to:\s*(\S+)/i.exec(n),i?.[1]??t),c=await T("adb",aU(e,["shell","cat",u])),p=ih(c.stdout,c.stderr);if(!p)throw new H("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return p}function ih(e,t){let r=`${e}
|
|
19
|
+
${t}`,a=r.indexOf("<?xml"),n=a>=0?a:r.indexOf("<hierarchy");if(n<0)return null;let i=r.lastIndexOf("</hierarchy>");if(i<0||i<n)return null;let o=r.slice(n,i+12).trim();return o.length>0?o:null}function iw(e){if(!(e instanceof H)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.details?.stderr??""}`.toLowerCase();return!!(t.includes("device offline")||t.includes("device not found")||t.includes("transport error")||t.includes("connection reset")||t.includes("broken pipe")||t.includes("timed out")||t.includes("no such file or directory"))}async function ig(e){try{let t=await T("adb",aU(e,["shell","dumpsys","activity","top"]),{allowFailure:!0,timeoutMs:8e3}),r=`${t.stdout}
|
|
20
|
+
${t.stderr}`.trim();return r.length>0?r:null}catch{return null}}async function iy(e,t,r){await T("adb",aU(e,["shell","input","tap",String(t),String(r)]))}async function iv(e,t,r,a,n,i=250){await T("adb",aU(e,["shell","input","swipe",String(t),String(r),String(a),String(n),String(i)]))}async function iI(e){await T("adb",aU(e,["shell","input","keyevent","4"]))}async function ib(e){await T("adb",aU(e,["shell","input","keyevent","3"]))}async function iA(e,t){let r=function(e){switch(e){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new H("INVALID_ARGS",`Unsupported Android rotation: ${e}`)}}(t);await T("adb",aU(e,["shell","settings","put","system","accelerometer_rotation","0"])),await T("adb",aU(e,["shell","settings","put","system","user_rotation",r]))}async function iS(e){await T("adb",aU(e,["shell","input","keyevent","187"]))}async function i_(e,t,r,a=800){await T("adb",aU(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function iN(e,t,r=0){r>0&&Array.from(t).length>1?await iP(e,t,1,r):await ix(e,t)}async function ix(e,t){let r=iR(t);if(!r||"ok"!==await iT(e,t))try{let r=t.replace(/ /g,"%s");await T("adb",aU(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof H)||"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 H("COMMAND_FAILED","Non-ASCII text input is not supported on this Android shell. Install an ADB keyboard IME or use ASCII input.",{textPreview:t.slice(0,32)},e instanceof Error?e:void 0);throw e}}async function iD(e,t,r){await iy(e,t,r)}async function ik(e,t,r,a,n=0){let i=Array.from(a).length,o=iR(a),s=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];!o&&n<=0&&s.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),(!o||n>0)&&s.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96});let l=null;for(let o of s){var d,u;await iD(e,t,r);let s=(d=i+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await i$(e,s),"input_text"===o.strategy)await iN(e,a,n);else if("clipboard_paste"===o.strategy){if("ok"!==await iT(e,a))continue}else await iP(e,a,1,n>0?n:15);let c=await iM(e,t,r,a);if(l=c.actual,c.ok)return}throw new H("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function iM(e,t,r,a){let n=null;for(let i of[0,150,350])if(i>0&&await aB(i),function(e,t){if(e===t)return!0;let r=iE(e),a=iE(t);return!!r&&!!a&&(!!(r===a||r.includes(a))||a.includes(r)&&r.length>=Math.max(4,Math.floor(.8*a.length)))}(n=await iF(e,t,r),a))return{ok:!0,actual:n};return{ok:!1,actual:n}}function iE(e){return(e??"").replace(/\s+/g," ").trim()}async function iO(e,t,r){let a=await iC(e),n=n8({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await T("adb",aU(e,["shell","input","swipe",String(n.x1),String(n.y1),String(n.x2),String(n.y2),"300"])),n}async function iL(e,t,r){let a=r?.maxScrolls??8,n="";try{n=await ip(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new H("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(n6(n,t))return{attempts:0};for(let r=1;r<=a;r+=1){await iO(e,"down",{amount:.5});let a="";try{a=await ip(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new H("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(n6(a,t))return{attempts:r};if(a===n)throw new H("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:r,stalled:!0});n=a}throw new H("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:a})}async function iC(e){let t=(await T("adb",aU(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new H("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iP(e,t,r,a){let n=Math.max(1,Math.floor(r)),i=Array.from(t);for(let t=0;t<i.length;t+=n){let r=i.slice(t,t+n).join("");await ix(e,r),a>0&&t+n<i.length&&await aB(a)}}function iR(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 iT(e,t){let r=await T("adb",aU(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":aV(r.stdout,r.stderr)?"unsupported":0===(await T("adb",aU(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await T("adb",aU(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function i$(e,t){let r=Math.max(0,t);await T("adb",aU(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let a=Math.min(24,r-t);await T("adb",aU(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function iF(e,t,r){let a,n=await ip(e),i=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=i.exec(n));){let e=n7(a[0]),n=ir(e.bounds);if(!n)continue;let i=e.className??"",d=(e.text??"").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/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&&iU(i)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&iU(i)){(!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 iU(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iG(e){let t=await T("adb",aU(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new H("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),n=a.length>0?a[a.length-1]?.[1]:void 0,i=n?`0x${n.toLowerCase()}`:void 0;return{visible:r,inputType:i,type:i?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(i):void 0}}(t.stdout)}async function iV(e){let t=await iG(e),r=t,a=0;for(;r.visible&&a<2;)await T("adb",aU(e,["shell","input","keyevent","111"])),a+=1,await aB(120),r=await iG(e);if(t.visible&&r.visible)throw new H("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:a,inputType:r.inputType,type:r.type});return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function iB(e){let t,r;return(r=(t=(await iq(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 ij(e,t){await iq(e,["shell","cmd","clipboard","set","text",t],"write")}async function iq(e,t,r){let a=await T("adb",aU(e,t),{allowFailure:!0});if(aV(a.stdout,a.stderr))throw new H("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new H("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let iH=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iW(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new H("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iz(e){let t=e?.trim().toLowerCase();if("camera"===t||"microphone"===t||"photos"===t||"contacts"===t||"contacts-limited"===t||"notifications"===t||"calendar"===t||"location"===t||"location-always"===t||"media-library"===t||"motion"===t||"reminders"===t||"siri"===t)return t;throw new H("INVALID_ARGS",`permission setting requires a target: ${iH.join("|")}`)}function iJ(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new H("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function iX(e,t,r,a,n){switch(t.toLowerCase()){case"wifi":{let t=iY(r);await T("adb",aU(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=iY(r);await T("adb",aU(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await T("adb",aU(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=iY(r);await T("adb",aU(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await iZ(e,r);await T("adb",aU(e,["shell","cmd","uimode","night","dark"===t?"yes":"no"]));return}case"fingerprint":{let t=function(e){let t=e.trim().toLowerCase();if("match"===t)return"match";if("nonmatch"===t)return"nonmatch";throw new H("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await iK(e,t);return}case"permission":{if(!a)throw new H("INVALID_ARGS","permission setting requires an active app in session");let t=iW(r),i=function(e,t){let r=iz(e);if(t?.trim())throw new H("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 H("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(n?.permissionTarget,n?.permissionMode);if("notifications"===i.kind)return void await i0(e,a,t,i);let o="grant"===t?"grant":"revoke";if("photos"===i.type)return void await iQ(e,a,o);await T("adb",aU(e,["shell","pm",o,a,i.value]));return}default:throw new H("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function iK(e,t){var r;let a,n,i=(r=e,n=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&n.push(["emu","finger","touch",a]),n),o=[];for(let t of i){let r=await T("adb",aU(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
|
|
21
|
+
${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new H("UNSUPPORTED_OPERATION","Android fingerprint simulation is not supported on this target/runtime.",{deviceId:e.id,action:t,hint:"Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.",attempts:s});throw new H("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function iY(e){let t=e.toLowerCase();if("on"===t||"true"===t||"1"===t)return!0;if("off"===t||"false"===t||"0"===t)return!1;throw new H("INVALID_ARGS",`Invalid setting state: ${e}`)}async function iZ(e,t){let r=iJ(t);if("toggle"!==r)return r;let a=await T("adb",aU(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new H("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let n=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
|
|
22
|
+
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!n)throw new H("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"auto"===n?"dark":"dark"===n?"light":"dark"}async function iQ(e,t,r){let a=await i1(e),n=[];for(let i of null!==a&&a>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let a=await T("adb",aU(e,["shell","pm",r,t,i]),{allowFailure:!0});if(0===a.exitCode)return;n.push({permission:i,stderr:a.stderr,exitCode:a.exitCode})}throw new H("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:a,attempts:n})}async function i0(e,t,r,a){"grant"===r?await T("adb",aU(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await T("adb",aU(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await T("adb",aU(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await T("adb",aU(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await T("adb",aU(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function i1(e){let t=await T("adb",aU(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 i2(e,t,r){let a="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,n=["shell","am","broadcast","-a",a,"-p",t],i="string"==typeof r.receiver?r.receiver.trim():"";i&&n.push("-n",i);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new H("INVALID_ARGS","Android push payload extras must be an object");let s=0;for(let[e,t]of Object.entries(o??{}))e&&(function(e,t,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 H("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(n,e,t),s+=1);return await T("adb",aU(e,n)),{action:a,extrasCount:s}}let i3=Buffer.from([137,80,78,71,13,10,26,10]);async function i4(e,t){await i5(e);try{await aB(1e3),await i6(e,t)}finally{await i8(e).catch(()=>{})}}async function i5(e){let t=t=>T("adb",aU(e,["shell",t]),{allowFailure:!0});await t("settings put global sysui_demo_allowed 1");let r=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await r("clock -e hhmm 0941"),await r("notifications -e visible false")}async function i8(e){await T("adb",aU(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function i6(e,t){let r=await T("adb",aU(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new H("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(i3);if(a<0)throw new H("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let n=function(e,t){let r=t+i3.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),a=r+4,n=e.toString("ascii",a,a+4),i=r+12+t;if(i>e.length)break;if("IEND"===n)return i;r=i}return null}(r.stdoutBuffer,a);if(!n)throw new H("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await d.writeFile(t,r.stdoutBuffer.subarray(a,n))}let i9=eQ(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,eR,5e3),i7=eQ(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,eP,1e3),oe=eQ(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),ot=eQ(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),or=eQ(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),oa=eQ(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),on=eQ(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3),oi=eC(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK);async function oo(e,t){let r=["devicectl",...e],a=await T("xcrun",r,{allowFailure:!0,timeoutMs:ot});if(0===a.exitCode)return;let n=String(a.stdout??""),i=String(a.stderr??"");throw new H("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:a.exitCode,stdout:n,stderr:i,deviceId:t.deviceId,hint:od(n,i)??ol})}async function os(e,t){let r=p.join(u.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),a=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],n=await T("xcrun",a,{allowFailure:!0,timeoutMs:ot});try{var i,o;if(0!==n.exitCode){let t=String(n.stdout??""),r=String(n.stderr??"");throw new H("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:n.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:od(t,r)??ol})}let s=await d.readFile(r,"utf8");return i=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 a="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:a})}return r}(JSON.parse(s)),o=t,"user-installed"===o?i.filter(e=>!e.bundleId.startsWith("com.apple.")):i}catch(t){if(t instanceof H)throw t;throw new H("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await d.unlink(r).catch(()=>{})}}let ol="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function od(e,t){let r=`${e}
|
|
23
|
+
${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function ou(e){if(!(e instanceof H)||"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 oc(e,t){let r=await T("xcrun",te(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let a=r.stdout.trim();if(!a)return{installed:!1};let n=await T("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${a}/Info.plist`],{allowFailure:!0});if(0!==n.exitCode||!n.stdout.trim())return{installed:!0};let i=n.stdout.trim(),o=`${a}/${i}`,s=await T("otool",["-l",o],{allowFailure:!0});if(0!==s.exitCode)return{installed:!0};let l=s.stdout.toLowerCase();return{installed:!0,simulatorCompatible:l.includes("iossimulator")||l.includes("platform 7")}}function op(e,t){if("simulator"!==e.kind)throw new H("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function of(){await T("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:or})}async function om(e){let t,r;if("simulator"!==e.kind||"Booted"===await ow(e))return;let a=e$.fromTimeoutMs(i9);try{await eF(async({deadline:a})=>{if(a?.isExpired())throw new H("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:i9});let n=Math.max(1e3,a?.remainingMs()??i9),i=await T("xcrun",te(e,["boot",e.id]),{allowFailure:!0,timeoutMs:n});t={stdout:String(i.stdout??""),stderr:String(i.stderr??""),exitCode:i.exitCode};let o=`${t.stdout}
|
|
24
|
+
${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new H("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await T("xcrun",te(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 H("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await ow(e);if("Booted"!==d)throw new H("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=e0({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==a&&"CI_RESOURCE_STARVATION_SUSPECTED"!==a}},{deadline:a,phase:"boot",classifyReason:e=>e0({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(i){let n=e0({error:i,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new H("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:i9,elapsedMs:a.elapsedMs(),reason:n,hint:e1(n),boot:t,bootstatus:r})}await of()}async function oh(e){let t=te(e,["shutdown",e.id]),r=await T("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function ow(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?e7(["list","devices","-j"]):te(e,["list","devices","-j"]),a=await T("xcrun",r,{allowFailure:!0,timeoutMs:i7});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function og(e,t){try{let r=await T("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{let r=await d.readFile(e,"utf8");return function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`<key>\\s*${r}\\s*<\\/key>\\s*<string>([\\s\\S]*?)<\\/string>`,"i"));if(!a?.[1])return;let n=a[1].trim().replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&");return n.length>0?n:void 0}(r,t)}catch{return}}async function oy(e,t){if("url"===e.kind&&!np(e.url))throw new H("INVALID_ARGS","iOS install_from_source URL sources are only supported for trusted artifact services such as GitHub Actions and EAS. Use a path source for other hosts.");let r=await nl({source:e,isInstallablePath:(e,t)=>t.isDirectory()&&e.toLowerCase().endsWith(".app")||t.isFile()&&e.toLowerCase().endsWith(".ipa"),installableLabel:"iOS installable (.app or .ipa)",allowArchiveExtraction:"url"!==e.kind||np(e.url),signal:t?.signal}),a=await oI(r.installablePath,t),n=await ov(a.installPath);return{archivePath:r.archivePath??(r.installablePath.toLowerCase().endsWith(".ipa")?r.installablePath:void 0),installablePath:a.installPath,bundleId:n.bundleId,appName:n.appName,cleanup:async()=>{await a.cleanup(),await r.cleanup()}}}async function ov(e){let t=p.join(e,"Info.plist"),[r,a,n]=await Promise.all([og(t,"CFBundleIdentifier"),og(t,"CFBundleDisplayName"),og(t,"CFBundleName")]);return{bundleId:r,appName:a??n}}async function oI(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await d.mkdtemp(p.join(u.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await d.rm(r,{recursive:!0,force:!0})};try{await T("ditto",["-x","-k",e,r]);let n=p.join(r,"Payload"),i=(await d.readdir(n,{withFileTypes:!0}).catch(()=>{throw new H("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:p.join(n,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===i.length)return{installPath:i[0].installPath,cleanup:a};if(0===i.length)throw new H("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await ob(i);let o=t?.appIdentifierHint?.trim();if(o){let e=function(e,t){let r=t.toLowerCase(),a=e.filter(e=>e.bundleName.toLowerCase()===r);if(1===a.length)return a[0];if(a.length>1)throw new H("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${t}" by name. Use a bundle id hint instead.`);if(t.includes(".")){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(1===t.length)return t[0]}}(i,o);if(e)return{installPath:e.installPath,cleanup:a};throw new H("INVALID_ARGS",`Invalid IPA: found ${i.length} .app bundles under Payload and none matched "${o}". Available bundles: ${i.map(oA).join(", ")}`)}throw new H("INVALID_ARGS",`Invalid IPA: found ${i.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${i.map(oA).join(", ")}`)}catch(e){throw await a(),e}}async function ob(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await ov(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function oA(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function oS(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let o_="agent-device-macos-helper",oN="AGENT_DEVICE_MACOS_HELPER_BIN",ox=p.join(u.homedir(),".agent-device","macos-helper","current"),oD=p.join(ox,"manifest.json"),ok=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function oM(e){let t=e.trim();if(!ok.test(t))throw new H("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function oE(){return function(e){let t=p.dirname(e);for(;;){let e=p.join(t,"macos-helper");if(l(p.join(e,"Package.swift")))return e;let r=p.dirname(t);if(r===t)break;t=r}throw new H("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(w(import.meta.url))}async function oO(e){let t=await d.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let r=p.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await oO(r):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[r]:[]}))).flat().sort()}async function oL(e){let t=await oO(e),r=o("sha256");for(let a of t)r.update(p.relative(e,a)),r.update("\0"),r.update(await d.readFile(a)),r.update("\0");let a=await T("swift",["--version"],{allowFailure:!0,cwd:e,timeoutMs:1e4});return r.update("swift-version"),r.update("\0"),r.update(a.stdout||a.stderr||`exit:${a.exitCode}`),r.update("\0"),r.digest("hex")}async function oC(){try{let e=JSON.parse(await d.readFile(oD,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function oP(){let e=process.env[oN]?.trim();if(e)return e;let t=oE(),r=await oL(t),a=p.join(ox,o_);try{if(await oC()===r)return await d.access(a),a}catch{}let n=p.join(oE(),".build","release",o_);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await T("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await d.mkdir(ox,{recursive:!0});let i=`${a}.tmp`;return await d.copyFile(n,i),await d.rename(i,a),await d.chmod(a,493),await d.writeFile(oD,`${JSON.stringify({fingerprint:r},null,2)}
|
|
25
|
+
`,"utf8"),a}async function oR(e){let t=process.env[oN]?.trim();if("darwin"!==process.platform&&!t)throw new H("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let r=await oP(),a=await T(r,e,{allowFailure:!0,timeoutMs:3e4}),n=a.stdout.trim(),i=null;if(n)try{i=JSON.parse(n)}catch{i=null}if(0===a.exitCode&&i?.ok)return i.data;throw new H("COMMAND_FAILED",i&&!i.ok?i.error?.message??`macOS helper exited with code ${a.exitCode}`:n||a.stderr.trim()||`macOS helper exited with code ${a.exitCode}`,{helperPath:r,args:e,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,...i&&!i.ok?i.error?.details:{}})}async function oT(){return await oR(["app","frontmost"])}async function o$(e){return await oR(["app","quit","--bundle-id",oM(e)])}async function oF(e,t){return await oR(["permission",e,t])}async function oU(e,t={}){let r=["alert",e];return t.bundleId&&r.push("--bundle-id",oM(t.bundleId)),t.surface&&r.push("--surface",t.surface),await oR(r)}async function oG(e,t={}){let r=["snapshot","--surface",e];return t.bundleId&&r.push("--bundle-id",oM(t.bundleId)),await oR(r)}async function oV(e,t,r={}){let a=["read","--x",String(e),"--y",String(t)];return r.bundleId&&a.push("--bundle-id",oM(r.bundleId)),r.surface&&a.push("--surface",r.surface),await oR(a)}async function oB(e,t,r={}){let a=["press","--x",String(e),"--y",String(t)];return r.bundleId&&a.push("--bundle-id",oM(r.bundleId)),r.surface&&a.push("--surface",r.surface),await oR(a)}async function oj(e,t={}){let r=["screenshot","--out",e];return t.surface&&r.push("--surface",t.surface),t.fullscreen&&r.push("--fullscreen"),await oR(r)}let oq={settings:"com.apple.systempreferences"},oH=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function oW(e,t){let r=["-b",e];return t&&r.push(t),r}async function oz(e){for(let t of[p.join(e,"Contents","Info.plist"),p.join(e,"Info.plist")]){let[e,r,a]=await Promise.all([og(t,"CFBundleIdentifier"),og(t,"CFBundleDisplayName"),og(t,"CFBundleName")]);if(e||r||a)return{bundleId:e,appName:r??a}}return{}}async function oJ(e){let t=e.trim(),r=oq[t.toLowerCase()];if(r)return r;if(oH.test(t))return t;let a=(await o1("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new H("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});throw new H("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function oX(e,t,r){let a=r?.url?.trim();if(a){if(!aj(a))throw new H("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await oJ(t);await T("open",oW(e,a));return}let n=t.trim();if(aj(n))return void await T("open",[n]);let i=r?.appBundleId??await oJ(n);await T("open",oW(i))}async function oK(e,t){let r=await oJ(t),a=await o$(r);if(a.running&&!a.terminated&&!a.forceTerminated)throw new H("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:r,running:a.running,terminated:a.terminated,forceTerminated:a.forceTerminated})}async function oY(){let e=await T("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new H("COMMAND_FAILED","Failed to read macOS clipboard",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});return e.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function oZ(e){let t=await T("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new H("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function oQ(){let e=await T("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new H("COMMAND_FAILED","Failed to read macOS appearance",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});let t=e.stdout.trim().toLowerCase();if("true"===t)return!0;if("false"===t)return!1;throw new H("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function o0(e){let t=iJ(e),r="toggle"===t?!await oQ():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${r?"true":"false"}`,n=await T("osascript",["-e",a],{allowFailure:!0});if(0!==n.exitCode)throw new H("COMMAND_FAILED","Failed to set macOS appearance",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}async function o1(e="all"){let t=["/Applications","/System/Applications",p.join(u.homedir(),"Applications")],r=new Set;for(let e of t){let t=await d.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await T("find",[e,"-maxdepth","4","-type","d","-name","*.app"],{allowFailure:!0});if(0===a.exitCode)for(let e of a.stdout.split("\n")){let t=e.trim();t&&r.add(t)}}return oS((await Promise.all(Array.from(r).map(async e=>{let t=await oz(e).catch(()=>({})),r=t.bundleId;return r?{bundleId:r,name:t.appName??p.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let o2=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],o3={0:"hide",1:"wifi",6:"3g",7:"4g",8:"lte",9:"lte-a",10:"lte+",11:"5g",12:"5g+",13:"5g-uwb",14:"5g-uc"},o4={1:"searching",2:"failed",3:"active"},o5={0:"notSupported",1:"searching",2:"failed",3:"active"};function o8(e,t,r){return T("xcrun",te(e,t),r)}async function o6(e,t){var r,a;let n;await o7(e),t&&await se(e,(n=[],(r=t).dataNetwork&&n.push("--dataNetwork",r.dataNetwork),r.wifiMode&&n.push("--wifiMode",r.wifiMode),void 0!==r.wifiBars&&("wifi"===r.dataNetwork||r.wifiMode)&&n.push("--wifiBars",r.wifiBars),r.cellularMode&&n.push("--cellularMode",r.cellularMode),void 0!==r.cellularBars&&(r.cellularMode||(a=r.dataNetwork)&&"hide"!==a&&"wifi"!==a||void 0!==r.operatorName)&&n.push("--cellularBars",r.cellularBars),void 0!==r.operatorName&&n.push("--operatorName",r.operatorName),n))}async function o9(e){let t=await o8(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new H("COMMAND_FAILED","Failed to read simulator status bar overrides",{exitCode:t.exitCode,stdout:t.stdout,stderr:t.stderr});return function(e){let t={};for(let r of e.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&"Current Status Bar Overrides:"!==e&&!/^=+$/.test(e))){let e=/^DataNetworkType:\s+(\d+)$/.exec(r);if(e){let r=Number(e[1]),a=o3[r];if(!a)throw new H("COMMAND_FAILED",`Unsupported simulator data network type: ${r}`);t.dataNetwork=a;continue}let a=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(r);if(a){let e=o4[Number(a[1])];e&&(t.wifiMode=e),t.wifiBars=a[2];continue}let n=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(r);if(n){let e=Number(n[1]),r=o5[e];if(!r)throw new H("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=r,t.cellularBars=n[2];continue}let i=/^Operator Name:\s*(.*)$/.exec(r);if(i){t.operatorName=i[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function o7(e){await o8(e,["status_bar",e.id,"clear"])}async function se(e,t){0!==t.length&&await o8(e,["status_bar",e.id,"override",...t])}function st(e,t,r){eu({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof H))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}(r)}})}function sr(e,t,r){return T("xcrun",te(e,t),r)}let sa={ensureBooted:om,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await o9(e),r=!0}catch(t){st(e,"snapshot_failed",t)}try{await o7(e),await se(e,o2)}catch(t){st(e,"prepare_failed",t)}return async()=>{await o6(e,r?t:null)}},captureWithRetry:so,runnerFallbackEnabled:oi,captureWithRunner:ss,shouldFallbackToRunner:sm};async function sn(e,t,r,a){if("macos"===e.platform)return void await ss(e,t,r,a);if("simulator"===e.kind)return void await si(e,t,r,a);try{await oo(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof H)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",n=`${e.message}
|
|
26
26
|
${r}
|
|
27
|
-
${a}`.toLowerCase();return n.includes("unknown option '--device'")||n.includes("unknown subcommand")&&n.includes("screenshot")||n.includes("unrecognized subcommand")&&n.includes("screenshot")}(t))throw t;
|
|
27
|
+
${a}`.toLowerCase();return n.includes("unknown option '--device'")||n.includes("unknown subcommand")&&n.includes("screenshot")||n.includes("unrecognized subcommand")&&n.includes("screenshot")}(t))throw t;sc(e,"devicectl_screenshot",t)}await ss(e,t,r,a)}async function si(e,t,r,a,n=sa){if("simulator"!==e.kind)throw new H("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let i="object"==typeof a&&null!==a?a:n;await i.ensureBooted(e);let o=async()=>{};try{o=await i.prepareStatusBarForScreenshot(e)}catch(t){sp(e,"prepare_failed",t)}try{try{await i.captureWithRetry(e,t);return}catch(t){if(!i.shouldFallbackToRunner(t))throw t;if(!i.runnerFallbackEnabled){var s,l,d;let r,a;throw s=e,l=t,r=sf(l),eu({level:"warn",phase:"ios_screenshot_fallback_skipped",data:{platform:s.platform,deviceKind:s.kind,deviceId:s.id,from:"simctl_screenshot",to:"runner",reason:"Simulator runner fallback is disabled to avoid XCTest automation instability during screenshot capture.",...r}}),a=(d=t)instanceof H?d:new H("COMMAND_FAILED","Failed to capture iOS screenshot: simulator screenshot retries exhausted",void 0,d),new H(a.code,a.message,{...a.details??{},hint:"Restart the simulator and retry. If simctl screenshots keep timing out and you accept the stability tradeoff, set AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK=1 to allow XCTest runner fallback."},a)}sc(e,"simctl_screenshot",t)}await i.captureWithRunner(e,t,r,"boolean"==typeof a?a:void 0)}finally{await o().catch(t=>sp(e,"restore_failed",t))}}async function so(e,t){let r=e$.fromTimeoutMs(oa);await eF(async({deadline:r})=>{await sr(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,r?.remainingMs()??oa)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>sm(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function ss(e,t,r,a){let n=(await rs(e,{command:"screenshot",appBundleId:r,fullscreen:a})).message;if(!n)throw new H("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await d.copyFile(n,t):"simulator"===e.kind?await sd(e,n,t):await sl(e,n,t)}async function sl(e,t,r){let a=e$.fromTimeoutMs(on),n={exitCode:1,stdout:"",stderr:""};for(let i of tF)if(0===(n=await T("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",i],{allowFailure:!0,timeoutMs:su(a,on,"runner screenshot copy")})).exitCode)return;let i=n.stderr.trim()||n.stdout.trim()||`devicectl exited with code ${n.exitCode}`;throw new H("COMMAND_FAILED",`Failed to capture iOS screenshot: ${i}`)}async function sd(e,t,r){let a=e$.fromTimeoutMs(on),n="Unable to locate runner container for simulator screenshot";for(let i of tF){let o=await sr(e,["get_app_container",e.id,i,"data"],{allowFailure:!0,timeoutMs:su(a,on,"runner screenshot container lookup")});if(0!==o.exitCode){let e=o.stderr.trim();e&&(n=e);continue}let s=o.stdout.trim();if(!s){n="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=p.resolve(e),a=t.trim();if(!a)return[];let n=[],i=new Set,o=e=>{let t=p.normalize(e);i.has(t)||(i.add(t),n.push(t))},s=a.replace(/^\/+/,""),l=s.replace(/\\/g,"/");if(s&&o(p.join(r,s)),p.isAbsolute(a)&&o(p.normalize(a)),l.startsWith("tmp/"))o(p.join(r,l));else{let e=l.lastIndexOf("/tmp/");if(e>=0){let t=l.slice(e+1);o(p.join(r,t))}}let d=p.basename(a);return d&&o(p.join(r,"tmp",d)),n}(s,t))try{await d.copyFile(e,r);return}catch(e){n=e instanceof Error?e.message:String(e)}}throw new H("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}function su(e,t,r){let a=e.remainingMs();if(a>0)return a;throw new H("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function sc(e,t,r){let a=sf(r);eu({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function sp(e,t,r){eu({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...sf(r)}})}function sf(e){if(!(e instanceof H))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}function sm(e){if(!(e instanceof H)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",n=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",i=`${e.message}
|
|
28
28
|
${r}
|
|
29
29
|
${a}
|
|
30
|
-
${n}`.toLowerCase();return i.includes("timeout waiting for screen surfaces")||i.includes("nsposixerrordomain")&&i.includes("code=60")&&i.includes("screenshot")||i.includes("timed out")&&i.includes("screenshot")}let
|
|
31
|
-
${i}`.toLowerCase()))throw new
|
|
32
|
-
${a.stderr}`.toLowerCase()))throw new
|
|
33
|
-
`,"utf8"),await
|
|
34
|
-
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!n)throw new
|
|
35
|
-
${n.stderr}`);if(0===i.size)throw new
|
|
36
|
-
${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new q("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:i});throw new q("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:i})}async function sO(e,t){await oi(e);let r=0,a=eT.fromTimeoutMs(i1);try{await e$(async({deadline:r})=>{var a;if(r?.isExpired())throw new q("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:i1});let n=(a=["launch",e.id,t],e7(e,a)),i=await R("xcrun",n,{allowFailure:!0});if(0!==i.exitCode)throw new q("COMMAND_FAILED",`xcrun exited with code ${i.exitCode}`,{cmd:"xcrun",args:n,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!ot(e)&&(r+=1)<3},{deadline:a})}catch(r){if(ot(r)){var n;let a=(n=await or(e,t)).installed?!1===n.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function sL(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await i6(a,{action:"launch iOS app",deviceId:e.id})}async function sC(e,t,r,a){let n=a?.maxScrolls??48,i=await e({command:"findText",text:r});if(i?.found)return{attempts:0};let o=sP(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let a=1;a<=n;a+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let n=await e({command:"findText",text:r});if(n?.found)return{attempts:a};let i=sP(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(i===o)throw new q("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a,stalled:!0});o=i}throw new q("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:n})}function sP(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function sR(e,t,r,a,n,i,o){if("tv"===t.target)return sF(await e(t,{command:"swipe",direction:function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left";default:return e}}(n),appBundleId:r.appBundleId},a),i);let s=o??await sT(e,t,r,a),l=nY({direction:n,amount:i?.amount,pixels:i?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return sF(await e(t,{command:"drag",x:s.originX+l.x1,y:s.originY+l.y1,x2:s.originX+l.x2,y2:s.originY+l.y2,appBundleId:r.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function sT(e,t,r,a){let n=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},a),i=s$(n.x),o=s$(n.y),s=s$(n.referenceWidth),l=s$(n.referenceHeight);if(void 0===i||void 0===o||void 0===s||void 0===l)throw new q("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:i,originY:o,referenceWidth:s,referenceHeight:l}}function s$(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function sF(e,t){var r;let{x1:a,y1:n,x2:i,y2:o}={x1:s$((r=e).x),y1:s$(r.y),x2:s$(r.x2),y2:s$(r.y2)},s=s$(e.referenceWidth),l=s$(e.referenceHeight),d=void 0!==a&&void 0!==i?Math.round(Math.abs(i-a)):void 0,u=void 0!==n&&void 0!==o?Math.round(Math.abs(o-n)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:d&&d>0?d:u&&u>0?u:void 0;return{...void 0!==a?{x1:a}:{},...void 0!==n?{y1:n}:{},...void 0!==i?{x2:i}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}function sU(e){return e?.clickButton??"primary"}function sV(e){return"primary"===e.button?null:"click"!==e.commandLabel?new q("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new q("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new q("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new q("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let sG=/^[A-Za-z0-9_.:-]{1,64}$/,sB=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function sj(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new q("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function sq(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await sH(t)}async function sH(e){await new Promise(t=>setTimeout(t,e))}function sW(e,t){let r,a=t?.subject??"Payload",n=e.trim();if(!n)throw new q("INVALID_ARGS",`${a} cannot be empty`);let i=t?.expandPath?t.expandPath(n,t.cwd):n;try{if(!s.statSync(i).isFile())throw new q("INVALID_ARGS",`${a} path is not a file: ${i}`);return{kind:"file",path:i}}catch(t){if(t instanceof q)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new q("INVALID_ARGS",`${a} file is not readable: ${i}`);if(e&&"ENOENT"!==e)throw new q("COMMAND_FAILED",`Unable to read ${a} file: ${i}`,{cause:String(t)})}if((r=n.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:n};throw new q("INVALID_ARGS",`${a} file not found: ${i}`)}async function sz(e){let t=sW(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await sJ(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new q("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof q)throw t;throw new q("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function sJ(e){try{return await d.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new q("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new q("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new q("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new q("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let sK=eZ(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),sX=/^(iphone|ipad|ipod|appletv)/i,sY=/\b(iphone|ipad|ipod)\b/i,sZ=/^appletv/i,sQ=["apple tv","appletv","tvos"],s0=/^==\s*(.+?)\s*==$/,s1=/^(?<name>.+?)\s+\[(?<id>[^[\]]+)\]\s*$/;function s2(e){return(e??"").trim().toLowerCase()}function s3(e){return s2(e.hardwareProperties?.platform)}function s4(e){return e.includes("tvos")}function s8(e){let t=s2(e);return sQ.some(e=>t.includes(e))}function s5(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function s6(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function s9(e={}){let t,r,a=e8(e.simulatorSetPath),n=e.target;try{t=await R("xcrun",e9(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let i=s7(r,a),o=null,s=null,l=null;for(let e of i)n&&e.target!==n||(e.booted&&(o=o??e),"mobile"===e.target&&(s=s??e),l=l??e);return o??s??l}function s7(e,t){let r=[];for(let[a,n]of Object.entries(e.devices))if(function(e){let t=s2(e);return t.includes("ios")||t.includes("tvos")}(a))for(let e of n)e.isAvailable&&r.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:s4(s2(a))?"tv":"mobile",booted:"Booted"===e.state,...t?{simulatorSetPath:t}:{}});return r}function le(e,t){let r=new Set(e.map(e=>e.id)),a=[...e];for(let e of t)r.has(e.id)||(r.add(e.id),a.push(e));return a}async function lt(){let e=null;try{e=c.join(u.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let t=await R("xcrun",["devicectl","list","devices","--json-output",e],{allowFailure:!0,timeoutMs:sK});if(0!==t.exitCode)return[];let r=await d.readFile(e,"utf8");return function(e){let t=[];for(let r of e.result?.devices??[]){if(!function(e){var t;let r=s3(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=s6(e),!!sX.test(t.trim())||s5(e).some(s8))}(r))continue;let e=r.hardwareProperties?.udid??r.identifier??"",a=r.name??r.deviceProperties?.name??e;e&&t.push({platform:"ios",id:e,name:a,kind:"device",target:function(e){var t;return s4(s3(e))?"tv":(t=s6(e),sZ.test(t.trim())||s5(e).some(s8))?"tv":"mobile"}(r),booted:!0})}return t}(JSON.parse(r))}catch{return[]}finally{e&&await d.rm(e,{force:!0}).catch(()=>{})}}async function lr(){try{let e=await R("xcrun",["xctrace","list","devices"],{allowFailure:!0});if(0!==e.exitCode)return[];return function(e){let t=[],r=null;for(let a of e.split(/\r?\n/)){let e=a.trim();if(!e)continue;let n=s0.exec(e);if(n){r=n[1]?.trim()??null;continue}if("Devices"!==r)continue;let i=s1.exec(e),o=i?.groups?.id?.trim()??"",s=i?.groups?.name?.trim()??"";if(!o||!s)continue;let l=function(e){return s8(e)?"tv":sY.test(e.trim())?"mobile":null}(s);l&&t.push({platform:"ios",id:o,name:s,kind:"device",target:l,booted:!0})}return t}(e.stdout)}catch{return[]}}async function la(e={}){if("darwin"!==process.platform)throw new q("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await J("xcrun"))throw new q("TOOL_MISSING","xcrun not found in PATH");let t=e8(e.simulatorSetPath),r=await R("xcrun",e9(["list","devices","-j"],{simulatorSetPath:t})),a=[];try{let e=JSON.parse(r.stdout);a=s7(e,t)}catch(e){throw new q("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(a.push({platform:"macos",id:"host-macos-local",name:u.hostname(),kind:"device",target:"desktop",booted:!0}),t)return a;let[n,i]=await Promise.all([lt(),lr()]);return a=le(a,n),le(a,i)}async function ln(e,t,r){let a,n=!!(t.udid||t.serial||t.deviceName);try{a=await tN(e,t,r)}catch(e){if(n||!(e instanceof q)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!n&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!a||"device"===a.kind)){let e=await s9({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new q("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function li(e){let t=e.platform,r=t_({simulatorSetPath:e8(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=e6(e.androidDeviceAllowlist);return await eo("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 q("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===n.platform){await aO();let e=await aJ({serialAllowlist:a});return await tN(e,n)}if(n.platform){let e=await la({simulatorSetPath:r});return await ln(e,n,{simulatorSetPath:r})}let i=[];try{i.push(...await aJ({serialAllowlist:a}))}catch{}try{i.push(...await la({simulatorSetPath:r}))}catch{}return await tN(i,n,{simulatorSetPath:r})},{platform:t,target:e.target})}async function lo(e,t,r,a,n){let i={requestId:n?.requestId,appBundleId:n?.appBundleId,verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>nO(e,t,r?.activity),openDevice:()=>n$(e),close:t=>nF(e,t),tap:(t,r)=>il(e,t,r),doubleTap:async(t,r)=>{await il(e,t,r),await il(e,t,r)},swipe:(t,r,a,n,i)=>id(e,t,r,a,n,i),longPress:(t,r,a)=>ih(e,t,r,a),focus:(t,r)=>iy(e,t,r),type:(t,r)=>iw(e,t,r),fill:(t,r,a,n)=>iv(e,t,r,a,n),scroll:(t,r)=>ib(e,t,r),scrollIntoView:(t,r)=>iS(e,t,r),screenshot:t=>iK(e,t),back:t=>iu(e),home:()=>ic(e),rotate:t=>ip(e,t),appSwitcher:()=>im(e),readClipboard:()=>iC(e),writeClipboard:t=>iP(e,t),setSetting:(t,r,a,n)=>iV(e,t,r,a,n)};case"ios":case"macos":{let r,a,{overrides:n,runnerOpts:i}=(r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},a=()=>{if(eJ(t.requestId))throw eX()},{runnerOpts:r,overrides:{tap:async(a,n)=>await t9(e,{command:"tap",x:a,y:n,appBundleId:t.appBundleId},r),doubleTap:async(a,n)=>await t9(e,{command:"tapSeries",x:a,y:n,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(a,n,i,o,s)=>await t9(e,{command:"drag",x:a,y:n,x2:i,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(a,n,i)=>await t9(e,{command:"longPress",x:a,y:n,durationMs:i,appBundleId:t.appBundleId},r),focus:async(a,n)=>await t9(e,{command:"tap",x:a,y:n,appBundleId:t.appBundleId},r),type:async(a,n)=>{await t9(e,{command:"type",text:a,delayMs:n,appBundleId:t.appBundleId},r)},fill:async(a,n,i,o)=>{let s=await t9(e,{command:"tap",x:a,y:n,appBundleId:t.appBundleId},r);return await t9(e,{command:"type",text:i,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},r),s},scroll:async(a,n)=>await sR(t9,e,t,r,a,n),scrollIntoView:async(n,i)=>await sC(a=>t9(e,{...a,appBundleId:t.appBundleId},r),a,n,i)}});return{open:(t,r)=>sc(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>sp(e),close:t=>sf(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await oP(t,{surface:r.surface,fullscreen:r.fullscreen}):await o8(e,t,r?.appBundleId,r?.fullscreen)},back:async r=>{await t9(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},i)},home:async()=>{await t9(e,{command:"home",appBundleId:t.appBundleId},i)},rotate:async r=>{await t9(e,{command:"rotate",orientation:r,appBundleId:t.appBundleId},i)},appSwitcher:async()=>{await t9(e,{command:"appSwitcher",appBundleId:t.appBundleId},i)},readClipboard:()=>sy(e),writeClipboard:t=>sv(e,t),setSetting:(t,r,a,n)=>sA(e,t,r,a,n),...n}}default:throw new q("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,i);return ed({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await eo("platform_command",async()=>{switch(t){case"open":return ls(e,o,r,n);case"close":{let e=r[0];if(!e)return{closed:"session",...el("Closed session")};return await o.close(e),{app:e,...el(`Closed: ${e}`)}}case"press":return ll(e,o,r,n,i);case"swipe":return ld(e,o,r,n,i);case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new q("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a,...el(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new q("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t,...el(`Focused (${e}, ${t})`)}}case"type":{let e=function(e){let t=e[0]?.trim();if(!t||!t.startsWith("@")||t.length<3)return null;let r=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(r)||/^(?:ref|node|element|el)[\w-]*$/i.test(r)?t:null}(r);if(e)throw new q("INVALID_ARGS",`type does not accept a target ref like "${e}"`,{hint:`Use fill ${e} "text" to target that field, or press ${e} then type "text" to append.`});let t=r.join(" ");if(!t)throw new q("INVALID_ARGS","type requires text");let a=sj(n?.delayMs??0,"delay-ms",0,1e4);return await o.type(t,a),{text:t,delayMs:a,...el(lI("Typed",t))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new q("INVALID_ARGS","fill requires x y text");let i=sj(n?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,a,i),{x:e,y:t,text:a,delayMs:i,...el(lI("Filled",a))}}case"scroll":return lu(o,r,n);case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new q("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:n?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...el(`Scrolled into view: ${e}`)};return{text:e,...el(`Scrolled into view: ${e}`)}}case"pinch":return lc(e,r,n,i);case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new q("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!sG.test(t))throw new q("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 q("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new q("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(r);if(Buffer.byteLength(a,"utf8")>8192)throw new q("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof q)throw t;throw new q("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),i=function(e,t,r){var a;let n,i=(n=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,n?.trim()||void 0);if(!i)throw new q("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=i.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new q("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await o.open(i,{appBundleId:n?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link",...el(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await d.mkdir(c.dirname(e),{recursive:!0}),await o.screenshot(e,{appBundleId:n?.appBundleId,fullscreen:n?.screenshotFullscreen,surface:n?.surface}),{path:e,...el(`Saved screenshot: ${e}`)}}case"back":return await o.back(n?.backMode),{action:"back",mode:n?.backMode??"in-app",...el("Back")};case"home":return await o.home(),{action:"home",...el("Home")};case"rotate":{let e=function(e){if(void 0===e)throw new q("INVALID_ARGS","rotate requires an orientation argument. Use portrait|portrait-upside-down|landscape-left|landscape-right.");switch(e?.trim().toLowerCase()){case"portrait":return"portrait";case"portrait-upside-down":case"upside-down":return"portrait-upside-down";case"landscape-left":case"left":return"landscape-left";case"landscape-right":case"right":return"landscape-right";default:throw new q("INVALID_ARGS",`Invalid rotation: ${e}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}(r[0]);return await o.rotate(e),{action:"rotate",orientation:e,...el(`Rotated to ${e}`)}}case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...el("Opened app switcher")};case"clipboard":return lp(o,r);case"keyboard":return lf(e,o,r,n,i);case"settings":return lm(e,o,r,n);case"push":return lh(e,r,n);case"snapshot":return lw(e,r,n,i);case"read":return lg(e,r,n,i);default:throw new q("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}async function ls(e,t,r,a){let n=r[0],i=r[1];if(r.length>2)throw new q("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!n)return await t.openDevice(),{app:null,...el("Opened device")};if(void 0!==i){if("android"===e.platform)throw new q("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(aP(n))throw new q("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!aP(i))throw new q("INVALID_ARGS","open <app> <url> requires a valid URL target");return await t.open(n,{activity:a?.activity,appBundleId:a?.appBundleId,url:i}),{app:n,url:i,...el(`Opened: ${n}`)}}return await t.open(n,{activity:a?.activity,appBundleId:a?.appBundleId}),{app:n,...el(`Opened: ${n}`)}}async function ll(e,t,r,a,n){let i,[o,s]=r.map(Number);if(Number.isNaN(o)||Number.isNaN(s))throw new q("INVALID_ARGS","press requires x y");if("macos"===e.platform&&a?.surface&&"app"!==a.surface){let e=sU(a);if("primary"!==e)throw new q("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${a.surface} sessions.`);return await oC(o,s,{bundleId:a.appBundleId,surface:a.surface}),{x:o,y:s,...el(ly({x:o,y:s}))}}let l=sU(a);if("primary"!==l){let t=sV({commandLabel:"click",platform:e.platform,button:l,count:a?.count,intervalMs:a?.intervalMs,holdMs:a?.holdMs,jitterPx:a?.jitterPx,doubleTap:a?.doubleTap});if(t)throw t;return await t9(e,{command:"mouseClick",x:o,y:s,button:l,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x:o,y:s,button:l,...el(ly({x:o,y:s,button:l}))}}let d=sj(a?.count??1,"count",1,200),u=sj(a?.intervalMs??0,"interval-ms",0,1e4),c=sj(a?.holdMs??0,"hold-ms",0,1e4),p=sj(a?.jitterPx??0,"jitter-px",0,100),f=a?.doubleTap===!0;if(f&&c>0)throw new q("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&p>0)throw new q("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&d>1&&0===c&&0===p){let t=await t9(e,{command:"tapSeries",x:o,y:s,count:d,intervalMs:u,doubleTap:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,timingMode:"runner-series",...t,...el(ly({x:o,y:s}))}}return await sq(d,u,async e=>{let[r,a]=function(e,t){if(t<=0)return[0,0];let[r,a]=sB[e%sB.length];return[r*t,a*t]}(e,p),n=o+r,l=s+a;if(f){i??=await t.doubleTap(n,l)??void 0;return}c>0?i??=await t.longPress(n,l,c)??void 0:i??=await t.tap(n,l)??void 0}),j({x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,...i},ly({x:o,y:s}))}async function ld(e,t,r,a,n){let i=Number(r[0]),o=Number(r[1]),s=Number(r[2]),l=Number(r[3]);if([i,o,s,l].some(Number.isNaN))throw new q("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let d=sj(r[4]?Number(r[4]):250,"durationMs",16,1e4),u="ios"===e.platform?Math.min(60,Math.max(16,Math.round(d))):d,c=sj(a?.count??1,"count",1,200),p=sj(a?.pauseMs??0,"pause-ms",0,1e4),f=a?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new q("INVALID_ARGS",`Invalid pattern: ${f}`);if(("ios"===e.platform||"macos"===e.platform)&&c>1){let t=await t9(e,{command:"dragSeries",x:i,y:o,x2:s,y2:l,durationMs:u,count:c,pauseMs:p,pattern:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x1:i,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"runner-series",count:c,pauseMs:p,pattern:f,...t,...el(lv(c,f))}}return await sq(c,p,async e=>{"ping-pong"===f&&e%2==1?await t.swipe(s,l,i,o,u):await t.swipe(i,o,s,l,u)}),j({x1:i,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:c,pauseMs:p,pattern:f},lv(c,f))}async function lu(e,t,r){let a=t[0],n=t[1]?Number(t[1]):void 0,i=r?.pixels;if(!a)throw new q("INVALID_ARGS","scroll requires direction");if(void 0!==n&&!Number.isFinite(n))throw new q("INVALID_ARGS","scroll amount must be a number");if(void 0!==n&&void 0!==i)throw new q("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let o=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new q("INVALID_ARGS",`Unknown direction: ${e}`)}}(a),s=await e.scroll(o,{amount:n,pixels:i});return j({direction:o,...void 0!==n?{amount:n}:{},...void 0!==i?{pixels:i}:{},...s},void 0!==i?`Scrolled ${o} by ${i}px`:void 0!==n?`Scrolled ${o} by ${n}`:`Scrolled ${o}`)}async function lc(e,t,r,a){if("android"===e.platform)throw new q("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&r?.surface&&"app"!==r.surface)throw new q("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let n=Number(t[0]),i=t[1]?Number(t[1]):void 0,o=t[2]?Number(t[2]):void 0;if(Number.isNaN(n)||n<=0)throw new q("INVALID_ARGS","pinch requires scale > 0");return await t9(e,{command:"pinch",scale:n,x:i,y:o,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId}),{scale:n,x:i,y:o,...el(`Pinched to scale ${n}`)}}async function lp(e,t){let r=(t[0]??"").toLowerCase();if("read"!==r&&"write"!==r)throw new q("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===r){if(1!==t.length)throw new q("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:r,text:await e.readClipboard()}}if(t.length<2)throw new q("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let a=t.slice(1).join(" ");return await e.writeClipboard(a),{action:r,textLength:Array.from(a).length,...el("Clipboard updated")}}async function lf(e,t,r,a,n){let i=(r[0]??"status").toLowerCase();if("status"!==i&&"get"!==i&&"dismiss"!==i)throw new q("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new q("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===i){let t=await iL(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let t=await iO(e);return{platform:"android",action:"status",visible:t.visible,inputType:t.inputType,type:t.type}}if("ios"===e.platform){if("dismiss"!==i)throw new q("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let t=await t9(e,{command:"keyboardDismiss",appBundleId:a?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,...el(t.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new q("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}async function lm(e,t,r,a){var n;let[i,o,s,l,d]=r,u="permission"===i?{permissionTarget:s,permissionMode:l}:void 0;ed({level:"debug",phase:"settings_apply",data:{setting:i,state:o,target:s,mode:l,platform:e.platform}});let c=await t.setSetting(i,o,d??a?.appBundleId,u);return c&&"object"==typeof c?j({setting:i,state:o,...c},("string"==typeof(n=c).message&&n.message.length>0?n.message:void 0)??`Updated setting: ${i}`):{setting:i,state:o,...el(`Updated setting: ${i}`)}}async function lh(e,t,r){let a=t[0]?.trim(),n=t[1]?.trim();if(!a||!n)throw new q("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await sz(n);if("ios"===e.platform)return await sI(e,a,i),{platform:"ios",bundleId:a,...el(`Pushed notification to ${a}`)};let o=await iz(e,a,i);return{platform:"android",package:a,action:o.action,extrasCount:o.extrasCount,...el(`Pushed notification to ${a}`)}}async function lw(e,t,r,a){if("android"!==e.platform){let t=await eo("snapshot_capture",async()=>await t9(e,{command:"snapshot",appBundleId:r?.appBundleId,interactiveOnly:r?.snapshotInteractiveOnly,compact:r?.snapshotCompact,depth:r?.snapshotDepth,scope:r?.snapshotScope,raw:r?.snapshotRaw},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId}),{backend:"xctest"}),a=t.nodes??[];if(0===a.length&&"simulator"===e.kind)throw new q("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:a,truncated:t.truncated??!1,backend:"xctest"}}let n=await eo("snapshot_capture",async()=>await ie(e,{interactiveOnly:r?.snapshotInteractiveOnly,compact:r?.snapshotCompact,depth:r?.snapshotDepth,scope:r?.snapshotScope,raw:r?.snapshotRaw}),{backend:"android"});return{nodes:n.nodes??[],truncated:n.truncated??!1,backend:"android",analysis:n.analysis}}async function lg(e,t,r,a){let[n,i]=t.map(Number);if(Number.isNaN(n)||Number.isNaN(i))throw new q("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await iM(e,n,i)??""};if("macos"===e.platform&&r?.surface&&"app"!==r.surface)return{action:"read",text:(await oL(n,i,{bundleId:r.appBundleId,surface:r.surface})).text};let o=await t9(e,{command:"readText",x:n,y:i,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId});return{action:"read",text:"string"==typeof o.text?o.text:"string"==typeof o.message?o.message:""}}function ly(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function lv(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function lI(e,t){return`${e} ${Array.from(t).length} chars`}let lA=e=>"macos"!==e.platform,lb=e=>"macos"===e.platform||"simulator"===e.kind,lS={alert:{apple:{simulator:!0,device:!0},android:{},supports:lb},pinch:{apple:{simulator:!0,device:!0},android:{},supports:lb},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:lA},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:lA},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:lA},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:lA},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:lA},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:lA},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},supports:lA},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},rotate:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function l_(e,t){let r=lS[e];if(!r)return!0;let a=tb(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function lN(e,t,r,a,n){return{requestId:n??en().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,screenshotFullscreen:t?.screenshotFullscreen,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:sU(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let lD=eZ(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function lx(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(eM);await t(e);return}if("device"===e.kind)return void await lk(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(eN);await t(e.id)}}async function lk(e){let t=c.join(u.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(lD/1e3));try{let a=await R("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:lD+3e3}),n=String(a.stdout??""),i=String(a.stderr??""),o=await lM(t);if(0===a.exitCode){if(!o.parsed)throw new q("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:n,stderr:i,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 q("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 q("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:n,stderr:i,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:lE(n,i)})}catch(t){if(t instanceof q&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),n=String(r.stderr??""),i=Number(r.timeoutMs??lD),o=`CoreDevice did not respond within ${i}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new q("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:i,stdout:a,stderr:n,hint:a||n?lE(a,n):o},t)}throw new q("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 d.rm(t,{force:!0}).catch(()=>{})}}async function lM(e){try{let t=await d.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,n="string"==typeof r?r:"string"==typeof a?a:void 0;return n?{tunnelState:n}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function lE(e,t){let r=oe(e,t);return r||(`${e}
|
|
37
|
-
${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":i7)}let lO=eZ(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),lL=new Map;async function lC(e){let t=await I.mkdtemp(c.join(u.tmpdir(),"agent-device-materialized-"));try{let r=await lT(e.installablePath,c.join(t,"installable")),a=e.archivePath?await lT(e.archivePath,c.join(t,"archive")):void 0,n=i.randomUUID(),o=e.ttlMs??lO,s=Date.now()+o,l=setTimeout(()=>{lP(n)},o);return lL.set(n,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:n,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await I.rm(t,{recursive:!0,force:!0}),e}}async function lP(e,t){let r=lL.get(e);if(!r)throw new q("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new q("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),lL.delete(e),await I.rm(r.rootPath,{recursive:!0,force:!0})}async function lR(e){let t=Array.from(lL.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await lP(e)}))}async function lT(e,t){let r=await I.stat(e);await I.mkdir(t,{recursive:!0});let a=c.join(t,c.basename(e));return r.isDirectory()?await I.cp(e,a,{recursive:!0}):await I.copyFile(e,a),a}async function l$(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new q("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await lx(e.session.device),e.session.device}if(!r)throw new q("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await li(e.flags??{});return await lx(a),a}async function lF(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);try{let e,i,o,s=(i=function(e){let t=e.meta?.installSource;if(!t)throw new q("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new q("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new q("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===i.kind?{source:{kind:"path",path:r5(o,t.meta?.tenantId)},cleanup:()=>{r6(o)}}:{source:i,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new q("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await l$({session:n,flags:t.flags});if(!l_("install",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let u=eK(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:i}=await Promise.resolve(eM),{prepareIosInstallArtifact:o}=await Promise.resolve(eE),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await lC({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:l.ttlMs})),await i(d,c.installablePath),!c.bundleId)throw new q("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=j(o,lU(o));return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await lP(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await Promise.resolve(ex),{installAndroidInstallablePathAndResolvePackageName:p}=await Promise.resolve(eD),f=await c(s.source,{signal:u});try{l.enabled&&(e=await lC({archivePath:f.archivePath,installablePath:f.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:l.ttlMs}));let i=await p(d,f.installablePath,f.packageName);if(!i)throw new q("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await Promise.resolve(eD),s=o(i),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:i,...s?{appName:s}:{},launchTarget:i,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=j(u,lU(u));return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await lP(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await f.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:ee(e)}}}function lU(e){return`Installed: ${eb(e)}`}async function lV(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new q("INVALID_ARGS","release_materialized_paths requires a materializationId");return await lP(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:ee(e)}}}let lG=eZ(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),lB=eZ(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function lj(e,t,r){return t||lq(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function lq(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function lH(e){return"ios"===e.platform&&"simulator"===e.kind}async function lW(e,t){lH(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function lz(e){let t=lq(e.flags)||!e.session?await li(e.flags??{}):await lJ(e.session.device);return!1!==e.ensureReady&&await lx(t),t}async function lJ(e){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let t={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await li(t)}catch(e){if(!(e instanceof q)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await li({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function lK(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 lX="shared_prefs/ReactNativeDevPrefs.xml",lY="debug_http_host",lZ="dev_server_https",lQ="RCT_jsLocation",l0="RCT_packager_scheme",l1="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",l2='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function l3(e){return void 0!==l4(e)}function l4(e){if(!e)return;let t=ds(e.metroHost),r=dd(e.metroPort),a="http",n=ds(e.bundleUrl);if(n){var i;let e;try{e=new m(n)}catch(e){throw new q("INVALID_ARGS",`Invalid runtime bundle URL: ${n}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=ds(e.hostname),r??=dd(e.port.length>0?Number(e.port):"https:"===(i=e.protocol)?443:"http:"===i?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function l8(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let n=l4(a);if(n){if("android"===t.platform)return void await l6(t,r,n);"ios"===t.platform&&"simulator"===t.kind&&await dt(t,r,n)}}async function l5(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await l9(t,r);"ios"===t.platform&&"simulator"===t.kind&&await dr(t,r)}}async function l6(e,t,r){var a,n,i,o,s,l;let d,u;dl(t);let c=(a=await l7(e,t),n=lY,i=`${r.host}:${r.port}`,d=` <string name="${du(n)}">${du(i)}</string>`,dn(di(a,n),d));o=c,s=lZ,l="https"===r.scheme,u=` <boolean name="${du(s)}" value="${l?"true":"false"}" />`,c=dn(di(o,s),u),await de(e,t,c)}async function l9(e,t){dl(t);let r=await l7(e,t),a=di(r,lY),n=di(a,lZ);n!==r&&await de(e,t,n)}async function l7(e,t){let r=await R("adb",aE(e,["shell","run-as",t,"cat",lX]),{allowFailure:!0});return 0!==r.exitCode?l2:da(r.stdout)}async function de(e,t,r){let a=aE(e,["shell","run-as",t,"id"]),n=await R("adb",a,{allowFailure:!0});if(0!==n.exitCode){let e=dc(n.stdout,n.stderr);throw new q("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,hint:e?l1:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await R("adb",aE(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await R("adb",aE(e,["shell","run-as",t,"tee",lX]),{stdin:r.trimEnd()})}catch(a){let e=G(a);if("TOOL_MISSING"===e.code)throw e;let r=dc("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new q("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?l1:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function dt(e,t,r){await R("xcrun",e7(e,["spawn",e.id,"defaults","write",t,lQ,"-string",`${r.host}:${r.port}`])),await R("xcrun",e7(e,["spawn",e.id,"defaults","write",t,l0,"-string",r.scheme]))}async function dr(e,t){await R("xcrun",e7(e,["spawn",e.id,"defaults","delete",t,lQ]),{allowFailure:!0}),await R("xcrun",e7(e,["spawn",e.id,"defaults","delete",t,l0]),{allowFailure:!0})}function da(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
38
|
-
`:
|
|
39
|
-
</map>`)}function
|
|
40
|
-
${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}let dp=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function df(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function dm(e){let t=e?.trim();return t&&t.length>0?t:void 0}function dh(e,t){if(void 0!==e){if("string"!=typeof e)throw new q("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return dm(e)}}function dw(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new q("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function dg(e){if("ios"===e||"android"===e)return e}async function dy(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:n}=e;!t||!n?.appBundleId||!l3(r)||l3(a)||await l5({device:n.device,appId:n.appBundleId})}async function dv(e){var t,r;let{req:a,sessionName:n,sessionStore:i}=e,o=(a.positionals?.[0]??"show").toLowerCase(),s=i.get(n),l=i.getRuntimeHints(n);if(!["set","show","clear"].includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===o){l3(l)&&s?.appBundleId&&await l5({device:s.device,appId:s.appBundleId});let e=i.clearRuntimeHints(n);return{ok:!0,data:{session:n,cleared:e}}}if("show"===o)return{ok:!0,data:{session:n,configured:!!l,runtime:l}};let d=dg(a.flags?.platform??l?.platform??s?.device.platform);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first."}};if(s&&s.device.platform!==d)return{ok:!1,error:{code:"INVALID_ARGS",message:`runtime set targets ${d}, but session "${n}" is already bound to ${s.device.platform}.`}};let u={platform:(t=a.flags,r={platform:d,metroHost:dm(t?.metroHost),metroPort:dw(t?.metroPort),bundleUrl:dm(t?.bundleUrl),launchUrl:dm(t?.launchUrl)}).platform??l?.platform,metroHost:r.metroHost??l?.metroHost,metroPort:r.metroPort??l?.metroPort,bundleUrl:r.bundleUrl??l?.bundleUrl,launchUrl:r.launchUrl??l?.launchUrl};return 0===df(u)?{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."}}:(i.setRuntimeHints(n,u),{ok:!0,data:{session:n,configured:!0,runtime:u}})}let dI="open-command-roundtrip",dA="Not implemented for this platform in this release.";async function db(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await ox();return{appBundleId:t.bundleId,appName:t.appName}}let dS=[250,400];function d_(e,t,r=e.snapshot){if("android"!==e.device.platform)return;let a=r?.comparisonSafe===!0;e.androidSnapshotFreshness={action:t,markedAt:Date.now(),baselineCount:r?.nodes.length??0,baselineSignatures:a?dk(r?.nodes??[]):void 0,routeComparable:a}}function dN(e){if(!e||"android"!==e.device.platform)return;let t=e.androidSnapshotFreshness;if(t)return Date.now()-t.markedAt>2500?void delete e.androidSnapshotFreshness:t}function dD(e){e&&"android"===e.device.platform&&delete e.androidSnapshotFreshness}function dx(e){return"press"===e||"click"===e||"back"===e||"open"===e}function dk(e){return e.map(e=>[e.depth??0,e.type??"",e.role??"",e.label??"",e.value??"",e.identifier??"",!1===e.enabled?"disabled":"enabled",!0===e.selected?"selected":"unselected",!0===e.hittable?"hittable":"not-hittable"].join("|"))}function dM(e,t){return!(e<12)&&t<=Math.floor(.2*e)}async function dE(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return aP(t)?"macos"===e.platform?void 0:"device"===e.kind?aR(r,t):void 0:await dO(e,t)}async function dO(e,t){try{let{resolveIosApp:r}=await Promise.resolve(eM);return await r(e,t)}catch{return}}async function dL(e,t){if(!("android"!==e.platform||!t||aP(t)))try{let{resolveAndroidApp:r}=await Promise.resolve(eD),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function dC(e,t,r,a){return await dE(e,t,r)??await a(e,t)??("android"===e.platform&&t&&aP(t)?r:void 0)}function dP(e){return{ok:!1,error:{code:"INVALID_ARGS",message:e}}}function dR(e,t,r,a){try{return function(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:n}=e;if("macos"===t.platform&&!r)return n??"app";if("macos"!==t.platform){if(r)throw new q("INVALID_ARGS","surface is only supported on macOS");return"app"}let i=r?e_(r):"app";if("app"!==i&&"menubar"!==i&&a)throw new q("INVALID_ARGS",`open --surface ${i} does not accept an app target`);return i}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return{ok:!1,error:{code:e instanceof q?e.code:"INVALID_ARGS",message:String(e.message)}}}}function dT(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:n}=e;return t?r&&aP(r)?dP("open --relaunch does not support URL targets."):"app"!==a?dP("open --relaunch is supported only for app surfaces."):"android"===n.platform&&r&&"binary"===a4(r)?dP(a8(r)):null:null}async function d$(e){let{req:t,sessionName:r,sessionStore:a,device:n,surface:i,openTarget:o,existingSession:s}=e;await lx(n);let{appBundleId:l,appName:d}=await dF({device:n,surface:i,openTarget:o,existingAppBundleId:s?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:n}=e,i=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new q("INVALID_ARGS","open runtime must be an object.");let n=Object.keys(t).find(e=>!dp.includes(e));if(n)throw new q("INVALID_ARGS",`Invalid open runtime field: ${n}. Supported fields are ${dp.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new q("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new q("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:dh(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new q("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return dw(e)}}(t.metroPort),bundleUrl:dh(t.bundleUrl,"bundleUrl"),launchUrl:dh(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:dg(n.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let n=r?.platform,i=dg(n);if(a.platform&&r&&!i)throw new q("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${n}.`);if(a.platform&&i&&a.platform!==i)throw new q("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${n}. Clear the runtime hints or use a different session.`);return i&&a.platform!==i?{...a,platform:i}:a}(r,a,n),previousRuntime:i,replacedStoredRuntime:!1}:{runtime:o&&df(o)>0?o:void 0,previousRuntime:i,replacedStoredRuntime:!0}}(e)}}catch(t){let e=G(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}({req:t,sessionStore:a,sessionName:r,device:n});if(!u.ok)return{type:"response",response:u.response};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await dy({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function dF(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:n}=e,i=await db(r);return{appBundleId:i.appBundleId??await dC(t,a,n,dL),appName:i.appName??a}}let dU=new Map;async function dV(e){let{device:t,closeTarget:r,outFlag:a,context:n}=e;"android"!==t.platform&&await t1(t.id),await lo(t,"close",[r],a,n),await lW(t,lG)}async function dG(e){let{runtime:t,device:r,req:a,logPath:n,appBundleId:i,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let d=s[0]?.trim();!d||aP(d)||await lo(r,"open",[l],a.flags?.out,{...lN(n,a.flags,i,o)})}async function dB(e){var t,r,a;let{req:n,sessionName:i,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:p,appBundleId:f,runtime:m,existingSession:h}=e,w=n.flags?.relaunch===!0,g=h?.trace?.outPath;if(w&&d){let e=f??d;await dV({device:l,closeTarget:e,outFlag:n.flags?.out,context:{...lN(s,n.flags,f??h?.appBundleId,g)}})}await l8({device:l,appId:f,runtime:m});let y=Date.now();await lo(l,"open",u,n.flags?.out,{...lN(s,n.flags,f)}),await dG({runtime:m,device:l,req:n,logPath:s,appBundleId:f,traceLogPath:g,openPositionals:u});let v=d?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:dI,appTarget:d,appBundleId:f}:void 0;if(await lW(l,lB),eJ(n.meta?.requestId)){let e=eX();return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}h&&d_(h,"open",h.snapshot);let I=function(e){let{existingSession:t,sessionName:r,device:a,surface:n,appBundleId:i,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:n,appBundleId:i,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:n,appBundleId:i,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:i,device:l,surface:p,appBundleId:f,appName:c,saveScript:!!n.flags?.saveScript});void 0!==n.runtime&&(t=o,r=i,(a=m)&&(0===df(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let A=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:n,startup:i,device:o,runtime:s,runtimeHintCount:l}=e,d={session:t,surface:n};return r&&(d.appName=r),a&&(d.appBundleId=a),i&&(d.startup=i),s&&l(s)>0&&(d.runtime=s),o&&(d.platform=o.platform,d.target=o.target??"mobile",d.device=o.name,d.id=o.id,d.kind=o.kind,"android"===o.platform&&(d.serial=o.id)),o?.platform==="ios"&&(d.device_udid=o.id,d.ios_simulator_device_set=o.simulatorSetPath??null),{...d,...el(`Opened: ${r??a??t}`)}}({sessionName:i,appName:c,appBundleId:f,surface:p,startup:v,device:l,runtime:m,runtimeHintCount:df});return o.recordAction(I,{command:"open",positionals:u,flags:n.flags??{},runtime:void 0!==n.runtime?m:void 0,result:A}),o.set(i,I),{ok:!0,data:A}}async function dj(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e;if(n.has(r)){let e=n.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:`Session "${r}" not found.`}};let i=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(i?e.appName:void 0),l=dR(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return i?dP("open --relaunch requires an app name or an active session app."):dP("Session already active. Close it first or pass a new --session name.");let d=dT({shouldRelaunch:i,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await lJ(e.device),c=await d$({req:t,sessionName:r,sessionStore:n,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await dB({req:t,sessionName:r,sessionStore:n,logPath:a,device:u,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let i=t.flags?.relaunch===!0,o=t.positionals?.[0];if(i&&!o)return dP("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&aP(r)?dP("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===a4(r)?dP(a8(r)):null:null}({shouldRelaunch:i,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await li(t.flags??{}),d=dR(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=dT({shouldRelaunch:i,openTarget:o,surface:d,device:l});return u||await tA(dU,l.id,async()=>{let e=n.toArray().find(e=>e.device.id===l.id);if(e)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${e.name}".`,details:{session:e.name,deviceId:l.id,deviceName:l.name}}};let i=await d$({req:t,sessionName:r,sessionStore:n,device:l,surface:d,openTarget:o});return"response"===i.type?i.response:await dB({req:t,sessionName:r,sessionStore:n,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:i.details.appBundleId,appName:i.details.appName,runtime:i.details.runtime,surface:d})})}async function dq(e){let t=await R("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function dH(e){let{device:t,shutdownRequested:r}=e;if(r&&(lH(t)||"android"===t.platform&&"emulator"===t.kind))try{return lH(t)?await oo(t):await dq(t)}catch(t){let e=ee(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function dW(e){if(await t1(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await oE("dismiss",t).catch(t=>{ed({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function dz(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,i=n.get(r);if(!i)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};i.appLog&&await r0(i.appLog),t.positionals&&t.positionals.length>0&&(("ios"===i.device.platform||"macos"===i.device.platform)&&await dW(i),await lo(i.device,"close",t.positionals,t.flags?.out,{...lN(a,t.flags,i.appBundleId,i.trace?.outPath)}),await lW(i.device,lG)),("ios"===i.device.platform||"macos"===i.device.platform)&&await dW(i),l3(n.getRuntimeHints(r))&&i.appBundleId&&await l5({device:i.device,appId:i.appBundleId}).catch(()=>{}),n.recordAction(i,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...el(`Closed: ${r}`)}}),t.flags?.saveScript&&(i.recordSession=!0),n.writeSessionLog(i),await lR(r).catch(()=>{}),n.delete(r);let o=await dH({device:i.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:j({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...el(`Closed: ${r}`)}}}function dJ(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}let dK={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve(eM);return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve(eD);return await a(e,t,r)}},dX={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve(eM),n=await a(e,r,{appIdentifierHint:t});return{bundleId:n.bundleId,appName:n.appName,launchTarget:n.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await Promise.resolve(eD),n=await a(e,r);return{package:n.packageName,appName:n.appName,launchTarget:n.launchTarget}}};async function dY(e){let{req:t,command:r,sessionName:a,sessionStore:n,deployOps:i}=e,o=n.get(a),l=t.flags??{},d=lj(r,o,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return dJ("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let p=t.meta?.uploadedArtifactId;try{var f;let e,a=p?r5(p,t.meta?.tenantId):rg.expandHome(c);if(!s.existsSync(a))return dJ("INVALID_ARGS",`App binary not found: ${a}`);let d=await lz({session:o,flags:l,ensureReady:!1});if(!l_(r,d))return dJ("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await i.ios(d,u,a),r=t.bundleId;e=r?{app:u,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await i.android(d,u,a),r=t.package;e=r?{app:u,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=j(e,(f=e,`Installed: ${f.appName??$(f)}`));return o&&n.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{p&&r6(p)}}let dZ=["platform","target","device","udid","serial","verbose","out"];async function dQ(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${a}.`}};let n=e.flags?.batchMaxSteps??ef;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 a=P(e.flags?.batchSteps,n),i=Date.now(),o=[];for(let n=0;n<a.length;n+=1){let i=a[n],s=await d0(e,t,i,r,n+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${i.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:i.command,positionals:i.positionals,executed:n,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-i,results:o}}}catch(t){let e=G(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function d0(e,t,r,a,n){let i=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:n,...i}=t??{},o=e??{};for(let e of dZ)void 0===i[e]&&void 0!==o[e]&&(i[e]=o[e]);return i}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-i;return s.ok?{ok:!0,step:n,result:{step:n,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:n,error:s.error}}async function d1(e){let t,r,a,{deviceName:n,runtime:i,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new q("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await d2({deviceName:n,runtime:i,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await d3({deviceName:n,runtime:i,simctlOpts:u})).udid,r=await d4(t,u),a=!0)}else t=(await d3({deviceName:n,runtime:i,simctlOpts:u})).udid,r=await d4(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:n,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:n,runtime:r,created:a,booted:c}}async function d2(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,n=await R("xcrun",e9(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:i0});if(0!==n.exitCode)return null;try{let e=JSON.parse(String(n.stdout??""));for(let[a,n]of Object.entries(e.devices??{}))if(!r||d8(a).includes(d8(r))){for(let e of n)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function d3(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,n=r?["create",t,t,r]:["create",t,t],i=await R("xcrun",e9(n,a),{allowFailure:!0});if(0!==i.exitCode)throw new q("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(i.stdout??""),stderr:String(i.stderr??""),exitCode:i.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(i.stdout??"").trim();if(!o)throw new q("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(i.stdout??""),stderr:String(i.stderr??"")});return{udid:o}}async function d4(e,t){let r=await R("xcrun",e9(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:i0});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function d8(e){return e.toLowerCase().replace(/[._-]/g,"")}async function d5(e){let{req:t,sessionName:r,sessionStore:a}=e;if("session_list"===t.command)return{ok:!0,data:{sessions:a.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",surface:e.surface??"app",device:e.device.name,id:e.device.id,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("ensure-simulator"===t.command)try{let e=t.flags??{},r=e.device,a=e.runtime,n=e8(e.iosSimulatorDeviceSet);if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let i=await d1({deviceName:r,runtime:a,simulatorSetPath:n,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:lx});return{ok:!0,data:{udid:i.udid,device:i.device,runtime:i.runtime,ios_simulator_device_set:n??null,created:i.created,booted:i.booted}}}catch(t){let e=G(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===t.command)try{let e=[],r=e6(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,n=t_({simulatorSetPath:e8(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await Promise.resolve(eN);e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await Promise.resolve(ek);e.push(...await t({simulatorSetPath:n}))}else{if("apple"!==a){let{listAndroidDevices:t}=await Promise.resolve(eN);try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await Promise.resolve(ek);try{e.push(...await t({simulatorSetPath:n}))}catch{}}let i="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?i.filter(e=>(e.target??"mobile")===t.flags?.target):i).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=G(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===t.command){let e=a.get(r),n=t.flags??{},i=lj(t.command,e,n);if(i)return i;let o=await lz({session:e,flags:n,ensureReady:!0});if(!l_("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(tb(o.platform)){let{listIosApps:e}=await Promise.resolve(eM);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(eD);return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function d6(e){let{ensureAndroidEmulatorBooted:t}=await Promise.resolve(eN);return await t(e)}let d9='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',d7='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function ue(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r),i=t.flags??{},o=i.platform;if(!n&&"string"==typeof i?.session&&i.session.trim().length>0)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"ios"===o?`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 s=lj("appstate",n,i);if(s)return s;let l=(n?.device.platform==="ios"||n?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!lq(e))return!0;let r=e?.platform;return!(r&&!tS(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(i,n);if("ios"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:d9}};if("macos"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:d7}};if(l&&n){let e=n.appName??n.appBundleId;if(!n.appName&&!n.appBundleId){if("macos"===n.device.platform&&n.surface&&"app"!==n.surface&&"frontmost-app"!==n.surface)return{ok:!0,data:{platform:n.device.platform,appName:n.surface,appBundleId:n.appBundleId,source:"session",surface:n.surface}};let e="macos"===n.device.platform?"macOS":"iOS";return{ok:!1,error:{code:"COMMAND_FAILED",message:`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`}}}return{ok:!0,data:{platform:n.device.platform,appName:e??"unknown",appBundleId:n.appBundleId,source:"session",surface:n.surface??"app",..."ios"===n.device.platform?{device_udid:n.device.id,ios_simulator_device_set:n.device.simulatorSetPath??null}:{}}}}let d=await lz({session:n,flags:i,ensureReady:!0});if("ios"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:d9}};if("macos"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:d7}};let{getAndroidAppState:u}=await Promise.resolve(eD),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function ut(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,n=a.get(r),i=t.flags??{},o=lj(t.command,n,i);if(o)return o;let s="android"===(i.platform??n?.device.platform),l=!0===i.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=lK({flags:i,sessionDevice:n?.device}),u=s&&!!d,c=!1;try{e=await lz({session:n,flags:i,ensureReady:!1})}catch(r){let t=G(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 d6({avdName:d,serial:i.serial,headless:l}),c=!0}if(i.target&&(e.target??"mobile")!==i.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${i.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=lK({flags:i,sessionDevice:n?.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 d6({avdName:t,serial:i.serial,headless:!0})}await lx(e)}else("android"!==e.platform||!0!==e.booted)&&await lx(e);return l_("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"}}}return"appstate"===t.command?await ue({req:t,sessionName:r,sessionStore:a}):null}let ur="adb-shell-dumpsys-cpuinfo",ua="adb-shell-dumpsys-meminfo";async function un(e,t){try{let r=await R("adb",aE(e,["shell","dumpsys","cpuinfo"]),{timeoutMs:15e3});return function(e,t,r){var a,n,i;let o=new Set,s=0;for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let i=e.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!i)continue;let l=Number(i[1]),d=i[2];Number.isFinite(l)&&(a=d,n=t,a===n||a.startsWith(`${n}:`))&&(s+=l,o.add(d))}return{usagePercent:(i=s,Math.round(10*i)/10),measuredAt:r,method:ur,matchedProcesses:[...o]}}(r.stdout,t,new Date().toISOString())}catch(e){throw uo("cpu",t,e)}}async function ui(e,t){try{let r=await R("adb",aE(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new q("COMMAND_FAILED",`Android meminfo did not find a running process for ${t}`,{metric:"memory",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf."});let a=us(e,"TOTAL PSS")??function(e){for(let t of e.split("\n")){let e=t.trim();if(!/^TOTAL\b(?!\s+PSS:)/.test(e))continue;let r=e.split(/\s+/).slice(1).find(e=>null!==ul(e));if(!r)break;return ul(r)??void 0}}(e);if(void 0===a)throw new q("COMMAND_FAILED",`Failed to parse Android meminfo output for ${t}`,{metric:"memory",package:t,hint:"Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging."});return{totalPssKb:a,totalRssKb:us(e,"TOTAL RSS"),measuredAt:r,method:ua}}(r.stdout,t,new Date().toISOString())}catch(e){throw uo("memory",t,e)}}function uo(e,t,r){return r instanceof q&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new q(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof q?r:new q("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function us(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return ul(a[1])??void 0}function ul(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let ud="ps-process-snapshot",uu="ps-process-snapshot",uc="CPU and memory sampling are not yet implemented for physical iOS devices.";async function up(e,t){if("ios"===e.platform&&"device"===e.kind)throw new q("UNSUPPORTED_OPERATION",uc,{platform:e.platform,deviceKind:e.kind,appBundleId:t,hint:"Use an iOS simulator or macOS app session for CPU/memory perf sampling for now."});let r=await uf(e,t),a=await uw(e,r);if(0===a.length)throw new q("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,hint:"Run open <app> for this session again to ensure the Apple app is active, then retry perf."});let n=new Date().toISOString(),i=rt(a.map(e=>c.basename(ug(e.command))));return{cpu:{usagePercent:Math.round(10*a.reduce((e,t)=>e+t.cpuPercent,0))/10,measuredAt:n,method:ud,matchedProcesses:i},memory:{residentMemoryKb:Math.round(a.reduce((e,t)=>e+t.rssKb,0)),measuredAt:n,method:uu,matchedProcesses:i}}}async function uf(e,t){let r="macos"===e.platform?await um(t):await uh(e,t),a="macos"===e.platform?c.join(r,"Contents","Info.plist"):c.join(r,"Info.plist"),n=await ol(a,"CFBundleExecutable");if(!n)throw new q("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:n,executablePath:"macos"===e.platform?c.join(r,"Contents","MacOS",n):void 0}}async function um(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await R("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new q("COMMAND_FAILED",`Failed to resolve macOS app bundle for ${e}`,{appBundleId:e,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let a=r.stdout.split("\n").map(e=>e.trim()).find(e=>e.endsWith(".app"));if(!a)throw new q("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function uh(e,t){let r=e7(e,["get_app_container",e.id,t,"app"]),a=await R("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new q("COMMAND_FAILED",`Failed to resolve iOS simulator app container for ${t}`,{appBundleId:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Ensure the iOS simulator app is installed and booted, then retry perf."});let n=a.stdout.trim();if(0===n.length)throw new q("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return n}async function uw(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:e7(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let a=e.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!a)continue;let n=Number(a[1]),i=Number(a[2]),o=Number(a[3]),s=a[4].trim();Number.isFinite(n)&&Number.isFinite(i)&&Number.isFinite(o)&&t.push({pid:n,cpuPercent:i,rssKb:o,command:s})}return t})((await R("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let n;return r=e.command,a=t,n=ug(r),!!(a.executablePath&&(n===a.executablePath||r.startsWith(`${a.executablePath} `)))||c.basename(n)===a.executableName})}function ug(e){let[t=""]=e.trim().split(/\s+/,1);return t}async function uy(e){var t,r;let a=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===dI&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:dI,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)}(e.actions),n=a.at(-1),i=n?{available:!0,lastDurationMs:n.durationMs,lastMeasuredAt:n.measuredAt,method:dI,sampleCount:a.length,samples:a}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:dI},o={session:e.name,platform:e.device.platform,device:e.device.name,deviceId:e.device.id,metrics:{startup:i,fps:{available:!1,reason:dA},memory:{available:!1,reason:dA},cpu:{available:!1,reason:dA}},sampling:{startup:{method:dI,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"},...function(e){if("android"===e.device.platform)return{memory:{method:ua,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:ur,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"}};var t=e.device;if("ios"===t.platform&&"device"===t.kind)return{memory:{method:uu,description:uc,unit:"kB"},cpu:{method:ud,description:uc,unit:"percent"}};let r="macos"===t.platform?"host ps for the running macOS app executable resolved from the bundle ID.":"xcrun simctl spawn ps for the running iOS simulator app executable resolved from the bundle ID.";return{memory:{method:uu,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:ud,description:`Recent CPU usage snapshot from ${r}`,unit:"percent"}}}(e)}};if("android"!==(t=e).device.platform&&"ios"!==t.device.platform&&"macos"!==t.device.platform)return o;if("ios"===(r=e).device.platform&&"device"===r.device.kind)return o.metrics.memory={available:!1,reason:uc},o.metrics.cpu={available:!1,reason:uc},o;if(!e.appBundleId){let t="android"===e.device.platform?"No Android app package is associated with this session. Run open <app> first.":"No Apple app bundle ID is associated with this session. Run open <app> first.";return o.metrics.memory={available:!1,reason:t},o.metrics.cpu={available:!1,reason:t},o}let[s,l]=await uv(e);return o.metrics.memory=uI(s),o.metrics.cpu=uI(l),o}async function uv(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,a]=await Promise.allSettled([ui(e.device,t),un(e.device,t)]);return[r,a]}try{let r=await up(e.device,t);return[{status:"fulfilled",value:r.memory},{status:"fulfilled",value:r.cpu}]}catch(e){return[{status:"rejected",reason:e},{status:"rejected",reason:e}]}}function uI(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=ee(e.reason);return{available:!1,reason:t.message,error:t}}let uA=["path","start","stop","doctor","mark","clear"],ub=`logs requires ${uA.slice(0,-1).join(", ")}, or ${uA.at(-1)}`,uS=["dump","log"],u_=`network requires ${uS.join(" or ")}`,uN=["summary","headers","body","all"],uD=`network include mode must be one of: ${uN.join(", ")}`;async function ux(e){let{req:t}=e;return"perf"===t.command?uk(e):"logs"===t.command?uM(e):"network"===t.command?uP(e):null}async function uk(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}};try{return{ok:!0,data:await uy(a)}}catch(e){return{ok:!1,error:ee(e)}}}async function uM(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!l_("logs",n.device))return{ok:!1,error:ee(new q("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let i=(t.positionals?.[0]??"path").toLowerCase(),o=!!t.flags?.restart;return uA.includes(i)?o&&"clear"!==i?{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}}:"path"===i?function(e,t,r){let a=r.resolveAppLogPath(t),n=function(e){if(!s.existsSync(e))return{exists:!1,sizeBytes:0};let t=s.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(a);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android",sizeBytes:n.sizeBytes,modifiedAt:n.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>'}}}(n,r,a):"doctor"===i?uE(n,r,a):"mark"===i?function(e,t,r){let a,n=e.positionals?.slice(1).join(" ")??"",i=r.resolveAppLogPath(t);return rX(i),a=`[agent-device][mark][${new Date().toISOString()}] ${n.trim()||"marker"}
|
|
41
|
-
`,s.appendFileSync(i,a,"utf8"),{ok:!0,data:{path:i,marked:!0}}}(t,r,a):"clear"===i?uO(n,r,a,o):"start"===i?uL(n,r,a):"stop"===i?uC(n,r,a):{ok:!1,error:{code:"INVALID_ARGS",message:ub}}:{ok:!1,error:{code:"INVALID_ARGS",message:ub}}}async function uE(e,t,r){let a=r.resolveAppLogPath(t),n=await r1(e.device,e.appBundleId);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:n.checks,notes:n.notes}}}async function uO(e,t,r,a){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&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let n=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:r2(n)};e.appLog&&await r0(e.appLog);let i=r2(n),o=r.resolveAppLogPidPath(t);try{let a=await rZ(e.device,e.appBundleId,n,o);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:n,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}}),{ok:!0,data:{...i,restarted:!0}}}catch(a){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:ee(a)}}}async function uL(e,t,r){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};let a=r.resolveAppLogPath(t),n=r.resolveAppLogPidPath(t);try{let i=await rZ(e.device,e.appBundleId,a,n);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:i.backend,outPath:a,startedAt:i.startedAt,getState:i.getState,stop:i.stop,wait:i.wait}}),{ok:!0,data:{path:a,started:!0}}}catch(e){return{ok:!1,error:ee(e)}}}async function uC(e,t,r){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let a=e.appLog.outPath;return await r0(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function uP(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!l_("network",n.device))return{ok:!1,error:ee(new q("UNSUPPORTED_OPERATION","network is not supported on this device"))};let i=(t.positionals?.[0]??"dump").toLowerCase();if(!uS.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:u_}};let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],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=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"network include mode was provided both positionally and via --include with different values"}}};let a=(r??t??"summary").toLowerCase();return uN.includes(a)?{ok:!0,include:a}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:uD}}}}(t);if(!s.ok)return s.response;let{include:l}=s,d=await rY({device:n.device,appBundleId:n.appBundleId,appLogState:n.appLog?.getState(),appLogStartedAt:n.appLog?.startedAt,appLogPath:a.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...d.dump,active:!!n.appLog,state:n.appLog?.getState()??"inactive",backend:d.backend,notes:d.notes}}}let uR=new Set(["ios","android","macos"]);function uT(e,t,r){let a=e[t];if(void 0!==a)throw new q("INVALID_ARGS",a===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(a)} vs ${String(r)}.`);e[t]=r}function u$(e){return!!e&&!Number.isNaN(Number(e))}let uF=/[*?[\]{}]/;async function uU(e){let t,{filePath:r,sessionName:a,requestId:n,timeoutMs:i,platform:o,runReplay:s,cleanupSession:l}=e;eH(n);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:n,artifactPaths:d}).catch(e=>{let t=G(e);return{ok:!1,error:{code:t.code,message:t.message}}}).finally(()=>{ez(n)});try{return"number"==typeof i?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,eW(n),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(i,[...d]))},i)})]):await c}finally{t&&clearTimeout(t),u&&(await uV(c)||ed({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:n,graceMs:2e3}}));try{await l(a)}catch(e){ed({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:G(e).message}})}}}async function uV(e){return await Promise.race([e.then(()=>!0),b(2e3).then(()=>!1)])}async function uG(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:n}=e;if((t.positionals?.length??0)===0)return{ok:!1,error:{code:"INVALID_ARGS",message:"test requires at least one path or glob"}};try{var i,o,l,d,u,p;let e,f,m,h,w,g=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,n=r??process.cwd(),i=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let n=rg.expandHome(e,t);if(s.existsSync(n)){let t=s.statSync(n);if(t.isDirectory())return s.globSync("**/*.ad",{cwd:n}).map(e=>c.join(n,e));if(t.isFile()){if(".ad"!==c.extname(n))throw new q("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[n]}return[]}if(r=e,!uF.test(r)&&(a=n,!uF.test(a)))throw new q("INVALID_ARGS",`test input not found: ${e}`);let i=c.isAbsolute(n)?n:e;return s.globSync(i,{cwd:c.isAbsolute(n)?void 0:t}).map(e=>c.isAbsolute(e)?e:c.resolve(t,e)).filter(e=>".ad"===c.extname(e)&&function(e){try{return s.statSync(e).isFile()}catch{return!1}}(e))})(e,n)))].map(e=>c.normalize(e)).sort((e,t)=>e.localeCompare(t)),o=[];for(let e of i){var l,d;let t=function(e){let t=e.split(/\r?\n/),r={};for(let e of t){let t=e.trim();if(0===t.length||t.startsWith("#"))continue;if(!t.startsWith("context "))break;let a=t.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&uR.has(e)&&uT(r,"platform",e)}let n=t.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&uT(r,"timeoutMs",Math.floor(e))}let i=t.match(/(?:^|\s)retries=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=0&&uT(r,"retries",Math.floor(e))}}return r}(s.readFileSync(e,"utf8"));if(!a){o.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){o.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${a}`});continue}l=a,d=t.platform,("apple"===l?"apple"===d||"ios"===d||"macos"===d:d===l)&&o.push({kind:"run",path:e,metadata:t})}if(0===o.filter(e=>"run"===e.kind).length){let e=a?` for --platform ${a}`:"";throw new q("INVALID_ARGS",`No .ad tests matched${e}.`)}return o}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),y=(i=t.meta?.requestId,(i?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),v=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:a}=e,n=rg.expandHome(t??".agent-device/test-artifacts",r);return c.join(n,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),I=[],A=Date.now(),b=0;for(let e of g){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}b+=1;let i=await uB({entry:e,sessionName:r,suiteInvocationId:y,caseIndex:b-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(o=t.flags?.timeoutMs,l=e.metadata.timeoutMs,"number"==typeof o?o:l),suiteArtifactsDir:v,runReplay:a,cleanupSession:n});if(I.push(i),t.flags?.failFast===!0)break}let S=(d=g.length,u=I,p=Date.now()-A,e=u.filter(e=>"passed"===e.status).length,m=(f=u.filter(e=>"failed"===e.status)).length,h=u.filter(e=>"skipped"===e.status).length,w=e+m,{total:d,executed:w,passed:e,failed:m,skipped:h,notRun:Math.max(0,d-w-h),durationMs:p,failures:f,tests:u});return{ok:!0,data:S}}catch(t){let e=G(t);return{ok:!1,error:{code:e.code,message:e.message}}}}async function uB(e){var t,r;let a,n,{entry:i,sessionName:o,suiteInvocationId:l,caseIndex:d,cwd:u,requestId:p,retries:f,timeoutMs:m,suiteArtifactsDir:h,runReplay:w,cleanupSession:g}=e,y=Date.now(),v=c.join(h,(t=i.path,(0===(n=u?c.relative(u,t):c.basename(t)).length||n.startsWith("..")?c.basename(t):n).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",A=0;for(let e=0;e<=f;e+=1){A=e+1;let t=function(e,t,r,a,n=0){let i=c.basename(r,c.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${i?`-${i}`:""}:attempt-${n+1}`}(o,l,i.path,d,e),n=c.join(v,`attempt-${A}`);r=i.path,s.mkdirSync(n,{recursive:!0}),s.copyFileSync(r,c.join(n,"replay.ad"));let u=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:n,attemptIndex:i}=e;return eq(`${t??r}:test:${n+1}:${c.basename(a)}:attempt:${i+1}`,r)}({requestId:p,suiteInvocationId:l,filePath:i.path,caseIndex:d,attemptIndex:e}),h=await uU({filePath:i.path,sessionName:t,requestId:u,timeoutMs:m,platform:i.metadata.platform,runReplay:w,cleanupSession:g});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:n,maxAttempts:i,attemptArtifactsDir:o}=e,l=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||l.push(t.error.logPath);let d=function(e,t){let r=[],a=new Map;for(let n of e){if(!function(e){try{return s.statSync(e).isFile()}catch{return!1}}(n))continue;let e=function(e,t){let r=c.extname(e),a=r?e.slice(0,-r.length):e,n=t.get(e)??0;return(t.set(e,n+1),0===n)?e:`${a}-${n+1}${r}`}(c.basename(n),a),i=c.join(t,e);c.resolve(n)!==c.resolve(i)&&s.copyFileSync(n,i),r.push(i)}return r}(l,o),u=[`file: ${r}`,`session: ${a}`,`attempt: ${n}/${i}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;u.push(`replayed: ${e}`,`healed: ${r}`)}else u.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&u.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&u.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&u.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&u.push("timeoutMode: cooperative");d.length>0&&u.push(`copiedArtifacts: ${d.map(e=>c.basename(e)).join(", ")}`);let p=c.join(o,"result.txt"),f=`${u.join("\n")}
|
|
42
|
-
`;s.writeFileSync(p,f),t.ok||s.writeFileSync(c.join(o,"failure.txt"),f)}({response:h,filePath:i.path,sessionName:t,attempts:A,maxAttempts:f+1,attemptArtifactsDir:n}),a=h,I=t,h.ok)break}let b=Date.now()-y;if(a?.ok)return{file:i.path,session:I,status:"passed",durationMs:b,attempts:A,artifactsDir:v,replayed:"number"==typeof a.data?.replayed?a.data.replayed:0,healed:"number"==typeof a.data?.healed?a.data.healed:0};let S=a?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:a?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:i.path,session:I,status:"failed",durationMs:b,attempts:A,artifactsDir:v,error:S}}function uj(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),a=(e.value??"").toLowerCase(),n=(e.identifier??"").toLowerCase();return t.includes(r)||a.includes(r)||n.includes(r)})??null}function uq(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&&uH(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,a=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!uH(t))continue;let n=Math.abs(e.rect.y+e.rect.height/2-r);(!a||n<a.distance)&&(a={label:t,distance:n})}return a?.label}(e,t)??(r&&uH(r)?r:void 0)}function uH(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function uW(e){let t=[],r=[];for(let a of e){let e=a.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let n=uz(a.type??""),i=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!i&&uH(i);if(("group"===n||"ioscontentgroup"===n)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...a,depth:s})}return r}function uz(e){let t=e.trim().replace(/XCUIElementType/gi,"");t.startsWith("AX")&&(t=t.slice(2));let r=Math.max((t=t.toLowerCase()).lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function uJ(e,t){let r=uz(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 uK(e,t){if(t.hittable)return t;let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}function uX(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let uY=new Set(["id","role","text","label","value"]),uZ=new Set(["visible","hidden","editable","selected","enabled","hittable"]),uQ=new Set([...uY,...uZ]);function u0(e){let t=e.trim();if(!t)throw new q("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let n=0;n<e.length;n+=1){let i=e[n];if(('"'===i||"'"===i)&&!u6(e,n)){a=u8(a,i),r+=i;continue}if(!a&&"|"===i&&"|"===e[n+1]){let a=r.trim();if(!a)throw new q("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",n+=1;continue}r+=i}let n=r.trim();if(!n)throw new q("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(n),t}(t);if(0===r.length)throw new q("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new q("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let n=0;n<e.length;n+=1){let i=e[n];if(('"'===i||"'"===i)&&!u6(e,n)){a=u8(a,i),r+=i;continue}if(!a&&/\s/.test(i)){r.trim()&&t.push(r.trim()),r="";continue}r+=i}if(a)throw new q("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim()&&t.push(r.trim()),t}(t);if(0===r.length)throw new q("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(u4)}})(e))}}function u1(e){try{return u0(e)}catch{return null}}function u2(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,a=0,n=[];for(;a<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return uQ.has(e)}return uQ.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&u1(t)&&n.push(a)}if(0===n.length)return null;let i=n[n.length-1];if(r){for(let t=n.length-1;t>=0;t-=1)if(n[t]<e.length){i=n[t];break}}let o=e.slice(0,i).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(i)}:null}function u3(e){let t=e[0]??"",r=u2(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function u4(e){let t=e.trim();if(!t)throw new q("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!uZ.has(r))throw new q("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),n=t.slice(r+1).trim();if(!uQ.has(a))throw new q("INVALID_ARGS",`Unknown selector key: ${a}`);if(!n)throw new q("INVALID_ARGS",`Missing selector value for key: ${a}`);if(uZ.has(a)){let e,t="true"===(e=u5(n).toLowerCase())||"false"!==e&&null;if(null===t)throw new q("INVALID_ARGS",`Invalid boolean value for ${a}: ${n}`);return{key:a,value:t}}return{key:a,value:u5(n)}}function u8(e,t){return e?e===t?null:e:t}function u5(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function u6(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function u9(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return ct(e.identifier,String(t.value));case"role":return ct(uz(e.type??""),String(t.value));case"label":return ct(e.label,String(t.value));case"value":return ct(e.value,String(t.value));case"text":return ct(uX(e),String(t.value));case"visible":return u7(e)===!!t.value;case"hidden":return!u7(e)==!!t.value;case"editable":return ce(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 u7(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function ce(e,t){return uJ(e.type??"",t)&&!1!==e.enabled}function ct(e,t){return cr(e??"")===cr(t)}function cr(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function ca(e,t,r){let a=r.requireRect??!1,n=r.requireUnique??!0,i=[];for(let o=0;o<t.selectors.length;o+=1){let s=t.selectors[o],l=function(e,t,r,a){let n=0,i=null,o=null,s=!1;for(let l of e){if(a&&!l.rect||!u9(l,t,r))continue;if(n+=1,i??=l,!o){o=l;continue}let e=function(e,t){let r=e.depth??0,a=t.depth??0;if(r!==a)return r>a?1:-1;let n=co(e),i=co(t);return n!==i?n<i?1:-1:0}(l,o);e>0?(o=l,s=!1):0===e&&(s=!0)}return{count:n,firstNode:i,disambiguated:s?null:o}}(e,s,r.platform,a);if(i.push({selector:s.raw,matches:l.count}),0!==l.count&&l.firstNode){if(n&&1!==l.count){if(!r.disambiguateAmbiguous||!l.disambiguated)continue;return{node:l.disambiguated,selector:s,selectorIndex:o,matches:l.count,diagnostics:i}}return{node:l.firstNode,selector:s,selectorIndex:o,matches:l.count,diagnostics:i}}}return null}function cn(e,t,r){let a=r.requireRect??!1,n=[];for(let i=0;i<t.selectors.length;i+=1){let o=t.selectors[i],s=function(e,t,r,a){let n=0;for(let i of e)(!a||i.rect)&&u9(i,t,r)&&(n+=1);return n}(e,o,r.platform,a);if(n.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:i,selector:o,matches:s,diagnostics:n}}return null}function ci(e,t,r){if(0===t.length)return`Selector did not match: ${e.raw}`;let a=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return r.unique??!0?`Selector did not resolve uniquely (${a})`:`Selector did not match (${a})`}function co(e){return e.rect?e.rect.width*e.rect.height:1/0}function cs(e,t,r={}){let a=[],n=uz(e.type??""),i=cd(e.identifier),o=cd(e.label),s=cd(e.value),l=cd(uX(e)),d="fill"===r.action;i&&a.push(`id=${cl(i)}`),n&&o&&a.push(d?`role=${cl(n)} label=${cl(o)} editable=true`:`role=${cl(n)} label=${cl(o)}`),o&&a.push(d?`label=${cl(o)} editable=true`:`label=${cl(o)}`),s&&a.push(d?`value=${cl(s)} editable=true`:`value=${cl(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${cl(l)} editable=true`:`text=${cl(l)}`),n&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${cl(n)} editable=true`);let u=rt(a);return 0===u.length&&n&&u.push(d?`role=${cl(n)} editable=true`:`role=${cl(n)}`),0===u.length&&u7(e)&&u.push("visible=true"),u}function cl(e){return JSON.stringify(e)}function cd(e){if(!e)return null;let t=e.trim();return t||null}function cu(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=u2(r?e.slice(0,-1):e.slice());return!a||a.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:a.selectorExpression,selectorTimeout:r?t:null}}async function cc(e){let{action:t,sessionName:r,logPath:a,sessionStore:n}=e;if(!(ro(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let i=n.get(r);if(!i)return null;let o=(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),ro(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}=u3(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=cu(e.positionals??[]);r&&t.push(r)}return rt(t).filter(e=>e.trim().length>0)})(t).map(e=>u1(e)).filter(e=>null!==e);if(0===o.length)return null;let s=ro(t.command)||"fill"===t.command,l=ro(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await cp(i,t,a,s,n);for(let e of o){let r=ca(d.nodes,e,{platform:i.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=cs(r.node,i.device.platform,{action:ro(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(ro(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=re(t);if(!e)continue;return{...t,positionals:[a,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,a]}}if("is"===t.command){let{predicate:e,split:r}=u3(t.positionals);if(!e)continue;let n=r?.rest.join(" ").trim()??"",i=[e,a];return"text"===e&&n.length>0&&i.push(n),{...t,positionals:i}}if("wait"===t.command){let{selectorTimeout:e}=cu(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function cp(e,t,r,a,n){let i=await lo(e.device,"snapshot",[],t.flags?.out,{...lN(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=i?.nodes??[],s={nodes:eS(t.flags?.snapshotRaw?o:uW(o)),truncated:i?.truncated,createdAt:Date.now(),backend:i?.backend};return e.snapshot=s,n.set(e.name,e),s}let cf=["platform","target","device","udid","serial","verbose","out"];async function cm(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e,o=t.positionals?.[0];if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};let l="",d=new Set;try{l=rg.expandHome(o,t.meta?.cwd);let e=s.readFileSync(l,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let c=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,n=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!n)break;n="\\"===t&&!n,"\\"!==t&&(n=!1),a+=1}if(a>=e.length)throw new q("INVALID_ARGS",`Invalid replay script line: ${e}`);let i=e.slice(r,a+1);t.push(JSON.parse(i)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...n]=r;if("context"===a)return null;let i={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){i.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("-i"===t){i.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){i.flags.snapshotCompact=!0;continue}if("--raw"===t){i.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<n.length){let t=Number(n[e+1]);Number.isFinite(t)&&t>=0&&(i.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<n.length){i.flags.snapshotScope=n[e+1],e+=1;continue}if("--backend"===t&&e+1<n.length){e+=1;continue}}return i}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let n=rm(r);return{positionals:n.positionals,flags:a,runtime:(t=n.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?n.flags:void 0}}(n);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i.runtime=e.runtime,i}if("runtime"===a){let e=rm(n);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i}if(ro(a)){let e=rf(a,n);if(Object.assign(i.flags,e.flags),0===e.positionals.length)return i;let t=e.positionals[0];if(t.startsWith("@"))return i.positionals=[t],e.positionals[1]&&(i.result={refLabel:e.positionals[1]}),i;let r=e.positionals[0],o=e.positionals[1];return u$(r)&&u$(o)&&e.positionals.length>=2?i.positionals=[r,o]:i.positionals=[e.positionals.join(" ")],i}if("fill"===a){let e=rf(a,n);if(Object.assign(i.flags,e.flags),e.positionals.length<2)return i.positionals=e.positionals,i;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(i.positionals=[t,e.positionals.slice(2).join(" ")],i.result={refLabel:e.positionals[1]}):i.positionals=[t,e.positionals[1]],i):(i.positionals=[t,e.positionals.slice(1).join(" ")],i)}if("get"===a){if(n.length<2)return i.positionals=n,i;let e=n[0],t=n[1];return t.startsWith("@")?(i.positionals=[e,t],n[2]&&(i.result={refLabel:n[2]})):i.positionals=[e,n.slice(1).join(" ")],i}if("swipe"===a||"type"===a){let e=rf(a,n);return Object.assign(i.flags,e.flags),i.positionals=e.positionals,i}if("record"===a){let e=[];for(let t=0;t<n.length;t+=1){let r=n[t];if("--hide-touches"===r){i.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<n.length){let e=Number(n[t+1]);Number.isFinite(e)&&(i.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return i.positionals=e,i}if("screenshot"===a){let e=[];for(let t of n){if("--fullscreen"===t){i.flags.screenshotFullscreen=!0;continue}e.push(t)}return i.positionals=e,i}return i.positionals=n,i}(r);e&&t.push(e)}return t}(e),p=t.flags?.replayUpdate===!0,f=0;for(let e=0;e<c.length;e+=1){let o=c[e];if(!o||"replay"===o.command)continue;let s=await ch({req:t,sessionName:r,action:o,invoke:i});if(s.ok){cg(s).forEach(e=>d.add(e));continue}if(!p)return cw(s,o,e,l,[...d]);let u=await cc({action:o,sessionName:r,logPath:a,sessionStore:n});if(!u)return cw(s,o,e,l,[...d]);if(c[e]=u,!(s=await ch({req:t,sessionName:r,action:u,invoke:i})).ok)return cw(s,u,e,l,[...d]);cg(s).forEach(e=>d.add(e)),f+=1}return p&&f>0&&function(e,t,r){let a=[];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}`:"";a.push(`context platform=${r.device.platform}${n} device="${e}"${t} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",rl(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return rw(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(rd(r));return rc(t,e.flags),t.join(" ")}if("record"===e.command)return rp(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(rl(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}for(let r of e.positionals??[])t.push(rl(r));return ru(t,e),t.join(" ")}(e));let n=`${a.join("\n")}
|
|
43
|
-
`,i=`${e}.tmp-${process.pid}-${Date.now()}`;s.writeFileSync(i,n),s.renameSync(i,e)}(l,c,n.get(r)),{ok:!0,data:{replayed:c.length,healed:f,session:r,artifactPaths:[...d]}}}catch(t){let e=G(t);return{ok:!1,error:{code:e.code,message:e.message,details:d.size>0?{artifactPaths:[...d]}:void 0}}}}async function ch(e){let{req:t,sessionName:r,action:a,invoke:n}=e;return await n({token:t.token,session:r,command:a.command,positionals:a.positionals??[],flags:function(e,t){let r={...t??{}},a=e??{};for(let e of cf)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}(t.flags,a.flags),runtime:a.runtime,meta:t.meta})}function cw(e,t,r,a,n=[]){let i;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${i=(t.positionals??[]).map(e=>rl(e)),[t.command,...i].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:a,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:n}}}}function cg(e){if(!e.ok||!e.data)return[];let t=[];if("string"==typeof e.data.path&&t.push(e.data.path),"string"==typeof e.data.outPath&&t.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let r of e.data.artifacts){if(!r||"object"!=typeof r)continue;let e="string"==typeof r.localPath?r.localPath:void 0,a="string"==typeof r.path?r.path:void 0;e?t.push(e):a&&t.push(a)}return[...new Set(t.filter(e=>(function(e){try{return s.statSync(e).isFile()}catch{return!1}})(e)))]}async function cy(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e;return"replay"===t.command?await cm({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}):"test"===t.command?await uG({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await cm({req:{...t,command:"replay",session:r,positionals:[e],flags:void 0===o?t.flags:{...t.flags??{},platform:o},meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:n,invoke:async e=>{var t;return t=await i(e),l&&cg(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{n.get(e)&&await dz({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:n})}}):null}let cv=new Set(["session_list","ensure-simulator","devices","apps"]),cI=new Set(["boot","appstate"]),cA=new Set(["perf","logs","network"]),cb=new Set(["replay","test"]);async function cS(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,command:i,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=n.get(r),u=t.flags??{},c=lj(i,d,u);if(c)return c;let p=await lz({session:d,flags:u,ensureReady:!0});if(!l_(i,p))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${i} is not supported on this device`}};let f=await lo(p,i,o,t.flags?.out,{...lN(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,f,p):d;n.recordAction(e,{command:i,positionals:s??o,flags:t.flags??{},result:f??{}}),e!==d&&n.set(r,e)}return{ok:!0,data:f??{}}}async function c_(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,i=n.get(r),o=t.flags??{},s=lj("clipboard",i,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return{ok:!1,error:{code:"INVALID_ARGS",message:"clipboard requires a subcommand: read or write"}};let d=await lz({session:i,flags:o,ensureReady:!0});if(!l_("clipboard",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let u=await lo(d,"clipboard",t.positionals??[],t.flags?.out,{...lN(a,t.flags,i?.appBundleId,i?.trace?.outPath)});return i&&n.recordAction(i,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function cN(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e;if(cv.has(t.command))return await d5({req:t,sessionName:r,sessionStore:n});if("runtime"===t.command)return await dv({req:t,sessionName:r,sessionStore:n});if(cI.has(t.command))return await ut({req:t,sessionName:r,sessionStore:n});if("clipboard"===t.command)return await c_({req:t,sessionName:r,logPath:a,sessionStore:n});if("keyboard"===t.command){let e=n.get(r),i=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==i||"ios"!==(t.flags??{}).platform?await cS({req:t,sessionName:r,logPath:a,sessionStore:n,command:"keyboard",positionals:t.positionals??[]}):{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first."}}}if(cA.has(t.command))return await ux({req:t,sessionName:r,sessionStore:n});if("install"===t.command||"reinstall"===t.command)return await dY({req:t,command:t.command,sessionName:r,sessionStore:n,deployOps:"install"===t.command?dX:dK});if("install_source"===t.command)return await lF({req:t,sessionName:r,sessionStore:n});if("release_materialized_paths"===t.command)return await lV({req:t});if("push"===t.command){let e,i=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return i&&o?await cS({req:t,sessionName:r,logPath:a,sessionStore:n,command:"push",positionals:[i,"file"===(e=sW(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>rg.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[i,o]}):{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}}}return"trigger-app-event"===t.command?await cS({req:t,sessionName:r,logPath:a,sessionStore:n,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await dC(e.device,r,e.appBundleId,dL)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await dj({req:t,sessionName:r,logPath:a,sessionStore:n}):cb.has(t.command)?await cy({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}):"batch"===t.command?await dQ(t,r,i):"close"===t.command?await dz({req:t,sessionName:r,logPath:a,sessionStore:n}):null}function cD(e,t){let r=Q(e.type??"Element"),a=U(e,r),n=!1===e.enabled?"disabled":"enabled",i=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,a,n,i,o].join("|")}function cx(e,t){return t.flatten?e.map(e=>({text:_(e,0,!1),comparable:cD(e,0)})):K(e).map(e=>({text:e.text,comparable:cD(e.node,e.depth)}))}function ck(e,t){return e.get(t)??0}async function cM(e){let t=dN(e.session);if(t&&"android"===e.device.platform)return await cO(e,t);let r=await cE(e);return dD(e.session),{snapshot:cP(r,e.flags),analysis:r.analysis}}async function cE(e){var t,r,a,n;let i,{device:o,session:s,flags:l,outPath:d,logPath:u,snapshotScope:c}=e;return"macos"===o.platform&&s?.surface&&"app"!==s.surface?(t=await oO(s.surface,{bundleId:"menubar"===s.surface?s.appBundleId:void 0}),r={snapshotDepth:l?.snapshotDepth,snapshotInteractiveOnly:l?.snapshotInteractiveOnly,snapshotScope:c},i=t.nodes??[],r.snapshotScope&&(i=cR(i,r.snapshotScope)),r.snapshotInteractiveOnly&&(i=function(e){if(0===e.length)return e;let t=new Map;for(let r of e)t.set(r.index,r);let r=new Set;for(let a of e){if(!function(e){if(e.hittable||e.rect)return!0;let t=`${e.type??""} ${e.role??""} ${e.subrole??""}`.toLowerCase();return t.includes("button")||t.includes("menu")||t.includes("textfield")||t.includes("searchfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")}(a))continue;let e=a;for(;e&&!r.has(e.index);)r.add(e.index),e="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0}return 0===r.size?e:cT(e.filter(e=>r.has(e.index)))}(i)),"number"==typeof r.snapshotDepth&&(a=i,n=r.snapshotDepth,i=cT(a.filter(e=>(e.depth??0)<=n))),{...t,nodes:i}):await lo(o,"snapshot",[],d,{...lN(u,{...l,snapshotScope:c},s?.appBundleId,s?.trace?.outPath)})}async function cO(e,t){let r=await cL(e),a=cC(r,t,e.flags),n=0;for(let i of dS){if(!a)break;await new Promise(e=>setTimeout(e,i)),r=await cL(e),n+=1,a=cC(r,t,e.flags)}return a||dD(e.session),{snapshot:r.snapshot,analysis:r.data.analysis,freshness:n>0||a?{action:t.action,retryCount:n,staleAfterRetries:!!a,reason:a??void 0}:void 0}}async function cL(e){let t=await cE(e);return{data:t,snapshot:cP(t,e.flags)}}function cC(e,t,r){let a=r?.snapshotInteractiveOnly===!0,n=e.data.analysis;return a&&0===e.snapshot.nodes.length&&n&&n.rawNodeCount>=12?"empty-interactive":dM(t.baselineCount,e.snapshot.nodes.length)?e.snapshot.nodes.some(e=>!0===e.hittable||!!e.label?.trim()||!!e.value?.trim()||!!e.identifier?.trim())?null:"sharp-drop":t.routeComparable&&dx(t.action)&&function(e,t){if(!e||0===e.length)return!1;let r=Math.max(e.length,t.length);if(r<12)return!1;let a=dk(t),n=Math.min(e.length,a.length),i=0;for(let t=0;t<n;t+=1)e[t]===a[t]&&(i+=1);let o=Math.max(0,a.length-e.length),s=Math.max(0,e.length-a.length),l=Math.max(3,Math.floor(.15*r));return i>=Math.floor(.9*r)&&o<=l&&s<=l}(t.baselineSignatures,e.snapshot.nodes)?"stuck-route":null}function cP(e,t){let r=e?.nodes??[],a=eu(t?.snapshotRaw?r:uW(r));return{nodes:eS(t?.snapshotScope&&e?.backend!=="macos-helper"?cR(a,t.snapshotScope):a),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend,comparisonSafe:e?.backend==="android"&&t?.snapshotInteractiveOnly!==!0&&t?.snapshotCompact!==!0&&"number"!=typeof t?.snapshotDepth&&!t?.snapshotScope}}function cR(e,t){let r=uj(eS(e),t);if(!r)return[];let a=e.findIndex(e=>e.index===r.index);if(-1===a)return[];let n=e[a]?.depth??0,i=[];for(let t=a;t<e.length;t+=1){let r=e[t];if(!r)continue;let o=r.depth??0;if(t>a&&o<=n)break;i.push(r)}return cT(i,n)}function cT(e,t=0){let r=new Map;for(let[t,a]of e.entries())r.set(a.index,t);return e.map((e,a)=>({...e,index:a,depth:Math.max(0,(e.depth??0)-t),parentIndex:"number"==typeof e.parentIndex?r.get(e.parentIndex):void 0}))}function c$(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=ep(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=es(t.snapshot.nodes,r),n=a?uq(a,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 cF(e,t,r){let a=e.get(t),n=a?.device??await li(r??{});return a||await lx(n),{session:a,device:n}}async function cU(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await t1(t.id)}}function cV(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function cG(e){let{session:t,sessionName:r,device:a,snapshot:n,appBundleId:i}=e;return t?{...t,snapshot:n}:{name:r,device:a,createdAt:Date.now(),appBundleId:i,snapshot:n,actions:[]}}function cB(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function cj(e){let{parsed:t,req:r,sessionName:a,logPath:n,sessionStore:i,session:o,device:s}=e;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),cV(i,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!l_("wait",s))return dJ("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===t.kind)return await cq({device:s,logPath:n,parsed:t,req:r,session:o,sessionName:a,sessionStore:i});let l=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}}};let r=ep(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=es(t.snapshot.nodes,r),n=a?uq(a,t.snapshot.nodes):void 0;return n?{ok:!0,text:n,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return l.ok?await cH({device:s,logPath:n,req:r,session:o,sessionStore:i,text:l.text,timeoutMs:l.timeoutMs}):l.response}async function cq(e){let{device:t,logPath:r,parsed:a,req:n,session:i,sessionName:o,sessionStore:s}=e,l=a.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let e=cn((await cW({device:t,logPath:r,req:n,session:i,sessionName:o,sessionStore:s})).nodes,a.selector,{platform:t.platform});if(e)return cz(s,i,n,{selector:e.selector.raw,waitedMs:Date.now()-d});await new Promise(e=>setTimeout(e,300))}return dJ("COMMAND_FAILED",`wait timed out for selector: ${a.selectorExpression}`)}async function cH(e){let{device:t,logPath:r,req:a,session:n,sessionStore:i,text:o,timeoutMs:s}=e,l=s??1e4,d=Date.now();for(;Date.now()-d<l;){if("macos"===t.platform&&n?.surface&&"app"!==n.surface){if(uj((await cW({device:t,logPath:r,req:a,session:n,sessionName:n?.name??a.session??"default",sessionStore:i})).nodes,o))return cz(i,n,a,{text:o,waitedMs:Date.now()-d})}else if(tb(t.platform)){let e=await t9(t,{command:"findText",text:o,appBundleId:n?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return cV(i,n,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}}}else if("android"===t.platform&&uj((await cW({device:t,logPath:r,req:a,session:n,sessionName:n?.name??a.session??"default",sessionStore:i})).nodes,o))return cV(i,n,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return dJ("COMMAND_FAILED",`wait timed out for text: ${o}`)}async function cW(e){let{device:t,logPath:r,req:a,session:n,sessionName:i,sessionStore:o}=e,{snapshot:s}=await cM({device:t,session:n,flags:{...a.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:a.flags?.out,logPath:r});return n&&(n.snapshot=s,o.set(i,n)),s}function cz(e,t,r,a){return cV(e,t,r,a),{ok:!0,data:a}}async function cJ(e){let{req:t,logPath:r,sessionStore:a,session:n,device:i}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=n?"frontmost-app"===n.surface?{surface:"frontmost-app"}:{bundleId:n.appBundleId,surface:n.surface}:{};if(!l_("alert",i))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is not supported on this device"}};if("macos"===i.platform){let e=async()=>await oE("wait"===o?"get":o,s);if("wait"===o){let r=cB(t.positionals?.[1])??1e4,i=Date.now();for(;Date.now()-i<r;){try{let r=await e();return cV(a,n,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r="accept"===o||"dismiss"===o?o:"get";if("accept"===r||"dismiss"===r){let e,i=Date.now();for(;Date.now()-i<2e3;){try{let e=await oE(r,s);return cV(a,n,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw cK(e)}let i=await oE("get",s);return cV(a,n,t,i),{ok:!0,data:i}}if("wait"===o){let e=cB(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await t9(i,{command:"alert",action:"get",appBundleId:n?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:t.meta?.requestId});return cV(a,n,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let l="accept"===o||"dismiss"===o?o:"get",d={verbose:t.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await t9(i,{command:"alert",action:l,appBundleId:n?.appBundleId},d);return cV(a,n,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw cK(e)}let u=await t9(i,{command:"alert",action:l,appBundleId:n?.appBundleId},d);return cV(a,n,t,u),{ok:!0,data:u}}function cK(e){if(!(e instanceof q))return e;let t=String(e.message??"").toLowerCase();return t.includes("alert not found")||t.includes("no alert")?new q(e.code,e.message,{...e.details??{},hint:"If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref."}):e}async function cX(e){let{req:t,logPath:r,sessionStore:a,session:n,device:i,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!l_("settings",i))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};if("macos"===i.platform&&!k(s))return{ok:!1,error:{code:"INVALID_ARGS",message:z(s)}};let u=n?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],p=await lo(i,"settings",c,t.flags?.out,{...lN(r,t.flags,u,n?.trace?.outPath)});return cV(a,n,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}let cY=new Set(["snapshot","diff","wait","alert","settings"]);async function cZ(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,i=t.command;if(!cY.has(i))return null;if("snapshot"===i){let{session:e,device:i}=await cF(n,r,t.flags);if(!l_("snapshot",i))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let o=c$(t.flags?.snapshotScope,e);return o.ok?await cU(e,i,async()=>{let s=await cM({device:i,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:o.scope}),l=cQ({capture:s,flags:t.flags,session:e}),d=function(e){let{nodes:t,backend:r,snapshotRaw:a}=e;if(a||"macos-helper"===r)return{partial:!1,visibleNodeCount:t.length,totalNodeCount:t.length,reasons:[]};let n=X(t),i=new Set;return n.hiddenCount>0&&i.add("offscreen-nodes"),n.nodes.some(e=>e.hiddenContentAbove)&&i.add("scroll-hidden-above"),n.nodes.some(e=>e.hiddenContentBelow)&&i.add("scroll-hidden-below"),{partial:i.size>0,visibleNodeCount:n.nodes.length,totalNodeCount:t.length,reasons:[...i]}}({nodes:s.snapshot.nodes,backend:s.snapshot.backend,snapshotRaw:t.flags?.snapshotRaw}),u=cG({session:e,sessionName:r,device:i,snapshot:s.snapshot,appBundleId:e?.appBundleId});return cV(n,u,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),n.set(r,u),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,visibility:d,...l.length>0?{warnings:l}:{},appName:u.appBundleId?u.appName??u.appBundleId:void 0,appBundleId:u.appBundleId}}}):o.response}if("diff"===i)return t.positionals?.[0]!=="snapshot"?{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}}:await c0({req:t,sessionName:r,logPath:a,sessionStore:n});if("wait"===i){let{session:e,device:i}=await cF(n,r,t.flags),o=function(e){if(0===e.length)return null;let t=cB(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=cB(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=cB(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=cB(e[e.length-1]),a=u2(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=u1(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}};let s=()=>cj({parsed:o,req:t,sessionName:r,logPath:a,sessionStore:n,session:e,device:i});return"sleep"===o.kind?await s():await cU(e,i,s)}if("alert"===i){let{session:e,device:i}=await cF(n,r,t.flags);return await cU(e,i,async()=>await cJ({req:t,logPath:a,sessionStore:n,session:e,device:i}))}if("settings"===i){let e,i,o,s=(e=t.positionals?.[0]?.toLowerCase(),i=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&i&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:i,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:C}}});if(!s.ok)return s.response;let{session:l,device:d}=await cF(n,r,t.flags);return await cU(l,d,async()=>await cX({req:t,logPath:a,sessionStore:n,session:l,device:d,parsed:s.parsed}))}return null}function cQ(e){let{capture:t,flags:r,session:a}=e,n=[],i=t.analysis,o=r?.snapshotInteractiveOnly===!0;"android"===t.snapshot.backend&&o&&0===t.snapshot.nodes.length&&i&&i.rawNodeCount>=12&&(n.push(`Interactive snapshot is empty after filtering ${i.rawNodeCount} raw Android nodes. Likely causes: depth too low, transient route change, or collector filtering.`),"number"==typeof r?.snapshotDepth&&i.maxDepth>=r.snapshotDepth+2&&n.push(`Interactive output is empty at depth ${r.snapshotDepth}; retry without -d.`));let s=a?.snapshot;return!t.freshness&&s&&Date.now()-s.createdAt<=2e3&&dM(s.nodes.length,t.snapshot.nodes.length)&&n.push("Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once."),t.freshness?.staleAfterRetries&&"android"===t.snapshot.backend&&("stuck-route"===t.freshness.reason?n.push(`Recent ${t.freshness.action} was followed by a nearly identical snapshot after ${t.freshness.retryCount} automatic retr${1===t.freshness.retryCount?"y":"ies"}. If you expected navigation or submit, the tree may still be stale. Use screenshot as visual truth, wait briefly, then re-snapshot once.`):"sharp-drop"===t.freshness.reason&&n.push("Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once.")),rt(n)}async function c0(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,{session:i,device:o}=await cF(n,r,t.flags);if(!l_("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let s=c$(t.flags?.snapshotScope,i);if(!s.ok)return s.response;let l=t.flags?.snapshotInteractiveOnly===!0;return await cU(i,o,async()=>{let e=await cM({device:o,session:i,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:s.scope}),d=e.snapshot,u=cQ({capture:e,flags:t.flags,session:i});if(!i?.snapshot){let e=function(e,t={}){return cx(e,t).length}(d.nodes,{flatten:l}),a=cG({session:i,sessionName:r,device:o,snapshot:d,appBundleId:i?.appBundleId});return cV(n,a,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e}}),n.set(r,a),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e},lines:[],...u.length>0?{warnings:u}:{}}}}let c=function(e,t,r={}){let a=function(e,t){let r=e.length,a=t.length,n=r+a,i=new Map,o=[];i.set(1,0);for(let s=0;s<=n;s+=1){o.push(new Map(i));for(let n=-s;n<=s;n+=2){let l=n===-s||n!==s&&ck(i,n-1)<ck(i,n+1)?ck(i,n+1):ck(i,n-1)+1,d=l-n;for(;l<r&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(i.set(n,l),l>=r&&d>=a)return function(e,t,r,a,n){let i=[],o=a,s=n;for(let a=e.length-1;a>=0;a-=1){let n=e[a],l=o-s,d=l===-a||l!==a&&ck(n,l-1)<ck(n,l+1)?l+1:l-1,u=ck(n,d),c=u-d;for(;o>u&&s>c;)i.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===a)break;o===u?(i.push({kind:"added",text:r[c].text}),s=c):(i.push({kind:"removed",text:t[u].text}),o=u)}return i.reverse(),i}(o,e,t,r,a)}}return[]}(cx(e,r),cx(t,r)),n={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(n.additions+=1),"removed"===e.kind&&(n.removals+=1),"unchanged"===e.kind&&(n.unchanged+=1);return{summary:n,lines:a}}(i.snapshot.nodes,d.nodes,{flatten:l}),p={...i,snapshot:d};return cV(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,...u.length>0?{warnings:u}:{}}}})}function c1(e,t,r,a={}){let n=c3(r);if(!n)return{matches:[],score:0};let i=0,o=[];for(let r of e){if(a.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return c2(e.label,r);case"value":return c2(e.value,r);case"id":return c2(e.identifier,r);default:return Math.max(c2(e.label,r),c2(e.value,r),c2(e.identifier,r))}}(r,t,n);if(!(e<=0)){if(e>i){i=e,o.length=0,o.push(r);continue}e===i&&o.push(r)}}return{matches:o,score:i}}function c2(e,t){let r=c3(e??"");return r?r===t?2:+!!r.includes(t):0}function c3(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function c4(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:n,invalidRefMessage:i,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=ep(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:i}}};let l=es(t.snapshot.nodes,s);return((!l||n&&!l.rect)&&a.length>0&&(l=uj(t.snapshot.nodes,a)),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 c8(e){let t=c5(e);if(!t)return null;let r=eA(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function c5(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),n=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(n)&&!(a<0)&&!(n<0)?{x:t,y:r,width:a,height:n}:null}async function c6(e){let{session:t,refInput:r,fallbackLabel:a,commandLabel:n,promoteToHittableAncestor:i,invalidRefMessage:o,missingBoundsMessage:s,invalidBoundsMessage:l,reqFlags:d,sessionStore:u,contextFromFlags:c,captureSnapshotForSession:p,resolveRefTarget:f}=e,m=f({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:o,notFoundMessage:s});if(!m.ok)return{ok:!1,response:m.response};let{ref:h}=m.target,w=i?c9(m.target.snapshotNodes,m.target.node):m.target.node,g=m.target.snapshotNodes,y=c8(w.rect);if(!y){let e=await p(t,d,u,c,{interactiveOnly:!0}),r=es(e.nodes,h),n=a.length>0?uj(e.nodes,a):null,o=r&&i?c9(e.nodes,r):r,s=n&&i?c9(e.nodes,n):n,l=c8(s?.rect),f=c8(o?.rect)?o:l?s:o??s,m=c8(f?.rect);f&&m&&(w=f,g=e.nodes,y=m)}if(!y)return{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:l}}};let v=w.rect?W(w,g):null;return w.rect&&v&&!x(w,g)?{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${r} is off-screen and not safe to ${n}`,hint:`Run scrollintoview ${r}, then retry ${n} with the returned currentRef or a fresh snapshot.`,details:{reason:"offscreen_ref",ref:h,rect:w.rect,viewport:v}}}}:{ok:!0,target:{ref:h,node:w,snapshotNodes:g,point:y}}}function c9(e,t){let r=function(e,t){let r=c5(t.rect);if(!r)return null;let a=t,n=new Set;for(;!n.has(a.ref);){n.add(a.ref);let t=e.filter(e=>{if(e.parentIndex!==a.index||!e.hittable)return!1;let t=c5(e.rect);return!!t&&c7(t,r)});if(1!==t.length)break;a=t[0]}return a===t?null:a}(e,t);if(r?.rect&&c8(r.rect))return r;let a=uK(e,t);return a?.rect&&c8(a.rect)?!function(e,t,r){var a,n,i,o;let s,l,d,u=c5(e.rect),c=c5(t.rect);if(!u||!c)return!1;let p=function(e,t){let r=eA(t),a=e.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}).map(e=>c5(e.rect)).filter(e=>null!==e);if(0===a.length)return null;let n=a.filter(e=>T(e,r.x,r.y));return ec(n.length>0?n:a)}(r,u);return!!p&&(a=c,n=p,s=(i=a,o=n,Math.max(0,Math.min(i.x+i.width,o.x+o.width)-Math.max(i.x,o.x))*Math.max(0,Math.min(i.y+i.height,o.y+o.height)-Math.max(i.y,o.y))),l=a.width*a.height,d=n.width*n.height,!(s<=0)&&!(l<=0)&&!(d<=0)&&!!(s/d>=.9)&&!!(s/l>=.8))&&!c7(u,c)}(t,a,e)?a:t:t}function c7(e,t){return .5>=Math.abs(e.x-t.x)&&.5>=Math.abs(e.y-t.y)&&.5>=Math.abs(e.width-t.width)&&.5>=Math.abs(e.height-t.height)}async function pe(e){let{device:t,node:r,flags:a,appBundleId:n,traceOutPath:i,surface:o,contextFromFlags:s}=e,l=H(r),d=c8(r.rect);if(!d)return l;try{let e=await lo(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,n,i),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return ed({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return ed({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}async function pt(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return dJ("INVALID_ARGS","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 a=e[r]??"",n=e.slice(r+1);if(0===n.length)return{locator:t,query:a,action:"click"};let i=n[0].toLowerCase();if("get"===i){let e=n[1]?.toLowerCase();if("text"===e)return{locator:t,query:a,action:"get_text"};if("attrs"===e)return{locator:t,query:a,action:"get_attrs"};throw new q("INVALID_ARGS","find get only supports text or attrs")}if("wait"===i)return{locator:t,query:a,action:"wait",timeoutMs:cB(n[1])??void 0};if("exists"===i)return{locator:t,query:a,action:"exists"};if("click"===i)return{locator:t,query:a,action:"click"};if("focus"===i)return{locator:t,query:a,action:"focus"};if("fill"===i)return{locator:t,query:a,action:"fill",value:n.slice(1).join(" ")};if("type"===i)return{locator:t,query:a,action:"type",value:n.slice(1).join(" ")};throw new q("INVALID_ARGS",`Unsupported find action: ${n[0]}`)}(s);if(!d)return dJ("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return dJ("INVALID_ARGS","find accepts only one of --first or --last");let f=n.get(r);if(!f&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return dJ("SESSION_NOT_FOUND","No active session. Run open first.");let m=f?.device??await li(t.flags??{});f||await lx(m);let h="role"!==l?d:void 0,w="click"===u||"focus"===u||"fill"===u||"type"===u,g=0,y=null,v=async()=>{let e=Date.now();if(y&&e-g<750&&!dN(f))return{nodes:y};let{snapshot:i}=await cM({device:m,session:f,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=i.nodes;return g=e,y=o,f&&(f.snapshot=i,n.set(r,f)),{nodes:o,truncated:i.truncated,backend:i.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i,session:f,device:m,command:o,locator:l,query:d};if("wait"===u)return pr(I,v,l,d,p);let{nodes:A}=await v(),b=c1(A,l,d,{requireRect:w});if(w&&b.matches.length>1)if(t.flags?.findFirst)b.matches=[b.matches[0]];else{if(!t.flags?.findLast){var S,_,N;let e;return S=b.matches,_=l,N=d,e=S.slice(0,8).map(e=>{let t=uX(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${S.length} elements for ${_} "${N}". Use a more specific locator or selector.`,details:{locator:_,query:N,matches:S.length,candidates:e}}}}b.matches=[b.matches[b.matches.length-1]]}let D=b.matches[0]??null;if(!D)return dJ("COMMAND_FAILED","find did not match any element");let x="click"===u||"focus"===u||"fill"===u||"type"===u?uK(A,D)??D:D,k=`@${x.ref}`,M={node:D,resolvedNode:x,ref:k,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},E={exists:()=>pa(I),get_text:()=>pn(I,M),get_attrs:()=>pi(I,M),click:()=>po(I,M),fill:()=>ps(I,M,c),focus:()=>pl(I,M),type:()=>pd(I,M,c)}[u];return E?E():null}async function pr(e,t,r,a,n){let{req:i,sessionStore:o,session:s,command:l}=e,d=n??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(c1(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:i.positionals??[],flags:i.flags??{},result:{found:!0,waitedMs:Date.now()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}async function pa(e){let{req:t,sessionStore:r,session:a,command:n}=e;return a&&r.recordAction(a,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function pn(e,t){let{req:r,sessionStore:a,session:n,command:i,device:o,logPath:s}=e,l=await pe({device:o,node:t.node,flags:r.flags,appBundleId:n?.appBundleId,traceOutPath:n?.trace?.outPath,surface:n?.surface,contextFromFlags:(e,t,r)=>lN(s,e,t,r)});return n&&a.recordAction(n,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function pi(e,t){let{req:r,sessionStore:a,session:n,command:i}=e;return n&&a.recordAction(n,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function po(e,t){let{req:r,sessionName:a,sessionStore:n,session:i,invoke:o,command:s,locator:l,query:d}=e,u=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?eA(t.resolvedNode.rect):null,p={ref:t.ref,locator:l,query:d};return c&&(p.x=c.x,p.y=c.y),i&&n.recordAction(i,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:p}}async function ps(e,t,r){let{req:a,sessionName:n,sessionStore:i,session:o,invoke:s,command:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let d=await s({token:a.token,session:n,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return d.ok&&o&&i.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),d}async function pl(e,t){let{req:r,sessionStore:a,session:n,device:i,command:o,logPath:s}=e,l=t.node.rect?eA(t.node.rect):null;if(!l)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let d=await lo(i,"focus",[String(l.x),String(l.y)],r.flags?.out,{...lN(s,r.flags,n?.appBundleId,n?.trace?.outPath)});return n&&a.recordAction(n,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:d??{ref:t.ref}}}async function pd(e,t,r){let{req:a,sessionStore:n,session:i,device:o,command:s,logPath:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let d=t.node.rect?eA(t.node.rect):null;if(!d)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await lo(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...lN(l,a.flags,i?.appBundleId,i?.trace?.outPath)});let u=await lo(o,"type",[r],a.flags?.out,{...lN(l,a.flags,i?.appBundleId,i?.trace?.outPath)});return i&&n.recordAction(i,{command:s,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:u??{ref:t.ref}}}let pu=`
|
|
30
|
+
${n}`.toLowerCase();return i.includes("timeout waiting for screen surfaces")||i.includes("nsposixerrordomain")&&i.includes("code=60")&&i.includes("screenshot")||i.includes("timed out")&&i.includes("screenshot")}let sh={settings:"com.apple.Preferences"},sw=null;function sg(e,t,r){return T("xcrun",te(e,t),r)}function sy(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function sv(e,t){if("macos"===e.platform)return await oJ(t);let r=t.trim();if(r.includes("."))return r;let a=sh[r.toLowerCase()];if(a)return a;let n=("simulator"===e.kind?await sL(e):await os(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===n.length)return n[0].bundleId;if(n.length>1)throw new H("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:n});throw new H("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function sI(e,t,r){if("macos"===e.platform)return void await oX(e,t,r);let a=r?.url?.trim();if(a){if(!aj(a))throw new H("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await om(e),await sg(e,["openurl",e.id,a]);return}let n=aq(r?.appBundleId??await sv(e,t),a);if(!n)throw new H("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await sV(e,n,{payloadUrl:a});return}let n=t.trim();if(aj(n)){if("simulator"===e.kind){await om(e),await sg(e,["openurl",e.id,n]);return}let t=aq(r?.appBundleId,n);if(!t)throw new H("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await sV(e,t,{payloadUrl:n});return}let i=r?.appBundleId??await sv(e,t);"simulator"===e.kind?await sG(e,i):await sV(e,i)}async function sb(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await ow(e)&&await om(e)}async function sA(e,t){if("macos"===e.platform)return void await oK(e,t);let r=await sv(e,t);if("simulator"===e.kind){await om(e);let t=te(e,["terminate",e.id,r]),a=await T("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new H("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await oo(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function sS(e,t){let r=await sv(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],a=await T("xcrun",t,{allowFailure:!0,timeoutMs:ot});if(0!==a.exitCode){let n=String(a.stdout??""),i=String(a.stderr??"");if(!sy(`${n}
|
|
31
|
+
${i}`.toLowerCase()))throw new H("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:n,stderr:i,deviceId:e.id,hint:od(n,i)??ol})}return{bundleId:r}}await om(e);let a=await sg(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==a.exitCode&&!sy(`${a.stdout}
|
|
32
|
+
${a.stderr}`.toLowerCase()))throw new H("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:r}}async function s_(e,t,r){let a=await oy({kind:"path",path:t},r);try{return await sx(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function sN(e,t,r){let{bundleId:a}=await sS(e,t);return await s_(e,r,{appIdentifierHint:t}),{bundleId:a}}async function sx(e,t){"simulator"!==e.kind?await oo(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await om(e),await sg(e,["install",e.id,t]))}async function sD(e){if("macos"===e.platform)return await oY();op(e,"clipboard"),await om(e);let t=await sg(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new H("COMMAND_FAILED","Failed to read iOS simulator clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return t.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function sk(e,t){if("macos"===e.platform)return void await oZ(t);op(e,"clipboard"),await om(e);let r=await sg(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new H("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function sM(e,t,r){op(e,"push"),await om(e);let a=await d.mkdtemp(p.join(u.tmpdir(),"agent-device-ios-push-")),n=p.join(a,"payload.apns");try{await d.writeFile(n,`${JSON.stringify(r)}
|
|
33
|
+
`,"utf8"),await sg(e,["push",e.id,t,n])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function sE(e,t,r,a,n){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await o0(r);if("permission"===e){let e=iW(r);if("deny"===e)throw new H("INVALID_ARGS",J("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new H("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(n?.permissionTarget);return await oF(e,t)}throw new H("INVALID_ARGS",J(t))}op(e,"settings"),await om(e);let i=t.toLowerCase();switch(i){case"wifi":{let t=sC(r);await sg(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(sC(r)?await sg(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await sg(e,["status_bar",e.id,"clear"]));case"location":{let t=sC(r);if(!a)throw new H("INVALID_ARGS","location setting requires an active app in session");await sg(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=sR[i],a=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new H("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,i);await sU(e,a,{settingName:i,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await sP(e,r);await sg(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new H("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=iW(r))?"revoke":o,i=function(e,t){let r=iz(e);if("photos"!==r&&t?.trim())throw new H("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 H("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new H("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(n?.permissionTarget,n?.permissionMode);await sT(e,t,i,a);return}default:throw new H("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function sO(e,t="all"){return"macos"===e.platform?await o1(t):"simulator"===e.kind?oS(await sL(e),t):await os(e,t)}async function sL(e){let t=(await sg(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 T("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 sC(e){let t=e.toLowerCase();if("on"===t||"true"===t||"1"===t)return!0;if("off"===t||"false"===t||"0"===t)return!1;throw new H("INVALID_ARGS",`Invalid setting state: ${e}`)}async function sP(e,t){let r=iJ(t);if("toggle"!==r)return r;let a=await sg(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new H("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let n=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
|
|
34
|
+
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!n)throw new H("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===n?"light":"dark"}let sR={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function sT(e,t,r,a){let n=await sF(e);if(!n.has(r))throw new H("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(n).sort().join(", ")}`});let i=["privacy",e.id,t,r,a],o="notifications"===r;if(!("reset"===t&&o))try{await sg(e,i);return}catch(t){if(!(o&&s$(t)))throw t;throw new H("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:a,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await sg(e,i);return}catch(e){if(!s$(e))throw e}try{await sg(e,["privacy",e.id,"reset","all",a])}catch(t){throw new H("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:a,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function s$(e){if(!(e instanceof H)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return(t.includes("failed to grant access")||t.includes("failed to revoke access")||t.includes("failed to reset access"))&&t.includes("operation not permitted")}async function sF(e){let r=e8(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(sw&&t===a)return sw;let n=await sg(e,["privacy","help"],{allowFailure:!0}),i=function(e){let t=new Set,r=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let n=/^([a-z-]+)\s+-\s+/.exec(e);n&&t.add(n[1])}return t}(`${n.stdout}
|
|
35
|
+
${n.stderr}`);if(0===i.size)throw new H("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 sw=i,t=a,i}async function sU(e,t,r){let a=function(e,t,r){let a=r.length>0?r:["face"];switch(t){case"match":return a.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return a.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),n=[];for(let t of a){let r=te(e,t),a=await T("xcrun",r,{allowFailure:!0});if(0===a.exitCode)return;n.push({args:r,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let i=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 a;return t=e.stdout,r=e.stderr,(a=`${t}
|
|
36
|
+
${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new H("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:i});throw new H("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:i})}async function sG(e,t){await om(e);let r=0,a=e$.fromTimeoutMs(oe);try{await eF(async({deadline:r})=>{var a;if(r?.isExpired())throw new H("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:oe});let n=(a=["launch",e.id,t],te(e,a)),i=await T("xcrun",n,{allowFailure:!0});if(0!==i.exitCode)throw new H("COMMAND_FAILED",`xcrun exited with code ${i.exitCode}`,{cmd:"xcrun",args:n,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!ou(e)&&(r+=1)<3},{deadline:a})}catch(r){if(ou(r)){var n;let a=(n=await oc(e,t)).installed?!1===n.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function sV(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await oo(a,{action:"launch iOS app",deviceId:e.id})}async function sB(e,t,r,a){let n=a?.maxScrolls??48,i=await e({command:"findText",text:r});if(i?.found)return{attempts:0};let o=sj(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let a=1;a<=n;a+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let n=await e({command:"findText",text:r});if(n?.found)return{attempts:a};let i=sj(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(i===o)throw new H("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a,stalled:!0});o=i}throw new H("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:n})}function sj(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function sq(e,t,r,a,n,i,o){if("tv"===t.target)return sz(await e(t,{command:"swipe",direction:function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left";default:return e}}(n),appBundleId:r.appBundleId},a),i);let s=o??await sH(e,t,r,a),l=n8({direction:n,amount:i?.amount,pixels:i?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return sz(await e(t,{command:"drag",x:s.originX+l.x1,y:s.originY+l.y1,x2:s.originX+l.x2,y2:s.originY+l.y2,appBundleId:r.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function sH(e,t,r,a){let n=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},a),i=sW(n.x),o=sW(n.y),s=sW(n.referenceWidth),l=sW(n.referenceHeight);if(void 0===i||void 0===o||void 0===s||void 0===l)throw new H("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:i,originY:o,referenceWidth:s,referenceHeight:l}}function sW(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function sz(e,t){var r;let{x1:a,y1:n,x2:i,y2:o}={x1:sW((r=e).x),y1:sW(r.y),x2:sW(r.x2),y2:sW(r.y2)},s=sW(e.referenceWidth),l=sW(e.referenceHeight),d=void 0!==a&&void 0!==i?Math.round(Math.abs(i-a)):void 0,u=void 0!==n&&void 0!==o?Math.round(Math.abs(o-n)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:d&&d>0?d:u&&u>0?u:void 0;return{...void 0!==a?{x1:a}:{},...void 0!==n?{y1:n}:{},...void 0!==i?{x2:i}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}function sJ(){return process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11"}function sX(){return"wayland"===sJ()}let sK=null;async function sY(){if(sK)return sK;let e=sJ();if("wayland"===e){if(await X("ydotool"))return sK={tool:"ydotool",display:e};throw new H("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await X("xdotool"))return sK={tool:"xdotool",display:e};throw new H("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function sZ(...e){await T("xdotool",e,{allowFailure:!1,timeoutMs:1e4})}async function sQ(...e){await T("ydotool",e,{allowFailure:!1,timeoutMs:1e4})}async function s0(e,t){let{tool:r}=await sY();"xdotool"===r?await sZ("mousemove","--sync",String(e),String(t)):await sQ("mousemove","--absolute","-x",String(e),"-y",String(t))}async function s1(e,t){let{tool:r}=await sY();"xdotool"===r?await sZ("key","--clearmodifiers",e):await sQ("key",...t)}async function s2(e,t,r,a){await s0(e,t);let{tool:n}=await sY();"xdotool"===n?await sZ("click",r):await sQ("click",a)}async function s3(e,t){await s2(e,t,"1","0xC0")}async function s4(e,t){await s2(e,t,"3","0xC1")}async function s5(e,t){await s2(e,t,"2","0xC2")}async function s8(e,t){let{tool:r}=await sY();await s0(e,t),"xdotool"===r?await sZ("click","--repeat","2","1"):(await sQ("click","0xC0"),await sQ("click","0xC0"))}async function s6(e,t,r=800){let{tool:a}=await sY();await s0(e,t),"xdotool"===a?(await sZ("mousedown","1"),await la(r),await sZ("mouseup","1")):(await sQ("click","--down","0xC0"),await la(r),await sQ("click","--up","0xC0"))}async function s9(e,t){await s3(e,t)}async function s7(e,t,r,a,n=300){let{tool:i}=await sY();await s0(e,t),"xdotool"===i?(await sZ("mousedown","1"),await sZ("mousemove","--sync",String(r),String(a)),await la(n),await sZ("mouseup","1")):(await sQ("click","--down","0xC0"),await sQ("mousemove","--absolute","-x",String(r),"-y",String(a)),await la(n),await sQ("click","--up","0xC0"))}async function le(e,t){let{tool:r}=await sY(),a=5;if(t?.pixels!=null?a="xdotool"===r?Math.max(1,Math.round(t.pixels/15)):Math.max(1,Math.round(t.pixels/40)):t?.amount!=null&&(a=Math.max(1,Math.round(5*(t.amount/.6)))),"xdotool"===r)await sZ("click","--repeat",String(a),"up"===e?"4":"down"===e?"5":"left"===e?"6":"7");else if("up"===e||"down"===e){let t="up"===e?String(-a):String(a);await sQ("mousemove","--wheel","-y",t)}else{let t="left"===e?String(-a):String(a);await sQ("mousemove","--wheel","-x",t)}}async function lt(e,t=0){let{tool:r}=await sY();if("xdotool"===r){let r=["type"];t>0&&r.push("--delay",String(t)),r.push("--clearmodifiers","--",e),await sZ(...r)}else await sQ("type","--",e)}async function lr(e,t,r,a=0){await s3(e,t),await la(100),await s1("ctrl+a",["29:1","30:1","30:0","29:0"]),await la(50),await lt(r,a)}function la(e){return new Promise(t=>setTimeout(t,e))}let ln=null;async function li(){if(ln)return ln;if(sX()){if(await X("grim"))return ln={tool:"grim",display:"wayland"};if(await X("gnome-screenshot"))return ln={tool:"gnome-screenshot",display:"wayland"};throw new H("TOOL_MISSING","grim or gnome-screenshot is required for screenshots on Wayland. Install via your package manager.")}if(await X("scrot"))return ln={tool:"scrot",display:"x11"};if(await X("import"))return ln={tool:"import",display:"x11"};if(await X("gnome-screenshot"))return ln={tool:"gnome-screenshot",display:"x11"};throw new H("TOOL_MISSING","scrot, import (ImageMagick), or gnome-screenshot is required for screenshots on X11. Install via your package manager.")}async function lo(e){let{tool:t}=await li();switch(t){case"grim":await T("grim",[e]);break;case"scrot":await T("scrot",[e]);break;case"import":await T("import",["-window","root",e]);break;case"gnome-screenshot":await T("gnome-screenshot",["-f",e])}}async function ls(e){if(e.includes("://")||e.startsWith("/"))return void await T("xdg-open",[e]);if(await X(e)){T(e,[],{allowFailure:!0}).catch(t=>{eu({level:"warn",phase:"linux_app_launch",data:{app:e,error:String(t)}})}),await new Promise(e=>setTimeout(e,500));return}await T("xdg-open",[e],{allowFailure:!0})}async function ll(e){await X("wmctrl")?await T("wmctrl",["-c",e],{allowFailure:!0}):await T("pkill",["-x",e],{allowFailure:!0})}async function ld(){await s1("alt+Left",["56:1","105:1","105:0","56:0"])}async function lu(){await s1("super+d",["125:1","32:1","32:0","125:0"])}let lc=null;async function lp(){if(lc)return lc;if(sX()){if(await X("wl-paste"))return lc={tool:"wl-clipboard",display:"wayland"};throw new H("TOOL_MISSING","wl-paste (wl-clipboard) is required for clipboard access on Wayland. Install via your package manager.")}if(await X("xclip"))return lc={tool:"xclip",display:"x11"};if(await X("xsel"))return lc={tool:"xsel",display:"x11"};throw new H("TOOL_MISSING","xclip or xsel is required for clipboard access on X11. Install via your package manager.")}async function lf(){let{tool:e}=await lp();switch(e){case"wl-clipboard":return(await T("wl-paste",["--no-newline"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xclip":return(await T("xclip",["-selection","clipboard","-o"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xsel":return(await T("xsel",["--clipboard","--output"],{allowFailure:!0,timeoutMs:5e3})).stdout}}async function lm(e){let{tool:t}=await lp();switch(t){case"wl-clipboard":await T("wl-copy",["--",e],{allowFailure:!1,timeoutMs:5e3});break;case"xclip":await T("xclip",["-selection","clipboard"],{allowFailure:!1,timeoutMs:5e3,stdin:e});break;case"xsel":await T("xsel",["--clipboard","--input"],{allowFailure:!1,timeoutMs:5e3,stdin:e})}}async function lh(){return"linux"!==process.platform?[]:[{platform:"linux",id:"local",name:c(),kind:"device",target:"desktop",booted:!0}]}let lw={"push button":"Button","toggle button":"Button","push button menu":"Button",label:"StaticText",static:"StaticText",caption:"StaticText",text:"TextField",entry:"TextField","password text":"TextField","spin button":"TextField",terminal:"TextArea","document text":"TextArea",paragraph:"TextArea",frame:"Window",window:"Window",dialog:"Dialog",alert:"Alert","file chooser":"Dialog","color chooser":"Dialog","font chooser":"Dialog",panel:"Group",filler:"Group",section:"Group",form:"Group",grouping:"Group","layered pane":"Group","glass pane":"Group","root pane":"Group","option pane":"Group","internal frame":"Group","desktop frame":"Group","block quote":"Group",article:"Group",comment:"Group",landmark:"Group",log:"Group",marquee:"Group",math:"Group",notification:"Group","content deletion":"Group","content insertion":"Group",mark:"Group",suggestion:"Group","scroll pane":"ScrollArea","scroll bar":"ScrollBar","menu bar":"MenuBar",menu:"Menu","popup menu":"Menu","menu item":"MenuItem","check menu item":"MenuItem","radio menu item":"MenuItem","tearoff menu item":"MenuItem","check box":"CheckBox","radio button":"RadioButton",switch:"Switch","combo box":"ComboBox","page tab":"Tab","page tab list":"TabList",table:"Table","tree table":"Table","table cell":"Cell","table row":"Row","table column header":"Cell","table row header":"Cell","column header":"Cell","row header":"Cell",list:"List","list item":"ListItem","list box":"List",tree:"Tree","tree item":"TreeItem","description list":"List","description term":"ListItem","description value":"ListItem","tool bar":"Toolbar","status bar":"StatusBar","info bar":"StatusBar",slider:"Slider","progress bar":"ProgressBar","level bar":"ProgressBar",image:"Image",icon:"Image",animation:"Image",canvas:"Image","drawing area":"Image",video:"Video",audio:"Audio",link:"Link",hyperlink:"Link",separator:"Separator",application:"Application","tool tip":"Tooltip",timer:"Timer",heading:"Heading",footnote:"Footnote","title bar":"TitleBar","date editor":"DateEditor",rating:"Slider"},lg="atspi-dump.py",ly=null;async function lv(e,t={}){let r;if("linux"!==process.platform)throw new H("UNSUPPORTED_PLATFORM","AT-SPI2 bridge is only available on Linux");if(!await X("python3"))throw new H("TOOL_MISSING","python3 is required for AT-SPI2 accessibility snapshots on Linux.");let a=t.maxNodes??1500,n=t.maxDepth??12,i=t.maxApps??24,o=[function(){if(ly)return ly;let e=p.dirname(w(import.meta.url));for(let t=0;t<5;t++){let r=p.join(e,"src","platforms","linux",lg);if(s.existsSync(r))return ly=r,r;if(0===t){let t=p.join(e,lg);if(s.existsSync(t))return ly=t,t}e=p.dirname(e)}throw new H("TOOL_MISSING",`Cannot find ${lg}. Ensure the agent-device package is installed correctly.`)}(),"--surface",e,"--max-nodes",String(a),"--max-depth",String(n),"--max-apps",String(i)],l=await T("python3",o,{allowFailure:!0,timeoutMs:3e4});if(0!==l.exitCode){let e=l.stderr.trim();if(e.includes("No module named")||e.includes("gi.require_version"))throw new H("TOOL_MISSING","AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.",{cause:e});throw new H("COMMAND_FAILED",`AT-SPI2 snapshot failed (exit ${l.exitCode}): ${e||l.stdout}`)}try{r=JSON.parse(l.stdout)}catch{throw new H("COMMAND_FAILED",`AT-SPI2 snapshot returned invalid JSON: ${l.stdout.slice(0,200)}`)}if(r.error)throw new H("COMMAND_FAILED",`AT-SPI2: ${r.error}`);return{nodes:(r.nodes??[]).map(e=>{let t,r;return{index:e.index,type:(r=lw[t=e.role.toLowerCase().trim()])||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0}}),truncated:r.truncated,surface:e}}async function lI(e){let t="desktop"===e?"desktop":"frontmost-app"===e||"app"===e?"frontmost-app":("menubar"===e&&eu({level:"warn",phase:"linux_snapshot",data:{message:"menubar surface is not supported on Linux, falling back to desktop"}}),"desktop"),r=await lv(t);return{nodes:r.nodes,truncated:r.truncated}}function lb(e){return e?.clickButton??"primary"}function lA(e){return"primary"===e.button?null:"click"!==e.commandLabel?new H("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform&&"linux"!==e.platform?new H("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS and Linux`):"macos"===e.platform&&"middle"===e.button?new H("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new H("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let lS=/^[A-Za-z0-9_.:-]{1,64}$/,l_=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function lN(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new H("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function lx(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await lD(t)}async function lD(e){await new Promise(t=>setTimeout(t,e))}function lk(e,t){let r,a=t?.subject??"Payload",n=e.trim();if(!n)throw new H("INVALID_ARGS",`${a} cannot be empty`);let i=t?.expandPath?t.expandPath(n,t.cwd):n;try{if(!s.statSync(i).isFile())throw new H("INVALID_ARGS",`${a} path is not a file: ${i}`);return{kind:"file",path:i}}catch(t){if(t instanceof H)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new H("INVALID_ARGS",`${a} file is not readable: ${i}`);if(e&&"ENOENT"!==e)throw new H("COMMAND_FAILED",`Unable to read ${a} file: ${i}`,{cause:String(t)})}if((r=n.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:n};throw new H("INVALID_ARGS",`${a} file not found: ${i}`)}async function lM(e){let t=lk(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await lE(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new H("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof H)throw t;throw new H("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function lE(e){try{return await d.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new H("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new H("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new H("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new H("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let lO=eQ(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),lL=/^(iphone|ipad|ipod|appletv)/i,lC=/\b(iphone|ipad|ipod)\b/i,lP=/^appletv/i,lR=["apple tv","appletv","tvos"],lT=/^==\s*(.+?)\s*==$/,l$=/^(?<name>.+?)\s+\[(?<id>[^[\]]+)\]\s*$/;function lF(e){return(e??"").trim().toLowerCase()}function lU(e){return lF(e.hardwareProperties?.platform)}function lG(e){return e.includes("tvos")}function lV(e){let t=lF(e);return lR.some(e=>t.includes(e))}function lB(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function lj(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function lq(e={}){let t,r,a=e8(e.simulatorSetPath),n=e.target;try{t=await T("xcrun",e7(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let i=lH(r,a),o=null,s=null,l=null;for(let e of i)n&&e.target!==n||(e.booted&&(o=o??e),"mobile"===e.target&&(s=s??e),l=l??e);return o??s??l}function lH(e,t){let r=[];for(let[a,n]of Object.entries(e.devices))if(function(e){let t=lF(e);return t.includes("ios")||t.includes("tvos")}(a))for(let e of n)e.isAvailable&&r.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:lG(lF(a))?"tv":"mobile",booted:"Booted"===e.state,...t?{simulatorSetPath:t}:{}});return r}function lW(e,t){let r=new Set(e.map(e=>e.id)),a=[...e];for(let e of t)r.has(e.id)||(r.add(e.id),a.push(e));return a}async function lz(){let e=null;try{e=p.join(u.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let t=await T("xcrun",["devicectl","list","devices","--json-output",e],{allowFailure:!0,timeoutMs:lO});if(0!==t.exitCode)return[];let r=await d.readFile(e,"utf8");return function(e){let t=[];for(let r of e.result?.devices??[]){if(!function(e){var t;let r=lU(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=lj(e),!!lL.test(t.trim())||lB(e).some(lV))}(r))continue;let e=r.hardwareProperties?.udid??r.identifier??"",a=r.name??r.deviceProperties?.name??e;e&&t.push({platform:"ios",id:e,name:a,kind:"device",target:function(e){var t;return lG(lU(e))?"tv":(t=lj(e),lP.test(t.trim())||lB(e).some(lV))?"tv":"mobile"}(r),booted:!0})}return t}(JSON.parse(r))}catch{return[]}finally{e&&await d.rm(e,{force:!0}).catch(()=>{})}}async function lJ(){try{let e=await T("xcrun",["xctrace","list","devices"],{allowFailure:!0});if(0!==e.exitCode)return[];return function(e){let t=[],r=null;for(let a of e.split(/\r?\n/)){let e=a.trim();if(!e)continue;let n=lT.exec(e);if(n){r=n[1]?.trim()??null;continue}if("Devices"!==r)continue;let i=l$.exec(e),o=i?.groups?.id?.trim()??"",s=i?.groups?.name?.trim()??"";if(!o||!s)continue;let l=function(e){return lV(e)?"tv":lC.test(e.trim())?"mobile":null}(s);l&&t.push({platform:"ios",id:o,name:s,kind:"device",target:l,booted:!0})}return t}(e.stdout)}catch{return[]}}async function lX(e={}){if("darwin"!==process.platform)throw new H("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await X("xcrun"))throw new H("TOOL_MISSING","xcrun not found in PATH");let t=e8(e.simulatorSetPath),r=await T("xcrun",e7(["list","devices","-j"],{simulatorSetPath:t})),a=[];try{let e=JSON.parse(r.stdout);a=lH(e,t)}catch(e){throw new H("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(a.push({platform:"macos",id:"host-macos-local",name:u.hostname(),kind:"device",target:"desktop",booted:!0}),t)return a;let[n,i]=await Promise.all([lz(),lJ()]);return a=lW(a,n),lW(a,i)}async function lK(e,t,r){let a,n=!!(t.udid||t.serial||t.deviceName);try{a=await tx(e,t,r)}catch(e){if(n||!(e instanceof H)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!n&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!a||"device"===a.kind)){let e=await lq({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new H("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function lY(e){let t=e.platform,r=tN({simulatorSetPath:e8(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=e9(e.androidDeviceAllowlist);return await es("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 H("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|linux|apple with --target mobile|tv|desktop.");if("linux"===n.platform){let e=await lh();return await tx(e,n)}if("android"===n.platform){await aG();let e=await a3({serialAllowlist:a});return await tx(e,n)}if(n.platform){let e=await lX({simulatorSetPath:r});return await lK(e,n,{simulatorSetPath:r})}let i=[];try{i.push(...await a3({serialAllowlist:a}))}catch{}try{i.push(...await lX({simulatorSetPath:r}))}catch{}try{i.push(...await lh())}catch{}return await tx(i,n,{simulatorSetPath:r})},{platform:t,target:e.target})}async function lZ(e,t,r,a,n){let i={requestId:n?.requestId,appBundleId:n?.appBundleId,verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>nG(e,t,r?.activity),openDevice:()=>nW(e),close:t=>nz(e,t),tap:(t,r)=>iy(e,t,r),doubleTap:async(t,r)=>{await iy(e,t,r),await iy(e,t,r)},swipe:(t,r,a,n,i)=>iv(e,t,r,a,n,i),longPress:(t,r,a)=>i_(e,t,r,a),focus:(t,r)=>iD(e,t,r),type:(t,r)=>iN(e,t,r),fill:(t,r,a,n)=>ik(e,t,r,a,n),scroll:(t,r)=>iO(e,t,r),scrollIntoView:(t,r)=>iL(e,t,r),screenshot:t=>i4(e,t),back:t=>iI(e),home:()=>ib(e),rotate:t=>iA(e,t),appSwitcher:()=>iS(e),readClipboard:()=>iB(e),writeClipboard:t=>ij(e,t),setSetting:(t,r,a,n)=>iX(e,t,r,a,n)};case"linux":return{open:e=>ls(e),openDevice:()=>Promise.resolve(),close:e=>ll(e),tap:(e,t)=>s3(e,t),doubleTap:(e,t)=>s8(e,t),swipe:(e,t,r,a,n)=>s7(e,t,r,a,n),longPress:(e,t,r)=>s6(e,t,r),focus:(e,t)=>s9(e,t),type:(e,t)=>lt(e,t),fill:(e,t,r,a)=>lr(e,t,r,a),scroll:(e,t)=>le(e,t),scrollIntoView:()=>{throw new H("UNSUPPORTED_OPERATION","scrollIntoView not yet supported on Linux")},screenshot:e=>lo(e),back:()=>ld(),home:()=>lu(),rotate:()=>{throw new H("UNSUPPORTED_OPERATION","rotate not supported on Linux")},appSwitcher:()=>{throw new H("UNSUPPORTED_OPERATION","appSwitcher not yet supported on Linux")},readClipboard:()=>lf(),writeClipboard:e=>lm(e),setSetting:()=>{throw new H("UNSUPPORTED_OPERATION","setSetting not supported on Linux")}};case"ios":case"macos":{let r,a,{overrides:n,runnerOpts:i}=(r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},a=()=>{if(eX(t.requestId))throw eY()},{runnerOpts:r,overrides:{tap:async(a,n)=>await rs(e,{command:"tap",x:a,y:n,appBundleId:t.appBundleId},r),doubleTap:async(a,n)=>await rs(e,{command:"tapSeries",x:a,y:n,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(a,n,i,o,s)=>await rs(e,{command:"drag",x:a,y:n,x2:i,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(a,n,i)=>await rs(e,{command:"longPress",x:a,y:n,durationMs:i,appBundleId:t.appBundleId},r),focus:async(a,n)=>await rs(e,{command:"tap",x:a,y:n,appBundleId:t.appBundleId},r),type:async(a,n)=>{await rs(e,{command:"type",text:a,delayMs:n,appBundleId:t.appBundleId},r)},fill:async(a,n,i,o)=>{let s=await rs(e,{command:"tap",x:a,y:n,appBundleId:t.appBundleId},r);return await rs(e,{command:"type",text:i,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},r),s},scroll:async(a,n)=>await sq(rs,e,t,r,a,n),scrollIntoView:async(n,i)=>await sB(a=>rs(e,{...a,appBundleId:t.appBundleId},r),a,n,i)}});return{open:(t,r)=>sI(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>sb(e),close:t=>sA(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await oj(t,{surface:r.surface,fullscreen:r.fullscreen}):await sn(e,t,r?.appBundleId,r?.fullscreen)},back:async r=>{await rs(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},i)},home:async()=>{await rs(e,{command:"home",appBundleId:t.appBundleId},i)},rotate:async r=>{await rs(e,{command:"rotate",orientation:r,appBundleId:t.appBundleId},i)},appSwitcher:async()=>{await rs(e,{command:"appSwitcher",appBundleId:t.appBundleId},i)},readClipboard:()=>sD(e),writeClipboard:t=>sk(e,t),setSetting:(t,r,a,n)=>sE(e,t,r,a,n),...n}}default:throw new H("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,i);return eu({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await es("platform_command",async()=>{switch(t){case"open":return lQ(e,o,r,n);case"close":{let e=r[0];if(!e)return{closed:"session",...ed("Closed session")};return await o.close(e),{app:e,...ed(`Closed: ${e}`)}}case"press":return l0(e,o,r,n,i);case"swipe":return l1(e,o,r,n,i);case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new H("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a,...ed(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new H("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t,...ed(`Focused (${e}, ${t})`)}}case"type":{let e=function(e){let t=e[0]?.trim();if(!t||!t.startsWith("@")||t.length<3)return null;let r=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(r)||/^(?:ref|node|element|el)[\w-]*$/i.test(r)?t:null}(r);if(e)throw new H("INVALID_ARGS",`type does not accept a target ref like "${e}"`,{hint:`Use fill ${e} "text" to target that field, or press ${e} then type "text" to append.`});let t=r.join(" ");if(!t)throw new H("INVALID_ARGS","type requires text");let a=lN(n?.delayMs??0,"delay-ms",0,1e4);return await o.type(t,a),{text:t,delayMs:a,...ed(dr("Typed",t))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new H("INVALID_ARGS","fill requires x y text");let i=lN(n?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,a,i),{x:e,y:t,text:a,delayMs:i,...ed(dr("Filled",a))}}case"scroll":return l2(o,r,n);case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new H("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:n?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...ed(`Scrolled into view: ${e}`)};return{text:e,...ed(`Scrolled into view: ${e}`)}}case"pinch":return l3(e,r,n,i);case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new H("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!lS.test(t))throw new H("INVALID_ARGS",`Invalid trigger-app-event event name: ${t}`,{hint:"Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash."});if(e.length>2)throw new H("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new H("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(r);if(Buffer.byteLength(a,"utf8")>8192)throw new H("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof H)throw t;throw new H("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),i=function(e,t,r){var a;let n,i=(n=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,n?.trim()||void 0);if(!i)throw new H("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=i.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new H("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await o.open(i,{appBundleId:n?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link",...ed(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await d.mkdir(p.dirname(e),{recursive:!0}),await o.screenshot(e,{appBundleId:n?.appBundleId,fullscreen:n?.screenshotFullscreen,surface:n?.surface}),{path:e,...ed(`Saved screenshot: ${e}`)}}case"back":return await o.back(n?.backMode),{action:"back",mode:n?.backMode??"in-app",...ed("Back")};case"home":return await o.home(),{action:"home",...ed("Home")};case"rotate":{let e=function(e){if(void 0===e)throw new H("INVALID_ARGS","rotate requires an orientation argument. Use portrait|portrait-upside-down|landscape-left|landscape-right.");switch(e?.trim().toLowerCase()){case"portrait":return"portrait";case"portrait-upside-down":case"upside-down":return"portrait-upside-down";case"landscape-left":case"left":return"landscape-left";case"landscape-right":case"right":return"landscape-right";default:throw new H("INVALID_ARGS",`Invalid rotation: ${e}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}(r[0]);return await o.rotate(e),{action:"rotate",orientation:e,...ed(`Rotated to ${e}`)}}case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...ed("Opened app switcher")};case"clipboard":return l4(o,r);case"keyboard":return l5(e,o,r,n,i);case"settings":return l8(e,o,r,n);case"push":return l6(e,r,n);case"snapshot":return l9(e,r,n,i);case"read":return l7(e,r,n,i);default:throw new H("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}async function lQ(e,t,r,a){let n=r[0],i=r[1];if(r.length>2)throw new H("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!n)return await t.openDevice(),{app:null,...ed("Opened device")};if(void 0!==i){if("android"===e.platform)throw new H("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(aj(n))throw new H("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!aj(i))throw new H("INVALID_ARGS","open <app> <url> requires a valid URL target");return await t.open(n,{activity:a?.activity,appBundleId:a?.appBundleId,url:i}),{app:n,url:i,...ed(`Opened: ${n}`)}}return await t.open(n,{activity:a?.activity,appBundleId:a?.appBundleId}),{app:n,...ed(`Opened: ${n}`)}}async function l0(e,t,r,a,n){let i,[o,s]=r.map(Number);if(Number.isNaN(o)||Number.isNaN(s))throw new H("INVALID_ARGS","press requires x y");if("macos"===e.platform&&a?.surface&&"app"!==a.surface){let e=lb(a);if("primary"!==e)throw new H("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${a.surface} sessions.`);return await oB(o,s,{bundleId:a.appBundleId,surface:a.surface}),{x:o,y:s,...ed(de({x:o,y:s}))}}let l=lb(a);if("primary"!==l){let t=lA({commandLabel:"click",platform:e.platform,button:l,count:a?.count,intervalMs:a?.intervalMs,holdMs:a?.holdMs,jitterPx:a?.jitterPx,doubleTap:a?.doubleTap});if(t)throw t;return"linux"===e.platform?"secondary"===l?await s4(o,s):await s5(o,s):await rs(e,{command:"mouseClick",x:o,y:s,button:l,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x:o,y:s,button:l,...ed(de({x:o,y:s,button:l}))}}let d=lN(a?.count??1,"count",1,200),u=lN(a?.intervalMs??0,"interval-ms",0,1e4),c=lN(a?.holdMs??0,"hold-ms",0,1e4),p=lN(a?.jitterPx??0,"jitter-px",0,100),f=a?.doubleTap===!0;if(f&&c>0)throw new H("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&p>0)throw new H("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&d>1&&0===c&&0===p){let t=await rs(e,{command:"tapSeries",x:o,y:s,count:d,intervalMs:u,doubleTap:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,timingMode:"runner-series",...t,...ed(de({x:o,y:s}))}}return await lx(d,u,async e=>{let[r,a]=function(e,t){if(t<=0)return[0,0];let[r,a]=l_[e%l_.length];return[r*t,a*t]}(e,p),n=o+r,l=s+a;if(f){i??=await t.doubleTap(n,l)??void 0;return}c>0?i??=await t.longPress(n,l,c)??void 0:i??=await t.tap(n,l)??void 0}),q({x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,...i},de({x:o,y:s}))}async function l1(e,t,r,a,n){let i=Number(r[0]),o=Number(r[1]),s=Number(r[2]),l=Number(r[3]);if([i,o,s,l].some(Number.isNaN))throw new H("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let d=lN(r[4]?Number(r[4]):250,"durationMs",16,1e4),u="ios"===e.platform?Math.min(60,Math.max(16,Math.round(d))):d,c=lN(a?.count??1,"count",1,200),p=lN(a?.pauseMs??0,"pause-ms",0,1e4),f=a?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new H("INVALID_ARGS",`Invalid pattern: ${f}`);if(("ios"===e.platform||"macos"===e.platform)&&c>1){let t=await rs(e,{command:"dragSeries",x:i,y:o,x2:s,y2:l,durationMs:u,count:c,pauseMs:p,pattern:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x1:i,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"runner-series",count:c,pauseMs:p,pattern:f,...t,...ed(dt(c,f))}}return await lx(c,p,async e=>{"ping-pong"===f&&e%2==1?await t.swipe(s,l,i,o,u):await t.swipe(i,o,s,l,u)}),q({x1:i,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:c,pauseMs:p,pattern:f},dt(c,f))}async function l2(e,t,r){let a=t[0],n=t[1]?Number(t[1]):void 0,i=r?.pixels;if(!a)throw new H("INVALID_ARGS","scroll requires direction");if(void 0!==n&&!Number.isFinite(n))throw new H("INVALID_ARGS","scroll amount must be a number");if(void 0!==n&&void 0!==i)throw new H("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let o=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new H("INVALID_ARGS",`Unknown direction: ${e}`)}}(a),s=await e.scroll(o,{amount:n,pixels:i});return q({direction:o,...void 0!==n?{amount:n}:{},...void 0!==i?{pixels:i}:{},...s},void 0!==i?`Scrolled ${o} by ${i}px`:void 0!==n?`Scrolled ${o} by ${n}`:`Scrolled ${o}`)}async function l3(e,t,r,a){if("android"===e.platform)throw new H("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&r?.surface&&"app"!==r.surface)throw new H("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let n=Number(t[0]),i=t[1]?Number(t[1]):void 0,o=t[2]?Number(t[2]):void 0;if(Number.isNaN(n)||n<=0)throw new H("INVALID_ARGS","pinch requires scale > 0");return await rs(e,{command:"pinch",scale:n,x:i,y:o,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId}),{scale:n,x:i,y:o,...ed(`Pinched to scale ${n}`)}}async function l4(e,t){let r=(t[0]??"").toLowerCase();if("read"!==r&&"write"!==r)throw new H("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===r){if(1!==t.length)throw new H("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:r,text:await e.readClipboard()}}if(t.length<2)throw new H("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let a=t.slice(1).join(" ");return await e.writeClipboard(a),{action:r,textLength:Array.from(a).length,...ed("Clipboard updated")}}async function l5(e,t,r,a,n){let i=(r[0]??"status").toLowerCase();if("status"!==i&&"get"!==i&&"dismiss"!==i)throw new H("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new H("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===i){let t=await iV(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let t=await iG(e);return{platform:"android",action:"status",visible:t.visible,inputType:t.inputType,type:t.type}}if("ios"===e.platform){if("dismiss"!==i)throw new H("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let t=await rs(e,{command:"keyboardDismiss",appBundleId:a?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,...ed(t.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new H("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}async function l8(e,t,r,a){var n;let[i,o,s,l,d]=r,u="permission"===i?{permissionTarget:s,permissionMode:l}:void 0;eu({level:"debug",phase:"settings_apply",data:{setting:i,state:o,target:s,mode:l,platform:e.platform}});let c=await t.setSetting(i,o,d??a?.appBundleId,u);return c&&"object"==typeof c?q({setting:i,state:o,...c},("string"==typeof(n=c).message&&n.message.length>0?n.message:void 0)??`Updated setting: ${i}`):{setting:i,state:o,...ed(`Updated setting: ${i}`)}}async function l6(e,t,r){let a=t[0]?.trim(),n=t[1]?.trim();if(!a||!n)throw new H("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await lM(n);if("ios"===e.platform)return await sM(e,a,i),{platform:"ios",bundleId:a,...ed(`Pushed notification to ${a}`)};let o=await i2(e,a,i);return{platform:"android",package:a,action:o.action,extrasCount:o.extrasCount,...ed(`Pushed notification to ${a}`)}}async function l9(e,t,r,a){if("linux"===e.platform){let e=await es("snapshot_capture",async()=>await lI(r?.surface),{backend:"linux-atspi"});return{nodes:e.nodes??[],truncated:e.truncated??!1,backend:"linux-atspi"}}if("android"!==e.platform){let t=await es("snapshot_capture",async()=>await rs(e,{command:"snapshot",appBundleId:r?.appBundleId,interactiveOnly:r?.snapshotInteractiveOnly,compact:r?.snapshotCompact,depth:r?.snapshotDepth,scope:r?.snapshotScope,raw:r?.snapshotRaw},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId}),{backend:"xctest"}),a=t.nodes??[];if(0===a.length&&"simulator"===e.kind)throw new H("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:a,truncated:t.truncated??!1,backend:"xctest"}}let n=await es("snapshot_capture",async()=>await iu(e,{interactiveOnly:r?.snapshotInteractiveOnly,compact:r?.snapshotCompact,depth:r?.snapshotDepth,scope:r?.snapshotScope,raw:r?.snapshotRaw}),{backend:"android"});return{nodes:n.nodes??[],truncated:n.truncated??!1,backend:"android",analysis:n.analysis}}async function l7(e,t,r,a){let[n,i]=t.map(Number);if(Number.isNaN(n)||Number.isNaN(i))throw new H("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await iF(e,n,i)??""};if("macos"===e.platform&&r?.surface&&"app"!==r.surface)return{action:"read",text:(await oV(n,i,{bundleId:r.appBundleId,surface:r.surface})).text};let o=await rs(e,{command:"readText",x:n,y:i,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId});return{action:"read",text:"string"==typeof o.text?o.text:"string"==typeof o.message?o.message:""}}function de(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function dt(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function dr(e,t){return`${e} ${Array.from(t).length} chars`}let da=e=>"macos"!==e.platform,dn=e=>"macos"===e.platform||"simulator"===e.kind,di={device:!0},ds={},dl={alert:{apple:{simulator:!0,device:!0},android:{},linux:ds,supports:dn},pinch:{apple:{simulator:!0,device:!0},android:{},linux:ds,supports:dn},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:da},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:da},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di,supports:e=>"android"===e.platform||"linux"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di,supports:da},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:da},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:da},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:da},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:da},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds},rotate:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds,supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:ds},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:di}};function dd(e,t){let r=dl[e];if(!r)return!0;let a=tS(t.platform)?r.apple:"linux"===t.platform?r.linux:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function du(e,t,r,a,n){return{requestId:n??ei().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,screenshotFullscreen:t?.screenshotFullscreen,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:lb(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let dc=eQ(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function dp(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(eE);await t(e);return}if("device"===e.kind)return void await df(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(ex);await t(e.id)}}async function df(e){let t=p.join(u.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(dc/1e3));try{let a=await T("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:dc+3e3}),n=String(a.stdout??""),i=String(a.stderr??""),o=await dm(t);if(0===a.exitCode){if(!o.parsed)throw new H("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:n,stderr:i,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new H("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,tunnelState:t,hint:"Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry."});return}throw new H("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:n,stderr:i,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:dh(n,i)})}catch(t){if(t instanceof H&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),n=String(r.stderr??""),i=Number(r.timeoutMs??dc),o=`CoreDevice did not respond within ${i}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new H("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:i,stdout:a,stderr:n,hint:a||n?dh(a,n):o},t)}throw new H("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,hint:"Reconnect the device, keep it unlocked, and retry."},t instanceof Error?t:void 0)}finally{await d.rm(t,{force:!0}).catch(()=>{})}}async function dm(e){try{let t=await d.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,n="string"==typeof r?r:"string"==typeof a?a:void 0;return n?{tunnelState:n}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function dh(e,t){let r=od(e,t);return r||(`${e}
|
|
37
|
+
${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":ol)}let dw=eQ(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),dg=new Map;async function dy(e){let t=await b.mkdtemp(p.join(u.tmpdir(),"agent-device-materialized-"));try{let r=await db(e.installablePath,p.join(t,"installable")),a=e.archivePath?await db(e.archivePath,p.join(t,"archive")):void 0,n=i.randomUUID(),o=e.ttlMs??dw,s=Date.now()+o,l=setTimeout(()=>{dv(n)},o);return dg.set(n,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:n,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await b.rm(t,{recursive:!0,force:!0}),e}}async function dv(e,t){let r=dg.get(e);if(!r)throw new H("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new H("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),dg.delete(e),await b.rm(r.rootPath,{recursive:!0,force:!0})}async function dI(e){let t=Array.from(dg.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await dv(e)}))}async function db(e,t){let r=await b.stat(e);await b.mkdir(t,{recursive:!0});let a=p.join(t,p.basename(e));return r.isDirectory()?await b.cp(e,a,{recursive:!0}):await b.copyFile(e,a),a}async function dA(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new H("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await dp(e.session.device),e.session.device}if(!r)throw new H("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await lY(e.flags??{});return await dp(a),a}async function dS(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);try{let e,i,o,s=(i=function(e){let t=e.meta?.installSource;if(!t)throw new H("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new H("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new H("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===i.kind?{source:{kind:"path",path:ai(o,t.meta?.tenantId)},cleanup:()=>{ao(o)}}:{source:i,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new H("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await dA({session:n,flags:t.flags});if(!dd("install",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let u=eK(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:i}=await Promise.resolve(eE),{prepareIosInstallArtifact:o}=await Promise.resolve(eO),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await dy({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:l.ttlMs})),await i(d,c.installablePath),!c.bundleId)throw new H("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=q(o,d_(o));return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await dv(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await Promise.resolve(ek),{installAndroidInstallablePathAndResolvePackageName:p}=await Promise.resolve(eD),f=await c(s.source,{signal:u});try{l.enabled&&(e=await dy({archivePath:f.archivePath,installablePath:f.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:l.ttlMs}));let i=await p(d,f.installablePath,f.packageName);if(!i)throw new H("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await Promise.resolve(eD),s=o(i),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:i,...s?{appName:s}:{},launchTarget:i,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=q(u,d_(u));return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await dv(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await f.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:et(e)}}}function d_(e){return`Installed: ${eS(e)}`}async function dN(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new H("INVALID_ARGS","release_materialized_paths requires a materializationId");return await dv(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:et(e)}}}let dx=eQ(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),dD=eQ(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function dk(e,t,r){return t||dM(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function dM(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function dE(e){return"ios"===e.platform&&"simulator"===e.kind}async function dO(e,t){dE(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function dL(e){let t=dM(e.flags)||!e.session?await lY(e.flags??{}):await dC(e.session.device);return!1!==e.ensureReady&&await dp(t),t}async function dC(e){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let t={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await lY(t)}catch(e){if(!(e instanceof H)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await lY({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function dP(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 dR="shared_prefs/ReactNativeDevPrefs.xml",dT="debug_http_host",d$="dev_server_https",dF="RCT_jsLocation",dU="RCT_packager_scheme",dG="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",dV='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function dB(e){return void 0!==dj(e)}function dj(e){if(!e)return;let t=d1(e.metroHost),r=d3(e.metroPort),a="http",n=d1(e.bundleUrl);if(n){var i;let e;try{e=new h(n)}catch(e){throw new H("INVALID_ARGS",`Invalid runtime bundle URL: ${n}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=d1(e.hostname),r??=d3(e.port.length>0?Number(e.port):"https:"===(i=e.protocol)?443:"http:"===i?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function dq(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let n=dj(a);if(n){if("android"===t.platform)return void await dW(t,r,n);"ios"===t.platform&&"simulator"===t.kind&&await dK(t,r,n)}}async function dH(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await dz(t,r);"ios"===t.platform&&"simulator"===t.kind&&await dY(t,r)}}async function dW(e,t,r){var a,n,i,o,s,l;let d,u;d2(t);let c=(a=await dJ(e,t),n=dT,i=`${r.host}:${r.port}`,d=` <string name="${d4(n)}">${d4(i)}</string>`,dQ(d0(a,n),d));o=c,s=d$,l="https"===r.scheme,u=` <boolean name="${d4(s)}" value="${l?"true":"false"}" />`,c=dQ(d0(o,s),u),await dX(e,t,c)}async function dz(e,t){d2(t);let r=await dJ(e,t),a=d0(r,dT),n=d0(a,d$);n!==r&&await dX(e,t,n)}async function dJ(e,t){let r=await T("adb",aU(e,["shell","run-as",t,"cat",dR]),{allowFailure:!0});return 0!==r.exitCode?dV:dZ(r.stdout)}async function dX(e,t,r){let a=aU(e,["shell","run-as",t,"id"]),n=await T("adb",a,{allowFailure:!0});if(0!==n.exitCode){let e=d5(n.stdout,n.stderr);throw new H("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,hint:e?dG:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await T("adb",aU(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await T("adb",aU(e,["shell","run-as",t,"tee",dR]),{stdin:r.trimEnd()})}catch(a){let e=B(a);if("TOOL_MISSING"===e.code)throw e;let r=d5("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new H("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?dG:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function dK(e,t,r){await T("xcrun",te(e,["spawn",e.id,"defaults","write",t,dF,"-string",`${r.host}:${r.port}`])),await T("xcrun",te(e,["spawn",e.id,"defaults","write",t,dU,"-string",r.scheme]))}async function dY(e,t){await T("xcrun",te(e,["spawn",e.id,"defaults","delete",t,dF]),{allowFailure:!0}),await T("xcrun",te(e,["spawn",e.id,"defaults","delete",t,dU]),{allowFailure:!0})}function dZ(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
38
|
+
`:dV}function dQ(e,t){return dZ(e).replace("</map>",`${t}
|
|
39
|
+
</map>`)}function d0(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return dZ(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function d1(e){let t=e?.trim();return t&&t.length>0?t:void 0}function d2(e){if("binary"!==na(e))return;let t=nn(e);throw new H("INVALID_ARGS",t,{package:e,hint:t})}function d3(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function d4(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function d5(e,t){let r=`${e}
|
|
40
|
+
${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}let d8=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function d6(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function d9(e){let t=e?.trim();return t&&t.length>0?t:void 0}function d7(e,t){if(void 0!==e){if("string"!=typeof e)throw new H("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return d9(e)}}function ue(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new H("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function ut(e){if("ios"===e||"android"===e)return e}async function ur(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:n}=e;!t||!n?.appBundleId||!dB(r)||dB(a)||await dH({device:n.device,appId:n.appBundleId})}async function ua(e){var t,r;let{req:a,sessionName:n,sessionStore:i}=e,o=(a.positionals?.[0]??"show").toLowerCase(),s=i.get(n),l=i.getRuntimeHints(n);if(!["set","show","clear"].includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===o){dB(l)&&s?.appBundleId&&await dH({device:s.device,appId:s.appBundleId});let e=i.clearRuntimeHints(n);return{ok:!0,data:{session:n,cleared:e}}}if("show"===o)return{ok:!0,data:{session:n,configured:!!l,runtime:l}};let d=ut(a.flags?.platform??l?.platform??s?.device.platform);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first."}};if(s&&s.device.platform!==d)return{ok:!1,error:{code:"INVALID_ARGS",message:`runtime set targets ${d}, but session "${n}" is already bound to ${s.device.platform}.`}};let u={platform:(t=a.flags,r={platform:d,metroHost:d9(t?.metroHost),metroPort:ue(t?.metroPort),bundleUrl:d9(t?.bundleUrl),launchUrl:d9(t?.launchUrl)}).platform??l?.platform,metroHost:r.metroHost??l?.metroHost,metroPort:r.metroPort??l?.metroPort,bundleUrl:r.bundleUrl??l?.bundleUrl,launchUrl:r.launchUrl??l?.launchUrl};return 0===d6(u)?{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."}}:(i.setRuntimeHints(n,u),{ok:!0,data:{session:n,configured:!0,runtime:u}})}let un="open-command-roundtrip",ui="Not implemented for this platform in this release.",uo=new Set(["app","desktop","frontmost-app"]);async function us(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await oT();return{appBundleId:t.bundleId,appName:t.appName}}let ul=[250,400];function ud(e,t,r=e.snapshot){if("android"!==e.device.platform)return;let a=r?.comparisonSafe===!0;e.androidSnapshotFreshness={action:t,markedAt:Date.now(),baselineCount:r?.nodes.length??0,baselineSignatures:a?uf(r?.nodes??[]):void 0,routeComparable:a}}function uu(e){if(!e||"android"!==e.device.platform)return;let t=e.androidSnapshotFreshness;if(t)return Date.now()-t.markedAt>2500?void delete e.androidSnapshotFreshness:t}function uc(e){e&&"android"===e.device.platform&&delete e.androidSnapshotFreshness}function up(e){return"press"===e||"click"===e||"back"===e||"open"===e}function uf(e){return e.map(e=>[e.depth??0,e.type??"",e.role??"",e.label??"",e.value??"",e.identifier??"",!1===e.enabled?"disabled":"enabled",!0===e.selected?"selected":"unselected",!0===e.hittable?"hittable":"not-hittable"].join("|"))}function um(e,t){return!(e<12)&&t<=Math.floor(.2*e)}async function uh(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return aj(t)?"macos"===e.platform?void 0:"device"===e.kind?aq(r,t):void 0:await uw(e,t)}async function uw(e,t){try{let{resolveIosApp:r}=await Promise.resolve(eE);return await r(e,t)}catch{return}}async function ug(e,t){if(!("android"!==e.platform||!t||aj(t)))try{let{resolveAndroidApp:r}=await Promise.resolve(eD),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function uy(e,t,r,a){return await uh(e,t,r)??await a(e,t)??("android"===e.platform&&t&&aj(t)?r:void 0)}function uv(e){return{ok:!1,error:{code:"INVALID_ARGS",message:e}}}function uI(e,t,r,a){try{return function(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:n}=e;if(("macos"===t.platform||"linux"===t.platform)&&!r)return n??"app";if("linux"===t.platform){if(!r)return"app";let e=eN(r);if(!uo.has(e))throw new H("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new H("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new H("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let i=r?eN(r):"app";if("app"!==i&&"menubar"!==i&&a)throw new H("INVALID_ARGS",`open --surface ${i} does not accept an app target`);return i}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return{ok:!1,error:{code:e instanceof H?e.code:"INVALID_ARGS",message:String(e.message)}}}}function ub(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:n}=e;return t?r&&aj(r)?uv("open --relaunch does not support URL targets."):"app"!==a?uv("open --relaunch is supported only for app surfaces."):"android"===n.platform&&r&&"binary"===na(r)?uv(nn(r)):null:null}async function uA(e){let{req:t,sessionName:r,sessionStore:a,device:n,surface:i,openTarget:o,existingSession:s}=e;await dp(n);let{appBundleId:l,appName:d}=await uS({device:n,surface:i,openTarget:o,existingAppBundleId:s?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:n}=e,i=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new H("INVALID_ARGS","open runtime must be an object.");let n=Object.keys(t).find(e=>!d8.includes(e));if(n)throw new H("INVALID_ARGS",`Invalid open runtime field: ${n}. Supported fields are ${d8.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new H("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new H("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:d7(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new H("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return ue(e)}}(t.metroPort),bundleUrl:d7(t.bundleUrl,"bundleUrl"),launchUrl:d7(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:ut(n.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let n=r?.platform,i=ut(n);if(a.platform&&r&&!i)throw new H("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${n}.`);if(a.platform&&i&&a.platform!==i)throw new H("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${n}. Clear the runtime hints or use a different session.`);return i&&a.platform!==i?{...a,platform:i}:a}(r,a,n),previousRuntime:i,replacedStoredRuntime:!1}:{runtime:o&&d6(o)>0?o:void 0,previousRuntime:i,replacedStoredRuntime:!0}}(e)}}catch(t){let e=B(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}({req:t,sessionStore:a,sessionName:r,device:n});if(!u.ok)return{type:"response",response:u.response};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await ur({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function uS(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:n}=e,i=await us(r);return{appBundleId:i.appBundleId??await uy(t,a,n,ug),appName:i.appName??a}}let u_=new Map;async function uN(e){let{device:t,closeTarget:r,outFlag:a,context:n}=e;"android"!==t.platform&&await re(t.id),await lZ(t,"close",[r],a,n),await dO(t,dx)}async function ux(e){let{runtime:t,device:r,req:a,logPath:n,appBundleId:i,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let d=s[0]?.trim();!d||aj(d)||await lZ(r,"open",[l],a.flags?.out,{...du(n,a.flags,i,o)})}async function uD(e){var t,r,a;let{req:n,sessionName:i,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:p,appBundleId:f,runtime:m,existingSession:h}=e,w=n.flags?.relaunch===!0,g=h?.trace?.outPath;if(w&&d){let e=f??d;await uN({device:l,closeTarget:e,outFlag:n.flags?.out,context:{...du(s,n.flags,f??h?.appBundleId,g)}})}await dq({device:l,appId:f,runtime:m});let y=Date.now();await lZ(l,"open",u,n.flags?.out,{...du(s,n.flags,f)}),await ux({runtime:m,device:l,req:n,logPath:s,appBundleId:f,traceLogPath:g,openPositionals:u});let v=d?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:un,appTarget:d,appBundleId:f}:void 0;if(await dO(l,dD),eX(n.meta?.requestId)){let e=eY();return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}h&&ud(h,"open",h.snapshot);let I=function(e){let{existingSession:t,sessionName:r,device:a,surface:n,appBundleId:i,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:n,appBundleId:i,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:n,appBundleId:i,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:i,device:l,surface:p,appBundleId:f,appName:c,saveScript:!!n.flags?.saveScript});void 0!==n.runtime&&(t=o,r=i,(a=m)&&(0===d6(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let b=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:n,startup:i,device:o,runtime:s,runtimeHintCount:l}=e,d={session:t,surface:n};return r&&(d.appName=r),a&&(d.appBundleId=a),i&&(d.startup=i),s&&l(s)>0&&(d.runtime=s),o&&(d.platform=o.platform,d.target=o.target??"mobile",d.device=o.name,d.id=o.id,d.kind=o.kind,"android"===o.platform&&(d.serial=o.id)),o?.platform==="ios"&&(d.device_udid=o.id,d.ios_simulator_device_set=o.simulatorSetPath??null),{...d,...ed(`Opened: ${r??a??t}`)}}({sessionName:i,appName:c,appBundleId:f,surface:p,startup:v,device:l,runtime:m,runtimeHintCount:d6});return o.recordAction(I,{command:"open",positionals:u,flags:n.flags??{},runtime:void 0!==n.runtime?m:void 0,result:b}),o.set(i,I),{ok:!0,data:b}}async function uk(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e;if(n.has(r)){let e=n.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:`Session "${r}" not found.`}};let i=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(i?e.appName:void 0),l=uI(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return i?uv("open --relaunch requires an app name or an active session app."):uv("Session already active. Close it first or pass a new --session name.");let d=ub({shouldRelaunch:i,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await dC(e.device),c=await uA({req:t,sessionName:r,sessionStore:n,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await uD({req:t,sessionName:r,sessionStore:n,logPath:a,device:u,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let i=t.flags?.relaunch===!0,o=t.positionals?.[0];if(i&&!o)return uv("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&aj(r)?uv("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===na(r)?uv(nn(r)):null:null}({shouldRelaunch:i,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await lY(t.flags??{}),d=uI(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=ub({shouldRelaunch:i,openTarget:o,surface:d,device:l});return u||await tA(u_,l.id,async()=>{let e=n.toArray().find(e=>e.device.id===l.id);if(e)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${e.name}".`,details:{session:e.name,deviceId:l.id,deviceName:l.name}}};let i=await uA({req:t,sessionName:r,sessionStore:n,device:l,surface:d,openTarget:o});return"response"===i.type?i.response:await uD({req:t,sessionName:r,sessionStore:n,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:i.details.appBundleId,appName:i.details.appName,runtime:i.details.runtime,surface:d})})}async function uM(e){let t=await T("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function uE(e){let{device:t,shutdownRequested:r}=e;if(r&&(dE(t)||"android"===t.platform&&"emulator"===t.kind))try{return dE(t)?await oh(t):await uM(t)}catch(t){let e=et(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function uO(e){if(await re(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await oU("dismiss",t).catch(t=>{eu({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function uL(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,i=n.get(r);if(!i)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};i.appLog&&await r7(i.appLog),t.positionals&&t.positionals.length>0&&(("ios"===i.device.platform||"macos"===i.device.platform)&&await uO(i),await lZ(i.device,"close",t.positionals,t.flags?.out,{...du(a,t.flags,i.appBundleId,i.trace?.outPath)}),await dO(i.device,dx)),("ios"===i.device.platform||"macos"===i.device.platform)&&await uO(i),dB(n.getRuntimeHints(r))&&i.appBundleId&&await dH({device:i.device,appId:i.appBundleId}).catch(()=>{}),n.recordAction(i,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...ed(`Closed: ${r}`)}}),t.flags?.saveScript&&(i.recordSession=!0),n.writeSessionLog(i),await dI(r).catch(()=>{}),n.delete(r);let o=await uE({device:i.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:q({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...ed(`Closed: ${r}`)}}}function uC(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}let uP={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve(eE);return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve(eD);return await a(e,t,r)}},uR={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve(eE),n=await a(e,r,{appIdentifierHint:t});return{bundleId:n.bundleId,appName:n.appName,launchTarget:n.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await Promise.resolve(eD),n=await a(e,r);return{package:n.packageName,appName:n.appName,launchTarget:n.launchTarget}}};async function uT(e){let{req:t,command:r,sessionName:a,sessionStore:n,deployOps:i}=e,o=n.get(a),l=t.flags??{},d=dk(r,o,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return uC("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let p=t.meta?.uploadedArtifactId;try{var f;let e,a=p?ai(p,t.meta?.tenantId):rx.expandHome(c);if(!s.existsSync(a))return uC("INVALID_ARGS",`App binary not found: ${a}`);let d=await dL({session:o,flags:l,ensureReady:!1});if(!dd(r,d))return uC("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await i.ios(d,u,a),r=t.bundleId;e=r?{app:u,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await i.android(d,u,a),r=t.package;e=r?{app:u,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=q(e,(f=e,`Installed: ${f.appName??F(f)}`));return o&&n.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{p&&ao(p)}}let u$=["platform","target","device","udid","serial","verbose","out"];async function uF(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${a}.`}};let n=e.flags?.batchMaxSteps??em;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 a=R(e.flags?.batchSteps,n),i=Date.now(),o=[];for(let n=0;n<a.length;n+=1){let i=a[n],s=await uU(e,t,i,r,n+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${i.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:i.command,positionals:i.positionals,executed:n,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-i,results:o}}}catch(t){let e=B(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function uU(e,t,r,a,n){let i=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:n,...i}=t??{},o=e??{};for(let e of u$)void 0===i[e]&&void 0!==o[e]&&(i[e]=o[e]);return i}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-i;return s.ok?{ok:!0,step:n,result:{step:n,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:n,error:s.error}}async function uG(e){let t,r,a,{deviceName:n,runtime:i,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new H("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await uV({deviceName:n,runtime:i,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await uB({deviceName:n,runtime:i,simctlOpts:u})).udid,r=await uj(t,u),a=!0)}else t=(await uB({deviceName:n,runtime:i,simctlOpts:u})).udid,r=await uj(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:n,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:n,runtime:r,created:a,booted:c}}async function uV(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,n=await T("xcrun",e7(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:i7});if(0!==n.exitCode)return null;try{let e=JSON.parse(String(n.stdout??""));for(let[a,n]of Object.entries(e.devices??{}))if(!r||uq(a).includes(uq(r))){for(let e of n)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function uB(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,n=r?["create",t,t,r]:["create",t,t],i=await T("xcrun",e7(n,a),{allowFailure:!0});if(0!==i.exitCode)throw new H("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(i.stdout??""),stderr:String(i.stderr??""),exitCode:i.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(i.stdout??"").trim();if(!o)throw new H("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(i.stdout??""),stderr:String(i.stderr??"")});return{udid:o}}async function uj(e,t){let r=await T("xcrun",e7(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:i7});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function uq(e){return e.toLowerCase().replace(/[._-]/g,"")}async function uH(e){let{req:t,sessionName:r,sessionStore:a}=e;if("session_list"===t.command)return{ok:!0,data:{sessions:a.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",surface:e.surface??"app",device:e.device.name,id:e.device.id,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("ensure-simulator"===t.command)try{let e=t.flags??{},r=e.device,a=e.runtime,n=e8(e.iosSimulatorDeviceSet);if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let i=await uG({deviceName:r,runtime:a,simulatorSetPath:n,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:dp});return{ok:!0,data:{udid:i.udid,device:i.device,runtime:i.runtime,ios_simulator_device_set:n??null,created:i.created,booted:i.booted}}}catch(t){let e=B(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===t.command)try{let e=[],r=e9(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,n=tN({simulatorSetPath:e8(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await Promise.resolve(ex);e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await Promise.resolve(eM);e.push(...await t({simulatorSetPath:n}))}else{if("apple"!==a){let{listAndroidDevices:t}=await Promise.resolve(ex);try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await Promise.resolve(eM);try{e.push(...await t({simulatorSetPath:n}))}catch{}}let i="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?i.filter(e=>(e.target??"mobile")===t.flags?.target):i).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=B(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===t.command){let e=a.get(r),n=t.flags??{},i=dk(t.command,e,n);if(i)return i;let o=await dL({session:e,flags:n,ensureReady:!0});if(!dd("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(tS(o.platform)){let{listIosApps:e}=await Promise.resolve(eE);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(eD);return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function uW(e){let{ensureAndroidEmulatorBooted:t}=await Promise.resolve(ex);return await t(e)}let uz='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',uJ='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function uX(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r),i=t.flags??{},o=i.platform;if(!n&&"string"==typeof i?.session&&i.session.trim().length>0)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"ios"===o?`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 s=dk("appstate",n,i);if(s)return s;let l=(n?.device.platform==="ios"||n?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!dM(e))return!0;let r=e?.platform;return!(r&&!t_(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(i,n);if("ios"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:uz}};if("macos"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:uJ}};if(l&&n){let e=n.appName??n.appBundleId;if(!n.appName&&!n.appBundleId){if("macos"===n.device.platform&&n.surface&&"app"!==n.surface&&"frontmost-app"!==n.surface)return{ok:!0,data:{platform:n.device.platform,appName:n.surface,appBundleId:n.appBundleId,source:"session",surface:n.surface}};let e="macos"===n.device.platform?"macOS":"iOS";return{ok:!1,error:{code:"COMMAND_FAILED",message:`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`}}}return{ok:!0,data:{platform:n.device.platform,appName:e??"unknown",appBundleId:n.appBundleId,source:"session",surface:n.surface??"app",..."ios"===n.device.platform?{device_udid:n.device.id,ios_simulator_device_set:n.device.simulatorSetPath??null}:{}}}}let d=await dL({session:n,flags:i,ensureReady:!0});if("ios"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:uz}};if("macos"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:uJ}};let{getAndroidAppState:u}=await Promise.resolve(eD),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function uK(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,n=a.get(r),i=t.flags??{},o=dk(t.command,n,i);if(o)return o;let s="android"===(i.platform??n?.device.platform),l=!0===i.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=dP({flags:i,sessionDevice:n?.device}),u=s&&!!d,c=!1;try{e=await dL({session:n,flags:i,ensureReady:!1})}catch(r){let t=B(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 uW({avdName:d,serial:i.serial,headless:l}),c=!0}if(i.target&&(e.target??"mobile")!==i.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${i.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=dP({flags:i,sessionDevice:n?.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 uW({avdName:t,serial:i.serial,headless:!0})}await dp(e)}else("android"!==e.platform||!0!==e.booted)&&await dp(e);return dd("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"}}}return"appstate"===t.command?await uX({req:t,sessionName:r,sessionStore:a}):null}let uY="adb-shell-dumpsys-cpuinfo",uZ="adb-shell-dumpsys-meminfo";async function uQ(e,t){try{let r=await T("adb",aU(e,["shell","dumpsys","cpuinfo"]),{timeoutMs:15e3});return function(e,t,r){var a,n,i;let o=new Set,s=0;for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let i=e.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!i)continue;let l=Number(i[1]),d=i[2];Number.isFinite(l)&&(a=d,n=t,a===n||a.startsWith(`${n}:`))&&(s+=l,o.add(d))}return{usagePercent:(i=s,Math.round(10*i)/10),measuredAt:r,method:uY,matchedProcesses:[...o]}}(r.stdout,t,new Date().toISOString())}catch(e){throw u1("cpu",t,e)}}async function u0(e,t){try{let r=await T("adb",aU(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new H("COMMAND_FAILED",`Android meminfo did not find a running process for ${t}`,{metric:"memory",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf."});let a=u2(e,"TOTAL PSS")??function(e){for(let t of e.split("\n")){let e=t.trim();if(!/^TOTAL\b(?!\s+PSS:)/.test(e))continue;let r=e.split(/\s+/).slice(1).find(e=>null!==u3(e));if(!r)break;return u3(r)??void 0}}(e);if(void 0===a)throw new H("COMMAND_FAILED",`Failed to parse Android meminfo output for ${t}`,{metric:"memory",package:t,hint:"Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging."});return{totalPssKb:a,totalRssKb:u2(e,"TOTAL RSS"),measuredAt:r,method:uZ}}(r.stdout,t,new Date().toISOString())}catch(e){throw u1("memory",t,e)}}function u1(e,t,r){return r instanceof H&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new H(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof H?r:new H("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function u2(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return u3(a[1])??void 0}function u3(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let u4="ps-process-snapshot",u5="ps-process-snapshot",u8="CPU and memory sampling are not yet implemented for physical iOS devices.";async function u6(e,t){if("ios"===e.platform&&"device"===e.kind)throw new H("UNSUPPORTED_OPERATION",u8,{platform:e.platform,deviceKind:e.kind,appBundleId:t,hint:"Use an iOS simulator or macOS app session for CPU/memory perf sampling for now."});let r=await u9(e,t),a=await ct(e,r);if(0===a.length)throw new H("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,hint:"Run open <app> for this session again to ensure the Apple app is active, then retry perf."});let n=new Date().toISOString(),i=ru(a.map(e=>p.basename(cr(e.command))));return{cpu:{usagePercent:Math.round(10*a.reduce((e,t)=>e+t.cpuPercent,0))/10,measuredAt:n,method:u4,matchedProcesses:i},memory:{residentMemoryKb:Math.round(a.reduce((e,t)=>e+t.rssKb,0)),measuredAt:n,method:u5,matchedProcesses:i}}}async function u9(e,t){let r="macos"===e.platform?await u7(t):await ce(e,t),a="macos"===e.platform?p.join(r,"Contents","Info.plist"):p.join(r,"Info.plist"),n=await og(a,"CFBundleExecutable");if(!n)throw new H("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:n,executablePath:"macos"===e.platform?p.join(r,"Contents","MacOS",n):void 0}}async function u7(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await T("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new H("COMMAND_FAILED",`Failed to resolve macOS app bundle for ${e}`,{appBundleId:e,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let a=r.stdout.split("\n").map(e=>e.trim()).find(e=>e.endsWith(".app"));if(!a)throw new H("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function ce(e,t){let r=te(e,["get_app_container",e.id,t,"app"]),a=await T("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new H("COMMAND_FAILED",`Failed to resolve iOS simulator app container for ${t}`,{appBundleId:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Ensure the iOS simulator app is installed and booted, then retry perf."});let n=a.stdout.trim();if(0===n.length)throw new H("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return n}async function ct(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:te(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let a=e.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!a)continue;let n=Number(a[1]),i=Number(a[2]),o=Number(a[3]),s=a[4].trim();Number.isFinite(n)&&Number.isFinite(i)&&Number.isFinite(o)&&t.push({pid:n,cpuPercent:i,rssKb:o,command:s})}return t})((await T("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let n;return r=e.command,a=t,n=cr(r),!!(a.executablePath&&(n===a.executablePath||r.startsWith(`${a.executablePath} `)))||p.basename(n)===a.executableName})}function cr(e){let[t=""]=e.trim().split(/\s+/,1);return t}async function ca(e){var t,r;let a=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===un&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:un,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)}(e.actions),n=a.at(-1),i=n?{available:!0,lastDurationMs:n.durationMs,lastMeasuredAt:n.measuredAt,method:un,sampleCount:a.length,samples:a}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:un},o={session:e.name,platform:e.device.platform,device:e.device.name,deviceId:e.device.id,metrics:{startup:i,fps:{available:!1,reason:ui},memory:{available:!1,reason:ui},cpu:{available:!1,reason:ui}},sampling:{startup:{method:un,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"},...function(e){if("android"===e.device.platform)return{memory:{method:uZ,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:uY,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"}};var t=e.device;if("ios"===t.platform&&"device"===t.kind)return{memory:{method:u5,description:u8,unit:"kB"},cpu:{method:u4,description:u8,unit:"percent"}};let r="macos"===t.platform?"host ps for the running macOS app executable resolved from the bundle ID.":"xcrun simctl spawn ps for the running iOS simulator app executable resolved from the bundle ID.";return{memory:{method:u5,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:u4,description:`Recent CPU usage snapshot from ${r}`,unit:"percent"}}}(e)}};if("android"!==(t=e).device.platform&&"ios"!==t.device.platform&&"macos"!==t.device.platform)return o;if("ios"===(r=e).device.platform&&"device"===r.device.kind)return o.metrics.memory={available:!1,reason:u8},o.metrics.cpu={available:!1,reason:u8},o;if(!e.appBundleId){let t="android"===e.device.platform?"No Android app package is associated with this session. Run open <app> first.":"No Apple app bundle ID is associated with this session. Run open <app> first.";return o.metrics.memory={available:!1,reason:t},o.metrics.cpu={available:!1,reason:t},o}let[s,l]=await cn(e);return o.metrics.memory=ci(s),o.metrics.cpu=ci(l),o}async function cn(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,a]=await Promise.allSettled([u0(e.device,t),uQ(e.device,t)]);return[r,a]}try{let r=await u6(e.device,t);return[{status:"fulfilled",value:r.memory},{status:"fulfilled",value:r.cpu}]}catch(e){return[{status:"rejected",reason:e},{status:"rejected",reason:e}]}}function ci(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=et(e.reason);return{available:!1,reason:t.message,error:t}}let co=["path","start","stop","doctor","mark","clear"],cs=`logs requires ${co.slice(0,-1).join(", ")}, or ${co.at(-1)}`,cl=["dump","log"],cd=`network requires ${cl.join(" or ")}`,cu=["summary","headers","body","all"],cc=`network include mode must be one of: ${cu.join(", ")}`;async function cp(e){let{req:t}=e;return"perf"===t.command?cf(e):"logs"===t.command?cm(e):"network"===t.command?cv(e):null}async function cf(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}};try{return{ok:!0,data:await ca(a)}}catch(e){return{ok:!1,error:et(e)}}}async function cm(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!dd("logs",n.device))return{ok:!1,error:et(new H("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let i=(t.positionals?.[0]??"path").toLowerCase(),o=!!t.flags?.restart;return co.includes(i)?o&&"clear"!==i?{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}}:"path"===i?function(e,t,r){let a=r.resolveAppLogPath(t),n=function(e){if(!s.existsSync(e))return{exists:!1,sizeBytes:0};let t=s.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(a);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android",sizeBytes:n.sizeBytes,modifiedAt:n.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>'}}}(n,r,a):"doctor"===i?ch(n,r,a):"mark"===i?function(e,t,r){let a,n=e.positionals?.slice(1).join(" ")??"",i=r.resolveAppLogPath(t);return r5(i),a=`[agent-device][mark][${new Date().toISOString()}] ${n.trim()||"marker"}
|
|
41
|
+
`,s.appendFileSync(i,a,"utf8"),{ok:!0,data:{path:i,marked:!0}}}(t,r,a):"clear"===i?cw(n,r,a,o):"start"===i?cg(n,r,a):"stop"===i?cy(n,r,a):{ok:!1,error:{code:"INVALID_ARGS",message:cs}}:{ok:!1,error:{code:"INVALID_ARGS",message:cs}}}async function ch(e,t,r){let a=r.resolveAppLogPath(t),n=await ae(e.device,e.appBundleId);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:n.checks,notes:n.notes}}}async function cw(e,t,r,a){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&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let n=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:at(n)};e.appLog&&await r7(e.appLog);let i=at(n),o=r.resolveAppLogPidPath(t);try{let a=await r6(e.device,e.appBundleId,n,o);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:n,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}}),{ok:!0,data:{...i,restarted:!0}}}catch(a){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:et(a)}}}async function cg(e,t,r){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};let a=r.resolveAppLogPath(t),n=r.resolveAppLogPidPath(t);try{let i=await r6(e.device,e.appBundleId,a,n);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:i.backend,outPath:a,startedAt:i.startedAt,getState:i.getState,stop:i.stop,wait:i.wait}}),{ok:!0,data:{path:a,started:!0}}}catch(e){return{ok:!1,error:et(e)}}}async function cy(e,t,r){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let a=e.appLog.outPath;return await r7(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function cv(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!dd("network",n.device))return{ok:!1,error:et(new H("UNSUPPORTED_OPERATION","network is not supported on this device"))};let i=(t.positionals?.[0]??"dump").toLowerCase();if(!cl.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:cd}};let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],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=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"network include mode was provided both positionally and via --include with different values"}}};let a=(r??t??"summary").toLowerCase();return cu.includes(a)?{ok:!0,include:a}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:cc}}}}(t);if(!s.ok)return s.response;let{include:l}=s,d=await r8({device:n.device,appBundleId:n.appBundleId,appLogState:n.appLog?.getState(),appLogStartedAt:n.appLog?.startedAt,appLogPath:a.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...d.dump,active:!!n.appLog,state:n.appLog?.getState()??"inactive",backend:d.backend,notes:d.notes}}}let cI=new Set(["ios","android","macos","linux"]);function cb(e,t,r){let a=e[t];if(void 0!==a)throw new H("INVALID_ARGS",a===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(a)} vs ${String(r)}.`);e[t]=r}function cA(e){return!!e&&!Number.isNaN(Number(e))}let cS=/[*?[\]{}]/;async function c_(e){let t,{filePath:r,sessionName:a,requestId:n,timeoutMs:i,platform:o,runReplay:s,cleanupSession:l}=e;eW(n);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:n,artifactPaths:d}).catch(e=>{let t=B(e);return{ok:!1,error:{code:t.code,message:t.message}}}).finally(()=>{eJ(n)});try{return"number"==typeof i?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,ez(n),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(i,[...d]))},i)})]):await c}finally{t&&clearTimeout(t),u&&(await cN(c)||eu({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:n,graceMs:2e3}}));try{await l(a)}catch(e){eu({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:B(e).message}})}}}async function cN(e){return await Promise.race([e.then(()=>!0),S(2e3).then(()=>!1)])}async function cx(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:n}=e;if((t.positionals?.length??0)===0)return{ok:!1,error:{code:"INVALID_ARGS",message:"test requires at least one path or glob"}};try{var i,o,l,d,u,c;let e,f,m,h,w,g=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,n=r??process.cwd(),i=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let n=rx.expandHome(e,t);if(s.existsSync(n)){let t=s.statSync(n);if(t.isDirectory())return s.globSync("**/*.ad",{cwd:n}).map(e=>p.join(n,e));if(t.isFile()){if(".ad"!==p.extname(n))throw new H("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[n]}return[]}if(r=e,!cS.test(r)&&(a=n,!cS.test(a)))throw new H("INVALID_ARGS",`test input not found: ${e}`);let i=p.isAbsolute(n)?n:e;return s.globSync(i,{cwd:p.isAbsolute(n)?void 0:t}).map(e=>p.isAbsolute(e)?e:p.resolve(t,e)).filter(e=>".ad"===p.extname(e)&&function(e){try{return s.statSync(e).isFile()}catch{return!1}}(e))})(e,n)))].map(e=>p.normalize(e)).sort((e,t)=>e.localeCompare(t)),o=[];for(let e of i){var l,d;let t=function(e){let t=e.split(/\r?\n/),r={};for(let e of t){let t=e.trim();if(0===t.length||t.startsWith("#"))continue;if(!t.startsWith("context "))break;let a=t.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&cI.has(e)&&cb(r,"platform",e)}let n=t.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&cb(r,"timeoutMs",Math.floor(e))}let i=t.match(/(?:^|\s)retries=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=0&&cb(r,"retries",Math.floor(e))}}return r}(s.readFileSync(e,"utf8"));if(!a){o.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){o.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${a}`});continue}l=a,d=t.platform,("apple"===l?"apple"===d||"ios"===d||"macos"===d:d===l)&&o.push({kind:"run",path:e,metadata:t})}if(0===o.filter(e=>"run"===e.kind).length){let e=a?` for --platform ${a}`:"";throw new H("INVALID_ARGS",`No .ad tests matched${e}.`)}return o}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),y=(i=t.meta?.requestId,(i?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),v=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:a}=e,n=rx.expandHome(t??".agent-device/test-artifacts",r);return p.join(n,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),I=[],b=Date.now(),A=0;for(let e of g){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}A+=1;let i=await cD({entry:e,sessionName:r,suiteInvocationId:y,caseIndex:A-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(o=t.flags?.timeoutMs,l=e.metadata.timeoutMs,"number"==typeof o?o:l),suiteArtifactsDir:v,runReplay:a,cleanupSession:n});if(I.push(i),t.flags?.failFast===!0)break}let S=(d=g.length,u=I,c=Date.now()-b,e=u.filter(e=>"passed"===e.status).length,m=(f=u.filter(e=>"failed"===e.status)).length,h=u.filter(e=>"skipped"===e.status).length,w=e+m,{total:d,executed:w,passed:e,failed:m,skipped:h,notRun:Math.max(0,d-w-h),durationMs:c,failures:f,tests:u});return{ok:!0,data:S}}catch(t){let e=B(t);return{ok:!1,error:{code:e.code,message:e.message}}}}async function cD(e){var t,r;let a,n,{entry:i,sessionName:o,suiteInvocationId:l,caseIndex:d,cwd:u,requestId:c,retries:f,timeoutMs:m,suiteArtifactsDir:h,runReplay:w,cleanupSession:g}=e,y=Date.now(),v=p.join(h,(t=i.path,(0===(n=u?p.relative(u,t):p.basename(t)).length||n.startsWith("..")?p.basename(t):n).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",b=0;for(let e=0;e<=f;e+=1){b=e+1;let t=function(e,t,r,a,n=0){let i=p.basename(r,p.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${i?`-${i}`:""}:attempt-${n+1}`}(o,l,i.path,d,e),n=p.join(v,`attempt-${b}`);r=i.path,s.mkdirSync(n,{recursive:!0}),s.copyFileSync(r,p.join(n,"replay.ad"));let u=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:n,attemptIndex:i}=e;return eH(`${t??r}:test:${n+1}:${p.basename(a)}:attempt:${i+1}`,r)}({requestId:c,suiteInvocationId:l,filePath:i.path,caseIndex:d,attemptIndex:e}),h=await c_({filePath:i.path,sessionName:t,requestId:u,timeoutMs:m,platform:i.metadata.platform,runReplay:w,cleanupSession:g});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:n,maxAttempts:i,attemptArtifactsDir:o}=e,l=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||l.push(t.error.logPath);let d=function(e,t){let r=[],a=new Map;for(let n of e){if(!function(e){try{return s.statSync(e).isFile()}catch{return!1}}(n))continue;let e=function(e,t){let r=p.extname(e),a=r?e.slice(0,-r.length):e,n=t.get(e)??0;return(t.set(e,n+1),0===n)?e:`${a}-${n+1}${r}`}(p.basename(n),a),i=p.join(t,e);p.resolve(n)!==p.resolve(i)&&s.copyFileSync(n,i),r.push(i)}return r}(l,o),u=[`file: ${r}`,`session: ${a}`,`attempt: ${n}/${i}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;u.push(`replayed: ${e}`,`healed: ${r}`)}else u.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&u.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&u.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&u.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&u.push("timeoutMode: cooperative");d.length>0&&u.push(`copiedArtifacts: ${d.map(e=>p.basename(e)).join(", ")}`);let c=p.join(o,"result.txt"),f=`${u.join("\n")}
|
|
42
|
+
`;s.writeFileSync(c,f),t.ok||s.writeFileSync(p.join(o,"failure.txt"),f)}({response:h,filePath:i.path,sessionName:t,attempts:b,maxAttempts:f+1,attemptArtifactsDir:n}),a=h,I=t,h.ok)break}let A=Date.now()-y;if(a?.ok)return{file:i.path,session:I,status:"passed",durationMs:A,attempts:b,artifactsDir:v,replayed:"number"==typeof a.data?.replayed?a.data.replayed:0,healed:"number"==typeof a.data?.healed?a.data.healed:0};let S=a?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:a?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:i.path,session:I,status:"failed",durationMs:A,attempts:b,artifactsDir:v,error:S}}function ck(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),a=(e.value??"").toLowerCase(),n=(e.identifier??"").toLowerCase();return t.includes(r)||a.includes(r)||n.includes(r)})??null}function cM(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&&cE(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,a=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!cE(t))continue;let n=Math.abs(e.rect.y+e.rect.height/2-r);(!a||n<a.distance)&&(a={label:t,distance:n})}return a?.label}(e,t)??(r&&cE(r)?r:void 0)}function cE(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function cO(e){let t=[],r=[];for(let a of e){let e=a.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let n=cL(a.type??""),i=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!i&&cE(i);if(("group"===n||"ioscontentgroup"===n)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...a,depth:s})}return r}function cL(e){let t=e.trim().replace(/XCUIElementType/gi,"");t.startsWith("AX")&&(t=t.slice(2));let r=Math.max((t=t.toLowerCase()).lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function cC(e,t){let r=cL(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 cP(e,t){if(t.hittable)return t;let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}function cR(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let cT=new Set(["id","role","text","label","value","appname","windowtitle"]),c$=new Set(["visible","hidden","editable","selected","enabled","hittable"]),cF=new Set([...cT,...c$]);function cU(e){let t=e.trim();if(!t)throw new H("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let n=0;n<e.length;n+=1){let i=e[n];if(('"'===i||"'"===i)&&!cW(e,n)){a=cq(a,i),r+=i;continue}if(!a&&"|"===i&&"|"===e[n+1]){let a=r.trim();if(!a)throw new H("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",n+=1;continue}r+=i}let n=r.trim();if(!n)throw new H("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(n),t}(t);if(0===r.length)throw new H("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new H("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let n=0;n<e.length;n+=1){let i=e[n];if(('"'===i||"'"===i)&&!cW(e,n)){a=cq(a,i),r+=i;continue}if(!a&&/\s/.test(i)){r.trim()&&t.push(r.trim()),r="";continue}r+=i}if(a)throw new H("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim()&&t.push(r.trim()),t}(t);if(0===r.length)throw new H("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(cj)}})(e))}}function cG(e){try{return cU(e)}catch{return null}}function cV(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,a=0,n=[];for(;a<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return cF.has(e)}return cF.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&cG(t)&&n.push(a)}if(0===n.length)return null;let i=n[n.length-1];if(r){for(let t=n.length-1;t>=0;t-=1)if(n[t]<e.length){i=n[t];break}}let o=e.slice(0,i).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(i)}:null}function cB(e){let t=e[0]??"",r=cV(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function cj(e){let t=e.trim();if(!t)throw new H("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!c$.has(r))throw new H("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),n=t.slice(r+1).trim();if(!cF.has(a))throw new H("INVALID_ARGS",`Unknown selector key: ${a}`);if(!n)throw new H("INVALID_ARGS",`Missing selector value for key: ${a}`);if(c$.has(a)){let e,t="true"===(e=cH(n).toLowerCase())||"false"!==e&&null;if(null===t)throw new H("INVALID_ARGS",`Invalid boolean value for ${a}: ${n}`);return{key:a,value:t}}return{key:a,value:cH(n)}}function cq(e,t){return e?e===t?null:e:t}function cH(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function cW(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function cz(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return cK(e.identifier,String(t.value));case"role":return cK(cL(e.type??""),String(t.value));case"label":return cK(e.label,String(t.value));case"value":return cK(e.value,String(t.value));case"text":return cK(cR(e),String(t.value));case"appname":return cK(e.appName,String(t.value));case"windowtitle":return cK(e.windowTitle,String(t.value));case"visible":return cJ(e)===!!t.value;case"hidden":return!cJ(e)==!!t.value;case"editable":return cX(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 cJ(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function cX(e,t){return cC(e.type??"",t)&&!1!==e.enabled}function cK(e,t){return cY(e??"")===cY(t)}function cY(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function cZ(e,t,r){let a=r.requireRect??!1,n=r.requireUnique??!0,i=[];for(let o=0;o<t.selectors.length;o+=1){let s=t.selectors[o],l=function(e,t,r,a){let n=0,i=null,o=null,s=!1;for(let l of e){if(a&&!l.rect||!cz(l,t,r))continue;if(n+=1,i??=l,!o){o=l;continue}let e=function(e,t){let r=e.depth??0,a=t.depth??0;if(r!==a)return r>a?1:-1;let n=c1(e),i=c1(t);return n!==i?n<i?1:-1:0}(l,o);e>0?(o=l,s=!1):0===e&&(s=!0)}return{count:n,firstNode:i,disambiguated:s?null:o}}(e,s,r.platform,a);if(i.push({selector:s.raw,matches:l.count}),0!==l.count&&l.firstNode){if(n&&1!==l.count){if(!r.disambiguateAmbiguous||!l.disambiguated)continue;return{node:l.disambiguated,selector:s,selectorIndex:o,matches:l.count,diagnostics:i}}return{node:l.firstNode,selector:s,selectorIndex:o,matches:l.count,diagnostics:i}}}return null}function cQ(e,t,r){let a=r.requireRect??!1,n=[];for(let i=0;i<t.selectors.length;i+=1){let o=t.selectors[i],s=function(e,t,r,a){let n=0;for(let i of e)(!a||i.rect)&&cz(i,t,r)&&(n+=1);return n}(e,o,r.platform,a);if(n.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:i,selector:o,matches:s,diagnostics:n}}return null}function c0(e,t,r){if(0===t.length)return`Selector did not match: ${e.raw}`;let a=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return r.unique??!0?`Selector did not resolve uniquely (${a})`:`Selector did not match (${a})`}function c1(e){return e.rect?e.rect.width*e.rect.height:1/0}function c2(e,t,r={}){let a=[],n=cL(e.type??""),i=c4(e.identifier),o=c4(e.label),s=c4(e.value),l=c4(cR(e)),d="fill"===r.action;i&&a.push(`id=${c3(i)}`),n&&o&&a.push(d?`role=${c3(n)} label=${c3(o)} editable=true`:`role=${c3(n)} label=${c3(o)}`),o&&a.push(d?`label=${c3(o)} editable=true`:`label=${c3(o)}`),s&&a.push(d?`value=${c3(s)} editable=true`:`value=${c3(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${c3(l)} editable=true`:`text=${c3(l)}`),n&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${c3(n)} editable=true`);let u=ru(a);return 0===u.length&&n&&u.push(d?`role=${c3(n)} editable=true`:`role=${c3(n)}`),0===u.length&&cJ(e)&&u.push("visible=true"),u}function c3(e){return JSON.stringify(e)}function c4(e){if(!e)return null;let t=e.trim();return t||null}function c5(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=cV(r?e.slice(0,-1):e.slice());return!a||a.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:a.selectorExpression,selectorTimeout:r?t:null}}async function c8(e){let{action:t,sessionName:r,logPath:a,sessionStore:n}=e;if(!(rh(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let i=n.get(r);if(!i)return null;let o=(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),rh(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}=cB(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=c5(e.positionals??[]);r&&t.push(r)}return ru(t).filter(e=>e.trim().length>0)})(t).map(e=>cG(e)).filter(e=>null!==e);if(0===o.length)return null;let s=rh(t.command)||"fill"===t.command,l=rh(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await c6(i,t,a,s,n);for(let e of o){let r=cZ(d.nodes,e,{platform:i.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=c2(r.node,i.device.platform,{action:rh(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(rh(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=rd(t);if(!e)continue;return{...t,positionals:[a,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,a]}}if("is"===t.command){let{predicate:e,split:r}=cB(t.positionals);if(!e)continue;let n=r?.rest.join(" ").trim()??"",i=[e,a];return"text"===e&&n.length>0&&i.push(n),{...t,positionals:i}}if("wait"===t.command){let{selectorTimeout:e}=c5(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function c6(e,t,r,a,n){let i=await lZ(e.device,"snapshot",[],t.flags?.out,{...du(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=i?.nodes??[],s={nodes:e_(t.flags?.snapshotRaw?o:cO(o)),truncated:i?.truncated,createdAt:Date.now(),backend:i?.backend};return e.snapshot=s,n.set(e.name,e),s}let c9=["platform","target","device","udid","serial","verbose","out"];async function c7(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e,o=t.positionals?.[0];if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};let l="",d=new Set;try{l=rx.expandHome(o,t.meta?.cwd);let e=s.readFileSync(l,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let c=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,n=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!n)break;n="\\"===t&&!n,"\\"!==t&&(n=!1),a+=1}if(a>=e.length)throw new H("INVALID_ARGS",`Invalid replay script line: ${e}`);let i=e.slice(r,a+1);t.push(JSON.parse(i)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...n]=r;if("context"===a)return null;let i={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){i.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("-i"===t){i.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){i.flags.snapshotCompact=!0;continue}if("--raw"===t){i.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<n.length){let t=Number(n[e+1]);Number.isFinite(t)&&t>=0&&(i.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<n.length){i.flags.snapshotScope=n[e+1],e+=1;continue}if("--backend"===t&&e+1<n.length){e+=1;continue}}return i}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let n=rS(r);return{positionals:n.positionals,flags:a,runtime:(t=n.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?n.flags:void 0}}(n);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i.runtime=e.runtime,i}if("runtime"===a){let e=rS(n);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i}if(rh(a)){let e=rA(a,n);if(Object.assign(i.flags,e.flags),0===e.positionals.length)return i;let t=e.positionals[0];if(t.startsWith("@"))return i.positionals=[t],e.positionals[1]&&(i.result={refLabel:e.positionals[1]}),i;let r=e.positionals[0],o=e.positionals[1];return cA(r)&&cA(o)&&e.positionals.length>=2?i.positionals=[r,o]:i.positionals=[e.positionals.join(" ")],i}if("fill"===a){let e=rA(a,n);if(Object.assign(i.flags,e.flags),e.positionals.length<2)return i.positionals=e.positionals,i;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(i.positionals=[t,e.positionals.slice(2).join(" ")],i.result={refLabel:e.positionals[1]}):i.positionals=[t,e.positionals[1]],i):(i.positionals=[t,e.positionals.slice(1).join(" ")],i)}if("get"===a){if(n.length<2)return i.positionals=n,i;let e=n[0],t=n[1];return t.startsWith("@")?(i.positionals=[e,t],n[2]&&(i.result={refLabel:n[2]})):i.positionals=[e,n.slice(1).join(" ")],i}if("swipe"===a||"type"===a){let e=rA(a,n);return Object.assign(i.flags,e.flags),i.positionals=e.positionals,i}if("record"===a){let e=[];for(let t=0;t<n.length;t+=1){let r=n[t];if("--hide-touches"===r){i.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<n.length){let e=Number(n[t+1]);Number.isFinite(e)&&(i.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return i.positionals=e,i}if("screenshot"===a){let e=[];for(let t of n){if("--fullscreen"===t){i.flags.screenshotFullscreen=!0;continue}e.push(t)}return i.positionals=e,i}return i.positionals=n,i}(r);e&&t.push(e)}return t}(e),p=t.flags?.replayUpdate===!0,f=0;for(let e=0;e<c.length;e+=1){let o=c[e];if(!o||"replay"===o.command)continue;let s=await pe({req:t,sessionName:r,action:o,invoke:i});if(s.ok){pr(s).forEach(e=>d.add(e));continue}if(!p)return pt(s,o,e,l,[...d]);let u=await c8({action:o,sessionName:r,logPath:a,sessionStore:n});if(!u)return pt(s,o,e,l,[...d]);if(c[e]=u,!(s=await pe({req:t,sessionName:r,action:u,invoke:i})).ok)return pt(s,u,e,l,[...d]);pr(s).forEach(e=>d.add(e)),f+=1}return p&&f>0&&function(e,t,r){let a=[];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}`:"";a.push(`context platform=${r.device.platform}${n} device="${e}"${t} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",rg(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return rN(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(ry(r));return rI(t,e.flags),t.join(" ")}if("record"===e.command)return rb(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(rg(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}for(let r of e.positionals??[])t.push(rg(r));return rv(t,e),t.join(" ")}(e));let n=`${a.join("\n")}
|
|
43
|
+
`,i=`${e}.tmp-${process.pid}-${Date.now()}`;s.writeFileSync(i,n),s.renameSync(i,e)}(l,c,n.get(r)),{ok:!0,data:{replayed:c.length,healed:f,session:r,artifactPaths:[...d]}}}catch(t){let e=B(t);return{ok:!1,error:{code:e.code,message:e.message,details:d.size>0?{artifactPaths:[...d]}:void 0}}}}async function pe(e){let{req:t,sessionName:r,action:a,invoke:n}=e;return await n({token:t.token,session:r,command:a.command,positionals:a.positionals??[],flags:function(e,t){let r={...t??{}},a=e??{};for(let e of c9)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}(t.flags,a.flags),runtime:a.runtime,meta:t.meta})}function pt(e,t,r,a,n=[]){let i;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${i=(t.positionals??[]).map(e=>rg(e)),[t.command,...i].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:a,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:n}}}}function pr(e){if(!e.ok||!e.data)return[];let t=[];if("string"==typeof e.data.path&&t.push(e.data.path),"string"==typeof e.data.outPath&&t.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let r of e.data.artifacts){if(!r||"object"!=typeof r)continue;let e="string"==typeof r.localPath?r.localPath:void 0,a="string"==typeof r.path?r.path:void 0;e?t.push(e):a&&t.push(a)}return[...new Set(t.filter(e=>(function(e){try{return s.statSync(e).isFile()}catch{return!1}})(e)))]}async function pa(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e;return"replay"===t.command?await c7({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}):"test"===t.command?await cx({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await c7({req:{...t,command:"replay",session:r,positionals:[e],flags:void 0===o?t.flags:{...t.flags??{},platform:o},meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:n,invoke:async e=>{var t;return t=await i(e),l&&pr(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{n.get(e)&&await uL({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:n})}}):null}let pn=new Set(["session_list","ensure-simulator","devices","apps"]),pi=new Set(["boot","appstate"]),po=new Set(["perf","logs","network"]),ps=new Set(["replay","test"]);async function pl(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,command:i,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=n.get(r),u=t.flags??{},c=dk(i,d,u);if(c)return c;let p=await dL({session:d,flags:u,ensureReady:!0});if(!dd(i,p))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${i} is not supported on this device`}};let f=await lZ(p,i,o,t.flags?.out,{...du(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,f,p):d;n.recordAction(e,{command:i,positionals:s??o,flags:t.flags??{},result:f??{}}),e!==d&&n.set(r,e)}return{ok:!0,data:f??{}}}async function pd(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,i=n.get(r),o=t.flags??{},s=dk("clipboard",i,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return{ok:!1,error:{code:"INVALID_ARGS",message:"clipboard requires a subcommand: read or write"}};let d=await dL({session:i,flags:o,ensureReady:!0});if(!dd("clipboard",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let u=await lZ(d,"clipboard",t.positionals??[],t.flags?.out,{...du(a,t.flags,i?.appBundleId,i?.trace?.outPath)});return i&&n.recordAction(i,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function pu(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e;if(pn.has(t.command))return await uH({req:t,sessionName:r,sessionStore:n});if("runtime"===t.command)return await ua({req:t,sessionName:r,sessionStore:n});if(pi.has(t.command))return await uK({req:t,sessionName:r,sessionStore:n});if("clipboard"===t.command)return await pd({req:t,sessionName:r,logPath:a,sessionStore:n});if("keyboard"===t.command){let e=n.get(r),i=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==i||"ios"!==(t.flags??{}).platform?await pl({req:t,sessionName:r,logPath:a,sessionStore:n,command:"keyboard",positionals:t.positionals??[]}):{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first."}}}if(po.has(t.command))return await cp({req:t,sessionName:r,sessionStore:n});if("install"===t.command||"reinstall"===t.command)return await uT({req:t,command:t.command,sessionName:r,sessionStore:n,deployOps:"install"===t.command?uR:uP});if("install_source"===t.command)return await dS({req:t,sessionName:r,sessionStore:n});if("release_materialized_paths"===t.command)return await dN({req:t});if("push"===t.command){let e,i=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return i&&o?await pl({req:t,sessionName:r,logPath:a,sessionStore:n,command:"push",positionals:[i,"file"===(e=lk(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>rx.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[i,o]}):{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}}}return"trigger-app-event"===t.command?await pl({req:t,sessionName:r,logPath:a,sessionStore:n,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await uy(e.device,r,e.appBundleId,ug)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await uk({req:t,sessionName:r,logPath:a,sessionStore:n}):ps.has(t.command)?await pa({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}):"batch"===t.command?await uF(t,r,i):"close"===t.command?await uL({req:t,sessionName:r,logPath:a,sessionStore:n}):null}function pc(e,t){let r=ee(e.type??"Element"),a=G(e,r),n=!1===e.enabled?"disabled":"enabled",i=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,a,n,i,o].join("|")}function pp(e,t){return t.flatten?e.map(e=>({text:N(e,0,!1),comparable:pc(e,0)})):K(e).map(e=>({text:e.text,comparable:pc(e.node,e.depth)}))}function pf(e,t){return e.get(t)??0}async function pm(e){let t=uu(e.session);if(t&&"android"===e.device.platform)return await pw(e,t);let r=await ph(e);return uc(e.session),{snapshot:pv(r,e.flags),analysis:r.analysis}}async function ph(e){let{device:t,session:r,flags:a,outPath:n,logPath:i,snapshotScope:o}=e;if("linux"===t.platform){let e=await lI(r?.surface);return pI({nodes:e.nodes,truncated:e.truncated,backend:"linux-atspi"},{snapshotDepth:a?.snapshotDepth,snapshotInteractiveOnly:a?.snapshotInteractiveOnly,snapshotScope:o})}return"macos"===t.platform&&r?.surface&&"app"!==r.surface?pI(await oG(r.surface,{bundleId:"menubar"===r.surface?r.appBundleId:void 0}),{snapshotDepth:a?.snapshotDepth,snapshotInteractiveOnly:a?.snapshotInteractiveOnly,snapshotScope:o}):await lZ(t,"snapshot",[],n,{...du(i,{...a,snapshotScope:o},r?.appBundleId,r?.trace?.outPath)})}async function pw(e,t){let r=await pg(e),a=py(r,t,e.flags),n=0;for(let i of ul){if(!a)break;await new Promise(e=>setTimeout(e,i)),r=await pg(e),n+=1,a=py(r,t,e.flags)}return a||uc(e.session),{snapshot:r.snapshot,analysis:r.data.analysis,freshness:n>0||a?{action:t.action,retryCount:n,staleAfterRetries:!!a,reason:a??void 0}:void 0}}async function pg(e){let t=await ph(e);return{data:t,snapshot:pv(t,e.flags)}}function py(e,t,r){let a=r?.snapshotInteractiveOnly===!0,n=e.data.analysis;return a&&0===e.snapshot.nodes.length&&n&&n.rawNodeCount>=12?"empty-interactive":um(t.baselineCount,e.snapshot.nodes.length)?e.snapshot.nodes.some(e=>!0===e.hittable||!!e.label?.trim()||!!e.value?.trim()||!!e.identifier?.trim())?null:"sharp-drop":t.routeComparable&&up(t.action)&&function(e,t){if(!e||0===e.length)return!1;let r=Math.max(e.length,t.length);if(r<12)return!1;let a=uf(t),n=Math.min(e.length,a.length),i=0;for(let t=0;t<n;t+=1)e[t]===a[t]&&(i+=1);let o=Math.max(0,a.length-e.length),s=Math.max(0,e.length-a.length),l=Math.max(3,Math.floor(.15*r));return i>=Math.floor(.9*r)&&o<=l&&s<=l}(t.baselineSignatures,e.snapshot.nodes)?"stuck-route":null}function pv(e,t){let r=e?.nodes??[],a=ec(t?.snapshotRaw?r:cO(r));return{nodes:e_(t?.snapshotScope&&e?.backend!=="macos-helper"?pb(a,t.snapshotScope):a),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend,comparisonSafe:e?.backend==="android"&&t?.snapshotInteractiveOnly!==!0&&t?.snapshotCompact!==!0&&"number"!=typeof t?.snapshotDepth&&!t?.snapshotScope}}function pI(e,t){var r,a;let n=e.nodes??[];return t.snapshotScope&&(n=pb(n,t.snapshotScope)),t.snapshotInteractiveOnly&&(n=function(e){if(0===e.length)return e;let t=new Map;for(let r of e)t.set(r.index,r);let r=new Set;for(let a of e){if(!function(e){if(e.hittable||e.rect)return!0;let t=`${e.type??""} ${e.role??""} ${e.subrole??""}`.toLowerCase();return t.includes("button")||t.includes("menu")||t.includes("textfield")||t.includes("searchfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")}(a))continue;let e=a;for(;e&&!r.has(e.index);)r.add(e.index),e="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0}return 0===r.size?e:pA(e.filter(e=>r.has(e.index)))}(n)),"number"==typeof t.snapshotDepth&&(r=n,a=t.snapshotDepth,n=pA(r.filter(e=>(e.depth??0)<=a))),{...e,nodes:n}}function pb(e,t){let r=ck(e_(e),t);if(!r)return[];let a=e.findIndex(e=>e.index===r.index);if(-1===a)return[];let n=e[a]?.depth??0,i=[];for(let t=a;t<e.length;t+=1){let r=e[t];if(!r)continue;let o=r.depth??0;if(t>a&&o<=n)break;i.push(r)}return pA(i,n)}function pA(e,t=0){let r=new Map;for(let[t,a]of e.entries())r.set(a.index,t);return e.map((e,a)=>({...e,index:a,depth:Math.max(0,(e.depth??0)-t),parentIndex:"number"==typeof e.parentIndex?r.get(e.parentIndex):void 0}))}function pS(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=ef(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=el(t.snapshot.nodes,r),n=a?cM(a,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 p_(e,t,r){let a=e.get(t),n=a?.device??await lY(r??{});return a||await dp(n),{session:a,device:n}}async function pN(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await re(t.id)}}function px(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function pD(e){let{session:t,sessionName:r,device:a,snapshot:n,appBundleId:i}=e;return t?{...t,snapshot:n}:{name:r,device:a,createdAt:Date.now(),appBundleId:i,snapshot:n,actions:[]}}function pk(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function pM(e){let{parsed:t,req:r,sessionName:a,logPath:n,sessionStore:i,session:o,device:s}=e;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),px(i,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!dd("wait",s))return uC("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===t.kind)return await pE({device:s,logPath:n,parsed:t,req:r,session:o,sessionName:a,sessionStore:i});let l=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}}};let r=ef(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=el(t.snapshot.nodes,r),n=a?cM(a,t.snapshot.nodes):void 0;return n?{ok:!0,text:n,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return l.ok?await pO({device:s,logPath:n,req:r,session:o,sessionStore:i,text:l.text,timeoutMs:l.timeoutMs}):l.response}async function pE(e){let{device:t,logPath:r,parsed:a,req:n,session:i,sessionName:o,sessionStore:s}=e,l=a.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let e=cQ((await pL({device:t,logPath:r,req:n,session:i,sessionName:o,sessionStore:s})).nodes,a.selector,{platform:t.platform});if(e)return pC(s,i,n,{selector:e.selector.raw,waitedMs:Date.now()-d});await new Promise(e=>setTimeout(e,300))}return uC("COMMAND_FAILED",`wait timed out for selector: ${a.selectorExpression}`)}async function pO(e){let{device:t,logPath:r,req:a,session:n,sessionStore:i,text:o,timeoutMs:s}=e,l=s??1e4,d=Date.now();for(;Date.now()-d<l;){if("macos"===t.platform&&n?.surface&&"app"!==n.surface){if(ck((await pL({device:t,logPath:r,req:a,session:n,sessionName:n?.name??a.session??"default",sessionStore:i})).nodes,o))return pC(i,n,a,{text:o,waitedMs:Date.now()-d})}else if(tS(t.platform)){let e=await rs(t,{command:"findText",text:o,appBundleId:n?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return px(i,n,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}}}else if("android"===t.platform&&ck((await pL({device:t,logPath:r,req:a,session:n,sessionName:n?.name??a.session??"default",sessionStore:i})).nodes,o))return px(i,n,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return uC("COMMAND_FAILED",`wait timed out for text: ${o}`)}async function pL(e){let{device:t,logPath:r,req:a,session:n,sessionName:i,sessionStore:o}=e,{snapshot:s}=await pm({device:t,session:n,flags:{...a.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:a.flags?.out,logPath:r});return n&&(n.snapshot=s,o.set(i,n)),s}function pC(e,t,r,a){return px(e,t,r,a),{ok:!0,data:a}}async function pP(e){let{req:t,logPath:r,sessionStore:a,session:n,device:i}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=n?"frontmost-app"===n.surface?{surface:"frontmost-app"}:{bundleId:n.appBundleId,surface:n.surface}:{};if(!dd("alert",i))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is not supported on this device"}};if("macos"===i.platform){let e=async()=>await oU("wait"===o?"get":o,s);if("wait"===o){let r=pk(t.positionals?.[1])??1e4,i=Date.now();for(;Date.now()-i<r;){try{let r=await e();return px(a,n,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r="accept"===o||"dismiss"===o?o:"get";if("accept"===r||"dismiss"===r){let e,i=Date.now();for(;Date.now()-i<2e3;){try{let e=await oU(r,s);return px(a,n,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw pR(e)}let i=await oU("get",s);return px(a,n,t,i),{ok:!0,data:i}}if("wait"===o){let e=pk(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await rs(i,{command:"alert",action:"get",appBundleId:n?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:t.meta?.requestId});return px(a,n,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let l="accept"===o||"dismiss"===o?o:"get",d={verbose:t.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await rs(i,{command:"alert",action:l,appBundleId:n?.appBundleId},d);return px(a,n,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw pR(e)}let u=await rs(i,{command:"alert",action:l,appBundleId:n?.appBundleId},d);return px(a,n,t,u),{ok:!0,data:u}}function pR(e){if(!(e instanceof H))return e;let t=String(e.message??"").toLowerCase();return t.includes("alert not found")||t.includes("no alert")?new H(e.code,e.message,{...e.details??{},hint:"If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref."}):e}async function pT(e){let{req:t,logPath:r,sessionStore:a,session:n,device:i,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!dd("settings",i))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};if("macos"===i.platform&&!M(s))return{ok:!1,error:{code:"INVALID_ARGS",message:J(s)}};let u=n?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],p=await lZ(i,"settings",c,t.flags?.out,{...du(r,t.flags,u,n?.trace?.outPath)});return px(a,n,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}let p$=new Set(["snapshot","diff","wait","alert","settings"]);async function pF(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,i=t.command;if(!p$.has(i))return null;if("snapshot"===i){let{session:e,device:i}=await p_(n,r,t.flags);if(!dd("snapshot",i))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let o=pS(t.flags?.snapshotScope,e);return o.ok?await pN(e,i,async()=>{let s=await pm({device:i,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:o.scope}),l=pU({capture:s,flags:t.flags,session:e}),d=function(e){var t;let{nodes:r,backend:a,snapshotRaw:n}=e;if(n||"macos-helper"===(t=a)||"linux-atspi"===t)return{partial:!1,visibleNodeCount:r.length,totalNodeCount:r.length,reasons:[]};let i=Y(r),o=new Set;return i.hiddenCount>0&&o.add("offscreen-nodes"),i.nodes.some(e=>e.hiddenContentAbove)&&o.add("scroll-hidden-above"),i.nodes.some(e=>e.hiddenContentBelow)&&o.add("scroll-hidden-below"),{partial:o.size>0,visibleNodeCount:i.nodes.length,totalNodeCount:r.length,reasons:[...o]}}({nodes:s.snapshot.nodes,backend:s.snapshot.backend,snapshotRaw:t.flags?.snapshotRaw}),u=pD({session:e,sessionName:r,device:i,snapshot:s.snapshot,appBundleId:e?.appBundleId});return px(n,u,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),n.set(r,u),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,visibility:d,...l.length>0?{warnings:l}:{},appName:u.appBundleId?u.appName??u.appBundleId:void 0,appBundleId:u.appBundleId}}}):o.response}if("diff"===i)return t.positionals?.[0]!=="snapshot"?{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}}:await pG({req:t,sessionName:r,logPath:a,sessionStore:n});if("wait"===i){let{session:e,device:i}=await p_(n,r,t.flags),o=function(e){if(0===e.length)return null;let t=pk(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=pk(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=pk(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=pk(e[e.length-1]),a=cV(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=cG(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}};let s=()=>pM({parsed:o,req:t,sessionName:r,logPath:a,sessionStore:n,session:e,device:i});return"sleep"===o.kind?await s():await pN(e,i,s)}if("alert"===i){let{session:e,device:i}=await p_(n,r,t.flags);return await pN(e,i,async()=>await pP({req:t,logPath:a,sessionStore:n,session:e,device:i}))}if("settings"===i){let e,i,o,s=(e=t.positionals?.[0]?.toLowerCase(),i=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&i&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:i,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:P}}});if(!s.ok)return s.response;let{session:l,device:d}=await p_(n,r,t.flags);return await pN(l,d,async()=>await pT({req:t,logPath:a,sessionStore:n,session:l,device:d,parsed:s.parsed}))}return null}function pU(e){let{capture:t,flags:r,session:a}=e,n=[],i=t.analysis,o=r?.snapshotInteractiveOnly===!0;"android"===t.snapshot.backend&&o&&0===t.snapshot.nodes.length&&i&&i.rawNodeCount>=12&&(n.push(`Interactive snapshot is empty after filtering ${i.rawNodeCount} raw Android nodes. Likely causes: depth too low, transient route change, or collector filtering.`),"number"==typeof r?.snapshotDepth&&i.maxDepth>=r.snapshotDepth+2&&n.push(`Interactive output is empty at depth ${r.snapshotDepth}; retry without -d.`));let s=a?.snapshot;return!t.freshness&&s&&Date.now()-s.createdAt<=2e3&&um(s.nodes.length,t.snapshot.nodes.length)&&n.push("Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once."),t.freshness?.staleAfterRetries&&"android"===t.snapshot.backend&&("stuck-route"===t.freshness.reason?n.push(`Recent ${t.freshness.action} was followed by a nearly identical snapshot after ${t.freshness.retryCount} automatic retr${1===t.freshness.retryCount?"y":"ies"}. If you expected navigation or submit, the tree may still be stale. Use screenshot as visual truth, wait briefly, then re-snapshot once.`):"sharp-drop"===t.freshness.reason&&n.push("Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once.")),ru(n)}async function pG(e){let{req:t,sessionName:r,logPath:a,sessionStore:n}=e,{session:i,device:o}=await p_(n,r,t.flags);if(!dd("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let s=pS(t.flags?.snapshotScope,i);if(!s.ok)return s.response;let l=t.flags?.snapshotInteractiveOnly===!0;return await pN(i,o,async()=>{let e=await pm({device:o,session:i,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:s.scope}),d=e.snapshot,u=pU({capture:e,flags:t.flags,session:i});if(!i?.snapshot){let e=function(e,t={}){return pp(e,t).length}(d.nodes,{flatten:l}),a=pD({session:i,sessionName:r,device:o,snapshot:d,appBundleId:i?.appBundleId});return px(n,a,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e}}),n.set(r,a),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e},lines:[],...u.length>0?{warnings:u}:{}}}}let c=function(e,t,r={}){let a=function(e,t){let r=e.length,a=t.length,n=r+a,i=new Map,o=[];i.set(1,0);for(let s=0;s<=n;s+=1){o.push(new Map(i));for(let n=-s;n<=s;n+=2){let l=n===-s||n!==s&&pf(i,n-1)<pf(i,n+1)?pf(i,n+1):pf(i,n-1)+1,d=l-n;for(;l<r&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(i.set(n,l),l>=r&&d>=a)return function(e,t,r,a,n){let i=[],o=a,s=n;for(let a=e.length-1;a>=0;a-=1){let n=e[a],l=o-s,d=l===-a||l!==a&&pf(n,l-1)<pf(n,l+1)?l+1:l-1,u=pf(n,d),c=u-d;for(;o>u&&s>c;)i.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===a)break;o===u?(i.push({kind:"added",text:r[c].text}),s=c):(i.push({kind:"removed",text:t[u].text}),o=u)}return i.reverse(),i}(o,e,t,r,a)}}return[]}(pp(e,r),pp(t,r)),n={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(n.additions+=1),"removed"===e.kind&&(n.removals+=1),"unchanged"===e.kind&&(n.unchanged+=1);return{summary:n,lines:a}}(i.snapshot.nodes,d.nodes,{flatten:l}),p={...i,snapshot:d};return px(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,...u.length>0?{warnings:u}:{}}}})}function pV(e,t,r,a={}){let n=pj(r);if(!n)return{matches:[],score:0};let i=0,o=[];for(let r of e){if(a.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return pB(e.label,r);case"value":return pB(e.value,r);case"id":return pB(e.identifier,r);default:return Math.max(pB(e.label,r),pB(e.value,r),pB(e.identifier,r))}}(r,t,n);if(!(e<=0)){if(e>i){i=e,o.length=0,o.push(r);continue}e===i&&o.push(r)}}return{matches:o,score:i}}function pB(e,t){let r=pj(e??"");return r?r===t?2:+!!r.includes(t):0}function pj(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function pq(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:n,invalidRefMessage:i,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=ef(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:i}}};let l=el(t.snapshot.nodes,s);return((!l||n&&!l.rect)&&a.length>0&&(l=ck(t.snapshot.nodes,a)),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 pH(e){let t=pW(e);if(!t)return null;let r=eA(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function pW(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),n=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(n)&&!(a<0)&&!(n<0)?{x:t,y:r,width:a,height:n}:null}async function pz(e){let{session:t,refInput:r,fallbackLabel:a,commandLabel:n,promoteToHittableAncestor:i,invalidRefMessage:o,missingBoundsMessage:s,invalidBoundsMessage:l,reqFlags:d,sessionStore:u,contextFromFlags:c,captureSnapshotForSession:p,resolveRefTarget:f}=e,m=f({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:o,notFoundMessage:s});if(!m.ok)return{ok:!1,response:m.response};let{ref:h}=m.target,w=i?pJ(m.target.snapshotNodes,m.target.node):m.target.node,g=m.target.snapshotNodes,y=pH(w.rect);if(!y){let e=await p(t,d,u,c,{interactiveOnly:!0}),r=el(e.nodes,h),n=a.length>0?ck(e.nodes,a):null,o=r&&i?pJ(e.nodes,r):r,s=n&&i?pJ(e.nodes,n):n,l=pH(s?.rect),f=pH(o?.rect)?o:l?s:o??s,m=pH(f?.rect);f&&m&&(w=f,g=e.nodes,y=m)}if(!y)return{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:l}}};let v=w.rect?z(w,g):null;return w.rect&&v&&!k(w,g)?{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${r} is off-screen and not safe to ${n}`,hint:`Run scrollintoview ${r}, then retry ${n} with the returned currentRef or a fresh snapshot.`,details:{reason:"offscreen_ref",ref:h,rect:w.rect,viewport:v}}}}:{ok:!0,target:{ref:h,node:w,snapshotNodes:g,point:y}}}function pJ(e,t){let r=function(e,t){let r=pW(t.rect);if(!r)return null;let a=t,n=new Set;for(;!n.has(a.ref);){n.add(a.ref);let t=e.filter(e=>{if(e.parentIndex!==a.index||!e.hittable)return!1;let t=pW(e.rect);return!!t&&pX(t,r)});if(1!==t.length)break;a=t[0]}return a===t?null:a}(e,t);if(r?.rect&&pH(r.rect))return r;let a=cP(e,t);return a?.rect&&pH(a.rect)?!function(e,t,r){var a,n,i,o;let s,l,d,u=pW(e.rect),c=pW(t.rect);if(!u||!c)return!1;let p=function(e,t){let r=eA(t),a=e.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}).map(e=>pW(e.rect)).filter(e=>null!==e);if(0===a.length)return null;let n=a.filter(e=>$(e,r.x,r.y));return ep(n.length>0?n:a)}(r,u);return!!p&&(a=c,n=p,s=(i=a,o=n,Math.max(0,Math.min(i.x+i.width,o.x+o.width)-Math.max(i.x,o.x))*Math.max(0,Math.min(i.y+i.height,o.y+o.height)-Math.max(i.y,o.y))),l=a.width*a.height,d=n.width*n.height,!(s<=0)&&!(l<=0)&&!(d<=0)&&!!(s/d>=.9)&&!!(s/l>=.8))&&!pX(u,c)}(t,a,e)?a:t:t}function pX(e,t){return .5>=Math.abs(e.x-t.x)&&.5>=Math.abs(e.y-t.y)&&.5>=Math.abs(e.width-t.width)&&.5>=Math.abs(e.height-t.height)}async function pK(e){let{device:t,node:r,flags:a,appBundleId:n,traceOutPath:i,surface:o,contextFromFlags:s}=e,l=W(r),d=pH(r.rect);if(!d)return l;try{let e=await lZ(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,n,i),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return eu({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return eu({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}async function pY(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return uC("INVALID_ARGS","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 a=e[r]??"",n=e.slice(r+1);if(0===n.length)return{locator:t,query:a,action:"click"};let i=n[0].toLowerCase();if("get"===i){let e=n[1]?.toLowerCase();if("text"===e)return{locator:t,query:a,action:"get_text"};if("attrs"===e)return{locator:t,query:a,action:"get_attrs"};throw new H("INVALID_ARGS","find get only supports text or attrs")}if("wait"===i)return{locator:t,query:a,action:"wait",timeoutMs:pk(n[1])??void 0};if("exists"===i)return{locator:t,query:a,action:"exists"};if("click"===i)return{locator:t,query:a,action:"click"};if("focus"===i)return{locator:t,query:a,action:"focus"};if("fill"===i)return{locator:t,query:a,action:"fill",value:n.slice(1).join(" ")};if("type"===i)return{locator:t,query:a,action:"type",value:n.slice(1).join(" ")};throw new H("INVALID_ARGS",`Unsupported find action: ${n[0]}`)}(s);if(!d)return uC("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return uC("INVALID_ARGS","find accepts only one of --first or --last");let f=n.get(r);if(!f&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return uC("SESSION_NOT_FOUND","No active session. Run open first.");let m=f?.device??await lY(t.flags??{});f||await dp(m);let h="role"!==l?d:void 0,w="click"===u||"focus"===u||"fill"===u||"type"===u,g=0,y=null,v=async()=>{let e=Date.now();if(y&&e-g<750&&!uu(f))return{nodes:y};let{snapshot:i}=await pm({device:m,session:f,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=i.nodes;return g=e,y=o,f&&(f.snapshot=i,n.set(r,f)),{nodes:o,truncated:i.truncated,backend:i.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:n,invoke:i,session:f,device:m,command:o,locator:l,query:d};if("wait"===u)return pZ(I,v,l,d,p);let{nodes:b}=await v(),A=pV(b,l,d,{requireRect:w});if(w&&A.matches.length>1)if(t.flags?.findFirst)A.matches=[A.matches[0]];else{if(!t.flags?.findLast){var S,_,N;let e;return S=A.matches,_=l,N=d,e=S.slice(0,8).map(e=>{let t=cR(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${S.length} elements for ${_} "${N}". Use a more specific locator or selector.`,details:{locator:_,query:N,matches:S.length,candidates:e}}}}A.matches=[A.matches[A.matches.length-1]]}let x=A.matches[0]??null;if(!x)return uC("COMMAND_FAILED","find did not match any element");let D="click"===u||"focus"===u||"fill"===u||"type"===u?cP(b,x)??x:x,k=`@${D.ref}`,M={node:x,resolvedNode:D,ref:k,nodes:b,actionFlags:{...t.flags??{},noRecord:!0}},E={exists:()=>pQ(I),get_text:()=>p0(I,M),get_attrs:()=>p1(I,M),click:()=>p2(I,M),fill:()=>p3(I,M,c),focus:()=>p4(I,M),type:()=>p5(I,M,c)}[u];return E?E():null}async function pZ(e,t,r,a,n){let{req:i,sessionStore:o,session:s,command:l}=e,d=n??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(pV(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:i.positionals??[],flags:i.flags??{},result:{found:!0,waitedMs:Date.now()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}async function pQ(e){let{req:t,sessionStore:r,session:a,command:n}=e;return a&&r.recordAction(a,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function p0(e,t){let{req:r,sessionStore:a,session:n,command:i,device:o,logPath:s}=e,l=await pK({device:o,node:t.node,flags:r.flags,appBundleId:n?.appBundleId,traceOutPath:n?.trace?.outPath,surface:n?.surface,contextFromFlags:(e,t,r)=>du(s,e,t,r)});return n&&a.recordAction(n,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function p1(e,t){let{req:r,sessionStore:a,session:n,command:i}=e;return n&&a.recordAction(n,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function p2(e,t){let{req:r,sessionName:a,sessionStore:n,session:i,invoke:o,command:s,locator:l,query:d}=e,u=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?eA(t.resolvedNode.rect):null,p={ref:t.ref,locator:l,query:d};return c&&(p.x=c.x,p.y=c.y),i&&n.recordAction(i,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:p}}async function p3(e,t,r){let{req:a,sessionName:n,sessionStore:i,session:o,invoke:s,command:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let d=await s({token:a.token,session:n,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return d.ok&&o&&i.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),d}async function p4(e,t){let{req:r,sessionStore:a,session:n,device:i,command:o,logPath:s}=e,l=t.node.rect?eA(t.node.rect):null;if(!l)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let d=await lZ(i,"focus",[String(l.x),String(l.y)],r.flags?.out,{...du(s,r.flags,n?.appBundleId,n?.trace?.outPath)});return n&&a.recordAction(n,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:d??{ref:t.ref}}}async function p5(e,t,r){let{req:a,sessionStore:n,session:i,device:o,command:s,logPath:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let d=t.node.rect?eA(t.node.rect):null;if(!d)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await lZ(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...du(l,a.flags,i?.appBundleId,i?.trace?.outPath)});let u=await lZ(o,"type",[r],a.flags?.out,{...du(l,a.flags,i?.appBundleId,i?.trace?.outPath)});return i&&n.recordAction(i,{command:s,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:u??{ref:t.ref}}}let p8=`
|
|
44
44
|
import Foundation
|
|
45
45
|
import AVFoundation
|
|
46
46
|
|
|
@@ -64,11 +64,11 @@ Task {
|
|
|
64
64
|
|
|
65
65
|
semaphore.wait()
|
|
66
66
|
exit(exitCode)
|
|
67
|
-
`.trim();async function
|
|
68
|
-
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return pm(e);return!1}catch(t){if(t instanceof q&&"TOOL_MISSING"===t.code)return pm(e);throw t}}async function pf(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await pp(e))return;await new Promise(e=>setTimeout(e,r))}}function pm(e){try{let t=s.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=s.openSync(e,"r");try{let e=s.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r))break;let n=e.readUInt32BE(0),i=e.toString("latin1",4,8);if(a.push(i),1===n){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r+8))break;n=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(n)||n<=0)break;r+=n}return a}finally{s.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function ph(e){let t=c.parse(e);return c.join(t.dir,`${t.name}.gesture-telemetry.json`)}function pw(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function pg(e){var t,r,a;let n,i,{recording:o,trimStartMs:l}=e,d=(n=ph((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:l}).videoPath),i={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?pw(r.flatMap(e=>{let t=e.tMs-a,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):pw(r))},s.writeFileSync(n,JSON.stringify(i,null,2)),n);return o.telemetryPath=d,d}function py(e){let t=c.dirname(h(import.meta.url)),r=[h(new URL(`./${e}`,import.meta.url)),c.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),c.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),c.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(s.existsSync(e))return e;throw new q("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}function pv(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}async function pI(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await pc(t),await pf(t);let i=s.mkdtempSync(c.join(u.tmpdir(),"agent-device-record-overlay-")),o=c.join(i,`input${c.extname(t)||".mp4"}`),l=c.join(i,c.basename(t)),d=c.join(i,"home"),p=c.join(i,"module-cache");s.copyFileSync(t,o),s.mkdirSync(d,{recursive:!0}),s.mkdirSync(p,{recursive:!0});try{await R("xcrun",["swift",r,"--input",o,"--output",l,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:p}}),await pf(l),s.copyFileSync(l,t)}catch(a){let e=a instanceof q?a:new q("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new q("COMMAND_FAILED",n,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{s.rmSync(i,{recursive:!0,force:!0})}}async function pA(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await pI({videoPath:t,scriptPath:a??=py("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function pb(e){let{videoPath:t,telemetryPath:a,targetLabel:n="recording"}=e;await pI({videoPath:t,scriptPath:r??=py("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${n}`})}function pS(e){return e instanceof Error?e.message:String(e)}function p_(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function pN(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===a.exitCode&&a.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function pD(e,t,r){for(let a=0;a<40;a+=1){if(!await pN(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await pN(e,t,r)}async function px(e,t,r){let a,n=0;for(let i=0;i<20;i+=1){let i=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===i.exitCode?i.stdout.trim():"";if(o.length>0&&o===a){if((n+=1)>=4)return}else n=0;a=o,await new Promise(e=>setTimeout(e,250))}}async function pk(e,t,r,a){for(let n=0;n<8;n+=1){let i=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===i.exitCode?Number(i.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await pN(e,t,a))break;if(n+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function pM(e){let t,{deps:r,deviceId:a,remotePath:n,outPath:i}=e;for(let e=0;e<2;e+=1){try{s.rmSync(i,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",a,"pull",n,i],{allowFailure:!0});if(0!==o.exitCode)t=p_(o,"adb pull");else{await r.waitForStableFile(i,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(i);if(ed({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:n,outPath:i,attempt:e+1,fileSize:(()=>{try{return s.statSync(i).size}catch{return 0}})(),playable:t}}),t)return;ed({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:n,outPath:i,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function pE(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function pO(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return ed({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await pN(e,t,r))&&await pD(e,t,r)}async function pL(e){var t;let r,{deps:a,device:n,recordingBase:i}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",n.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${p_(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){o="failed to start recording: adb did not return a valid Android screenrecord pid",await pE(a,n.id,e);continue}if(ed({level:"debug",phase:"record_start_android_started",data:{deviceId:n.id,remotePath:e,remotePid:r}}),await pk(a,n.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...i,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await pO(a,n.id,r),await pE(a,n.id,e)}return{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}async function pC(e){let t,r,{deps:a,device:n,recording:i}=e;ed({level:"debug",phase:"record_stop_android_enter",data:{deviceId:n.id,remotePath:i.remotePath,remotePid:i.remotePid}});let o=await a.runCmd("adb",["-s",n.id,"shell","kill","-2",i.remotePid],{allowFailure:!0});if(ed({level:"debug",phase:"record_stop_android_signal",data:{deviceId:n.id,remotePath:i.remotePath,remotePid:i.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await pN(a,n.id,i.remotePid)&&!await pO(a,n.id,i.remotePid)&&(t=`failed to stop recording: ${p_(o,"adb shell kill")}`):await pD(a,n.id,i.remotePid)||await pO(a,n.id,i.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${i.remotePid} did not exit`),!t){await px(a,n.id,i.remotePath);let e=await pM({deps:a,deviceId:n.id,remotePath:i.remotePath,outPath:i.outPath});if(e)return await s(),{ok:!1,error:{code:"COMMAND_FAILED",message:e}};if(pg({recording:i}),i.showTouches&&i.telemetryPath){let e=pv();if(e)i.overlayWarning=e;else try{await a.overlayRecordingTouches({videoPath:i.outPath,telemetryPath:i.telemetryPath,targetLabel:"Android recording"})}catch(e){i.overlayWarning=`failed to overlay recording touches: ${pS(e)}`}}}if(await s(),t)return{ok:!1,error:{code:"COMMAND_FAILED",message:t}};if(r)return{ok:!1,error:{code:"COMMAND_FAILED",message:r}};return null;async function s(){let e=await a.runCmd("adb",["-s",n.id,"shell","rm","-f",i.remotePath],{allowFailure:!0});ed({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:n.id,remotePath:i.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${p_(e,"adb shell rm")}`)}}function pP(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function pR(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function pT(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i}=e,o=pP(r);if(o)try{await i.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},pR(t,n,r))}catch(e){ed({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:pS(e)}})}}async function p$(e){let t,r,{req:a,activeSession:n,sessionStore:i,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=pR(a,s,n),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var w,g;if(!pS(a).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${pS(a)}`}};ed({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:n.name,error:pS(a)}});let e=(w=o.id,g=n.name,i.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${e.name}'`}};try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${pS(e)}`}}}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function pF(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await i.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},pR(t,n,r))}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${pS(e)}`}}}return{platform:"macos-runner",...s}}async function pU(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i,recording:o}=e,s=pP(r);try{await i.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},pR(t,n,r))}catch(e){ed({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:pS(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of tP)if(0===(l=await i.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);d>0&&await i.trimRecordingStart({videoPath:o.outPath,trimStartMs:d});let u=pg({recording:o,trimStartMs:d});if(o.showTouches){let e=pv();if(e)o.overlayWarning=e;else try{await i.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:u,targetLabel:"iOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${pS(e)}`}}return null}async function pV(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i,recording:o}=e,s=pP(r);try{await i.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},pR(t,n,r))}catch(e){ed({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:pS(e)}})}let l=pg({recording:o});if(o.showTouches){let e=pv();if(e)o.overlayWarning=e;else try{await i.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:l,targetLabel:"macOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${pS(e)}`}}return null}async function pG(e){for(let t=0;t<2;t+=1){try{if(s.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function pB(e){let t,r,{req:a,activeSession:n,device:i,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await pT({req:a,activeSession:n,device:i,logPath:o,deps:s});let{child:u,wait:c}=s.runCmdBackground("xcrun",e7(i,["io",i.id,"recordVideo",d]),{allowFailure:!0}),p=await pG(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(i,{command:"uptime",appBundleId:pP(n)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:n.trace?.outPath}),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:u,wait:c,...l,startedAt:p,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function pj(e){let t,{req:r,sessionName:a,sessionStore:n,activeSession:i,device:o,logPath:l,deps:d}=e;if(i.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let u=r.flags?.fps;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};if(!l_("record",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,f=rg.expandHome(p,r.meta?.cwd),m={outPath:f,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(s.mkdirSync(c.dirname(f),{recursive:!0}),s.rmSync(f,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=pP(i);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};t=await p$({req:r,activeSession:i,sessionStore:n,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else if("macos"===o.platform){let e=pP(i);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on macOS requires an active app session; run open <app> first"}};t=await pF({req:r,activeSession:i,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else t="ios"===o.platform?await pB({req:r,activeSession:i,device:o,logPath:l,deps:d,recordingBase:m,resolvedOut:f}):await pL({deps:d,device:o,recordingBase:m});return"ok"in t?t:(i.recording=t,n.set(a,i),n.recordAction(i,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??p,showTouches:t.showTouches}})}async function pq(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await pC({deps:t,device:r,recording:a});a.child.kill("SIGINT");let n=await a.wait;if(0!==n.exitCode)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to stop recording: ${p_(n,"simctl recordVideo")}`}};let i=pg({recording:a});if(a.showTouches){let e=pv();if(e)a.overlayWarning=e;else try{await t.overlayRecordingTouches({videoPath:a.outPath,telemetryPath:i,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to overlay recording touches: ${pS(e)}`}}return null}async function pH(e){var t;let r,{req:a,activeSession:n,device:i,logPath:o,deps:s}=e;if(!n.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let l=n.recording,d=l.invalidatedReason;n.recording=void 0;let u="ios-device-runner"===l.platform?await pU({req:a,activeSession:n,device:i,logPath:o,deps:s,recording:l}):"macos-runner"===l.platform?await pV({req:a,activeSession:n,device:i,logPath:o,deps:s,recording:l}):await pq({deps:s,device:i,recording:l});return u||(d?{ok:!1,error:{code:"COMMAND_FAILED",message:d}}:(r=[{field:"outPath",path:(t=l).outPath,localPath:t.clientOutPath,fileName:c.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return ph(e.clientOutPath)}(t),fileName:c.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function pW(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,i={runCmd:R,runCmdBackground:L,runIosRunnerCommand:t9,waitForStableFile:pc,isPlayableVideo:pp,trimRecordingStart:pA,overlayRecordingTouches:pb},o=a.get(r),s=o?.device??await li(t.flags??{});o||await lx(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};if("start"===d)return pj({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:n,deps:i});let u=await pH({req:t,activeSession:l,device:s,logPath:n,deps:i});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function pz(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,i=t.command;if("record"===i)return pW({req:t,sessionName:r,sessionStore:a,logPath:n});if("trace"===i){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return dJ("INVALID_ARGS","trace requires start|stop");let n=a.get(r);if(!n)return dJ("SESSION_NOT_FOUND","No active session");if("start"===e){if(n.trace)return dJ("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(n),r=rg.expandHome(e);return s.mkdirSync(c.dirname(r),{recursive:!0}),s.appendFileSync(r,""),n.trace={outPath:r,startedAt:Date.now()},a.recordAction(n,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!n.trace)return dJ("INVALID_ARGS","no active trace");let o=n.trace.outPath;if(t.positionals?.[1]){let e=rg.expandHome(t.positionals[1]);s.mkdirSync(c.dirname(e),{recursive:!0}),s.existsSync(o)?s.renameSync(o,e):s.appendFileSync(e,""),o=e}return n.trace=void 0,a.recordAction(n,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function pJ(e){return"number"==typeof e.gestureClockOriginAtMs&&"number"==typeof e.gestureClockOriginUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureClockOriginAtMs+(e.gestureStartUptimeMs-e.gestureClockOriginUptimeMs)-e.recordingStartedAt):"number"==typeof e.runnerStartedAtUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureStartUptimeMs-e.runnerStartedAtUptimeMs):"number"==typeof e.gestureStartUptimeMs&&"number"==typeof e.gestureEndUptimeMs?Math.max(0,e.fallbackFinishedAtMs-(e.gestureEndUptimeMs-e.gestureStartUptimeMs)-e.recordingStartedAt):Math.max(0,e.fallbackStartedAtMs-e.recordingStartedAt)}let pK=new WeakMap;function pX(e){if(!e)return;let t=pK.get(e);if(t)return t;let r=function(e){let t=function(e){let t=e.filter(e=>(function(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("application")||t.includes("window")})(e.type)&&pY(e.rect)).map(e=>e.rect).sort((e,t)=>(t?.width??0)*(t?.height??0)-(e?.width??0)*(e?.height??0))[0];if(t)return t;let r=e.map(e=>e.rect).filter(pY);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),n=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(n<=0))return{x:0,y:0,width:a,height:n}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return pK.set(e,r),r}function pY(e){return!!e&&e.width>0&&e.height>0}let pZ={referenceWidth:1e3,referenceHeight:1e3};function pQ(e,t,r,a,n={},i=Date.now(),o=Date.now()){var s,l,d;let u,c,p=e.recording;if(!p)return;let f={...n,...a??{}},m=p3(f.effectiveDurationMs)??p3(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:p3(f.gestureStartUptimeMs),gestureEndUptimeMs:p3(f.gestureEndUptimeMs),fallbackStartedAtMs:i,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:p3(f.gestureStartUptimeMs),gestureEndUptimeMs:p3(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:i,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===p3(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=p4(p3(t.count),1)??1,r=!0===t.doubleTap,a=p4(p3(t.holdMs),1);return 1===e&&!r&&void 0===a}default:return!1}}(t,f)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return pJ(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):pJ(h),y=(l=e.snapshot,u=p3((d=f).referenceWidth),c=p3(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:pX(l)),v=function(e,t,r,a,n,i){switch(e){case"click":case"press":return function(e,t,r,a){let n=p8(t,e);if(!n)return[];let{x:i,y:o}=n,s=p4(p3(t.count),1)??1,l=p4(p3(t.intervalMs),0)??0,d=!0===t.doubleTap,u=p4(p3(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(p1(t,i,o,u,a));continue}c.push(p0(t,i,o,a)),d&&c.push(p0(t+90,i,o,a))}return c}(t,r,a,i);case"fill":case"focus":return function(e,t,r,a){let n=p8(t,e);if(!n)return[];let{x:i,y:o}=n;return[p0(r,i,o,a)]}(t,r,a,i);case"longpress":return function(e,t,r,a,n){let i=p8(t,e);if(!i)return[];let{x:o,y:s}=i;return[p1(r,o,s,p6(a,[p3(t.durationMs),p3(e[2])],800),n)]}(t,r,a,n,i);case"scroll":return function(e,t,r,a,n){let i=p5(t,e),o=p2(t.contentDirection)??p2(t.direction);if(!i||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=i,c=p6(a,[],250),p=p3(t.amount)??p3(e[1]),f=p3(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...n,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{},...void 0!==f?{pixels:f}:{}}]}(t,r,a,n,i);case"swipe":return function(e,t,r,a,n){let i=p5(t,e);if(!i)return[];let{x1:o,y1:s,x2:l,y2:d}=i,u=p6(a,[p3(t.effectiveDurationMs),p3(t.durationMs),p3(e[4])],250),c=p4(p3(t.count),1)??1,p=p4(p3(t.pauseMs),0)??0,f="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===f&&e%2==1,a=t?l:o,i=t?d:s,c=t?o:l,h=t?s:d,w=r+e*(u+p);if("back-swipe"===function(e,t,r,a,n){if(!n||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let i=.08*n.referenceWidth;return e<=i&&r>e||e>=n.referenceWidth-i&&r<e?"back-swipe":"swipe"}(a,i,c,h,n)){m.push({kind:"back-swipe",tMs:w,x:a,y:i,x2:c,y2:h,...n,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,n)});continue}m.push({kind:"swipe",tMs:w,x:a,y:i,x2:c,y2:h,...n,durationMs:u})}return m}(t,r,a,n,i);case"pinch":return function(e,t,r,a,n){let i=p8(t,e,1),o=p3(t.scale)??p3(e[0]);if(!i||void 0===o||o<=0)return[];let{x:s,y:l}=i;return[{kind:"pinch",tMs:r,x:s,y:l,...n,scale:o,durationMs:p6(a,[],280)}]}(t,r,a,n,i);default:return[]}}(t,r,f,g,w,y);0!==v.length&&(p.gestureEvents.push(...v),ed({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:v.length,tMs:g,gestureDurationMs:w,kinds:v.map(e=>e.kind)}}))}function p0(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function p1(e,t,r,a,n){return{kind:"longpress",tMs:e,x:t,y:r,...n,durationMs:a}}function p2(e){if("string"!=typeof e)return;let t=e.trim().toLowerCase();switch(t){case"up":case"down":case"left":case"right":return t;default:return}}function p3(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e||0===e.trim().length)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function p4(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function p8(e,t,r=0){let a=p3(e.x)??p3(t[r]),n=p3(e.y)??p3(t[r+1]);if(void 0!==a&&void 0!==n)return{x:a,y:n}}function p5(e,t){let r=p3(e.x1)??p3(t[0]),a=p3(e.y1)??p3(t[1]),n=p3(e.x2)??p3(t[2]),i=p3(e.y2)??p3(t[3]);if(void 0!==r&&void 0!==a&&void 0!==n&&void 0!==i)return{x1:r,y1:a,x2:n,y2:i}}function p6(e,t,r){return p4(e,1)??t.map(e=>p4(e,1)).find(e=>void 0!==e)??r}function p9(e){var t,r,a;let n,i,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,r=s,a=l,n="string"==typeof t?.ref?t.ref:void 0,i="string"==typeof t?.button?t.button:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:n?i&&"primary"!==i?`Clicked ${i} @${n} (${r}, ${a})`:`Tapped @${n} (${r}, ${a})`:void 0)??("string"==typeof o?.message?o.message:void 0));return{x:s,y:l,...d??{},...u??{},...o??{},...el(c)}}async function p7(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:n,flags:i,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,afterDispatch:u,buildPayloads:c}=e,p=await fe({session:t,flags:i,contextFromFlags:o,command:s,positionals:l,outPath:d});await u?.(p.data);let{result:f,responseData:m=f}=await c(p.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:n,flags:i,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:n,flags:i??{},result:o}),dx(a)&&d_(t,a),pQ(t,a,n,o,i??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:n,flags:i,result:f,responseData:m,actionStartedAt:p.actionStartedAt,actionFinishedAt:p.actionFinishedAt})}async function fe(e){let{session:t,flags:r,contextFromFlags:a,command:n,positionals:i,outPath:o}=e,s=Date.now(),l={...a(r,t.appBundleId,t.trace?.outPath)},d=await lo(t.device,n,i,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function ft(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await i_(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=pX(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=pX(await i(t,r,a,n,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function fr(e){try{return await ft(e)}catch(t){ed({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function fa(e){return pX({nodes:e,createdAt:0})}function fn(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`}}}async function fi(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r),d=t.command,u="click"===d?"click":"press";if(!l)return dJ("SESSION_NOT_FOUND","No active session. Run open first.");let c=fn(l,u);if(c)return c;if(!l_("press",l.device))return dJ("UNSUPPORTED_OPERATION","press is not supported on this device");let p=sU(t.flags),f="primary"===p?{}:{button:p};if("primary"!==p){let e=sV({commandLabel:u,platform:l.device.platform,button:p,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(e)return dJ(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return p7({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:n,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,afterDispatch:async()=>{await fo(l,"coordinate tap")},buildPayloads:async e=>{let r=await fr({session:l,flags:t.flags,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i}),o=p9({data:e,fallbackX:m.x,fallbackY:m.y,referenceFrame:r,extra:f});return{result:o,responseData:o}}});let h="click",w=t.positionals?.[0]??"";if(w.startsWith("@")){let e=s("press",t.flags);if(e)return e;let r=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",c=await c6({session:l,refInput:w,fallbackLabel:r,commandLabel:u,promoteToHittableAncestor:!0,invalidRefMessage:`${u} requires a ref like @e2`,missingBoundsMessage:`Ref ${w} not found or has no bounds`,invalidBoundsMessage:`Ref ${w} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o});if(!c.ok)return c.response;let{ref:p,node:m,snapshotNodes:g,point:y}=c.target,v=uq(m,g),I=cs(m,l.device.platform,{action:h}),{x:A,y:b}=y;return p7({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"press",interactionPositionals:[String(A),String(b)],outPath:t.flags?.out,afterDispatch:async()=>{await fo(l,`@${p}`)},buildPayloads:e=>{let t=p9({data:e,fallbackX:A,fallbackY:b,referenceFrame:fa(g),extra:{ref:p,refLabel:v,selectorChain:I,...f}});return{result:t,responseData:t}}})}let g=(t.positionals??[]).join(" ").trim();if(!g)return{ok:!1,error:{code:"INVALID_ARGS",message:`${u} requires @ref, selector expression, or x y coordinates`}};let y=u0(g),v=await i(l,t.flags,a,n,{interactiveOnly:!0}),I=await eo("selector_resolve",()=>ca(v.nodes,y,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:d});if(!I||!I.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:ci(y,I?.diagnostics??[],{unique:!0})}};let A=c9(v.nodes,I.node),b=c8(A.rect);if(!b)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${I.selector.raw} resolved to invalid bounds`}};let{x:S,y:_}=b,N=cs(A,l.device.platform,{action:h}),D=uq(A,v.nodes);return p7({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"press",interactionPositionals:[String(S),String(_)],outPath:t.flags?.out,afterDispatch:async()=>{await fo(l,I.selector.raw)},buildPayloads:e=>{let t=p9({data:e,fallbackX:S,fallbackY:_,referenceFrame:fa(v.nodes),extra:{selector:I.selector.raw,selectorChain:N,refLabel:D,...f}});return{result:t,responseData:t}}})}async function fo(e,t){if("android"!==e.device.platform||!e.appBundleId)return;let r=await nM(e.device),a=r.package?.trim();if(a&&a!==e.appBundleId){var n;if("com.android.settings"===(n=a)||"com.android.systemui"===n||"com.google.android.permissioncontroller"===n||n.includes("launcher"))throw new q("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${a}. The tap likely escaped the app.`,{expectedPackage:e.appBundleId,foregroundPackage:a,activity:r.activity,hint:"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."})}}async function fs(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r);if(l){let e=fn(l,"fill");if(e)return e}if(l&&!l_("fill",l.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let e=s("fill",t.flags);if(e)return e;let r=t.positionals.length>=3?t.positionals[1]:"",d=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let u=await c6({session:l,refInput:t.positionals[0],fallbackLabel:r,commandLabel:"fill",promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o});if(!u.ok)return u.response;let{ref:c,node:p,snapshotNodes:f,point:m}=u.target,h=p.type??"",w=h&&!uJ(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,g=uq(p,f),y=cs(p,l.device.platform,{action:"fill"}),{x:v,y:I}=m;return p7({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"fill",interactionPositionals:[String(v),String(I),d],outPath:t.flags?.out,buildPayloads:e=>{let t=p9({data:e,fallbackX:v,fallbackY:I,referenceFrame:fa(f),extra:{ref:c,refLabel:g,selectorChain:y,text:d}}),r={...e??{ref:c,x:v,y:I}};return w&&(t.warning=w,r.warning=w),{result:t,responseData:r}}})}if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let d=u2(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let e=d.rest.join(" ").trim();if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=u0(d.selectorExpression),o=await i(l,t.flags,a,n,{interactiveOnly:!0}),s=await eo("selector_resolve",()=>ca(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:ci(r,s?.diagnostics??[],{unique:!0})}};let u=s.node,c=s.node.rect,p=u.type??"",f=p&&!uJ(p,l.device.platform)?`fill target ${s.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=eA(c),w=cs(u,l.device.platform,{action:"fill"});return p7({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=p9({data:t,fallbackX:m,fallbackY:h,referenceFrame:fa(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:w,refLabel:uq(u,o.nodes)}});return f&&(r.warning=f),{result:r,responseData:r}}})}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}async function fl(e){switch(e.req.command){case"press":case"click":return await fi(e);case"fill":return await fs(e);default:return null}}let fd=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function fu(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of fd)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}async function fc(e,t,r,a,n){let i={...t??{},snapshotInteractiveOnly:n.interactiveOnly,snapshotCompact:n.interactiveOnly},o=a(i,e.appBundleId,e.trace?.outPath),{snapshot:s}=await cM({device:e.device,session:e,flags:i,outPath:i.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function fp(e){let{command:t,selectorExpression:r,session:a,flags:n,sessionStore:i,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=u0(r),p=await fc(a,n,i,o,{interactiveOnly:s}),f=await eo("selector_resolve",()=>ca(p.nodes,c,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return f&&(!l||f.node.rect)?{ok:!0,chain:c,snapshot:p,resolved:f}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:ci(c,f?.diagnostics??[],{unique:d})}}}}async function ff(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n}=e,i=t.positionals?.[0];if("text"!==i&&"attrs"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!l_("get",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=fu("get",t.flags);if(e)return e;let r=c4({session:o,refInput:s,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${s} not found`});if(!r.ok)return r.response;let{ref:l,node:d}=r.target,u=cs(d,o.device.platform,{action:"get"});if("attrs"===i)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,selectorChain:u}}),{ok:!0,data:{ref:l,node:d}};let c=await pe({device:o.device,node:d,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:n});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:fm(c),selectorChain:u}}),{ok:!0,data:{ref:l,text:c,node:d}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"get requires @ref or selector expression"}};let d=await fp({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:a,contextFromFlags:n,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===i});if(!d.ok)return d.response;let{resolved:u}=d,c=u.node,p=cs(c,o.device.platform,{action:"get"});if("attrs"===i)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:u.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:u.selector.raw,node:c}};let f=await pe({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:n});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:f,refLabel:fm(f),selector:u.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:u.selector.raw,text:f,node:c}}}function fm(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function fh(e){return!!(e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.width)&&Number.isFinite(e.height)&&e.width>0&&e.height>0)}async function fw(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n}=e,i=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!l_("is",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:s}=u3(t.positionals);if(!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires a selector expression"}};let l=s.rest.join(" ").trim();if("text"===i&&!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==i&&s.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${i} does not accept trailing values`}};let d=u0(s.selectorExpression);if("exists"===i){let e=cn((await fc(o,t.flags,a,n,{interactiveOnly:!1})).nodes,d,{platform:o.device.platform});return e?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:i,selector:e.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:i,pass:!0,selector:e.selector.raw,matches:e.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:ci(d,[],{unique:!1})}}}let u=await fp({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:n,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!u.ok)return u.response;let{resolved:c}=u,p=function(e){let{predicate:t,node:r,nodes:a,expectedText:n,platform:i}=e,o=uX(r),s=ce(r,i),l=!0===r.selected,d="text"===t?u7(r):function(e,t){if(!0===e.hittable)return!0;if(fh(e.rect))return x(e,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),a=e,n=new Set;for(;"number"==typeof a.parentIndex&&!n.has(a.index);){n.add(a.index);let e=r.get(a.parentIndex);if(!e)break;if(function(e){let t=uz(e.type??"");return!(t.includes("application")||t.includes("window")||t.includes("scrollview")||t.includes("tableview")||t.includes("collectionview"))&&"table"!==t&&"list"!==t&&"listview"!==t&&(!0===e.hittable||fh(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!fh(r.rect)&&x(r,t))}(r,a),u=!1;switch(t){case"visible":u=d;break;case"hidden":u=!d;break;case"editable":u=s;break;case"selected":u=l;break;case"text":u=o===(n??"")}let c="text"===t?`expected="${n??""}" actual="${o}"`:`actual=${JSON.stringify({visible:d,editable:s,selected:l})}`;return{pass:u,actualText:o,details:c}}({predicate:i,node:c.node,nodes:u.snapshot.nodes,expectedText:l,platform:o.device.platform});return p.pass?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:i,selector:c.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,text:"text"===i?p.actualText:void 0}}),{ok:!0,data:{predicate:i,pass:!0,selector:c.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${i} failed for selector ${c.selector.raw}: ${p.details}`}}}function fg(e,t){var r,a;let n=Math.max(1,t.height),i=Math.max(1,t.width),o=t.y,s=t.y+n,l=t.x,d=t.x+i,u=s-.25*n,c=Math.max(8,.1*i),p=e.y+e.height/2,f=e.x+e.width/2;if(p>=o+.25*n&&p<=u)return null;let m=Math.round((r=f,a=l+c,Math.min(d-c,Math.max(a,r)))),h=Math.round(o+.86*n),w=Math.round(o+.14*n);return p>u?{x:m,startY:h,endY:w,direction:"down"}:{x:m,startY:w,endY:h,direction:"up"}}async function fy(e){let t,r,{req:a,sessionName:n,sessionStore:i,contextFromFlags:o}=e,s=i.get(n);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!l_("scrollintoview",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let l=a.positionals?.[0]??"";if(!l.startsWith("@"))return null;let d=fu("scrollintoview",a.flags);if(d)return d;let u=a.positionals&&a.positionals.length>1?a.positionals.slice(1).join(" ").trim():"",c=function(e,t,r){let a=c4({session:e,refInput:t,fallbackLabel:r,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${t} not found or has no bounds`});if(!a.ok){let{response:e}=a;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:fI(t,0,{message:e.error.message})}}return fv(t,0,a.target)}(s,l,u);if(!c.ok)return c.response;let{ref:p}=c.state,{currentRef:f,node:m,snapshotNodes:h,viewportRect:w}=c.state,g=uq(m,h),y=cs(m,s.device.platform,{action:"get"}),v=u||g||m.label||"";if(!fg(m.rect,w)){let e=fA({ref:p,currentRef:f,attempts:0,alreadyVisible:!0});return i.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{refLabel:g,selectorChain:y,...e}}),{ok:!0,data:e}}let I=a.flags?.maxScrolls??48,A=0,b=0,S=V(m.rect,w);for(;A<I;){let e=fg(m.rect,w);if(!e)break;t=e.direction,r=await lo(s.device,"swipe",[String(e.x),String(e.startY),String(e.x),String(e.endY),"16"],a.flags?.out,{...o(a.flags,s.appBundleId,s.trace?.outPath),count:1,pauseMs:0,pattern:"one-way"}),A+=1,await fc(s,a.flags,i,o,{interactiveOnly:!0});let n=function(e){let{session:t,targetInput:r,fallbackLabel:a,attempts:n,ref:i,selectorChain:o,platform:s}=e;if(t.snapshot){let e=function(e,t,r,a){for(let r of t){let t=ca(e,u0(r),{platform:a,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?uj(e,r):null}(t.snapshot.nodes,o,a,s);if(e)return fv(r,n,{ref:i,node:e,snapshotNodes:t.snapshot.nodes},{currentRef:e.ref})}let l=c4({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${r} not found or has no bounds`});if(!l.ok){let{response:e}=l;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:fI(r,n,{message:`scrollintoview lost track of ${r} after ${n} scroll${1===n?"":"s"}`,ref:i})}}return fv(r,n,l.target,{ref:i,currentRef:l.target.node.ref,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${n} scroll${1===n?"":"s"}`})}({session:s,targetInput:l,fallbackLabel:v,attempts:A,ref:p,selectorChain:y,platform:s.device.platform});if(!n.ok)return n.response;({currentRef:f,node:m,snapshotNodes:h,viewportRect:w}=n.state);let d=V(m.rect,w);if(0===d)break;if(d>=S){if((b+=1)>=2)return fI(l,A,{message:`scrollintoview made no progress toward ${l} after ${A} scroll${1===A?"":"s"}`,ref:p,stalled:!0})}else b=0;S=d}if(V(m.rect,w)>0)return fI(l,A,{message:`scrollintoview reached --max-scrolls=${I} before ${l} entered view`,ref:p,maxScrolls:I});let _=fA({data:r,ref:p,currentRef:f,attempts:A,direction:t});return i.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{refLabel:g,selectorChain:y,..._}}),{ok:!0,data:_}}function fv(e,t,r,a={}){let{ref:n,currentRef:i,missingBoundsMessage:o}=a,s=r.node;if(!s.rect)return{ok:!1,response:fI(e,t,{message:o??`Ref ${e} not found or has no bounds`,ref:n??r.ref})};let l=Y(r.snapshotNodes,s.rect);return l?{ok:!0,state:{ref:n??r.ref,currentRef:i??r.node.ref,node:s,snapshotNodes:r.snapshotNodes,viewportRect:l}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${e}`}}}}function fI(e,t,r={}){let{message:a,...n}=r;return{ok:!1,error:{code:"COMMAND_FAILED",message:"string"==typeof a?a:`scrollintoview could not find ${e}`,details:{reason:"not_found",attempts:t,...n}}}}function fA(e){let{data:t,ref:r,currentRef:a,attempts:n,alreadyVisible:i,direction:o}=e;return{...t??{},ref:r,currentRef:a,attempts:n,...i?{alreadyVisible:i}:{},...o?{direction:o}:{},...el(`Scrolled into view: @${r}`)}}async function fb(e){let t=await fl({...e,captureSnapshotForSession:fc,resolveRefTarget:c4,refSnapshotFlagGuardResponse:fu});if(t)return t;switch(e.req.command){case"get":return await ff(e);case"is":return await fw(e);case"scrollintoview":return await fy(e);default:return null}}function fS(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 f_(e){let{req:t,leaseRegistry:r}=e,a=fS(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:a.tenantId??"",runId:a.runId??"",backend:a.leaseBackend,ttlMs:a.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId,ttlMs:a.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId})};default:return null}}function fN(e,t){if(!t)return[];let r=[],a=e.device,n=t.platform;if(n&&!tS(a.platform,n)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),n=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==n)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=e5(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function fD(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let fx=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],fk=/\bis(?:n't| not)\s+responding\b/i,fM=/^close app$/i;async function fE(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await fO(t),r=function(e){if(fR(e))return e.find(e=>{let t=fP(e);return t.length>0&&fM.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:n}=eA(r.rect),i=await R("adb",aE(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(n))]),{allowFailure:!0});if(0!==i.exitCode)return ed({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:i.exitCode,stdout:i.stdout.trim(),stderr:i.stderr.trim()}}),"failed";if(!await fL(t))return ed({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await nO(t.device,t.appBundleId),!await fC(t,t.appBundleId)))return ed({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return ed({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:a,y:n}}),"recovered"}catch(e){return ed({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function fO(e){return eS(uW((await ie(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function fL(e){for(let t=0;t<12;t+=1){if(!fR(await fO(e)))return!0;await fT(500)}return!fR(await fO(e))}async function fC(e,t){for(let r=0;r<12;r+=1){if((await nM(e.device)).package===t)return!0;await fT(500)}return(await nM(e.device)).package===t}function fP(e){let t=[e.label,e.identifier];return"string"==typeof e.value&&e.value.trim().length>0&&t.push(e.value),t.filter(e=>"string"==typeof e&&e.trim().length>0).join(" ").trim()}function fR(e){return e.some(e=>{let t=fP(e);return t.length>0&&fk.test(t)})}function fT(e){return new Promise(t=>setTimeout(t,e))}let f$=[255,59,48,255],fF=[255,214,10,255],fU=[0,0,0,255],fV={e:["01110","10000","11110","10000","10000","10001","01110"],0:["01110","10001","10011","10101","11001","10001","01110"],1:["00100","01100","00100","00100","00100","00100","01110"],2:["01110","10001","00001","00010","00100","01000","11111"],3:["11110","00001","00001","01110","00001","00001","11110"],4:["00010","00110","01010","10010","11111","00010","00010"],5:["11111","10000","10000","11110","00001","00001","11110"],6:["01110","10000","10000","11110","10001","10001","01110"],7:["11111","00001","00010","00100","01000","01000","01000"],8:["01110","10001","10001","01110","10001","10001","01110"],9:["01110","10001","10001","01111","00001","00001","01110"]};async function fG(e){let t=N(await d.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let n=function(e){let t=null;for(let r of e)fj(r)&&fJ(r.rect)&&(!t||fK(r.rect)>fK(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,a=-1/0,n=-1/0;for(let i of e)i.rect&&fJ(i.rect)&&(t=Math.min(t,i.rect.x),r=Math.min(r,i.rect.y),a=Math.max(a,i.rect.x+i.rect.width),n=Math.max(n,i.rect.y+i.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||a<=t||n<=r?null:{x:t,y:r,width:a-t,height:n-r}}(e.filter(e=>{var t;return fJ(e.rect)&&!("image"===uz((t=e).type??"")&&!fq(t.label))}))}(e.nodes),i=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(fH)||fW(e.identifier);return fB(e)?t:t&&function(e){let t=uz(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(a))continue;let o=function(e,t){if(function(e){return fB(e)&&!fj(e)}(t)&&fJ(t.rect))return t;let r=function(e,t){let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){;a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(fB(t)&&!fj(t)&&fJ(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&fJ(r.rect))return r;if(t.hittable&&fJ(t.rect)&&!fj(t))return t;let a=uK(e,t);return a?.rect&&fJ(a.rect)&&!fj(a)?a:null}(e.nodes,a);if(!o?.rect||!fJ(o.rect))continue;let s=function(e,t,r){let a=fz(e);if(e.ref!==t.ref&&a)return a;let n=function(e,t){let r=null;for(let a of t){if(a.ref===e.ref||!function(e,t,r){let a=e;for(;void 0!==a.parentIndex;){let e=r[a.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;a=e}return!1}(a,e,t))continue;let n=fz(a);if(!n)continue;let i=function(e){let t=0;return uz(e.type??"").includes("text")&&(t+=2),fH(e.label)&&(t+=2),fH(e.value)&&(t+=1),t}(a);(!r||i>r.score)&&(r={label:n,score:i})}return r?.label}(t,r);return n||(fz(t)??uq(t,r))}(a,o,e.nodes),l=function(e,t,r){let a=0;return e.ref===t.ref&&(a+=4),t.hittable&&(a+=3),fB(t)&&(a+=3),fB(e)&&(a+=2),r&&(a+=2),fW(t.identifier)&&(a+=1),fq(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return fZ({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,a);let n=r/e.width,i=a/e.height;return fZ({x:Math.round((t.x-e.x)*n),y:Math.round((t.y-e.y)*i),width:Math.max(1,Math.round(t.width*n)),height:Math.max(1,Math.round(t.height*i))},r,a)}(n,o.rect,t,r);if(!fJ(d))continue;let u=i.get(o.ref);(!u||l>u.score)&&i.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:d,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>fK(e.overlayRect)-fK(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(fX(e.overlayRect,r.overlayRect)||fX(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}fK(r.overlayRect)<fK(t[e].overlayRect)&&(t[e]=r)}return t})([...i.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:fY(e.ref,t.ref)}).slice(0,a.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:fY(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:eA(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,n;(function(e,t,r){for(let a=0;a<2;a+=1)f0(e,t.x,t.x+t.width-1,t.y+a,r),f0(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),f1(e,t.x+a,t.y,t.y+t.height-1,r),f1(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(n=e).overlayRect,f$),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),n=fQ(t.x,0,Math.max(0,e.width-a)),i=t.y-11-2,o=i>=0?i:fQ(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,n){for(let i=0;i<11;i+=1)for(let o=0;o<a;o+=1)f2(e,t+o,r+i,n)})(e,n,o,a,fF),function(e,t,r,a,n){let i=t;for(let t of a.toLowerCase()){let a=fV[t];if(a)for(let t=0;t<a.length;t+=1)for(let o=0;o<a[t].length;o+=1)"1"===a[t][o]&&f2(e,i+o,r+t,n);i+=6}}(e,n+3,o+2,r,fU)}(a,n.overlayRect,n.ref)}return await d.writeFile(e.screenshotPath,S.sync.write(t)),r}function fB(e){let t=[e.type,e.role,e.subrole].map(e=>uz(e??"")).join(" ");return t.includes("button")||t.includes("link")||t.includes("menu")||t.includes("tab")||t.includes("textfield")||t.includes("searchfield")||t.includes("securetextfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")||t.includes("cell")}function fj(e){let t=[e.type,e.role,e.subrole].map(e=>uz(e??"")).join(" ");return t.includes("application")||t.includes("window")}function fq(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function fH(e){var t;let r;return!!fq(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function fW(e){var t;return"string"==typeof e&&!!fH(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function fz(e){let t=[e.label,e.value].find(fH);return t?t.trim():fW(e.identifier)?e.identifier.trim():void 0}function fJ(e){return!!(e&&e.width>0&&e.height>0)}function fK(e){return e.width*e.height}function fX(e,t){return t.x>=e.x&&t.y>=e.y&&t.x+t.width<=e.x+e.width&&t.y+t.height<=e.y+e.height}function fY(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function fZ(e,t,r){let a=fQ(e.x,0,Math.max(0,t-1)),n=fQ(e.y,0,Math.max(0,r-1)),i=Math.max(1,t-a),o=Math.max(1,r-n);return{x:a,y:n,width:fQ(e.width,1,i),height:fQ(e.height,1,o)}}function fQ(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function f0(e,t,r,a,n){for(let i=t;i<=r;i+=1)f2(e,i,a,n)}function f1(e,t,r,a,n){for(let i=r;i<=a;i+=1)f2(e,t,i,n)}function f2(e,t,r,a){if(t<0||r<0||t>=e.width||r>=e.height)return;let n=(e.width*r+t)*4;e.data[n]=a[0],e.data[n+1]=a[1],e.data[n+2]=a[2],e.data[n+3]=a[3]}let f3=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),f4=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),f8=new Set(f4),f5=new Map;function f6(e,t,r,a){let n=en().requestId;return{...lN(e,t,r,a,n),requestId:n}}async function f9(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||lq(e.flags))try{let t=await li(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function f7(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,leaseRegistry:i,invoke:o,contextFromFlags:s}=e,l=await f_({req:t,leaseRegistry:i});if(l)return l;let d=await cN({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:o});if(d)return d;let u=await cZ({req:t,sessionName:r,logPath:a,sessionStore:n});if(u)return u;let c=await pz({req:t,sessionName:r,sessionStore:n,logPath:a});if(c)return c;let p=await pt({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:o});if(p)return p;let f=await fb({req:t,sessionName:r,sessionStore:n,contextFromFlags:s});return f||null}async function me(e){var t;let r,a,n,i,o,s,l,{req:d,session:u,logPath:c,sessionStore:p}=e,f=d.command;if(!l_(f,u.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${f} is not supported on this device`}};if("android"===u.device.platform&&u.recording&&"record"!==f&&"failed"===await fE({session:u}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:m,resolvedOut:h,recordedPositionals:w,recordedFlags:g}=(r=(t=d).command,a=t.positionals??[],n=t.flags?.out,i="screenshot"===r&&a[0]?[rg.expandHome(a[0],t.meta?.cwd),...a.slice(1)]:a,o="screenshot"===r&&n?rg.expandHome(n,t.meta?.cwd):n,s="screenshot"===r?i:a,l="screenshot"===r&&o?{...t.flags??{},out:o}:t.flags??{},{resolvedPositionals:i,resolvedOut:o,recordedPositionals:s,recordedFlags:l}),y=Date.now(),v={...f6(c,d.flags,u.appBundleId,u.trace?.outPath),surface:u.surface},I=await lo(u.device,f,m,h,{...v});return"screenshot"===f&&d.flags?.overlayRefs&&"string"==typeof I?.path&&await mt(u,I,c),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:n,recordedPositionals:i,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:d,flags:u}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let n=pX(e.snapshot),i={...a??{}},o=p2(i.direction)??p2(r[0]);if(!o)return a;let s=p3(i.amount)??p3(r[1]),l=p3(i.pixels),d=p5(i,[]),u=p3(i.referenceWidth),c=p3(i.referenceHeight),p=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:n??pZ;if(d&&(d.x1!==d.x2||d.y1!==d.y2))return{...i,x1:d.x1,y1:d.y1,x2:d.x2,y2:d.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250};let f=nY({direction:o,amount:s,pixels:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return{...i,x1:f.x1,y1:f.y1,x2:f.x2,y2:f.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==f.pixels?{pixels:f.pixels}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250}}(t,a,n,s);pQ(t,a,n,c,u,l,d),r.recordAction(t,{command:a,positionals:i,flags:o,result:s??{}})}({session:u,sessionStore:p,command:f,resolvedPositionals:m,recordedPositionals:w,recordedFlags:g,data:I,actionStartedAt:y,actionFinishedAt:Date.now(),flags:d.flags??{}}),dx(f)&&d_(u,f),{ok:!0,data:I??{}}}async function mt(e,t,r){let a=cP(await cE({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=a;let n=await fG({screenshotPath:t.path,snapshot:a});t.overlayRefs=n}function mr(e){s.existsSync(e)&&s.unlinkSync(e)}function ma(e){if(!s.existsSync(e))return null;try{let t=JSON.parse(s.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function mn(e){let t=ma(e);if(!t||t.pid===process.pid)try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}function mi(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:mo,infoPath:ms,lockPath:ml,logPath:md,sessionsDir:mu}=ey(process.env.AGENT_DEVICE_STATE_DIR),mc=eI(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var mp=mu;if(s.existsSync(mp))for(let e of s.readdirSync(mp,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=c.join(mp,e.name,"app-log.pid");if(s.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}}(s.readFileSync(t,"utf8"));if(e&&function(e){let t,r=ew(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=D(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{rv(t)}}let mf=new rg(mu),mm=new a_({maxActiveSimulatorLeases:mi(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:mi(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:mi(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:mi(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),mh=ea(),mw=i.randomBytes(24).toString("hex"),mg=ew(process.pid)??void 0,my=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=s.statSync(e),r=em(),a=c.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),mv=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:n,trackDownloadableArtifact:i}=e;async function o(e){let s=!!(e.meta?.debug||e.flags?.verbose);return await eg({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:s,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:ee(new q("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=et(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=M(r);if(r&&!a)throw new q("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new q("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let n=e.session||"default";return n.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${n}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);ed({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let s=r.command,l=fS(r);f4.has(s)||r.meta?.sessionIsolation!=="tenant"||n.assertLeaseAdmission({tenantId:l.tenantId,runId:l.runId,leaseId:l.leaseId,backend:l.leaseBackend});let d=function(e,t){var r;let a,n=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==n||t.has(n))return n;let i=t.toArray();return 1===i.length?i[0].name:n}(r,a),u=f8.has(s)?null:await f9(r,d,a),p=async()=>{let e=a.get(d);e&&(!function(e){var t,r;let a,n=e.recording;if(!n||"ios"!==e.device.platform)return;let i=(t=e.device.id,(a=tK.get(t))?{sessionId:a.sessionId,alive:!!(r=a.child.pid)&&eh(r)}:null);if(!n.runnerSessionId){i?.alive&&(n.runnerSessionId=i.sessionId);return}if(!i?.alive){n.invalidatedReason??="iOS runner session exited during recording";return}i.sessionId!==n.runnerSessionId&&(n.invalidatedReason??="iOS runner session restarted during recording")}(e),a.set(d,e));let l=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},n=t?fN(t,a):function(e,t,r){var a,n;let i=[];if(void 0!==e.platform&&t&&(a=e.platform,n=t,a&&n&&a!==n&&("apple"===a?!tb(n):"apple"!==n||!tb(a)))&&i.push({key:"platform",value:e.platform}),"open"===r)return i;for(let t of fx){let r=e[t];"string"==typeof r&&r.trim().length>0&&i.push({key:t,value:r})}return i}(a,e.meta?.lockPlatform,e.command);if(0===n.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,n),a.platform=t.device.platform):function(e,t){for(let t of fx)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new q("INVALID_ARGS",`${e.command} cannot override session lock policy with ${n.map(fD).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),u=e=>(function(e,t,r){let a=en();if(!t.ok){ed({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=ev({force:!0})??void 0;return{ok:!1,error:ee(new q(t.error.code,t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:a.diagnosticId,logPath:e})}}return ed({level:"info",phase:"request_success"}),ev(),{ok:!0,data:function(e,t,r){var a,n;let i;if(!t)return t;let o=(a=e,n=t,i=Array.isArray(n.artifacts)?[...n.artifacts]:[],"screenshot"!==a.command||i.some(e=>e?.field==="path")||"string"!=typeof n.path||i.push({field:"path",path:n.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:c.basename(a.meta?.clientArtifactPaths?.path??n.path)}),i.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===o.length?t:{...t,artifacts:o.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(l,e,i);if(e?.recording?.invalidatedReason&&"record"!==s&&"close"!==s)return u({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||l.meta?.lockPolicy||f3.has(s)||function(e,t){let r=fN(e,t);if(0!==r.length){var a;let t,n,i;throw new q("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,n=a.device.name.trim(),i=a.device.id,`${t} device "${n}" (${i})`)} and cannot be used with ${r.map(fD).join(", ")}. Use a different --session name or close this session first.`)}}(e,l.flags);let p=await f7({req:l,sessionName:d,logPath:t,sessionStore:a,leaseRegistry:n,invoke:o,contextFromFlags:(e,r,n)=>({...f6(t,e,r,n),surface:a.get(d)?.surface})});if(p)return u(p);let f=a.get(d);if(!f)return u({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await me({req:l,session:f,sessionName:d,logPath:t,sessionStore:a});return u(m)};if(!u)return await p();return await tA(f5,u,p)}catch(r){ed({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=en(),t=ev({force:!0})??void 0;return{ok:!1,error:ee(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return o}({logPath:md,token:mw,sessionStore:mf,leaseRegistry:mm,trackDownloadableArtifact:function(e){let t=i.randomUUID(),r=setTimeout(()=>{r4(t)},9e5);return r.unref(),r3.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){s.existsSync(e)||s.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),n=()=>{try{return s.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(n())return!0;let i=ma(t);if(i?.pid&&i.pid!==process.pid&&E(i.pid,i.processStartTime))return!1;try{s.unlinkSync(t)}catch{}return n()}(mo,ml,{pid:process.pid,version:mh,startedAt:Date.now(),processStartTime:mg})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let n;if("socket"===mc||"dual"===mc){let t=p.createServer(e=>{let t="",r=0,a=new Set,n=!1,i=()=>{if(!n&&0!==r){for(let e of(n=!0,a))eW(e);ed({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await t2(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){ed({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",i),e.on("error",i),e.on("data",async n=>{let i=(t+=n).indexOf("\n");for(;-1!==i;){let n,o,s=t.slice(0,i).trim();if(t=t.slice(i+1),0===s.length){i=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=eq(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),eH(o),eJ(o))throw eX();n=await mv(e)}catch(e){n={ok:!1,error:ee(e)}}finally{r-=1,o&&(a.delete(o),ez(o))}e.destroyed||e.write(`${JSON.stringify(n)}
|
|
69
|
-
`),i=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new
|
|
67
|
+
`.trim();async function p6(e,t={}){let r,a=t.pollMs??150,n=t.attempts??12,i=0;for(let t=0;t<n;t+=1){let t=0;try{t=s.statSync(e).size}catch{t=0}if(t>0&&t===r){if((i+=1)>=2)return}else i=0;r=t,await new Promise(e=>setTimeout(e,a))}}async function p9(e){try{var t,r;let a,n=await T("swift",["-",e],{stdin:p8,allowFailure:!0,timeoutMs:1e4});if(0===n.exitCode)return!0;if(t=n.stderr,r=n.stdout,a=`${t}
|
|
68
|
+
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return fe(e);return!1}catch(t){if(t instanceof H&&"TOOL_MISSING"===t.code)return fe(e);throw t}}async function p7(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await p9(e))return;await new Promise(e=>setTimeout(e,r))}}function fe(e){try{let t=s.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=s.openSync(e,"r");try{let e=s.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r))break;let n=e.readUInt32BE(0),i=e.toString("latin1",4,8);if(a.push(i),1===n){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r+8))break;n=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(n)||n<=0)break;r+=n}return a}finally{s.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function ft(e){let t=p.parse(e);return p.join(t.dir,`${t.name}.gesture-telemetry.json`)}function fr(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function fa(e){var t,r,a;let n,i,{recording:o,trimStartMs:l}=e,d=(n=ft((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:l}).videoPath),i={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?fr(r.flatMap(e=>{let t=e.tMs-a,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):fr(r))},s.writeFileSync(n,JSON.stringify(i,null,2)),n);return o.telemetryPath=d,d}function fn(e){let t=p.dirname(w(import.meta.url)),r=[w(new URL(`./${e}`,import.meta.url)),p.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),p.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),p.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(s.existsSync(e))return e;throw new H("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}function fi(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}async function fo(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await p6(t),await p7(t);let i=s.mkdtempSync(p.join(u.tmpdir(),"agent-device-record-overlay-")),o=p.join(i,`input${p.extname(t)||".mp4"}`),l=p.join(i,p.basename(t)),d=p.join(i,"home"),c=p.join(i,"module-cache");s.copyFileSync(t,o),s.mkdirSync(d,{recursive:!0}),s.mkdirSync(c,{recursive:!0});try{await T("xcrun",["swift",r,"--input",o,"--output",l,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:c}}),await p7(l),s.copyFileSync(l,t)}catch(a){let e=a instanceof H?a:new H("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new H("COMMAND_FAILED",n,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{s.rmSync(i,{recursive:!0,force:!0})}}async function fs(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await fo({videoPath:t,scriptPath:a??=fn("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function fl(e){let{videoPath:t,telemetryPath:a,targetLabel:n="recording"}=e;await fo({videoPath:t,scriptPath:r??=fn("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${n}`})}function fd(e){return e instanceof Error?e.message:String(e)}function fu(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function fc(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===a.exitCode&&a.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function fp(e,t,r){for(let a=0;a<40;a+=1){if(!await fc(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await fc(e,t,r)}async function ff(e,t,r){let a,n=0;for(let i=0;i<20;i+=1){let i=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===i.exitCode?i.stdout.trim():"";if(o.length>0&&o===a){if((n+=1)>=4)return}else n=0;a=o,await new Promise(e=>setTimeout(e,250))}}async function fm(e,t,r,a){for(let n=0;n<8;n+=1){let i=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===i.exitCode?Number(i.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await fc(e,t,a))break;if(n+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function fh(e){let t,{deps:r,deviceId:a,remotePath:n,outPath:i}=e;for(let e=0;e<2;e+=1){try{s.rmSync(i,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",a,"pull",n,i],{allowFailure:!0});if(0!==o.exitCode)t=fu(o,"adb pull");else{await r.waitForStableFile(i,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(i);if(eu({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:n,outPath:i,attempt:e+1,fileSize:(()=>{try{return s.statSync(i).size}catch{return 0}})(),playable:t}}),t)return;eu({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:n,outPath:i,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function fw(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function fg(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return eu({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await fc(e,t,r))&&await fp(e,t,r)}async function fy(e){var t;let r,{deps:a,device:n,recordingBase:i}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",n.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${fu(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){o="failed to start recording: adb did not return a valid Android screenrecord pid",await fw(a,n.id,e);continue}if(eu({level:"debug",phase:"record_start_android_started",data:{deviceId:n.id,remotePath:e,remotePid:r}}),await fm(a,n.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...i,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await fg(a,n.id,r),await fw(a,n.id,e)}return{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}async function fv(e){let t,r,{deps:a,device:n,recording:i}=e;eu({level:"debug",phase:"record_stop_android_enter",data:{deviceId:n.id,remotePath:i.remotePath,remotePid:i.remotePid}});let o=await a.runCmd("adb",["-s",n.id,"shell","kill","-2",i.remotePid],{allowFailure:!0});if(eu({level:"debug",phase:"record_stop_android_signal",data:{deviceId:n.id,remotePath:i.remotePath,remotePid:i.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await fc(a,n.id,i.remotePid)&&!await fg(a,n.id,i.remotePid)&&(t=`failed to stop recording: ${fu(o,"adb shell kill")}`):await fp(a,n.id,i.remotePid)||await fg(a,n.id,i.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${i.remotePid} did not exit`),!t){await ff(a,n.id,i.remotePath);let e=await fh({deps:a,deviceId:n.id,remotePath:i.remotePath,outPath:i.outPath});if(e)return await s(),{ok:!1,error:{code:"COMMAND_FAILED",message:e}};if(fa({recording:i}),i.showTouches&&i.telemetryPath){let e=fi();if(e)i.overlayWarning=e;else try{await a.overlayRecordingTouches({videoPath:i.outPath,telemetryPath:i.telemetryPath,targetLabel:"Android recording"})}catch(e){i.overlayWarning=`failed to overlay recording touches: ${fd(e)}`}}}if(await s(),t)return{ok:!1,error:{code:"COMMAND_FAILED",message:t}};if(r)return{ok:!1,error:{code:"COMMAND_FAILED",message:r}};return null;async function s(){let e=await a.runCmd("adb",["-s",n.id,"shell","rm","-f",i.remotePath],{allowFailure:!0});eu({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:n.id,remotePath:i.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${fu(e,"adb shell rm")}`)}}function fI(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function fb(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function fA(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i}=e,o=fI(r);if(o)try{await i.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},fb(t,n,r))}catch(e){eu({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:fd(e)}})}}async function fS(e){let t,r,{req:a,activeSession:n,sessionStore:i,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=fb(a,s,n),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var w,g;if(!fd(a).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${fd(a)}`}};eu({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:n.name,error:fd(a)}});let e=(w=o.id,g=n.name,i.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${e.name}'`}};try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${fd(e)}`}}}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function f_(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await i.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},fb(t,n,r))}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${fd(e)}`}}}return{platform:"macos-runner",...s}}async function fN(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i,recording:o}=e,s=fI(r);try{await i.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},fb(t,n,r))}catch(e){eu({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:fd(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of tF)if(0===(l=await i.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);d>0&&await i.trimRecordingStart({videoPath:o.outPath,trimStartMs:d});let u=fa({recording:o,trimStartMs:d});if(o.showTouches){let e=fi();if(e)o.overlayWarning=e;else try{await i.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:u,targetLabel:"iOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${fd(e)}`}}return null}async function fx(e){let{req:t,activeSession:r,device:a,logPath:n,deps:i,recording:o}=e,s=fI(r);try{await i.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},fb(t,n,r))}catch(e){eu({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:fd(e)}})}let l=fa({recording:o});if(o.showTouches){let e=fi();if(e)o.overlayWarning=e;else try{await i.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:l,targetLabel:"macOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${fd(e)}`}}return null}async function fD(e){for(let t=0;t<2;t+=1){try{if(s.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function fk(e){let t,r,{req:a,activeSession:n,device:i,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await fA({req:a,activeSession:n,device:i,logPath:o,deps:s});let{child:u,wait:c}=s.runCmdBackground("xcrun",te(i,["io",i.id,"recordVideo",d]),{allowFailure:!0}),p=await fD(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(i,{command:"uptime",appBundleId:fI(n)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:n.trace?.outPath}),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:u,wait:c,...l,startedAt:p,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function fM(e){let t,{req:r,sessionName:a,sessionStore:n,activeSession:i,device:o,logPath:l,deps:d}=e;if(i.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let u=r.flags?.fps;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};if(!dd("record",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let c=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,f=rx.expandHome(c,r.meta?.cwd),m={outPath:f,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(s.mkdirSync(p.dirname(f),{recursive:!0}),s.rmSync(f,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=fI(i);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};t=await fS({req:r,activeSession:i,sessionStore:n,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else if("macos"===o.platform){let e=fI(i);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on macOS requires an active app session; run open <app> first"}};t=await f_({req:r,activeSession:i,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else t="ios"===o.platform?await fk({req:r,activeSession:i,device:o,logPath:l,deps:d,recordingBase:m,resolvedOut:f}):await fy({deps:d,device:o,recordingBase:m});return"ok"in t?t:(i.recording=t,n.set(a,i),n.recordAction(i,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??c,showTouches:t.showTouches}})}async function fE(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await fv({deps:t,device:r,recording:a});a.child.kill("SIGINT");let n=await a.wait;if(0!==n.exitCode)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to stop recording: ${fu(n,"simctl recordVideo")}`}};let i=fa({recording:a});if(a.showTouches){let e=fi();if(e)a.overlayWarning=e;else try{await t.overlayRecordingTouches({videoPath:a.outPath,telemetryPath:i,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to overlay recording touches: ${fd(e)}`}}return null}async function fO(e){var t;let r,{req:a,activeSession:n,device:i,logPath:o,deps:s}=e;if(!n.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let l=n.recording,d=l.invalidatedReason;n.recording=void 0;let u="ios-device-runner"===l.platform?await fN({req:a,activeSession:n,device:i,logPath:o,deps:s,recording:l}):"macos-runner"===l.platform?await fx({req:a,activeSession:n,device:i,logPath:o,deps:s,recording:l}):await fE({deps:s,device:i,recording:l});return u||(d?{ok:!1,error:{code:"COMMAND_FAILED",message:d}}:(r=[{field:"outPath",path:(t=l).outPath,localPath:t.clientOutPath,fileName:p.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return ft(e.clientOutPath)}(t),fileName:p.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function fL(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,i={runCmd:T,runCmdBackground:C,runIosRunnerCommand:rs,waitForStableFile:p6,isPlayableVideo:p9,trimRecordingStart:fs,overlayRecordingTouches:fl},o=a.get(r),s=o?.device??await lY(t.flags??{});o||await dp(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};if("start"===d)return fM({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:n,deps:i});let u=await fO({req:t,activeSession:l,device:s,logPath:n,deps:i});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function fC(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,i=t.command;if("record"===i)return fL({req:t,sessionName:r,sessionStore:a,logPath:n});if("trace"===i){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return uC("INVALID_ARGS","trace requires start|stop");let n=a.get(r);if(!n)return uC("SESSION_NOT_FOUND","No active session");if("start"===e){if(n.trace)return uC("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(n),r=rx.expandHome(e);return s.mkdirSync(p.dirname(r),{recursive:!0}),s.appendFileSync(r,""),n.trace={outPath:r,startedAt:Date.now()},a.recordAction(n,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!n.trace)return uC("INVALID_ARGS","no active trace");let o=n.trace.outPath;if(t.positionals?.[1]){let e=rx.expandHome(t.positionals[1]);s.mkdirSync(p.dirname(e),{recursive:!0}),s.existsSync(o)?s.renameSync(o,e):s.appendFileSync(e,""),o=e}return n.trace=void 0,a.recordAction(n,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function fP(e){return"number"==typeof e.gestureClockOriginAtMs&&"number"==typeof e.gestureClockOriginUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureClockOriginAtMs+(e.gestureStartUptimeMs-e.gestureClockOriginUptimeMs)-e.recordingStartedAt):"number"==typeof e.runnerStartedAtUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureStartUptimeMs-e.runnerStartedAtUptimeMs):"number"==typeof e.gestureStartUptimeMs&&"number"==typeof e.gestureEndUptimeMs?Math.max(0,e.fallbackFinishedAtMs-(e.gestureEndUptimeMs-e.gestureStartUptimeMs)-e.recordingStartedAt):Math.max(0,e.fallbackStartedAtMs-e.recordingStartedAt)}let fR=new WeakMap;function fT(e){if(!e)return;let t=fR.get(e);if(t)return t;let r=function(e){let t=function(e){let t=e.filter(e=>(function(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("application")||t.includes("window")})(e.type)&&f$(e.rect)).map(e=>e.rect).sort((e,t)=>(t?.width??0)*(t?.height??0)-(e?.width??0)*(e?.height??0))[0];if(t)return t;let r=e.map(e=>e.rect).filter(f$);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),n=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(n<=0))return{x:0,y:0,width:a,height:n}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return fR.set(e,r),r}function f$(e){return!!e&&e.width>0&&e.height>0}let fF={referenceWidth:1e3,referenceHeight:1e3};function fU(e,t,r,a,n={},i=Date.now(),o=Date.now()){var s,l,d;let u,c,p=e.recording;if(!p)return;let f={...n,...a??{}},m=fj(f.effectiveDurationMs)??fj(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:fj(f.gestureStartUptimeMs),gestureEndUptimeMs:fj(f.gestureEndUptimeMs),fallbackStartedAtMs:i,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:fj(f.gestureStartUptimeMs),gestureEndUptimeMs:fj(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:i,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===fj(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=fq(fj(t.count),1)??1,r=!0===t.doubleTap,a=fq(fj(t.holdMs),1);return 1===e&&!r&&void 0===a}default:return!1}}(t,f)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return fP(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):fP(h),y=(l=e.snapshot,u=fj((d=f).referenceWidth),c=fj(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:fT(l)),v=function(e,t,r,a,n,i){switch(e){case"click":case"press":return function(e,t,r,a){let n=fH(t,e);if(!n)return[];let{x:i,y:o}=n,s=fq(fj(t.count),1)??1,l=fq(fj(t.intervalMs),0)??0,d=!0===t.doubleTap,u=fq(fj(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(fV(t,i,o,u,a));continue}c.push(fG(t,i,o,a)),d&&c.push(fG(t+90,i,o,a))}return c}(t,r,a,i);case"fill":case"focus":return function(e,t,r,a){let n=fH(t,e);if(!n)return[];let{x:i,y:o}=n;return[fG(r,i,o,a)]}(t,r,a,i);case"longpress":return function(e,t,r,a,n){let i=fH(t,e);if(!i)return[];let{x:o,y:s}=i;return[fV(r,o,s,fz(a,[fj(t.durationMs),fj(e[2])],800),n)]}(t,r,a,n,i);case"scroll":return function(e,t,r,a,n){let i=fW(t,e),o=fB(t.contentDirection)??fB(t.direction);if(!i||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=i,c=fz(a,[],250),p=fj(t.amount)??fj(e[1]),f=fj(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...n,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{},...void 0!==f?{pixels:f}:{}}]}(t,r,a,n,i);case"swipe":return function(e,t,r,a,n){let i=fW(t,e);if(!i)return[];let{x1:o,y1:s,x2:l,y2:d}=i,u=fz(a,[fj(t.effectiveDurationMs),fj(t.durationMs),fj(e[4])],250),c=fq(fj(t.count),1)??1,p=fq(fj(t.pauseMs),0)??0,f="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===f&&e%2==1,a=t?l:o,i=t?d:s,c=t?o:l,h=t?s:d,w=r+e*(u+p);if("back-swipe"===function(e,t,r,a,n){if(!n||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let i=.08*n.referenceWidth;return e<=i&&r>e||e>=n.referenceWidth-i&&r<e?"back-swipe":"swipe"}(a,i,c,h,n)){m.push({kind:"back-swipe",tMs:w,x:a,y:i,x2:c,y2:h,...n,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,n)});continue}m.push({kind:"swipe",tMs:w,x:a,y:i,x2:c,y2:h,...n,durationMs:u})}return m}(t,r,a,n,i);case"pinch":return function(e,t,r,a,n){let i=fH(t,e,1),o=fj(t.scale)??fj(e[0]);if(!i||void 0===o||o<=0)return[];let{x:s,y:l}=i;return[{kind:"pinch",tMs:r,x:s,y:l,...n,scale:o,durationMs:fz(a,[],280)}]}(t,r,a,n,i);default:return[]}}(t,r,f,g,w,y);0!==v.length&&(p.gestureEvents.push(...v),eu({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:v.length,tMs:g,gestureDurationMs:w,kinds:v.map(e=>e.kind)}}))}function fG(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function fV(e,t,r,a,n){return{kind:"longpress",tMs:e,x:t,y:r,...n,durationMs:a}}function fB(e){if("string"!=typeof e)return;let t=e.trim().toLowerCase();switch(t){case"up":case"down":case"left":case"right":return t;default:return}}function fj(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e||0===e.trim().length)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function fq(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function fH(e,t,r=0){let a=fj(e.x)??fj(t[r]),n=fj(e.y)??fj(t[r+1]);if(void 0!==a&&void 0!==n)return{x:a,y:n}}function fW(e,t){let r=fj(e.x1)??fj(t[0]),a=fj(e.y1)??fj(t[1]),n=fj(e.x2)??fj(t[2]),i=fj(e.y2)??fj(t[3]);if(void 0!==r&&void 0!==a&&void 0!==n&&void 0!==i)return{x1:r,y1:a,x2:n,y2:i}}function fz(e,t,r){return fq(e,1)??t.map(e=>fq(e,1)).find(e=>void 0!==e)??r}function fJ(e){var t,r,a;let n,i,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,r=s,a=l,n="string"==typeof t?.ref?t.ref:void 0,i="string"==typeof t?.button?t.button:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:n?i&&"primary"!==i?`Clicked ${i} @${n} (${r}, ${a})`:`Tapped @${n} (${r}, ${a})`:void 0)??("string"==typeof o?.message?o.message:void 0));return{x:s,y:l,...d??{},...u??{},...o??{},...ed(c)}}async function fX(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:n,flags:i,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,afterDispatch:u,buildPayloads:c}=e,p=await fK({session:t,flags:i,contextFromFlags:o,command:s,positionals:l,outPath:d});await u?.(p.data);let{result:f,responseData:m=f}=await c(p.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:n,flags:i,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:n,flags:i??{},result:o}),up(a)&&ud(t,a),fU(t,a,n,o,i??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:n,flags:i,result:f,responseData:m,actionStartedAt:p.actionStartedAt,actionFinishedAt:p.actionFinishedAt})}async function fK(e){let{session:t,flags:r,contextFromFlags:a,command:n,positionals:i,outPath:o}=e,s=Date.now(),l={...a(r,t.appBundleId,t.trace?.outPath)},d=await lZ(t.device,n,i,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function fY(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await iC(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=fT(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=fT(await i(t,r,a,n,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function fZ(e){try{return await fY(e)}catch(t){eu({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function fQ(e){return fT({nodes:e,createdAt:0})}function f0(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`}}}async function f1(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r),d=t.command,u="click"===d?"click":"press";if(!l)return uC("SESSION_NOT_FOUND","No active session. Run open first.");let c=f0(l,u);if(c)return c;if(!dd("press",l.device))return uC("UNSUPPORTED_OPERATION","press is not supported on this device");let p=lb(t.flags),f="primary"===p?{}:{button:p};if("primary"!==p){let e=lA({commandLabel:u,platform:l.device.platform,button:p,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(e)return uC(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return fX({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:n,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,afterDispatch:async()=>{await f2(l,"coordinate tap")},buildPayloads:async e=>{let r=await fZ({session:l,flags:t.flags,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i}),o=fJ({data:e,fallbackX:m.x,fallbackY:m.y,referenceFrame:r,extra:f});return{result:o,responseData:o}}});let h="click",w=t.positionals?.[0]??"";if(w.startsWith("@")){let e=s("press",t.flags);if(e)return e;let r=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",c=await pz({session:l,refInput:w,fallbackLabel:r,commandLabel:u,promoteToHittableAncestor:!0,invalidRefMessage:`${u} requires a ref like @e2`,missingBoundsMessage:`Ref ${w} not found or has no bounds`,invalidBoundsMessage:`Ref ${w} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o});if(!c.ok)return c.response;let{ref:p,node:m,snapshotNodes:g,point:y}=c.target,v=cM(m,g),I=c2(m,l.device.platform,{action:h}),{x:b,y:A}=y;return fX({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"press",interactionPositionals:[String(b),String(A)],outPath:t.flags?.out,afterDispatch:async()=>{await f2(l,`@${p}`)},buildPayloads:e=>{let t=fJ({data:e,fallbackX:b,fallbackY:A,referenceFrame:fQ(g),extra:{ref:p,refLabel:v,selectorChain:I,...f}});return{result:t,responseData:t}}})}let g=(t.positionals??[]).join(" ").trim();if(!g)return{ok:!1,error:{code:"INVALID_ARGS",message:`${u} requires @ref, selector expression, or x y coordinates`}};let y=cU(g),v=await i(l,t.flags,a,n,{interactiveOnly:!0}),I=await es("selector_resolve",()=>cZ(v.nodes,y,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:d});if(!I||!I.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:c0(y,I?.diagnostics??[],{unique:!0})}};let b=pJ(v.nodes,I.node),A=pH(b.rect);if(!A)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${I.selector.raw} resolved to invalid bounds`}};let{x:S,y:_}=A,N=c2(b,l.device.platform,{action:h}),x=cM(b,v.nodes);return fX({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"press",interactionPositionals:[String(S),String(_)],outPath:t.flags?.out,afterDispatch:async()=>{await f2(l,I.selector.raw)},buildPayloads:e=>{let t=fJ({data:e,fallbackX:S,fallbackY:_,referenceFrame:fQ(v.nodes),extra:{selector:I.selector.raw,selectorChain:N,refLabel:x,...f}});return{result:t,responseData:t}}})}async function f2(e,t){if("android"!==e.device.platform||!e.appBundleId)return;let r=await nF(e.device),a=r.package?.trim();if(a&&a!==e.appBundleId){var n;if("com.android.settings"===(n=a)||"com.android.systemui"===n||"com.google.android.permissioncontroller"===n||n.includes("launcher"))throw new H("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${a}. The tap likely escaped the app.`,{expectedPackage:e.appBundleId,foregroundPackage:a,activity:r.activity,hint:"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."})}}async function f3(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r);if(l){let e=f0(l,"fill");if(e)return e}if(l&&!dd("fill",l.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let e=s("fill",t.flags);if(e)return e;let r=t.positionals.length>=3?t.positionals[1]:"",d=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let u=await pz({session:l,refInput:t.positionals[0],fallbackLabel:r,commandLabel:"fill",promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:n,captureSnapshotForSession:i,resolveRefTarget:o});if(!u.ok)return u.response;let{ref:c,node:p,snapshotNodes:f,point:m}=u.target,h=p.type??"",w=h&&!cC(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,g=cM(p,f),y=c2(p,l.device.platform,{action:"fill"}),{x:v,y:I}=m;return fX({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"fill",interactionPositionals:[String(v),String(I),d],outPath:t.flags?.out,buildPayloads:e=>{let t=fJ({data:e,fallbackX:v,fallbackY:I,referenceFrame:fQ(f),extra:{ref:c,refLabel:g,selectorChain:y,text:d}}),r={...e??{ref:c,x:v,y:I}};return w&&(t.warning=w,r.warning=w),{result:t,responseData:r}}})}if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let d=cV(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let e=d.rest.join(" ").trim();if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=cU(d.selectorExpression),o=await i(l,t.flags,a,n,{interactiveOnly:!0}),s=await es("selector_resolve",()=>cZ(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:c0(r,s?.diagnostics??[],{unique:!0})}};let u=s.node,c=s.node.rect,p=u.type??"",f=p&&!cC(p,l.device.platform)?`fill target ${s.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=eA(c),w=c2(u,l.device.platform,{action:"fill"});return fX({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:n,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=fJ({data:t,fallbackX:m,fallbackY:h,referenceFrame:fQ(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:w,refLabel:cM(u,o.nodes)}});return f&&(r.warning=f),{result:r,responseData:r}}})}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}async function f4(e){switch(e.req.command){case"press":case"click":return await f1(e);case"fill":return await f3(e);default:return null}}let f5=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function f8(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of f5)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}async function f6(e,t,r,a,n){let i={...t??{},snapshotInteractiveOnly:n.interactiveOnly,snapshotCompact:n.interactiveOnly},o=a(i,e.appBundleId,e.trace?.outPath),{snapshot:s}=await pm({device:e.device,session:e,flags:i,outPath:i.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function f9(e){let{command:t,selectorExpression:r,session:a,flags:n,sessionStore:i,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=cU(r),p=await f6(a,n,i,o,{interactiveOnly:s}),f=await es("selector_resolve",()=>cZ(p.nodes,c,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return f&&(!l||f.node.rect)?{ok:!0,chain:c,snapshot:p,resolved:f}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:c0(c,f?.diagnostics??[],{unique:d})}}}}async function f7(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n}=e,i=t.positionals?.[0];if("text"!==i&&"attrs"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!dd("get",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=f8("get",t.flags);if(e)return e;let r=pq({session:o,refInput:s,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${s} not found`});if(!r.ok)return r.response;let{ref:l,node:d}=r.target,u=c2(d,o.device.platform,{action:"get"});if("attrs"===i)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,selectorChain:u}}),{ok:!0,data:{ref:l,node:d}};let c=await pK({device:o.device,node:d,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:n});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:me(c),selectorChain:u}}),{ok:!0,data:{ref:l,text:c,node:d}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"get requires @ref or selector expression"}};let d=await f9({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:a,contextFromFlags:n,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===i});if(!d.ok)return d.response;let{resolved:u}=d,c=u.node,p=c2(c,o.device.platform,{action:"get"});if("attrs"===i)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:u.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:u.selector.raw,node:c}};let f=await pK({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:n});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:f,refLabel:me(f),selector:u.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:u.selector.raw,text:f,node:c}}}function me(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function mt(e){return!!(e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.width)&&Number.isFinite(e.height)&&e.width>0&&e.height>0)}async function mr(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:n}=e,i=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!dd("is",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:s}=cB(t.positionals);if(!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires a selector expression"}};let l=s.rest.join(" ").trim();if("text"===i&&!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==i&&s.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${i} does not accept trailing values`}};let d=cU(s.selectorExpression);if("exists"===i){let e=cQ((await f6(o,t.flags,a,n,{interactiveOnly:!1})).nodes,d,{platform:o.device.platform});return e?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:i,selector:e.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:i,pass:!0,selector:e.selector.raw,matches:e.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:c0(d,[],{unique:!1})}}}let u=await f9({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:n,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!u.ok)return u.response;let{resolved:c}=u,p=function(e){let{predicate:t,node:r,nodes:a,expectedText:n,platform:i}=e,o=cR(r),s=cX(r,i),l=!0===r.selected,d="text"===t?cJ(r):function(e,t){if(!0===e.hittable)return!0;if(mt(e.rect))return k(e,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),a=e,n=new Set;for(;"number"==typeof a.parentIndex&&!n.has(a.index);){n.add(a.index);let e=r.get(a.parentIndex);if(!e)break;if(function(e){let t=cL(e.type??"");return!(t.includes("application")||t.includes("window")||t.includes("scrollview")||t.includes("tableview")||t.includes("collectionview"))&&"table"!==t&&"list"!==t&&"listview"!==t&&(!0===e.hittable||mt(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!mt(r.rect)&&k(r,t))}(r,a),u=!1;switch(t){case"visible":u=d;break;case"hidden":u=!d;break;case"editable":u=s;break;case"selected":u=l;break;case"text":u=o===(n??"")}let c="text"===t?`expected="${n??""}" actual="${o}"`:`actual=${JSON.stringify({visible:d,editable:s,selected:l})}`;return{pass:u,actualText:o,details:c}}({predicate:i,node:c.node,nodes:u.snapshot.nodes,expectedText:l,platform:o.device.platform});return p.pass?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:i,selector:c.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,text:"text"===i?p.actualText:void 0}}),{ok:!0,data:{predicate:i,pass:!0,selector:c.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${i} failed for selector ${c.selector.raw}: ${p.details}`}}}function ma(e,t){var r,a;let n=Math.max(1,t.height),i=Math.max(1,t.width),o=t.y,s=t.y+n,l=t.x,d=t.x+i,u=s-.25*n,c=Math.max(8,.1*i),p=e.y+e.height/2,f=e.x+e.width/2;if(p>=o+.25*n&&p<=u)return null;let m=Math.round((r=f,a=l+c,Math.min(d-c,Math.max(a,r)))),h=Math.round(o+.86*n),w=Math.round(o+.14*n);return p>u?{x:m,startY:h,endY:w,direction:"down"}:{x:m,startY:w,endY:h,direction:"up"}}async function mn(e){let t,r,{req:a,sessionName:n,sessionStore:i,contextFromFlags:o}=e,s=i.get(n);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!dd("scrollintoview",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let l=a.positionals?.[0]??"";if(!l.startsWith("@"))return null;let d=f8("scrollintoview",a.flags);if(d)return d;let u=a.positionals&&a.positionals.length>1?a.positionals.slice(1).join(" ").trim():"",c=function(e,t,r){let a=pq({session:e,refInput:t,fallbackLabel:r,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${t} not found or has no bounds`});if(!a.ok){let{response:e}=a;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:mo(t,0,{message:e.error.message})}}return mi(t,0,a.target)}(s,l,u);if(!c.ok)return c.response;let{ref:p}=c.state,{currentRef:f,node:m,snapshotNodes:h,viewportRect:w}=c.state,g=cM(m,h),y=c2(m,s.device.platform,{action:"get"}),v=u||g||m.label||"";if(!ma(m.rect,w)){let e=ms({ref:p,currentRef:f,attempts:0,alreadyVisible:!0});return i.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{refLabel:g,selectorChain:y,...e}}),{ok:!0,data:e}}let I=a.flags?.maxScrolls??48,b=0,A=0,S=V(m.rect,w);for(;b<I;){let e=ma(m.rect,w);if(!e)break;t=e.direction,r=await lZ(s.device,"swipe",[String(e.x),String(e.startY),String(e.x),String(e.endY),"16"],a.flags?.out,{...o(a.flags,s.appBundleId,s.trace?.outPath),count:1,pauseMs:0,pattern:"one-way"}),b+=1,await f6(s,a.flags,i,o,{interactiveOnly:!0});let n=function(e){let{session:t,targetInput:r,fallbackLabel:a,attempts:n,ref:i,selectorChain:o,platform:s}=e;if(t.snapshot){let e=function(e,t,r,a){for(let r of t){let t=cZ(e,cU(r),{platform:a,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?ck(e,r):null}(t.snapshot.nodes,o,a,s);if(e)return mi(r,n,{ref:i,node:e,snapshotNodes:t.snapshot.nodes},{currentRef:e.ref})}let l=pq({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${r} not found or has no bounds`});if(!l.ok){let{response:e}=l;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:mo(r,n,{message:`scrollintoview lost track of ${r} after ${n} scroll${1===n?"":"s"}`,ref:i})}}return mi(r,n,l.target,{ref:i,currentRef:l.target.node.ref,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${n} scroll${1===n?"":"s"}`})}({session:s,targetInput:l,fallbackLabel:v,attempts:b,ref:p,selectorChain:y,platform:s.device.platform});if(!n.ok)return n.response;({currentRef:f,node:m,snapshotNodes:h,viewportRect:w}=n.state);let d=V(m.rect,w);if(0===d)break;if(d>=S){if((A+=1)>=2)return mo(l,b,{message:`scrollintoview made no progress toward ${l} after ${b} scroll${1===b?"":"s"}`,ref:p,stalled:!0})}else A=0;S=d}if(V(m.rect,w)>0)return mo(l,b,{message:`scrollintoview reached --max-scrolls=${I} before ${l} entered view`,ref:p,maxScrolls:I});let _=ms({data:r,ref:p,currentRef:f,attempts:b,direction:t});return i.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{refLabel:g,selectorChain:y,..._}}),{ok:!0,data:_}}function mi(e,t,r,a={}){let{ref:n,currentRef:i,missingBoundsMessage:o}=a,s=r.node;if(!s.rect)return{ok:!1,response:mo(e,t,{message:o??`Ref ${e} not found or has no bounds`,ref:n??r.ref})};let l=Z(r.snapshotNodes,s.rect);return l?{ok:!0,state:{ref:n??r.ref,currentRef:i??r.node.ref,node:s,snapshotNodes:r.snapshotNodes,viewportRect:l}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${e}`}}}}function mo(e,t,r={}){let{message:a,...n}=r;return{ok:!1,error:{code:"COMMAND_FAILED",message:"string"==typeof a?a:`scrollintoview could not find ${e}`,details:{reason:"not_found",attempts:t,...n}}}}function ms(e){let{data:t,ref:r,currentRef:a,attempts:n,alreadyVisible:i,direction:o}=e;return{...t??{},ref:r,currentRef:a,attempts:n,...i?{alreadyVisible:i}:{},...o?{direction:o}:{},...ed(`Scrolled into view: @${r}`)}}async function ml(e){let t=await f4({...e,captureSnapshotForSession:f6,resolveRefTarget:pq,refSnapshotFlagGuardResponse:f8});if(t)return t;switch(e.req.command){case"get":return await f7(e);case"is":return await mr(e);case"scrollintoview":return await mn(e);default:return null}}function md(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 mu(e){let{req:t,leaseRegistry:r}=e,a=md(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:a.tenantId??"",runId:a.runId??"",backend:a.leaseBackend,ttlMs:a.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId,ttlMs:a.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId})};default:return null}}function mc(e,t){if(!t)return[];let r=[],a=e.device,n=t.platform;if(n&&!t_(a.platform,n)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),n=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==n)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=e6(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function mp(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let mf=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],mm=/\bis(?:n't| not)\s+responding\b/i,mh=/^close app$/i;async function mw(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await mg(t),r=function(e){if(mb(e))return e.find(e=>{let t=mI(e);return t.length>0&&mh.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:n}=eA(r.rect),i=await T("adb",aU(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(n))]),{allowFailure:!0});if(0!==i.exitCode)return eu({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:i.exitCode,stdout:i.stdout.trim(),stderr:i.stderr.trim()}}),"failed";if(!await my(t))return eu({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await nG(t.device,t.appBundleId),!await mv(t,t.appBundleId)))return eu({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return eu({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:a,y:n}}),"recovered"}catch(e){return eu({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function mg(e){return e_(cO((await iu(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function my(e){for(let t=0;t<12;t+=1){if(!mb(await mg(e)))return!0;await mA(500)}return!mb(await mg(e))}async function mv(e,t){for(let r=0;r<12;r+=1){if((await nF(e.device)).package===t)return!0;await mA(500)}return(await nF(e.device)).package===t}function mI(e){let t=[e.label,e.identifier];return"string"==typeof e.value&&e.value.trim().length>0&&t.push(e.value),t.filter(e=>"string"==typeof e&&e.trim().length>0).join(" ").trim()}function mb(e){return e.some(e=>{let t=mI(e);return t.length>0&&mm.test(t)})}function mA(e){return new Promise(t=>setTimeout(t,e))}let mS=[255,59,48,255],m_=[255,214,10,255],mN=[0,0,0,255],mx={e:["01110","10000","11110","10000","10000","10001","01110"],0:["01110","10001","10011","10101","11001","10001","01110"],1:["00100","01100","00100","00100","00100","00100","01110"],2:["01110","10001","00001","00010","00100","01000","11111"],3:["11110","00001","00001","01110","00001","00001","11110"],4:["00010","00110","01010","10010","11111","00010","00010"],5:["11111","10000","10000","11110","00001","00001","11110"],6:["01110","10000","10000","11110","10001","10001","01110"],7:["11111","00001","00010","00100","01000","01000","01000"],8:["01110","10001","10001","01110","10001","10001","01110"],9:["01110","10001","10001","01111","00001","00001","01110"]};async function mD(e){let t=x(await d.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let n=function(e){let t=null;for(let r of e)mM(r)&&mP(r.rect)&&(!t||mR(r.rect)>mR(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,a=-1/0,n=-1/0;for(let i of e)i.rect&&mP(i.rect)&&(t=Math.min(t,i.rect.x),r=Math.min(r,i.rect.y),a=Math.max(a,i.rect.x+i.rect.width),n=Math.max(n,i.rect.y+i.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||a<=t||n<=r?null:{x:t,y:r,width:a-t,height:n-r}}(e.filter(e=>{var t;return mP(e.rect)&&!("image"===cL((t=e).type??"")&&!mE(t.label))}))}(e.nodes),i=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(mO)||mL(e.identifier);return mk(e)?t:t&&function(e){let t=cL(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(a))continue;let o=function(e,t){if(function(e){return mk(e)&&!mM(e)}(t)&&mP(t.rect))return t;let r=function(e,t){let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){;a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(mk(t)&&!mM(t)&&mP(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&mP(r.rect))return r;if(t.hittable&&mP(t.rect)&&!mM(t))return t;let a=cP(e,t);return a?.rect&&mP(a.rect)&&!mM(a)?a:null}(e.nodes,a);if(!o?.rect||!mP(o.rect))continue;let s=function(e,t,r){let a=mC(e);if(e.ref!==t.ref&&a)return a;let n=function(e,t){let r=null;for(let a of t){if(a.ref===e.ref||!function(e,t,r){let a=e;for(;void 0!==a.parentIndex;){let e=r[a.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;a=e}return!1}(a,e,t))continue;let n=mC(a);if(!n)continue;let i=function(e){let t=0;return cL(e.type??"").includes("text")&&(t+=2),mO(e.label)&&(t+=2),mO(e.value)&&(t+=1),t}(a);(!r||i>r.score)&&(r={label:n,score:i})}return r?.label}(t,r);return n||(mC(t)??cM(t,r))}(a,o,e.nodes),l=function(e,t,r){let a=0;return e.ref===t.ref&&(a+=4),t.hittable&&(a+=3),mk(t)&&(a+=3),mk(e)&&(a+=2),r&&(a+=2),mL(t.identifier)&&(a+=1),mE(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return mF({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,a);let n=r/e.width,i=a/e.height;return mF({x:Math.round((t.x-e.x)*n),y:Math.round((t.y-e.y)*i),width:Math.max(1,Math.round(t.width*n)),height:Math.max(1,Math.round(t.height*i))},r,a)}(n,o.rect,t,r);if(!mP(d))continue;let u=i.get(o.ref);(!u||l>u.score)&&i.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:d,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>mR(e.overlayRect)-mR(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(mT(e.overlayRect,r.overlayRect)||mT(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}mR(r.overlayRect)<mR(t[e].overlayRect)&&(t[e]=r)}return t})([...i.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:m$(e.ref,t.ref)}).slice(0,a.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:m$(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:eA(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,n;(function(e,t,r){for(let a=0;a<2;a+=1)mG(e,t.x,t.x+t.width-1,t.y+a,r),mG(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),mV(e,t.x+a,t.y,t.y+t.height-1,r),mV(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(n=e).overlayRect,mS),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),n=mU(t.x,0,Math.max(0,e.width-a)),i=t.y-11-2,o=i>=0?i:mU(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,n){for(let i=0;i<11;i+=1)for(let o=0;o<a;o+=1)mB(e,t+o,r+i,n)})(e,n,o,a,m_),function(e,t,r,a,n){let i=t;for(let t of a.toLowerCase()){let a=mx[t];if(a)for(let t=0;t<a.length;t+=1)for(let o=0;o<a[t].length;o+=1)"1"===a[t][o]&&mB(e,i+o,r+t,n);i+=6}}(e,n+3,o+2,r,mN)}(a,n.overlayRect,n.ref)}return await d.writeFile(e.screenshotPath,_.sync.write(t)),r}function mk(e){let t=[e.type,e.role,e.subrole].map(e=>cL(e??"")).join(" ");return t.includes("button")||t.includes("link")||t.includes("menu")||t.includes("tab")||t.includes("textfield")||t.includes("searchfield")||t.includes("securetextfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")||t.includes("cell")}function mM(e){let t=[e.type,e.role,e.subrole].map(e=>cL(e??"")).join(" ");return t.includes("application")||t.includes("window")}function mE(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function mO(e){var t;let r;return!!mE(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function mL(e){var t;return"string"==typeof e&&!!mO(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function mC(e){let t=[e.label,e.value].find(mO);return t?t.trim():mL(e.identifier)?e.identifier.trim():void 0}function mP(e){return!!(e&&e.width>0&&e.height>0)}function mR(e){return e.width*e.height}function mT(e,t){return t.x>=e.x&&t.y>=e.y&&t.x+t.width<=e.x+e.width&&t.y+t.height<=e.y+e.height}function m$(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function mF(e,t,r){let a=mU(e.x,0,Math.max(0,t-1)),n=mU(e.y,0,Math.max(0,r-1)),i=Math.max(1,t-a),o=Math.max(1,r-n);return{x:a,y:n,width:mU(e.width,1,i),height:mU(e.height,1,o)}}function mU(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function mG(e,t,r,a,n){for(let i=t;i<=r;i+=1)mB(e,i,a,n)}function mV(e,t,r,a,n){for(let i=r;i<=a;i+=1)mB(e,t,i,n)}function mB(e,t,r,a){if(t<0||r<0||t>=e.width||r>=e.height)return;let n=(e.width*r+t)*4;e.data[n]=a[0],e.data[n+1]=a[1],e.data[n+2]=a[2],e.data[n+3]=a[3]}let mj=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),mq=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),mH=new Set(mq),mW=new Map;function mz(e,t,r,a){let n=ei().requestId;return{...du(e,t,r,a,n),requestId:n}}async function mJ(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||dM(e.flags))try{let t=await lY(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function mX(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,leaseRegistry:i,invoke:o,contextFromFlags:s}=e,l=await mu({req:t,leaseRegistry:i});if(l)return l;let d=await pu({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:o});if(d)return d;let u=await pF({req:t,sessionName:r,logPath:a,sessionStore:n});if(u)return u;let c=await fC({req:t,sessionName:r,sessionStore:n,logPath:a});if(c)return c;let p=await pY({req:t,sessionName:r,logPath:a,sessionStore:n,invoke:o});if(p)return p;let f=await ml({req:t,sessionName:r,sessionStore:n,contextFromFlags:s});return f||null}async function mK(e){var t;let r,a,n,i,o,s,l,{req:d,session:u,logPath:c,sessionStore:p}=e,f=d.command;if(!dd(f,u.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${f} is not supported on this device`}};if("android"===u.device.platform&&u.recording&&"record"!==f&&"failed"===await mw({session:u}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:m,resolvedOut:h,recordedPositionals:w,recordedFlags:g}=(r=(t=d).command,a=t.positionals??[],n=t.flags?.out,i="screenshot"===r&&a[0]?[rx.expandHome(a[0],t.meta?.cwd),...a.slice(1)]:a,o="screenshot"===r&&n?rx.expandHome(n,t.meta?.cwd):n,s="screenshot"===r?i:a,l="screenshot"===r&&o?{...t.flags??{},out:o}:t.flags??{},{resolvedPositionals:i,resolvedOut:o,recordedPositionals:s,recordedFlags:l}),y=Date.now(),v={...mz(c,d.flags,u.appBundleId,u.trace?.outPath),surface:u.surface},I=await lZ(u.device,f,m,h,{...v});return"screenshot"===f&&d.flags?.overlayRefs&&"string"==typeof I?.path&&await mY(u,I,c),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:n,recordedPositionals:i,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:d,flags:u}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let n=fT(e.snapshot),i={...a??{}},o=fB(i.direction)??fB(r[0]);if(!o)return a;let s=fj(i.amount)??fj(r[1]),l=fj(i.pixels),d=fW(i,[]),u=fj(i.referenceWidth),c=fj(i.referenceHeight),p=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:n??fF;if(d&&(d.x1!==d.x2||d.y1!==d.y2))return{...i,x1:d.x1,y1:d.y1,x2:d.x2,y2:d.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250};let f=n8({direction:o,amount:s,pixels:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return{...i,x1:f.x1,y1:f.y1,x2:f.x2,y2:f.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==f.pixels?{pixels:f.pixels}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250}}(t,a,n,s);fU(t,a,n,c,u,l,d),r.recordAction(t,{command:a,positionals:i,flags:o,result:s??{}})}({session:u,sessionStore:p,command:f,resolvedPositionals:m,recordedPositionals:w,recordedFlags:g,data:I,actionStartedAt:y,actionFinishedAt:Date.now(),flags:d.flags??{}}),up(f)&&ud(u,f),{ok:!0,data:I??{}}}async function mY(e,t,r){let a=pv(await ph({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=a;let n=await mD({screenshotPath:t.path,snapshot:a});t.overlayRefs=n}function mZ(e){s.existsSync(e)&&s.unlinkSync(e)}function mQ(e){if(!s.existsSync(e))return null;try{let t=JSON.parse(s.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function m0(e){let t=mQ(e);if(!t||t.pid===process.pid)try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}function m1(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:m2,infoPath:m3,lockPath:m4,logPath:m5,sessionsDir:m8}=ev(process.env.AGENT_DEVICE_STATE_DIR),m6=eb(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var m9=m8;if(s.existsSync(m9))for(let e of s.readdirSync(m9,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=p.join(m9,e.name,"app-log.pid");if(s.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}}(s.readFileSync(t,"utf8"));if(e&&function(e){let t,r=eg(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=D(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{rk(t)}}let m7=new rx(m8),he=new aC({maxActiveSimulatorLeases:m1(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:m1(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:m1(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:m1(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),ht=en(),hr=i.randomBytes(24).toString("hex"),ha=eg(process.pid)??void 0,hn=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=s.statSync(e),r=eh(),a=p.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),hi=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:n,trackDownloadableArtifact:i}=e;async function o(e){let s=!!(e.meta?.debug||e.flags?.verbose);return await ey({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:s,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:et(new H("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=er(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=E(r);if(r&&!a)throw new H("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new H("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let n=e.session||"default";return n.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${n}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);eu({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let s=r.command,l=md(r);mq.has(s)||r.meta?.sessionIsolation!=="tenant"||n.assertLeaseAdmission({tenantId:l.tenantId,runId:l.runId,leaseId:l.leaseId,backend:l.leaseBackend});let d=function(e,t){var r;let a,n=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==n||t.has(n))return n;let i=t.toArray();return 1===i.length?i[0].name:n}(r,a),u=mH.has(s)?null:await mJ(r,d,a),c=async()=>{let e=a.get(d);e&&(!function(e){var t,r;let a,n=e.recording;if(!n||"ios"!==e.device.platform)return;let i=(t=e.device.id,(a=t4.get(t))?{sessionId:a.sessionId,alive:!!(r=a.child.pid)&&ew(r)}:null);if(!n.runnerSessionId){i?.alive&&(n.runnerSessionId=i.sessionId);return}if(!i?.alive){n.invalidatedReason??="iOS runner session exited during recording";return}i.sessionId!==n.runnerSessionId&&(n.invalidatedReason??="iOS runner session restarted during recording")}(e),a.set(d,e));let l=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},n=t?mc(t,a):function(e,t,r){var a,n;let i=[];if(void 0!==e.platform&&t&&(a=e.platform,n=t,a&&n&&a!==n&&("apple"===a?!tS(n):"apple"!==n||!tS(a)))&&i.push({key:"platform",value:e.platform}),"open"===r)return i;for(let t of mf){let r=e[t];"string"==typeof r&&r.trim().length>0&&i.push({key:t,value:r})}return i}(a,e.meta?.lockPlatform,e.command);if(0===n.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,n),a.platform=t.device.platform):function(e,t){for(let t of mf)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new H("INVALID_ARGS",`${e.command} cannot override session lock policy with ${n.map(mp).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),u=e=>(function(e,t,r){let a=ei();if(!t.ok){eu({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=eI({force:!0})??void 0;return{ok:!1,error:et(new H(t.error.code,t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:a.diagnosticId,logPath:e})}}return eu({level:"info",phase:"request_success"}),eI(),{ok:!0,data:function(e,t,r){var a,n;let i;if(!t)return t;let o=(a=e,n=t,i=Array.isArray(n.artifacts)?[...n.artifacts]:[],"screenshot"!==a.command||i.some(e=>e?.field==="path")||"string"!=typeof n.path||i.push({field:"path",path:n.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:p.basename(a.meta?.clientArtifactPaths?.path??n.path)}),i.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===o.length?t:{...t,artifacts:o.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(l,e,i);if(e?.recording?.invalidatedReason&&"record"!==s&&"close"!==s)return u({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||l.meta?.lockPolicy||mj.has(s)||function(e,t){let r=mc(e,t);if(0!==r.length){var a;let t,n,i;throw new H("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,n=a.device.name.trim(),i=a.device.id,`${t} device "${n}" (${i})`)} and cannot be used with ${r.map(mp).join(", ")}. Use a different --session name or close this session first.`)}}(e,l.flags);let c=await mX({req:l,sessionName:d,logPath:t,sessionStore:a,leaseRegistry:n,invoke:o,contextFromFlags:(e,r,n)=>({...mz(t,e,r,n),surface:a.get(d)?.surface})});if(c)return u(c);let f=a.get(d);if(!f)return u({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await mK({req:l,session:f,sessionName:d,logPath:t,sessionStore:a});return u(m)};if(!u)return await c();return await tA(mW,u,c)}catch(r){eu({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=ei(),t=eI({force:!0})??void 0;return{ok:!1,error:et(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return o}({logPath:m5,token:hr,sessionStore:m7,leaseRegistry:he,trackDownloadableArtifact:function(e){let t=i.randomUUID(),r=setTimeout(()=>{aa(t)},9e5);return r.unref(),ar.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){s.existsSync(e)||s.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),n=()=>{try{return s.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(n())return!0;let i=mQ(t);if(i?.pid&&i.pid!==process.pid&&O(i.pid,i.processStartTime))return!1;try{s.unlinkSync(t)}catch{}return n()}(m2,m4,{pid:process.pid,version:ht,startedAt:Date.now(),processStartTime:ha})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let n;if("socket"===m6||"dual"===m6){let t=f.createServer(e=>{let t="",r=0,a=new Set,n=!1,i=()=>{if(!n&&0!==r){for(let e of(n=!0,a))ez(e);eu({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await rt(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){eu({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",i),e.on("error",i),e.on("data",async n=>{let i=(t+=n).indexOf("\n");for(;-1!==i;){let n,o,s=t.slice(0,i).trim();if(t=t.slice(i+1),0===s.length){i=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=eH(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),eW(o),eX(o))throw eY();n=await hi(e)}catch(e){n={ok:!1,error:et(e)}}finally{r-=1,o&&(a.delete(o),eJ(o))}e.destroyed||e.write(`${JSON.stringify(n)}
|
|
69
|
+
`),i=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new H("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===m6||"dual"===m6){let e=await ax({handleRequest:hi,token:hr});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let a=e.address();"object"==typeof a&&a?.port?t(a.port):r(new H("COMMAND_FAILED","Failed to bind HTTP server"))})})}a={socketPort:e,httpPort:t,token:hr,version:ht,codeSignature:hn,processStartTime:ha},s.existsSync(m2)||s.mkdirSync(m2,{recursive:!0}),s.writeFileSync(m5,""),n=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",s.writeFileSync(m3,JSON.stringify({port:a.socketPort,httpPort:a.httpPort,transport:n,token:a.token,pid:process.pid,version:a.version,codeSignature:a.codeSignature,processStartTime:a.processStartTime,stateDir:m2},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
|
|
70
70
|
`),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
|
|
71
|
-
`)}catch(t){let e=
|
|
72
|
-
`),r))try{t.close(()=>{})}catch{}
|
|
73
|
-
`),o()}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof
|
|
71
|
+
`)}catch(t){let e=B(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
|
|
72
|
+
`),r))try{t.close(()=>{})}catch{}mZ(m3),m0(m4),process.exit(1);return}let n=!1,i=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 i(),m7.toArray()))m7.writeSessionLog(e);await rr(),mZ(m3),m0(m4),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof H?e:B(e);process.stderr.write(`Daemon error: ${t.message}
|
|
73
|
+
`),o()}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof H?t:B(t);process.stderr.write(`Daemon error: ${r.message}
|
|
74
74
|
`),o()})}();
|