agent-device 0.10.3 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/src/306.js +3 -0
- package/dist/src/bin.js +78 -62
- package/dist/src/daemon.js +40 -39
- package/dist/src/index.d.ts +24 -0
- package/dist/src/index.js +2 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +84 -16
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +140 -50
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +13 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +22 -9
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +221 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +19 -7
- package/ios-runner/README.md +17 -2
- package/ios-runner/RUNNER_PROTOCOL.md +73 -0
- package/package.json +13 -9
- package/skills/agent-device/SKILL.md +3 -0
- package/skills/agent-device/references/exploration.md +29 -1
- package/skills/agent-device/references/verification.md +8 -1
- package/dist/src/376.js +0 -3
package/dist/src/daemon.js
CHANGED
|
@@ -1,41 +1,42 @@
|
|
|
1
|
-
let e,t,r,a;import i from"node:dns/promises";import n from"node:fs/promises";import{
|
|
2
|
-
`)}let
|
|
1
|
+
let e,t,r,a;import i from"node:dns/promises";import n from"node:fs/promises";import{setTimeout as o}from"node:timers/promises";import{resolveInstallFromSourceResultTarget as s,node_path as l,readProcessCommand as d,parseSessionSurface as u,formatSnapshotLine as c,normalizeTenantId as p,existsSync as f,runCmdDetached as m,runCmdBackground as h,isAgentDeviceDaemonProcess as w,node_crypto as g,runCmd as v,validateAndNormalizeBatchSteps as y,resolveDeployResultTarget as I,displayLabel as A,SETTINGS_INVALID_ARGS_MESSAGE as b,PNG as S,spawn as _,asAppError as N,expandUserHomePath as D,pathToFileURL as x,AppError as k,withSuccessText as M,extractReadableText as E,decodePng as O,external_node_url_URL as L,whichCmd as C,buildSnapshotDisplayLines as P,fileURLToPath as R,runCmdStreaming as T,createHash as $,formatRole as F,normalizeError as U,resolveSessionIsolationMode as V,resolveUserPath as G,readVersion as j,getDiagnosticsMeta as B,runCmdSync as q,withDiagnosticTimer as H,TextDecoder as W,successText as z,emitDiagnostic as J,findProjectRoot as K,promises as X,DEFAULT_BATCH_MAX_STEPS as Y,isProcessAlive as Z,readProcessStartTime as Q,withDiagnosticsScope as ee,node_fs as et,flushDiagnosticsToSessionFile as er,node_os as ea,node_net as ei,resolveDaemonServerMode as en,resolveDaemonPaths as eo,node_http as es}from"./306.js";let el=ed(process.env.AGENT_DEVICE_RETRY_LOGS);function ed(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let eu=2e4,ec=12e4,ep=1e4;class ef{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new ef(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 em(e,t={},r={}){let a,i={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=i.maxAttempts;t+=1){if(r.signal?.aborted)throw new k("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(r.deadline?.isExpired()&&t>1)break;try{let a=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),ew({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),a}catch(d){a=d;let e=r.classifyReason?.(d),n={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(n),ew(n),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(d,t))break;let o=function(e,t,r,a){let i=Math.min(t,e*2**(a-1));return Math.max(0,i+i*r*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),s=r.deadline?Math.min(o,r.deadline.remainingMs()):o;if(s<=0)break;let l={phase:r.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),ew(l),await function(e,t){return new Promise(r=>{let a;if(t?.aborted)return void r();let i=!1,n=()=>{i||(i=!0,t&&a&&t.removeEventListener("abort",a),r())},o=setTimeout(n,e);a=()=>{clearTimeout(o),n()},t&&t.addEventListener("abort",a,{once:!0})})}(s,r.signal)}}let n={phase:r.phase,event:"exhausted",attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(a)};if(r.onEvent?.(n),ew(n),a)throw a;throw new k("COMMAND_FAILED","retry failed")}async function eh(e,t={}){return em(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function ew(e){J({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 eg=new Set,ev=new Map,ey="request_canceled",eI="request canceled";function eA(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 eb(e){if(!e)return;let t=new AbortController;ev.set(e,t),eg.has(e)&&t.abort()}function eS(e){e&&(eg.add(e),ev.get(e)?.abort())}function e_(e){e&&(eg.delete(e),ev.delete(e))}function eN(e){return!!e&&eg.has(e)}function eD(e){if(e)return ev.get(e)?.signal}function ex(){return new k("COMMAND_FAILED",eI,{reason:ey})}function ek(e){return e instanceof k&&"COMMAND_FAILED"===e.code&&(e.details?.reason===ey||e.message===eI)}function eM(e){let t=e.error?N(e.error):null,r=e.context?.platform,a=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===r?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let i=t?.details??{},n="string"==typeof i.message?i.message:void 0,o="string"==typeof i.stdout?i.stdout:void 0,s="string"==typeof i.stderr?i.stderr:void 0,l=i.boot&&"object"==typeof i.boot?i.boot:null,d=i.bootstatus&&"object"==typeof i.bootstatus?i.bootstatus:null,u=[e.message,t?.message,e.stdout,e.stderr,n,o,s,"string"==typeof l?.stdout?l.stdout:void 0,"string"==typeof l?.stderr?l.stderr:void 0,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===r&&(u.includes("runner did not accept connection")||"connect"===a&&(u.includes("timed out")||u.includes("timeout")||u.includes("econnrefused")||u.includes("connection refused")||u.includes("fetch failed")||u.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":u.includes("resource temporarily unavailable")||u.includes("killed: 9")||u.includes("cannot allocate memory")||u.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===r&&(u.includes("device not found")||u.includes("no devices")||u.includes("device offline")||u.includes("offline")||u.includes("unauthorized")||u.includes("not authorized")||u.includes("unable to locate device")||u.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||u.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function eE(e){switch(e){case"IOS_BOOT_TIMEOUT":return"Retry simulator boot and inspect simctl bootstatus logs; in CI consider increasing AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS.";case"IOS_RUNNER_CONNECT_TIMEOUT":return"Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.";case"ANDROID_BOOT_TIMEOUT":return"Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.";case"ADB_TRANSPORT_UNAVAILABLE":return"Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.";case"CI_RESOURCE_STARVATION_SUSPECTED":return"CI machine may be resource constrained; reduce parallel jobs or use a larger runner.";case"IOS_TOOL_MISSING":return"Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.";case"BOOT_COMMAND_FAILED":return"Inspect command stderr/stdout for the failing boot phase and retry after environment validation.";default:return"Retry once and inspect verbose logs for the failing phase."}}function eO(e){return!(e instanceof k)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function eL(e){let{port:t,endpoints:r,logPath:a,lastError:i}=e,n="Runner did not accept connection";return new k("COMMAND_FAILED",n,{port:t,endpoints:r,logPath:a,lastError:i?String(i):void 0,reason:eM({error:i,message:n,context:{platform:"ios",phase:"connect"}}),hint:eE("IOS_RUNNER_CONNECT_TIMEOUT")})}async function eC(e){var t,r;let a,{session:i,port:n,logPath:o}=e,s=await i.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=eM({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new k("COMMAND_FAILED",l,{port:n,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(a=`${l}
|
|
3
3
|
${t}
|
|
4
|
-
${r}`.toLowerCase()).includes("device is busy")&&a.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":
|
|
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 _("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 e8=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function e5(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new _("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(!J.existsSync(e))throw new _("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==F("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await w("codesign",["--remove-signature",e],{allowFailure:!0});try{await w("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof _?a:new _("COMMAND_FAILED",String(a));throw new _("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 e6=s.join(K.homedir(),".agent-device","ios-runner"),e9=new Map,e7=new Set;function te(e){return e?.trim()??""}function tt(e=process.env){return te(e.AGENT_DEVICE_IOS_BUNDLE_ID)||te(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tr(e=process.env){let t=te(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tt(e)}.uitests`}let ta=function(e=process.env){let t=tt(e),r=tr(e);return Array.from(new Set([te(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env),ti={findProjectRoot:function(){let e=s.dirname(M(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=s.join(t,"package.json");if(J.existsSync(e))return t;t=s.dirname(t)}return e},findXctestrun:function(e,t){if(!J.existsSync(e))return null;let r=[],a=[e];for(;a.length>0;){let e=a.pop();for(let t of J.readdirSync(e,{withFileTypes:!0})){let i=s.join(e,t.name);if(t.isDirectory()){a.push(i);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=J.statSync(i);r.push({path:i,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let a=ts(r.path,t)-ts(e.path,t);if(0!==a)return a}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)},xctestrunReferencesProjectRoot:function(e,t){try{let r=J.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(J.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}},resolveExistingXctestrunProductPaths:function(e){let t=function(e){let t=function(e){try{let t=F("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())return null;return JSON.parse(t.stdout)}catch{return null}}(e);if(t){var r,a=t;let e=new Set,i=t=>{if(t&&"object"==typeof t)for(let r of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),r=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){r.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};i(a);let n=a.TestConfigurations;if(Array.isArray(n))for(let e of n){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)i(e)}for(let e of Object.values(a))e&&"object"==typeof e&&"TestBundlePath"in e&&i(e);return Array.from(e)}if("darwin"===process.platform)return null;try{return r=J.readFileSync(e,"utf8"),Array.from(new Set([...["ProductPaths","DependentProductPaths"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<array>([\\s\\S]*?)</array>`,"g"),i=/<string>([\s\S]*?)<\/string>/g,n=new Set;for(;null!==(r=a.exec(e));){let e,t=r[1]??"";for(;null!==(e=i.exec(t));){let t=e[1]?.trim();t&&n.add(t)}}return Array.from(n)})(r,e)),...["TestHostPath","TestBundlePath","UITargetAppPath"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<string>([\\s\\S]*?)</string>`,"g"),i=new Set;for(;null!==(r=a.exec(e));){let e=r[1]?.trim();e&&i.add(e)}return Array.from(i)})(r,e))]))}catch{return null}}(e);if(!t||0===t.length)return null;let r=s.dirname(e),a=new Set,i=new Set,n=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),n=s.join(r,t);if(!J.existsSync(n))return null;a.add(n);let o=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);o&&i.add(s.join(r,o));continue}e.startsWith("__TESTHOST__/")&&n.push(e.slice(13))}for(let e of n){let t=Array.from(i).find(t=>J.existsSync(s.join(t,e)));if(!t)return null;a.add(s.join(t,e))}return Array.from(a)},repairRunnerProductsIfNeeded:e5,assertSafeDerivedCleanup:function(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return er(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new _("COMMAND_FAILED","Refusing to clean AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH automatically",{derivedPath:e,hint:"Unset AGENT_DEVICE_IOS_CLEAN_DERIVED, or set AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN=1 if you trust this path."})},cleanRunnerDerivedArtifacts:function(e){try{if(!J.existsSync(e))return;if("derived"!==s.basename(e))return void J.rmSync(e,{recursive:!0,force:!0});for(let r of J.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,to.has(t)&&J.rmSync(s.join(e,r.name),{recursive:!0,force:!0})}}catch{}},buildRunnerXctestrun:td};async function tn(e,t,r=ti){var a;let i,n=(a=e,(i=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?s.resolve(i):"macos"===a.platform?s.join(e6,"derived","macos"):"simulator"===a.kind?s.join(e6,"derived"):s.join(e6,"derived",a.kind)),o=r.findProjectRoot();return await e0(e9,n,async()=>{er(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(tf("clean","forced_clean",{derived:n}),r.assertSafeDerivedCleanup(n),r.cleanRunnerDerivedArtifacts(n));let a=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let r=e.resolveExistingXctestrunProductPaths(t);return r?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:r}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:r}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:n,projectRoot:o,findXctestrun:t=>r.findXctestrun(t,e),xctestrunReferencesProjectRoot:r.xctestrunReferencesProjectRoot,resolveExistingXctestrunProductPaths:r.resolveExistingXctestrunProductPaths});if("reuse_ready"!==a.reason&&tf("rebuild",a.reason,{derived:n,xctestrunPath:a.xctestrunPath}),"reuse_ready"===a.reason)try{return await r.repairRunnerProductsIfNeeded(e,a.productPaths,a.xctestrunPath),tf("reuse","reuse_ready",{derived:n,xctestrunPath:a.xctestrunPath}),a.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof _))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&e8.has(t)}(e))throw e;tf("rebuild","repair_failed",{derived:n,xctestrunPath:a.xctestrunPath})}a.xctestrunPath&&(r.assertSafeDerivedCleanup(n),r.cleanRunnerDerivedArtifacts(n));let i=s.join(o,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!J.existsSync(i))throw new _("COMMAND_FAILED","iOS runner project not found",{projectPath:i});await r.buildRunnerXctestrun(e,i,n,t);let l=r.findXctestrun(n,e);if(!l)throw new _("COMMAND_FAILED","Failed to locate .xctestrun after build");let d=r.resolveExistingXctestrunProductPaths(l);if(!d)throw new _("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:l});return await r.repairRunnerProductsIfNeeded(e,d,l),tf("build","built_new",{derived:n,xctestrunPath:l}),l})}let to=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function ts(e,t){var r;let a=0,i=e.toLowerCase();s.basename(i).startsWith("agentdevicerunner.env.")&&(a-=1e3),i.includes(`${s.sep}macos${s.sep}`)&&(a-=5e3);let n="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return n.preferred.length>0&&(n.preferred.some(e=>i.includes(e))?a+=2e3:a-=500),n.disallowed.some(e=>i.includes(e))&&(a-=2500),a}async function tl(e,t,r){let a,i=s.dirname(e),n=r.replace(/[^a-zA-Z0-9._-]/g,"_"),o=s.join(i,`AgentDeviceRunner.env.${n}.json`),l=s.join(i,`AgentDeviceRunner.env.${n}.xctestrun`),d=await w("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new _("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new _("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);J.writeFileSync(o,JSON.stringify(a,null,2));let p=await w("plutil",["-convert","xml1","-o",l,o],{allowFailure:!0});if(0!==p.exitCode)throw new _("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:p.stderr});return{xctestrunPath:l,jsonPath:o}}async function td(e,t,r,a){let i=function(e=process.env){let t=tt(e),r=tr(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),n=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),i&&o.push(`CODE_SIGN_IDENTITY=${i}`),n&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var s;let l;await x("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",tp(e),"1","-destination",(s=e,l=tu(s),"macOS"===l?`platform=macOS,arch=${tc()}`:"simulator"===s.kind?`platform=${l} Simulator,id=${s.id}`:`generic/platform=${l}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...n],{detached:!0,onSpawn:e=>{e7.add(e),e.on("close",()=>{e7.delete(e)})},onStdoutChunk:e=>{eZ(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{eZ(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(n){let e,t,r=n instanceof _?n:new _("COMMAND_FAILED",String(n)),i=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
|
|
6
|
-
${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new
|
|
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 tv(e){await e0(th,e.deviceId,async()=>{await tI(e.deviceId,e)})}async function tI(e,t){let r=t??tm.get(e);if(r){try{await eW(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await tS(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await tS(r.child.pid,"SIGKILL"),eQ(r.xctestrunPath),eQ(r.jsonPath),tm.get(e)===r&&tm.delete(e)}}async function tA(e){await e0(th,e,async()=>{await tI(e)})}async function ty(){let e=Array.from(tm.values()),t=Array.from(e7);await Promise.allSettled(e.map(async e=>{await tS(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await tS(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await tS(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await tS(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await tS(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await tS(e.pid,"SIGKILL"),e7.delete(e)}))}async function tb(){await ty();let e=Array.from(tm.keys());await Promise.allSettled(e.map(async e=>{await tA(e)}));let t=Array.from(e7);await Promise.allSettled(t.map(async e=>{try{await tS(e.pid,"SIGTERM"),await tS(e.pid,"SIGKILL")}finally{e7.delete(e)}}))}async function tS(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 w("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function t_(e){await w("xcrun",e$(e,["bootstatus",e.id,"-b"]),{timeoutMs:eF})}async function tN(e,t,r,a,i,n){let o=await eW(e,t.port,r,a,i,t,n);return await tD(o,t,a)}async function tD(e,t,r){let a=await e.text(),i={};try{i=JSON.parse(a)}catch{throw new _("COMMAND_FAILED","Invalid runner response",{text:a})}if(!i.ok)throw new _("COMMAND_FAILED",i.error?.message??"Runner error",{runner:i,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,i.data??{}}async function tE(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new _("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new _("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(eE(r.requestId),"snapshot"===(a=t.command)||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?el(()=>(eE(r.requestId),tk(e,t,r)),{shouldRetry:e=>{eE(r.requestId);if(!(e instanceof _)||"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"))}}):tk(e,t,r)}async function tk(e,t,r={}){let a;eE(r.requestId);let i=eI(r.requestId);try{let n=(a=await tw(e,r)).ready?eU:eF;return await tN(e,a,t,r.logPath,n,i)}catch(o){let n=o instanceof _?o:new _("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&e_(n)&&a?.ready){eE(r.requestId),a?await tv(a):await tA(e.id),a=await tw(e,r);let n=await eW(a.device,a.port,t,r.logPath,eF,void 0,i);return await tD(n,a,r.logPath)}throw o}}function tM(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 tx(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tO=/^-?\d+(\.\d+)?$/,tL=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tC=new Map([["--count","count"],["--pause-ms","pauseMs"]]);function tP(e){return"click"===e||"press"===e}function tR(e){let t=e.trim();return t.startsWith("@")||tO.test(t)?t:JSON.stringify(t)}function tT(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function t$(e,t){let r=t.flags??{};if(tP(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}"swipe"===t.command&&("number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern))}function tF(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",tT(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",tT(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tT(t.launchUrl)))}function tU(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tT(r)),a))e.push(tR(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function tV(e,t){let r=[],a={},i=tP(e)?tL:"swipe"===e?tC:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tP(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tP(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=tB(t[n+1]);null!==e&&(a[s]=e),n+=1;continue}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:a}}function tG(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let i=e[a];if("--platform"===i&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===i&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===i&&a+1<e.length){let t=tB(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function tB(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tj(e,t){for(let r of t.positionals??[])e.push(tR(r));t.flags?.relaunch&&e.push("--relaunch"),tF(e,t.runtime)}class tq{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=tq.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:v,fps:I,hideTouches:A,count:y,intervalMs:b,holdMs:S,jitterPx:_,doubleTap:N,clickButton:D,pauseMs:E,pattern:k}=e;return{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:v,fps:I,hideTouches:A,count:y,intervalMs:b,holdMs:S,jitterPx:_,doubleTap:N,clickButton:D,pauseMs:E,pattern:k}}(t.flags),result:t.result}),B({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=s.dirname(t);J.existsSync(r)||J.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.name.replace(/"/g,'\\"'),i=e.device.kind?` kind=${e.device.kind}`:"";for(let n of(r.push(`context platform=${e.device.platform} device="${a}"${i} theme=unknown`),t))n.flags?.noRecord||r.push(function(e){let t=[e.command];if(tP(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tR(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tR(a)),t$(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tR(r)),t$(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tR(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tR(a)),i&&t.push(tR(i)),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tR(r)),t.push(tR(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tR(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",tR(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tj(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tT(r)),tF(t,e.flags),t.join(" ")}if("record"===e.command)return tU(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tR(r));return t$(t,e),t.join(" ")}(n));return`${r.join("\n")}
|
|
8
|
-
`}(e,this.buildOptimizedActions(e));
|
|
9
|
-
`)}function
|
|
10
|
-
`)},flush:()=>{a&&(i(a),a="")}}}function tK(e,t,r){let a=e.stdout,i=e.stderr;return a&&i?(a.setEncoding("utf8"),i.setEncoding("utf8"),a.on("data",r.writer.onChunk),i.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(a=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),a({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function tY(e,t){let r=(await w("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function tZ(e,t,r,a,i){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await tY(e,t);if(!d){await tJ(1e3);continue}let u=A("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=tX(r,{redactionPatterns:a});o=tK(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&tH(i,u.pid);let p=await o;if(tW(i),n=void 0,o=void 0,l)break;0!==p.exitCode&&(s="failed"),await tJ(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tW(i)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await tz(o),n&&!n.killed&&n.kill("SIGKILL"),await tz(d),tW(i)}}}function tQ(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}" OR eventMessage CONTAINS[c] "${e}"`}async function t0(e,t,r,a){let i="active",n=A("log",["stream","--style","compact","--predicate",tQ(e)],{stdio:["ignore","pipe","pipe"]}),o=tX(t,{redactionPatterns:r});"number"==typeof n.pid&&tH(a,n.pid);let s=tK(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tW(a),e));return{backend:"ios-simulator",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tz(s),n.killed||n.kill("SIGKILL"),await tz(s),tW(a)}}}async function t1(e,t,r,a){let i="active",n=A("log",["stream","--style","compact","--predicate",tQ(e)],{stdio:["ignore","pipe","pipe"]}),o=tX(t,{redactionPatterns:r});"number"==typeof n.pid&&tH(a,n.pid);let s=tK(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tW(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tz(s),n.killed||n.kill("SIGKILL"),await tz(s),tW(a)}}}async function t2(e,t,r,a){let i="active",n=A("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tX(t,{redactionPatterns:r});"number"==typeof n.pid&&tH(a,n.pid);let s=tK(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tW(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tz(s),n.killed||n.kill("SIGKILL"),await tz(s),tW(a)}}}function t3(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 t4(e){let t=s.dirname(e);J.existsSync(t)||J.mkdirSync(t,{recursive:!0}),function(e,t){if(J.existsSync(e)&&!(J.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}`;J.existsSync(t)&&(J.existsSync(a)&&J.unlinkSync(a),J.renameSync(t,a))}}(e,{maxBytes:t3("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:t3("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function t8(e,t,r,a){t4(r);let i=J.createWriteStream(r,{flags:"a"}),n=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await t2(e.id,i,n,a):await t0(t,i,n,a);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new _("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await tZ(e.id,t,i,n,a)}if("macos"===e.platform)return await t1(t,i,n,a);throw i.end(),new _("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function t5(e){await e.stop(),await tz(e.wait)}async function t6(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 w("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await w("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 w("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 w("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await w("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function t9(e){let t=s.dirname(e),r=s.basename(e);J.existsSync(t)||J.mkdirSync(t,{recursive:!0}),J.existsSync(e)?J.truncateSync(e,0):J.writeFileSync(e,"","utf8");let a=0;for(let e of J.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let i=e.slice(r.length+1);if(/^\d+$/.test(i))try{J.unlinkSync(s.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let t7=new Map;function re(e){let t=t7.get(e);if(t&&(clearTimeout(t.timer),t7.delete(e),t.deleteAfterDownload))try{J.rmSync(t.artifactPath,{force:!0})}catch{}}let rt=new Map;function rr(e,t){let r=rt.get(e);if(!r)throw new _("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new _("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function ra(e){let t=rt.get(e);t&&(clearTimeout(t.timer),rt.delete(e),J.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function ri(e){let t=await rn(e);await w("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=s.join(e.tempDir,t);if(!J.existsSync(r))throw new _("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rn(e){let t=await w("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new _("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 _("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(e=>(function(e){if(e.includes("\0"))throw new _("INVALID_ARGS",`Invalid archive entry: ${e}`);if(s.posix.isAbsolute(e))throw new _("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=s.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new _("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t})(e)),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new _("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new _("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 _("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===i||e.startsWith(`${i}/`)))throw new _("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,o=i;if(n!==o&&!n.startsWith(`${o}/`))throw new _("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await w("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean)){let e=t[0];if("l"===e||"h"===e)throw new _("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links")}return i}let ro=ek(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rs(e,t){return new Promise((r,a)=>{let i,n=J.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},s=!1,l=0,d=e=>{if(!s){if(s=!0,i&&clearTimeout(i),e){n.destroy(),J.rmSync(t,{force:!0}),a(e);return}r()}},u=()=>{i&&clearTimeout(i),i=setTimeout(()=>{let e=new _("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:ro});o(e),n.destroy(e),d(e)},ro)};e.on("data",e=>{u();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((l+=t)>0x80000000){let e=new _("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),n.destroy(e),d(e)}}),e.on("error",d),e.on("aborted",()=>{d(new _("COMMAND_FAILED","Artifact transfer was interrupted"))}),n.on("error",d),n.on("finish",()=>d()),u(),e.pipe(n)})}async function rl(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new _("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new _("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 _("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let i=function(e){let t=e.trim(),r=s.basename(t);if(!r||"."===r||".."===r)throw new _("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),n=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),J.mkdtempSync(s.join(K.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=s.join(n,i);return await rs(e,t),{artifactPath:t,tempDir:n}}let t=s.join(n,"artifact.tar");await rs(e,t);let a=await ri({archivePath:t,tempDir:n,platform:"ios",expectedRootName:i});return J.rmSync(t,{force:!0}),{artifactPath:a,tempDir:n}}catch(e){throw J.rmSync(n,{recursive:!0,force:!0}),e}}let rd=new Set(["agent_device.command","agent-device.command"]),ru=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rc=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rp={"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"},rf=new Set([...rd,...ru,...rc,...Object.keys(rp)]);function rm(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rh(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rw(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rg(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,i="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??i??a??""}function rv(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rI(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rA(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=C(new _("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:rm(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=C(new _(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:rm(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=u(r.tenantId);if(!e){let e=C(new _("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:rm(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function ry(){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=s.isAbsolute(t)?t:s.resolve(t);try{e=await import(S(a).href)}catch(e){throw new _("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let i=e[r];if("function"!=typeof i)throw new _("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rb(e){let t=await ry(),{handleRequest:r,token:a}=e;return ee.createServer((e,i)=>{if("GET"===e.method&&"/health"===e.url){i.statusCode=200,i.setHeader("content-type","application/json"),i.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void rS(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void r_(e,i,t,a);if("POST"!==e.method||"/rpc"!==e.url){i.statusCode=404,i.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{i.headersSent||rh(i,rm(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rh(i,rm(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rh(i,rm(a.id??null,-32600,"Invalid Request"),400);if(!rf.has(a.method))return void rh(i,rm(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rh(i,rm(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rd.has(e))return{token:rg(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(ru.has(e)){let e,a=rv(t,"platform");if("ios"!==a&&"android"!==a)throw new _("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rg(t,r),session:rv(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rv(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new _("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new _("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 _("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 _("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 _("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new _("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rI(t,"retentionMs")}}}if(rc.has(e)){let e=rv(t,"materializationId")?.trim();if(!e)throw new _("INVALID_ARGS","Invalid params: materializationId is required");return{token:rg(t,r),session:rv(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rv(t,"requestId"),materializationId:e}}}let a=rp[e];if(a)return{token:rg(t,r),session:rv(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rv(t,"tenantId")??rv(t,"tenant"),runId:rv(t,"runId"),leaseId:rv(t,"leaseId"),leaseTtlMs:rI(t,"ttlMs"),leaseBackend:rv(t,"backend")}};throw new _("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rd.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rh(i,rm(a.id??null,-32602,"Invalid params: command is required"),400);o=em(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},eh(o);let d=()=>{i.writableFinished||ew(o)};e.on("aborted",d),i.on("close",d);let u=await rA(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rh(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rh(i,{jsonrpc:"2.0",id:a.id??null,result:c});rh(i,rm(a.id??null,-32e3,c.error.message,c.error),rw(c.error.code))}catch(t){let e=C(t);rh(i,rm(a.id??null,-32e3,e.message,e),rw(e.code))}finally{eg(o)}})})}async function rS(e,t,r,a){try{var i;let n,o,s=rg({},e.headers),l=rN(s,a);if(l){t.statusCode=rw(l.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.message,code:l.code}));return}let d=await rA(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:s,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let u=await rl(e),c=(i={artifactPath:u.artifactPath,tempDir:u.tempDir,tenantId:d.tenantId},n=h.randomUUID(),o=setTimeout(()=>{ra(n)},3e5),rt.set(n,{artifactPath:i.artifactPath,tempDir:i.tempDir,tenantId:i.tenantId,timer:o}),n);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:c}))}catch(r){let e=C(r);t.statusCode=rw(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function r_(e,t,r,a){let i=e.url?.slice("/upload/".length)??"";if(!i){t.statusCode=400,t.end("Missing artifact id");return}try{let n=rg({},e.headers),o=rN(n,a);if(o){t.statusCode=rw(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let s=await rA(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:n,session:"default",command:"download_artifact",positionals:[i]}});if(!s.ok){t.statusCode=s.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.response.error?.data?.message??s.response.error?.message??"Unauthorized"}));return}let l=function(e,t){let r=t7.get(e);if(!r)throw new _("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new _("UNAUTHORIZED","Artifact belongs to a different tenant");if(!J.existsSync(r.artifactPath))throw re(e),new _("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(i,s.tenantId),d=J.createReadStream(l.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),l.fileName&&t.setHeader("content-disposition",`attachment; filename="${l.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=C(e);t.statusCode=rw(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&re(i)}),d.pipe(t)}catch(r){let e=C(r);t.statusCode=rw(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rN(e,t){return t&&e!==t?C(new _("UNAUTHORIZED","Invalid token")):null}function rD(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rE(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rk(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new _("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rM{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=rk(e.backend),r=u(e.tenantId);if(!r)throw new _("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=rD(e.runId);if(!a)throw new _("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let i=this.resolveLeaseTtlMs(e.ttlMs),n=this.bindingKey(r,a,t),o=this.runBindings.get(n);if(o){let e=this.leases.get(o);if(e)return this.refreshLease(e,i);this.runBindings.delete(n)}this.enforceCapacity(t);let s=this.now(),l={leaseId:h.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:s,heartbeatAt:s,expiresAt:s+i};return this.leases.set(l.leaseId,l),this.runBindings.set(n,l.leaseId),{...l}}heartbeatLease(e){let t=rE(e.leaseId);if(!t)throw new _("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new _("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=rE(e.leaseId);if(!t)throw new _("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=rk(e.backend),r=u(e.tenantId);if(!r)throw new _("INVALID_ARGS","tenant isolation requires tenant id.");let a=rD(e.runId);if(!a)throw new _("INVALID_ARGS","tenant isolation requires run id.");let i=rE(e.leaseId);if(!i)throw new _("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new _("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new _("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 _("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 _("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=u(t),i=rD(r);if(t&&!a)throw new _("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new _("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||i&&e.runId!==i)throw new _("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rx=["emulator","platform-tools",s.join("cmdline-tools","latest","bin"),s.join("cmdline-tools","tools","bin")];function rO(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 rL(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||K.homedir();return rO([t??"",r??"",a?s.join(a,"Android","Sdk"):""])}async function rC(e){try{return await j.access(e,j.constants.X_OK),!0}catch{return!1}}async function rP(e=process.env){let t,r=[];for(let a of rL(e)){let e=[];for(let t of rx){let r=s.join(a,t);await rC(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(s.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=rO([...r,...a]).join(s.delimiter)}function rR(e,t){return["-s",e.id,...t]}async function rT(){if(await rP(),!await E("adb"))throw new _("TOOL_MISSING","adb not found in PATH")}function r$(e,t){let r=`${e}
|
|
11
|
-
${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function
|
|
12
|
-
${e.stderr}`}function rj(e,t){return["-s",e,...t]}function rq(e){return e.startsWith("emulator-")}function rH(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}function rW(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}async function rz(e,t=en){return w("adb",rj(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function rJ(e,t){let r=t.replace(/_/g," ").trim();if(!rq(e))return r||e;let a=await rK(e);return a?a.replace(/_/g," "):r||e}async function rX(e,t,r){try{return await r("adb",rj(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=y(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function rK(e,t=w){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await rX(e,["shell","getprop",r],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let r=await rX(e,["emu","avd","name"],t);if(!r)return;let a=rW(r.stdout);if(0===r.exitCode&&a)return a}function rY(e){let t=e.toLowerCase();return t.includes("tv")||t.includes("leanback")?"tv":null}function rZ(e){return/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(e)}async function rQ(e,t){let r=rB(await w("adb",rj(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:en})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function r0(e){return(await Promise.all(rG.map(async t=>await rQ(e,t)))).some(e=>!0===e)}async function r1(e){return"tv"===rY(rB(await w("adb",rj(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:en})))||await r0(e)||rZ(rB(await w("adb",rj(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:en})))?"tv":"mobile"}async function r2(e={}){if(await rP(),!await E("adb"))throw new _("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??eR(void 0),r=(await r3()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,i]=await Promise.all([rJ(e,t),r7(e),r1(e)]);return{platform:"android",id:e,name:r,kind:rq(e)?"emulator":"device",target:i,booted:a}}))}async function r3(){return(await w("adb",["devices","-l"],{timeoutMs:en})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).filter(e=>"device"===e[1]).map(e=>({serial:e[0],rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}))}function r4(e){return e.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}function r8(e,t){let r=e.find(e=>e===t);if(r)return r;let a=rH(t);return e.find(e=>rH(e)===a)}async function r5(){let e=await w("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:en});if(0!==e.exitCode)throw new _("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 r4(e.stdout)}async function r6(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await r9(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 _("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 r9(e,t){let r=rH(e);for(let e of(await r3()).filter(e=>(!t||e.serial===t)&&rq(e.serial)))if(rH(e.rawModel)===r||rH(await rJ(e.serial,e.rawModel))===r)return e.serial}async function r7(e){try{let t=await rz(e);return"1"===t.stdout.trim()}catch{return!1}}async function ae(e){var t,r;let a;await rP();let i=e.avdName.trim();if(!i)throw new _("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await E("adb"))throw new _("TOOL_MISSING","adb not found in PATH");if(!await E("emulator"))throw new _("TOOL_MISSING","emulator not found in PATH");let o=await r5(),s=r8(o,i);if(!s)throw new _("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:i,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),d=(t=await r2(),r=e.serial,a=rH(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&rH(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),p("emulator",t)}let u=d??await r6({avdName:s,serial:e.serial,timeoutMs:n}),c=Math.max(1e3,n-(Date.now()-l));await ar(u.id,c);let f=(await r2()).find(e=>e.id===u.id);return f?{...f,name:s,booted:!0}:{...u,name:s,booted:!0}}async function at(e){return await ae({...e,headless:!0})}async function ar(e,t=6e4){let r,a=eo.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await es(async({deadline:i})=>{if(i?.isExpired())throw n=!0,new _("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),message:"timeout"});let o=Math.max(1e3,i?.remainingMs()??t),s=await rz(e,Math.min(o,en));if(r=s,"1"!==s.stdout.trim())throw new _("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:i,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=eb({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=>eb({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=y(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eb({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===i.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),reason:d,hint:eS(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new _("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new _("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new _("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new _(i.code,i.message,{...u,...i.details??{}},i.cause)}}let aa=/\.(?:apk|aab)$/i,ai=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function an(e){var t,r;let a=e.trim();return 0===a.length?"other":aa.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!ai.test(t))?"binary":"package":(r=a,ai.test(r))?"package":"other"}function ao(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let as=[".zip",".tar",".tar.gz",".tgz"],al=ek(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),ad=["1","true","yes","on"];async function au(e){let t=[];try{let r=await ac(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await aw(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 aA(t)}}}catch(e){throw await aA(t),e}}async function ac(e,t){if("path"===e.kind)return{localPath:b(e.path),cleanup:async()=>{}};let r=await j.mkdtemp(s.join(K.tmpdir(),"agent-device-source-"));try{return{localPath:await ap(r,e.url,e.headers,t),cleanup:async()=>{await j.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await j.rm(r,{recursive:!0,force:!0}),e}}async function ap(e,t,r,a){let i;try{i=new URL(t)}catch{throw new _("INVALID_ARGS",`Invalid source URL: ${t}`)}await af(i);let n=a?.signal;if(n?.aborted)throw new _("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,l=()=>{o.abort(n?.reason)};n?.addEventListener("abort",l,{once:!0});let d=a?.downloadTimeoutMs??al,u=setTimeout(()=>{o.abort(Error("download timeout"))},d);try{let t=await fetch(i,{headers:r,redirect:"follow",signal:o.signal});if(!t.ok)throw new _("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:i.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),i=a?.[1]?.trim();if(i)return s.basename(i);let n=s.basename(t.pathname);return n||"downloaded-artifact.bin"}(t,i),n=s.join(e,a),l=t.body;if(!l)throw new _("COMMAND_FAILED","Download response body was empty",{url:i.toString()});let d=await j.open(n,"w");try{for await(let e of l)await d.write(e)}finally{await d.close()}return n}catch(e){if(n?.aborted)throw new _("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new _("COMMAND_FAILED",`App source download timed out after ${d}ms`,{timeoutMs:d,url:i.toString()},e);throw e}finally{n?.removeEventListener("abort",l),clearTimeout(u)}}async function af(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new _("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!ad.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||ah(t))throw new _("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=>ah(e.address)))throw new _("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 am(e){var t,r,a,i;let n=e instanceof URL?e:new URL(e),o=n.hostname.toLowerCase();if(!o)return!1;let s=n.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,i=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(i))}function ah(e){let t,r=Y.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 aw(e,t){let r=await j.stat(e).catch(()=>null);if(!r)throw new _("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&aI(e)){if(!t.allowArchiveExtraction)throw new _("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await av(e);return t.registerCleanup(r.cleanup),await aw(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await ag(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new _("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await ag(e,(e,t)=>t.isFile()&&aI(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new _("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await av(a[0]);return t.registerCleanup(e.cleanup),await aw(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new _("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new _("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function ag(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let i=await j.readdir(e.path,{withFileTypes:!0});for(let n of(i.sort((e,t)=>e.name.localeCompare(t.name)),i)){let i=s.join(e.path,n.name);if(t(i,n)){r.push(i);continue}n.isDirectory()&&e.depth<5&&a.push({path:i,depth:e.depth+1})}}return r}async function av(e){let t=await j.mkdtemp(s.join(K.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await w("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await w("tar",["-xzf",e,"-C",t]):await w("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await j.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await j.rm(t,{recursive:!0,force:!0}),e}}function aI(e){let t=e.toLowerCase();return as.some(e=>t.endsWith(e))}async function aA(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let ay=new V("utf-16le");async function ab(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await aS(e,r);if(!a)continue;let i=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),i=e.readUInt16LE(r+2),n=e.readUInt32LE(r+4);if(n<=0||r+n>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),i=(256&r)!=0,n=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);n.push(i?function(e,t){let[,r]=a_(e,t),[a,i]=a_(e,t+r),n=t+r+i;return e.subarray(n,n+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),i=t+a;return ay.decode(e.subarray(i,i+2*r))}(e,o))}return n}(e.subarray(r,r+n));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let i=e.readUInt16LE(t+24),n=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let r=s+t*n;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let i=e.readUInt32LE(r+8);if(0xffffffff!==i)return a[i];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,i,t);if(a)return a}r+=n}}(t);if(i)return i}return await aN(e)}async function aS(e,t){try{let r=await w("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 a_(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function aN(e){let t=await aD();if(!t)return;let r=await w(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function aD(){if(void 0!==e)return e??void 0;try{for(let t of rL()){let r=s.join(t,"build-tools");try{for(let t of(await n.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=s.join(r,t,"aapt");try{return await n.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function aE(e,t){let r="url"===e.kind&&am(e.url),a=await au({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=s.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await ak(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function ak(e){let t=s.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await ab(e)}}let aM={settings:{type:"intent",value:"android.settings.SETTINGS"}},ax="android.intent.category.LAUNCHER",aO="android.intent.category.LEANBACK_LAUNCHER",aL="android.intent.category.DEFAULT";async function aC(e,t){let r=t.trim();if("package"===an(r))return{type:"package",value:r};let a=aM[r.toLowerCase()];if(a)return a;let i=(await w("adb",rR(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new _("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:i});throw new _("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function aP(e,t="all"){let r=await aR(e);return("user-installed"===t?(await a$(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:aF(e)}))}async function aR(e){let t=new Set;for(let r of aT(e,{includeFallbackWhenUnknown:!0})){let a=await w("adb",rR(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],i=a.includes("/")?a.split("/")[0]:a;i&&t.add(i)}}return t}function aT(e,t={}){return"tv"===e.target?[aO]:"mobile"===e.target?[ax]:t.includeFallbackWhenUnknown?[ax,aO]:[ax]}async function a$(e){return(await w("adb",rR(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function aF(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let i=r[e];if(!t.has(i)){a=i;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function aU(e){let t=await aV(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await aV(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function aV(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 w("adb",rR(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function aG(e,t,r){e.booted||await ar(e.id);let a=t.trim();if(rU(a)){if(r)throw new _("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await w("adb",rR(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",a]));return}let i=await aC(e,t),n=aT(e)[0]??ax;if("intent"===i.type){if(r)throw new _("INVALID_ARGS","Activity override requires a package name, not an intent");await w("adb",rR(e,["shell","am","start","-W","-a",i.value]));return}if(r){let t=r.includes("/")?r:`${i.value}/${r.startsWith(".")?r:`.${r}`}`;await w("adb",rR(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aL,"-c",n,"-n",t]));return}let o=await w("adb",rR(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aL,"-c",n,"-p",i.value]),{allowFailure:!0});if(0===o.exitCode&&!aj(o.stdout,o.stderr))return;let s=await aB(e,i.value);if(!s)throw new _("COMMAND_FAILED",`Failed to launch ${i.value}`,{stdout:o.stdout,stderr:o.stderr});await w("adb",rR(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aL,"-c",n,"-n",s]))}async function aB(e,t){for(let r of Array.from(new Set(aT(e,{includeFallbackWhenUnknown:!0})))){let a=await w("adb",rR(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=aq(a.stdout);if(i)return i}return null}function aj(e,t){let r=`${e}
|
|
13
|
-
${
|
|
14
|
-
${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new
|
|
15
|
-
${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),u=await
|
|
16
|
-
${t}`,a=r.indexOf("<?xml"),i=a>=0?a:r.indexOf("<hierarchy");if(i<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<i)return null;let o=r.slice(i,n+12).trim();return o.length>0?o:null}function io(e){if(!(e instanceof _)||"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 is(e,t,r){await w("adb",rR(e,["shell","input","tap",String(t),String(r)]))}async function il(e,t,r,a,i,n=250){await w("adb",rR(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function id(e){await w("adb",rR(e,["shell","input","keyevent","4"]))}async function iu(e){await w("adb",rR(e,["shell","input","keyevent","3"]))}async function ic(e){await w("adb",rR(e,["shell","input","keyevent","187"]))}async function ip(e,t,r,a=800){await w("adb",rR(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function im(e,t){let r=iy(t);if(!r||"ok"!==await ib(e,t))try{let r=t.replace(/ /g,"%s");await w("adb",rR(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof _)||"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 _("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 ih(e,t,r){await is(e,t,r)}async function iw(e,t,r,a){let i=Array.from(a).length,n=iy(a),o=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];n||(o.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),o.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96}));let s=null;for(let n of o){var l,d;await ih(e,t,r);let o=(l=i+n.clearPadding,d=n.minClear,Math.max(d,Math.min(n.maxClear,l)));if(await iS(e,o),"input_text"===n.strategy)await im(e,a);else if("clipboard_paste"===n.strategy){if("ok"!==await ib(e,a))continue}else await iA(e,a,1,15);if((s=await i_(e,t,r))===a)return}throw new _("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:s??null})}async function ig(e,t,r=.6){let{width:a,height:i}=await iI(e),n=Math.floor(a*r),o=Math.floor(i*r),s=Math.floor(a/2),l=Math.floor(i/2),d=s,u=l,c=s,p=l;switch(t){case"up":u=l-Math.floor(o/2),p=l+Math.floor(o/2);break;case"down":u=l+Math.floor(o/2),p=l-Math.floor(o/2);break;case"left":d=s-Math.floor(n/2),c=s+Math.floor(n/2);break;case"right":d=s+Math.floor(n/2),c=s-Math.floor(n/2);break;default:throw new _("INVALID_ARGS",`Unknown direction: ${t}`)}await w("adb",rR(e,["shell","input","swipe",String(d),String(u),String(c),String(p),"300"]))}async function iv(e,t){for(let r=0;r<8;r+=1){let r="";try{r=await ir(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new _("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(function(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,i=a.exec(e);for(;i;){let t=a5(i[0]),n=(a6(t,"text")??"").toLowerCase(),o=(a6(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=a9(a6(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}i=a.exec(e)}return null}(r,t))return;await ig(e,"down",.5)}throw new _("COMMAND_FAILED",`Could not find element containing "${t}" after scrolling`)}async function iI(e){let t=(await w("adb",rR(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new _("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iA(e,t,r,a){let i=Math.max(1,Math.floor(r)),n=Array.from(t);for(let t=0;t<n.length;t+=i){let r=n.slice(t,t+i).join("");await im(e,r),a>0&&t+i<n.length&&await rF(a)}}function iy(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 ib(e,t){let r=await w("adb",rR(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":r$(r.stdout,r.stderr)?"unsupported":0===(await w("adb",rR(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await w("adb",rR(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function iS(e,t){let r=Math.max(0,t);await w("adb",rR(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 w("adb",rR(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function i_(e,t,r){let a,i=await ir(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=a8(a[0]),i=a9(e.bounds);if(!i)continue;let n=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,i.width*i.height),p=t>=i.x&&t<=i.x+i.width&&r>=i.y&&r<=i.y+i.height;if(u&&iN(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&iN(n)){(!s||c<=s.area)&&(s={text:d,area:c});continue}p&&(!l||c<=l.area)&&(l={text:d,area:c})}return o?.text??s?.text??l?.text??null}function iN(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iD(e){let t=await w("adb",rR(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new _("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),i=a.length>0?a[a.length-1]?.[1]:void 0,n=i?`0x${i.toLowerCase()}`:void 0;return{visible:r,inputType:n,type:n?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(n):void 0}}(t.stdout)}async function iE(e){let t=await iD(e),r=t,a=0;for(;r.visible&&a<2;)await id(e),a+=1,await rF(120),r=await iD(e);return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function ik(e){let t,r;return(r=(t=(await ix(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 iM(e,t){await ix(e,["shell","cmd","clipboard","set","text",t],"write")}async function ix(e,t,r){let a=await w("adb",rR(e,t),{allowFailure:!0});if(r$(a.stdout,a.stderr))throw new _("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new _("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let iO=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iL(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new _("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iC(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 _("INVALID_ARGS",`permission setting requires a target: ${iO.join("|")}`)}function iP(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new _("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function iR(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=i$(r);await w("adb",rR(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=i$(r);await w("adb",rR(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await w("adb",rR(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=i$(r);await w("adb",rR(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await iF(e,r);await w("adb",rR(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 _("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await iT(e,t);return}case"permission":{if(!a)throw new _("INVALID_ARGS","permission setting requires an active app in session");let t=iL(r),n=function(e,t){let r=iC(e);if(t?.trim())throw new _("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 _("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===n.kind)return void await iV(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await iU(e,a,o);await w("adb",rR(e,["shell","pm",o,a,n.value]));return}default:throw new _("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function iT(e,t){var r;let a,i,n=(r=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of n){let r=await w("adb",rR(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
|
|
17
|
-
${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new
|
|
18
|
-
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new
|
|
19
|
-
${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function
|
|
20
|
-
${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new
|
|
21
|
-
`,"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.":eE("IOS_RUNNER_CONNECT_TIMEOUT"))})}function eP(e){if(eN(e))throw ex()}function eR(e,t,r){if(!e)return t;let a=Number(e);return Number.isFinite(a)?Math.max(r,Math.floor(a)):t}let eT=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],e$=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function eF(e){return e?.trim()||void 0}function eU(e,t){for(let r of e){let e=eF(t[r]);if(e)return e}}function eV(e,t=process.env){return eF(e)??eU(eT,t)}function eG(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function ej(e,t=process.env){let r=eF(e)??eU(e$,t);if(r)return eG(r)}function eB(e,t={}){let r=eV(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function eq(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:eB(t,{simulatorSetPath:e.simulatorSetPath})}let eH=eR(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),eW=eR(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),ez=eR(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),eJ=eR(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),eK=eR(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),eX=eR(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),eY=eR(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),eZ=eR(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function eQ(e,t,r,a,i=eH,n,o){let s=ef.fromTimeoutMs(i),l=await e0(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/ez));try{return await em(async({deadline:s})=>{if(s?.isExpired())throw new k("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(n&&null!==n.child.exitCode&&void 0!==n.child.exitCode)throw await eC({session:n,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await e0(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new k("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await e1(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(eX,e),o)}catch(e){if(o?.aborted||ek(e))throw ex();d=e}throw new k("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:eJ,maxDelayMs:eK,jitter:.2,shouldRetry:eO},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||ek(e))throw ex();d||(d=e)}if(o?.aborted)throw ex();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw eL({port:t,endpoints:l,logPath:a,lastError:d});let n=await e3(e,t,r,i);return new Response(n.body,{status:n.status})}throw eL({port:t,endpoints:l,logPath:a,lastError:d})}async function e0(e,t,r){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await e2(e.id,r);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function e1(e,t,r,a){let i,n=new AbortController,o=setTimeout(()=>n.abort(),r);a&&(a.aborted?(clearTimeout(o),n.abort()):(i=()=>n.abort(),a.addEventListener("abort",i,{once:!0})));try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(o),i&&a&&a.removeEventListener("abort",i)}}async function e2(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(eY,t)):eY,a=l.join(ea.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),i=await v("xcrun",["devicectl","device","info","details","--device",e,"--json-output",a,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==i.exitCode||!et.existsSync(a))return null;let n=JSON.parse(et.readFileSync(a,"utf8"));if(n.info?.outcome&&"success"!==n.info.outcome)return null;let o=(n.result?.connectionProperties?.tunnelIPAddress??n.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{e5(a)}}async function e3(e,t,r,a){let i=JSON.stringify(r),n=eq(e,["spawn",e.id,"/usr/bin/curl","-s","-X","POST","-H","Content-Type: application/json","--data",i,`http://127.0.0.1:${t}/command`]),o=await v("xcrun",n,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=eM({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new k("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:eE(e)})}return{status:200,body:s}}async function e4(){return await new Promise((e,t)=>{let r=ei.createServer();r.listen(0,"127.0.0.1",()=>{let a=r.address();r.close(),"object"==typeof a&&a?.port?e(a.port):t(new k("COMMAND_FAILED","Failed to allocate port"))}),r.on("error",t)})}function e8(e,t,r,a){t&&et.appendFileSync(t,e),r&&et.appendFileSync(r,e),a&&process.stderr.write(e)}function e5(e){try{et.existsSync(e)&&et.unlinkSync(e)}catch{}}async function e6(e,t,r){let a=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r);return e.set(t,a),a.finally(()=>{e.get(t)===a&&e.delete(t)})}function e9(e){return"apple"===e||"ios"===e||"macos"===e}function e7(e,t){return!t||("apple"===t?e9(e):e===t)}function te(e){let{simulatorSetPath:t,platform:r,target:a}=e;if(t&&"macos"!==r&&"desktop"!==a)return t}async function tt(e,t,r={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>e7(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&&e9(e.platform));if(!e)throw new k("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 k("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=i(t.deviceName),r=a.find(t=>i(t.name)===e);if(!r)throw new k("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===a.length)return a[0];if(0===a.length){var n;let e=r.simulatorSetPath;if(e&&(!(n=t.platform)||"apple"===n||"ios"===n))throw new k("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 k("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 tr=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function ta(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new k("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(!et.existsSync(e))throw new k("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==q("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await v("codesign",["--remove-signature",e],{allowFailure:!0});try{await v("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof k?a:new k("COMMAND_FAILED",String(a));throw new k("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}function ti(e){let t=function(e){let t=function(e){try{let t=q("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())return null;return JSON.parse(t.stdout)}catch{return null}}(e);if(t){var r,a=t;let e=new Set,i=t=>{if(t&&"object"==typeof t)for(let r of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),r=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){r.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};i(a);let n=a.TestConfigurations;if(Array.isArray(n))for(let e of n){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)i(e)}for(let e of Object.values(a))e&&"object"==typeof e&&"TestBundlePath"in e&&i(e);return Array.from(e)}if("darwin"===process.platform)return null;try{return r=et.readFileSync(e,"utf8"),Array.from(new Set([...["ProductPaths","DependentProductPaths"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<array>([\\s\\S]*?)</array>`,"g"),i=/<string>([\s\S]*?)<\/string>/g,n=new Set;for(;null!==(r=a.exec(e));){let e,t=r[1]??"";for(;null!==(e=i.exec(t));){let t=e[1]?.trim();t&&n.add(t)}}return Array.from(n)})(r,e)),...["TestHostPath","TestBundlePath","UITargetAppPath"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<string>([\\s\\S]*?)</string>`,"g"),i=new Set;for(;null!==(r=a.exec(e));){let e=r[1]?.trim();e&&i.add(e)}return Array.from(i)})(r,e))]))}catch{return null}}(e);if(!t||0===t.length)return null;let r=l.dirname(e),a=new Set,i=new Set,n=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),n=l.join(r,t);if(!et.existsSync(n))return null;a.add(n);let o=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);o&&i.add(l.join(r,o));continue}e.startsWith("__TESTHOST__/")&&n.push(e.slice(13))}for(let e of n){let t=Array.from(i).find(t=>et.existsSync(l.join(t,e)));if(!t)return null;a.add(l.join(t,e))}return Array.from(a)}let tn=l.join(ea.homedir(),".agent-device","ios-runner"),to=new Map,ts=new Set;function tl(e){return e?.trim()??""}function td(e=process.env){return tl(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tl(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tu(e=process.env){let t=tl(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${td(e)}.uitests`}let tc=function(e=process.env){let t=td(e),r=tu(e);return Array.from(new Set([tl(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);async function tp(e,t){var r;let a,i=(r=e,(a=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?l.resolve(a):"macos"===r.platform?l.join(tn,"derived","macos"):"simulator"===r.kind?l.join(tn,"derived"):l.join(tn,"derived",r.kind)),n=function(){let e=l.dirname(R(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=l.join(t,"package.json");if(et.existsSync(e))return t;t=l.dirname(t)}return e}();return await e6(to,i,async()=>{ed(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(t_("clean","forced_clean",{derived:i}),tS(i),tf(i));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:i,projectRoot:n,findXctestrun:t=>th(t,e),xctestrunReferencesProjectRoot:tg,resolveExistingXctestrunProductPaths:ti});if("reuse_ready"!==r.reason&&t_("rebuild",r.reason,{derived:i,xctestrunPath:r.xctestrunPath}),"reuse_ready"===r.reason)try{return await ta(e,r.productPaths,r.xctestrunPath),t_("reuse","reuse_ready",{derived:i,xctestrunPath:r.xctestrunPath}),r.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof k))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&tr.has(t)}(e))throw e;t_("rebuild","repair_failed",{derived:i,xctestrunPath:r.xctestrunPath})}r.xctestrunPath&&(tS(i),tf(i));let a=l.join(n,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!et.existsSync(a))throw new k("COMMAND_FAILED","iOS runner project not found",{projectPath:a});await ty(e,a,i,t);let o=th(i,e);if(!o)throw new k("COMMAND_FAILED","Failed to locate .xctestrun after build");let s=ti(o);if(!s)throw new k("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:o});return await ta(e,s,o),t_("build","built_new",{derived:i,xctestrunPath:o}),o})}function tf(e){try{if(!et.existsSync(e))return;if("derived"!==l.basename(e))return void et.rmSync(e,{recursive:!0,force:!0});for(let r of et.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,tm.has(t)&&et.rmSync(l.join(e,r.name),{recursive:!0,force:!0})}}catch{}}let tm=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function th(e,t){if(!et.existsSync(e))return null;let r=[],a=[e];for(;a.length>0;){let e=a.pop();for(let t of et.readdirSync(e,{withFileTypes:!0})){let i=l.join(e,t.name);if(t.isDirectory()){a.push(i);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=et.statSync(i);r.push({path:i,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let a=tw(r.path,t)-tw(e.path,t);if(0!==a)return a}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)}function tw(e,t){var r;let a=0,i=e.toLowerCase();l.basename(i).startsWith("agentdevicerunner.env.")&&(a-=1e3),i.includes(`${l.sep}macos${l.sep}`)&&(a-=5e3);let n="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return n.preferred.length>0&&(n.preferred.some(e=>i.includes(e))?a+=2e3:a-=500),n.disallowed.some(e=>i.includes(e))&&(a-=2500),a}function tg(e,t){try{let r=et.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(et.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}}async function tv(e,t,r){let a,i=l.dirname(e),n=r.replace(/[^a-zA-Z0-9._-]/g,"_"),o=l.join(i,`AgentDeviceRunner.env.${n}.json`),s=l.join(i,`AgentDeviceRunner.env.${n}.xctestrun`),d=await v("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new k("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new k("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);et.writeFileSync(o,JSON.stringify(a,null,2));let p=await v("plutil",["-convert","xml1","-o",s,o],{allowFailure:!0});if(0!==p.exitCode)throw new k("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:s,stderr:p.stderr});return{xctestrunPath:s,jsonPath:o}}async function ty(e,t,r,a){let i=function(e=process.env){let t=td(e),r=tu(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),n=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),i&&o.push(`CODE_SIGN_IDENTITY=${i}`),n&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var s;let l;await T("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",tb(e),"1","-destination",(s=e,l=tI(s),"macOS"===l?`platform=macOS,arch=${tA()}`:"simulator"===s.kind?`platform=${l} Simulator,id=${s.id}`:`generic/platform=${l}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...n],{detached:!0,onSpawn:e=>{ts.add(e),e.on("close",()=>{ts.delete(e)})},onStdoutChunk:e=>{e8(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{e8(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(n){let e,t,r=n instanceof k?n:new k("COMMAND_FAILED",String(n)),i=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
|
|
6
|
+
${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new k("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:r.message,details:r.details,logPath:a.logPath,hint:i})}}function tI(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new k("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 tA(){return"arm64"===process.arch?"arm64":"x86_64"}function tb(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function tS(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return ed(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new k("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 t_(e,t,r){J({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}let tN=new Map,tD=new Map;async function tx(e,t){return await e6(tD,e.id,async()=>{var r;let a,i=tN.get(e.id);if(i){if(function(e){return!!e&&Z(e)}(i.child.pid))return i;await tE(e.id,i)}await ("simulator"!==(r=e).kind?Promise.resolve():tR(r)),await tk(e);let n=await tp(e,t),o=await e4(),{xctestrunPath:s,jsonPath:l}=await tv(n,{AGENT_DEVICE_RUNNER_PORT:String(o)},`session-${e.id}-${o}`),{child:d,wait:u}=h("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",tb(e),"1","-destination-timeout",String(eZ),"-xctestrun",s,"-destination","macOS"===(a=tI(e))?`platform=macOS,arch=${tA()}`:"simulator"===e.kind?`platform=${a} Simulator,id=${e.id}`:`platform=${a},id=${e.id}`],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(o)},detached:!0});d.stdout?.on("data",e=>{e8(e,t.logPath,t.traceLogPath,t.verbose)}),d.stderr?.on("data",e=>{e8(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${o}:${Date.now()}`,device:e,deviceId:e.id,port:o,xctestrunPath:s,jsonPath:l,testPromise:u,child:d,ready:!1};return tN.set(e.id,c),c})}async function tk(e){if("simulator"===e.kind)for(let t of tc){let r=await v("xcrun",eq(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==r.exitCode){let e=`${r.stdout}
|
|
7
|
+
${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found nothing")&&!e.includes("no such file")&&!e.includes("invalid device")&&!e.includes("could not find"))continue}}}async function tM(e){await e6(tD,e.deviceId,async()=>{await tE(e.deviceId,e)})}async function tE(e,t){let r=t??tN.get(e);if(r){try{await eQ(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await tP(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await tP(r.child.pid,"SIGKILL"),e5(r.xctestrunPath),e5(r.jsonPath),tN.get(e)===r&&tN.delete(e)}}async function tO(e){await e6(tD,e,async()=>{await tE(e)})}async function tL(){let e=Array.from(tN.values()),t=Array.from(ts);await Promise.allSettled(e.map(async e=>{await tP(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await tP(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await tP(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await tP(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await tP(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await tP(e.pid,"SIGKILL"),ts.delete(e)}))}async function tC(){await tL();let e=Array.from(tN.keys());await Promise.allSettled(e.map(async e=>{await tO(e)}));let t=Array.from(ts);await Promise.allSettled(t.map(async e=>{try{await tP(e.pid,"SIGTERM"),await tP(e.pid,"SIGKILL")}finally{ts.delete(e)}}))}async function tP(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 v("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function tR(e){await v("xcrun",eq(e,["bootstatus",e.id,"-b"]),{timeoutMs:eH})}async function tT(e,t,r,a,i,n){let o=await eQ(e,t.port,r,a,i,t,n);return await t$(o,t,a)}async function t$(e,t,r){let a=await e.text(),i={};try{i=JSON.parse(a)}catch{throw new k("COMMAND_FAILED","Invalid runner response",{text:a})}if(!i.ok)throw new k("string"==typeof i.error?.code&&i.error.code.trim().length>0?i.error.code:"COMMAND_FAILED",i.error?.message??"Runner error",{runner:i,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,i.data??{}}async function tF(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new k("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new k("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(eP(r.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?eh(()=>(eP(r.requestId),tU(e,t,r)),{shouldRetry:e=>{eP(r.requestId);if(!(e instanceof k)||"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"))}}):tU(e,t,r)}async function tU(e,t,r={}){let a;eP(r.requestId);let i=eD(r.requestId);try{let n=(a=await tx(e,r)).ready?eW:eH;return await tT(e,a,t,r.logPath,n,i)}catch(o){let n=o instanceof k?o:new k("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&eO(n)&&a?.ready){eP(r.requestId),a?await tM(a):await tO(e.id),a=await tx(e,r);let n=await eQ(a.device,a.port,t,r.logPath,eH,void 0,i);return await t$(n,a,r.logPath)}throw o}}function tV(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 tG(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tj=/^-?\d+(\.\d+)?$/,tB=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tq=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tH=new Map([["--delay-ms","delayMs"]]);function tW(e){return"click"===e||"press"===e}function tz(e){return"type"===e||"fill"===e}function tJ(e){let t=e.trim();return t.startsWith("@")||tj.test(t)?t:JSON.stringify(t)}function tK(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function tX(e,t){let r=t.flags??{};if(tW(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}tz(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tY(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",tK(t.metroHost)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tK(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tK(t.launchUrl)))}function tZ(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tK(r)),a))e.push(tJ(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function tQ(e,t){let r=[],a={},i=tW(e)?tB:"swipe"===e?tq:tz(e)?tH:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tW(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tW(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=t1(t[n+1]);if(null!==e){a[s]=e,n+=1;continue}}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:a}}function t0(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let i=e[a];if("--platform"===i&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===i&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===i&&a+1<e.length){let t=t1(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function t1(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function t2(e,t){for(let r of t.positionals??[])e.push(tJ(r));t.flags?.relaunch&&e.push("--relaunch"),tY(e,t.runtime)}class t3{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=t3.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:v,fps:y,hideTouches:I,count:A,intervalMs:b,delayMs:S,holdMs:_,jitterPx:N,doubleTap:D,clickButton:x,pauseMs:k,pattern:M}=e;return{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:v,fps:y,hideTouches:I,count:A,intervalMs:b,delayMs:S,holdMs:_,jitterPx:N,doubleTap:D,clickButton:x,pauseMs:k,pattern:M}}(t.flags),result:t.result}),J({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=l.dirname(t);et.existsSync(r)||et.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.name.replace(/"/g,'\\"'),i=e.device.kind?` kind=${e.device.kind}`:"";for(let n of(r.push(`context platform=${e.device.platform} device="${a}"${i} theme=unknown`),t))n.flags?.noRecord||r.push(function(e){let t=[e.command];if(tW(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tJ(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tJ(a)),tX(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tJ(r)),tX(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tJ(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tJ(a)),i&&t.push(tJ(i)),tX(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tJ(r)),t.push(tJ(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tJ(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",tJ(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return t2(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tK(r)),tY(t,e.flags),t.join(" ")}if("record"===e.command)return tZ(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tJ(r));return tX(t,e),t.join(" ")}(n));return`${r.join("\n")}
|
|
8
|
+
`}(e,this.buildOptimizedActions(e));et.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=t3.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return l.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return l.join(this.sessionsDir,t3.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return l.join(this.sessionsDir,t3.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return G(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return t3.expandHome(e.saveScriptPath);et.existsSync(this.sessionsDir)||et.mkdirSync(this.sessionsDir,{recursive:!0});let t=t3.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return l.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&&(tW(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tW(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=tV(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(tW(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 t4(e,t){if(!e)return;let r=l.dirname(e);et.existsSync(r)||et.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:Q(t)??void 0,command:d(t)??void 0};et.writeFileSync(e,`${JSON.stringify(a)}
|
|
9
|
+
`)}function t8(e){if(e&&et.existsSync(e))try{et.unlinkSync(e)}catch{}}async function t5(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function t6(e){await new Promise(t=>setTimeout(t,e))}function t9(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],a="",i=a=>{(!(r.length>0)||r.some(e=>a.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(a,t.redactionPatterns))};return{onChunk:e=>{let t=`${a}${e}`.split("\n");for(let e of(a=t.pop()??"",t))i(`${e}
|
|
10
|
+
`)},flush:()=>{a&&(i(a),a="")}}}function t7(e,t,r){let a=e.stdout,i=e.stderr;return a&&i?(a.setEncoding("utf8"),i.setEncoding("utf8"),a.on("data",r.writer.onChunk),i.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(a=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),a({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function re(e,t){let r=(await v("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function rt(e,t,r,a,i){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await re(e,t);if(!d){await t6(1e3);continue}let u=_("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=t9(r,{redactionPatterns:a});o=t7(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&t4(i,u.pid);let p=await o;if(t8(i),n=void 0,o=void 0,l)break;0!==p.exitCode&&(s="failed"),await t6(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),t8(i)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await t5(o),n&&!n.killed&&n.kill("SIGKILL"),await t5(d),t8(i)}}}function rr(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}" OR eventMessage CONTAINS[c] "${e}"`}async function ra(e,t,r,a){let i="active",n=_("log",["stream","--style","compact","--predicate",rr(e)],{stdio:["ignore","pipe","pipe"]}),o=t9(t,{redactionPatterns:r});"number"==typeof n.pid&&t4(a,n.pid);let s=t7(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),t8(a),e));return{backend:"ios-simulator",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await t5(s),n.killed||n.kill("SIGKILL"),await t5(s),t8(a)}}}async function ri(e,t,r,a){let i="active",n=_("log",["stream","--style","compact","--predicate",rr(e)],{stdio:["ignore","pipe","pipe"]}),o=t9(t,{redactionPatterns:r});"number"==typeof n.pid&&t4(a,n.pid);let s=t7(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),t8(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await t5(s),n.killed||n.kill("SIGKILL"),await t5(s),t8(a)}}}async function rn(e,t,r,a){let i="active",n=_("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=t9(t,{redactionPatterns:r});"number"==typeof n.pid&&t4(a,n.pid);let s=t7(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),t8(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await t5(s),n.killed||n.kill("SIGKILL"),await t5(s),t8(a)}}}function ro(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 rs(e){let t=l.dirname(e);et.existsSync(t)||et.mkdirSync(t,{recursive:!0}),function(e,t){if(et.existsSync(e)&&!(et.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}`;et.existsSync(t)&&(et.existsSync(a)&&et.unlinkSync(a),et.renameSync(t,a))}}(e,{maxBytes:ro("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:ro("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rl(e,t,r,a){rs(r);let i=et.createWriteStream(r,{flags:"a"}),n=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await rn(e.id,i,n,a):await ra(t,i,n,a);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new k("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await rt(e.id,t,i,n,a)}if("macos"===e.platform)return await ri(t,i,n,a);throw i.end(),new k("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rd(e){await e.stop(),await t5(e.wait)}async function ru(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 v("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await v("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 v("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 v("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await v("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function rc(e){let t=l.dirname(e),r=l.basename(e);et.existsSync(t)||et.mkdirSync(t,{recursive:!0}),et.existsSync(e)?et.truncateSync(e,0):et.writeFileSync(e,"","utf8");let a=0;for(let e of et.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let i=e.slice(r.length+1);if(/^\d+$/.test(i))try{et.unlinkSync(l.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let rp=new Map;function rf(e){let t=rp.get(e);if(t&&(clearTimeout(t.timer),rp.delete(e),t.deleteAfterDownload))try{et.rmSync(t.artifactPath,{force:!0})}catch{}}let rm=new Map;function rh(e,t){let r=rm.get(e);if(!r)throw new k("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new k("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function rw(e){let t=rm.get(e);t&&(clearTimeout(t.timer),rm.delete(e),et.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rg(e){let t=await rv(e);await v("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=l.join(e.tempDir,t);if(!et.existsSync(r))throw new k("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rv(e){let t=await v("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new k("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 k("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(e=>(function(e){if(e.includes("\0"))throw new k("INVALID_ARGS",`Invalid archive entry: ${e}`);if(l.posix.isAbsolute(e))throw new k("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=l.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new k("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t})(e)),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new k("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new k("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 k("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===i||e.startsWith(`${i}/`)))throw new k("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,o=i;if(n!==o&&!n.startsWith(`${o}/`))throw new k("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await v("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean)){let e=t[0];if("l"===e||"h"===e)throw new k("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links")}return i}let ry=eR(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rI(e,t){return new Promise((r,a)=>{let i,n=et.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},s=!1,l=0,d=e=>{if(!s){if(s=!0,i&&clearTimeout(i),e){n.destroy(),et.rmSync(t,{force:!0}),a(e);return}r()}},u=()=>{i&&clearTimeout(i),i=setTimeout(()=>{let e=new k("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:ry});o(e),n.destroy(e),d(e)},ry)};e.on("data",e=>{u();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((l+=t)>0x80000000){let e=new k("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),n.destroy(e),d(e)}}),e.on("error",d),e.on("aborted",()=>{d(new k("COMMAND_FAILED","Artifact transfer was interrupted"))}),n.on("error",d),n.on("finish",()=>d()),u(),e.pipe(n)})}async function rA(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new k("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new k("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 k("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let i=function(e){let t=e.trim(),r=l.basename(t);if(!r||"."===r||".."===r)throw new k("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),n=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),et.mkdtempSync(l.join(ea.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=l.join(n,i);return await rI(e,t),{artifactPath:t,tempDir:n}}let t=l.join(n,"artifact.tar");await rI(e,t);let a=await rg({archivePath:t,tempDir:n,platform:"ios",expectedRootName:i});return et.rmSync(t,{force:!0}),{artifactPath:a,tempDir:n}}catch(e){throw et.rmSync(n,{recursive:!0,force:!0}),e}}let rb=new Set(["agent_device.command","agent-device.command"]),rS=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),r_=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rN={"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"},rD=new Set([...rb,...rS,...r_,...Object.keys(rN)]);function rx(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rk(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rM(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rE(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,i="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??i??a??""}function rO(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rL(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rC(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=U(new k("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:rx(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=U(new k(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:rx(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=p(r.tenantId);if(!e){let e=U(new k("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:rx(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rP(){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=l.isAbsolute(t)?t:l.resolve(t);try{e=await import(x(a).href)}catch(e){throw new k("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let i=e[r];if("function"!=typeof i)throw new k("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rR(e){let t=await rP(),{handleRequest:r,token:a}=e;return es.createServer((e,i)=>{if("GET"===e.method&&"/health"===e.url){i.statusCode=200,i.setHeader("content-type","application/json"),i.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void rT(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void r$(e,i,t,a);if("POST"!==e.method||"/rpc"!==e.url){i.statusCode=404,i.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{i.headersSent||rk(i,rx(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rk(i,rx(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rk(i,rx(a.id??null,-32600,"Invalid Request"),400);if(!rD.has(a.method))return void rk(i,rx(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rk(i,rx(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rb.has(e))return{token:rE(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(rS.has(e)){let e,a=rO(t,"platform");if("ios"!==a&&"android"!==a)throw new k("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rE(t,r),session:rO(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rO(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new k("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new k("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 k("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 k("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 k("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new k("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rL(t,"retentionMs")}}}if(r_.has(e)){let e=rO(t,"materializationId")?.trim();if(!e)throw new k("INVALID_ARGS","Invalid params: materializationId is required");return{token:rE(t,r),session:rO(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rO(t,"requestId"),materializationId:e}}}let a=rN[e];if(a)return{token:rE(t,r),session:rO(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rO(t,"tenantId")??rO(t,"tenant"),runId:rO(t,"runId"),leaseId:rO(t,"leaseId"),leaseTtlMs:rL(t,"ttlMs"),leaseBackend:rO(t,"backend")}};throw new k("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rb.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rk(i,rx(a.id??null,-32602,"Invalid params: command is required"),400);o=eA(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},eb(o);let d=()=>{i.writableFinished||eS(o)};e.on("aborted",d),i.on("close",d);let u=await rC(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rk(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rk(i,{jsonrpc:"2.0",id:a.id??null,result:c});rk(i,rx(a.id??null,-32e3,c.error.message,c.error),rM(c.error.code))}catch(t){let e=U(t);rk(i,rx(a.id??null,-32e3,e.message,e),rM(e.code))}finally{e_(o)}})})}async function rT(e,t,r,a){try{var i;let n,o,s=rE({},e.headers),l=rF(s,a);if(l){t.statusCode=rM(l.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.message,code:l.code}));return}let d=await rC(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:s,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let u=await rA(e),c=(i={artifactPath:u.artifactPath,tempDir:u.tempDir,tenantId:d.tenantId},n=g.randomUUID(),o=setTimeout(()=>{rw(n)},3e5),rm.set(n,{artifactPath:i.artifactPath,tempDir:i.tempDir,tenantId:i.tenantId,timer:o}),n);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:c}))}catch(r){let e=U(r);t.statusCode=rM(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function r$(e,t,r,a){let i=e.url?.slice("/upload/".length)??"";if(!i){t.statusCode=400,t.end("Missing artifact id");return}try{let n=rE({},e.headers),o=rF(n,a);if(o){t.statusCode=rM(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let s=await rC(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:n,session:"default",command:"download_artifact",positionals:[i]}});if(!s.ok){t.statusCode=s.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.response.error?.data?.message??s.response.error?.message??"Unauthorized"}));return}let l=function(e,t){let r=rp.get(e);if(!r)throw new k("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new k("UNAUTHORIZED","Artifact belongs to a different tenant");if(!et.existsSync(r.artifactPath))throw rf(e),new k("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(i,s.tenantId),d=et.createReadStream(l.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),l.fileName&&t.setHeader("content-disposition",`attachment; filename="${l.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=U(e);t.statusCode=rM(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rf(i)}),d.pipe(t)}catch(r){let e=U(r);t.statusCode=rM(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rF(e,t){return t&&e!==t?U(new k("UNAUTHORIZED","Invalid token")):null}function rU(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rV(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rG(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new k("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rj{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=rG(e.backend),r=p(e.tenantId);if(!r)throw new k("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=rU(e.runId);if(!a)throw new k("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let i=this.resolveLeaseTtlMs(e.ttlMs),n=this.bindingKey(r,a,t),o=this.runBindings.get(n);if(o){let e=this.leases.get(o);if(e)return this.refreshLease(e,i);this.runBindings.delete(n)}this.enforceCapacity(t);let s=this.now(),l={leaseId:g.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:s,heartbeatAt:s,expiresAt:s+i};return this.leases.set(l.leaseId,l),this.runBindings.set(n,l.leaseId),{...l}}heartbeatLease(e){let t=rV(e.leaseId);if(!t)throw new k("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new k("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=rV(e.leaseId);if(!t)throw new k("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=rG(e.backend),r=p(e.tenantId);if(!r)throw new k("INVALID_ARGS","tenant isolation requires tenant id.");let a=rU(e.runId);if(!a)throw new k("INVALID_ARGS","tenant isolation requires run id.");let i=rV(e.leaseId);if(!i)throw new k("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new k("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new k("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 k("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 k("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=p(t),i=rU(r);if(t&&!a)throw new k("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new k("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||i&&e.runId!==i)throw new k("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rB=["emulator","platform-tools",l.join("cmdline-tools","latest","bin"),l.join("cmdline-tools","tools","bin")];function rq(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 rH(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||ea.homedir();return rq([t??"",r??"",a?l.join(a,"Android","Sdk"):""])}async function rW(e){try{return await X.access(e,X.constants.X_OK),!0}catch{return!1}}async function rz(e=process.env){let t,r=[];for(let a of rH(e)){let e=[];for(let t of rB){let r=l.join(a,t);await rW(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(l.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=rq([...r,...a]).join(l.delimiter)}function rJ(e,t){return["-s",e.id,...t]}async function rK(){if(await rz(),!await C("adb"))throw new k("TOOL_MISSING","adb not found in PATH")}function rX(e,t){let r=`${e}
|
|
11
|
+
${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function rY(e){await new Promise(t=>setTimeout(t,e))}function rZ(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let a=r[1]?.toLowerCase(),i=r[2]??"";return"http"!==a&&"https"!==a&&"ws"!==a&&"wss"!==a&&"ftp"!==a&&"ftps"!==a||i.startsWith("//")}function rQ(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 r0=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function r1(e){return`${e.stdout}
|
|
12
|
+
${e.stderr}`}function r2(e,t){return["-s",e,...t]}function r3(e){return e.startsWith("emulator-")}function r4(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function r8(e,t=ep){return v("adb",r2(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function r5(e,t){let r=t.replace(/_/g," ").trim();if(!r3(e))return r||e;let a=await r9(e);return a?a.replace(/_/g," "):r||e}async function r6(e,t,r){try{return await r("adb",r2(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=N(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function r9(e,t=v){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await r6(e,["shell","getprop",r],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let r=await r6(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 r7(e,t){let r=r1(await v("adb",r2(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:ep})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function ae(e){return(await Promise.all(r0.map(async t=>await r7(e,t)))).some(e=>!0===e)}async function at(e){var t;let r;return"tv"===((r=r1(await v("adb",r2(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:ep})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await ae(e)?"tv":(t=r1(await v("adb",r2(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:ep})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function ar(e={}){if(await rz(),!await C("adb"))throw new k("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??ej(void 0),r=(await aa()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,i]=await Promise.all([r5(e,t),as(e),at(e)]);return{platform:"android",id:e,name:r,kind:r3(e)?"emulator":"device",target:i,booted:a}}))}async function aa(){return(await v("adb",["devices","-l"],{timeoutMs:ep})).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 ai(){let e=await v("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:ep});if(0!==e.exitCode)throw new k("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 an(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await ao(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 k("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 ao(e,t){let r=r4(e);for(let e of(await aa()).filter(e=>(!t||e.serial===t)&&r3(e.serial)))if(r4(e.rawModel)===r||r4(await r5(e.serial,e.rawModel))===r)return e.serial}async function as(e){try{let t=await r8(e);return"1"===t.stdout.trim()}catch{return!1}}async function al(e){var t,r;let a;await rz();let i=e.avdName.trim();if(!i)throw new k("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await C("adb"))throw new k("TOOL_MISSING","adb not found in PATH");if(!await C("emulator"))throw new k("TOOL_MISSING","emulator not found in PATH");let o=await ai(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let a=r4(t);return e.find(e=>r4(e)===a)}(o,i);if(!s)throw new k("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:i,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),d=(t=await ar(),r=e.serial,a=r4(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&r4(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),m("emulator",t)}let u=d??await an({avdName:s,serial:e.serial,timeoutMs:n}),c=Math.max(1e3,n-(Date.now()-l));await ad(u.id,c);let p=(await ar()).find(e=>e.id===u.id);return p?{...p,name:s,booted:!0}:{...u,name:s,booted:!0}}async function ad(e,t=6e4){let r,a=ef.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await em(async({deadline:i})=>{if(i?.isExpired())throw n=!0,new k("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),message:"timeout"});let o=Math.max(1e3,i?.remainingMs()??t),s=await r8(e,Math.min(o,ep));if(r=s,"1"!==s.stdout.trim())throw new k("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:i,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=eM({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=>eM({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=N(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eM({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===i.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),reason:d,hint:eE(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new k("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new k("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new k("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new k(i.code,i.message,{...u,...i.details??{}},i.cause)}}let au=/\.(?:apk|aab)$/i,ac=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function ap(e){var t,r;let a=e.trim();return 0===a.length?"other":au.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!ac.test(t))?"binary":"package":(r=a,ac.test(r))?"package":"other"}function af(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let am=[".zip",".tar",".tar.gz",".tgz"],ah=eR(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),aw=["1","true","yes","on"];async function ag(e){let t=[];try{let r=await av(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await aS(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 ax(t)}}}catch(e){throw await ax(t),e}}async function av(e,t){if("path"===e.kind)return{localPath:D(e.path),cleanup:async()=>{}};let r=await X.mkdtemp(l.join(ea.tmpdir(),"agent-device-source-"));try{return{localPath:await ay(r,e.url,e.headers,t),cleanup:async()=>{await X.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await X.rm(r,{recursive:!0,force:!0}),e}}async function ay(e,t,r,a){let i;try{i=new URL(t)}catch{throw new k("INVALID_ARGS",`Invalid source URL: ${t}`)}await aI(i);let n=a?.signal;if(n?.aborted)throw new k("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,s=()=>{o.abort(n?.reason)};n?.addEventListener("abort",s,{once:!0});let d=a?.downloadTimeoutMs??ah,u=setTimeout(()=>{o.abort(Error("download timeout"))},d);try{let t=await fetch(i,{headers:r,redirect:"follow",signal:o.signal});if(!t.ok)throw new k("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:i.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),i=a?.[1]?.trim();if(i)return l.basename(i);let n=l.basename(t.pathname);return n||"downloaded-artifact.bin"}(t,i),n=l.join(e,a),s=t.body;if(!s)throw new k("COMMAND_FAILED","Download response body was empty",{url:i.toString()});let d=await X.open(n,"w");try{for await(let e of s)await d.write(e)}finally{await d.close()}return n}catch(e){if(n?.aborted)throw new k("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new k("COMMAND_FAILED",`App source download timed out after ${d}ms`,{timeoutMs:d,url:i.toString()},e);throw e}finally{n?.removeEventListener("abort",s),clearTimeout(u)}}async function aI(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new k("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!aw.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||ab(t))throw new k("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=>ab(e.address)))throw new k("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function aA(e){var t,r,a,i;let n=e instanceof URL?e:new URL(e),o=n.hostname.toLowerCase();if(!o)return!1;let s=n.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,i=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(i))}function ab(e){let t,r=ei.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 aS(e,t){let r=await X.stat(e).catch(()=>null);if(!r)throw new k("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&aD(e)){if(!t.allowArchiveExtraction)throw new k("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await aN(e);return t.registerCleanup(r.cleanup),await aS(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await a_(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new k("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await a_(e,(e,t)=>t.isFile()&&aD(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new k("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await aN(a[0]);return t.registerCleanup(e.cleanup),await aS(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new k("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new k("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function a_(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let i=await X.readdir(e.path,{withFileTypes:!0});for(let n of(i.sort((e,t)=>e.name.localeCompare(t.name)),i)){let i=l.join(e.path,n.name);if(t(i,n)){r.push(i);continue}n.isDirectory()&&e.depth<5&&a.push({path:i,depth:e.depth+1})}}return r}async function aN(e){let t=await X.mkdtemp(l.join(ea.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await v("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await v("tar",["-xzf",e,"-C",t]):await v("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await X.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await X.rm(t,{recursive:!0,force:!0}),e}}function aD(e){let t=e.toLowerCase();return am.some(e=>t.endsWith(e))}async function ax(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let ak=new W("utf-16le");async function aM(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await aE(e,r);if(!a)continue;let i=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),i=e.readUInt16LE(r+2),n=e.readUInt32LE(r+4);if(n<=0||r+n>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),i=(256&r)!=0,n=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);n.push(i?function(e,t){let[,r]=aO(e,t),[a,i]=aO(e,t+r),n=t+r+i;return e.subarray(n,n+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),i=t+a;return ak.decode(e.subarray(i,i+2*r))}(e,o))}return n}(e.subarray(r,r+n));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let i=e.readUInt16LE(t+24),n=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let r=s+t*n;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let i=e.readUInt32LE(r+8);if(0xffffffff!==i)return a[i];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,i,t);if(a)return a}r+=n}}(t);if(i)return i}return await aL(e)}async function aE(e,t){try{let r=await v("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 aO(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function aL(e){let t=await aC();if(!t)return;let r=await v(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function aC(){if(void 0!==e)return e??void 0;try{for(let t of rH()){let r=l.join(t,"build-tools");try{for(let t of(await n.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=l.join(r,t,"aapt");try{return await n.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function aP(e,t){let r="url"===e.kind&&aA(e.url),a=await ag({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=l.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await aR(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function aR(e){let t=l.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await aM(e)}}let aT={settings:{type:"intent",value:"android.settings.SETTINGS"}},a$="android.intent.category.LAUNCHER",aF="android.intent.category.LEANBACK_LAUNCHER",aU="android.intent.category.DEFAULT";async function aV(e,t){let r=t.trim();if("package"===ap(r))return{type:"package",value:r};let a=aT[r.toLowerCase()];if(a)return a;let i=(await v("adb",rJ(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new k("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:i});throw new k("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function aG(e,t="all"){let r=await aj(e);return("user-installed"===t?(await aq(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:aH(e)}))}async function aj(e){let t=new Set;for(let r of aB(e,{includeFallbackWhenUnknown:!0})){let a=await v("adb",rJ(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],i=a.includes("/")?a.split("/")[0]:a;i&&t.add(i)}}return t}function aB(e,t={}){return"tv"===e.target?[aF]:"mobile"===e.target?[a$]:t.includeFallbackWhenUnknown?[a$,aF]:[a$]}async function aq(e){return(await v("adb",rJ(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function aH(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let i=r[e];if(!t.has(i)){a=i;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function aW(e){let t=await az(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await az(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function az(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 v("adb",rJ(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function aJ(e,t,r){var a,i;let n;e.booted||await ad(e.id);let o=t.trim();if(rZ(o)){if(r)throw new k("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await v("adb",rJ(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await aV(e,t),l=aB(e)[0]??a$;if("intent"===s.type){if(r)throw new k("INVALID_ARGS","Activity override requires a package name, not an intent");await v("adb",rJ(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;await v("adb",rJ(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aU,"-c",l,"-n",t]));return}let d=await v("adb",rJ(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aU,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,i=d.stderr,n=`${a}
|
|
13
|
+
${i}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)))return;let u=await aK(e,s.value);if(!u)throw new k("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr});await v("adb",rJ(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aU,"-c",l,"-n",u]))}async function aK(e,t){for(let r of Array.from(new Set(aB(e,{includeFallbackWhenUnknown:!0})))){let a=await v("adb",rJ(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=function(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}(a.stdout);if(i)return i}return null}async function aX(e){e.booted||await ad(e.id)}async function aY(e,t){if("settings"===t.trim().toLowerCase())return void await v("adb",rJ(e,["shell","am","force-stop","com.android.settings"]));let r=await aV(e,t);if("intent"===r.type)throw new k("INVALID_ARGS","Close requires a package name, not an intent");await v("adb",rJ(e,["shell","am","force-stop",r.value]))}async function aZ(e,t){let r=await aV(e,t);if("intent"===r.type)throw new k("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await v("adb",rJ(e,["uninstall",r.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
|
|
14
|
+
${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new k("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let aQ=null;async function a0(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(aQ?.key===e)return aQ.invocation;if(await C("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return aQ={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new k("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await X.access(t)}catch{throw new k("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return aQ={key:e,invocation:r},r}async function a1(e){let t=await a0();await v(t.cmd,[...t.prefixArgs,...e])}async function a2(e,t){let r,a=await X.mkdtemp(l.join(ea.tmpdir(),"agent-device-aab-")),i=l.join(a,"bundle.apks"),n=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await a1(["build-apks","--bundle",t,"--output",i,"--mode",n]),await a1(["install-apks","--apks",i,"--device-id",e.id])}finally{await X.rm(a,{recursive:!0,force:!0})}}async function a3(e,t){".aab"===l.extname(t).toLowerCase()?await a2(e,t):await v("adb",rJ(e,["install","-r",t]))}async function a4(e){return new Set((await v("adb",rJ(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function a8(e,t){let r=Array.from(await a4(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function a5(e,t){e.booted||await ad(e.id),await a3(e,t)}async function a6(e,t,r){let a=r?void 0:await a4(e);return await a5(e,t),r??(a?await a8(e,a):void 0)}async function a9(e,t){e.booted||await ad(e.id);let r=await aP({kind:"path",path:t});try{let t=await a6(e,r.installablePath,r.packageName),a=t?aH(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function a7(e,t,r){e.booted||await ad(e.id);let{package:a}=await aZ(e,t),i=await aP({kind:"path",path:r},{resolveIdentity:!1});try{return await a5(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function ie(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 k("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),i=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new k("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*a),n=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(i,Math.max(1,r-2*n))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(r,a,i,n)=>({direction:t,x1:r,y1:a,x2:i,y2:n,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 it(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,i=a.exec(e);for(;i;){let t=ia(i[0]),n=(ii(t,"text")??"").toLowerCase(),o=(ii(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=io(ii(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}i=a.exec(e)}return null}function ir(e){let t=ia(e),r=e=>{let r=ii(t,e);if(null!==r)return"true"===r};return{text:ii(t,"text"),desc:ii(t,"content-desc"),resourceId:ii(t,"resource-id"),className:ii(t,"class"),bounds:ii(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function ia(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,n=r;for(;n<a;){for(;n<a;){let t=e[n];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;n+=1}if(n>=a)break;let r=e[n];if("/"===r||">"===r)break;i.lastIndex=n;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),n=i.lastIndex}return t}function ii(e,t){return e.get(t)??null}function io(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),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 is(e){return e?e.toLowerCase():""}function il(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function id(e,t={}){return function(e,t,r){let a=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=a.exec(e);continue}let n=ir(t),o=io(n.bounds),s=r[r.length-1],l={type:n.className,label:n.text||n.desc,value:n.text,identifier:n.resourceId,rect:o,enabled:n.enabled,hittable:n.clickable??n.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),i=a.exec(e)}return t}(e),i=[],n=!1,o=r.depth??1/0,s=r.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children];for(;a.length>0;){let e=a.shift(),t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",n=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||n.includes(r))return e;a.push(...e.children)}return null}(a,r.scope):null,l=s?[s]:a.children,d=new Map,u=e=>{let t=d.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||u(t))return d.set(e,!0),!0;return d.set(e,!1),!1},c=(e,t,a,s=!1,l=!1)=>{var d,p,f,m,h,w;let g,v,y,I,A,b,S,_;if(i.length>=800){n=!0;return}if(t>o)return;let N=!!r.raw||(d=e,p=r,f=s,m=u(e),h=l,v=is(d.type),y=!!(d.label&&d.label.trim().length>0),I=!!(d.identifier&&d.identifier.trim().length>0),A=y&&!il(d.label??""),b=I&&!il(d.identifier??""),S=(g=(w=v).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,_="imageview"===v||"imagebutton"===v,p.interactiveOnly?!!d.hittable||!!(A||b)&&!_&&(!S||!!h)&&(f||m||h):p.compact?A||b||!!d.hittable:!S&&!_||!!d.hittable||!!A||!!b&&!!m||m),D=a;N&&(D=i.length,i.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:t,parentIndex:a}));let x=s||!!e.hittable,k=l||function(e){if(!e)return!1;let t=is(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let r of e.children)if(c(r,t+1,D,x,k),n)return};for(let e of l)if(c(e,0,void 0,!1,!1),n)break;return n?{nodes:i,truncated:n}:{nodes:i}}(await iu(e),0,t)}async function iu(e){return eh(()=>ic(e),{shouldRetry:im})}async function ic(e){var t,r,a;let i,n,o=await v("adb",rJ(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=ip(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await v("adb",rJ(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,a=l.stderr,i=`${r}
|
|
15
|
+
${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),u=await v("adb",rJ(e,["shell","cat",d])),c=ip(u.stdout,u.stderr);if(!c)throw new k("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return c}function ip(e,t){let r=`${e}
|
|
16
|
+
${t}`,a=r.indexOf("<?xml"),i=a>=0?a:r.indexOf("<hierarchy");if(i<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<i)return null;let o=r.slice(i,n+12).trim();return o.length>0?o:null}function im(e){if(!(e instanceof k)||"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 ih(e,t,r){await v("adb",rJ(e,["shell","input","tap",String(t),String(r)]))}async function iw(e,t,r,a,i,n=250){await v("adb",rJ(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function ig(e){await v("adb",rJ(e,["shell","input","keyevent","4"]))}async function iv(e){await v("adb",rJ(e,["shell","input","keyevent","3"]))}async function iy(e){await v("adb",rJ(e,["shell","input","keyevent","187"]))}async function iI(e,t,r,a=800){await v("adb",rJ(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function iA(e,t,r=0){r>0&&Array.from(t).length>1?await ik(e,t,1,r):await ib(e,t)}async function ib(e,t){let r=iM(t);if(!r||"ok"!==await iE(e,t))try{let r=t.replace(/ /g,"%s");await v("adb",rJ(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof k)||"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 k("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 iS(e,t,r){await ih(e,t,r)}async function i_(e,t,r,a,i=0){let n=Array.from(a).length,o=iM(a),s=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];!o&&i<=0&&s.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),(!o||i>0)&&s.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96});let l=null;for(let o of s){var d,u;await iS(e,t,r);let s=(d=n+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await iO(e,s),"input_text"===o.strategy)await iA(e,a,i);else if("clipboard_paste"===o.strategy){if("ok"!==await iE(e,a))continue}else await ik(e,a,1,i>0?i:15);if((l=await iL(e,t,r))===a)return}throw new k("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function iN(e,t,r){let a=await ix(e),i=ie({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await v("adb",rJ(e,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"])),i}async function iD(e,t,r){let a=r?.maxScrolls??8,i="";try{i=await iu(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new k("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(it(i,t))return{attempts:0};for(let r=1;r<=a;r+=1){await iN(e,"down",{amount:.5});let a="";try{a=await iu(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new k("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(it(a,t))return{attempts:r};if(a===i)throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:r,stalled:!0});i=a}throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:a})}async function ix(e){let t=(await v("adb",rJ(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new k("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function ik(e,t,r,a){let i=Math.max(1,Math.floor(r)),n=Array.from(t);for(let t=0;t<n.length;t+=i){let r=n.slice(t,t+i).join("");await ib(e,r),a>0&&t+i<n.length&&await rY(a)}}function iM(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 iE(e,t){let r=await v("adb",rJ(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":rX(r.stdout,r.stderr)?"unsupported":0===(await v("adb",rJ(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await v("adb",rJ(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function iO(e,t){let r=Math.max(0,t);await v("adb",rJ(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 v("adb",rJ(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function iL(e,t,r){let a,i=await iu(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=ir(a[0]),i=io(e.bounds);if(!i)continue;let n=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,i.width*i.height),p=t>=i.x&&t<=i.x+i.width&&r>=i.y&&r<=i.y+i.height;if(u&&iC(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&iC(n)){(!s||c<=s.area)&&(s={text:d,area:c});continue}p&&(!l||c<=l.area)&&(l={text:d,area:c})}return o?.text??s?.text??l?.text??null}function iC(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iP(e){let t=await v("adb",rJ(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new k("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),i=a.length>0?a[a.length-1]?.[1]:void 0,n=i?`0x${i.toLowerCase()}`:void 0;return{visible:r,inputType:n,type:n?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(n):void 0}}(t.stdout)}async function iR(e){let t=await iP(e),r=t,a=0;for(;r.visible&&a<2;)await v("adb",rJ(e,["shell","input","keyevent","111"])),a+=1,await rY(120),r=await iP(e);if(t.visible&&r.visible)throw new k("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 iT(e){let t,r;return(r=(t=(await iF(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 i$(e,t){await iF(e,["shell","cmd","clipboard","set","text",t],"write")}async function iF(e,t,r){let a=await v("adb",rJ(e,t),{allowFailure:!0});if(rX(a.stdout,a.stderr))throw new k("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new k("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let iU=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iV(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new k("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iG(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 k("INVALID_ARGS",`permission setting requires a target: ${iU.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 k("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function iB(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=iH(r);await v("adb",rJ(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=iH(r);await v("adb",rJ(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await v("adb",rJ(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=iH(r);await v("adb",rJ(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await iW(e,r);await v("adb",rJ(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 k("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await iq(e,t);return}case"permission":{if(!a)throw new k("INVALID_ARGS","permission setting requires an active app in session");let t=iV(r),n=function(e,t){let r=iG(e);if(t?.trim())throw new k("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 k("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===n.kind)return void await iJ(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await iz(e,a,o);await v("adb",rJ(e,["shell","pm",o,a,n.value]));return}default:throw new k("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function iq(e,t){var r;let a,i,n=(r=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of n){let r=await v("adb",rJ(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
|
|
17
|
+
${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new k("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 k("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function iH(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 k("INVALID_ARGS",`Invalid setting state: ${e}`)}async function iW(e,t){let r=ij(t);if("toggle"!==r)return r;let a=await v("adb",rJ(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new k("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
|
|
18
|
+
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new k("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"auto"===i?"dark":"dark"===i?"light":"dark"}async function iz(e,t,r){let a=await iK(e),i=[];for(let n of null!==a&&a>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let a=await v("adb",rJ(e,["shell","pm",r,t,n]),{allowFailure:!0});if(0===a.exitCode)return;i.push({permission:n,stderr:a.stderr,exitCode:a.exitCode})}throw new k("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function iJ(e,t,r,a){"grant"===r?await v("adb",rJ(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await v("adb",rJ(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await v("adb",rJ(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await v("adb",rJ(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await v("adb",rJ(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function iK(e){let t=await v("adb",rJ(e,["shell","getprop","ro.build.version.sdk"]),{allowFailure:!0});if(0!==t.exitCode)return null;let r=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(r)||r<=0?null:r}async function iX(e,t,r){let a="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,i=["shell","am","broadcast","-a",a,"-p",t],n="string"==typeof r.receiver?r.receiver.trim():"";n&&i.push("-n",n);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new k("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 k("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await v("adb",rJ(e,i)),{action:a,extrasCount:s}}let iY=Buffer.from([137,80,78,71,13,10,26,10]);async function iZ(e,t){await iQ(e);try{await rY(1e3),await i1(e,t)}finally{await i0(e).catch(()=>{})}}async function iQ(e){let t=t=>v("adb",rJ(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 i0(e){await v("adb",rJ(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function i1(e,t){let r=await v("adb",rJ(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new k("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(iY);if(a<0)throw new k("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let i=function(e,t){let r=t+iY.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),a=r+4,i=e.toString("ascii",a,a+4),n=r+12+t;if(n>e.length)break;if("IEND"===i)return n;r=n}return null}(r.stdoutBuffer,a);if(!i)throw new k("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await X.writeFile(t,r.stdoutBuffer.subarray(a,i))}let i2=eR(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,ec,5e3),i3=eR(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,eu,1e3),i4=eR(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),i8=eR(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),i5=eR(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),i6=eR(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),i9=eR(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function i7(e,t){let r=["devicectl",...e],a=await v("xcrun",r,{allowFailure:!0,timeoutMs:i8});if(0===a.exitCode)return;let i=String(a.stdout??""),n=String(a.stderr??"");throw new k("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:t.deviceId,hint:nr(i,n)??nt})}async function ne(e,t){let r=l.join(ea.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),a=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],i=await v("xcrun",a,{allowFailure:!0,timeoutMs:i8});try{var n,o;if(0!==i.exitCode){let t=String(i.stdout??""),r=String(i.stderr??"");throw new k("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:i.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:nr(t,r)??nt})}let s=await X.readFile(r,"utf8");return n=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?n.filter(e=>!e.bundleId.startsWith("com.apple.")):n}catch(t){if(t instanceof k)throw t;throw new k("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await X.unlink(r).catch(()=>{})}}let nt="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function nr(e,t){let r=`${e}
|
|
19
|
+
${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function na(e){if(!(e instanceof k)||"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 ni(e,t){let r=await v("xcrun",eq(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let a=r.stdout.trim();if(!a)return{installed:!1};let i=await v("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${a}/Info.plist`],{allowFailure:!0});if(0!==i.exitCode||!i.stdout.trim())return{installed:!0};let n=i.stdout.trim(),o=`${a}/${n}`,s=await v("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 nn(e,t){if("simulator"!==e.kind)throw new k("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function no(){await v("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:i5})}async function ns(e){let t,r;if("simulator"!==e.kind||"Booted"===await nd(e))return;let a=ef.fromTimeoutMs(i2);try{await em(async({deadline:a})=>{if(a?.isExpired())throw new k("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:i2});let i=Math.max(1e3,a?.remainingMs()??i2),n=await v("xcrun",eq(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode};let o=`${t.stdout}
|
|
20
|
+
${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new k("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await v("xcrun",eq(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:i});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new k("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await nd(e);if("Booted"!==d)throw new k("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=eM({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=>eM({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(n){let i=eM({error:n,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new k("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:i2,elapsedMs:a.elapsedMs(),reason:i,hint:eE(i),boot:t,bootstatus:r})}}async function nl(e){let t=eq(e,["shutdown",e.id]),r=await v("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function nd(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?eB(["list","devices","-j"]):eq(e,["list","devices","-j"]),a=await v("xcrun",r,{allowFailure:!0,timeoutMs:i3});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 nu(e,t){try{let r=await v("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{let r=await X.readFile(e,"utf8");return function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`<key>\\s*${r}\\s*<\\/key>\\s*<string>([\\s\\S]*?)<\\/string>`,"i"));if(!a?.[1])return;let i=a[1].trim().replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&");return i.length>0?i:void 0}(r,t)}catch{return}}async function nc(e,t){if("url"===e.kind&&!aA(e.url))throw new k("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 ag({source:e,isInstallablePath:(e,t)=>t.isDirectory()&&e.toLowerCase().endsWith(".app")||t.isFile()&&e.toLowerCase().endsWith(".ipa"),installableLabel:"iOS installable (.app or .ipa)",allowArchiveExtraction:"url"!==e.kind||aA(e.url),signal:t?.signal}),a=await nf(r.installablePath,t),i=await np(a.installPath);return{archivePath:r.archivePath??(r.installablePath.toLowerCase().endsWith(".ipa")?r.installablePath:void 0),installablePath:a.installPath,bundleId:i.bundleId,appName:i.appName,cleanup:async()=>{await a.cleanup(),await r.cleanup()}}}async function np(e){let t=l.join(e,"Info.plist"),[r,a,i]=await Promise.all([nu(t,"CFBundleIdentifier"),nu(t,"CFBundleDisplayName"),nu(t,"CFBundleName")]);return{bundleId:r,appName:a??i}}async function nf(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await X.mkdtemp(l.join(ea.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await X.rm(r,{recursive:!0,force:!0})};try{await v("ditto",["-x","-k",e,r]);let i=l.join(r,"Payload"),n=(await X.readdir(i,{withFileTypes:!0}).catch(()=>{throw new k("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:l.join(i,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===n.length)return{installPath:n[0].installPath,cleanup:a};if(0===n.length)throw new k("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await nm(n);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 k("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${t}" by name. Use a bundle id hint instead.`);if(t.includes(".")){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(1===t.length)return t[0]}}(n,o);if(e)return{installPath:e.installPath,cleanup:a};throw new k("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload and none matched "${o}". Available bundles: ${n.map(nh).join(", ")}`)}throw new k("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${n.map(nh).join(", ")}`)}catch(e){throw await a(),e}}async function nm(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await np(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function nh(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function nw(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let ng="agent-device-macos-helper",nv="AGENT_DEVICE_MACOS_HELPER_BIN",ny=l.join(ea.homedir(),".agent-device","macos-helper","current"),nI=l.join(ny,"manifest.json"),nA=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function nb(e){let t=e.trim();if(!nA.test(t))throw new k("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function nS(){return function(e){let t=l.dirname(e);for(;;){let e=l.join(t,"macos-helper");if(f(l.join(e,"Package.swift")))return e;let r=l.dirname(t);if(r===t)break;t=r}throw new k("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(R(import.meta.url))}async function n_(e){let t=await X.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let r=l.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await n_(r):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[r]:[]}))).flat().sort()}async function nN(e){let t=await n_(e),r=$("sha256");for(let a of t)r.update(l.relative(e,a)),r.update("\0"),r.update(await X.readFile(a)),r.update("\0");let a=await v("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 nD(){try{let e=JSON.parse(await X.readFile(nI,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function nx(){let e=process.env[nv]?.trim();if(e)return e;let t=nS(),r=await nN(t),a=l.join(ny,ng);try{if(await nD()===r)return await X.access(a),a}catch{}let i=l.join(nS(),".build","release",ng);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await v("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await X.mkdir(ny,{recursive:!0});let n=`${a}.tmp`;return await X.copyFile(i,n),await X.rename(n,a),await X.chmod(a,493),await X.writeFile(nI,`${JSON.stringify({fingerprint:r},null,2)}
|
|
21
|
+
`,"utf8"),a}async function nk(e){let t=process.env[nv]?.trim();if("darwin"!==process.platform&&!t)throw new k("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let r=await nx(),a=await v(r,e,{allowFailure:!0,timeoutMs:3e4}),i=a.stdout.trim(),n=null;if(i)try{n=JSON.parse(i)}catch{n=null}if(0===a.exitCode&&n?.ok)return n.data;throw new k("COMMAND_FAILED",n&&!n.ok?n.error?.message??`macOS helper exited with code ${a.exitCode}`:i||a.stderr.trim()||`macOS helper exited with code ${a.exitCode}`,{helperPath:r,args:e,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,...n&&!n.ok?n.error?.details:{}})}async function nM(){return await nk(["app","frontmost"])}async function nE(e){return await nk(["app","quit","--bundle-id",nb(e)])}async function nO(e,t){return await nk(["permission",e,t])}async function nL(e,t={}){let r=["alert",e];return t.bundleId&&r.push("--bundle-id",nb(t.bundleId)),t.surface&&r.push("--surface",t.surface),await nk(r)}async function nC(e){return await nk(["snapshot","--surface",e])}async function nP(e,t,r={}){let a=["read","--x",String(e),"--y",String(t)];return r.bundleId&&a.push("--bundle-id",nb(r.bundleId)),r.surface&&a.push("--surface",r.surface),await nk(a)}let nR={settings:"com.apple.systempreferences"},nT=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function n$(e,t){let r=["-b",e];return t&&r.push(t),r}async function nF(e){for(let t of[l.join(e,"Contents","Info.plist"),l.join(e,"Info.plist")]){let[e,r,a]=await Promise.all([nu(t,"CFBundleIdentifier"),nu(t,"CFBundleDisplayName"),nu(t,"CFBundleName")]);if(e||r||a)return{bundleId:e,appName:r??a}}return{}}async function nU(e){let t=e.trim(),r=nR[t.toLowerCase()];if(r)return r;let a=(await nW("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new k("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});if(nT.test(t))return t;throw new k("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function nV(e,t,r){let a=r?.url?.trim();if(a){if(!rZ(a))throw new k("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await nU(t);await v("open",n$(e,a));return}let i=t.trim();if(rZ(i))return void await v("open",[i]);let n=r?.appBundleId??await nU(i);await v("open",n$(n))}async function nG(e,t){let r=await nU(t),a=await nE(r);if(a.running&&!a.terminated&&!a.forceTerminated)throw new k("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:r,running:a.running,terminated:a.terminated,forceTerminated:a.forceTerminated})}async function nj(){let e=await v("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new k("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 nB(e){let t=await v("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new k("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function nq(){let e=await v("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new k("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 k("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function nH(e){let t=ij(e),r="toggle"===t?!await nq():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${r?"true":"false"}`,i=await v("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new k("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function nW(e="all"){let t=["/Applications","/System/Applications",l.join(ea.homedir(),"Applications")],r=new Set;for(let e of t){let t=await X.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await v("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 nw((await Promise.all(Array.from(r).map(async e=>{let t=await nF(e).catch(()=>({})),r=t.bundleId;return r?{bundleId:r,name:t.appName??l.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let nz=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],nJ={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"},nK={1:"searching",2:"failed",3:"active"},nX={0:"notSupported",1:"searching",2:"failed",3:"active"};function nY(e,t,r){return v("xcrun",eq(e,t),r)}async function nZ(e){let t=null,r=!1;try{t=await n0(e),r=!0}catch(t){n3(e,"snapshot_failed",t)}try{await n1(e),await n2(e,nz)}catch(t){n3(e,"prepare_failed",t)}return async()=>{await nQ(e,r?t:null)}}async function nQ(e,t){var r,a;let i;await n1(e),t&&await n2(e,(i=[],(r=t).dataNetwork&&i.push("--dataNetwork",r.dataNetwork),r.wifiMode&&i.push("--wifiMode",r.wifiMode),void 0!==r.wifiBars&&("wifi"===r.dataNetwork||r.wifiMode)&&i.push("--wifiBars",r.wifiBars),r.cellularMode&&i.push("--cellularMode",r.cellularMode),void 0!==r.cellularBars&&(r.cellularMode||(a=r.dataNetwork)&&"hide"!==a&&"wifi"!==a||void 0!==r.operatorName)&&i.push("--cellularBars",r.cellularBars),void 0!==r.operatorName&&i.push("--operatorName",r.operatorName),i))}async function n0(e){let t=await nY(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new k("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=nJ[r];if(!a)throw new k("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=nK[Number(a[1])];e&&(t.wifiMode=e),t.wifiBars=a[2];continue}let i=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(r);if(i){let e=Number(i[1]),r=nX[e];if(!r)throw new k("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=r,t.cellularBars=i[2];continue}let n=/^Operator Name:\s*(.*)$/.exec(r);if(n){t.operatorName=n[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function n1(e){await nY(e,["status_bar",e.id,"clear"])}async function n2(e,t){0!==t.length&&await nY(e,["status_bar",e.id,"override",...t])}function n3(e,t,r){J({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof k))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 n4(e,t,r){return v("xcrun",eq(e,t),r)}async function n8(e,t,r){if("macos"===e.platform)return void await n9(e,t,r);if("simulator"===e.kind)return void await n5(e,t,r);try{await i7(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof k)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=`${e.message}
|
|
22
22
|
${r}
|
|
23
|
-
${a}`.toLowerCase();return i.includes("unknown option '--device'")||i.includes("unknown subcommand")&&i.includes("screenshot")||i.includes("unrecognized subcommand")&&i.includes("screenshot")}(t))throw t;
|
|
23
|
+
${a}`.toLowerCase();return i.includes("unknown option '--device'")||i.includes("unknown subcommand")&&i.includes("screenshot")||i.includes("unrecognized subcommand")&&i.includes("screenshot")}(t))throw t;or(e,"devicectl_screenshot",t)}await n9(e,t,r)}async function n5(e,t,r){if("simulator"!==e.kind)throw new k("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");await ns(e);let a=async()=>{};try{a=await nZ(e)}catch(t){oa(e,"prepare_failed",t)}try{try{await n6(e,t);return}catch(t){if(!on(t))throw t;or(e,"simctl_screenshot",t)}await n9(e,t,r)}finally{await a().catch(t=>oa(e,"restore_failed",t))}}async function n6(e,t){let r=ef.fromTimeoutMs(i6);await no(),await em(async({attempt:r,deadline:a})=>{r>1&&await no(),await n4(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,a?.remainingMs()??i6)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>on(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function n9(e,t,r){let a=(await tF(e,{command:"screenshot",appBundleId:r})).message;if(!a)throw new k("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await X.copyFile(a,t):"simulator"===e.kind?await oe(e,a,t):await n7(e,a,t)}async function n7(e,t,r){let a=ef.fromTimeoutMs(i9),i={exitCode:1,stdout:"",stderr:""};for(let n of tc)if(0===(i=await v("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",n],{allowFailure:!0,timeoutMs:ot(a,i9,"runner screenshot copy")})).exitCode)return;let n=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new k("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}async function oe(e,t,r){let a=ef.fromTimeoutMs(i9),i="Unable to locate runner container for simulator screenshot";for(let n of tc){let o=await n4(e,["get_app_container",e.id,n,"data"],{allowFailure:!0,timeoutMs:ot(a,i9,"runner screenshot container lookup")});if(0!==o.exitCode){let e=o.stderr.trim();e&&(i=e);continue}let s=o.stdout.trim();if(!s){i="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=l.resolve(e),a=t.trim();if(!a)return[];let i=[],n=new Set,o=e=>{let t=l.normalize(e);n.has(t)||(n.add(t),i.push(t))},s=a.replace(/^\/+/,""),d=s.replace(/\\/g,"/");if(s&&o(l.join(r,s)),l.isAbsolute(a)&&o(l.normalize(a)),d.startsWith("tmp/"))o(l.join(r,d));else{let e=d.lastIndexOf("/tmp/");if(e>=0){let t=d.slice(e+1);o(l.join(r,t))}}let u=l.basename(a);return u&&o(l.join(r,"tmp",u)),i}(s,t))try{await X.copyFile(e,r);return}catch(e){i=e instanceof Error?e.message:String(e)}}throw new k("COMMAND_FAILED",`Failed to capture iOS screenshot: ${i}`)}function ot(e,t,r){let a=e.remainingMs();if(a>0)return a;throw new k("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function or(e,t,r){let a=oi(r);J({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function oa(e,t,r){J({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...oi(r)}})}function oi(e){if(!(e instanceof k))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 on(e){if(!(e instanceof k)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",n=`${e.message}
|
|
24
24
|
${r}
|
|
25
25
|
${a}
|
|
26
|
-
${i}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")||n.includes("timed out")&&n.includes("screenshot")}let
|
|
27
|
-
${n}`.toLowerCase()))throw new
|
|
28
|
-
${a.stderr}`.toLowerCase()))throw new
|
|
29
|
-
`,"utf8"),await
|
|
30
|
-
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new
|
|
31
|
-
${i.stderr}`);if(0===n.size)throw new
|
|
32
|
-
${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new _("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new _("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function oN(e,t){await nt(e),await ne();let r=0,a=eo.fromTimeoutMs(iY);try{await es(async({deadline:r})=>{var a;if(r?.isExpired())throw new _("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:iY});let i=(a=["launch",e.id,t],e$(e,a)),n=await w("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new _("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!i6(e)&&(r+=1)<3},{deadline:a})}catch(r){if(i6(r)){var i;let a=(i=await i9(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function oD(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await i2(a,{action:"launch iOS app",deviceId:e.id})}function oE(e){return e?.clickButton??"primary"}function ok(e){return"primary"===e.button?null:"click"!==e.commandLabel?new _("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new _("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new _("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 _("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let oM=/^[A-Za-z0-9_.:-]{1,64}$/,ox=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function oO(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new _("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function oL(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await oC(t)}async function oC(e){await new Promise(t=>setTimeout(t,e))}function oP(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new _("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!J.statSync(n).isFile())throw new _("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof _)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new _("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new _("COMMAND_FAILED",`Unable to read ${a} file: ${n}`,{cause:String(t)})}if((r=i.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:i};throw new _("INVALID_ARGS",`${a} file not found: ${n}`)}async function oR(e){let t=oP(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await oT(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new _("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof _)throw t;throw new _("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function oT(e){try{return await j.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new _("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new _("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new _("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new _("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let o$=ek(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),oF=/^(iphone|ipad|ipod|appletv)/i,oU=/^appletv/i,oV=["apple tv","appletv","tvos"];function oG(e){return(e??"").trim().toLowerCase()}function oB(e){return oG(e.hardwareProperties?.platform)}function oj(e){return e.includes("tvos")}function oq(e){return oj(oG(e))?"tv":"mobile"}function oH(e){let t=oG(e);return t.includes("ios")||t.includes("tvos")}function oW(e){let t=oG(e);return oV.some(e=>t.includes(e))}function oz(e){return oF.test(e.trim())}function oJ(e){return oU.test(e.trim())}function oX(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function oK(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}function oY(e){return oj(oB(e))||oJ(oK(e))||oX(e).some(oW)?"tv":"mobile"}function oZ(e){let t=oB(e);return!!(t.includes("ios")||t.includes("tvos")||oz(oK(e)))||oX(e).some(oW)}async function oQ(e={}){let t,r,a=eC(e.simulatorSetPath),i=e.target;try{t=await w("xcrun",eT(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!oH(e))continue;let r=oq(e);if(!i||r===i)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...a?{simulatorSetPath:a}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function o0(e={}){if("darwin"!==process.platform)throw new _("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await E("xcrun"))throw new _("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eC(e.simulatorSetPath),a=await w("xcrun",eT(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(oH(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:oq(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new _("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(t.push({platform:"macos",id:"host-macos-local",name:K.hostname(),kind:"device",target:"desktop",booted:!0}),r)return t;let i=null;try{i=s.join(K.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await w("xcrun",["devicectl","list","devices","--json-output",i],{allowFailure:!0,timeoutMs:o$});if(0!==e.exitCode)return t;let r=await j.readFile(i,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(oZ(e)){let r=e.hardwareProperties?.udid??e.identifier??"",a=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:a,kind:"device",target:oY(e),booted:!0})}}catch{}finally{i&&await j.rm(i,{force:!0}).catch(()=>{})}return t}async function o1(e,t,r,a){let i,n=!!(t.udid||t.serial||t.deviceName);try{i=await a.resolveDevice(e,t,r)}catch(e){if(n||!(e instanceof _)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!n&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!i||"device"===i.kind)){let e=await a.findBootableSimulator({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(i)return i;throw new _("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function o2(e){let t=e.platform,r=e3({simulatorSetPath:eC(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=eR(e.androidDeviceAllowlist);return await U("resolve_target_device",async()=>{let i={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(i.target&&!i.platform)throw new _("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await rT();let e=await r2({serialAllowlist:a});return await e4(e,i)}if(i.platform){let e=await o0({simulatorSetPath:r});return await o1(e,i,{simulatorSetPath:r},{resolveDevice:e4,findBootableSimulator:oQ})}let n=[];try{n.push(...await r2({serialAllowlist:a}))}catch{}try{n.push(...await o0({simulatorSetPath:r}))}catch{}return await e4(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function o3(e,t,r,a,i){let n=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>aG(e,t,r?.activity),openDevice:()=>aH(e),close:t=>aW(e,t),tap:(t,r)=>is(e,t,r),doubleTap:async(t,r)=>{await is(e,t,r),await is(e,t,r)},swipe:(t,r,a,i,n)=>il(e,t,r,a,i,n),longPress:(t,r,a)=>ip(e,t,r,a),focus:(t,r)=>ih(e,t,r),type:t=>im(e,t),fill:(t,r,a)=>iw(e,t,r,a),scroll:(t,r)=>ig(e,t,r),scrollIntoView:t=>iv(e,t),screenshot:(t,r)=>iH(e,t),back:()=>id(e),home:()=>iu(e),appSwitcher:()=>ic(e),readClipboard:()=>ik(e),writeClipboard:t=>iM(e,t),setSetting:(t,r,a,i)=>iR(e,t,r,a,i)};case"ios":case"macos":{var r,a;let i,n,{overrides:o,runnerOpts:s}=(r=e,i={verbose:(a=t).verbose,logPath:a.logPath,traceLogPath:a.traceLogPath,requestId:a.requestId},n=()=>{if(ev(a.requestId))throw eA()},{runnerOpts:i,overrides:{tap:async(e,t)=>await tE(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),doubleTap:async(e,t)=>await tE(r,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:a.appBundleId},i),swipe:async(e,t,n,o,s)=>await tE(r,{command:"drag",x:e,y:t,x2:n,y2:o,durationMs:s,appBundleId:a.appBundleId},i),longPress:async(e,t,n)=>await tE(r,{command:"longPress",x:e,y:t,durationMs:n,appBundleId:a.appBundleId},i),focus:async(e,t)=>await tE(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),type:async e=>{await tE(r,{command:"type",text:e,appBundleId:a.appBundleId},i)},fill:async(e,t,n)=>{let o=await tE(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i);return await tE(r,{command:"type",text:n,clearFirst:!0,appBundleId:a.appBundleId},i),o},scroll:async(e,t)=>{if(!["up","down","left","right"].includes(e))throw new _("INVALID_ARGS",`Unknown direction: ${e}`);let n=function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left"}}(e);return await tE(r,{command:"swipe",direction:n,appBundleId:a.appBundleId},i)},scrollIntoView:async e=>{let t=await tE(r,{command:"findText",text:e,appBundleId:a.appBundleId},i);if(t?.found)return{attempts:1};for(let t=0;t<12;t+=1){for(let e=0;e<4;e+=1)n(),await tE(r,{command:"swipe",direction:"up",appBundleId:a.appBundleId},i),await new Promise(e=>setTimeout(e,80));n();let o=await tE(r,{command:"findText",text:e,appBundleId:a.appBundleId},i);if(o?.found)return{attempts:t+2}}throw new _("COMMAND_FAILED",`scrollintoview could not find text: ${e}`)}}});return{open:(t,r)=>on(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>oo(e),close:t=>os(e,t),screenshot:(t,r)=>nQ(e,t,r),back:async()=>{await tE(e,{command:"back",appBundleId:t.appBundleId},s)},home:async()=>{await tE(e,{command:"home",appBundleId:t.appBundleId},s)},appSwitcher:async()=>{await tE(e,{command:"appSwitcher",appBundleId:t.appBundleId},s)},readClipboard:()=>op(e),writeClipboard:t=>of(e,t),setSetting:(t,r,a,i)=>oh(e,t,r,a,i),...o}}default:throw new _("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,{requestId:i?.requestId,appBundleId:i?.appBundleId,verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath});return B({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await U("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new _("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await n.openDevice(),{app:null};if(void 0!==a){if("android"===e.platform)throw new _("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(rU(t))throw new _("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!rU(a))throw new _("INVALID_ARGS","open <app> <url> requires a valid URL target");return await n.open(t,{activity:i?.activity,appBundleId:i?.appBundleId,url:a}),{app:t,url:a}}return await n.open(t,{activity:i?.activity,appBundleId:i?.appBundleId}),{app:t}}case"close":{let e=r[0];if(!e)return{closed:"session"};return await n.close(e),{app:e}}case"press":{let t,[a,o]=r.map(Number);if(Number.isNaN(a)||Number.isNaN(o))throw new _("INVALID_ARGS","press requires x y");let s=oE(i);if("primary"!==s){let t=ok({commandLabel:"click",platform:e.platform,button:s,count:i?.count,intervalMs:i?.intervalMs,holdMs:i?.holdMs,jitterPx:i?.jitterPx,doubleTap:i?.doubleTap});if(t)throw t;return await tE(e,{command:"mouseClick",x:a,y:o,button:s,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{x:a,y:o,button:s}}let l=oO(i?.count??1,"count",1,200),d=oO(i?.intervalMs??0,"interval-ms",0,1e4),u=oO(i?.holdMs??0,"hold-ms",0,1e4),c=oO(i?.jitterPx??0,"jitter-px",0,100),p=i?.doubleTap===!0;if(p&&u>0)throw new _("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(p&&c>0)throw new _("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&l>1&&0===u&&0===c){let t=await tE(e,{command:"tapSeries",x:a,y:o,count:l,intervalMs:d,doubleTap:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x:a,y:o,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,timingMode:"runner-series",...t}}return await oL(l,d,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=ox[e%ox.length];return[r*t,a*t]}(e,c),s=a+r,l=o+i;if(p){t??=await n.doubleTap(s,l)??void 0;return}u>0?t??=await n.longPress(s,l,u)??void 0:t??=await n.tap(s,l)??void 0}),{x:a,y:o,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,...t}}case"swipe":{let t=Number(r[0]),a=Number(r[1]),o=Number(r[2]),s=Number(r[3]);if([t,a,o,s].some(Number.isNaN))throw new _("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=oO(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=oO(i?.count??1,"count",1,200),c=oO(i?.pauseMs??0,"pause-ms",0,1e4),p=i?.pattern??"one-way";if("one-way"!==p&&"ping-pong"!==p)throw new _("INVALID_ARGS",`Invalid pattern: ${p}`);if(("ios"===e.platform||"macos"===e.platform)&&u>1){let r=await tE(e,{command:"dragSeries",x:t,y:a,x2:o,y2:s,durationMs:d,count:u,pauseMs:c,pattern:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x1:t,y1:a,x2:o,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:p,...r}}return await oL(u,c,async e=>{"ping-pong"===p&&e%2==1?await n.swipe(o,s,t,a,d):await n.swipe(t,a,o,s,d)}),{x1:t,y1:a,x2:o,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:p}}case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new _("INVALID_ARGS","longpress requires x y [durationMs]");return await n.longPress(e,t,a),{x:e,y:t,durationMs:a}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new _("INVALID_ARGS","focus requires x y");return await n.focus(e,t),{x:e,y:t}}case"type":{let e=r.join(" ");if(!e)throw new _("INVALID_ARGS","type requires text");return await n.type(e),{text:e}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new _("INVALID_ARGS","fill requires x y text");return await n.fill(e,t,a),{x:e,y:t,text:a}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0;if(!e)throw new _("INVALID_ARGS","scroll requires direction");let a=await n.scroll(e,t);return{direction:e,amount:t,...a}}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new _("INVALID_ARGS","scrollintoview requires text");let t=await n.scrollIntoView(e);if(t?.attempts)return{text:e,attempts:t.attempts};return{text:e}}case"pinch":{if("android"===e.platform)throw new _("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");let t=Number(r[0]),a=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new _("INVALID_ARGS","pinch requires scale > 0");return await tE(e,{command:"pinch",scale:t,x:a,y:n,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{scale:t,x:a,y:n}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new _("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oM.test(t))throw new _("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 _("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 _("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 _("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof _)throw t;throw new _("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),o=function(e,t,r){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new _("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new _("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await n.open(o,{appBundleId:i?.appBundleId}),{event:t,eventUrl:o,transport:"deep-link"}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await j.mkdir(s.dirname(e),{recursive:!0}),await n.screenshot(e,i?.appBundleId),{path:e}}case"back":return await n.back(),{action:"back"};case"home":return await n.home(),{action:"home"};case"app-switcher":return await n.appSwitcher(),{action:"app-switcher"};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new _("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new _("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await n.readClipboard()}}if(r.length<2)throw new _("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await n.writeClipboard(t),{action:e,textLength:Array.from(t).length}}case"keyboard":{if("android"!==e.platform)throw new _("UNSUPPORTED_OPERATION","keyboard is currently supported only on Android");let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new _("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new _("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("dismiss"===t){let t=await iE(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let a=await iD(e);return{platform:"android",action:"status",visible:a.visible,inputType:a.inputType,type:a.type}}case"settings":{let[t,a,o,s,l]=r,d="permission"===t?{permissionTarget:o,permissionMode:s}:void 0;B({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:o,mode:s,platform:e.platform}});let u=await n.setSetting(t,a,l??i?.appBundleId,d);return u&&"object"==typeof u?{setting:t,state:a,...u}:{setting:t,state:a}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new _("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await oR(a);if("ios"===e.platform)return await om(e,t,i),{platform:"ios",bundleId:t};let n=await iB(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount}}case"snapshot":{if("android"!==e.platform){let t=await U("snapshot_capture",async()=>await tE(e,{command:"snapshot",appBundleId:i?.appBundleId,interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new _("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await U("snapshot_capture",async()=>await it(e,{interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}case"read":{let[t,a]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(a))throw new _("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await i_(e,t,a)??""};if("macos"===e.platform&&i?.surface&&"app"!==i.surface)return{action:"read",text:(await nk(t,a,{bundleId:i.appBundleId,surface:i.surface})).text};let n=await tE(e,{command:"readText",x:t,y:a,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{action:"read",text:"string"==typeof n.text?n.text:"string"==typeof n.message?n.message:""}}default:throw new _("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}let o4=e=>"macos"!==e.platform,o8={alert:{apple:{simulator:!0,device:!0},android:{},supports:e=>"macos"===e.platform||"simulator"===e.kind},pinch:{apple:{simulator:!0},android:{}},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:o4},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:o4},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{},android:{emulator:!0,device:!0,unknown:!0}},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:o4},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:o4},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:o4},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:o4},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:o4},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function o5(e,t){let r=o8[e];if(!r)return!0;let a=e1(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function o6(e,t,r,a,i){return{requestId:i??$().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,count:t?.count,intervalMs:t?.intervalMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,doubleTap:t?.doubleTap,clickButton:oE(t),pauseMs:t?.pauseMs,pattern:t?.pattern}}let o9=ek(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function o7(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:nt}));await t(e);return}if("device"===e.kind)return void await se(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:ar}));await t(e.id)}}async function se(e){let t=s.join(K.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(o9/1e3));try{let a=await w("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:o9+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await st(t);if(0===a.exitCode){if(!o.parsed)throw new _("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new _("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 _("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:n,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sr(i,n)})}catch(t){if(t instanceof _&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),i=String(r.stderr??""),n=Number(r.timeoutMs??o9),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new _("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?sr(a,i):o},t)}throw new _("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 j.rm(t,{force:!0}).catch(()=>{})}}async function st(e){try{let t=await j.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof r?r:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sr(e,t){let r=i5(e,t);return r||(`${e}
|
|
33
|
-
${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":i8)}function sa(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function si(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function sn(e,t){return e.find(e=>e.ref===t)??null}function so(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function ss(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),a=(e.value??"").toLowerCase(),i=(e.identifier??"").toLowerCase();return t.includes(r)||a.includes(r)||i.includes(r)})??null}function sl(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&&sd(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||!sd(t))continue;let i=Math.abs(e.rect.y+e.rect.height/2-r);(!a||i<a.distance)&&(a={label:t,distance:i})}return a?.label}(e,t)??(r&&sd(r)?r:void 0)}function sd(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function su(e){let t=[],r=[];for(let a of e){let e=a.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let i=sc(a.type??""),n=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&sd(n);if(("group"===i||"ioscontentgroup"===i)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...a,depth:s})}return r}function sc(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 sp(e,t){let r=sc(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 sf(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let sm=new Set(["id","role","text","label","value"]),sh=new Set(["visible","hidden","editable","selected","enabled","hittable"]),sw=new Set([...sm,...sh]);function sg(e){let t=e.trim();if(!t)throw new _("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!sS(e,i)){a?a===n&&(a=null):a=n,r+=n;continue}if(!a&&"|"===n&&"|"===e[i+1]){let a=r.trim();if(!a)throw new _("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",i+=1;continue}r+=n}let i=r.trim();if(!i)throw new _("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(i),t}(t);if(0===r.length)throw new _("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new _("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!sS(e,i)){a?a===n&&(a=null):a=n,r+=n;continue}if(!a&&/\s/.test(n)){r.trim().length>0&&t.push(r.trim()),r="";continue}r+=n}if(a)throw new _("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim().length>0&&t.push(r.trim()),t}(t);if(0===r.length)throw new _("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(sy)}})(e))}}function sv(e){try{return sg(e)}catch{return null}}function sI(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,a=0,i=[];for(;a<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return sw.has(e)}return sw.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&sv(t)&&i.push(a)}if(0===i.length)return null;let n=i[i.length-1];if(r){for(let t=i.length-1;t>=0;t-=1)if(i[t]<e.length){n=i[t];break}}let o=e.slice(0,n).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(n)}:null}function sA(e){let t=e[0]??"",r=sI(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function sy(e){let t=e.trim();if(!t)throw new _("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!sh.has(r))throw new _("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),i=t.slice(r+1).trim();if(!sw.has(a))throw new _("INVALID_ARGS",`Unknown selector key: ${a}`);if(!i)throw new _("INVALID_ARGS",`Missing selector value for key: ${a}`);if(sh.has(a)){let e,t="true"===(e=sb(i).toLowerCase())||"false"!==e&&null;if(null===t)throw new _("INVALID_ARGS",`Invalid boolean value for ${a}: ${i}`);return{key:a,value:t}}return{key:a,value:sb(i)}}function sb(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function sS(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function s_(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return sE(e.identifier,String(t.value));case"role":var a,i;return a=e.type,i=String(t.value),function(e){return sc(e)}(a??"")===function(e){return sc(e)}(i);case"label":return sE(e.label,String(t.value));case"value":return sE(e.value,String(t.value));case"text":{let r=sk(String(t.value));return sk(sf(e))===r}case"visible":return sN(e)===!!t.value;case"hidden":return!sN(e)==!!t.value;case"editable":return sD(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 sN(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function sD(e,t){return sp(e.type??"",t)&&!1!==e.enabled}function sE(e,t){return sk(e??"")===sk(t)}function sk(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function sM(e,t,r){let a=r.requireRect??!1,i=r.requireUnique??!0,n=r.disambiguateAmbiguous??!1,o=[];for(let s=0;s<t.selectors.length;s+=1){let l=t.selectors[s],d=function(e,t,r){let a=0,i=null,n=null,o=!1;for(let s of e){if(r.requireRect&&!s.rect||!s_(s,t,r.platform))continue;if(a+=1,i||(i=s),!n){n=s;continue}let e=function(e,t){let r=e.depth??0,a=t.depth??0;if(r!==a)return r>a?1:-1;let i=sL(e),n=sL(t);return i!==n?i<n?1:-1:0}(s,n);if(e>0){n=s,o=!1;continue}0===e&&(o=!0)}return{count:a,firstNode:i,disambiguated:o?null:n}}(e,l,{platform:r.platform,requireRect:a});if(o.push({selector:l.raw,matches:d.count}),0!==d.count&&d.firstNode){if(i&&1!==d.count){if(!n)continue;let e=d.disambiguated;if(!e)continue;return{node:e,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}return{node:d.firstNode,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}}return null}function sx(e,t,r){let a=r.requireRect??!1,i=[];for(let n=0;n<t.selectors.length;n+=1){let o=t.selectors[n],s=function(e,t,r){let a=0;for(let i of e)(!r.requireRect||i.rect)&&s_(i,t,r.platform)&&(a+=1);return a}(e,o,{platform:r.platform,requireRect:a});if(i.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:n,selector:o,matches:s,diagnostics:i}}return null}function sO(e,t,r){let a=r.unique??!0;if(0===t.length)return`Selector did not match: ${e.raw}`;let i=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return a?`Selector did not resolve uniquely (${i})`:`Selector did not match (${i})`}function sL(e){return e.rect?e.rect.width*e.rect.height:1/0}function sC(e,t,r={}){let a=[],i=sc(e.type??""),n=sR(e.identifier),o=sR(e.label),s=sR(e.value),l=sR(sf(e)),d="fill"===r.action;n&&a.push(`id=${sP(n)}`),i&&o&&a.push(d?`role=${sP(i)} label=${sP(o)} editable=true`:`role=${sP(i)} label=${sP(o)}`),o&&a.push(d?`label=${sP(o)} editable=true`:`label=${sP(o)}`),s&&a.push(d?`value=${sP(s)} editable=true`:`value=${sP(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${sP(l)} editable=true`:`text=${sP(l)}`),i&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${sP(i)} editable=true`);let u=tx(a);return 0===u.length&&i&&u.push(d?`role=${sP(i)} editable=true`:`role=${sP(i)}`),0===u.length&&sN(e)&&u.push("visible=true"),u}function sP(e){return JSON.stringify(e)}function sR(e){if(!e)return null;let t=e.trim();return t||null}let sT=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),s$=/https?:\/\/[^\s"'<>\])]+/i,sF=[/\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 sU(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 sV(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return sG(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 sG(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function sB(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function sj(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}let sq="shared_prefs/ReactNativeDevPrefs.xml",sH="debug_http_host",sW="dev_server_https",sz="RCT_jsLocation",sJ="RCT_packager_scheme",sX="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.",sK='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function sY(e){return void 0!==sZ(e)}function sZ(e){if(!e)return;let t=le(e.metroHost),r=lr(e.metroPort),a="http",i=le(e.bundleUrl);if(i){var n;let e;try{e=new D(i)}catch(e){throw new _("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=le(e.hostname),r??=lr(e.port.length>0?Number(e.port):"https:"===(n=e.protocol)?443:"http:"===n?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function sQ(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=sZ(a);if(i){if("android"===t.platform)return void await s1(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await s8(t,r,i)}}async function s0(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await s2(t,r);"ios"===t.platform&&"simulator"===t.kind&&await s5(t,r)}}async function s1(e,t,r){var a,i,n,o,s,l;let d,u;lt(t);let c=(a=await s3(e,t),i=sH,n=`${r.host}:${r.port}`,d=` <string name="${la(i)}">${la(n)}</string>`,s9(s7(a,i),d));o=c,s=sW,l="https"===r.scheme,u=` <boolean name="${la(s)}" value="${l?"true":"false"}" />`,c=s9(s7(o,s),u),await s4(e,t,c)}async function s2(e,t){lt(t);let r=await s3(e,t),a=s7(r,sH),i=s7(a,sW);i!==r&&await s4(e,t,i)}async function s3(e,t){let r=await w("adb",rR(e,["shell","run-as",t,"cat",sq]),{allowFailure:!0});return 0!==r.exitCode?sK:s6(r.stdout)}async function s4(e,t,r){let a=rR(e,["shell","run-as",t,"id"]),i=await w("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=li(i.stdout,i.stderr);throw new _("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?sX:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await w("adb",rR(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await w("adb",rR(e,["shell","run-as",t,"tee",sq]),{stdin:r.trimEnd()})}catch(a){let e=y(a);if("TOOL_MISSING"===e.code)throw e;let r=li("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new _("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?sX:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function s8(e,t,r){await w("xcrun",e$(e,["spawn",e.id,"defaults","write",t,sz,"-string",`${r.host}:${r.port}`])),await w("xcrun",e$(e,["spawn",e.id,"defaults","write",t,sJ,"-string",r.scheme]))}async function s5(e,t){await w("xcrun",e$(e,["spawn",e.id,"defaults","delete",t,sz]),{allowFailure:!0}),await w("xcrun",e$(e,["spawn",e.id,"defaults","delete",t,sJ]),{allowFailure:!0})}function s6(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
34
|
-
`:
|
|
35
|
-
</map>`)}function
|
|
36
|
-
${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}function ln(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=sI(r?e.slice(0,-1):e.slice());return!a||a.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:a.selectorExpression,selectorTimeout:r?t:null}}function lo(e){return!!e&&!Number.isNaN(Number(e))}let ls=ek(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),ll=new Map;async function ld(e){let t=await n.mkdtemp(s.join(K.tmpdir(),"agent-device-materialized-"));try{let r=await lp(e.installablePath,s.join(t,"installable")),a=e.archivePath?await lp(e.archivePath,s.join(t,"archive")):void 0,i=h.randomUUID(),n=e.ttlMs??ls,o=Date.now()+n,l=setTimeout(()=>{lu(i)},n);return ll.set(i,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:o,timer:l}),{materializationId:i,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(o).toISOString()}}catch(e){throw await n.rm(t,{recursive:!0,force:!0}),e}}async function lu(e,t){let r=ll.get(e);if(!r)throw new _("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new _("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),ll.delete(e),await n.rm(r.rootPath,{recursive:!0,force:!0})}async function lc(e){let t=Array.from(ll.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await lu(e)}))}async function lp(e,t){let r=await n.stat(e);await n.mkdir(t,{recursive:!0});let a=s.join(t,s.basename(e));return r.isDirectory()?await n.cp(e,a,{recursive:!0}):await n.copyFile(e,a),a}async function lf(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 _("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await o7(e.session.device),e.session.device}if(!r)throw new _("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await o2(e.flags??{});return await o7(a),a}async function lm(e){let{req:t,sessionName:r,sessionStore:a,deps:i}=e,n=a.get(r);try{let e,o,s,l=(o=function(e){let t=e.meta?.installSource;if(!t)throw new _("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new _("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new _("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(s=t.meta?.uploadedArtifactId)&&"path"===o.kind?{source:{kind:"path",path:rr(s,t.meta?.tenantId)},cleanup:()=>{ra(s)}}:{source:o,cleanup:()=>{}}),d=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new _("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),u=await (i?.resolveInstallDevice??lf)({session:n,flags:t.flags});if(!o5("install",u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let c=(i?.getRequestSignal??eI)(t.meta?.requestId);if("ios"===u.platform){let e,o=i?.installIosInstallablePath??(await Promise.resolve().then(()=>({closeIosApp:os,ensureBootedSimulator:nt,installIosApp:od,installIosInstallablePath:oc,listIosApps:ow,listSimulatorApps:og,openIosApp:on,openIosDevice:oo,parseIosDeviceAppsPayload:i4,pushIosNotification:om,readIosClipboardText:op,reinstallIosApp:ou,resolveIosApp:oi,screenshotIos:nQ,setIosSetting:oh,uninstallIosApp:ol,writeIosClipboardText:of}))).installIosInstallablePath,s=i?.prepareIosInstallArtifact??(await Promise.resolve().then(()=>({prepareIosInstallArtifact:nn,readIosBundleInfo:no}))).prepareIosInstallArtifact,p=await s(l.source,{signal:c});try{if(d.enabled&&(e=await ld({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:d.ttlMs})),await o(u,p.installablePath),!p.bundleId)throw new _("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let i={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:p.bundleId,...p.appName?{appName:p.appName}:{},launchTarget:p.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}};return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:i}),{ok:!0,data:i}}catch(r){throw e&&await lu(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),l.cleanup()}}let p=i?.prepareAndroidInstallArtifact??(await Promise.resolve().then(()=>({prepareAndroidInstallArtifact:aE}))).prepareAndroidInstallArtifact,f=i?.installAndroidInstallablePathAndResolvePackageName??(await Promise.resolve().then(()=>({appSwitcherAndroid:ic,backAndroid:id,closeAndroidApp:aW,dismissAndroidKeyboard:iE,ensureAdb:rT,fillAndroid:iw,focusAndroid:ih,getAndroidAppState:aU,getAndroidKeyboardState:iD,getAndroidScreenSize:iI,homeAndroid:iu,inferAndroidAppName:aF,installAndroidApp:a3,installAndroidInstallablePath:a1,installAndroidInstallablePathAndResolvePackageName:a2,isAmStartError:aj,listAndroidApps:aP,longPressAndroid:ip,openAndroidApp:aG,openAndroidDevice:aH,parseAndroidLaunchComponent:aq,pressAndroid:is,pushAndroidNotification:iB,readAndroidClipboardText:ik,readAndroidTextAtPoint:i_,reinstallAndroidApp:a4,resolveAndroidApp:aC,screenshotAndroid:iH,scrollAndroid:ig,scrollIntoViewAndroid:iv,setAndroidSetting:iR,snapshotAndroid:it,swipeAndroid:il,typeAndroid:im,writeAndroidClipboardText:iM}))).installAndroidInstallablePathAndResolvePackageName,m=await p(l.source,{signal:c});try{d.enabled&&(e=await ld({archivePath:m.archivePath,installablePath:m.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:d.ttlMs}));let o=await f(u,m.installablePath,m.packageName);if(!o)throw new _("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let s=(i?.inferAndroidAppName??(await Promise.resolve().then(()=>({appSwitcherAndroid:ic,backAndroid:id,closeAndroidApp:aW,dismissAndroidKeyboard:iE,ensureAdb:rT,fillAndroid:iw,focusAndroid:ih,getAndroidAppState:aU,getAndroidKeyboardState:iD,getAndroidScreenSize:iI,homeAndroid:iu,inferAndroidAppName:aF,installAndroidApp:a3,installAndroidInstallablePath:a1,installAndroidInstallablePathAndResolvePackageName:a2,isAmStartError:aj,listAndroidApps:aP,longPressAndroid:ip,openAndroidApp:aG,openAndroidDevice:aH,parseAndroidLaunchComponent:aq,pressAndroid:is,pushAndroidNotification:iB,readAndroidClipboardText:ik,readAndroidTextAtPoint:i_,reinstallAndroidApp:a4,resolveAndroidApp:aC,screenshotAndroid:iH,scrollAndroid:ig,scrollIntoViewAndroid:iv,setAndroidSetting:iR,snapshotAndroid:it,swipeAndroid:il,typeAndroid:im,writeAndroidClipboardText:iM}))).inferAndroidAppName)(o),l={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:o,...s?{appName:s}:{},launchTarget:o,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}};return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:l}),{ok:!0,data:l}}catch(r){throw e&&await lu(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await m.cleanup(),l.cleanup()}}catch(e){return{ok:!1,error:C(e)}}}async function lh(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new _("INVALID_ARGS","release_materialized_paths requires a materializationId");return await lu(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:C(e)}}}async function lw(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new _("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await lg({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await lv({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lI(t,u),a=!0)}else t=(await lv({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lI(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function lg(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await w("xcrun",eT(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:iK});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||lA(a).includes(lA(r))){for(let e of i)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function lv(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await w("xcrun",eT(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new _("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(n.stdout??"").trim();if(!o)throw new _("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function lI(e,t){let r=await w("xcrun",eT(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:iK});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 lA(e){return e.toLowerCase().replace(/[._-]/g,"")}let ly=ek(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),lb=ek(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function lS(e,t,r){return t||l_(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function l_(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function lN(e){return"ios"===e.platform&&"simulator"===e.kind}async function lD(e,t){lN(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function lE(e){let t=l_(e.flags)||!e.session?await e.resolveTargetDeviceFn(e.flags??{}):await lk(e.session.device,e.resolveTargetDeviceFn);return!1!==e.ensureReady&&await e.ensureReadyFn(t),t}async function lk(e,t){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let r={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await t(r)}catch(e){if(!(e instanceof _)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await t({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function lM(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=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function lO(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function lL(e){let t=e?.trim();return t&&t.length>0?t:void 0}function lC(e,t){if(void 0!==e){if("string"!=typeof e)throw new _("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return lL(e)}}function lP(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new _("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function lR(e){if("ios"===e||"android"===e)return e}function lT(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new _("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!lx.includes(e));if(i)throw new _("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${lx.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new _("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new _("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:lC(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new _("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return lP(e)}}(t.metroPort),bundleUrl:lC(t.bundleUrl,"bundleUrl"),launchUrl:lC(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:lR(i.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let i=r?.platform,n=lR(i);if(a.platform&&r&&!n)throw new _("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new _("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&lO(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=y(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}async function l$(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i,clearRuntimeHints:n}=e;!t||!i?.appBundleId||!sY(r)||sY(a)||await n({device:i.device,appId:i.appBundleId})}async function lF(e){var t,r;let{req:a,sessionName:i,sessionStore:n,clearRuntimeHints:o=s0}=e,s=(a.positionals?.[0]??"show").toLowerCase(),l=n.get(i),d=n.getRuntimeHints(i);if(!["set","show","clear"].includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===s){sY(d)&&l?.appBundleId&&await o({device:l.device,appId:l.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===s)return{ok:!0,data:{session:i,configured:!!d,runtime:d}};let u=lR(a.flags?.platform??d?.platform??l?.device.platform);if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first."}};if(l&&l.device.platform!==u)return{ok:!1,error:{code:"INVALID_ARGS",message:`runtime set targets ${u}, but session "${i}" is already bound to ${l.device.platform}.`}};let c={platform:(t=a.flags,r={platform:u,metroHost:lL(t?.metroHost),metroPort:lP(t?.metroPort),bundleUrl:lL(t?.bundleUrl),launchUrl:lL(t?.launchUrl)}).platform??d?.platform,metroHost:r.metroHost??d?.metroHost,metroPort:r.metroPort??d?.metroPort,bundleUrl:r.bundleUrl??d?.bundleUrl,launchUrl:r.launchUrl??d?.launchUrl};return 0===lO(c)?{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."}}:(n.setRuntimeHints(i,c),{ok:!0,data:{session:i,configured:!0,runtime:c}})}async function lU(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return rU(t)?"macos"===e.platform?void 0:"device"===e.kind?rV(r,t):void 0:await lV(e,t)}async function lV(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:oi}));return await r(e,t)}catch{return}}async function lG(e,t){if(!("android"!==e.platform||!t||rU(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:aC})),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function lB(e,t,r,a){return await lU(e,t,r)??await a(e,t)??("android"===e.platform&&t&&rU(t)?r:void 0)}let lj="open-command-roundtrip",lq="Not implemented for this platform in this release.";function lH(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:i}=e;if("macos"===t.platform&&!r)return i??"app";if("macos"!==t.platform){if(r)throw new _("INVALID_ARGS","surface is only supported on macOS");return"app"}let n=r?o(r):"app";if("app"!==n&&a)throw new _("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}async function lW(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await nS();return{appBundleId:t.bundleId,appName:t.appName}}async function lz(e){let{device:t,closeTarget:r,stopIosRunner:a,dispatch:i,outFlag:n,context:o,settleSimulator:s}=e;"android"!==t.platform&&await a(t.id),await i(t,"close",[r],n,o),await s(t,ly)}async function lJ(e){let{runtime:t,device:r,dispatch:a,req:i,logPath:n,appBundleId:o,traceLogPath:s,openPositionals:l}=e,d=t?.launchUrl;if(!d||0===l.length||l.length>1)return;let u=l[0]?.trim();!u||rU(u)||await a(r,"open",[d],i.flags?.out,{...o6(n,i.flags,o,s)})}async function lX(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,dispatch:d,applyRuntimeHints:u,stopIosRunner:c,settleSimulator:p,openTarget:f,openPositionals:m,appName:h,surface:w,appBundleId:g,runtime:v,existingSession:I}=e,A=i.flags?.relaunch===!0,y=I?.trace?.outPath;if(A&&f){let e=g??f;await lz({device:l,closeTarget:e,stopIosRunner:c,dispatch:d,outFlag:i.flags?.out,context:{...o6(s,i.flags,g??I?.appBundleId,y)},settleSimulator:p})}await u({device:l,appId:g,runtime:v});let b=Date.now();await d(l,"open",m,i.flags?.out,{...o6(s,i.flags,g)}),await lJ({runtime:v,device:l,dispatch:d,req:i,logPath:s,appBundleId:g,traceLogPath:y,openPositionals:m});let S=f?{durationMs:Math.max(0,Date.now()-b),measuredAt:new Date().toISOString(),method:lj,appTarget:f,appBundleId:g}:void 0;await p(l,lb);let _=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:I,sessionName:n,device:l,surface:w,appBundleId:g,appName:h,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=v)&&(0===lO(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let N=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:i,startup:n,device:o,runtime:s}=e,l={session:t};return l.surface=i,r&&(l.appName=r),a&&(l.appBundleId=a),n&&(l.startup=n),s&&lO(s)>0&&(l.runtime=s),o&&(l.platform=o.platform,l.target=o.target??"mobile",l.device=o.name,l.id=o.id,l.kind=o.kind,"android"===o.platform&&(l.serial=o.id)),o?.platform==="ios"&&(l.device_udid=o.id,l.ios_simulator_device_set=o.simulatorSetPath??null),l}({sessionName:n,appName:h,appBundleId:g,surface:w,startup:S,device:l,runtime:v});return o.recordAction(_,{command:"open",positionals:m,flags:i.flags??{},runtime:void 0!==i.runtime?v:void 0,result:N}),o.set(n,_),{ok:!0,data:N}}async function lK(e){let t,{req:r,sessionName:a,logPath:i,sessionStore:n,dispatch:o,ensureReady:s,resolveDevice:l,applyRuntimeHints:d=sQ,clearRuntimeHints:u=s0,stopIosRunner:c=tA,settleSimulator:p=lD,resolveAndroidPackageForOpen:f=lG}=e,m=r.flags?.relaunch===!0;if(n.has(a)){let e,t=n.get(a);if(!t)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:`Session "${a}" not found.`}};let h=r.positionals?.[0],w=h??(m?t.appName:void 0);try{e=lH({device:t.device,surfaceFlag:r.flags?.surface,openTarget:w,existingSurface:t.surface})}catch(e){return{ok:!1,error:{code:e instanceof _?e.code:"INVALID_ARGS",message:String(e.message)}}}if(!t||!w&&"app"===e)return m?{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app name or an active session app."}}:{ok:!1,error:{code:"INVALID_ARGS",message:"Session already active. Close it first or pass a new --session name."}};if(m&&rU(w))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};if(m&&"app"!==e)return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch is supported only for app surfaces."}};if(m&&"android"===t.device.platform&&"binary"===an(w))return{ok:!1,error:{code:"INVALID_ARGS",message:ao(w)}};let g=await lk(t.device,l);await s(g);let v=await lW(e),I=v.appBundleId??await lB(g,w,t.appBundleId,f),A=v.appName??w,y=lT({req:r,sessionStore:n,sessionName:a,device:g});if(!y.ok)return y.response;let{runtime:b,previousRuntime:S,replacedStoredRuntime:N}=y.data;await l$({replacedStoredRuntime:N,previousRuntime:S,runtime:b,session:t,clearRuntimeHints:u});let D=h?r.positionals??[]:w?[w]:[];return await lX({req:r,sessionName:a,sessionStore:n,logPath:i,device:g,dispatch:o,applyRuntimeHints:d,stopIosRunner:c,settleSimulator:p,openTarget:w,openPositionals:D,appName:A,surface:e,appBundleId:I,runtime:b,existingSession:t})}let h=r.positionals?.[0];if(m&&!h)return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app argument."}};if(m&&h&&rU(h))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};let w=await l(r.flags??{});try{t=lH({device:w,surfaceFlag:r.flags?.surface,openTarget:h})}catch(e){return{ok:!1,error:{code:e instanceof _?e.code:"INVALID_ARGS",message:String(e.message)}}}if(m&&"app"!==t)return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch is supported only for app surfaces."}};if(m&&"android"===w.platform&&h&&"binary"===an(h))return{ok:!1,error:{code:"INVALID_ARGS",message:ao(h)}};let g=n.toArray().find(e=>e.device.id===w.id);if(g)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${g.name}".`,details:{session:g.name,deviceId:w.id,deviceName:w.name}}};await s(w);let v=await lW(t),I=v.appBundleId??await lB(w,h,void 0,f),A=v.appName??h,y=lT({req:r,sessionStore:n,sessionName:a,device:w});if(!y.ok)return y.response;let{runtime:b}=y.data;return await lX({req:r,sessionName:a,sessionStore:n,logPath:i,device:w,dispatch:o,applyRuntimeHints:d,stopIosRunner:c,settleSimulator:p,openTarget:h,openPositionals:r.positionals??[],appName:A,surface:t,appBundleId:I,runtime:b})}async function lY(e){let t=await w("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 lZ(e){let{device:t,shutdownRequested:r,shutdownSimulator:a,shutdownAndroidEmulator:i}=e;if(r&&(lN(t)||"android"===t.platform&&"emulator"===t.kind))try{return lN(t)?await a(t):await i(t)}catch(t){let e=C(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function lQ(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n,stopIosRunner:o=tA,clearRuntimeHints:s=s0,settleSimulator:l=lD,shutdownSimulator:d=nr,shutdownAndroidEmulator:u=lY,appLogOps:c}=e,p=i.get(r);if(!p)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};p.appLog&&await c.stop(p.appLog),t.positionals&&t.positionals.length>0&&("ios"===p.device.platform&&await o(p.device.id),await n(p.device,"close",t.positionals,t.flags?.out,{...o6(a,t.flags,p.appBundleId,p.trace?.outPath)}),await l(p.device,ly)),"ios"===p.device.platform&&await o(p.device.id),sY(i.getRuntimeHints(r))&&p.appBundleId&&await s({device:p.device,appId:p.appBundleId}).catch(()=>{}),i.recordAction(p,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r}}),t.flags?.saveScript&&(p.recordSession=!0),i.writeSessionLog(p),await lc(r).catch(()=>{}),i.delete(r);let f=await lZ({device:p.device,shutdownRequested:t.flags?.shutdown,shutdownSimulator:d,shutdownAndroidEmulator:u});return f?{ok:!0,data:{session:r,shutdown:f}}:{ok:!0,data:{session:r}}}let l0={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve().then(()=>({reinstallIosApp:ou}));return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve().then(()=>({reinstallAndroidApp:a4}));return await a(e,t,r)}},l1={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve().then(()=>({installIosApp:od})),i=await a(e,r,{appIdentifierHint:t});return{bundleId:i.bundleId,appName:i.appName,launchTarget:i.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await Promise.resolve().then(()=>({installAndroidApp:a3})),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function l2(e){let{req:t,command:r,sessionName:a,sessionStore:i,ensureReady:n,resolveDevice:o,deployOps:s}=e,l=i.get(a),d=t.flags??{},u=lS(r,l,d);if(u)return u;let c=t.positionals?.[0]?.trim(),p=t.positionals?.[1]?.trim();if(!c||!p)return{ok:!1,error:{code:"INVALID_ARGS",message:`${r} requires: ${r} <app> <path-to-app-binary>`}};let f=t.meta?.uploadedArtifactId;try{let e,a=f?rr(f,t.meta?.tenantId):tq.expandHome(p);if(!J.existsSync(a))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${a}`}};let u=await lE({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!1});if(!o5(r,u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${r} is not supported on this device`}};if("ios"===u.platform){let t=await s.ios(u,c,a),r=t.bundleId;e=r?{app:c,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await s.android(u,c,a),r=t.package;e=r?{app:c,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}return l&&i.recordAction(l,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:e}),{ok:!0,data:e}}finally{f&&ra(f)}}let l3=["platform","target","device","udid","serial","verbose","out"];async function l4(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${a}.`}};let i=e.flags?.batchMaxSteps??q;if(!Number.isInteger(i)||i<1||i>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let a=g(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await l8(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=y(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function l8(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{},o=e??{};for(let e of l3)void 0===n[e]&&void 0!==o[e]&&(n[e]=o[e]);return n}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}let l5='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',l6='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").',l9=["platform","target","device","udid","serial","verbose","out"],l7=["path","start","stop","doctor","mark","clear"],de=`logs requires ${l7.slice(0,-1).join(", ")}, or ${l7.at(-1)}`,dt=["dump","log"],dr=`network requires ${dt.join(" or ")}`,da=["summary","headers","body","all"],di=`network include mode must be one of: ${da.join(", ")}`,dn=async({avdName:e,serial:t,headless:r})=>{let{ensureAndroidEmulatorBooted:a}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:ae}));return await a({avdName:e,serial:t,headless:r})};async function ds(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:n,resolveDevice:o,dispatch:s,command:l,positionals:d,recordPositionals:u,deriveNextSession:c}=e,p=i.get(r),f=t.flags??{},m=lS(l,p,f);if(m)return m;let h=await lE({session:p,flags:f,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!o5(l,h))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${l} is not supported on this device`}};let w=await s(h,l,d,t.flags?.out,{...o6(a,t.flags,p?.appBundleId,p?.trace?.outPath)});if(p){let e=c?await c(p,w,h):p;i.recordAction(e,{command:l,positionals:u??d,flags:t.flags??{},result:w??{}}),e!==p&&i.set(r,e)}return{ok:!0,data:w??{}}}function dl(e){return e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"}async function dd(e){let{req:t,sessionName:r,sessionStore:a,ensureReady:i,resolveDevice:n}=e,o=a.get(r),s=t.flags??{},l=s.platform;if(!o&&"string"==typeof s?.session&&s.session.trim().length>0)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"ios"===l?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`}};let d=lS("appstate",o,s);if(d)return d;let u=(o?.device.platform==="ios"||o?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!l_(e))return!0;let r=e?.platform;return!(r&&!e2(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(s,o);if("ios"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l5}};if("macos"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l6}};if(u&&o){let e=o.appName??o.appBundleId;if(!o.appName&&!o.appBundleId){if("macos"===o.device.platform&&o.surface&&"app"!==o.surface&&"frontmost-app"!==o.surface)return{ok:!0,data:{platform:o.device.platform,appName:o.surface,appBundleId:o.appBundleId,source:"session",surface:o.surface}};let e="macos"===o.device.platform?"macOS":"iOS";return{ok:!1,error:{code:"COMMAND_FAILED",message:`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`}}}return{ok:!0,data:{platform:o.device.platform,appName:e??"unknown",appBundleId:o.appBundleId,source:"session",surface:o.surface??"app",..."ios"===o.device.platform?{device_udid:o.device.id,ios_simulator_device_set:o.device.simulatorSetPath??null}:{}}}}let c=await lE({session:o,flags:s,ensureReadyFn:i,resolveTargetDeviceFn:n,ensureReady:!0});if("ios"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l5}};if("macos"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l6}};let{getAndroidAppState:p}=await Promise.resolve().then(()=>({getAndroidAppState:aU})),f=await p(c);return{ok:!0,data:{platform:"android",package:f.package,activity:f.activity}}}async function du(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:n,resolveDevice:o,dispatch:s}=e,l=i.get(r),d=t.flags??{},u=lS("clipboard",l,d);if(u)return u;let c=(t.positionals?.[0]??"").toLowerCase();if("read"!==c&&"write"!==c)return{ok:!1,error:{code:"INVALID_ARGS",message:"clipboard requires a subcommand: read or write"}};let p=await lE({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!o5("clipboard",p))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let f=await s(p,"clipboard",t.positionals??[],t.flags?.out,{...o6(a,t.flags,l?.appBundleId,l?.trace?.outPath)});return l&&i.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:f??{}}),{ok:!0,data:{platform:p.platform,...f??{}}}}async function dc(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,dispatch:o,ensureReady:s,resolveTargetDevice:l,installOps:d=l1,reinstallOps:u=l0,stopIosRunner:c,appLogOps:p={start:t8,stop:t5},ensureAndroidEmulatorBoot:f=dn,resolveAndroidPackageForOpen:m=lG,applyRuntimeHints:h=sQ,clearRuntimeHints:w=s0,settleSimulator:g,shutdownSimulator:v,shutdownAndroidEmulator:I,listAndroidDevices:A,listAppleDevices:b,listAppleApps:S}=e,N=o??o3,D=s??o7,E=l??o2,k=c??tA,M=g??lD,x=t.command;if("session_list"===x)return{ok:!0,data:{sessions:i.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",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("runtime"===x)return await lF({req:t,sessionName:r,sessionStore:i,clearRuntimeHints:w});if("ensure-simulator"===x)try{let e=t.flags??{},r=e.device,a=e.runtime,i=eC(e.iosSimulatorDeviceSet);if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let n=!0===e.boot,o=!1!==e.reuseExisting,s=await lw({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:o,boot:n,ensureReady:D});return{ok:!0,data:{udid:s.udid,device:s.device,runtime:s.runtime,ios_simulator_device_set:i??null,created:s.created,booted:s.booted}}}catch(t){let e=y(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===x)try{let e=[],r=eR(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,i=e3({simulatorSetPath:eC(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let t=A??(await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:ae,ensureAndroidEmulatorHeadlessBooted:at,listAndroidDevices:r2,parseAndroidAvdList:r4,parseAndroidEmulatorAvdNameOutput:rW,parseAndroidFeatureListForTv:rZ,parseAndroidTargetFromCharacteristics:rY,resolveAndroidAvdName:r8,resolveAndroidEmulatorAvdName:rK,waitForAndroidBoot:ar}))).listAndroidDevices;e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let t=b??(await Promise.resolve().then(()=>({findBootableIosSimulator:oQ,isAppleProductType:oz,isAppleTvProductType:oJ,isSupportedAppleDevicectlDevice:oZ,listAppleDevices:o0,listIosDevices:o0,resolveAppleTargetFromDevicectlDevice:oY}))).listAppleDevices;e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let t=A??(await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:ae,ensureAndroidEmulatorHeadlessBooted:at,listAndroidDevices:r2,parseAndroidAvdList:r4,parseAndroidEmulatorAvdNameOutput:rW,parseAndroidFeatureListForTv:rZ,parseAndroidTargetFromCharacteristics:rY,resolveAndroidAvdName:r8,resolveAndroidEmulatorAvdName:rK,waitForAndroidBoot:ar}))).listAndroidDevices;try{e.push(...await t({serialAllowlist:r}))}catch{}}let t=b??(await Promise.resolve().then(()=>({findBootableIosSimulator:oQ,isAppleProductType:oz,isAppleTvProductType:oJ,isSupportedAppleDevicectlDevice:oZ,listAppleDevices:o0,listIosDevices:o0,resolveAppleTargetFromDevicectlDevice:oY}))).listAppleDevices;try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=y(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===x){let e=i.get(r),a=t.flags??{},n=lS(x,e,a);if(n)return n;let o=await lE({session:e,flags:a,ensureReadyFn:D,resolveTargetDeviceFn:E,ensureReady:!0});if(!o5("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(e1(o.platform)){let e=S??(await Promise.resolve().then(()=>({closeIosApp:os,ensureBootedSimulator:nt,installIosApp:od,installIosInstallablePath:oc,listIosApps:ow,listSimulatorApps:og,openIosApp:on,openIosDevice:oo,parseIosDeviceAppsPayload:i4,pushIosNotification:om,readIosClipboardText:op,reinstallIosApp:ou,resolveIosApp:oi,screenshotIos:nQ,setIosSetting:oh,uninstallIosApp:ol,writeIosClipboardText:of}))).listIosApps;return{ok:!0,data:{apps:(await e(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await Promise.resolve().then(()=>({listAndroidApps:aP}));return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}if("boot"===x){let e,a=i.get(r),n=t.flags??{},o=lS(x,a,n);if(o)return o;let s="android"===(n.platform??a?.device.platform),l=!0===n.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=lM({flags:n,sessionDevice:a?.device}),u=s&&!!d,c=!1;try{e=await lE({session:a,flags:n,ensureReadyFn:D,resolveTargetDeviceFn:E,ensureReady:!1})}catch(r){let t=y(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await f({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${n.target}.`}};if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};if(!c){let t=lM({flags:n,sessionDevice:a?.device,resolvedDevice:e});if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await f({avdName:t,serial:n.serial,headless:!0})}await D(e)}else("android"!==e.platform||!0!==e.booted)&&await D(e);return o5("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"boot is not supported on this device"}}}if("appstate"===x)return await dd({req:t,sessionName:r,sessionStore:i,ensureReady:D,resolveDevice:E});if("clipboard"===x)return await du({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:D,resolveDevice:E,dispatch:N});if("keyboard"===x)return await ds({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:D,resolveDevice:E,dispatch:N,command:"keyboard",positionals:t.positionals??[]});if("perf"===x){let e,t,a,n=i.get(r);return n?{ok:!0,data:(a=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===lj&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:lj,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(n.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:lj,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:lj},{session:n.name,platform:n.device.platform,device:n.device.name,deviceId:n.device.id,metrics:{startup:a,fps:{available:!1,reason:lq},memory:{available:!1,reason:lq},cpu:{available:!1,reason:lq}},sampling:{startup:{method:lj,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"}}})}:{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}}}if("install"===x||"reinstall"===x)return await l2({req:t,command:x,sessionName:r,sessionStore:i,ensureReady:D,resolveDevice:E,deployOps:"install"===x?d:u});if("install_source"===x)return await lm({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===x)return await lh({req:t});if("push"===x){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();if(!n||!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}};let s="file"===(e=oP(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tq.expandHome(e,t)})).kind?e.path:e.text;return await ds({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:D,resolveDevice:E,dispatch:N,command:"push",positionals:[n,s],recordPositionals:[n,o]})}if("trigger-app-event"===x)return await ds({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:D,resolveDevice:E,dispatch:N,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await lB(e.device,r,e.appBundleId,m)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}});if("open"===x)return await lK({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:N,ensureReady:D,resolveDevice:E,applyRuntimeHints:h,clearRuntimeHints:w,stopIosRunner:k,settleSimulator:M,resolveAndroidPackageForOpen:m});if("replay"===x){let e=t.positionals?.[0];if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};try{let o=tq.expandHome(e,t.meta?.cwd),s=J.readFileSync(o,"utf8"),l=s.trimStart()[0];if("{"===l||"["===l)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let d=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,i=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!i)break;i="\\"===t&&!i,"\\"!==t&&(i=!1),a+=1}if(a>=e.length)throw new _("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=tG(r);return{positionals:i.positionals,flags:a,runtime:(t=i.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?i.flags:void 0}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n.runtime=e.runtime,n}if("runtime"===a){let e=tG(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tP(a)){let e=tV(a,i);if(Object.assign(n.flags,e.flags),0===e.positionals.length)return n;let t=e.positionals[0];if(t.startsWith("@"))return n.positionals=[t],e.positionals[1]&&(n.result={refLabel:e.positionals[1]}),n;let r=e.positionals[0],o=e.positionals[1];return lo(r)&&lo(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){if(i.length<2)return n.positionals=i,n;let e=i[0];return e.startsWith("@")?(i.length>=3?(n.positionals=[e,i.slice(2).join(" ")],n.result={refLabel:i[1]}):n.positionals=[e,i[1]],n):(n.positionals=[e,i.slice(1).join(" ")],n)}if("get"===a){if(i.length<2)return n.positionals=i,n;let e=i[0],t=i[1];return t.startsWith("@")?(n.positionals=[e,t],i[2]&&(n.result={refLabel:i[2]})):n.positionals=[e,i.slice(1).join(" ")],n}if("swipe"===a){let e=tV(a,i);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}if("record"===a){let e=[];for(let t=0;t<i.length;t+=1){let r=i[t];if("--hide-touches"===r){n.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(n.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return n.positionals=e,n}return n.positionals=i,n}(r);e&&t.push(e)}return t}(s),u=t.flags?.replayUpdate===!0,c=0;for(let e=0;e<d.length;e+=1){let s=d[e];if(!s||"replay"===s.command)continue;let l=await n({token:t.token,session:r,command:s.command,positionals:s.positionals??[],flags:df(t.flags,s.flags),runtime:s.runtime,meta:t.meta});if(l.ok)continue;if(!u)return dp(l,s,e,o);let p=await dm({action:s,sessionName:r,logPath:a,sessionStore:i,dispatch:N});if(!p)return dp(l,s,e,o);if(d[e]=p,!(l=await n({token:t.token,session:r,command:p.command,positionals:p.positionals??[],flags:df(t.flags,p.flags),runtime:p.runtime,meta:t.meta})).ok)return dp(l,p,e,o);c+=1}if(u&&c>0){let e=i.get(r);!function(e,t,r){let a=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",i=r.device.target?` target=${r.device.target}`:"";a.push(`context platform=${r.device.platform}${i} device="${e}"${t} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tR(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tj(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tT(r));return tF(t,e.flags),t.join(" ")}if("record"===e.command)return tU(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tR(r));return t$(t,e),t.join(" ")}(e));let i=`${a.join("\n")}
|
|
37
|
-
`,n=`${e}.tmp-${process.pid}-${Date.now()}`;J.writeFileSync(n,i),J.renameSync(n,e)}(o,d,e)}return{ok:!0,data:{replayed:d.length,healed:c,session:r}}}catch(t){let e=y(t);return{ok:!1,error:{code:e.code,message:e.message}}}}if("logs"===x){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!o5("logs",e.device))return{ok:!1,error:C(new _("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let a=(t.positionals?.[0]??"path").toLowerCase(),n=!!t.flags?.restart;if(!l7.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:de}};if(n&&"clear"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===a){let t=i.resolveAppLogPath(r),a=function(e){if(!J.existsSync(e))return{exists:!1,sizeBytes:0};let t=J.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t),n=dl(e);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:n,sizeBytes:a.sizeBytes,modifiedAt:a.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===a){let t=i.resolveAppLogPath(r),a=await t6(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:a.checks,notes:a.notes}}}if("mark"===a){let e,a=t.positionals?.slice(1).join(" ")??"",n=i.resolveAppLogPath(r);return t4(n),e=`[agent-device][mark][${new Date().toISOString()}] ${a.trim()||"marker"}
|
|
38
|
-
`,J.appendFileSync(n,e,"utf8"),{ok:!0,data:{path:n,marked:!0}}}if("clear"===a){if(e.appLog&&!n)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(n&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let t=i.resolveAppLogPath(r);if(n){e.appLog&&await p.stop(e.appLog);let a=t9(t),n=i.resolveAppLogPidPath(r);try{let o=await p.start(e.device,e.appBundleId,t,n),s={...e,appLog:{platform:e.device.platform,backend:o.backend,outPath:t,startedAt:o.startedAt,getState:o.getState,stop:o.stop,wait:o.wait}};return i.set(r,s),{ok:!0,data:{...a,restarted:!0}}}catch(a){let t=C(a);return i.set(r,{...e,appLog:void 0}),{ok:!1,error:t}}}return{ok:!0,data:t9(t)}}if("start"===a){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};let t=i.resolveAppLogPath(r),a=i.resolveAppLogPidPath(r);try{let n=await p.start(e.device,e.appBundleId,t,a),o={...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}};return i.set(r,o),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:C(e)}}}if("stop"===a){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await p.stop(e.appLog),i.set(r,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===x){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!o5("network",e.device))return{ok:!1,error:C(new _("UNSUPPORTED_OPERATION","network is not supported on this device"))};let a=(t.positionals?.[0]??"dump").toLowerCase();if(!dt.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:dr}};let n=t.positionals?.[1],o=n?Number.parseInt(n,10):25;if(!Number.isInteger(o)||o<1||o>200)return{ok:!1,error:{code:"INVALID_ARGS",message:"network dump limit must be an integer in range 1..200"}};let s=(t.positionals?.[2]??"summary").toLowerCase();if(!da.includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:di}};let l=function(e,t){let r=sj(t?.maxEntries,25,1,200),a=t?.include??"summary",i=sj(t?.maxPayloadChars,2048,64,16384),n=sj(t?.maxScanLines,4e3,100,2e4);if(!J.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}};let o=J.readFileSync(e,"utf8").split("\n"),s=Math.max(0,o.length-n),l=o.slice(s),d=[];for(let e=l.length-1;e>=0&&d.length<r;e-=1){let t=l[e]?.trim();if(!t)continue;let r=function(e,t,r,a){let i=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(e),n=sU(i,["method","httpMethod"]),o=sU(i,["url","requestUrl"]),s=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(i,["status","statusCode","responseCode"]),l=sT.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(n??d?.[1]??l?.[1])?.toUpperCase(),c=s$.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of sF){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}(e)??void 0,timestamp:function(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);return t?.[0]}(e),raw:sB(e,a),line:t};if("headers"===r||"all"===r){let t=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return sG(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,i);t&&(f.headers=sB(t,a))}if("body"===r||"all"===r){let t=sV(e,i,["requestBody","body","payload","request"]),r=sV(e,i,["responseBody","response"]);t&&(f.requestBody=sB(t,a)),r&&(f.responseBody=sB(r,a))}return f}(t,s+e+1,a,i);r&&d.push(r)}return{path:e,exists:!0,scannedLines:l.length,matchedLines:d.length,entries:d,include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}}}(i.resolveAppLogPath(r),{maxEntries:o,include:s,maxPayloadChars:2048,maxScanLines:4e3}),d=dl(e),u=[];return e.appLog||u.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===l.entries.length&&u.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...l,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:d,notes:u}}}return"batch"===x?await l4(t,r,n):"close"===x?await lQ({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:N,stopIosRunner:k,clearRuntimeHints:w,settleSimulator:M,shutdownSimulator:v??nr,shutdownAndroidEmulator:I,appLogOps:{stop:p.stop}}):null}function dp(e,t,r,a){if(e.ok)return e;let i=r+1,n=function(e){let t;return t=(e.positionals??[]).map(e=>tR(e)),[e.command,...t].join(" ")}(t),o={...e.error.details??{},replayPath:a,step:i,action:t.command,positionals:t.positionals??[]};return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${i} (${n}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:o}}}function df(e,t){let r={...t??{}},a=e??{};for(let e of l9)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}async function dm(e){let{action:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n}=e;if(!(tP(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let o=i.get(r);if(!o)return null;let s=tP(t.command)||"fill"===t.command,l=tP(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await dh(o,t,a,s,n,i);for(let e of function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),tP(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}=sA(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=ln(e.positionals??[]);r&&t.push(r)}let a="string"==typeof e.result?.refLabel?e.result.refLabel.trim():"";if(a.length>0){let r=JSON.stringify(a);"fill"===e.command?(t.push(`id=${r} editable=true`),t.push(`label=${r} editable=true`),t.push(`text=${r} editable=true`),t.push(`value=${r} editable=true`)):(t.push(`id=${r}`),t.push(`label=${r}`),t.push(`text=${r}`),t.push(`value=${r}`))}return tx(t).filter(e=>e.trim().length>0)}(t)){let r=sv(e);if(!r)continue;let a=sM(d.nodes,r,{platform:o.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!a)continue;let i=sC(a.node,o.device.platform,{action:tP(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tP(t.command))return{...t,positionals:[i]};if("fill"===t.command){let e=tM(t);if(!e)continue;return{...t,positionals:[i,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,i]}}if("is"===t.command){let{predicate:e,split:r}=sA(t.positionals);if(!e)continue;let a=r?.rest.join(" ").trim()??"",n=[e,i];return"text"===e&&a.length>0&&n.push(a),{...t,positionals:n}}if("wait"===t.command){let{selectorTimeout:e}=ln(t.positionals??[]),r=[i];return e&&r.push(e),{...t,positionals:r}}}let u=function(e,t,r){if("get"!==e.command||e.positionals?.[0]!=="text")return null;let a=e.positionals?.[1];if(!a)return null;let i=sv(a);if(!i)return null;let n=new Set,o=!1;for(let e of i.selectors)for(let t of e.terms)"role"===t.key&&"string"==typeof t.value&&n.add(sc(t.value)),("text"===t.key||"label"===t.key||"value"===t.key)&&"string"==typeof t.value&&/^\d+$/.test(t.value.trim())&&(o=!0);if(!o)return null;let s=t.nodes.filter(e=>{let t=sf(e).trim();return!!/^\d+$/.test(t)&&(0===n.size||n.has(sc(e.type??"")))});if(0===s.length||1!==tx(s.map(e=>sf(e).trim())).length)return null;let l=s[0];if(!l)return null;let d=sC(l,r.device.platform,{action:"get"});return 0===d.length?null:{...e,positionals:["text",d.join(" || ")]}}(t,d,o);return u||null}async function dh(e,t,r,a,i,n){let o=await i(e.device,"snapshot",[],t.flags?.out,{...o6(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[],l={nodes:sa(t.flags?.snapshotRaw?s:su(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend};return e.snapshot=l,n.set(e.name,e),l}function dw(e,t){let r=L(e.type??"Element"),a=v(e,r),i=!1===e.enabled?"disabled":"enabled",n=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,a,i,n,o].join("|")}function dg(e,t){return t.flatten?e.map(e=>({text:d(e,0,!1),comparable:dw(e,0)})):k(e).map(e=>({text:e.text,comparable:dw(e.node,e.depth)}))}function dv(e,t){return e.get(t)??0}async function dI(e){var t,r;let a;return{snapshot:(t=await dA(e),r=e.flags?.snapshotRaw,a=t?.nodes??[],{nodes:sa(r?a:su(a)),truncated:t?.truncated,createdAt:Date.now(),backend:t?.backend})}}async function dA(e){var t,r,a,i;let n,{dispatchSnapshotCommand:o,device:s,session:l,flags:d,outPath:u,logPath:c,snapshotScope:p}=e;return"macos"===s.platform&&l?.surface&&"app"!==l.surface?(t=await nE(l.surface),r={snapshotDepth:d?.snapshotDepth,snapshotInteractiveOnly:d?.snapshotInteractiveOnly,snapshotScope:p},n=t.nodes??[],r.snapshotScope&&(n=function(e,t){let r=ss(sa(e),t);if(!r)return[];let a=e.findIndex(e=>e.index===r.index);if(-1===a)return[];let i=e[a]?.depth??0,n=[];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<=i)break;n.push(r)}return dy(n,i)}(n,r.snapshotScope)),r.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:dy(e.filter(e=>r.has(e.index)))}(n)),"number"==typeof r.snapshotDepth&&(a=n,i=r.snapshotDepth,n=dy(a.filter(e=>(e.depth??0)<=i))),{...t,nodes:n}):await o(s,"snapshot",[],u,{...o6(c,{...d,snapshotScope:p},l?.appBundleId,l?.trace?.outPath)})}function dy(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 db(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=si(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=sn(t.snapshot.nodes,r),i=a?sl(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function dS(e,t,r){let a=e.get(t),i=a?.device??await o2(r??{});return a||await o7(i),{session:a,device:i}}async function d_(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await tA(t.id)}}function dN(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function dD(e){let{session:t,sessionName:r,device:a,snapshot:i,appBundleId:n}=e;return t?{...t,snapshot:i}:{name:r,device:a,createdAt:Date.now(),appBundleId:n,snapshot:i,actions:[]}}function dE(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function dk(e){let{parsed:t,req:r,sessionName:a,logPath:i,sessionStore:n,session:o,device:s}=e,l=e.dispatchSnapshotCommand??o3,d=e.runnerCommand??tE;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),dN(n,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!o5("wait",s))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}};if("selector"===t.kind)return await dM({dispatchSnapshotCommand:l,device:s,logPath:i,parsed:t,req:r,session:o,sessionName:a,sessionStore:n});let u=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}}};let r=si(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=sn(t.snapshot.nodes,r),i=a?sl(a,t.snapshot.nodes):void 0;return i?{ok:!0,text:i,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return u.ok?await dx({dispatchSnapshotCommand:l,device:s,logPath:i,req:r,runnerCommand:d,session:o,sessionStore:n,text:u.text,timeoutMs:u.timeoutMs}):u.response}async function dM(e){let{dispatchSnapshotCommand:t,device:r,logPath:a,parsed:i,req:n,session:o,sessionName:s,sessionStore:l}=e,d=i.timeoutMs??1e4,u=Date.now();for(;Date.now()-u<d;){let e=sx((await dO({dispatchSnapshotCommand:t,device:r,logPath:a,req:n,session:o,sessionName:s,sessionStore:l})).nodes,i.selector,{platform:r.platform});if(e)return dL(l,o,n,{selector:e.selector.raw,waitedMs:Date.now()-u});await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${i.selectorExpression}`}}}async function dx(e){let{device:t,logPath:r,req:a,runnerCommand:i,session:n,sessionStore:o,text:s,timeoutMs:l}=e,d=l??1e4,u=Date.now();for(;Date.now()-u<d;){if("macos"===t.platform&&n?.surface&&"app"!==n.surface){if(ss((await dO({dispatchSnapshotCommand:e.dispatchSnapshotCommand,device:t,logPath:r,req:a,session:n,sessionName:n?.name??a.session??"default",sessionStore:o})).nodes,s))return dL(o,n,a,{text:s,waitedMs:Date.now()-u})}else if(e1(t.platform)){let e=await i(t,{command:"findText",text:s,appBundleId:n?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:n?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return dN(o,n,a,{text:s,waitedMs:Date.now()-u}),{ok:!0,data:{text:s,waitedMs:Date.now()-u}}}else if("android"===t.platform&&ss(sa((await it(t,{scope:s})).nodes??[]),s))return dN(o,n,a,{text:s,waitedMs:Date.now()-u}),{ok:!0,data:{text:s,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${s}`}}}async function dO(e){let{dispatchSnapshotCommand:t,device:r,logPath:a,req:i,session:n,sessionName:o,sessionStore:s}=e,{snapshot:l}=await dI({dispatchSnapshotCommand:t,device:r,session:n,flags:{...i.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:i.flags?.out,logPath:a});return n&&(n.snapshot=l,s.set(o,n)),l}function dL(e,t,r,a){return dN(e,t,r,a),{ok:!0,data:a}}async function dC(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n}=e,o=e.runnerCommand??tE,s=(t.positionals?.[0]??"get").toLowerCase(),l=i?"frontmost-app"===i.surface?{surface:"frontmost-app"}:{bundleId:i.appBundleId,surface:i.surface}:{};if(!o5("alert",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is not supported on this device"}};if("macos"===n.platform){let e=async()=>await nD("wait"===s?"get":s,l);if("wait"===s){let r=dE(t.positionals?.[1])??1e4,n=Date.now();for(;Date.now()-n<r;){try{let r=await e();return dN(a,i,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r="accept"===s||"dismiss"===s?s:"get";if("accept"===r||"dismiss"===r){let e,n=Date.now();for(;Date.now()-n<2e3;){try{let e=await nD(r,l);return dN(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let n=await nD("get",l);return dN(a,i,t,n),{ok:!0,data:n}}if("wait"===s){let e=dE(t.positionals?.[1])??1e4,s=Date.now();for(;Date.now()-s<e;){try{let e=await o(n,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return dN(a,i,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let d="accept"===s||"dismiss"===s?s:"get",u={verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===d||"dismiss"===d){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await o(n,{command:"alert",action:d,appBundleId:i?.appBundleId},u);return dN(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let c=await o(n,{command:"alert",action:d,appBundleId:i?.appBundleId},u);return dN(a,i,t,c),{ok:!0,data:c}}async function dP(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!o5("settings",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};let u=i?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],p=await o3(n,"settings",c,t.flags?.out,{...o6(r,t.flags,u,i?.trace?.outPath)});return dN(a,i,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}async function dR(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=e.dispatchSnapshotCommand??o3,o=e.runnerCommand??tE,s=e.sessionlessRunnerCleanup??d_,l=t.command;if("snapshot"===l){let{session:e,device:o}=await dS(i,r,t.flags);if(!o5("snapshot",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let l=db(t.flags?.snapshotScope,e);return l.ok?await s(e,o,async()=>{let s=await dI({dispatchSnapshotCommand:n,device:o,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:l.scope}),d=dD({session:e,sessionName:r,device:o,snapshot:s.snapshot,appBundleId:e?.appBundleId});return dN(i,d,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),i.set(r,d),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,appName:d.appBundleId?d.appName??d.appBundleId:void 0,appBundleId:d.appBundleId}}}):l.response}if("diff"===l){if(t.positionals?.[0]!=="snapshot")return{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}};let{session:e,device:o}=await dS(i,r,t.flags);if(!o5("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let l=db(t.flags?.snapshotScope,e);if(!l.ok)return l.response;let d=t.flags?.snapshotInteractiveOnly===!0;return await s(e,o,async()=>{let s=(await dI({dispatchSnapshotCommand:n,device:o,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:l.scope})).snapshot;if(!e?.snapshot){let a=function(e,t={}){return dg(e,t).length}(s.nodes,{flatten:d}),n=dD({session:e,sessionName:r,device:o,snapshot:s,appBundleId:e?.appBundleId});return dN(i,n,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a}}),i.set(r,n),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a},lines:[]}}}let u=function(e,t,r={}){let a=function(e,t){let r=e.length,a=t.length,i=r+a,n=new Map,o=[];n.set(1,0);for(let s=0;s<=i;s+=1){o.push(new Map(n));for(let i=-s;i<=s;i+=2){let l=i===-s||i!==s&&dv(n,i-1)<dv(n,i+1)?dv(n,i+1):dv(n,i-1)+1,d=l-i;for(;l<r&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(n.set(i,l),l>=r&&d>=a)return function(e,t,r,a,i){let n=[],o=a,s=i;for(let a=e.length-1;a>=0;a-=1){let i=e[a],l=o-s,d=l===-a||l!==a&&dv(i,l-1)<dv(i,l+1)?l+1:l-1,u=dv(i,d),c=u-d;for(;o>u&&s>c;)n.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===a)break;o===u?(n.push({kind:"added",text:r[c].text}),s=c):(n.push({kind:"removed",text:t[u].text}),o=u)}return n.reverse(),n}(o,e,t,r,a)}}return[]}(dg(e,r),dg(t,r)),i={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(i.additions+=1),"removed"===e.kind&&(i.removals+=1),"unchanged"===e.kind&&(i.unchanged+=1);return{summary:i,lines:a}}(e.snapshot.nodes,s.nodes,{flatten:d}),c={...e,snapshot:s};return dN(i,c,t,{mode:"snapshot",baselineInitialized:!1,summary:u.summary}),i.set(r,c),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:u.summary,lines:u.lines}}})}if("wait"===l){let{session:e,device:l}=await dS(i,r,t.flags),d=function(e){if(0===e.length)return null;let t=dE(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=dE(e[e.length-1]);return{kind:"text",text:(null!==t?e.slice(1,-1).join(" "):e.slice(1).join(" ")).trim(),timeoutMs:t}}if(e[0].startsWith("@")){let t=dE(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=dE(e[e.length-1]),a=sI(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=sv(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}};let u=()=>dk({parsed:d,req:t,sessionName:r,logPath:a,sessionStore:i,session:e,device:l,dispatchSnapshotCommand:n,runnerCommand:o});return"sleep"===d.kind?await u():await s(e,l,u)}if("alert"===l){let{session:e,device:n}=await dS(i,r,t.flags);return await s(e,n,async()=>await dC({req:t,logPath:a,sessionStore:i,session:e,device:n,runnerCommand:o}))}if("settings"===l){let e,n,o,l=(e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&n&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:n,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:I}}});if(!l.ok)return l.response;let{session:d,device:u}=await dS(i,r,t.flags);return await s(d,u,async()=>await dP({req:t,logPath:a,sessionStore:i,session:d,device:u,parsed:l.parsed}))}return null}function dT(e,t,r,a={}){let i=dF(r);if(!i)return{matches:[],score:0};let n=0,o=[];for(let r of e){if(a.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return d$(e.label,r);case"value":return d$(e.value,r);case"id":return d$(e.identifier,r);default:return Math.max(d$(e.label,r),d$(e.value,r),d$(e.identifier,r))}}(r,t,i);if(!(e<=0)){if(e>n){n=e,o.length=0,o.push(r);continue}e===n&&o.push(r)}}return{matches:o,score:n}}function d$(e,t){let r=dF(e??"");return r?r===t?2:+!!r.includes(t):0}function dF(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function dU(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"No snapshot in session. Run snapshot first."}}};let s=si(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=sn(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=ss(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}}async function dV(e){let{device:t,node:r,flags:a,appBundleId:i,traceOutPath:n,surface:o,contextFromFlags:s,dispatch:l}=e,d=N(r),u=function(e){let t=function(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}(e);if(!t)return null;let r=so(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}(r.rect);if(!u)return d;try{let e=await l(t,"read",[String(u.x),String(u.y)],void 0,{...s(a,i,n),surface:o}),c=e&&"object"==typeof e?e:void 0,p="string"==typeof c?.text?c.text:"";if(p.trim())return p;return B({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),d}catch(e){return B({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)}}),d}}async function dG(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=e.dispatch??o3,s=t.command;if("find"!==s)return null;let l=t.positionals??[];if(0===l.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a locator or text"}};let{locator:d,query:u,action:c,value:p,timeoutMs:f}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let a=e[r]??"",i=e.slice(r+1);if(0===i.length)return{locator:t,query:a,action:"click"};let n=i[0].toLowerCase();if("get"===n){let e=i[1]?.toLowerCase();if("text"===e)return{locator:t,query:a,action:"get_text"};if("attrs"===e)return{locator:t,query:a,action:"get_attrs"};throw new _("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:a,action:"wait",timeoutMs:dE(i[1])??void 0};if("exists"===n)return{locator:t,query:a,action:"exists"};if("click"===n)return{locator:t,query:a,action:"click"};if("focus"===n)return{locator:t,query:a,action:"focus"};if("fill"===n)return{locator:t,query:a,action:"fill",value:i.slice(1).join(" ")};if("type"===n)return{locator:t,query:a,action:"type",value:i.slice(1).join(" ")};throw new _("INVALID_ARGS",`Unsupported find action: ${i[0]}`)}(l);if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a value"}};let m=i.get(r);if(!m&&"exists"!==c&&"wait"!==c&&"get_text"!==c&&"get_attrs"!==c)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let h=m?.device??await o2(t.flags??{});m||await o7(h);let w="role"!==d?u:void 0,g="click"===c||"focus"===c||"fill"===c||"type"===c,v=0,I=null,A=async()=>{let e=Date.now();if(I&&e-v<750)return{nodes:I};let{snapshot:n}=await dI({dispatchSnapshotCommand:o,device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:g,snapshotCompact:g},outPath:t.flags?.out,logPath:a,snapshotScope:w}),s=n.nodes;return v=e,I=s,m&&(m.snapshot=n,i.set(r,m)),{nodes:s,truncated:n.truncated,backend:n.backend}};if("wait"===c){let e=f??1e4,r=Date.now();for(;Date.now()-r<e;){let{nodes:e}=await A();if(dT(e,d,u,{requireRect:!1}).matches[0])return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0,waitedMs:Date.now()-r}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-r}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}let{nodes:y}=await A(),b=dT(y,d,u,{requireRect:g});if(g&&b.matches.length>1){let e=b.matches.slice(0,8).map(e=>{let t=sf(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`});return{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${b.matches.length} elements for ${d} "${u}". Use a more specific locator or selector.`,details:{locator:d,query:u,matches:b.matches.length,candidates:e}}}}let S=b.matches[0]??null;if(!S)return{ok:!1,error:{code:"COMMAND_FAILED",message:"find did not match any element"}};let N="click"===c||"focus"===c||"fill"===c||"type"===c?function(e,t){if(t.hittable)return t;let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}(y,S)??S:S,D=`@${N.ref}`,E={...t.flags??{},noRecord:!0};if("exists"===c)return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}};if("get_text"===c){let e=await dV({device:h,node:S,flags:t.flags,appBundleId:m?.appBundleId,traceOutPath:m?.trace?.outPath,surface:m?.surface,contextFromFlags:(e,t,r)=>o6(a,e,t,r),dispatch:o});return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"get text",text:e}}),{ok:!0,data:{ref:D,text:e,node:S}}}if("get_attrs"===c)return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"get attrs"}}),{ok:!0,data:{ref:D,node:S}};if("click"===c){let e=await n({token:t.token,session:r,command:"click",positionals:[D],flags:E});if(!e.ok)return e;let a=N.rect?so(N.rect):null,o={ref:D,locator:d,query:u};return a&&(o.x=a.x,o.y=a.y),m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"click",locator:d,query:u}}),{ok:!0,data:o}}if("fill"===c){if(!p)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let e=await n({token:t.token,session:r,command:"fill",positionals:[D,p],flags:E});return e.ok&&m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"fill"}}),e}if("focus"===c){let e=S.rect?so(S.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let r=await o(h,"focus",[String(e.x),String(e.y)],t.flags?.out,{...o6(a,t.flags,m?.appBundleId,m?.trace?.outPath)});return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"focus"}}),{ok:!0,data:r??{ref:D}}}if("type"===c){if(!p)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let e=S.rect?so(S.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await o(h,"focus",[String(e.x),String(e.y)],t.flags?.out,{...o6(a,t.flags,m?.appBundleId,m?.trace?.outPath)});let r=await o(h,"type",[p],t.flags?.out,{...o6(a,t.flags,m?.appBundleId,m?.trace?.outPath)});return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:D,action:"type"}}),{ok:!0,data:r??{ref:D}}}return null}let dB=`
|
|
26
|
+
${i}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")||n.includes("timed out")&&n.includes("screenshot")}let oo={settings:"com.apple.Preferences"},os=null;function ol(e,t,r){return v("xcrun",eq(e,t),r)}function od(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function ou(e,t){if("macos"===e.platform)return await nU(t);let r=t.trim();if(r.includes("."))return r;let a=oo[r.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await oS(e):await ne(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new k("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new k("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function oc(e,t,r){if("macos"===e.platform)return void await nV(e,t,r);let a=r?.url?.trim();if(a){if(!rZ(a))throw new k("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await ns(e),await no(),await ol(e,["openurl",e.id,a]);return}let i=rQ(r?.appBundleId??await ou(e,t),a);if(!i)throw new k("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oL(e,i,{payloadUrl:a});return}let i=t.trim();if(rZ(i)){if("simulator"===e.kind){await ns(e),await no(),await ol(e,["openurl",e.id,i]);return}let t=rQ(r?.appBundleId,i);if(!t)throw new k("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oL(e,t,{payloadUrl:i});return}let n=r?.appBundleId??await ou(e,t);"simulator"===e.kind?await oO(e,n):await oL(e,n)}async function op(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await nd(e)&&(await ns(e),await no())}async function of(e,t){if("macos"===e.platform)return void await nG(e,t);let r=await ou(e,t);if("simulator"===e.kind){await ns(e);let t=eq(e,["terminate",e.id,r]),a=await v("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new k("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await i7(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function om(e,t){let r=await ou(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],a=await v("xcrun",t,{allowFailure:!0,timeoutMs:i8});if(0!==a.exitCode){let i=String(a.stdout??""),n=String(a.stderr??"");if(!od(`${i}
|
|
27
|
+
${n}`.toLowerCase()))throw new k("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:e.id,hint:nr(i,n)??nt})}return{bundleId:r}}await ns(e);let a=await ol(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==a.exitCode&&!od(`${a.stdout}
|
|
28
|
+
${a.stderr}`.toLowerCase()))throw new k("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:r}}async function oh(e,t,r){let a=await nc({kind:"path",path:t},r);try{return await og(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function ow(e,t,r){let{bundleId:a}=await om(e,t);return await oh(e,r,{appIdentifierHint:t}),{bundleId:a}}async function og(e,t){"simulator"!==e.kind?await i7(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await ns(e),await ol(e,["install",e.id,t]))}async function ov(e){if("macos"===e.platform)return await nj();nn(e,"clipboard"),await ns(e);let t=await ol(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new k("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 oy(e,t){if("macos"===e.platform)return void await nB(t);nn(e,"clipboard"),await ns(e);let r=await ol(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new k("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function oI(e,t,r){nn(e,"push"),await ns(e);let a=await X.mkdtemp(l.join(ea.tmpdir(),"agent-device-ios-push-")),i=l.join(a,"payload.apns");try{await X.writeFile(i,`${JSON.stringify(r)}
|
|
29
|
+
`,"utf8"),await ol(e,["push",e.id,t,i])}finally{await X.rm(a,{recursive:!0,force:!0})}}async function oA(e,t,r,a,i){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await nH(r);if("permission"===e){let e=iV(r);if("deny"===e)throw new k("INVALID_ARGS","Unsupported macOS permission action: deny. macOS supports only settings permission <grant|reset> <accessibility|screen-recording|input-monitoring>.");let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new k("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(i?.permissionTarget);return await nO(e,t)}throw new k("INVALID_ARGS",`Unsupported macOS setting: ${t}. macOS supports settings appearance <light|dark|toggle> and settings permission <grant|reset> <accessibility|screen-recording|input-monitoring>.`)}nn(e,"settings"),await ns(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=o_(r);await ol(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(o_(r)?await ol(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await ol(e,["status_bar",e.id,"clear"]));case"location":{let t=o_(r);if(!a)throw new k("INVALID_ARGS","location setting requires an active app in session");await ol(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=oD[n],a=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new k("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,n);await oE(e,a,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await oN(e,r);await ol(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new k("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=iV(r))?"revoke":o,n=function(e,t){let r=iG(e);if("photos"!==r&&t?.trim())throw new k("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 k("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new k("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(i?.permissionTarget,i?.permissionMode);await ox(e,t,n,a);return}default:throw new k("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function ob(e,t="all"){return"macos"===e.platform?await nW(t):"simulator"===e.kind?nw(await oS(e),t):await ne(e,t)}async function oS(e){let t=(await ol(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 v("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 o_(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 k("INVALID_ARGS",`Invalid setting state: ${e}`)}async function oN(e,t){let r=ij(t);if("toggle"!==r)return r;let a=await ol(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new k("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
|
|
30
|
+
${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new k("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let oD={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function ox(e,t,r,a){let i=await oM(e);if(!i.has(r))throw new k("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(i).sort().join(", ")}`});let n=["privacy",e.id,t,r,a],o="notifications"===r;if(!("reset"===t&&o))try{await ol(e,n);return}catch(t){if(!(o&&ok(t)))throw t;throw new k("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 ol(e,n);return}catch(e){if(!ok(e))throw e}try{await ol(e,["privacy",e.id,"reset","all",a])}catch(t){throw new k("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 ok(e){if(!(e instanceof k)||"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 oM(e){let r=eV(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(os&&t===a)return os;let i=await ol(e,["privacy","help"],{allowFailure:!0}),n=function(e){let t=new Set,r=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let i=/^([a-z-]+)\s+-\s+/.exec(e);i&&t.add(i[1])}return t}(`${i.stdout}
|
|
31
|
+
${i.stderr}`);if(0===n.size)throw new k("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return os=n,t=a,n}async function oE(e,t,r){let a=function(e,t,r){let a=r.length>0?r:["face"];switch(t){case"match":return a.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return a.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),i=[];for(let t of a){let r=eq(e,t),a=await v("xcrun",r,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:r,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let n=i.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(i.length>0&&i.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
|
|
32
|
+
${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new k("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new k("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function oO(e,t){await ns(e),await no();let r=0,a=ef.fromTimeoutMs(i4);try{await em(async({deadline:r})=>{var a;if(r?.isExpired())throw new k("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:i4});let i=(a=["launch",e.id,t],eq(e,a)),n=await v("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new k("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!na(e)&&(r+=1)<3},{deadline:a})}catch(r){if(na(r)){var i;let a=(i=await ni(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function oL(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await i7(a,{action:"launch iOS app",deviceId:e.id})}async function oC(e,t,r,a){let i=a?.maxScrolls??48,n=await e({command:"findText",text:r});if(n?.found)return{attempts:0};let o=oP(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let a=1;a<=i;a+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let i=await e({command:"findText",text:r});if(i?.found)return{attempts:a};let n=oP(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(n===o)throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a,stalled:!0});o=n}throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:i})}function oP(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function oR(e,t,r,a,i,n,o){if("tv"===t.target)return oF(await e(t,{command:"swipe",direction:function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left";default:return e}}(i),appBundleId:r.appBundleId},a),n);let s=o??await oT(e,t,r,a),l=ie({direction:i,amount:n?.amount,pixels:n?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return oF(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 oT(e,t,r,a){let i=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},a),n=o$(i.x),o=o$(i.y),s=o$(i.referenceWidth),l=o$(i.referenceHeight);if(void 0===n||void 0===o||void 0===s||void 0===l)throw new k("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:n,originY:o,referenceWidth:s,referenceHeight:l}}function o$(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function oF(e,t){var r;let{x1:a,y1:i,x2:n,y2:o}={x1:o$((r=e).x),y1:o$(r.y),x2:o$(r.x2),y2:o$(r.y2)},s=o$(e.referenceWidth),l=o$(e.referenceHeight),d=void 0!==a&&void 0!==n?Math.round(Math.abs(n-a)):void 0,u=void 0!==i&&void 0!==o?Math.round(Math.abs(o-i)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:d&&d>0?d:u&&u>0?u:void 0;return{...void 0!==a?{x1:a}:{},...void 0!==i?{y1:i}:{},...void 0!==n?{x2:n}:{},...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 oU(e){return e?.clickButton??"primary"}function oV(e){return"primary"===e.button?null:"click"!==e.commandLabel?new k("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new k("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new k("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 k("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let oG=/^[A-Za-z0-9_.:-]{1,64}$/,oj=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function oB(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new k("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function oq(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await oH(t)}async function oH(e){await new Promise(t=>setTimeout(t,e))}function oW(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new k("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!et.statSync(n).isFile())throw new k("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof k)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new k("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new k("COMMAND_FAILED",`Unable to read ${a} file: ${n}`,{cause:String(t)})}if((r=i.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:i};throw new k("INVALID_ARGS",`${a} file not found: ${n}`)}async function oz(e){let t=oW(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await oJ(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new k("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof k)throw t;throw new k("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function oJ(e){try{return await X.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new k("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new k("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new k("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new k("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let oK=eR(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),oX=/^(iphone|ipad|ipod|appletv)/i,oY=/^appletv/i,oZ=["apple tv","appletv","tvos"];function oQ(e){return(e??"").trim().toLowerCase()}function o0(e){return oQ(e.hardwareProperties?.platform)}function o1(e){return e.includes("tvos")}function o2(e){return o1(oQ(e))?"tv":"mobile"}function o3(e){let t=oQ(e);return t.includes("ios")||t.includes("tvos")}function o4(e){let t=oQ(e);return oZ.some(e=>t.includes(e))}function o8(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function o5(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function o6(e={}){let t,r,a=eV(e.simulatorSetPath),i=e.target;try{t=await v("xcrun",eB(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!o3(e))continue;let r=o2(e);if(!i||r===i)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...a?{simulatorSetPath:a}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function o9(e={}){if("darwin"!==process.platform)throw new k("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await C("xcrun"))throw new k("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eV(e.simulatorSetPath),a=await v("xcrun",eB(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(o3(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:o2(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new k("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(t.push({platform:"macos",id:"host-macos-local",name:ea.hostname(),kind:"device",target:"desktop",booted:!0}),r)return t;let i=null;try{i=l.join(ea.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await v("xcrun",["devicectl","list","devices","--json-output",i],{allowFailure:!0,timeoutMs:oK});if(0!==e.exitCode)return t;let r=await X.readFile(i,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(function(e){var t;let r=o0(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=o5(e),!!oX.test(t.trim())||o8(e).some(o4))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",a=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:a,kind:"device",target:function(e){var t;return o1(o0(e))?"tv":(t=o5(e),oY.test(t.trim())||o8(e).some(o4))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{i&&await X.rm(i,{force:!0}).catch(()=>{})}return t}async function o7(e,t,r){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await tt(e,t,r)}catch(e){if(i||!(e instanceof k)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!i&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!a||"device"===a.kind)){let e=await o6({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new k("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function se(e){let t=e.platform,r=te({simulatorSetPath:eV(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=ej(e.androidDeviceAllowlist);return await H("resolve_target_device",async()=>{let i={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(i.target&&!i.platform)throw new k("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await rK();let e=await ar({serialAllowlist:a});return await tt(e,i)}if(i.platform){let e=await o9({simulatorSetPath:r});return await o7(e,i,{simulatorSetPath:r})}let n=[];try{n.push(...await ar({serialAllowlist:a}))}catch{}try{n.push(...await o9({simulatorSetPath:r}))}catch{}return await tt(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function st(e,t,r,a,i){let n={requestId:i?.requestId,appBundleId:i?.appBundleId,verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>aJ(e,t,r?.activity),openDevice:()=>aX(e),close:t=>aY(e,t),tap:(t,r)=>ih(e,t,r),doubleTap:async(t,r)=>{await ih(e,t,r),await ih(e,t,r)},swipe:(t,r,a,i,n)=>iw(e,t,r,a,i,n),longPress:(t,r,a)=>iI(e,t,r,a),focus:(t,r)=>iS(e,t,r),type:(t,r)=>iA(e,t,r),fill:(t,r,a,i)=>i_(e,t,r,a,i),scroll:(t,r)=>iN(e,t,r),scrollIntoView:(t,r)=>iD(e,t,r),screenshot:(t,r)=>iZ(e,t),back:t=>ig(e),home:()=>iv(e),appSwitcher:()=>iy(e),readClipboard:()=>iT(e),writeClipboard:t=>i$(e,t),setSetting:(t,r,a,i)=>iB(e,t,r,a,i)};case"ios":case"macos":{var r,a;let i,n,{overrides:o,runnerOpts:s}=(r=e,i={verbose:(a=t).verbose,logPath:a.logPath,traceLogPath:a.traceLogPath,requestId:a.requestId},n=()=>{if(eN(a.requestId))throw ex()},{runnerOpts:i,overrides:{tap:async(e,t)=>await tF(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),doubleTap:async(e,t)=>await tF(r,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:a.appBundleId},i),swipe:async(e,t,n,o,s)=>await tF(r,{command:"drag",x:e,y:t,x2:n,y2:o,durationMs:s,appBundleId:a.appBundleId},i),longPress:async(e,t,n)=>await tF(r,{command:"longPress",x:e,y:t,durationMs:n,appBundleId:a.appBundleId},i),focus:async(e,t)=>await tF(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),type:async(e,t)=>{await tF(r,{command:"type",text:e,delayMs:t,appBundleId:a.appBundleId},i)},fill:async(e,t,n,o)=>{let s=await tF(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i);return await tF(r,{command:"type",x:e,y:t,text:n,clearFirst:!0,delayMs:o,appBundleId:a.appBundleId},i),s},scroll:async(e,t)=>await oR(tF,r,a,i,e,t),scrollIntoView:async(e,t)=>await oC(e=>tF(r,{...e,appBundleId:a.appBundleId},i),n,e,t)}});return{open:(t,r)=>oc(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>op(e),close:t=>of(e,t),screenshot:(t,r)=>n8(e,t,r),back:async r=>{await tF(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},s)},home:async()=>{await tF(e,{command:"home",appBundleId:t.appBundleId},s)},appSwitcher:async()=>{await tF(e,{command:"appSwitcher",appBundleId:t.appBundleId},s)},readClipboard:()=>ov(e),writeClipboard:t=>oy(e,t),setSetting:(t,r,a,i)=>oA(e,t,r,a,i),...o}}default:throw new k("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,n);return J({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await H("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new k("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null,...z("Opened device")};if(void 0!==a){if("android"===e.platform)throw new k("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(rZ(t))throw new k("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!rZ(a))throw new k("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId,url:a}),{app:t,url:a,...z(`Opened: ${t}`)}}return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId}),{app:t,...z(`Opened: ${t}`)}}case"close":{let e=r[0];if(!e)return{closed:"session",...z("Closed session")};return await o.close(e),{app:e,...z(`Closed: ${e}`)}}case"press":{let t,[a,n]=r.map(Number);if(Number.isNaN(a)||Number.isNaN(n))throw new k("INVALID_ARGS","press requires x y");let s=oU(i);if("primary"!==s){let t=oV({commandLabel:"click",platform:e.platform,button:s,count:i?.count,intervalMs:i?.intervalMs,holdMs:i?.holdMs,jitterPx:i?.jitterPx,doubleTap:i?.doubleTap});if(t)throw t;return await tF(e,{command:"mouseClick",x:a,y:n,button:s,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{x:a,y:n,button:s,...z(sr({x:a,y:n,button:s}))}}let l=oB(i?.count??1,"count",1,200),d=oB(i?.intervalMs??0,"interval-ms",0,1e4),u=oB(i?.holdMs??0,"hold-ms",0,1e4),c=oB(i?.jitterPx??0,"jitter-px",0,100),p=i?.doubleTap===!0;if(p&&u>0)throw new k("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(p&&c>0)throw new k("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&l>1&&0===u&&0===c){let t=await tF(e,{command:"tapSeries",x:a,y:n,count:l,intervalMs:d,doubleTap:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,timingMode:"runner-series",...t,...z(sr({x:a,y:n}))}}return await oq(l,d,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=oj[e%oj.length];return[r*t,a*t]}(e,c),s=a+r,l=n+i;if(p){t??=await o.doubleTap(s,l)??void 0;return}u>0?t??=await o.longPress(s,l,u)??void 0:t??=await o.tap(s,l)??void 0}),M({x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,...t},sr({x:a,y:n}))}case"swipe":{let t=Number(r[0]),a=Number(r[1]),n=Number(r[2]),s=Number(r[3]);if([t,a,n,s].some(Number.isNaN))throw new k("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=oB(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=oB(i?.count??1,"count",1,200),c=oB(i?.pauseMs??0,"pause-ms",0,1e4),p=i?.pattern??"one-way";if("one-way"!==p&&"ping-pong"!==p)throw new k("INVALID_ARGS",`Invalid pattern: ${p}`);if(("ios"===e.platform||"macos"===e.platform)&&u>1){let r=await tF(e,{command:"dragSeries",x:t,y:a,x2:n,y2:s,durationMs:d,count:u,pauseMs:c,pattern:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:p,...r,...z(sa(u,p))}}return await oq(u,c,async e=>{"ping-pong"===p&&e%2==1?await o.swipe(n,s,t,a,d):await o.swipe(t,a,n,s,d)}),M({x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:p},sa(u,p))}case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new k("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a,...z(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new k("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t,...z(`Focused (${e}, ${t})`)}}case"type":{let e=r.join(" ");if(!e)throw new k("INVALID_ARGS","type requires text");let t=oB(i?.delayMs??0,"delay-ms",0,1e4);return await o.type(e,t),{text:e,delayMs:t,...z(si("Typed",e))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new k("INVALID_ARGS","fill requires x y text");let n=oB(i?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,a,n),{x:e,y:t,text:a,delayMs:n,...z(si("Filled",a))}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0,a=i?.pixels;if(!e)throw new k("INVALID_ARGS","scroll requires direction");if(void 0!==t&&!Number.isFinite(t))throw new k("INVALID_ARGS","scroll amount must be a number");if(void 0!==t&&void 0!==a)throw new k("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let n=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new k("INVALID_ARGS",`Unknown direction: ${e}`)}}(e),s=await o.scroll(n,{amount:t,pixels:a});return M({direction:n,...void 0!==t?{amount:t}:{},...void 0!==a?{pixels:a}:{},...s},void 0!==a?`Scrolled ${n} by ${a}px`:void 0!==t?`Scrolled ${n} by ${t}`:`Scrolled ${n}`)}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new k("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:i?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...z(`Scrolled into view: ${e}`)};return{text:e,...z(`Scrolled into view: ${e}`)}}case"pinch":{if("android"===e.platform)throw new k("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");let t=Number(r[0]),a=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new k("INVALID_ARGS","pinch requires scale > 0");return await tF(e,{command:"pinch",scale:t,x:a,y:n,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{scale:t,x:a,y:n,...z(`Pinched to scale ${t}`)}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new k("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oG.test(t))throw new k("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 k("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 k("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 k("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof k)throw t;throw new k("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),n=function(e,t,r){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new k("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new k("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(n,{appBundleId:i?.appBundleId}),{event:t,eventUrl:n,transport:"deep-link",...z(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await X.mkdir(l.dirname(e),{recursive:!0}),await o.screenshot(e,i?.appBundleId),{path:e,...z(`Saved screenshot: ${e}`)}}case"back":return await o.back(i?.backMode),{action:"back",mode:i?.backMode??"in-app",...z("Back")};case"home":return await o.home(),{action:"home",...z("Home")};case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...z("Opened app switcher")};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new k("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new k("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await o.readClipboard()}}if(r.length<2)throw new k("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await o.writeClipboard(t),{action:e,textLength:Array.from(t).length,...z("Clipboard updated")}}case"keyboard":{let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new k("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new k("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===t){let t=await iR(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 r=await iP(e);return{platform:"android",action:"status",visible:r.visible,inputType:r.inputType,type:r.type}}if("ios"===e.platform){if("dismiss"!==t)throw new k("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let r=await tF(e,{command:"keyboardDismiss",appBundleId:i?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:r.wasVisible,dismissed:r.dismissed,visible:r.visible,...z(r.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new k("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}case"settings":{var s;let[t,a,n,l,d]=r,u="permission"===t?{permissionTarget:n,permissionMode:l}:void 0;J({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:n,mode:l,platform:e.platform}});let c=await o.setSetting(t,a,d??i?.appBundleId,u);return c&&"object"==typeof c?M({setting:t,state:a,...c},("string"==typeof(s=c).message&&s.message.length>0?s.message:void 0)??`Updated setting: ${t}`):{setting:t,state:a,...z(`Updated setting: ${t}`)}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new k("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await oz(a);if("ios"===e.platform)return await oI(e,t,i),{platform:"ios",bundleId:t,...z(`Pushed notification to ${t}`)};let n=await iX(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount,...z(`Pushed notification to ${t}`)}}case"snapshot":{if("android"!==e.platform){let t=await H("snapshot_capture",async()=>await tF(e,{command:"snapshot",appBundleId:i?.appBundleId,interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new k("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await H("snapshot_capture",async()=>await id(e,{interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}case"read":{let[t,a]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(a))throw new k("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await iL(e,t,a)??""};if("macos"===e.platform&&i?.surface&&"app"!==i.surface)return{action:"read",text:(await nP(t,a,{bundleId:i.appBundleId,surface:i.surface})).text};let n=await tF(e,{command:"readText",x:t,y:a,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{action:"read",text:"string"==typeof n.text?n.text:"string"==typeof n.message?n.message:""}}default:throw new k("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}function sr(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function sa(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function si(e,t){return`${e} ${Array.from(t).length} chars`}let sn=e=>"macos"!==e.platform,so={alert:{apple:{simulator:!0,device:!0},android:{},supports:e=>"macos"===e.platform||"simulator"===e.kind},pinch:{apple:{simulator:!0},android:{}},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sn},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:sn},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:sn},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:sn},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sn},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sn},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:sn},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function ss(e,t){let r=so[e];if(!r)return!0;let a=e9(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function sl(e,t,r,a,i){return{requestId:i??B().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:oU(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let sd=eR(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function su(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:ns}));await t(e);return}if("device"===e.kind)return void await sc(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:ad}));await t(e.id)}}async function sc(e){let t=l.join(ea.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(sd/1e3));try{let a=await v("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:sd+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await sp(t);if(0===a.exitCode){if(!o.parsed)throw new k("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new k("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 k("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:n,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sf(i,n)})}catch(t){if(t instanceof k&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),i=String(r.stderr??""),n=Number(r.timeoutMs??sd),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new k("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?sf(a,i):o},t)}throw new k("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,hint:"Reconnect the device, keep it unlocked, and retry."},t instanceof Error?t:void 0)}finally{await X.rm(t,{force:!0}).catch(()=>{})}}async function sp(e){try{let t=await X.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof r?r:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sf(e,t){let r=nr(e,t);return r||(`${e}
|
|
33
|
+
${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":nt)}let sm=eR(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),sh=new Map;async function sw(e){let t=await n.mkdtemp(l.join(ea.tmpdir(),"agent-device-materialized-"));try{let r=await sy(e.installablePath,l.join(t,"installable")),a=e.archivePath?await sy(e.archivePath,l.join(t,"archive")):void 0,i=g.randomUUID(),n=e.ttlMs??sm,o=Date.now()+n,s=setTimeout(()=>{sg(i)},n);return sh.set(i,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:o,timer:s}),{materializationId:i,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(o).toISOString()}}catch(e){throw await n.rm(t,{recursive:!0,force:!0}),e}}async function sg(e,t){let r=sh.get(e);if(!r)throw new k("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new k("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),sh.delete(e),await n.rm(r.rootPath,{recursive:!0,force:!0})}async function sv(e){let t=Array.from(sh.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await sg(e)}))}async function sy(e,t){let r=await n.stat(e);await n.mkdir(t,{recursive:!0});let a=l.join(t,l.basename(e));return r.isDirectory()?await n.cp(e,a,{recursive:!0}):await n.copyFile(e,a),a}async function sI(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 k("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await su(e.session.device),e.session.device}if(!r)throw new k("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await se(e.flags??{});return await su(a),a}async function sA(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);try{let e,n,o,s=(n=function(e){let t=e.meta?.installSource;if(!t)throw new k("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new k("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new k("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:rh(o,t.meta?.tenantId)},cleanup:()=>{rw(o)}}:{source:n,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 k("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await sI({session:i,flags:t.flags});if(!ss("install",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let u=eD(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await Promise.resolve().then(()=>({installIosInstallablePath:og})),{prepareIosInstallArtifact:o}=await Promise.resolve().then(()=>({prepareIosInstallArtifact:nc})),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await sw({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(d,c.installablePath),!c.bundleId)throw new k("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=M(o,sb(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await sg(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await Promise.resolve().then(()=>({prepareAndroidInstallArtifact:aP})),{installAndroidInstallablePathAndResolvePackageName:p}=await Promise.resolve().then(()=>({installAndroidInstallablePathAndResolvePackageName:a6})),f=await c(s.source,{signal:u});try{l.enabled&&(e=await sw({archivePath:f.archivePath,installablePath:f.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await p(d,f.installablePath,f.packageName);if(!n)throw new k("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await Promise.resolve().then(()=>({inferAndroidAppName:aH})),s=o(n),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=M(u,sb(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await sg(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await f.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:U(e)}}}function sb(e){return`Installed: ${s(e)}`}async function sS(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new k("INVALID_ARGS","release_materialized_paths requires a materializationId");return await sg(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:U(e)}}}let s_=eR(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),sN=eR(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function sD(e,t,r){return t||sx(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function sx(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function sk(e){return"ios"===e.platform&&"simulator"===e.kind}async function sM(e,t){sk(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function sE(e){let t=sx(e.flags)||!e.session?await se(e.flags??{}):await sO(e.session.device);return!1!==e.ensureReady&&await su(t),t}async function sO(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 se(t)}catch(e){if(!(e instanceof k)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await se({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function sL(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 sC="shared_prefs/ReactNativeDevPrefs.xml",sP="debug_http_host",sR="dev_server_https",sT="RCT_jsLocation",s$="RCT_packager_scheme",sF="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.",sU='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function sV(e){return void 0!==sG(e)}function sG(e){if(!e)return;let t=sQ(e.metroHost),r=s1(e.metroPort),a="http",i=sQ(e.bundleUrl);if(i){var n;let e;try{e=new L(i)}catch(e){throw new k("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=sQ(e.hostname),r??=s1(e.port.length>0?Number(e.port):"https:"===(n=e.protocol)?443:"http:"===n?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function sj(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=sG(a);if(i){if("android"===t.platform)return void await sq(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await sJ(t,r,i)}}async function sB(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await sH(t,r);"ios"===t.platform&&"simulator"===t.kind&&await sK(t,r)}}async function sq(e,t,r){var a,i,n,o,s,l;let d,u;s0(t);let c=(a=await sW(e,t),i=sP,n=`${r.host}:${r.port}`,d=` <string name="${s2(i)}">${s2(n)}</string>`,sY(sZ(a,i),d));o=c,s=sR,l="https"===r.scheme,u=` <boolean name="${s2(s)}" value="${l?"true":"false"}" />`,c=sY(sZ(o,s),u),await sz(e,t,c)}async function sH(e,t){s0(t);let r=await sW(e,t),a=sZ(r,sP),i=sZ(a,sR);i!==r&&await sz(e,t,i)}async function sW(e,t){let r=await v("adb",rJ(e,["shell","run-as",t,"cat",sC]),{allowFailure:!0});return 0!==r.exitCode?sU:sX(r.stdout)}async function sz(e,t,r){let a=rJ(e,["shell","run-as",t,"id"]),i=await v("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=s3(i.stdout,i.stderr);throw new k("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?sF:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await v("adb",rJ(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await v("adb",rJ(e,["shell","run-as",t,"tee",sC]),{stdin:r.trimEnd()})}catch(a){let e=N(a);if("TOOL_MISSING"===e.code)throw e;let r=s3("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new k("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?sF:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function sJ(e,t,r){await v("xcrun",eq(e,["spawn",e.id,"defaults","write",t,sT,"-string",`${r.host}:${r.port}`])),await v("xcrun",eq(e,["spawn",e.id,"defaults","write",t,s$,"-string",r.scheme]))}async function sK(e,t){await v("xcrun",eq(e,["spawn",e.id,"defaults","delete",t,sT]),{allowFailure:!0}),await v("xcrun",eq(e,["spawn",e.id,"defaults","delete",t,s$]),{allowFailure:!0})}function sX(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
34
|
+
`:sU}function sY(e,t){return sX(e).replace("</map>",`${t}
|
|
35
|
+
</map>`)}function sZ(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return sX(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 sQ(e){let t=e?.trim();return t&&t.length>0?t:void 0}function s0(e){if("binary"!==ap(e))return;let t=af(e);throw new k("INVALID_ARGS",t,{package:e,hint:t})}function s1(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function s2(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function s3(e,t){let r=`${e}
|
|
36
|
+
${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}let s4=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function s8(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function s5(e){let t=e?.trim();return t&&t.length>0?t:void 0}function s6(e,t){if(void 0!==e){if("string"!=typeof e)throw new k("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return s5(e)}}function s9(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new k("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function s7(e){if("ios"===e||"android"===e)return e}async function le(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!sV(r)||sV(a)||await sB({device:i.device,appId:i.appBundleId})}async function lt(e){var t,r;let{req:a,sessionName:i,sessionStore:n}=e,o=(a.positionals?.[0]??"show").toLowerCase(),s=n.get(i),l=n.getRuntimeHints(i);if(!["set","show","clear"].includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===o){sV(l)&&s?.appBundleId&&await sB({device:s.device,appId:s.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===o)return{ok:!0,data:{session:i,configured:!!l,runtime:l}};let d=s7(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 "${i}" is already bound to ${s.device.platform}.`}};let u={platform:(t=a.flags,r={platform:d,metroHost:s5(t?.metroHost),metroPort:s9(t?.metroPort),bundleUrl:s5(t?.bundleUrl),launchUrl:s5(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===s8(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."}}:(n.setRuntimeHints(i,u),{ok:!0,data:{session:i,configured:!0,runtime:u}})}let lr="open-command-roundtrip",la="Not implemented for this platform in this release.";async function li(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await nM();return{appBundleId:t.bundleId,appName:t.appName}}async function ln(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return rZ(t)?"macos"===e.platform?void 0:"device"===e.kind?rQ(r,t):void 0:await lo(e,t)}async function lo(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:ou}));return await r(e,t)}catch{return}}async function ls(e,t){if(!("android"!==e.platform||!t||rZ(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:aV})),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function ll(e,t,r,a){return await ln(e,t,r)??await a(e,t)??("android"===e.platform&&t&&rZ(t)?r:void 0)}function ld(e){return{ok:!1,error:{code:"INVALID_ARGS",message:e}}}function lu(e,t,r,a){try{return function(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:i}=e;if("macos"===t.platform&&!r)return i??"app";if("macos"!==t.platform){if(r)throw new k("INVALID_ARGS","surface is only supported on macOS");return"app"}let n=r?u(r):"app";if("app"!==n&&a)throw new k("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return{ok:!1,error:{code:e instanceof k?e.code:"INVALID_ARGS",message:String(e.message)}}}}function lc(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&rZ(r)?ld("open --relaunch does not support URL targets."):"app"!==a?ld("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===ap(r)?ld(af(r)):null:null}async function lp(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await su(i);let{appBundleId:l,appName:d}=await lf({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new k("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!s4.includes(e));if(i)throw new k("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${s4.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new k("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new k("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:s6(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new k("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return s9(e)}}(t.metroPort),bundleUrl:s6(t.bundleUrl,"bundleUrl"),launchUrl:s6(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:s7(i.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let i=r?.platform,n=s7(i);if(a.platform&&r&&!n)throw new k("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new k("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&s8(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=N(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}({req:t,sessionStore:a,sessionName:r,device:i});if(!u.ok)return{type:"response",response:u.response};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await le({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function lf(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await li(r);return{appBundleId:n.appBundleId??await ll(t,a,i,ls),appName:n.appName??a}}async function lm(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await tO(t.id),await st(t,"close",[r],a,i),await sM(t,s_)}async function lh(e){let{runtime:t,device:r,req:a,logPath:i,appBundleId:n,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let d=s[0]?.trim();!d||rZ(d)||await st(r,"open",[l],a.flags?.out,{...sl(i,a.flags,n,o)})}async function lw(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:p,appBundleId:f,runtime:m,existingSession:h}=e,w=i.flags?.relaunch===!0,g=h?.trace?.outPath;if(w&&d){let e=f??d;await lm({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...sl(s,i.flags,f??h?.appBundleId,g)}})}await sj({device:l,appId:f,runtime:m});let v=Date.now();await st(l,"open",u,i.flags?.out,{...sl(s,i.flags,f)}),await lh({runtime:m,device:l,req:i,logPath:s,appBundleId:f,traceLogPath:g,openPositionals:u});let y=d?{durationMs:Math.max(0,Date.now()-v),measuredAt:new Date().toISOString(),method:lr,appTarget:d,appBundleId:f}:void 0;await sM(l,sN);let I=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:n,device:l,surface:p,appBundleId:f,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===s8(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let A=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:i,startup:n,device:o,runtime:s,runtimeHintCount:l}=e,d={session:t,surface:i};return r&&(d.appName=r),a&&(d.appBundleId=a),n&&(d.startup=n),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,...z(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:f,surface:p,startup:y,device:l,runtime:m,runtimeHintCount:s8});return o.recordAction(I,{command:"open",positionals:u,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:A}),o.set(n,I),{ok:!0,data:A}}async function lg(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:`Session "${r}" not found.`}};let n=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(n?e.appName:void 0),l=lu(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?ld("open --relaunch requires an app name or an active session app."):ld("Session already active. Close it first or pass a new --session name.");let d=lc({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await sO(e.device),c=await lp({req:t,sessionName:r,sessionStore:i,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await lw({req:t,sessionName:r,sessionStore:i,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 n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return ld("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&rZ(r)?ld("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===ap(r)?ld(af(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await se(t.flags??{}),d=lu(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=lc({shouldRelaunch:n,openTarget:o,surface:d,device:l});if(u)return u;let c=i.toArray().find(e=>e.device.id===l.id);if(c)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${c.name}".`,details:{session:c.name,deviceId:l.id,deviceName:l.name}}};let p=await lp({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:o});return"response"===p.type?p.response:await lw({req:t,sessionName:r,sessionStore:i,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:p.details.appBundleId,appName:p.details.appName,runtime:p.details.runtime,surface:d})}async function lv(e){let t=await v("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 ly(e){let{device:t,shutdownRequested:r}=e;if(r&&(sk(t)||"android"===t.platform&&"emulator"===t.kind))try{return sk(t)?await nl(t):await lv(t)}catch(t){let e=U(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function lI(e){if(await tO(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await nL("dismiss",t).catch(t=>{J({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function lA(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};n.appLog&&await rd(n.appLog),t.positionals&&t.positionals.length>0&&(("ios"===n.device.platform||"macos"===n.device.platform)&&await lI(n),await st(n.device,"close",t.positionals,t.flags?.out,{...sl(a,t.flags,n.appBundleId,n.trace?.outPath)}),await sM(n.device,s_)),("ios"===n.device.platform||"macos"===n.device.platform)&&await lI(n),sV(i.getRuntimeHints(r))&&n.appBundleId&&await sB({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...z(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await sv(r).catch(()=>{}),i.delete(r);let o=await ly({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:M({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...z(`Closed: ${r}`)}}}let lb={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve().then(()=>({reinstallIosApp:ow}));return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve().then(()=>({reinstallAndroidApp:a7}));return await a(e,t,r)}},lS={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve().then(()=>({installIosApp:oh})),i=await a(e,r,{appIdentifierHint:t});return{bundleId:i.bundleId,appName:i.appName,launchTarget:i.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await Promise.resolve().then(()=>({installAndroidApp:a9})),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function l_(e){let{req:t,command:r,sessionName:a,sessionStore:i,deployOps:n}=e,o=i.get(a),s=t.flags??{},l=sD(r,o,s);if(l)return l;let d=t.positionals?.[0]?.trim(),u=t.positionals?.[1]?.trim();if(!d||!u)return{ok:!1,error:{code:"INVALID_ARGS",message:`${r} requires: ${r} <app> <path-to-app-binary>`}};let c=t.meta?.uploadedArtifactId;try{var p;let e,a=c?rh(c,t.meta?.tenantId):t3.expandHome(u);if(!et.existsSync(a))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${a}`}};let l=await sE({session:o,flags:s,ensureReady:!1});if(!ss(r,l))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${r} is not supported on this device`}};if("ios"===l.platform){let t=await n.ios(l,d,a),r=t.bundleId;e=r?{app:d,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await n.android(l,d,a),r=t.package;e=r?{app:d,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let f=M(e,(p=e,`Installed: ${p.appName??I(p)}`));return o&&i.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:f}),{ok:!0,data:f}}finally{c&&rw(c)}}let lN=["platform","target","device","udid","serial","verbose","out"];async function lD(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${a}.`}};let i=e.flags?.batchMaxSteps??Y;if(!Number.isInteger(i)||i<1||i>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let a=y(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await lx(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=N(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function lx(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{},o=e??{};for(let e of lN)void 0===n[e]&&void 0!==o[e]&&(n[e]=o[e]);return n}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}async function lk(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new k("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await lM({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await lE({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lO(t,u),a=!0)}else t=(await lE({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lO(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function lM(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await v("xcrun",eB(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:i3});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||lL(a).includes(lL(r))){for(let e of i)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function lE(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await v("xcrun",eB(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new k("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(n.stdout??"").trim();if(!o)throw new k("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function lO(e,t){let r=await v("xcrun",eB(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:i3});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 lL(e){return e.toLowerCase().replace(/[._-]/g,"")}async function lC(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,i=eV(e.iosSimulatorDeviceSet);if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let n=await lk({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:su});return{ok:!0,data:{udid:n.udid,device:n.device,runtime:n.runtime,ios_simulator_device_set:i??null,created:n.created,booted:n.booted}}}catch(t){let e=N(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===t.command)try{let e=[],r=ej(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,i=te({simulatorSetPath:eV(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:ar}));e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await Promise.resolve().then(()=>({listAppleDevices:o9}));e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:ar}));try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await Promise.resolve().then(()=>({listAppleDevices:o9}));try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=N(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=sD(t.command,e,i);if(n)return n;let o=await sE({session:e,flags:i,ensureReady:!0});if(!ss("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(e9(o.platform)){let{listIosApps:e}=await Promise.resolve().then(()=>({listIosApps:ob}));return{ok:!0,data:{apps:(await e(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await Promise.resolve().then(()=>({listAndroidApps:aG}));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 lP(e){let{ensureAndroidEmulatorBooted:t}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:al}));return await t(e)}let lR='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',lT='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function l$(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=n.platform;if(!i&&"string"==typeof n?.session&&n.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=sD("appstate",i,n);if(s)return s;let l=(i?.device.platform==="ios"||i?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!sx(e))return!0;let r=e?.platform;return!(r&&!e7(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())}(n,i);if("ios"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lR}};if("macos"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lT}};if(l&&i){let e=i.appName??i.appBundleId;if(!i.appName&&!i.appBundleId){if("macos"===i.device.platform&&i.surface&&"app"!==i.surface&&"frontmost-app"!==i.surface)return{ok:!0,data:{platform:i.device.platform,appName:i.surface,appBundleId:i.appBundleId,source:"session",surface:i.surface}};let e="macos"===i.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:i.device.platform,appName:e??"unknown",appBundleId:i.appBundleId,source:"session",surface:i.surface??"app",..."ios"===i.device.platform?{device_udid:i.device.id,ios_simulator_device_set:i.device.simulatorSetPath??null}:{}}}}let d=await sE({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lR}};if("macos"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lT}};let{getAndroidAppState:u}=await Promise.resolve().then(()=>({getAndroidAppState:aW})),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function lF(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=sD(t.command,i,n);if(o)return o;let s="android"===(n.platform??i?.device.platform),l=!0===n.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=sL({flags:n,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await sE({session:i,flags:n,ensureReady:!1})}catch(r){let t=N(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 lP({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${n.target}.`}};if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};if(!c){let t=sL({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await lP({avdName:t,serial:n.serial,headless:!0})}await su(e)}else("android"!==e.platform||!0!==e.booted)&&await su(e);return ss("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 l$({req:t,sessionName:r,sessionStore:a}):null}let lU=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),lV=/https?:\/\/[^\s"'<>\])]+/i,lG=[/\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 lj(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 lB(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return lq(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 lq(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function lH(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function lW(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}let lz=["path","start","stop","doctor","mark","clear"],lJ=`logs requires ${lz.slice(0,-1).join(", ")}, or ${lz.at(-1)}`,lK=["dump","log"],lX=`network requires ${lK.join(" or ")}`,lY=["summary","headers","body","all"],lZ=`network include mode must be one of: ${lY.join(", ")}`;function lQ(e){return e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"}async function l0(e){let{req:t,sessionName:r,sessionStore:a}=e;if("perf"===t.command){let e,t,i,n=a.get(r);return n?{ok:!0,data:(i=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===lr&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:lr,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(n.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:lr,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:lr},{session:n.name,platform:n.device.platform,device:n.device.name,deviceId:n.device.id,metrics:{startup:i,fps:{available:!1,reason:la},memory:{available:!1,reason:la},cpu:{available:!1,reason:la}},sampling:{startup:{method:lr,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"}}})}:{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}}}if("logs"===t.command){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!ss("logs",e.device))return{ok:!1,error:U(new k("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let i=(t.positionals?.[0]??"path").toLowerCase(),n=!!t.flags?.restart;if(!lz.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:lJ}};if(n&&"clear"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===i){let t=a.resolveAppLogPath(r),i=function(e){if(!et.existsSync(e))return{exists:!1,sizeBytes:0};let t=et.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:lQ(e),sizeBytes:i.sizeBytes,modifiedAt:i.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===i){let t=a.resolveAppLogPath(r),i=await ru(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}if("mark"===i){let e,i=t.positionals?.slice(1).join(" ")??"",n=a.resolveAppLogPath(r);return rs(n),e=`[agent-device][mark][${new Date().toISOString()}] ${i.trim()||"marker"}
|
|
37
|
+
`,et.appendFileSync(n,e,"utf8"),{ok:!0,data:{path:n,marked:!0}}}if("clear"===i){if(e.appLog&&!n)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(n&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let t=a.resolveAppLogPath(r);if(!n)return{ok:!0,data:rc(t)};e.appLog&&await rd(e.appLog);let i=rc(t),o=a.resolveAppLogPidPath(r);try{let n=await rl(e.device,e.appBundleId,t,o);return a.set(r,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{...i,restarted:!0}}}catch(t){return a.set(r,{...e,appLog:void 0}),{ok:!1,error:U(t)}}}if("start"===i){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};let t=a.resolveAppLogPath(r),i=a.resolveAppLogPidPath(r);try{let n=await rl(e.device,e.appBundleId,t,i);return a.set(r,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:U(e)}}}if("stop"===i){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await rd(e.appLog),a.set(r,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===t.command){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!ss("network",e.device))return{ok:!1,error:U(new k("UNSUPPORTED_OPERATION","network is not supported on this device"))};let i=(t.positionals?.[0]??"dump").toLowerCase();if(!lK.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:lX}};let n=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(n)||n<1||n>200)return{ok:!1,error:{code:"INVALID_ARGS",message:"network dump limit must be an integer in range 1..200"}};let o=(t.positionals?.[2]??"summary").toLowerCase();if(!lY.includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:lZ}};let s=function(e,t){let r=lW(t?.maxEntries,25,1,200),a=t?.include??"summary",i=lW(t?.maxPayloadChars,2048,64,16384),n=lW(t?.maxScanLines,4e3,100,2e4);if(!et.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}};let o=et.readFileSync(e,"utf8").split("\n"),s=Math.max(0,o.length-n),l=o.slice(s),d=[];for(let e=l.length-1;e>=0&&d.length<r;e-=1){let t=l[e]?.trim();if(!t)continue;let r=function(e,t,r,a){let i=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(e),n=lj(i,["method","httpMethod"]),o=lj(i,["url","requestUrl"]),s=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(i,["status","statusCode","responseCode"]),l=lU.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(n??d?.[1]??l?.[1])?.toUpperCase(),c=lV.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of lG){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}(e)??void 0,timestamp:function(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);return t?.[0]}(e),raw:lH(e,a),line:t};if("headers"===r||"all"===r){let t=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return lq(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,i);t&&(f.headers=lH(t,a))}if("body"===r||"all"===r){let t=lB(e,i,["requestBody","body","payload","request"]),r=lB(e,i,["responseBody","response"]);t&&(f.requestBody=lH(t,a)),r&&(f.responseBody=lH(r,a))}return f}(t,s+e+1,a,i);r&&d.push(r)}return{path:e,exists:!0,scannedLines:l.length,matchedLines:d.length,entries:d,include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}}}(a.resolveAppLogPath(r),{maxEntries:n,include:o,maxPayloadChars:2048,maxScanLines:4e3}),l=[];return e.appLog||l.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===s.entries.length&&l.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...s,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:lQ(e),notes:l}}}return null}let l1=new Set(["ios","android","macos"]);function l2(e,t,r){let a=e[t];if(void 0!==a)throw new k("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 l3(e){return!!e&&!Number.isNaN(Number(e))}let l4=/[*?[\]{}]/;async function l8(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,runReplay:s,cleanupSession:l}=e;eb(i);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:i,artifactPaths:d}).catch(e=>{let t=N(e);return{ok:!1,error:{code:t.code,message:t.message}}});try{return"number"==typeof n?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,eS(i),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}}}}(n,[...d]))},n)})]):await c}finally{t&&clearTimeout(t),u&&(await l5(c)||J({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}})),e_(i);try{await l(a)}catch(e){J({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:N(e).message}})}}}async function l5(e){return await Promise.race([e.then(()=>!0),o(2e3).then(()=>!1)])}async function l6(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:i}=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 n,o,s,d,u,c;let e,p,f,m,h,w=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,i=r??process.cwd(),n=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let i=t3.expandHome(e,t);if(et.existsSync(i)){let t=et.statSync(i);if(t.isDirectory())return et.globSync("**/*.ad",{cwd:i}).map(e=>l.join(i,e));if(t.isFile()){if(".ad"!==l.extname(i))throw new k("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[i]}return[]}if(r=e,!l4.test(r)&&(a=i,!l4.test(a)))throw new k("INVALID_ARGS",`test input not found: ${e}`);let n=l.isAbsolute(i)?i:e;return et.globSync(n,{cwd:l.isAbsolute(i)?void 0:t}).map(e=>l.isAbsolute(e)?e:l.resolve(t,e)).filter(e=>".ad"===l.extname(e)&&function(e){try{return et.statSync(e).isFile()}catch{return!1}}(e))})(e,i)))].map(e=>l.normalize(e)).sort((e,t)=>e.localeCompare(t)),o=[];for(let e of n){var s,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&&l1.has(e)&&l2(r,"platform",e)}let i=t.match(/(?:^|\s)timeout=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=1&&l2(r,"timeoutMs",Math.floor(e))}let n=t.match(/(?:^|\s)retries=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=0&&l2(r,"retries",Math.floor(e))}}return r}(et.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}s=a,d=t.platform,("apple"===s?"apple"===d||"ios"===d||"macos"===d:d===s)&&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 k("INVALID_ARGS",`No .ad tests matched${e}.`)}return o}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),g=(n=t.meta?.requestId,(n?.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,i=t3.expandHome(t??".agent-device/test-artifacts",r);return l.join(i,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:g}),y=[],I=Date.now(),A=0;for(let e of w){if("skip"===e.kind){y.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}A+=1;let n=await l9({entry:e,sessionName:r,suiteInvocationId:g,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,s=e.metadata.timeoutMs,"number"==typeof o?o:s),suiteArtifactsDir:v,runReplay:a,cleanupSession:i});if(y.push(n),t.flags?.failFast===!0)break}let b=(d=w.length,u=y,c=Date.now()-I,e=u.filter(e=>"passed"===e.status).length,f=(p=u.filter(e=>"failed"===e.status)).length,m=u.filter(e=>"skipped"===e.status).length,h=e+f,{total:d,executed:h,passed:e,failed:f,skipped:m,notRun:Math.max(0,d-h-m),durationMs:c,failures:p,tests:u});return{ok:!0,data:b}}catch(t){let e=N(t);return{ok:!1,error:{code:e.code,message:e.message}}}}async function l9(e){var t,r;let a,i,{entry:n,sessionName:o,suiteInvocationId:s,caseIndex:d,cwd:u,requestId:c,retries:p,timeoutMs:f,suiteArtifactsDir:m,runReplay:h,cleanupSession:w}=e,g=Date.now(),v=l.join(m,(t=n.path,(0===(i=u?l.relative(u,t):l.basename(t)).length||i.startsWith("..")?l.basename(t):i).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),y="",I=0;for(let e=0;e<=p;e+=1){I=e+1;let t=function(e,t,r,a,i=0){let n=l.basename(r,l.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${n?`-${n}`:""}:attempt-${i+1}`}(o,s,n.path,d,e),i=l.join(v,`attempt-${I}`);r=n.path,et.mkdirSync(i,{recursive:!0}),et.copyFileSync(r,l.join(i,"replay.ad"));let u=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:n}=e;return eA(`${t??r}:test:${i+1}:${l.basename(a)}:attempt:${n+1}`,r)}({requestId:c,suiteInvocationId:s,filePath:n.path,caseIndex:d,attemptIndex:e}),m=await l8({filePath:n.path,sessionName:t,requestId:u,timeoutMs:f,platform:n.metadata.platform,runReplay:h,cleanupSession:w});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:i,maxAttempts:n,attemptArtifactsDir:o}=e,s=[...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||s.push(t.error.logPath);let d=function(e,t){let r=[],a=new Map;for(let i of e){if(!function(e){try{return et.statSync(e).isFile()}catch{return!1}}(i))continue;let e=function(e,t){let r=l.extname(e),a=r?e.slice(0,-r.length):e,i=t.get(e)??0;return(t.set(e,i+1),0===i)?e:`${a}-${i+1}${r}`}(l.basename(i),a),n=l.join(t,e);l.resolve(i)!==l.resolve(n)&&et.copyFileSync(i,n),r.push(n)}return r}(s,o),u=[`file: ${r}`,`session: ${a}`,`attempt: ${i}/${n}`,`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=>l.basename(e)).join(", ")}`);let c=l.join(o,"result.txt"),p=`${u.join("\n")}
|
|
38
|
+
`;et.writeFileSync(c,p),t.ok||et.writeFileSync(l.join(o,"failure.txt"),p)}({response:m,filePath:n.path,sessionName:t,attempts:I,maxAttempts:p+1,attemptArtifactsDir:i}),a=m,y=t,m.ok)break}let A=Date.now()-g;if(a?.ok)return{file:n.path,session:y,status:"passed",durationMs:A,attempts:I,artifactsDir:v,replayed:"number"==typeof a.data?.replayed?a.data.replayed:0,healed:"number"==typeof a.data?.healed?a.data.healed:0};let b=a?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:a?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:n.path,session:y,status:"failed",durationMs:A,attempts:I,artifactsDir:v,error:b}}function l7(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function de(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function dt(e,t){return e.find(e=>e.ref===t)??null}function dr(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function da(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),a=(e.value??"").toLowerCase(),i=(e.identifier??"").toLowerCase();return t.includes(r)||a.includes(r)||i.includes(r)})??null}function di(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&&dn(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||!dn(t))continue;let i=Math.abs(e.rect.y+e.rect.height/2-r);(!a||i<a.distance)&&(a={label:t,distance:i})}return a?.label}(e,t)??(r&&dn(r)?r:void 0)}function dn(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function ds(e){let t=[],r=[];for(let a of e){let e=a.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let i=dl(a.type??""),n=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&dn(n);if(("group"===i||"ioscontentgroup"===i)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...a,depth:s})}return r}function dl(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 dd(e,t){let r=dl(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 du(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 dc(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let dp=new Set(["id","role","text","label","value"]),df=new Set(["visible","hidden","editable","selected","enabled","hittable"]),dm=new Set([...dp,...df]);function dh(e){let t=e.trim();if(!t)throw new k("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!dA(e,i)){a?a===n&&(a=null):a=n,r+=n;continue}if(!a&&"|"===n&&"|"===e[i+1]){let a=r.trim();if(!a)throw new k("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",i+=1;continue}r+=n}let i=r.trim();if(!i)throw new k("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(i),t}(t);if(0===r.length)throw new k("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new k("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!dA(e,i)){a?a===n&&(a=null):a=n,r+=n;continue}if(!a&&/\s/.test(n)){r.trim().length>0&&t.push(r.trim()),r="";continue}r+=n}if(a)throw new k("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim().length>0&&t.push(r.trim()),t}(t);if(0===r.length)throw new k("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(dy)}})(e))}}function dw(e){try{return dh(e)}catch{return null}}function dg(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,a=0,i=[];for(;a<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return dm.has(e)}return dm.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&dw(t)&&i.push(a)}if(0===i.length)return null;let n=i[i.length-1];if(r){for(let t=i.length-1;t>=0;t-=1)if(i[t]<e.length){n=i[t];break}}let o=e.slice(0,n).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(n)}:null}function dv(e){let t=e[0]??"",r=dg(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function dy(e){let t=e.trim();if(!t)throw new k("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!df.has(r))throw new k("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),i=t.slice(r+1).trim();if(!dm.has(a))throw new k("INVALID_ARGS",`Unknown selector key: ${a}`);if(!i)throw new k("INVALID_ARGS",`Missing selector value for key: ${a}`);if(df.has(a)){let e,t="true"===(e=dI(i).toLowerCase())||"false"!==e&&null;if(null===t)throw new k("INVALID_ARGS",`Invalid boolean value for ${a}: ${i}`);return{key:a,value:t}}return{key:a,value:dI(i)}}function dI(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function dA(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function db(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return dN(e.identifier,String(t.value));case"role":var a,i;return a=e.type,i=String(t.value),function(e){return dl(e)}(a??"")===function(e){return dl(e)}(i);case"label":return dN(e.label,String(t.value));case"value":return dN(e.value,String(t.value));case"text":{let r=dD(String(t.value));return dD(dc(e))===r}case"visible":return dS(e)===!!t.value;case"hidden":return!dS(e)==!!t.value;case"editable":return d_(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 dS(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function d_(e,t){return dd(e.type??"",t)&&!1!==e.enabled}function dN(e,t){return dD(e??"")===dD(t)}function dD(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function dx(e,t,r){let a=r.requireRect??!1,i=r.requireUnique??!0,n=r.disambiguateAmbiguous??!1,o=[];for(let s=0;s<t.selectors.length;s+=1){let l=t.selectors[s],d=function(e,t,r){let a=0,i=null,n=null,o=!1;for(let s of e){if(r.requireRect&&!s.rect||!db(s,t,r.platform))continue;if(a+=1,i||(i=s),!n){n=s;continue}let e=function(e,t){let r=e.depth??0,a=t.depth??0;if(r!==a)return r>a?1:-1;let i=dE(e),n=dE(t);return i!==n?i<n?1:-1:0}(s,n);if(e>0){n=s,o=!1;continue}0===e&&(o=!0)}return{count:a,firstNode:i,disambiguated:o?null:n}}(e,l,{platform:r.platform,requireRect:a});if(o.push({selector:l.raw,matches:d.count}),0!==d.count&&d.firstNode){if(i&&1!==d.count){if(!n)continue;let e=d.disambiguated;if(!e)continue;return{node:e,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}return{node:d.firstNode,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}}return null}function dk(e,t,r){let a=r.requireRect??!1,i=[];for(let n=0;n<t.selectors.length;n+=1){let o=t.selectors[n],s=function(e,t,r){let a=0;for(let i of e)(!r.requireRect||i.rect)&&db(i,t,r.platform)&&(a+=1);return a}(e,o,{platform:r.platform,requireRect:a});if(i.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:n,selector:o,matches:s,diagnostics:i}}return null}function dM(e,t,r){let a=r.unique??!0;if(0===t.length)return`Selector did not match: ${e.raw}`;let i=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return a?`Selector did not resolve uniquely (${i})`:`Selector did not match (${i})`}function dE(e){return e.rect?e.rect.width*e.rect.height:1/0}function dO(e,t,r={}){let a=[],i=dl(e.type??""),n=dC(e.identifier),o=dC(e.label),s=dC(e.value),l=dC(dc(e)),d="fill"===r.action;n&&a.push(`id=${dL(n)}`),i&&o&&a.push(d?`role=${dL(i)} label=${dL(o)} editable=true`:`role=${dL(i)} label=${dL(o)}`),o&&a.push(d?`label=${dL(o)} editable=true`:`label=${dL(o)}`),s&&a.push(d?`value=${dL(s)} editable=true`:`value=${dL(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${dL(l)} editable=true`:`text=${dL(l)}`),i&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${dL(i)} editable=true`);let u=tG(a);return 0===u.length&&i&&u.push(d?`role=${dL(i)} editable=true`:`role=${dL(i)}`),0===u.length&&dS(e)&&u.push("visible=true"),u}function dL(e){return JSON.stringify(e)}function dC(e){if(!e)return null;let t=e.trim();return t||null}function dP(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=dg(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 dR(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(tW(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let n=i.get(r);if(!n)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),tW(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}=dv(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=dP(e.positionals??[]);r&&t.push(r)}return tG(t).filter(e=>e.trim().length>0)})(t).map(e=>dw(e)).filter(e=>null!==e);if(0===o.length)return null;let s=tW(t.command)||"fill"===t.command,l=tW(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await dT(n,t,a,s,i);for(let e of o){let r=dx(d.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=dO(r.node,n.device.platform,{action:tW(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tW(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=tV(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}=dv(t.positionals);if(!e)continue;let i=r?.rest.join(" ").trim()??"",n=[e,a];return"text"===e&&i.length>0&&n.push(i),{...t,positionals:n}}if("wait"===t.command){let{selectorTimeout:e}=dP(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function dT(e,t,r,a,i){let n=await st(e.device,"snapshot",[],t.flags?.out,{...sl(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:l7(t.flags?.snapshotRaw?o:ds(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return e.snapshot=s,i.set(e.name,e),s}let d$=["platform","target","device","udid","serial","verbose","out"];async function dF(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.positionals?.[0];if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};let s="",l=new Set;try{s=t3.expandHome(o,t.meta?.cwd);let e=et.readFileSync(s,"utf8"),d=e.trimStart()[0];if("{"===d||"["===d)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let u=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,i=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!i)break;i="\\"===t&&!i,"\\"!==t&&(i=!1),a+=1}if(a>=e.length)throw new k("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=t0(r);return{positionals:i.positionals,flags:a,runtime:(t=i.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?i.flags:void 0}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n.runtime=e.runtime,n}if("runtime"===a){let e=t0(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tW(a)){let e=tQ(a,i);if(Object.assign(n.flags,e.flags),0===e.positionals.length)return n;let t=e.positionals[0];if(t.startsWith("@"))return n.positionals=[t],e.positionals[1]&&(n.result={refLabel:e.positionals[1]}),n;let r=e.positionals[0],o=e.positionals[1];return l3(r)&&l3(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=tQ(a,i);if(Object.assign(n.flags,e.flags),e.positionals.length<2)return n.positionals=e.positionals,n;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(n.positionals=[t,e.positionals.slice(2).join(" ")],n.result={refLabel:e.positionals[1]}):n.positionals=[t,e.positionals[1]],n):(n.positionals=[t,e.positionals.slice(1).join(" ")],n)}if("get"===a){if(i.length<2)return n.positionals=i,n;let e=i[0],t=i[1];return t.startsWith("@")?(n.positionals=[e,t],i[2]&&(n.result={refLabel:i[2]})):n.positionals=[e,i.slice(1).join(" ")],n}if("swipe"===a||"type"===a){let e=tQ(a,i);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}if("record"===a){let e=[];for(let t=0;t<i.length;t+=1){let r=i[t];if("--hide-touches"===r){n.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(n.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return n.positionals=e,n}return n.positionals=i,n}(r);e&&t.push(e)}return t}(e),c=t.flags?.replayUpdate===!0,p=0;for(let e=0;e<u.length;e+=1){let o=u[e];if(!o||"replay"===o.command)continue;let d=await dU({req:t,sessionName:r,action:o,invoke:n});if(d.ok){dG(d).forEach(e=>l.add(e));continue}if(!c)return dV(d,o,e,s,[...l]);let f=await dR({action:o,sessionName:r,logPath:a,sessionStore:i});if(!f)return dV(d,o,e,s,[...l]);if(u[e]=f,!(d=await dU({req:t,sessionName:r,action:f,invoke:n})).ok)return dV(d,f,e,s,[...l]);dG(d).forEach(e=>l.add(e)),p+=1}return c&&p>0&&function(e,t,r){let a=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",i=r.device.target?` target=${r.device.target}`:"";a.push(`context platform=${r.device.platform}${i} device="${e}"${t} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tJ(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return t2(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tK(r));return tY(t,e.flags),t.join(" ")}if("record"===e.command)return tZ(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tJ(r));return tX(t,e),t.join(" ")}(e));let i=`${a.join("\n")}
|
|
39
|
+
`,n=`${e}.tmp-${process.pid}-${Date.now()}`;et.writeFileSync(n,i),et.renameSync(n,e)}(s,u,i.get(r)),{ok:!0,data:{replayed:u.length,healed:p,session:r,artifactPaths:[...l]}}}catch(t){let e=N(t);return{ok:!1,error:{code:e.code,message:e.message,details:l.size>0?{artifactPaths:[...l]}:void 0}}}}async function dU(e){let{req:t,sessionName:r,action:a,invoke:i}=e;return await i({token:t.token,session:r,command:a.command,positionals:a.positionals??[],flags:function(e,t){let r={...t??{}},a=e??{};for(let e of d$)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 dV(e,t,r,a,i=[]){let n;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${n=(t.positionals??[]).map(e=>tJ(e)),[t.command,...n].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:i}}}}function dG(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 et.statSync(e).isFile()}catch{return!1}})(e)))]}async function dj(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await dF({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await l6({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await dF({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:i,invoke:async e=>{var t;return t=await n(e),l&&dG(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{i.get(e)&&await lA({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let dB=new Set(["session_list","ensure-simulator","devices","apps"]),dq=new Set(["boot","appstate"]),dH=new Set(["perf","logs","network"]),dW=new Set(["replay","test"]);async function dz(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=i.get(r),u=t.flags??{},c=sD(n,d,u);if(c)return c;let p=await sE({session:d,flags:u,ensureReady:!0});if(!ss(n,p))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${n} is not supported on this device`}};let f=await st(p,n,o,t.flags?.out,{...sl(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,f,p):d;i.recordAction(e,{command:n,positionals:s??o,flags:t.flags??{},result:f??{}}),e!==d&&i.set(r,e)}return{ok:!0,data:f??{}}}async function dJ(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=sD("clipboard",n,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 sE({session:n,flags:o,ensureReady:!0});if(!ss("clipboard",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let u=await st(d,"clipboard",t.positionals??[],t.flags?.out,{...sl(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function dK(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(dB.has(t.command))return await lC({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await lt({req:t,sessionName:r,sessionStore:i});if(dq.has(t.command))return await lF({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await dJ({req:t,sessionName:r,logPath:a,sessionStore:i});if("keyboard"===t.command){let e=i.get(r),n=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==n||"ios"!==(t.flags??{}).platform?await dz({req:t,sessionName:r,logPath:a,sessionStore:i,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(dH.has(t.command))return await l0({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await l_({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?lS:lb});if("install_source"===t.command)return await sA({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await sS({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await dz({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=oW(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>t3.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}}}return"trigger-app-event"===t.command?await dz({req:t,sessionName:r,logPath:a,sessionStore:i,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await ll(e.device,r,e.appBundleId,ls)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await lg({req:t,sessionName:r,logPath:a,sessionStore:i}):dW.has(t.command)?await dj({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await lD(t,r,n):"close"===t.command?await lA({req:t,sessionName:r,logPath:a,sessionStore:i}):null}function dX(e,t){let r=F(e.type??"Element"),a=A(e,r),i=!1===e.enabled?"disabled":"enabled",n=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,a,i,n,o].join("|")}function dY(e,t){return t.flatten?e.map(e=>({text:c(e,0,!1),comparable:dX(e,0)})):P(e).map(e=>({text:e.text,comparable:dX(e.node,e.depth)}))}function dZ(e,t){return e.get(t)??0}async function dQ(e){return{snapshot:d1(await d0(e),e.flags?.snapshotRaw)}}async function d0(e){var t,r,a,i;let n,{device:o,session:s,flags:l,outPath:d,logPath:u,snapshotScope:c}=e;return"macos"===o.platform&&s?.surface&&"app"!==s.surface?(t=await nC(s.surface),r={snapshotDepth:l?.snapshotDepth,snapshotInteractiveOnly:l?.snapshotInteractiveOnly,snapshotScope:c},n=t.nodes??[],r.snapshotScope&&(n=function(e,t){let r=da(l7(e),t);if(!r)return[];let a=e.findIndex(e=>e.index===r.index);if(-1===a)return[];let i=e[a]?.depth??0,n=[];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<=i)break;n.push(r)}return d2(n,i)}(n,r.snapshotScope)),r.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:d2(e.filter(e=>r.has(e.index)))}(n)),"number"==typeof r.snapshotDepth&&(a=n,i=r.snapshotDepth,n=d2(a.filter(e=>(e.depth??0)<=i))),{...t,nodes:n}):await st(o,"snapshot",[],d,{...sl(u,{...l,snapshotScope:c},s?.appBundleId,s?.trace?.outPath)})}function d1(e,t){let r=e?.nodes??[];return{nodes:l7(t?r:ds(r)),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend}}function d2(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 d3(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=de(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=dt(t.snapshot.nodes,r),i=a?di(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function d4(e,t,r){let a=e.get(t),i=a?.device??await se(r??{});return a||await su(i),{session:a,device:i}}async function d8(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await tO(t.id)}}function d5(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function d6(e){let{session:t,sessionName:r,device:a,snapshot:i,appBundleId:n}=e;return t?{...t,snapshot:i}:{name:r,device:a,createdAt:Date.now(),appBundleId:n,snapshot:i,actions:[]}}function d9(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function d7(e){let{parsed:t,req:r,sessionName:a,logPath:i,sessionStore:n,session:o,device:s}=e;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),d5(n,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!ss("wait",s))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}};if("selector"===t.kind)return await ue({device:s,logPath:i,parsed:t,req:r,session:o,sessionName:a,sessionStore:n});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=de(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=dt(t.snapshot.nodes,r),i=a?di(a,t.snapshot.nodes):void 0;return i?{ok:!0,text:i,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return l.ok?await ut({device:s,logPath:i,req:r,session:o,sessionStore:n,text:l.text,timeoutMs:l.timeoutMs}):l.response}async function ue(e){let{device:t,logPath:r,parsed:a,req:i,session:n,sessionName:o,sessionStore:s}=e,l=a.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let e=dk((await ur({device:t,logPath:r,req:i,session:n,sessionName:o,sessionStore:s})).nodes,a.selector,{platform:t.platform});if(e)return ua(s,n,i,{selector:e.selector.raw,waitedMs:Date.now()-d});await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${a.selectorExpression}`}}}async function ut(e){let{device:t,logPath:r,req:a,session:i,sessionStore:n,text:o,timeoutMs:s}=e,l=s??1e4,d=Date.now();for(;Date.now()-d<l;){if("macos"===t.platform&&i?.surface&&"app"!==i.surface){if(da((await ur({device:t,logPath:r,req:a,session:i,sessionName:i?.name??a.session??"default",sessionStore:n})).nodes,o))return ua(n,i,a,{text:o,waitedMs:Date.now()-d})}else if(e9(t.platform)){let e=await tF(t,{command:"findText",text:o,appBundleId:i?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return d5(n,i,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}}}else if("android"===t.platform&&da(l7((await id(t,{scope:o})).nodes??[]),o))return d5(n,i,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${o}`}}}async function ur(e){let{device:t,logPath:r,req:a,session:i,sessionName:n,sessionStore:o}=e,{snapshot:s}=await dQ({device:t,session:i,flags:{...a.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:a.flags?.out,logPath:r});return i&&(i.snapshot=s,o.set(n,i)),s}function ua(e,t,r,a){return d5(e,t,r,a),{ok:!0,data:a}}async function ui(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=i?"frontmost-app"===i.surface?{surface:"frontmost-app"}:{bundleId:i.appBundleId,surface:i.surface}:{};if(!ss("alert",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is not supported on this device"}};if("macos"===n.platform){let e=async()=>await nL("wait"===o?"get":o,s);if("wait"===o){let r=d9(t.positionals?.[1])??1e4,n=Date.now();for(;Date.now()-n<r;){try{let r=await e();return d5(a,i,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,n=Date.now();for(;Date.now()-n<2e3;){try{let e=await nL(r,s);return d5(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let n=await nL("get",s);return d5(a,i,t,n),{ok:!0,data:n}}if("wait"===o){let e=d9(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await tF(n,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return d5(a,i,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let l="accept"===o||"dismiss"===o?o:"get",d={verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await tF(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return d5(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let u=await tF(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return d5(a,i,t,u),{ok:!0,data:u}}async function un(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!ss("settings",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};let u=i?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],p=await st(n,"settings",c,t.flags?.out,{...sl(r,t.flags,u,i?.trace?.outPath)});return d5(a,i,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}async function uo(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=t.command;if("snapshot"===n){let{session:e,device:n}=await d4(i,r,t.flags);if(!ss("snapshot",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let o=d3(t.flags?.snapshotScope,e);return o.ok?await d8(e,n,async()=>{let s=await dQ({device:n,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:o.scope}),l=d6({session:e,sessionName:r,device:n,snapshot:s.snapshot,appBundleId:e?.appBundleId});return d5(i,l,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),i.set(r,l),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,appName:l.appBundleId?l.appName??l.appBundleId:void 0,appBundleId:l.appBundleId}}}):o.response}if("diff"===n){if(t.positionals?.[0]!=="snapshot")return{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}};let{session:e,device:n}=await d4(i,r,t.flags);if(!ss("diff",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let o=d3(t.flags?.snapshotScope,e);if(!o.ok)return o.response;let s=t.flags?.snapshotInteractiveOnly===!0;return await d8(e,n,async()=>{let l=(await dQ({device:n,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:o.scope})).snapshot;if(!e?.snapshot){let a=function(e,t={}){return dY(e,t).length}(l.nodes,{flatten:s}),o=d6({session:e,sessionName:r,device:n,snapshot:l,appBundleId:e?.appBundleId});return d5(i,o,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a}}),i.set(r,o),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a},lines:[]}}}let d=function(e,t,r={}){let a=function(e,t){let r=e.length,a=t.length,i=r+a,n=new Map,o=[];n.set(1,0);for(let s=0;s<=i;s+=1){o.push(new Map(n));for(let i=-s;i<=s;i+=2){let l=i===-s||i!==s&&dZ(n,i-1)<dZ(n,i+1)?dZ(n,i+1):dZ(n,i-1)+1,d=l-i;for(;l<r&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(n.set(i,l),l>=r&&d>=a)return function(e,t,r,a,i){let n=[],o=a,s=i;for(let a=e.length-1;a>=0;a-=1){let i=e[a],l=o-s,d=l===-a||l!==a&&dZ(i,l-1)<dZ(i,l+1)?l+1:l-1,u=dZ(i,d),c=u-d;for(;o>u&&s>c;)n.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===a)break;o===u?(n.push({kind:"added",text:r[c].text}),s=c):(n.push({kind:"removed",text:t[u].text}),o=u)}return n.reverse(),n}(o,e,t,r,a)}}return[]}(dY(e,r),dY(t,r)),i={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(i.additions+=1),"removed"===e.kind&&(i.removals+=1),"unchanged"===e.kind&&(i.unchanged+=1);return{summary:i,lines:a}}(e.snapshot.nodes,l.nodes,{flatten:s}),u={...e,snapshot:l};return d5(i,u,t,{mode:"snapshot",baselineInitialized:!1,summary:d.summary}),i.set(r,u),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:d.summary,lines:d.lines}}})}if("wait"===n){let{session:e,device:n}=await d4(i,r,t.flags),o=function(e){if(0===e.length)return null;let t=d9(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=d9(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=d9(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=d9(e[e.length-1]),a=dg(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=dw(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=()=>d7({parsed:o,req:t,sessionName:r,logPath:a,sessionStore:i,session:e,device:n});return"sleep"===o.kind?await s():await d8(e,n,s)}if("alert"===n){let{session:e,device:n}=await d4(i,r,t.flags);return await d8(e,n,async()=>await ui({req:t,logPath:a,sessionStore:i,session:e,device:n}))}if("settings"===n){let e,n,o,s=(e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&n&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:n,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:b}}});if(!s.ok)return s.response;let{session:l,device:d}=await d4(i,r,t.flags);return await d8(l,d,async()=>await un({req:t,logPath:a,sessionStore:i,session:l,device:d,parsed:s.parsed}))}return null}function us(e,t,r,a={}){let i=ud(r);if(!i)return{matches:[],score:0};let n=0,o=[];for(let r of e){if(a.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return ul(e.label,r);case"value":return ul(e.value,r);case"id":return ul(e.identifier,r);default:return Math.max(ul(e.label,r),ul(e.value,r),ul(e.identifier,r))}}(r,t,i);if(!(e<=0)){if(e>n){n=e,o.length=0,o.push(r);continue}e===n&&o.push(r)}}return{matches:o,score:n}}function ul(e,t){let r=ud(e??"");return r?r===t?2:+!!r.includes(t):0}function ud(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function uu(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"No snapshot in session. Run snapshot first."}}};let s=de(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=dt(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=da(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}}function uc(e){let t=function(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}(e);if(!t)return null;let r=dr(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}async function up(e){let{session:t,refInput:r,fallbackLabel:a,promoteToHittableAncestor:i,invalidRefMessage:n,missingBoundsMessage:o,invalidBoundsMessage:s,reqFlags:l,sessionStore:d,contextFromFlags:u,captureSnapshotForSession:c,resolveRefTarget:p}=e,f=p({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:n,notFoundMessage:o});if(!f.ok)return{ok:!1,response:f.response};let{ref:m}=f.target,h=i?uf(f.target.snapshotNodes,f.target.node):f.target.node,w=f.target.snapshotNodes,g=uc(h.rect);if(!g){let e=await c(t,l,d,u,{interactiveOnly:!0}),r=dt(e.nodes,m),n=a.length>0?da(e.nodes,a):null,o=r&&i?uf(e.nodes,r):r,s=n&&i?uf(e.nodes,n):n,p=uc(s?.rect),f=uc(o?.rect)?o:p?s:o??s,v=uc(f?.rect);f&&v&&(h=f,w=e.nodes,g=v)}return g?{ok:!0,target:{ref:m,node:h,snapshotNodes:w,point:g}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:s}}}}function uf(e,t){let r=du(e,t);return r?.rect&&uc(r.rect)?r:t}async function um(e){let{device:t,node:r,flags:a,appBundleId:i,traceOutPath:n,surface:o,contextFromFlags:s}=e,l=E(r),d=uc(r.rect);if(!d)return l;try{let e=await st(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,i,n),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return J({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return J({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 uh(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a locator or text"}};let{locator:l,query:d,action:u,value:c,timeoutMs:p}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let a=e[r]??"",i=e.slice(r+1);if(0===i.length)return{locator:t,query:a,action:"click"};let n=i[0].toLowerCase();if("get"===n){let e=i[1]?.toLowerCase();if("text"===e)return{locator:t,query:a,action:"get_text"};if("attrs"===e)return{locator:t,query:a,action:"get_attrs"};throw new k("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:a,action:"wait",timeoutMs:d9(i[1])??void 0};if("exists"===n)return{locator:t,query:a,action:"exists"};if("click"===n)return{locator:t,query:a,action:"click"};if("focus"===n)return{locator:t,query:a,action:"focus"};if("fill"===n)return{locator:t,query:a,action:"fill",value:i.slice(1).join(" ")};if("type"===n)return{locator:t,query:a,action:"type",value:i.slice(1).join(" ")};throw new k("INVALID_ARGS",`Unsupported find action: ${i[0]}`)}(s);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a value"}};let f=i.get(r);if(!f&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let m=f?.device??await se(t.flags??{});f||await su(m);let h="role"!==l?d:void 0,w="click"===u||"focus"===u||"fill"===u||"type"===u,g=0,v=null,y=async()=>{let e=Date.now();if(v&&e-g<750)return{nodes:v};let{snapshot:n}=await dQ({device:m,session:f,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=n.nodes;return g=e,v=o,f&&(f.snapshot=n,i.set(r,f)),{nodes:o,truncated:n.truncated,backend:n.backend}};if("wait"===u){let e=p??1e4,r=Date.now();for(;Date.now()-r<e;){let{nodes:e}=await y();if(us(e,l,d,{requireRect:!1}).matches[0])return f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0,waitedMs:Date.now()-r}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-r}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}let{nodes:I}=await y(),A=us(I,l,d,{requireRect:w});if(w&&A.matches.length>1){let e=A.matches.slice(0,8).map(e=>{let t=dc(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`});return{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${A.matches.length} elements for ${l} "${d}". Use a more specific locator or selector.`,details:{locator:l,query:d,matches:A.matches.length,candidates:e}}}}let b=A.matches[0]??null;if(!b)return{ok:!1,error:{code:"COMMAND_FAILED",message:"find did not match any element"}};let S="click"===u||"focus"===u||"fill"===u||"type"===u?du(I,b)??b:b,_=`@${S.ref}`,N={...t.flags??{},noRecord:!0};if("exists"===u)return f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}};if("get_text"===u){let e=await um({device:m,node:b,flags:t.flags,appBundleId:f?.appBundleId,traceOutPath:f?.trace?.outPath,surface:f?.surface,contextFromFlags:(e,t,r)=>sl(a,e,t,r)});return f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:_,action:"get text",text:e}}),{ok:!0,data:{ref:_,text:e,node:b}}}if("get_attrs"===u)return f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:_,action:"get attrs"}}),{ok:!0,data:{ref:_,node:b}};if("click"===u){let e=await n({token:t.token,session:r,command:"click",positionals:[_],flags:N});if(!e.ok)return e;let a=S.rect?dr(S.rect):null,s={ref:_,locator:l,query:d};return a&&(s.x=a.x,s.y=a.y),f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:_,action:"click",locator:l,query:d}}),{ok:!0,data:s}}if("fill"===u){if(!c)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let e=await n({token:t.token,session:r,command:"fill",positionals:[_,c],flags:N});return e.ok&&f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:_,action:"fill"}}),e}if("focus"===u){let e=b.rect?dr(b.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let r=await st(m,"focus",[String(e.x),String(e.y)],t.flags?.out,{...sl(a,t.flags,f?.appBundleId,f?.trace?.outPath)});return f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:_,action:"focus"}}),{ok:!0,data:r??{ref:_}}}if("type"===u){if(!c)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let e=b.rect?dr(b.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await st(m,"focus",[String(e.x),String(e.y)],t.flags?.out,{...sl(a,t.flags,f?.appBundleId,f?.trace?.outPath)});let r=await st(m,"type",[c],t.flags?.out,{...sl(a,t.flags,f?.appBundleId,f?.trace?.outPath)});return f&&i.recordAction(f,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:_,action:"type"}}),{ok:!0,data:r??{ref:_}}}return null}let uw=`
|
|
39
40
|
import Foundation
|
|
40
41
|
import AVFoundation
|
|
41
42
|
|
|
@@ -59,10 +60,10 @@ Task {
|
|
|
59
60
|
|
|
60
61
|
semaphore.wait()
|
|
61
62
|
exit(exitCode)
|
|
62
|
-
`.trim();async function
|
|
63
|
-
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return dW(e);return!1}catch(t){if(t instanceof _&&"TOOL_MISSING"===t.code)return dW(e);throw t}}async function dH(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await dq(e))return;await new Promise(e=>setTimeout(e,r))}}function dW(e){try{let t=J.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=J.openSync(e,"r");try{let e=J.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>J.readSync(t,e,0,8,r))break;let i=e.readUInt32BE(0),n=e.toString("latin1",4,8);if(a.push(n),1===i){let e=Buffer.alloc(8);if(8>J.readSync(t,e,0,8,r+8))break;i=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(i)||i<=0)break;r+=i}return a}finally{J.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function dz(e){let t=s.parse(e);return s.join(t.dir,`${t.name}.gesture-telemetry.json`)}function dJ(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function dX(e){var t,r;let a=dz(e.videoPath),i={version:1,generatedAt:new Date().toISOString(),events:(t=e.events,(r=e.trimStartMs??0)>0?dJ(t.flatMap(e=>{let t=e.tMs-r,a="durationMs"in e?e.durationMs:void 0;return("number"==typeof a?t+a:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):dJ(t))};return J.writeFileSync(a,JSON.stringify(i,null,2)),a}function dK(e){let{recording:t,trimStartMs:r,writeTelemetry:a=dX}=e,i=a({videoPath:t.outPath,events:t.gestureEvents,trimStartMs:r});return t.telemetryPath=i,i}function dY(e){let t=s.dirname(M(import.meta.url)),r=[M(new URL(`./${e}`,import.meta.url)),s.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),s.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),s.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(J.existsSync(e))return e;throw new _("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 dZ(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 dQ(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:i}=e;await dj(t),await dH(t);let n=J.mkdtempSync(s.join(K.tmpdir(),"agent-device-record-overlay-")),o=s.join(n,`input${s.extname(t)||".mp4"}`),l=s.join(n,s.basename(t)),d=s.join(n,"home"),u=s.join(n,"module-cache");J.copyFileSync(t,o),J.mkdirSync(d,{recursive:!0}),J.mkdirSync(u,{recursive:!0});try{await w("xcrun",["swift",r,"--input",o,"--output",l,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:u}}),await dH(l),J.copyFileSync(l,t)}catch(a){let e=a instanceof _?a:new _("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new _("COMMAND_FAILED",i,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{J.rmSync(n,{recursive:!0,force:!0})}}async function d0(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await dQ({videoPath:t,scriptPath:a??=dY("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function d1(e){let{videoPath:t,telemetryPath:a,targetLabel:i="recording"}=e;await dQ({videoPath:t,scriptPath:r??=dY("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function d2(e){return e instanceof Error?e.message:String(e)}function d3(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function d4(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 d8(e,t,r){for(let a=0;a<40;a+=1){if(!await d4(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await d4(e,t,r)}async function d5(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await new Promise(e=>setTimeout(e,250))}}async function d6(e,t,r,a){for(let i=0;i<8;i+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?Number(n.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await d4(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function d9(e){let t,{deps:r,deviceId:a,remotePath:i,outPath:n}=e;for(let e=0;e<2;e+=1){try{J.rmSync(n,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",a,"pull",i,n],{allowFailure:!0});if(0!==o.exitCode)t=d3(o,"adb pull");else{await r.waitForStableFile(n,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(n);if(B({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1,fileSize:(()=>{try{return J.statSync(n).size}catch{return 0}})(),playable:t}}),t)return;B({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function d7(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function ue(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return B({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 d4(e,t,r))&&await d8(e,t,r)}async function ut(e){var t;let r,{deps:a,device:i,recordingBase:n}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",i.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${d3(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 d7(a,i.id,e);continue}if(B({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await d6(a,i.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...n,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await ue(a,i.id,r),await d7(a,i.id,e)}return{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}async function ur(e){let t,r,{deps:a,device:i,recording:n}=e;B({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(B({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await d4(a,i.id,n.remotePid)&&!await ue(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${d3(o,"adb shell kill")}`):await d8(a,i.id,n.remotePid)||await ue(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await d5(a,i.id,n.remotePath);let e=await d9({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),{ok:!1,error:{code:"COMMAND_FAILED",message:e}};if(dK({recording:n,writeTelemetry:a.writeRecordingTelemetry}),n.showTouches&&n.telemetryPath){let e=dZ();if(e)n.overlayWarning=e;else try{await a.overlayRecordingTouches({videoPath:n.outPath,telemetryPath:n.telemetryPath,targetLabel:"Android recording"})}catch(e){n.overlayWarning=`failed to overlay recording touches: ${d2(e)}`}}}if(await s(),t)return{ok:!1,error:{code:"COMMAND_FAILED",message:t}};if(r)return{ok:!1,error:{code:"COMMAND_FAILED",message:r}};return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});B({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:i.id,remotePath:n.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${d3(e,"adb shell rm")}`)}}function ua(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function ui(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function un(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=ua(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},ui(t,i,r))}catch(e){B({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:d2(e)}})}}async function uo(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=ui(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var w,g;if(!d2(a).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${d2(a)}`}};B({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:d2(a)}});let e=(w=o.id,g=i.name,n.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${e.name}'`}};try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${d2(e)}`}}}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function us(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},ui(t,i,r))}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${d2(e)}`}}}return{platform:"macos-runner",...s}}async function ul(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=ua(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},ui(t,i,r))}catch(e){B({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:d2(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of ta)if(0===(l=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);d>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:d});let u=dK({recording:o,trimStartMs:d,writeTelemetry:n.writeRecordingTelemetry});if(o.showTouches){let e=dZ();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:u,targetLabel:"iOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${d2(e)}`}}return null}async function ud(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=ua(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},ui(t,i,r))}catch(e){B({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:d2(e)}})}let l=dK({recording:o,writeTelemetry:n.writeRecordingTelemetry});if(o.showTouches){let e=dZ();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:l,targetLabel:"macOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${d2(e)}`}}return null}async function uu(e){for(let t=0;t<2;t+=1){try{if(J.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 uc(e){let t,{req:r,sessionName:a,sessionStore:i,activeSession:n,device:o,logPath:l,deps:d}=e;if(n.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let u=r.flags?.fps;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};if(!o5("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`,p=tq.expandHome(c,r.meta?.cwd),f={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(J.mkdirSync(s.dirname(p),{recursive:!0}),J.rmSync(p,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=ua(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};t=await uo({req:r,activeSession:n,sessionStore:i,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:f,appBundleId:e})}else if("macos"===o.platform){let e=ua(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on macOS requires an active app session; run open <app> first"}};t=await us({req:r,activeSession:n,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:f,appBundleId:e})}else if("ios"===o.platform){let e,a;await un({req:r,activeSession:n,device:o,logPath:l,deps:d});let{child:i,wait:s}=d.runCmdBackground("xcrun",e$(o,["io",o.id,"recordVideo",p]),{allowFailure:!0}),u=await uu(p);try{let t=Date.now(),i=await d.runIosRunnerCommand(o,{command:"uptime",appBundleId:ua(n)},{verbose:r.flags?.verbose,logPath:l,traceLogPath:n.trace?.outPath}),s=Date.now();e=Math.round((t+s)/2),a="number"==typeof i.currentUptimeMs?i.currentUptimeMs:void 0}catch{}t={platform:"ios",child:i,wait:s,...f,startedAt:u,gestureClockOriginAtMs:void 0===a?void 0:e,gestureClockOriginUptimeMs:a}}else t=await ut({deps:d,device:o,recordingBase:f});return"ok"in t?t:(n.recording=t,i.set(a,n),i.recordAction(n,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??c,showTouches:t.showTouches}})}async function up(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await ur({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to stop recording: ${d3(i,"simctl recordVideo")}`}};let n=dK({recording:a,writeTelemetry:t.writeRecordingTelemetry});if(a.showTouches){let e=dZ();if(e)a.overlayWarning=e;else try{await t.overlayRecordingTouches({videoPath:a.outPath,telemetryPath:n,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to overlay recording touches: ${d2(e)}`}}return null}async function uf(e){var t;let r,{req:a,activeSession:i,device:n,logPath:o,deps:l}=e;if(!i.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let d=i.recording,u=d.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===d.platform?await ul({req:a,activeSession:i,device:n,logPath:o,deps:l,recording:d}):"macos-runner"===d.platform?await ud({req:a,activeSession:i,device:n,logPath:o,deps:l,recording:d}):await up({deps:l,device:n,recording:d});return c||(u?{ok:!1,error:{code:"COMMAND_FAILED",message:u}}:(r=[{field:"outPath",path:(t=d).outPath,localPath:t.clientOutPath,fileName:s.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return dz(e.clientOutPath)}(t),fileName:s.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function um(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:w,runCmdBackground:f,runIosRunnerCommand:tE,waitForStableFile:dj,isPlayableVideo:dq,writeRecordingTelemetry:dX,trimRecordingStart:d0,overlayRecordingTouches:d1,...e.deps},o=a.get(r),s=o?.device??await o2(t.flags??{});o||await o7(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 uc({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await uf({req:t,activeSession:l,device:s,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function uh(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n=t.command;if("record"===n)return um({req:t,sessionName:r,sessionStore:a,logPath:i,deps:e.deps});if("trace"===n){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"trace requires start|stop"}};let i=a.get(r);if(!i)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};if("start"===e){if(i.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"trace already in progress"}};let e=t.positionals?.[1]??a.defaultTracePath(i),r=tq.expandHome(e);return J.mkdirSync(s.dirname(r),{recursive:!0}),J.appendFileSync(r,""),i.trace={outPath:r,startedAt:Date.now()},a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!i.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active trace"}};let o=i.trace.outPath;if(t.positionals?.[1]){let e=tq.expandHome(t.positionals[1]);J.mkdirSync(s.dirname(e),{recursive:!0}),J.existsSync(o)?J.renameSync(o,e):J.appendFileSync(e,""),o=e}return i.trace=void 0,a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}let uw=new WeakMap;function ug(e){if(!e)return;let t=uw.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)&&uv(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(uv);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),i=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(i<=0))return{x:0,y:0,width:a,height:i}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return uw.set(e,r),r}function uv(e){return!!e&&e.width>0&&e.height>0}function uI(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 uA={referenceWidth:1e3,referenceHeight:1e3};function uy(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,p=e.recording;if(!p)return;let f={...i,...a??{}},m=uN(f.effectiveDurationMs)??uN(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:uN(f.gestureStartUptimeMs),gestureEndUptimeMs:uN(f.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:uN(f.gestureStartUptimeMs),gestureEndUptimeMs:uN(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===uN(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=uD(uN(t.count),1)??1,r=!0===t.doubleTap,a=uD(uN(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 uI(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):uI(h),v=(l=e.snapshot,u=uN((d=f).referenceWidth),c=uN(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:ug(l)),I=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=uk(t,e);if(!i)return[];let{x:n,y:o}=i,s=uD(uN(t.count),1)??1,l=uD(uN(t.intervalMs),0)??0,d=!0===t.doubleTap,u=uD(uN(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(uS(t,n,o,u,a));continue}c.push(ub(t,n,o,a)),d&&c.push(ub(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=uk(t,e);if(!i)return[];let{x:n,y:o}=i;return[ub(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=uk(t,e);if(!n)return[];let{x:o,y:s}=n;return[uS(r,o,s,ux(a,[uN(t.durationMs),uN(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=uM(t,e),o=u_(t.contentDirection)??u_(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=ux(a,[],250),p=uN(t.amount)??uN(e[1]);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=uM(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=ux(a,[uN(t.effectiveDurationMs),uN(t.durationMs),uN(e[4])],250),c=uD(uN(t.count),1)??1,p=uD(uN(t.pauseMs),0)??0,f="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===f&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,w=r+e*(u+p);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=uk(t,e,1),o=uN(t.scale)??uN(e[0]);if(!n||void 0===o||o<=0)return[];let{x:s,y:l}=n;return[{kind:"pinch",tMs:r,x:s,y:l,...i,scale:o,durationMs:ux(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,f,g,w,v);0!==I.length&&(p.gestureEvents.push(...I),B({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:I.length,tMs:g,gestureDurationMs:w,kinds:I.map(e=>e.kind)}}))}function ub(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function uS(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function u_(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 uN(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 uD(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function uE(e,t,r){return Math.max(t,Math.min(r,e))}function uk(e,t,r=0){let a=uN(e.x)??uN(t[r]),i=uN(e.y)??uN(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function uM(e,t){let r=uN(e.x1)??uN(t[0]),a=uN(e.y1)??uN(t[1]),i=uN(e.x2)??uN(t[2]),n=uN(e.y2)??uN(t[3]);if(void 0!==r&&void 0!==a&&void 0!==i&&void 0!==n)return{x1:r,y1:a,x2:i,y2:n}}function ux(e,t,r){return uD(e,1)??t.map(e=>uD(e,1)).find(e=>void 0!==e)??r}function uO(e){let{data:t,fallbackX:r,fallbackY:a,referenceFrame:i,extra:n}=e;return{x:r,y:a,...i??{},...n??{},...t??{}}}async function uL(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:i,flags:n,contextFromFlags:o,dispatch:s,interactionCommand:l,interactionPositionals:d,outPath:u,buildPayloads:c}=e,p=await uC({session:t,flags:n,contextFromFlags:o,dispatch:s,command:l,positionals:d,outPath:u}),{result:f,responseData:m=f}=await c(p.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),uy(t,a,i,o,n??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:i,flags:n,result:f,responseData:m,actionStartedAt:p.actionStartedAt,actionFinishedAt:p.actionFinishedAt})}async function uC(e){let{session:t,flags:r,contextFromFlags:a,dispatch:i,command:n,positionals:o,outPath:s}=e,l=Date.now(),d={...a(r,t.appBundleId,t.trace?.outPath)},u=await i(t.device,n,o,s,d);return{data:u&&"object"==typeof u?u:void 0,actionStartedAt:l,actionFinishedAt:Date.now()}}async function uP(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=e.dispatch??o3,d=e.readAndroidScreenSize??iI,u=t.command;if("press"===u||"click"===u){let e="click"===u?"click":"press",c=a.get(r);if(!c)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let p=uR(c,e);if(p)return p;if(!o5("press",c.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let f=oE(t.flags),m="primary"===f?{}:{button:f};if("primary"!==f){let r=ok({commandLabel:e,platform:c.device.platform,button:f,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(r)return{ok:!1,error:{code:r.code,message:r.message,details:r.details}}}let h=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(h)return uL({session:c,sessionStore:a,requestCommand:u,requestPositionals:t.positionals??[String(h.x),String(h.y)],flags:t.flags,contextFromFlags:i,dispatch:l,interactionCommand:"press",interactionPositionals:[String(h.x),String(h.y)],outPath:t.flags?.out,buildPayloads:async e=>{let r=await u$({session:c,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,dispatch:l,readAndroidScreenSize:d}),o=uO({data:e,fallbackX:h.x,fallbackY:h.y,referenceFrame:r,extra:m});return{result:o,responseData:o}}});let w="click",g=t.positionals?.[0]??"";if(g.startsWith("@")){let r=s("press",t.flags);if(r)return r;let d=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",p=await uF({session:c,refInput:g,fallbackLabel:d,invalidRefMessage:`${e} requires a ref like @e2`,missingBoundsMessage:`Ref ${g} not found or has no bounds`,invalidBoundsMessage:`Ref ${g} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,dispatch:l,resolveRefTarget:o});if(!p.ok)return p.response;let{ref:f,node:h,snapshotNodes:v,point:I}=p.target,A=sl(h,v),y=sC(h,c.device.platform,{action:w}),{x:b,y:S}=I;return uL({session:c,sessionStore:a,requestCommand:u,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,dispatch:l,interactionCommand:"press",interactionPositionals:[String(b),String(S)],outPath:t.flags?.out,buildPayloads:e=>{let t=uO({data:e,fallbackX:b,fallbackY:S,referenceFrame:uU(v),extra:{ref:f,refLabel:A,selectorChain:y,...m}});return{result:t,responseData:t}}})}let v=(t.positionals??[]).join(" ").trim();if(!v)return{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires @ref, selector expression, or x y coordinates`}};let I=sg(v),A=await n(c,t.flags,a,i,{interactiveOnly:!0},l),y=await U("selector_resolve",()=>sM(A.nodes,I,{platform:c.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:u});if(!y||!y.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:sO(I,y?.diagnostics??[],{unique:!0})}};let b=uV(y.node.rect);if(!b)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${y.selector.raw} resolved to invalid bounds`}};let{x:S,y:_}=b,N=sC(y.node,c.device.platform,{action:w}),D=sl(y.node,A.nodes);return uL({session:c,sessionStore:a,requestCommand:u,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,dispatch:l,interactionCommand:"press",interactionPositionals:[String(S),String(_)],outPath:t.flags?.out,buildPayloads:e=>{let t=uO({data:e,fallbackX:S,fallbackY:_,referenceFrame:uU(A.nodes),extra:{selector:y.selector.raw,selectorChain:N,refLabel:D,...m}});return{result:t,responseData:t}}})}if("fill"===u){let e=a.get(r);if(e){let t=uR(e,u);if(t)return t}if(e&&!o5("fill",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let r=s("fill",t.flags);if(r)return r;let d=t.positionals.length>=3?t.positionals[1]:"",c=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!c)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let p=await uF({session:e,refInput:t.positionals[0],fallbackLabel:d,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:i,captureSnapshotForSession:n,dispatch:l,resolveRefTarget:o});if(!p.ok)return p.response;let{ref:f,node:m,snapshotNodes:h,point:w}=p.target,g=m.type??"",v=g&&!sp(g,e.device.platform)?`fill target ${t.positionals[0]} resolved to "${g}", attempting fill anyway.`:void 0,I=sl(m,h),A=sC(m,e.device.platform,{action:"fill"}),{x:y,y:b}=w;return uL({session:e,sessionStore:a,requestCommand:u,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,dispatch:l,interactionCommand:"fill",interactionPositionals:[String(y),String(b),c],outPath:t.flags?.out,buildPayloads:e=>{let t=uO({data:e,fallbackX:y,fallbackY:b,referenceFrame:uU(h),extra:{ref:f,refLabel:I,selectorChain:A}}),r={...e??{ref:f,x:y,y:b}};return v&&(t.warning=v,r.warning=v),{result:t,responseData:r}}})}if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let d=sI(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=d.rest.join(" ").trim();if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let o=sg(d.selectorExpression),s=await n(e,t.flags,a,i,{interactiveOnly:!0},l),c=await U("selector_resolve",()=>sM(s.nodes,o,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:u});if(!c||!c.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:sO(o,c?.diagnostics??[],{unique:!0})}};let p=c.node,f=p.type??"",m=f&&!sp(f,e.device.platform)?`fill target ${c.selector.raw} resolved to "${f}", attempting fill anyway.`:void 0,{x:h,y:w}=so(c.node.rect),g=sC(p,e.device.platform,{action:"fill"});return uL({session:e,sessionStore:a,requestCommand:u,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,dispatch:l,interactionCommand:"fill",interactionPositionals:[String(h),String(w),r],outPath:t.flags?.out,buildPayloads:e=>{let t=uO({data:e,fallbackX:h,fallbackY:w,referenceFrame:uU(s.nodes),extra:{text:r,selector:c.selector.raw,selectorChain:g,refLabel:sl(p,s.nodes)}});return m&&(t.warning=m),{result:t,responseData:t}}})}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}return null}function uR(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface?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 uT(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,dispatch:o,readAndroidScreenSize:s}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await s(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let l=ug(t.snapshot);if(l)return t.recording&&(t.recording.touchReferenceFrame=l),l;if(!t.recording)return;let d=ug(await n(t,r,a,i,{interactiveOnly:!0},o));return d&&t.recording&&(t.recording.touchReferenceFrame=d),d}async function u$(e){try{return await uT(e)}catch(t){B({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}async function uF(e){let{session:t,refInput:r,fallbackLabel:a,invalidRefMessage:i,missingBoundsMessage:n,invalidBoundsMessage:o,reqFlags:s,sessionStore:l,contextFromFlags:d,captureSnapshotForSession:u,dispatch:c,resolveRefTarget:p}=e,f=p({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:i,notFoundMessage:n});if(!f.ok)return{ok:!1,response:f.response};let{ref:m}=f.target,h=f.target.node,w=f.target.snapshotNodes,g=uV(h.rect);if(!g){let e=await u(t,s,l,d,{interactiveOnly:!0},c),r=sn(e.nodes,m),i=a.length>0?ss(e.nodes,a):null,n=uV(i?.rect),o=uV(r?.rect)?r:n?i:r??i,p=uV(o?.rect);o&&p&&(h=o,w=e.nodes,g=p)}return g?{ok:!0,target:{ref:m,node:h,snapshotNodes:w,point:g}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}}function uU(e){return ug({nodes:e,createdAt:0})}function uV(e){let t=function(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}(e);if(!t)return null;let r=so(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}let uG=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function uB(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of uG)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 uj(e,t,r,a,i,n=o3){let o={...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},s=a(o,e.appBundleId,e.trace?.outPath),{snapshot:l}=await dI({dispatchSnapshotCommand:n,device:e.device,session:e,flags:o,outPath:o.out,logPath:s.logPath??""});return e.snapshot=l,r.set(e.name,e),e.snapshot}async function uq(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u,dispatch:c}=e,p=sg(r),f=await uj(a,i,n,o,{interactiveOnly:s},c),m=await U("selector_resolve",()=>sM(f.nodes,p,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return m&&(!l||m.node.rect)?{ok:!0,chain:p,snapshot:f,resolved:m}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:sO(p,m?.diagnostics??[],{unique:d})}}}}async function uH(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o=t.positionals?.[0];if("text"!==o&&"attrs"!==o)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let s=a.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!o5("get",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let l=t.positionals?.[1]??"";if(l.startsWith("@")){let e=uB("get",t.flags);if(e)return e;let r=dU({session:s,refInput:l,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${l} not found`});if(!r.ok)return r.response;let{ref:d,node:u}=r.target,c=sC(u,s.device.platform,{action:"get"});if("attrs"===o)return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:d,selectorChain:c}}),{ok:!0,data:{ref:d,node:u}};let p=await dV({device:s.device,node:u,flags:t.flags,appBundleId:s.appBundleId,traceOutPath:s.trace?.outPath,surface:s.surface,contextFromFlags:i,dispatch:n});return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:d,text:p,refLabel:uW(p),selectorChain:c}}),{ok:!0,data:{ref:d,text:p,node:u}}}let d=t.positionals.slice(1).join(" ").trim();if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"get requires @ref or selector expression"}};let u=await uq({command:t.command,selectorExpression:d,session:s,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===o,dispatch:n});if(!u.ok)return u.response;let{resolved:c}=u,p=c.node,f=sC(p,s.device.platform,{action:"get"});if("attrs"===o)return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:c.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:c.selector.raw,node:p}};let m=await dV({device:s.device,node:p,flags:t.flags,appBundleId:s.appBundleId,traceOutPath:s.trace?.outPath,surface:s.surface,contextFromFlags:i,dispatch:n});return a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:m,refLabel:uW(m),selector:c.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:c.selector.raw,text:m,node:p}}}function uW(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}async function uz(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let s=a.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!o5("is",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:l}=sA(t.positionals);if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires a selector expression"}};let d=l.rest.join(" ").trim();if("text"===o&&!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==o&&l.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${o} does not accept trailing values`}};let u=sg(l.selectorExpression);if("exists"===o){let e=sx((await uj(s,t.flags,a,i,{interactiveOnly:!1},n)).nodes,u,{platform:s.device.platform});return e?(a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:o,selector:e.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:o,pass:!0,selector:e.selector.raw,matches:e.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:sO(u,[],{unique:!1})}}}let c=await uq({command:"is",selectorExpression:l.selectorExpression,session:s,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1,dispatch:n});if(!c.ok)return c.response;let{resolved:p}=c,f=function(e){let{predicate:t,node:r,expectedText:a,platform:i}=e,n=sf(r),o=!1;switch(t){case"visible":o=sN(r);break;case"hidden":o=!sN(r);break;case"editable":o=sD(r,i);break;case"selected":o=!0===r.selected;break;case"text":o=n===(a??"")}let s="text"===t?`expected="${a??""}" actual="${n}"`:`actual=${JSON.stringify({visible:sN(r),editable:sD(r,i),selected:!0===r.selected})}`;return{pass:o,actualText:n,details:s}}({predicate:o,node:p.node,expectedText:d,platform:s.device.platform});return f.pass?(a.recordAction(s,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:o,selector:p.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,text:"text"===o?f.actualText:void 0}}),{ok:!0,data:{predicate:o,pass:!0,selector:p.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${o} failed for selector ${p.selector.raw}: ${f.details}`}}}function uJ(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function uX(e){let t=null,r=-1;for(let a of e){let e=a.width*a.height;e>r&&(t=a,r=e)}return t}function uK(e,t,r){return Math.min(r,Math.max(t,Math.round(e)))}async function uY(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,dispatch:n}=e,o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!o5("scrollintoview",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let s=t.positionals?.[0]??"";if(!s.startsWith("@"))return null;let l=uB("scrollintoview",t.flags);if(l)return l;let d=dU({session:o,refInput:s,fallbackLabel:t.positionals&&t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${s} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s} not found or has no bounds`}};let f=function(e,t){let r=so(t),a=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),i=a.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),n=uX(i.map(e=>e.rect).filter(e=>uJ(e,r.x,r.y)));if(n)return n;let o=uX(i.map(e=>e.rect));if(o)return o;let s=uX(a.map(e=>e.rect).filter(e=>uJ(e,r.x,r.y)));return s||null}(p,c.rect);if(!f)return{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${s}`}};let m=function(e,t){var r,a;let i=Math.max(1,t.height),n=Math.max(1,t.width),o=t.y,s=t.y+i,l=t.x,d=t.x+n,u=o+.25*i,c=s-.25*i,p=Math.max(8,.1*n),f=e.y+e.height/2,m=e.x+e.width/2;if(f>=u&&f<=c)return null;let h=Math.round((r=m,a=l+p,Math.min(d-p,Math.max(a,r)))),w=Math.round(o+.86*i),g=Math.round(o+.14*i),v=Math.max(1,Math.abs(w-g));return f>c?{x:h,startY:w,endY:g,count:uK(Math.ceil((f-c)/v),1,50),direction:"down"}:{x:h,startY:g,endY:w,count:uK(Math.ceil((u-f)/v),1,50),direction:"up"}}(c.rect,f),h=sl(c,p),w=sC(c,o.device.platform,{action:"get"});if(!m)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:u,attempts:0,alreadyVisible:!0,refLabel:h,selectorChain:w}}),{ok:!0,data:{ref:u,attempts:0,alreadyVisible:!0}};let g=await n(o.device,"swipe",[String(m.x),String(m.startY),String(m.x),String(m.endY),"16"],t.flags?.out,{...i(t.flags,o.appBundleId,o.trace?.outPath),count:m.count,pauseMs:0,pattern:"one-way"});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{...g??{},ref:u,attempts:m.count,direction:m.direction,refLabel:h,selectorChain:w}}),{ok:!0,data:{...g??{},ref:u,attempts:m.count,direction:m.direction}}}async function uZ(e){let t=e.dispatch??o3,r=e.readAndroidScreenSize??iI,a={...e,dispatch:t},i=await uP({...a,readAndroidScreenSize:r,captureSnapshotForSession:uj,resolveRefTarget:dU,refSnapshotFlagGuardResponse:uB});if(i)return i;switch(e.req.command){case"get":return await uH(a);case"is":return await uz(a);case"scrollintoview":return await uY(a);default:return null}}function uQ(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 u0(e){let{req:t,leaseRegistry:r}=e,a=uQ(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 u1(e,t){if(!t)return[];let r=[],a=e.device,i=t.platform;if(i&&!e2(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=eP(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function u2(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 u3=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],u4=/\bis(?:n't| not)\s+responding\b/i,u8=/^close app$/i;async function u5(e){let{session:t,snapshotAndroidUi:r=it,reopenAndroidApp:a=aG,readAndroidAppState:i=aU,execCommand:n=w}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await u6(t,r),o=function(e){if(ct(e))return e.find(e=>{let t=ce(e);return t.length>0&&u8.test(t)&&e.rect})}(e);if(!o?.rect)return"absent";let{x:s,y:l}=so(o.rect),d=await n("adb",rR(t.device,["shell","input","tap",String(Math.round(s)),String(Math.round(l))]),{allowFailure:!0});if(0!==d.exitCode)return B({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:d.exitCode,stdout:d.stdout.trim(),stderr:d.stderr.trim()}}),"failed";if(!await u9(t,r))return B({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await a(t.device,t.appBundleId),!await u7(t,t.appBundleId,i)))return B({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return B({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:s,y:l}}),"recovered"}catch(e){return B({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 u6(e,t){return sa(su((await t(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function u9(e,t){for(let r=0;r<12;r+=1){if(!ct(await u6(e,t)))return!0;await cr(500)}return!ct(await u6(e,t))}async function u7(e,t,r){for(let a=0;a<12;a+=1){if((await r(e.device)).package===t)return!0;await cr(500)}return(await r(e.device)).package===t}function ce(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 ct(e){return e.some(e=>{let t=ce(e);return t.length>0&&u4.test(t)})}function cr(e){return new Promise(t=>setTimeout(t,e))}let ca=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),ci=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function cn(e,t,r,a){let i=$().requestId;return{...o6(e,t,r,a,i),requestId:i}}function co(e){J.existsSync(e)&&J.unlinkSync(e)}function cs(e){if(!J.existsSync(e))return null;try{let t=JSON.parse(J.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function cl(e){let t=cs(e);if(!t||t.pid===process.pid)try{J.existsSync(e)&&J.unlinkSync(e)}catch{}}function cd(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:cu,infoPath:cc,lockPath:cp,logPath:cf,sessionsDir:cm}=Q(process.env.AGENT_DEVICE_STATE_DIR),ch=Z(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var cw=cm;if(J.existsSync(cw))for(let e of J.readdirSync(cw,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=s.join(cw,e.name,"app-log.pid");if(J.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}}(J.readFileSync(t,"utf8"));if(e&&function(e){let t,r=W(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=l(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{tW(t)}}let cg=new tq(cm),cv=new rM({maxActiveSimulatorLeases:cd(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:cd(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:cd(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:cd(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),cI=T(),cA=h.randomBytes(24).toString("hex"),cy=W(process.pid)??void 0,cb=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=J.statSync(e),r=G(),a=s.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),cS=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:n}=e,o=e.dispatchCommand??o3,l=e.snapshotAndroidUi??it,d=e.reopenAndroidApp??aG,c=e.readAndroidAppState??aU,p=e.execCommand??w;async function f(e){let m=!!(e.meta?.debug||e.flags?.verbose);return await z({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:m,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:C(new _("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=P(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=u(r);if(r&&!a)throw new _("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new _("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);B({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let m=r.command,h=uQ(r);ci.has(m)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:h.tenantId,runId:h.runId,leaseId:h.leaseId,backend:h.leaseBackend});let w=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),g=a.get(w);g&&(!function(e){var t,r;let a,i=e.recording;if(!i||"ios"!==e.device.platform)return;let n=(t=e.device.id,(a=tm.get(t))?{sessionId:a.sessionId,alive:!!(r=a.child.pid)&&H(r)}:null);if(!i.runnerSessionId){n?.alive&&(i.runnerSessionId=n.sessionId);return}if(!n?.alive){i.invalidatedReason??="iOS runner session exited during recording";return}n.sessionId!==i.runnerSessionId&&(i.invalidatedReason??="iOS runner session restarted during recording")}(g),a.set(w,g));let v=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?u1(t,a):function(e,t){var r,a;let i=[];for(let n of(void 0!==e.platform&&t&&(r=e.platform,a=t,r&&a&&r!==a&&("apple"===r?!e1(a):"apple"!==a||!e1(r)))&&i.push({key:"platform",value:e.platform}),u3)){let t=e[n];"string"==typeof t&&t.trim().length>0&&i.push({key:n,value:t})}return i}(a,e.meta?.lockPlatform);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of u3)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new _("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(u2).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,g),I=e=>(function(e,t,r){let a=$();if(!t.ok){B({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=X({force:!0})??void 0;return{ok:!1,error:C(new _(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 B({level:"info",phase:"request_success"}),X(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let o=(a=e,i=t,n=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||n.some(e=>e?.field==="path")||"string"!=typeof i.path||n.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:s.basename(a.meta?.clientArtifactPaths?.path??i.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===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)}})(v,e,n);if(g?.recording?.invalidatedReason&&"record"!==m&&"close"!==m)return I({ok:!1,error:{code:"COMMAND_FAILED",message:g.recording.invalidatedReason}});!g||v.meta?.lockPolicy||ca.has(m)||function(e,t){let r=u1(e,t);if(0!==r.length){var a;let t,i,n;throw new _("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(u2).join(", ")}. Use a different --session name or close this session first.`)}}(g,v.flags);let A=await u0({req:v,leaseRegistry:i});if(A)return I(A);let y=await dc({req:v,sessionName:w,logPath:t,sessionStore:a,invoke:f});if(y)return I(y);let b=await dR({req:v,sessionName:w,logPath:t,sessionStore:a});if(b)return I(b);let S=await uh({req:v,sessionName:w,sessionStore:a,logPath:t});if(S)return I(S);let N=await dG({req:v,sessionName:w,logPath:t,sessionStore:a,invoke:f});if(N)return I(N);let D=await uZ({req:v,sessionName:w,sessionStore:a,contextFromFlags:(e,r,a)=>cn(t,e,r,a)});if(D)return I(D);let E=a.get(w);if(!E)return I({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!o5(m,E.device))return I({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${m} is not supported on this device`}});if("android"===E.device.platform&&E.recording&&"record"!==m){let e=await u5({session:E,snapshotAndroidUi:l,reopenAndroidApp:d,readAndroidAppState:c,execCommand:p});if("failed"===e)return I({ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}})}let k=v.positionals??[],M=v.flags?.out,x="screenshot"===m&&k[0]?[tq.expandHome(k[0],v.meta?.cwd),...k.slice(1)]:k,O="screenshot"===m&&M?tq.expandHome(M,v.meta?.cwd):M,L="screenshot"===m?x:k,R="screenshot"===m&&O?{...v.flags??{},out:O}:v.flags??{},T=Date.now(),F={...cn(t,v.flags,E.appBundleId,E.trace?.outPath)},U=await o(E.device,m,x,O,{...F}),V=Date.now(),G=function(e,t,r,a){var i;if("scroll"!==t)return a;let n=ug(e.snapshot),o={...a??{}},s=u_(o.direction)??u_(r[0]);if(!s)return a;let l=uN(o.amount)??uN(r[1]),d=(i=l,void 0===i||!Number.isFinite(i)||i<=0?.4:i<=1?uE(i,.2,.7):uE(i/100,.2,.7)),u=uN(o.referenceWidth),c=uN(o.referenceHeight),p=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:n??uA,{start:f,end:m}=function(e,t,r){let a=Math.round(t.referenceWidth/2),i=Math.round(t.referenceHeight/2),n=Math.round(t.referenceWidth*r/2),o=Math.round(t.referenceHeight*r/2);switch(e){case"up":return{start:{x:a,y:i-o},end:{x:a,y:i+o}};case"down":return{start:{x:a,y:i+o},end:{x:a,y:i-o}};case"left":return{start:{x:a-n,y:i},end:{x:a+n,y:i}};case"right":return{start:{x:a+n,y:i},end:{x:a-n,y:i}}}}(s,p,d);return{...o,x1:f.x,y1:f.y,x2:m.x,y2:m.y,contentDirection:s,amount:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250}}(E,m,x,U);return uy(E,m,x,G,v.flags??{},T,V),a.recordAction(E,{command:m,positionals:L,flags:R,result:U??{}}),I({ok:!0,data:U??{}})}catch(r){B({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=$(),t=X({force:!0})??void 0;return{ok:!1,error:C(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return f}({logPath:cf,token:cA,sessionStore:cg,leaseRegistry:cv,trackDownloadableArtifact:function(e){let t=h.randomUUID(),r=setTimeout(()=>{re(t)},9e5);return r.unref(),t7.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){J.existsSync(e)||J.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),i=()=>{try{return J.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(i())return!0;let n=cs(t);if(n?.pid&&n.pid!==process.pid&&m(n.pid,n.processStartTime))return!1;try{J.unlinkSync(t)}catch{}return i()}(cu,cp,{pid:process.pid,version:cI,startedAt:Date.now(),processStartTime:cy})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let i;if("socket"===ch||"dual"===ch){let t=Y.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))ew(e);B({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await ty(),!(r<=0));)await new Promise(e=>setTimeout(e,200))})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async i=>{let n=(t+=i).indexOf("\n");for(;-1!==n;){let i,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=em(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),eh(o),ev(o))throw eA();i=await cS(e)}catch(e){i={ok:!1,error:C(e)}}finally{r-=1,o&&(a.delete(o),eg(o))}e.destroyed||e.write(`${JSON.stringify(i)}
|
|
64
|
-
`),n=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new
|
|
63
|
+
`.trim();async function ug(e,t={}){let r,a=t.pollMs??150,i=t.attempts??12,n=0;for(let t=0;t<i;t+=1){let t=0;try{t=et.statSync(e).size}catch{t=0}if(t>0&&t===r){if((n+=1)>=2)return}else n=0;r=t,await new Promise(e=>setTimeout(e,a))}}async function uv(e){try{var t,r;let a,i=await v("swift",["-",e],{stdin:uw,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
|
|
64
|
+
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return uI(e);return!1}catch(t){if(t instanceof k&&"TOOL_MISSING"===t.code)return uI(e);throw t}}async function uy(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await uv(e))return;await new Promise(e=>setTimeout(e,r))}}function uI(e){try{let t=et.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=et.openSync(e,"r");try{let e=et.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>et.readSync(t,e,0,8,r))break;let i=e.readUInt32BE(0),n=e.toString("latin1",4,8);if(a.push(n),1===i){let e=Buffer.alloc(8);if(8>et.readSync(t,e,0,8,r+8))break;i=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(i)||i<=0)break;r+=i}return a}finally{et.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function uA(e){let t=l.parse(e);return l.join(t.dir,`${t.name}.gesture-telemetry.json`)}function ub(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function uS(e){var t,r,a;let i,n,{recording:o,trimStartMs:s}=e,l=(i=uA((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:s}).videoPath),n={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?ub(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)}]})):ub(r))},et.writeFileSync(i,JSON.stringify(n,null,2)),i);return o.telemetryPath=l,l}function u_(e){let t=l.dirname(R(import.meta.url)),r=[R(new URL(`./${e}`,import.meta.url)),l.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),l.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),l.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(et.existsSync(e))return e;throw new k("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 uN(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 uD(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:i}=e;await ug(t),await uy(t);let n=et.mkdtempSync(l.join(ea.tmpdir(),"agent-device-record-overlay-")),o=l.join(n,`input${l.extname(t)||".mp4"}`),s=l.join(n,l.basename(t)),d=l.join(n,"home"),u=l.join(n,"module-cache");et.copyFileSync(t,o),et.mkdirSync(d,{recursive:!0}),et.mkdirSync(u,{recursive:!0});try{await v("xcrun",["swift",r,"--input",o,"--output",s,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:u}}),await uy(s),et.copyFileSync(s,t)}catch(a){let e=a instanceof k?a:new k("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new k("COMMAND_FAILED",i,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{et.rmSync(n,{recursive:!0,force:!0})}}async function ux(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await uD({videoPath:t,scriptPath:a??=u_("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function uk(e){let{videoPath:t,telemetryPath:a,targetLabel:i="recording"}=e;await uD({videoPath:t,scriptPath:r??=u_("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function uM(e){return e instanceof Error?e.message:String(e)}function uE(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function uO(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 uL(e,t,r){for(let a=0;a<40;a+=1){if(!await uO(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await uO(e,t,r)}async function uC(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await new Promise(e=>setTimeout(e,250))}}async function uP(e,t,r,a){for(let i=0;i<8;i+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?Number(n.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await uO(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function uR(e){let t,{deps:r,deviceId:a,remotePath:i,outPath:n}=e;for(let e=0;e<2;e+=1){try{et.rmSync(n,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",a,"pull",i,n],{allowFailure:!0});if(0!==o.exitCode)t=uE(o,"adb pull");else{await r.waitForStableFile(n,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(n);if(J({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1,fileSize:(()=>{try{return et.statSync(n).size}catch{return 0}})(),playable:t}}),t)return;J({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function uT(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function u$(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return J({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 uO(e,t,r))&&await uL(e,t,r)}async function uF(e){var t;let r,{deps:a,device:i,recordingBase:n}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",i.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${uE(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 uT(a,i.id,e);continue}if(J({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await uP(a,i.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...n,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await u$(a,i.id,r),await uT(a,i.id,e)}return{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}async function uU(e){let t,r,{deps:a,device:i,recording:n}=e;J({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(J({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await uO(a,i.id,n.remotePid)&&!await u$(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${uE(o,"adb shell kill")}`):await uL(a,i.id,n.remotePid)||await u$(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await uC(a,i.id,n.remotePath);let e=await uR({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),{ok:!1,error:{code:"COMMAND_FAILED",message:e}};if(uS({recording:n}),n.showTouches&&n.telemetryPath){let e=uN();if(e)n.overlayWarning=e;else try{await a.overlayRecordingTouches({videoPath:n.outPath,telemetryPath:n.telemetryPath,targetLabel:"Android recording"})}catch(e){n.overlayWarning=`failed to overlay recording touches: ${uM(e)}`}}}if(await s(),t)return{ok:!1,error:{code:"COMMAND_FAILED",message:t}};if(r)return{ok:!1,error:{code:"COMMAND_FAILED",message:r}};return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});J({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:i.id,remotePath:n.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${uE(e,"adb shell rm")}`)}}function uV(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function uG(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function uj(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=uV(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},uG(t,i,r))}catch(e){J({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:uM(e)}})}}async function uB(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=uG(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var w,g;if(!uM(a).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${uM(a)}`}};J({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:uM(a)}});let e=(w=o.id,g=i.name,n.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${e.name}'`}};try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${uM(e)}`}}}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function uq(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},uG(t,i,r))}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${uM(e)}`}}}return{platform:"macos-runner",...s}}async function uH(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=uV(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},uG(t,i,r))}catch(e){J({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:uM(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of tc)if(0===(l=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);d>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:d});let u=uS({recording:o,trimStartMs:d});if(o.showTouches){let e=uN();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:u,targetLabel:"iOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${uM(e)}`}}return null}async function uW(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=uV(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},uG(t,i,r))}catch(e){J({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:uM(e)}})}let l=uS({recording:o});if(o.showTouches){let e=uN();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:l,targetLabel:"macOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${uM(e)}`}}return null}async function uz(e){for(let t=0;t<2;t+=1){try{if(et.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 uJ(e){let t,{req:r,sessionName:a,sessionStore:i,activeSession:n,device:o,logPath:s,deps:d}=e;if(n.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let u=r.flags?.fps;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};if(!ss("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`,p=t3.expandHome(c,r.meta?.cwd),f={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(et.mkdirSync(l.dirname(p),{recursive:!0}),et.rmSync(p,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=uV(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};t=await uB({req:r,activeSession:n,sessionStore:i,device:o,logPath:s,deps:d,fpsFlag:u,recordingBase:f,appBundleId:e})}else if("macos"===o.platform){let e=uV(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on macOS requires an active app session; run open <app> first"}};t=await uq({req:r,activeSession:n,device:o,logPath:s,deps:d,fpsFlag:u,recordingBase:f,appBundleId:e})}else if("ios"===o.platform){let e,a;await uj({req:r,activeSession:n,device:o,logPath:s,deps:d});let{child:i,wait:l}=d.runCmdBackground("xcrun",eq(o,["io",o.id,"recordVideo",p]),{allowFailure:!0}),u=await uz(p);try{let t=Date.now(),i=await d.runIosRunnerCommand(o,{command:"uptime",appBundleId:uV(n)},{verbose:r.flags?.verbose,logPath:s,traceLogPath:n.trace?.outPath}),l=Date.now();e=Math.round((t+l)/2),a="number"==typeof i.currentUptimeMs?i.currentUptimeMs:void 0}catch{}t={platform:"ios",child:i,wait:l,...f,startedAt:u,gestureClockOriginAtMs:void 0===a?void 0:e,gestureClockOriginUptimeMs:a}}else t=await uF({deps:d,device:o,recordingBase:f});return"ok"in t?t:(n.recording=t,i.set(a,n),i.recordAction(n,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??c,showTouches:t.showTouches}})}async function uK(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await uU({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to stop recording: ${uE(i,"simctl recordVideo")}`}};let n=uS({recording:a});if(a.showTouches){let e=uN();if(e)a.overlayWarning=e;else try{await t.overlayRecordingTouches({videoPath:a.outPath,telemetryPath:n,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to overlay recording touches: ${uM(e)}`}}return null}async function uX(e){var t;let r,{req:a,activeSession:i,device:n,logPath:o,deps:s}=e;if(!i.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let d=i.recording,u=d.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===d.platform?await uH({req:a,activeSession:i,device:n,logPath:o,deps:s,recording:d}):"macos-runner"===d.platform?await uW({req:a,activeSession:i,device:n,logPath:o,deps:s,recording:d}):await uK({deps:s,device:n,recording:d});return c||(u?{ok:!1,error:{code:"COMMAND_FAILED",message:u}}:(r=[{field:"outPath",path:(t=d).outPath,localPath:t.clientOutPath,fileName:l.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return uA(e.clientOutPath)}(t),fileName:l.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function uY(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:v,runCmdBackground:h,runIosRunnerCommand:tF,waitForStableFile:ug,isPlayableVideo:uv,trimRecordingStart:ux,overlayRecordingTouches:uk},o=a.get(r),s=o?.device??await se(t.flags??{});o||await su(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 uJ({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await uX({req:t,activeSession:l,device:s,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function uZ(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n=t.command;if("record"===n)return uY({req:t,sessionName:r,sessionStore:a,logPath:i});if("trace"===n){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"trace requires start|stop"}};let i=a.get(r);if(!i)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};if("start"===e){if(i.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"trace already in progress"}};let e=t.positionals?.[1]??a.defaultTracePath(i),r=t3.expandHome(e);return et.mkdirSync(l.dirname(r),{recursive:!0}),et.appendFileSync(r,""),i.trace={outPath:r,startedAt:Date.now()},a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!i.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active trace"}};let o=i.trace.outPath;if(t.positionals?.[1]){let e=t3.expandHome(t.positionals[1]);et.mkdirSync(l.dirname(e),{recursive:!0}),et.existsSync(o)?et.renameSync(o,e):et.appendFileSync(e,""),o=e}return i.trace=void 0,a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function uQ(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 u0=new WeakMap;function u1(e){if(!e)return;let t=u0.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)&&u2(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(u2);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),i=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(i<=0))return{x:0,y:0,width:a,height:i}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return u0.set(e,r),r}function u2(e){return!!e&&e.width>0&&e.height>0}let u3={referenceWidth:1e3,referenceHeight:1e3};function u4(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,p=e.recording;if(!p)return;let f={...i,...a??{}},m=u9(f.effectiveDurationMs)??u9(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:u9(f.gestureStartUptimeMs),gestureEndUptimeMs:u9(f.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:u9(f.gestureStartUptimeMs),gestureEndUptimeMs:u9(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===u9(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=u7(u9(t.count),1)??1,r=!0===t.doubleTap,a=u7(u9(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 uQ(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):uQ(h),v=(l=e.snapshot,u=u9((d=f).referenceWidth),c=u9(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:u1(l)),y=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=ce(t,e);if(!i)return[];let{x:n,y:o}=i,s=u7(u9(t.count),1)??1,l=u7(u9(t.intervalMs),0)??0,d=!0===t.doubleTap,u=u7(u9(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(u5(t,n,o,u,a));continue}c.push(u8(t,n,o,a)),d&&c.push(u8(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=ce(t,e);if(!i)return[];let{x:n,y:o}=i;return[u8(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=ce(t,e);if(!n)return[];let{x:o,y:s}=n;return[u5(r,o,s,cr(a,[u9(t.durationMs),u9(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=ct(t,e),o=u6(t.contentDirection)??u6(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=cr(a,[],250),p=u9(t.amount)??u9(e[1]),f=u9(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{},...void 0!==f?{pixels:f}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=ct(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=cr(a,[u9(t.effectiveDurationMs),u9(t.durationMs),u9(e[4])],250),c=u7(u9(t.count),1)??1,p=u7(u9(t.pauseMs),0)??0,f="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===f&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,w=r+e*(u+p);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=ce(t,e,1),o=u9(t.scale)??u9(e[0]);if(!n||void 0===o||o<=0)return[];let{x:s,y:l}=n;return[{kind:"pinch",tMs:r,x:s,y:l,...i,scale:o,durationMs:cr(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,f,g,w,v);0!==y.length&&(p.gestureEvents.push(...y),J({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:y.length,tMs:g,gestureDurationMs:w,kinds:y.map(e=>e.kind)}}))}function u8(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function u5(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function u6(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 u9(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 u7(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function ce(e,t,r=0){let a=u9(e.x)??u9(t[r]),i=u9(e.y)??u9(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function ct(e,t){let r=u9(e.x1)??u9(t[0]),a=u9(e.y1)??u9(t[1]),i=u9(e.x2)??u9(t[2]),n=u9(e.y2)??u9(t[3]);if(void 0!==r&&void 0!==a&&void 0!==i&&void 0!==n)return{x1:r,y1:a,x2:i,y2:n}}function cr(e,t,r){return u7(e,1)??t.map(e=>u7(e,1)).find(e=>void 0!==e)??r}function ca(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,r=s,a=l,i="string"==typeof t?.ref?t.ref:void 0,n="string"==typeof t?.button?t.button:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:i?n&&"primary"!==n?`Clicked ${n} @${i} (${r}, ${a})`:`Tapped @${i} (${r}, ${a})`:void 0)??("string"==typeof o?.message?o.message:void 0));return{x:s,y:l,...d??{},...u??{},...o??{},...z(c)}}async function ci(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:i,flags:n,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,buildPayloads:u}=e,c=await cn({session:t,flags:n,contextFromFlags:o,command:s,positionals:l,outPath:d}),{result:p,responseData:f=p}=await u(c.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),u4(t,a,i,o,n??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:i,flags:n,result:p,responseData:f,actionStartedAt:c.actionStartedAt,actionFinishedAt:c.actionFinishedAt})}async function cn(e){let{session:t,flags:r,contextFromFlags:a,command:i,positionals:n,outPath:o}=e,s=Date.now(),l={...a(r,t.appBundleId,t.trace?.outPath)},d=await st(t.device,i,n,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function co(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await ix(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=u1(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=u1(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function cs(e){try{return await co(e)}catch(t){J({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function cl(e){return u1({nodes:e,createdAt:0})}function cd(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface?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 cu(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r),d=t.command,u="click"===d?"click":"press";if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let c=cd(l,u);if(c)return c;if(!ss("press",l.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let p=oU(t.flags),f="primary"===p?{}:{button:p};if("primary"!==p){let e=oV({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{ok:!1,error:{code:e.code,message:e.message,details: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 ci({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,buildPayloads:async e=>{let r=await cs({session:l,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}),o=ca({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 up({session:l,refInput:w,fallbackLabel:r,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:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!c.ok)return c.response;let{ref:p,node:m,snapshotNodes:g,point:v}=c.target,y=di(m,g),I=dO(m,l.device.platform,{action:h}),{x:A,y:b}=v;return ci({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(A),String(b)],outPath:t.flags?.out,buildPayloads:e=>{let t=ca({data:e,fallbackX:A,fallbackY:b,referenceFrame:cl(g),extra:{ref:p,refLabel:y,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 v=dh(g),y=await n(l,t.flags,a,i,{interactiveOnly:!0}),I=await H("selector_resolve",()=>dx(y.nodes,v,{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:dM(v,I?.diagnostics??[],{unique:!0})}};let A=uf(y.nodes,I.node),b=uc(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=dO(A,l.device.platform,{action:h}),D=di(A,y.nodes);return ci({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(S),String(_)],outPath:t.flags?.out,buildPayloads:e=>{let t=ca({data:e,fallbackX:S,fallbackY:_,referenceFrame:cl(y.nodes),extra:{selector:I.selector.raw,selectorChain:N,refLabel:D,...f}});return{result:t,responseData:t}}})}async function cc(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r);if(l){let e=cd(l,"fill");if(e)return e}if(l&&!ss("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 up({session:l,refInput:t.positionals[0],fallbackLabel:r,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:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!u.ok)return u.response;let{ref:c,node:p,snapshotNodes:f,point:m}=u.target,h=p.type??"",w=h&&!dd(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,g=di(p,f),v=dO(p,l.device.platform,{action:"fill"}),{x:y,y:I}=m;return ci({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(y),String(I),d],outPath:t.flags?.out,buildPayloads:e=>{let t=ca({data:e,fallbackX:y,fallbackY:I,referenceFrame:cl(f),extra:{ref:c,refLabel:g,selectorChain:v,text:d}}),r={...e??{ref:c,x:y,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=dg(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=dh(d.selectorExpression),o=await n(l,t.flags,a,i,{interactiveOnly:!0}),s=await H("selector_resolve",()=>dx(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:dM(r,s?.diagnostics??[],{unique:!0})}};let u=s.node,c=s.node.rect,p=u.type??"",f=p&&!dd(p,l.device.platform)?`fill target ${s.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=dr(c),w=dO(u,l.device.platform,{action:"fill"});return ci({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=ca({data:t,fallbackX:m,fallbackY:h,referenceFrame:cl(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:w,refLabel:di(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 cp(e){switch(e.req.command){case"press":case"click":return await cu(e);case"fill":return await cc(e);default:return null}}let cf=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function cm(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of cf)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 ch(e,t,r,a,i){let n={...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},o=a(n,e.appBundleId,e.trace?.outPath),{snapshot:s}=await dQ({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function cw(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=dh(r),p=await ch(a,i,n,o,{interactiveOnly:s}),f=await H("selector_resolve",()=>dx(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:dM(c,f?.diagnostics??[],{unique:d})}}}}async function cg(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)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(!ss("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=cm("get",t.flags);if(e)return e;let r=uu({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=dO(d,o.device.platform,{action:"get"});if("attrs"===n)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 um({device:o.device,node:d,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:cv(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 cw({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===n});if(!d.ok)return d.response;let{resolved:u}=d,c=u.node,p=dO(c,o.device.platform,{action:"get"});if("attrs"===n)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 um({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:f,refLabel:cv(f),selector:u.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:u.selector.raw,text:f,node:c}}}function cv(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function cy(e,t){let r=dr(t),a=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),i=a.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),n=cS(i.map(e=>e.rect).filter(e=>cb(e,r.x,r.y)));if(n)return n;let o=cS(i.map(e=>e.rect));if(o)return o;let s=cS(a.map(e=>e.rect).filter(e=>cb(e,r.x,r.y)));return s||null}function cI(e,t){var r,a;let i=Math.max(1,t.height),n=Math.max(1,t.width),o=t.y,s=t.y+i,l=t.x,d=t.x+n,u=s-.25*i,c=Math.max(8,.1*n),p=e.y+e.height/2,f=e.x+e.width/2;if(p>=o+.25*i&&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*i),w=Math.round(o+.14*i);return p>u?{x:m,startY:h,endY:w,direction:"down"}:{x:m,startY:w,endY:h,direction:"up"}}function cA(e,t){let r=Math.max(1,t.height),a=t.y,i=t.y+r,n=a+.25*r,o=i-.25*r,s=e.y+e.height/2;return s<n?Math.ceil(n-s):s>o?Math.ceil(s-o):0}function cb(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function cS(e){let t=null,r=-1;for(let a of e){let e=a.width*a.height;e>r&&(t=a,r=e)}return t}function c_(e,t){var r,a;let i=cy(t,e);return!i||(r=e,a=i,r.x<a.x+a.width&&r.x+r.width>a.x&&r.y<a.y+a.height&&r.y+r.height>a.y)}function cN(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 cD(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(n))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(!ss("is",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:s}=dv(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"===n&&!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==n&&s.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${n} does not accept trailing values`}};let d=dh(s.selectorExpression);if("exists"===n){let e=dk((await ch(o,t.flags,a,i,{interactiveOnly:!1})).nodes,d,{platform:o.device.platform});return e?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:e.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:n,pass:!0,selector:e.selector.raw,matches:e.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:dM(d,[],{unique:!1})}}}let u=await cw({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,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:i,platform:n}=e,o=dc(r),s=d_(r,n),l=!0===r.selected,d="text"===t?dS(r):function(e,t){if(!0===e.hittable)return!0;if(cN(e.rect))return c_(e.rect,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),a=e,i=new Set;for(;"number"==typeof a.parentIndex&&!i.has(a.index);){i.add(a.index);let e=r.get(a.parentIndex);if(!e)break;if(function(e){let t=dl(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||cN(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!cN(r.rect)&&c_(r.rect,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===(i??"")}let c="text"===t?`expected="${i??""}" actual="${o}"`:`actual=${JSON.stringify({visible:d,editable:s,selected:l})}`;return{pass:u,actualText:o,details:c}}({predicate:n,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:n,selector:c.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,text:"text"===n?p.actualText:void 0}}),{ok:!0,data:{predicate:n,pass:!0,selector:c.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${n} failed for selector ${c.selector.raw}: ${p.details}`}}}async function cx(e){let t,r,{req:a,sessionName:i,sessionStore:n,contextFromFlags:o}=e,s=n.get(i);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!ss("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=cm("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=uu({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:cM(t,0,{message:e.error.message})}}return ck(t,0,a.target)}(s,l,u);if(!c.ok)return c.response;let{ref:p}=c.state,{node:f,snapshotNodes:m,viewportRect:h}=c.state,w=di(f,m),g=dO(f,s.device.platform,{action:"get"}),v=u||w||f.label||"";if(!cI(f.rect,h))return n.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{ref:p,attempts:0,alreadyVisible:!0,refLabel:w,selectorChain:g,...z(`Scrolled into view: @${p}`)}}),{ok:!0,data:{ref:p,attempts:0,alreadyVisible:!0,...z(`Scrolled into view: @${p}`)}};let y=a.flags?.maxScrolls??48,I=0,A=0,b=cA(f.rect,h);for(;I<y;){let e=cI(f.rect,h);if(!e)break;t=e.direction,r=await st(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"}),I+=1,await ch(s,a.flags,n,o,{interactiveOnly:!0});let i=function(e){let{session:t,targetInput:r,fallbackLabel:a,attempts:i,ref:n,selectorChain:o,platform:s}=e;if(t.snapshot){let e=function(e,t,r,a){for(let r of t){let t=dx(e,dh(r),{platform:a,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?da(e,r):null}(t.snapshot.nodes,o,a,s);if(e)return ck(r,i,{ref:n,node:e,snapshotNodes:t.snapshot.nodes})}let l=uu({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:cM(r,i,{message:`scrollintoview lost track of ${r} after ${i} scroll${1===i?"":"s"}`,ref:n})}}return ck(r,i,l.target,{ref:n,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${i} scroll${1===i?"":"s"}`})}({session:s,targetInput:l,fallbackLabel:v,attempts:I,ref:p,selectorChain:g,platform:s.device.platform});if(!i.ok)return i.response;({node:f,snapshotNodes:m,viewportRect:h}=i.state);let d=cA(f.rect,h);if(0===d)break;if(d>=b){if((A+=1)>=2)return cM(l,I,{message:`scrollintoview made no progress toward ${l} after ${I} scroll${1===I?"":"s"}`,ref:p,stalled:!0})}else A=0;b=d}return cA(f.rect,h)>0?cM(l,I,{message:`scrollintoview reached --max-scrolls=${y} before ${l} entered view`,ref:p,maxScrolls:y}):(n.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{...r??{},ref:p,attempts:I,direction:t,refLabel:w,selectorChain:g,...z(`Scrolled into view: @${p}`)}}),{ok:!0,data:{...r??{},ref:p,attempts:I,direction:t,...z(`Scrolled into view: @${p}`)}})}function ck(e,t,r,a={}){let{ref:i,missingBoundsMessage:n}=a,o=r.node;if(!o.rect)return{ok:!1,response:cM(e,t,{message:n??`Ref ${e} not found or has no bounds`,ref:i??r.ref})};let s=cy(r.snapshotNodes,o.rect);return s?{ok:!0,state:{ref:r.ref,node:o,snapshotNodes:r.snapshotNodes,viewportRect:s}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${e}`}}}}function cM(e,t,r={}){let{message:a,...i}=r;return{ok:!1,error:{code:"COMMAND_FAILED",message:"string"==typeof a?a:`scrollintoview could not find ${e}`,details:{reason:"not_found",attempts:t,...i}}}}async function cE(e){let t=await cp({...e,captureSnapshotForSession:ch,resolveRefTarget:uu,refSnapshotFlagGuardResponse:cm});if(t)return t;switch(e.req.command){case"get":return await cg(e);case"is":return await cD(e);case"scrollintoview":return await cx(e);default:return null}}function cO(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 cL(e){let{req:t,leaseRegistry:r}=e,a=cO(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 cC(e,t){if(!t)return[];let r=[],a=e.device,i=t.platform;if(i&&!e7(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=eG(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function cP(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 cR=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],cT=/\bis(?:n't| not)\s+responding\b/i,c$=/^close app$/i;async function cF(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await cU(t),r=function(e){if(cB(e))return e.find(e=>{let t=cj(e);return t.length>0&&c$.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=dr(r.rect),n=await v("adb",rJ(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return J({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:n.exitCode,stdout:n.stdout.trim(),stderr:n.stderr.trim()}}),"failed";if(!await cV(t))return J({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await aJ(t.device,t.appBundleId),!await cG(t,t.appBundleId)))return J({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return J({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:a,y:i}}),"recovered"}catch(e){return J({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 cU(e){return l7(ds((await id(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function cV(e){for(let t=0;t<12;t+=1){if(!cB(await cU(e)))return!0;await cq(500)}return!cB(await cU(e))}async function cG(e,t){for(let r=0;r<12;r+=1){if((await aW(e.device)).package===t)return!0;await cq(500)}return(await aW(e.device)).package===t}function cj(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 cB(e){return e.some(e=>{let t=cj(e);return t.length>0&&cT.test(t)})}function cq(e){return new Promise(t=>setTimeout(t,e))}let cH=[255,59,48,255],cW=[255,214,10,255],cz=[0,0,0,255],cJ={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 cK(e){let t=O(await X.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)cY(r)&&c2(r.rect)&&(!t||c3(r.rect)>c3(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,a=-1/0,i=-1/0;for(let n of e)n.rect&&c2(n.rect)&&(t=Math.min(t,n.rect.x),r=Math.min(r,n.rect.y),a=Math.max(a,n.rect.x+n.rect.width),i=Math.max(i,n.rect.y+n.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||a<=t||i<=r?null:{x:t,y:r,width:a-t,height:i-r}}(e.filter(e=>{var t;return c2(e.rect)&&!("image"===dl((t=e).type??"")&&!cZ(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(cQ)||c0(e.identifier);return cX(e)?t:t&&function(e){let t=dl(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 cX(e)&&!cY(e)}(t)&&c2(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(cX(t)&&!cY(t)&&c2(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&c2(r.rect))return r;if(t.hittable&&c2(t.rect)&&!cY(t))return t;let a=du(e,t);return a?.rect&&c2(a.rect)&&!cY(a)?a:null}(e.nodes,a);if(!o?.rect||!c2(o.rect))continue;let s=function(e,t,r){let a=c1(e);if(e.ref!==t.ref&&a)return a;let i=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 i=c1(a);if(!i)continue;let n=function(e){let t=0;return dl(e.type??"").includes("text")&&(t+=2),cQ(e.label)&&(t+=2),cQ(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(c1(t)??di(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),cX(t)&&(a+=3),cX(e)&&(a+=2),r&&(a+=2),c0(t.identifier)&&(a+=1),cZ(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return c5({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,a);let i=r/e.width,n=a/e.height;return c5({x:Math.round((t.x-e.x)*i),y:Math.round((t.y-e.y)*n),width:Math.max(1,Math.round(t.width*i)),height:Math.max(1,Math.round(t.height*n))},r,a)}(i,o.rect,t,r);if(!c2(d))continue;let u=n.get(o.ref);(!u||l>u.score)&&n.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)=>c3(e.overlayRect)-c3(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(c4(e.overlayRect,r.overlayRect)||c4(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}c3(r.overlayRect)<c3(t[e].overlayRect)&&(t[e]=r)}return t})([...n.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:c8(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:c8(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:dr(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,i;(function(e,t,r,a){for(let a=0;a<2;a+=1)c9(e,t.x,t.x+t.width-1,t.y+a,r),c9(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),c7(e,t.x+a,t.y,t.y+t.height-1,r),c7(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,cH,2),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=c6(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:c6(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,i,n){for(let i=0;i<11;i+=1)for(let o=0;o<a;o+=1)pe(e,t+o,r+i,n)})(e,i,o,a,11,cW),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=cJ[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]&&pe(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,cz)}(a,i.overlayRect,i.ref)}return await X.writeFile(e.screenshotPath,S.sync.write(t)),r}function cX(e){let t=[e.type,e.role,e.subrole].map(e=>dl(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 cY(e){let t=[e.type,e.role,e.subrole].map(e=>dl(e??"")).join(" ");return t.includes("application")||t.includes("window")}function cZ(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function cQ(e){var t;let r;return!!cZ(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function c0(e){var t;return"string"==typeof e&&!!cQ(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function c1(e){let t=[e.label,e.value].find(cQ);return t?t.trim():c0(e.identifier)?e.identifier.trim():void 0}function c2(e){return!!(e&&e.width>0&&e.height>0)}function c3(e){return e.width*e.height}function c4(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 c8(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function c5(e,t,r){let a=c6(e.x,0,Math.max(0,t-1)),i=c6(e.y,0,Math.max(0,r-1)),n=Math.max(1,t-a),o=Math.max(1,r-i);return{x:a,y:i,width:c6(e.width,1,n),height:c6(e.height,1,o)}}function c6(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function c9(e,t,r,a,i){for(let n=t;n<=r;n+=1)pe(e,n,a,i)}function c7(e,t,r,a,i){for(let n=r;n<=a;n+=1)pe(e,t,n,i)}function pe(e,t,r,a){if(t<0||r<0||t>=e.width||r>=e.height)return;let i=(e.width*r+t)*4;e.data[i]=a[0],e.data[i+1]=a[1],e.data[i+2]=a[2],e.data[i+3]=a[3]}let pt=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),pr=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function pa(e,t,r,a){let i=B().requestId;return{...sl(e,t,r,a,i),requestId:i}}function pi(e){et.existsSync(e)&&et.unlinkSync(e)}function pn(e){if(!et.existsSync(e))return null;try{let t=JSON.parse(et.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function po(e){let t=pn(e);if(!t||t.pid===process.pid)try{et.existsSync(e)&&et.unlinkSync(e)}catch{}}function ps(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:pl,infoPath:pd,lockPath:pu,logPath:pc,sessionsDir:pp}=eo(process.env.AGENT_DEVICE_STATE_DIR),pf=en(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var pm=pp;if(et.existsSync(pm))for(let e of et.readdirSync(pm,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=l.join(pm,e.name,"app-log.pid");if(et.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}}(et.readFileSync(t,"utf8"));if(e&&function(e){let t,r=Q(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{t8(t)}}let ph=new t3(pp),pw=new rj({maxActiveSimulatorLeases:ps(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:ps(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:ps(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:ps(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),pg=j(),pv=g.randomBytes(24).toString("hex"),py=Q(process.pid)??void 0,pI=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=et.statSync(e),r=K(),a=l.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),pA=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:n}=e;async function o(e){let s=!!(e.meta?.debug||e.flags?.verbose);return await ee({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:s,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:U(new k("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=V(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=p(r);if(r&&!a)throw new k("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new k("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);J({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let s=r.command,d=cO(r);pr.has(s)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:d.tenantId,runId:d.runId,leaseId:d.leaseId,backend:d.leaseBackend});let u=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),c=a.get(u);c&&(!function(e){var t,r;let a,i=e.recording;if(!i||"ios"!==e.device.platform)return;let n=(t=e.device.id,(a=tN.get(t))?{sessionId:a.sessionId,alive:!!(r=a.child.pid)&&Z(r)}:null);if(!i.runnerSessionId){n?.alive&&(i.runnerSessionId=n.sessionId);return}if(!n?.alive){i.invalidatedReason??="iOS runner session exited during recording";return}n.sessionId!==i.runnerSessionId&&(i.invalidatedReason??="iOS runner session restarted during recording")}(c),a.set(u,c));let f=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?cC(t,a):function(e,t){var r,a;let i=[];for(let n of(void 0!==e.platform&&t&&(r=e.platform,a=t,r&&a&&r!==a&&("apple"===r?!e9(a):"apple"!==a||!e9(r)))&&i.push({key:"platform",value:e.platform}),cR)){let t=e[n];"string"==typeof t&&t.trim().length>0&&i.push({key:n,value:t})}return i}(a,e.meta?.lockPlatform);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of cR)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new k("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(cP).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,c),m=e=>(function(e,t,r){let a=B();if(!t.ok){J({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=er({force:!0})??void 0;return{ok:!1,error:U(new k(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 J({level:"info",phase:"request_success"}),er(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let o=(a=e,i=t,n=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||n.some(e=>e?.field==="path")||"string"!=typeof i.path||n.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:l.basename(a.meta?.clientArtifactPaths?.path??i.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===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)}})(f,e,n);if(c?.recording?.invalidatedReason&&"record"!==s&&"close"!==s)return m({ok:!1,error:{code:"COMMAND_FAILED",message:c.recording.invalidatedReason}});!c||f.meta?.lockPolicy||pt.has(s)||function(e,t){let r=cC(e,t);if(0!==r.length){var a;let t,i,n;throw new k("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(cP).join(", ")}. Use a different --session name or close this session first.`)}}(c,f.flags);let h=await cL({req:f,leaseRegistry:i});if(h)return m(h);let w=await dK({req:f,sessionName:u,logPath:t,sessionStore:a,invoke:o});if(w)return m(w);let g=await uo({req:f,sessionName:u,logPath:t,sessionStore:a});if(g)return m(g);let v=await uZ({req:f,sessionName:u,sessionStore:a,logPath:t});if(v)return m(v);let y=await uh({req:f,sessionName:u,logPath:t,sessionStore:a,invoke:o});if(y)return m(y);let I=await cE({req:f,sessionName:u,sessionStore:a,contextFromFlags:(e,r,a)=>pa(t,e,r,a)});if(I)return m(I);let A=a.get(u);if(!A)return m({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!ss(s,A.device))return m({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${s} is not supported on this device`}});if("android"===A.device.platform&&A.recording&&"record"!==s){let e=await cF({session:A});if("failed"===e)return m({ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}})}let b=f.positionals??[],S=f.flags?.out,_="screenshot"===s&&b[0]?[t3.expandHome(b[0],f.meta?.cwd),...b.slice(1)]:b,N="screenshot"===s&&S?t3.expandHome(S,f.meta?.cwd):S,D="screenshot"===s?_:b,x="screenshot"===s&&N?{...f.flags??{},out:N}:f.flags??{},M=Date.now(),E={...pa(t,f.flags,A.appBundleId,A.trace?.outPath)},O=await st(A.device,s,_,N,{...E});if("screenshot"===s&&f.flags?.overlayRefs&&"string"==typeof O?.path){let e=await d0({device:A.device,session:A,flags:void 0,logPath:t,snapshotScope:void 0}),r=d1(e,!1);A.snapshot=r;let a=await cK({screenshotPath:O.path,snapshot:r});O.overlayRefs=a}let L=Date.now(),C=function(e,t,r,a){if("scroll"!==t)return a;let i=u1(e.snapshot),n={...a??{}},o=u6(n.direction)??u6(r[0]);if(!o)return a;let s=u9(n.amount)??u9(r[1]),l=u9(n.pixels),d=ct(n,[]),u=u9(n.referenceWidth),c=u9(n.referenceHeight),p=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:i??u3;if(d&&(d.x1!==d.x2||d.y1!==d.y2))return{...n,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=ie({direction:o,amount:s,pixels:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return{...n,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}}(A,s,_,O);return u4(A,s,_,C,f.flags??{},M,L),a.recordAction(A,{command:s,positionals:D,flags:x,result:O??{}}),m({ok:!0,data:O??{}})}catch(r){J({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=B(),t=er({force:!0})??void 0;return{ok:!1,error:U(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return o}({logPath:pc,token:pv,sessionStore:ph,leaseRegistry:pw,trackDownloadableArtifact:function(e){let t=g.randomUUID(),r=setTimeout(()=>{rf(t)},9e5);return r.unref(),rp.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){et.existsSync(e)||et.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),i=()=>{try{return et.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(i())return!0;let n=pn(t);if(n?.pid&&n.pid!==process.pid&&w(n.pid,n.processStartTime))return!1;try{et.unlinkSync(t)}catch{}return i()}(pl,pu,{pid:process.pid,version:pg,startedAt:Date.now(),processStartTime:py})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let i;if("socket"===pf||"dual"===pf){let t=ei.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))eS(e);J({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await tL(),!(r<=0));)await new Promise(e=>setTimeout(e,200))})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async i=>{let n=(t+=i).indexOf("\n");for(;-1!==n;){let i,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=eA(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),eb(o),eN(o))throw ex();i=await pA(e)}catch(e){i={ok:!1,error:U(e)}}finally{r-=1,o&&(a.delete(o),e_(o))}e.destroyed||e.write(`${JSON.stringify(i)}
|
|
65
|
+
`),n=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new k("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===pf||"dual"===pf){let e=await rR({handleRequest:pA,token:pv});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 k("COMMAND_FAILED","Failed to bind HTTP server"))})})}a={socketPort:e,httpPort:t,token:pv,version:pg,codeSignature:pI,processStartTime:py},et.existsSync(pl)||et.mkdirSync(pl,{recursive:!0}),et.writeFileSync(pc,""),i=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",et.writeFileSync(pd,JSON.stringify({port:a.socketPort,httpPort:a.httpPort,transport:i,token:a.token,pid:process.pid,version:a.version,codeSignature:a.codeSignature,processStartTime:a.processStartTime,stateDir:pl},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
|
|
65
66
|
`),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
|
|
66
|
-
`)}catch(t){let e=
|
|
67
|
-
`),r))try{t.close(()=>{})}catch{}
|
|
67
|
+
`)}catch(t){let e=N(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
|
|
68
|
+
`),r))try{t.close(()=>{})}catch{}pi(pd),po(pu),process.exit(1);return}let i=!1,n=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},o=async()=>{if(!i){for(let e of(i=!0,await n(),ph.toArray()))ph.writeSessionLog(e);await tC(),pi(pd),po(pu),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof k?e:N(e);process.stderr.write(`Daemon error: ${t.message}
|
|
68
69
|
`),o()})}();
|