agent-device 0.11.14 → 0.11.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/152.js +1 -0
- package/dist/src/155.js +38 -0
- package/dist/src/164.js +1 -0
- package/dist/src/267.js +1 -0
- package/dist/src/556.js +1 -0
- package/dist/src/57.js +1 -0
- package/dist/src/818.js +1 -3
- package/dist/src/924.js +1 -0
- package/dist/src/940.js +1 -0
- package/dist/src/974.js +2 -2
- package/dist/src/artifacts.d.ts +3 -0
- package/dist/src/artifacts.js +1 -0
- package/dist/src/bin.js +63 -73
- package/dist/src/contracts.d.ts +59 -0
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon.js +16 -50
- package/dist/src/finders.d.ts +75 -0
- package/dist/src/finders.js +1 -0
- package/dist/src/index.d.ts +460 -44
- package/dist/src/index.js +3 -2
- package/dist/src/install-source.d.ts +40 -0
- package/dist/src/install-source.js +1 -0
- package/dist/src/metro.d.ts +6 -0
- package/dist/src/metro.js +1 -1
- package/dist/src/remote-config.js +1 -1
- package/dist/src/selectors.d.ts +110 -0
- package/dist/src/selectors.js +1 -0
- package/package.json +17 -1
- package/dist/src/32.js +0 -2
- package/dist/src/957.js +0 -2
package/dist/src/daemon.js
CHANGED
|
@@ -1,46 +1,12 @@
|
|
|
1
|
-
let e,t
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
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=n.filter(e=>"device"!==e.kind);o.length>0&&(n=o);let s=n.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??n[0]}let tN=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function t_(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 n=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of n)if(!s.existsSync(e))throw new k("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of n)if(0!==R("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await T("codesign",["--remove-signature",e],{allowFailure:!0});try{await T("codesign",["--force","--sign","-",e])}catch(n){let t=n instanceof k?n:new k("COMMAND_FAILED",String(n));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})}}}let tx=null;function tD(e){return function e(t){if(!Array.isArray(t))return[];let r=[];for(let n of t)if(!(!n||"object"!=typeof n||Array.isArray(n)))for(let[t,a]of Object.entries(n))":@"!==t&&"#text"!==t&&r.push({name:t,attributes:function(e){if(!e||"object"!=typeof e||Array.isArray(e))return{};let t={};for(let[r,n]of Object.entries(e))"string"==typeof n&&(t[r]=n);return t}(n[":@"]),text:tE(a)??tE(n["#text"]),children:e(a)});return r}((tx??=new y({ignoreAttributes:!1,attributeNamePrefix:"",preserveOrder:!0,trimValues:!0,parseTagValue:!1})).parse(e))}function tM(e,t){for(let r of e){if("dict"===r.name)for(let e=0;e<r.children.length-1;e+=1){let n=r.children[e],a=r.children[e+1];n?.name==="key"&&n.text&&a&&t(n.text,a)}tM(r.children,t)}}function tE(e){if("string"==typeof e){let t=e.trim();return t.length>0?t:null}if(!Array.isArray(e))return null;let t=e.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return null;let t=e["#text"];return"string"==typeof t?t.trim():null}).filter(e=>null!==e&&e.length>0).join("").trim();return t.length>0?t:null}let tO="XCTestDevices",tk=".agent-device-backup",tL=".agent-device-xctestdevices-backup-",tC=p.join(d.homedir(),".agent-device","ios-runner"),tP=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),tR=new Map,tT=new Set;function t$(e){return e?.trim()??""}function tF(e=process.env){return t$(e.AGENT_DEVICE_IOS_BUNDLE_ID)||t$(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tU(e=process.env){let t=t$(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tF(e)}.uitests`}let tG=function(e=process.env){let t=tF(e),r=tU(e);return Array.from(new Set([t$(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);function tV(e=d.homedir()){return p.join(e,"Library","Developer","XCTestDevices")}async function tB(e,t={}){if("ios"!==e.platform||"simulator"!==e.kind)return null;let r=e3(e.simulatorSetPath);if(!r)return null;let n=p.resolve(r),a=p.resolve(t.xctestDeviceSetPath??tV()),i=p.resolve(t.backupPath??function(e=tV()){return`${e}${tk}`}(a)),o=p.resolve(t.lockDirPath??function(e=d.homedir()){return p.join(e,".agent-device","xctest-device-set.lock")}()),l=t.ownerStartTime??eS(process.pid),u=await tH({lockDirPath:o,owner:{pid:t.ownerPid??process.pid,startTime:l,acquiredAtMs:t.nowMs??Date.now()}});try{if(tj({xctestDeviceSetPath:a,backupPath:i}),function(e,t){if(p.resolve(e)===p.resolve(t))return!0;try{return s.realpathSync.native(e)===s.realpathSync.native(t)}catch{return!1}}(n,a))return await u(),null;s.mkdirSync(n,{recursive:!0}),s.existsSync(a)&&s.renameSync(a,i),function(e){let{requestedSetPath:t,xctestDeviceSetPath:r}=e,n=p.dirname(r),a=p.join(n,`${tO}.agent-device-link-${process.pid}-${Date.now()}`);s.mkdirSync(n,{recursive:!0});try{s.symlinkSync(t,a,"dir"),s.renameSync(a,r)}catch(e){throw s.existsSync(a)&&tq(a),e}}({requestedSetPath:n,xctestDeviceSetPath:a})}catch(e){throw tj({xctestDeviceSetPath:a,backupPath:i}),await u(),new k("COMMAND_FAILED","Failed to redirect XCTest device set path",{requestedSetPath:n,xctestDeviceSetPath:a,backupPath:i,error:String(e)})}let c=!1;return{release:async()=>{if(!c){c=!0;try{tj({xctestDeviceSetPath:a,backupPath:i})}finally{await u()}}}}}function tj(e){let{xctestDeviceSetPath:t,backupPath:r}=e,n=[r,...function(e){let t=p.dirname(e),r=p.basename(e).replace(tk,""),n=r===tO?tL:`${r}${tL}`;try{return s.readdirSync(t).filter(e=>e.startsWith(n)).sort().map(e=>p.join(t,e))}catch{return[]}}(r)],a=n.find(e=>s.existsSync(e)),i=s.existsSync(t)&&s.lstatSync(t).isSymbolicLink();if(a){if(i&&tq(t),s.existsSync(t))if(!i)return void D({level:"warn",phase:"ios_runner_xctest_device_set_restore_collision",data:{xctestDeviceSetPath:t,activeBackupPath:a}});else a!==r?s.rmSync(a,{recursive:!0,force:!0}):s.rmSync(r,{recursive:!0,force:!0});else s.mkdirSync(p.dirname(t),{recursive:!0}),s.renameSync(a,t);for(let e of n)e!==a&&s.existsSync(e)&&s.rmSync(e,{recursive:!0,force:!0});return}i&&(D({level:"warn",phase:"ios_runner_xctest_device_set_orphaned_symlink",data:{xctestDeviceSetPath:t}}),tq(t))}function tq(e){!s.existsSync(e)||s.lstatSync(e).isSymbolicLink()&&s.unlinkSync(e)}async function tH(e){let{lockDirPath:t,owner:r}=e,n=p.join(t,"owner.json"),a=Date.now()+3e4;for(s.mkdirSync(p.dirname(t),{recursive:!0});Date.now()<a;)try{s.mkdirSync(t),function(e,t){let r=`${e}.${process.pid}.${Date.now()}.tmp`;s.writeFileSync(r,JSON.stringify(t),"utf8"),s.renameSync(r,e)}(n,r);let e=!1;return async()=>{e||(e=!0,s.rmSync(t,{recursive:!0,force:!0}))}}catch(e){if("EEXIST"!==e.code)throw e;if(function(e,t){let r=null;try{r=s.statSync(e)}catch{return!0}let n=function(e){try{return JSON.parse(s.readFileSync(e,"utf8"))}catch{return null}}(t);if(n){var a;return!(Number.isInteger((a=n).pid)&&!(a.pid<=0)&&eA(a.pid)&&(!a.startTime||eS(a.pid)===a.startTime))&&(s.rmSync(e,{recursive:!0,force:!0}),!0)}return!(Date.now()-r.mtimeMs<5e3)&&(s.rmSync(e,{recursive:!0,force:!0}),!0)}(t,n))continue;await new Promise(e=>setTimeout(e,100))}throw new k("COMMAND_FAILED","Timed out waiting for XCTest device set lock",{lockDirPath:t})}async function tW(e,t){var r;let n,a=(r=e,(n=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?p.resolve(n):"macos"===r.platform?p.join(tC,"derived","macos"):"simulator"===r.kind?p.join(tC,"derived"):p.join(tC,"derived",r.kind)),i=function(){let e=p.dirname(w(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=p.join(t,"package.json");if(s.existsSync(e))return t;t=p.dirname(t)}return e}();return await tv(tR,a,async()=>{z(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(t4("clean","forced_clean",{derived:a}),t3(a),tz(a));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:a,projectRoot:i,findXctestrun:t=>tK(t,e),xctestrunReferencesProjectRoot:tY,resolveExistingXctestrunProductPaths:t5});if("reuse_ready"!==r.reason&&t4("rebuild",r.reason,{derived:a,xctestrunPath:r.xctestrunPath}),"reuse_ready"===r.reason)try{return await t_(e,r.productPaths,r.xctestrunPath),t4("reuse","reuse_ready",{derived:a,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&&tN.has(t)}(e))throw e;t4("rebuild","repair_failed",{derived:a,xctestrunPath:r.xctestrunPath})}r.xctestrunPath&&(t3(a),tz(a));let n=p.join(i,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!s.existsSync(n))throw new k("COMMAND_FAILED","iOS runner project not found",{projectPath:n});await tQ(e,n,a,t);let o=tK(a,e);if(!o)throw new k("COMMAND_FAILED","Failed to locate .xctestrun after build");let l=t5(o);if(!l)throw new k("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:o});return await t_(e,l,o),t4("build","built_new",{derived:a,xctestrunPath:o}),o})}function tz(e){try{if(!s.existsSync(e))return;if("derived"!==p.basename(e))return void s.rmSync(e,{recursive:!0,force:!0});for(let r of s.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,tJ.has(t)&&s.rmSync(p.join(e,r.name),{recursive:!0,force:!0})}}catch{}}let tJ=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function tK(e,t){if(!s.existsSync(e))return null;let r=[],n=[e];for(;n.length>0;){let e=n.pop();for(let t of s.readdirSync(e,{withFileTypes:!0})){let a=p.join(e,t.name);if(t.isDirectory()){n.push(a);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=s.statSync(a);r.push({path:a,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let n=tX(r.path,t)-tX(e.path,t);if(0!==n)return n}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)}function tX(e,t){var r;let n=0,a=e.toLowerCase();p.basename(a).startsWith("agentdevicerunner.env.")&&(n-=1e3),a.includes(`${p.sep}macos${p.sep}`)&&(n-=5e3);let i="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return i.preferred.length>0&&(i.preferred.some(e=>a.includes(e))?n+=2e3:n-=500),i.disallowed.some(e=>a.includes(e))&&(n-=2500),n}function tY(e,t){try{let r=s.readFileSync(e,"utf8"),n=new Set([t]);try{n.add(s.realpathSync(t))}catch{}for(let e of n)if(r.includes(e))return!0;return!1}catch{return!1}}async function tZ(e,t,r){let n,a=p.dirname(e),i=r.replace(/[^a-zA-Z0-9._-]/g,"_"),o=p.join(a,`AgentDeviceRunner.env.${i}.json`),l=p.join(a,`AgentDeviceRunner.env.${i}.xctestrun`),u=await T("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==u.exitCode||!u.stdout.trim())throw new k("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:u.stderr});try{n=JSON.parse(u.stdout)}catch(t){throw new k("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let d=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},c=n.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&&d(e)}for(let[e,t]of Object.entries(n))t&&"object"==typeof t&&t.TestBundlePath&&(d(t),n[e]=t);s.writeFileSync(o,JSON.stringify(n,null,2));let f=await T("plutil",["-convert","xml1","-o",l,o],{allowFailure:!0});if(0!==f.exitCode)throw new k("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:f.stderr});return{xctestrunPath:l,jsonPath:o}}async function tQ(e,t,r,n){let a=function(e=process.env){let t=tF(e),r=tU(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),i=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let n=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",a=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",i=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return n&&o.push(`DEVELOPMENT_TEAM=${n}`),a&&o.push(`CODE_SIGN_IDENTITY=${a}`),i&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${i}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[],s=await tB(e);try{var l;let s;await M("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",t2(e),"1","-destination",(l=e,s=t0(l),"macOS"===s?`platform=macOS,arch=${t1()}`:"simulator"===l.kind?`platform=${s} Simulator,id=${l.id}`:`generic/platform=${s}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...a,...o,...i],{detached:!0,onSpawn:e=>{tT.add(e),e.on("close",()=>{tT.delete(e)})},onStdoutChunk:e=>{tw(e,n.logPath,n.traceLogPath,n.verbose)},onStderrChunk:e=>{tw(e,n.logPath,n.traceLogPath,n.verbose)}})}catch(i){let e,t,r=i instanceof k?i:new k("COMMAND_FAILED",String(i)),a=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
|
|
5
|
-
${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:n.logPath,hint:a})}finally{await s?.release()}}function t0(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 t1(){return"arm64"===process.arch?"arm64":"x86_64"}function t2(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function t3(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return z(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new 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 t4(e,t,r){D({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}function t5(e){let t=function(e){let t=function(e){try{let t=R("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,n,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[n,a]of Object.entries(e))if(t.has(n)){if("string"==typeof a){r.add(a);continue}if(Array.isArray(a))for(let e of a)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};i(a);let o=a.TestConfigurations;if(Array.isArray(o))for(let e of o){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{let t;return r=s.readFileSync(e,"utf8"),n=tD(r),t=new Set,tM(n,(e,r)=>{if(tP.has(e)){if("string"===r.name&&r.text)return void t.add(r.text);if("array"===r.name)for(let e of r.children)"string"===e.name&&e.text&&t.add(e.text)}}),Array.from(t)}catch{return null}}(e);if(!t||0===t.length)return null;let r=p.dirname(e),n=new Set,a=new Set,i=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),i=p.join(r,t);if(!s.existsSync(i))return null;n.add(i);let o=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);o&&a.add(p.join(r,o));continue}e.startsWith("__TESTHOST__/")&&i.push(e.slice(13))}for(let e of i){let t=Array.from(a).find(t=>s.existsSync(p.join(t,e)));if(!t)return null;n.add(p.join(t,e))}return Array.from(n)}let t8=new Map,t6=new Map;async function t9(e,t){return await tv(t6,e.id,async()=>{var r;let n,a,i=t8.get(e.id);if(i){if(function(e){return!!e&&eA(e)}(i.child.pid))return i;await rt(e.id,i)}await ("simulator"!==(r=e).kind?Promise.resolve():ro(r)),await t7(e);let o=await tW(e,t),s=await th(),{xctestrunPath:l,jsonPath:u}=await tZ(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`),d=await tB(e);try{let t;({child:n,wait:a}=L("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",t2(e),"1","-destination-timeout",String(tu),"-xctestrun",l,"-destination",(t=t0(e),"macOS"===t?`platform=macOS,arch=${t1()}`:"simulator"===e.kind?`platform=${t} Simulator,id=${e.id}`:`platform=${t},id=${e.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(s)},detached:!0}))}catch(e){throw await d?.release(),e}n.stdout?.on("data",e=>{tw(e,t.logPath,t.traceLogPath,t.verbose)}),n.stderr?.on("data",e=>{tw(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${s}:${Date.now()}`,device:e,deviceId:e.id,port:s,xctestrunPath:l,jsonPath:u,testPromise:a,child:n,ready:!1,simulatorSetRedirect:d??void 0};return t8.set(e.id,c),c})}async function t7(e){if("simulator"===e.kind)for(let t of tG){let r=await T("xcrun",e6(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==r.exitCode){let e=`${r.stdout}
|
|
6
|
-
${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 re(e){await tv(t6,e.deviceId,async()=>{await rt(e.deviceId,e)})}async function rt(e,t){let r=t??t8.get(e);if(r){try{await td(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await ri(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await ri(r.child.pid,"SIGKILL"),tg(r.xctestrunPath),tg(r.jsonPath),await r.simulatorSetRedirect?.release(),t8.get(e)===r&&t8.delete(e)}}async function rr(e){await tv(t6,e,async()=>{await rt(e)})}async function rn(){let e=Array.from(t8.values()),t=Array.from(tT);await Promise.allSettled(e.map(async e=>{await ri(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await ri(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await ri(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await ri(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await ri(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await ri(e.pid,"SIGKILL"),tT.delete(e)})),await Promise.allSettled(e.map(async e=>{await e.simulatorSetRedirect?.release()}))}async function ra(){await rn();let e=Array.from(t8.keys());await Promise.allSettled(e.map(async e=>{await rr(e)}));let t=Array.from(tT);await Promise.allSettled(t.map(async e=>{try{await ri(e.pid,"SIGTERM"),await ri(e.pid,"SIGKILL")}finally{tT.delete(e)}}))}async function ri(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let r="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await T("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function ro(e){await T("xcrun",e6(e,["bootstatus",e.id,"-b"]),{timeoutMs:tr})}async function rs(e,t,r,n,a,i){let o=await td(e,t.port,r,n,a,t,i);return await rl(o,t,n)}async function rl(e,t,r){let n=await e.text(),a={};try{a=JSON.parse(n)}catch{throw new k("COMMAND_FAILED","Invalid runner response",{text:n})}if(!a.ok)throw new k("string"==typeof a.error?.code&&a.error.code.trim().length>0?a.error.code:"COMMAND_FAILED",a.error?.message??"Runner error",{runner:a,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,a.data??{}}async function ru(e,t,r={}){var n;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(tt(r.requestId),"interactionFrame"===(n=t.command)||"snapshot"===n||"screenshot"===n||"findText"===n||"readText"===n||"alert"===n||"uptime"===n)?H(()=>(tt(r.requestId),rd(e,t,r)),{shouldRetry:e=>{tt(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"))}}):rd(e,t,r)}async function rd(e,t,r={}){let n;tt(r.requestId);let a=ez(r.requestId);try{let i=(n=await t9(e,r)).ready?tn:tr;return await rs(e,n,t,r.logPath,i,a)}catch(o){let i=o instanceof k?o:new k("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===i.code&&"string"==typeof i.message&&i.message.includes("Runner did not accept connection")&&e9(i)&&n?.ready){tt(r.requestId),n?await re(n):await rr(e.id),n=await t9(e,r);let i=await td(n.device,n.port,t,r.logPath,tr,void 0,a);return await rl(i,n,r.logPath)}throw o}}function rc(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 rp(e){let t=new Set,r=[];for(let n of e)t.has(n)||(t.add(n),r.push(n));return r}let rf=/^-?\d+(\.\d+)?$/,rm=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),rh=new Map([["--count","count"],["--pause-ms","pauseMs"]]),rw=new Map([["--delay-ms","delayMs"]]);function rg(e){return"click"===e||"press"===e}function ry(e){return"type"===e||"fill"===e}function rv(e){let t=e.trim();return t.startsWith("@")||rf.test(t)?t:JSON.stringify(t)}function rI(e){return JSON.stringify(e)}function rb(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function rA(e,t){let r=t.flags??{};if(rg(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}ry(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function rS(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",rb(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",rb(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",rb(t.launchUrl)))}function rN(e,t){let[r,...n]=t.positionals??[];for(let t of(r&&e.push(rb(r)),n))e.push(rv(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function r_(e,t){let r=[],n={},a=rg(e)?rm:"swipe"===e?rh:ry(e)?rw:void 0;for(let i=0;i<t.length;i+=1){let o=t[i];if(rg(e)&&"--double-tap"===o){n.doubleTap=!0;continue}if(rg(e)&&"--button"===o&&i+1<t.length){let e=t[i+1];("primary"===e||"secondary"===e||"middle"===e)&&(n.clickButton=e),i+=1;continue}let s=a?.get(o);if(s&&i+1<t.length){let e=rD(t[i+1]);if(null!==e){n[s]=e,i+=1;continue}}if("swipe"===e&&"--pattern"===o&&i+1<t.length){let e=t[i+1];("one-way"===e||"ping-pong"===e)&&(n.pattern=e),i+=1;continue}r.push(o)}return{positionals:r,flags:n}}function rx(e){let t=[],r={};for(let n=0;n<e.length;n+=1){let a=e[n];if("--platform"===a&&n+1<e.length){let t=e[n+1];("ios"===t||"android"===t)&&(r.platform=t),n+=1;continue}if("--metro-host"===a&&n+1<e.length){r.metroHost=e[n+1],n+=1;continue}if("--metro-port"===a&&n+1<e.length){let t=rD(e[n+1]);null!==t&&(r.metroPort=t),n+=1;continue}if("--bundle-url"===a&&n+1<e.length){r.bundleUrl=e[n+1],n+=1;continue}if("--launch-url"===a&&n+1<e.length){r.launchUrl=e[n+1],n+=1;continue}t.push(a)}return{positionals:t,flags:r}}function rD(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function rM(e,t){for(let r of t.positionals??[])e.push(rv(r));t.flags?.relaunch&&e.push("--relaunch"),rS(e,t.runtime)}class rE{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=rE.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 t={};for(let r of rO)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),D({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=p.dirname(t);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let n=function(e,t){let r=[],n=e.device.kind?` kind=${e.device.kind}`:"";for(let a of(r.push(`context platform=${e.device.platform} device=${rI(e.device.name)}${n} theme=unknown`),t))a.flags?.noRecord||r.push(function(e){let t=[e.command];if(rg(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(rv(r));let n=e.result?.refLabel;return"string"==typeof n&&n.trim().length>0&&t.push(rv(n)),rA(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(rv(r)),rA(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(rv(r));let n=e.result?.refLabel,a=e.positionals.slice(1).join(" ");return"string"==typeof n&&n.trim().length>0&&t.push(rv(n)),a&&t.push(rv(a)),rA(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],n=e.positionals?.[1];if(r&&n){if(t.push(rv(r)),t.push(rv(n)),n.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(rv(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",rv(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(rv(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}if("open"===e.command)return rM(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(rb(r)),rS(t,e.flags),t.join(" ")}if("record"===e.command)return rN(t,e),t.join(" ");for(let r of e.positionals??[])t.push(rv(r));return rA(t,e),t.join(" ")}(a));return`${r.join("\n")}
|
|
7
|
-
`}(e,this.buildOptimizedActions(e));s.writeFileSync(t,n)}catch{}}defaultTracePath(e){let t=rE.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return p.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return p.join(this.sessionsDir,rE.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return p.join(this.sessionsDir,rE.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return ep(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return rE.expandHome(e.saveScriptPath);s.existsSync(this.sessionsDir)||s.mkdirSync(this.sessionsDir,{recursive:!0});let t=rE.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return p.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let n=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(n.length>0&&(rg(r.command)||"fill"===r.command||"get"===r.command)){let e=n.join(" || ");if(rg(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let n=rc(r);if(n.length>0){t.push({...r,positionals:[e,n]});continue}}if("get"===r.command){let n=r.positionals?.[0];if("text"===n||"attrs"===n){t.push({...r,positionals:[n,e]});continue}}}if(rg(r.command)||"fill"===r.command||"get"===r.command){let n=r.result?.refLabel;"string"==typeof n&&n.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:n.trim()},result:{scope:n.trim()}})}t.push(r)}return t}}let rO=["platform","device","udid","serial","out","verbose","metroHost","metroPort","bundleUrl","launchUrl","snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw","screenshotFullscreen","relaunch","saveScript","noRecord","fps","hideTouches","count","intervalMs","delayMs","holdMs","jitterPx","doubleTap","clickButton","pauseMs","pattern"],rk="app-log.pid";function rL(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}}function rC(e,t){if(!e)return;let r=p.dirname(e);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let n={pid:t,startTime:eS(t)??void 0,command:V(t)??void 0};s.writeFileSync(e,`${JSON.stringify(n)}
|
|
8
|
-
|
|
9
|
-
`)},flush:()=>{n&&(a(n),n="")}}}function rF(e,t,r){let n=e.stdout,a=e.stderr;return n&&a?(n.setEncoding("utf8"),a.setEncoding("utf8"),n.on("data",r.writer.onChunk),a.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(n=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),n({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}function rU(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new k("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function rG(e,t){let r=(await T("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function rV(e,t){var r,n;let a;rU(t);let i=await rG(e,t),o=await T("adb",["-s",e,"logcat","-d","-v","time","-t","4000"],{allowFailure:!0,timeoutMs:3e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=function(e,t,r){let n=new Set;for(let a of(r&&n.add(r),e.split("\n")))if(a.includes(t))for(let e of function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=[RegExp(`\\bStart proc\\s+(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`\\b(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`${r}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,"i"),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${r}`,"i")],a=[];for(let t of n){let r=t.exec(e),n=r?.[1];n&&/^\d+$/.test(n)&&a.push(n)}return a}(a,t))n.add(e);return[...n]}(o.stdout,t,i);if(0===s.length)return null;let l=(r=o.stdout,n=t,a=new Set(s),r.split("\n").filter(e=>{var t;let r;if(!e.trim())return!1;if(e.includes(n))return!0;let i=(t=e,r=/\(\s*(\d+)\)\s*:/.exec(t),r?.[1]??null);return!!i&&a.has(i)}).join("\n"));return 0===l.trim().length?null:{pid:i,text:l,recoveredPids:s}}async function rB(e,t,r,n,a){let i,o,s="recovering",l=!1,u=(async()=>{try{for(;!l;){let u=await rG(e,t);if(!u){s="recovering",await rT(1e3);continue}let d=v("adb",["-s",e,"logcat","-v","time","--pid",u],{stdio:["ignore","pipe","pipe"]});i=d;let c=r$(r,{redactionPatterns:n});if(o=rF(d,r,{endStreamOnClose:!1,writer:c}),"number"==typeof d.pid&&(rC(a,d.pid),s="active"),await o,rP(a),i=void 0,o=void 0,l)break;s="recovering",await rT(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),rP(a)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:u,stop:async()=>{l=!0,i&&!i.killed&&i.kill("SIGINT"),o&&await rR(o),i&&!i.killed&&i.kill("SIGKILL"),await rR(u),rP(a)}}}function rj(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}"`}async function rq(e){let{deviceId:t,appBundleId:r,startedAt:n,simulatorSetPath:a}=e,i=e8(["spawn",t,"log","show","--style","compact","--info","--predicate",rj(r)],{simulatorSetPath:a});"number"==typeof n&&Number.isFinite(n)&&n>0?i.push("--start",`@${Math.floor(n/1e3)}`):i.push("--last","5m");let o=await T("xcrun",i,{allowFailure:!0,timeoutMs:4e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=o.stdout.split("\n").map(e=>e.trimEnd()).filter(e=>{let t=e.trim();return t.length>0&&!t.startsWith("Timestamp Ty Process[PID:TID]")});return 0===s.length?null:{text:`${s.join("\n")}
|
|
10
|
-
`,recoveredLineCount:s.length}}async function rH(e,t,r,n,a,i){let o="active",s=v("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:n}=e;return e8(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",rj(r)],{simulatorSetPath:n})}({deviceId:e,appBundleId:t,simulatorSetPath:a}),{stdio:["ignore","pipe","pipe"]}),l=r$(r,{redactionPatterns:n});"number"==typeof s.pid&&rC(i,s.pid);let u=rF(s,r,{endStreamOnClose:!0,writer:l}).then(e=>(0!==e.exitCode&&(o="failed"),rP(i),e));return{backend:"ios-simulator",getState:()=>o,startedAt:Date.now(),wait:u,stop:async()=>{s.killed||s.kill("SIGINT"),await rR(u),s.killed||s.kill("SIGKILL"),await rR(u),rP(i)}}}async function rW(e,t,r,n){let a="active",i=v("log",["stream","--style","compact","--predicate",rj(e)],{stdio:["ignore","pipe","pipe"]}),o=r$(t,{redactionPatterns:r});"number"==typeof i.pid&&rC(n,i.pid);let s=rF(i,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(a="failed"),rP(n),e));return{backend:"macos",getState:()=>a,startedAt:Date.now(),wait:s,stop:async()=>{i.killed||i.kill("SIGINT"),await rR(s),i.killed||i.kill("SIGKILL"),await rR(s),rP(n)}}}async function rz(e,t,r,n){let a="active",i=v("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=r$(t,{redactionPatterns:r});"number"==typeof i.pid&&rC(n,i.pid);let s=rF(i,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(a="failed"),rP(n),e));return{backend:"ios-device",getState:()=>a,startedAt:Date.now(),wait:s,stop:async()=>{i.killed||i.kill("SIGINT"),await rR(s),i.killed||i.kill("SIGKILL"),await rR(s),rP(n)}}}let rJ=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),rK=/https?:\/\/[^\s"'<>\])]+/i,rX=[/\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 rY(e,t,r=e.limits.maxEntries){let n=[...e.entries],a=new Set(n.map(e=>rQ(e)));for(let e of t.entries){let t=rQ(e);if(!a.has(t)&&(a.add(t),n.push(e),n.length>=r))break}return{...e,matchedLines:n.length,entries:n}}function rZ(e,t){let r=r7(t?.maxEntries,25,1,200),n=t?.backend,a=t?.include??"summary",i=r7(t?.maxPayloadChars,2048,64,16384),o=r7(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),u=s.slice(l),d=[];for(let e=u.length-1;e>=0&&d.length<r;e-=1){let t=u[e];if(!t?.trim())continue;let r=function(e,t,r,n,a,i){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let n=e.slice(t,r+1);try{let e=JSON.parse(n);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=r5(s,["method","httpMethod"]),u=r5(s,["url","requestUrl"]),d=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=rJ.exec(o),p=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),f=(l??p?.[1]??c?.[1])?.toUpperCase(),m=rK.exec(o),h=u??m?.[0];if(!h)return null;let w=d??r1(o)??void 0;if(!(l||p?.[1]||c?.[1]||void 0!==w||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let g={method:f,url:h,status:w,timestamp:r2(o),packetId:r3(o)??void 0,durationMs:r4(o)??void 0,raw:r9(o,i),line:r};if("android"===n&&function(e,t,r){let n=r0(t,r,5),a=e.packetId??n.map(e=>r3(e)).find(e=>"string"==typeof e&&e.length>0);a&&(e.packetId=a);let i=a?r0(t,r,12).filter(e=>r3(e)===a):n;e.timestamp||(e.timestamp=i.map(e=>r2(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=i.map(e=>r1(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=i.map(e=>r4(e)).find(e=>"number"==typeof e))}(g,e,t),"headers"===a||"all"===a){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return r6(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(g.headers=r9(e,i))}if("body"===a||"all"===a){let e=r8(o,s,["requestBody","body","payload","request"]),t=r8(o,s,["responseBody","response"]);e&&(g.requestBody=r9(e,i)),t&&(g.responseBody=r9(t,i))}return g}(u,e,l+e+1,n,a,i);r&&d.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:u.length,matchedLines:d.length,entries:d,include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:o}}}function rQ(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function r0(e,t,r){let n=[],a=Math.max(0,t-r),i=Math.min(e.length-1,t+r);for(let t=a;t<=i;t+=1){let r=e[t]?.trim();r&&n.push(r)}return n}function r1(e){for(let t of rX){let r=t.exec(e);if(!r)continue;let n=Number.parseInt(r[1]??"",10);if(Number.isInteger(n))return n}return null}function r2(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function r3(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function r4(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function r5(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 r8(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return r6(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(n?.[1])return n[1].trim()}}function r6(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function r9(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function r7(e,t,r,n){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(n,e)):t}function ne(e,t){let r=process.env[e];if(!r)return t;let n=Number.parseInt(r,10);return Number.isInteger(n)&&n>0?n:t}function nt(e){let t=p.dirname(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),function(e,t){if(s.existsSync(e)&&!(s.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,n=`${e}.${r}`;s.existsSync(t)&&(s.existsSync(n)&&s.unlinkSync(n),s.renameSync(t,n))}}(e,{maxBytes:ne("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:ne("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function nr(e){var t,r,n,a;let i,o,l,u,{device:d,appBundleId:c,appLogState:p,appLogStartedAt:f,appLogPath:m,maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y}=e,v="macos"===d.platform?"macos":"ios"===d.platform?"device"===d.kind?"ios-device":"ios-simulator":"android",I=(t={backend:v,maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y},i=r7(t?.maxEntries,25,1,200),o=t?.include??"summary",l=r7(t?.maxPayloadChars,2048,64,16384),u=r7(t?.maxScanLines,4e3,100,2e4),s.existsSync(m)?rZ(s.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:o,limits:{maxEntries:i,maxPayloadChars:l,maxScanLines:u}}),b=[],A=await nn({device:d,appBundleId:c,appLogPath:m,appLogState:p});if(A){let e=await rV(d.id,c);if(e){let t=rZ(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y});t.entries.length>0&&(I=rY(t,I,h),b.push((r=A,n=e.recoveredPids,"stale-active"===r.reason?`Session app log stream was still bound to prior Android PID ${r.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${n.join(", ")}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${n.join(", ")}.`)))}}if("ios"===d.platform&&"simulator"===d.kind&&c&&0===I.entries.length){let e=await ni({deviceId:d.id,appBundleId:c,startedAt:f,simulatorSetPath:d.simulatorSetPath,appLogPath:m,maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y});e&&(e.dump.entries.length>0?(I=rY(e.dump,I,h),b.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&b.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===p?b.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==p&&0===b.length&&("ios"===d.platform&&"simulator"===d.kind?b.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):b.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===I.entries.length&&b.push("ios"===(a=d).platform&&"simulator"===a.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===a.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:v,dump:I,notes:b}}async function nn(e){let{device:t,appBundleId:r,appLogPath:n,appLogState:a}=e;if("android"!==t.platform||!r)return null;if(void 0!==a&&"active"!==a)return{reason:"inactive"};if("active"!==a)return null;let i=function(e){let t=function(e){if(!e||!s.existsSync(e))return null;try{return rL(s.readFileSync(e,"utf8"))}catch{return null}}(e)?.command;if(!t)return null;let r=/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(t);return r?.[1]??null}(p.join(p.dirname(n),rk));if(!i)return null;let o=await rG(t.id,r);return o&&o!==i?{reason:"stale-active",trackedPid:i}:null}async function na(e,t,r,n){nt(r);let a=s.createWriteStream(r,{flags:"a"}),i=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await rz(e.id,a,i,n):await rH(e.id,t,a,i,e.simulatorSetPath,n);if("android"===e.platform)return rU(t),await rB(e.id,t,a,i,n);if("macos"===e.platform)return await rW(t,a,i,n);throw a.end(),new k("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function ni(e){let t=await rq({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:rZ(t.text,{path:`${e.appLogPath} (simctl log show recovery)`,backend:"ios-simulator",maxEntries:e.maxEntries,include:e.include,maxPayloadChars:e.maxPayloadChars,maxScanLines:e.maxScanLines}),recoveredLineCount:t.recoveredLineCount}:null}async function no(e){await e.stop(),await rR(e.wait)}async function ns(e,t){let r={},n=[];if(t||n.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await T("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await T("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await T("xcrun",["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await T("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await T("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:n}}function nl(e){let t=p.dirname(e),r=p.basename(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),s.existsSync(e)?s.truncateSync(e,0):s.writeFileSync(e,"","utf8");let n=0;for(let e of s.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let a=e.slice(r.length+1);if(/^\d+$/.test(a))try{s.unlinkSync(p.join(t,e)),n+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:n}}let nu=new Map;function nd(e){let t=nu.get(e);if(t&&(clearTimeout(t.timer),nu.delete(e),t.deleteAfterDownload))try{s.rmSync(t.artifactPath,{force:!0})}catch{}}let nc=new Map;function np(e,t){let r=nc.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 nf(e){let t=nc.get(e);t&&(clearTimeout(t.timer),nc.delete(e),s.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function nm(e){let t=await nh(e);await T("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=p.join(e.tempDir,t);if(!s.existsSync(r))throw new k("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function nh(e){let t=await T("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 n=r.map(nw),a=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let n=[...r];if("ios"===t){let e=n.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===n.length)return n[0];throw new k("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${n.join(", ")}`)}(n,e.platform);if(!n.some(e=>e===a||e.startsWith(`${a}/`)))throw new k("INVALID_ARGS",`Uploaded archive must contain a top-level "${a}" bundle`);for(let e of n){var i=e,o=a;if(i!==o&&!i.startsWith(`${o}/`))throw new k("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${i}`)}for(let t of(await T("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new k("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return a}function nw(e){if(e.includes("\0"))throw new k("INVALID_ARGS",`Invalid archive entry: ${e}`);if(p.posix.isAbsolute(e))throw new k("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=p.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new k("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let ng=eX(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function ny(e,t){return new Promise((r,n)=>{let a,i=s.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,u=0,d=e=>{if(!l){if(l=!0,a&&clearTimeout(a),e){i.destroy(),s.rmSync(t,{force:!0}),n(e);return}r()}},c=()=>{a&&clearTimeout(a),a=setTimeout(()=>{let e=new k("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:ng});o(e),i.destroy(e),d(e)},ng)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((u+=t)>0x80000000){let e=new k("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),i.destroy(e),d(e)}}),e.on("error",d),e.on("aborted",()=>{d(new k("COMMAND_FAILED","Artifact transfer was interrupted"))}),i.on("error",d),i.on("finish",()=>d()),c(),e.pipe(i)})}async function nv(e){let t,r=e.headers["x-artifact-type"],n=e.headers["x-artifact-filename"];if(!r||!n)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 a=function(e){let t=e.trim(),r=p.basename(t);if(!r||"."===r||".."===r)throw new k("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(n),i=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),s.mkdtempSync(p.join(d.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=p.join(i,a);return await ny(e,t),{artifactPath:t,tempDir:i}}let t=p.join(i,"artifact.tar");await ny(e,t);let n=await nm({archivePath:t,tempDir:i,platform:"ios",expectedRootName:a});return s.rmSync(t,{force:!0}),{artifactPath:n,tempDir:i}}catch(e){throw s.rmSync(i,{recursive:!0,force:!0}),e}}let nI=new Set(["agent_device.command","agent-device.command"]),nb=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),nA=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),nS={"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"},nN=new Set([...nI,...nb,...nA,...Object.keys(nS)]);function n_(e,t,r,n){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:n}}}function nx(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function nD(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function nM(e,t){let r="string"==typeof t.authorization?t.authorization:"",n=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,a="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??a??n??""}function nE(e,t){let r=e[t];return"string"==typeof r?r:void 0}function nO(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function nk(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=O(new k("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:n_(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=O(new k(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:n_(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=q(r.tenantId);if(!e){let e=O(new k("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:n_(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function nL(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",n=p.isAbsolute(t)?t:p.resolve(t);try{e=await import(g(n).href)}catch(e){throw new k("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:n,error:e instanceof Error?e.message:String(e)})}let a=e[r];if("function"!=typeof a)throw new k("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:n,exportName:r});return a}async function nC(e){let t=await nL(),{handleRequest:r,token:n}=e;return I.createServer((e,a)=>{if("GET"===e.method&&"/health"===e.url){a.statusCode=200,a.setHeader("content-type","application/json"),a.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void nP(e,a,t,n);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void nR(e,a,t,n);if("POST"!==e.method||"/rpc"!==e.url){a.statusCode=404,a.end("Not found");return}let i="";e.setEncoding("utf8"),e.on("data",t=>{(i+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{a.headersSent||nx(a,n_(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let n,o;try{n=JSON.parse(i)}catch{nx(a,n_(null,-32700,"Parse error"),400);return}if("2.0"!==n.jsonrpc||"string"!=typeof n.method)return void nx(a,n_(n.id??null,-32600,"Invalid Request"),400);if(!nN.has(n.method))return void nx(a,n_(n.id??null,-32601,`Method not found: ${n.method}`),404);if(!n.params||"object"!=typeof n.params)return void nx(a,n_(n.id??null,-32602,"Invalid params"),400);try{var s;let i=n.params,l=function(e,t,r){if(nI.has(e))return{token:nM(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(nb.has(e)){let e,n=nE(t,"platform");if("ios"!==n&&"android"!==n)throw new k("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:nM(t,r),session:nE(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:n},meta:{requestId:nE(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,n={};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");n[e]=t}}return Object.keys(n).length>0?{kind:"url",url:e,headers:n}:{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:nO(t,"retentionMs")}}}if(nA.has(e)){let e=nE(t,"materializationId")?.trim();if(!e)throw new k("INVALID_ARGS","Invalid params: materializationId is required");return{token:nM(t,r),session:nE(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:nE(t,"requestId"),materializationId:e}}}let n=nS[e];if(n)return{token:nM(t,r),session:nE(t,"session")??"default",command:n,positionals:[],meta:{tenantId:nE(t,"tenantId")??nE(t,"tenant"),runId:nE(t,"runId"),leaseId:nE(t,"leaseId"),leaseTtlMs:nO(t,"ttlMs"),leaseBackend:nE(t,"backend")}};throw new k("INVALID_ARGS",`Method not found: ${e}`)}(n.method,i,e.headers);if(s=n.method,nI.has(s)&&("string"!=typeof l.command||0===l.command.length))return void nx(a,n_(n.id??null,-32602,"Invalid params: command is required"),400);o=eB(l.meta?.requestId,n.id),l.meta={...l.meta,requestId:o},ej(o);let u=()=>{a.writableFinished||eq(o)};e.on("aborted",u),a.on("close",u);let d=await nk(t,{headers:e.headers,rpcRequest:n,daemonRequest:l});if(!d.ok)return void nx(a,d.response,d.statusCode);d.tenantId&&(l.meta={...l.meta,tenantId:d.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void nx(a,{jsonrpc:"2.0",id:n.id??null,result:c});nx(a,n_(n.id??null,-32e3,c.error.message,c.error),nD(c.error.code))}catch(t){let e=O(t);nx(a,n_(n.id??null,-32e3,e.message,e),nD(e.code))}finally{eH(o)}})})}async function nP(e,t,r,n){try{var a;let o,s,l=nM({},e.headers),u=nT(l,n);if(u){t.statusCode=nD(u.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.message,code:u.code}));return}let d=await nk(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let c=await nv(e),p=(a={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:d.tenantId},o=i.randomUUID(),(s=setTimeout(()=>{nf(o)},3e5)).unref(),nc.set(o,{artifactPath:a.artifactPath,tempDir:a.tempDir,tenantId:a.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:p}))}catch(r){let e=O(r);t.statusCode=nD(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function nR(e,t,r,n){let a=e.url?.slice("/upload/".length)??"";if(!a){t.statusCode=400,t.end("Missing artifact id");return}try{let i=nM({},e.headers),o=nT(i,n);if(o){t.statusCode=nD(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let l=await nk(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:i,session:"default",command:"download_artifact",positionals:[a]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let u=function(e,t){let r=nu.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(!s.existsSync(r.artifactPath))throw nd(e),new k("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(a,l.tenantId),d=s.createReadStream(u.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),u.fileName&&t.setHeader("content-disposition",`attachment; filename="${u.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=O(e);t.statusCode=nD(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&nd(a)}),d.pipe(t)}catch(r){let e=O(r);t.statusCode=nD(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function nT(e,t){return t&&e!==t?O(new k("UNAUTHORIZED","Invalid token")):null}function n$(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function nF(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function nU(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new k("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class nG{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=nU(e.backend),r=q(e.tenantId);if(!r)throw new k("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let n=n$(e.runId);if(!n)throw new k("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let a=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(r,n,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,a);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),u={leaseId:i.randomBytes(16).toString("hex"),tenantId:r,runId:n,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+a};return this.leases.set(u.leaseId,u),this.runBindings.set(o,u.leaseId),{...u}}heartbeatLease(e){let t=nF(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 n=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,n)}releaseLease(e){let t=nF(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=nU(e.backend),r=q(e.tenantId);if(!r)throw new k("INVALID_ARGS","tenant isolation requires tenant id.");let n=n$(e.runId);if(!n)throw new k("INVALID_ARGS","tenant isolation requires run id.");let a=nF(e.leaseId);if(!a)throw new k("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let i=this.leases.get(a);if(!i)throw new k("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(i.backend!==t||i.tenantId!==r||i.runId!==n)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(),n={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(n.leaseId,n),this.runBindings.set(this.bindingKey(n.tenantId,n.runId,n.backend),n.leaseId),{...n}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let n=q(t),a=n$(r);if(t&&!n)throw new k("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!a)throw new k("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(n&&e.tenantId!==n||a&&e.runId!==a)throw new k("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let nV=["emulator","platform-tools",p.join("cmdline-tools","latest","bin"),p.join("cmdline-tools","tools","bin")];function nB(e){let t=new Set,r=[];for(let n of e){let e=n.trim();!e||t.has(e)||(t.add(e),r.push(e))}return r}function nj(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),n=e.HOME?.trim()||d.homedir();return nB([t??"",r??"",n?p.join(n,"Android","Sdk"):""])}async function nq(e){try{return await u.access(e,u.constants.X_OK),!0}catch{return!1}}async function nH(e=process.env){let t,r=[];for(let n of nj(e)){let e=[];for(let t of nV){let r=p.join(n,t);await nq(r)&&e.push(r)}0!==e.length&&(t||(t=n),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 n=(e.PATH??"").split(p.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=nB([...r,...n]).join(p.delimiter)}function nW(e,t){return["-s",e.id,...t]}async function nz(){if(await nH(),!await F("adb"))throw new k("TOOL_MISSING","adb not found in PATH")}function nJ(e,t){let r=`${e}
|
|
11
|
-
${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function nK(e){await new Promise(t=>setTimeout(t,e))}function nX(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 n=r[1]?.toLowerCase(),a=r[2]??"";return"http"!==n&&"https"!==n&&"ws"!==n&&"wss"!==n&&"ftp"!==n&&"ftps"!==n||a.startsWith("//")}function nY(e,t){let r,n=e?.trim();return n?n:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}let nZ=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function nQ(e){return`${e.stdout}
|
|
12
|
-
${e.stderr}`}function n0(e,t){return["-s",e,...t]}function n1(e){return e.startsWith("emulator-")}function n2(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function n3(e,t=Y.android_boot.operationMs){return T("adb",n0(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function n4(e,t){let r=t.replace(/_/g," ").trim();if(!n1(e))return r||e;let n=await n8(e);return n?n.replace(/_/g," "):r||e}async function n5(e,t,r){try{return await r("adb",n0(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var n;if("COMMAND_FAILED"===(n=E(e)).code&&"number"==typeof n.details?.timeoutMs)return;throw e}}async function n8(e,t=T){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let n=await n5(e,["shell","getprop",r],t);if(!n)continue;let a=n.stdout.trim();if(0===n.exitCode&&a.length>0)return a}let r=await n5(e,["emu","avd","name"],t);if(!r)return;let n=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&&n)return n}async function n6(e,t){let r=nQ(await T("adb",n0(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:Y.android_boot.operationMs})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function n9(e){return(await Promise.all(nZ.map(async t=>await n6(e,t)))).some(e=>!0===e)}async function n7(e){var t;let r;return"tv"===((r=nQ(await T("adb",n0(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:Y.android_boot.operationMs})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await n9(e)?"tv":(t=nQ(await T("adb",n0(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:Y.android_boot.operationMs})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function ae(e={}){if(await nH(),!await F("adb"))throw new k("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??e5(void 0),r=(await at()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,n,a]=await Promise.all([n4(e,t),ai(e),n7(e)]);return{platform:"android",id:e,name:r,kind:n1(e)?"emulator":"device",target:a,booted:n}}))}async function at(){return(await T("adb",["devices","-l"],{timeoutMs:Y.android_boot.operationMs})).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 ar(){let e=await T("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:Y.android_boot.operationMs});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 aa(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 aa(e,t){let r=n2(e);for(let e of(await at()).filter(e=>(!t||e.serial===t)&&n1(e.serial)))if(n2(e.rawModel)===r||n2(await n4(e.serial,e.rawModel))===r)return e.serial}async function ai(e){try{let t=await n3(e);return"1"===t.stdout.trim()}catch{return!1}}async function ao(e){var t,r;let n;await nH();let a=e.avdName.trim();if(!a)throw new k("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let i=e.timeoutMs??12e4;if(!await F("adb"))throw new k("TOOL_MISSING","adb not found in PATH");if(!await F("emulator"))throw new k("TOOL_MISSING","emulator not found in PATH");let o=await ar(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let n=n2(t);return e.find(e=>n2(e)===n)}(o,a);if(!s)throw new k("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:a,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),u=(t=await ae(),r=e.serial,n=n2(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&n2(e.name)===n));if(!u){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),C("emulator",t)}let d=u??await an({avdName:s,serial:e.serial,timeoutMs:i}),c=Math.max(1e3,i-(Date.now()-l));await as(d.id,c);let p=(await ae()).find(e=>e.id===d.id);return p?{...p,name:s,booted:!0}:{...d,name:s,booted:!0}}async function as(e,t=6e4){let r,n=ec.fromTimeoutMs(t),a=Math.max(1,Math.ceil(t/1e3)),i=!1;try{await eb(async({deadline:a})=>{if(a?.isExpired())throw i=!0,new k("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:n.elapsedMs(),message:"timeout"});let o=Math.max(1e3,a?.remainingMs()??t),s=await n3(e,Math.min(o,Y.android_boot.operationMs));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:a,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=eY({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:n,phase:"boot",classifyReason:e=>eY({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let a=E(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,u=eY({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===u&&"Android device is still booting"===a.message&&(u="ANDROID_BOOT_TIMEOUT");let d={serial:e,timeoutMs:t,elapsedMs:n.elapsedMs(),reason:u,hint:eZ(u),stdout:o,stderr:s,exitCode:l};if(i||"ANDROID_BOOT_TIMEOUT"===u)throw new k("COMMAND_FAILED","Android device did not finish booting in time",d);if("TOOL_MISSING"===a.code)throw new k("TOOL_MISSING",a.message,{...d,...a.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===u)throw new k("COMMAND_FAILED",a.message,{...d,...a.details??{}});throw new k(a.code,a.message,{...d,...a.details??{}},a.cause)}}let al=/\.(?:apk|aab)$/i,au=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function ad(e){var t,r;let n=e.trim();return 0===n.length?"other":al.test(n)?n.includes("/")||n.includes("\\")||n.startsWith(".")||n.startsWith("~")||(t=n,!au.test(t))?"binary":"package":(r=n,au.test(r))?"package":"other"}function ac(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let ap=[".zip",".tar",".tar.gz",".tgz"],af=eX(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),am=["1","true","yes","on"];async function ah(e){let t=[];try{let r=await aw(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let n=await ab(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:n.archivePath,installablePath:n.installablePath,cleanup:async()=>{await a_(t)}}}catch(e){throw await a_(t),e}}async function aw(e,t){if("path"===e.kind)return{localPath:er(e.path),cleanup:async()=>{}};let r=await u.mkdtemp(p.join(d.tmpdir(),"agent-device-source-"));try{return{localPath:await ag(r,e.url,e.headers,t),cleanup:async()=>{await u.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await u.rm(r,{recursive:!0,force:!0}),e}}async function ag(e,t,r,n){let a;try{a=new URL(t)}catch{throw new k("INVALID_ARGS",`Invalid source URL: ${t}`)}await ay(a);let i=n?.signal;if(i?.aborted)throw new k("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,s=()=>{o.abort(i?.reason)};i?.addEventListener("abort",s,{once:!0});let l=n?.downloadTimeoutMs??af,d=setTimeout(()=>{o.abort(Error("download timeout"))},l);try{let t=await fetch(a,{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:a.toString()});let n=function(e,t){let r=e.headers.get("content-disposition"),n=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),a=n?.[1]?.trim();if(a)return p.basename(a);let i=p.basename(t.pathname);return i||"downloaded-artifact.bin"}(t,a),i=p.join(e,n),s=t.body;if(!s)throw new k("COMMAND_FAILED","Download response body was empty",{url:a.toString()});let l=await u.open(i,"w");try{for await(let e of s)await l.write(e)}finally{await l.close()}return i}catch(e){if(i?.aborted)throw new k("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new k("COMMAND_FAILED",`App source download timed out after ${l}ms`,{timeoutMs:l,url:a.toString()},e);throw e}finally{i?.removeEventListener("abort",s),clearTimeout(d)}}async function ay(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new k("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!am.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||aI(t))throw new 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 b.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>aI(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 av(e){var t,r,n,a;let i=e instanceof URL?e:new URL(e),o=i.hostname.toLowerCase();if(!o)return!1;let s=i.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(n=o,a=s,("expo.dev"===n||!!n.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(a))}function aI(e){let t,r=f.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,n]=t;return 10===r||127===r||169===r&&254===n||172===r&&!!(n>=16)&&!!(n<=31)||192===r&&168===n}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function ab(e,t){let r=await u.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()&&aN(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 aS(e);return t.registerCleanup(r.cleanup),await ab(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await aA(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 n=await aA(e,(e,t)=>t.isFile()&&aN(e));if(1===n.length){if(!t.allowArchiveExtraction)throw new k("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:n[0]});let e=await aS(n[0]);return t.registerCleanup(e.cleanup),await ab(e.outputPath,{...t,archivePath:t.archivePath??n[0]})}if(n.length>1)throw new k("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:n})}throw new k("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function aA(e,t){let r=[],n=[{path:e,depth:0}];for(;n.length>0;){let e=n.shift();if(!e)continue;let a=await u.readdir(e.path,{withFileTypes:!0});for(let i of(a.sort((e,t)=>e.name.localeCompare(t.name)),a)){let a=p.join(e.path,i.name);if(t(a,i)){r.push(a);continue}i.isDirectory()&&e.depth<5&&n.push({path:a,depth:e.depth+1})}}return r}async function aS(e){let t=await u.mkdtemp(p.join(d.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await T("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await T("tar",["-xzf",e,"-C",t]):await T("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await u.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await u.rm(t,{recursive:!0,force:!0}),e}}function aN(e){let t=e.toLowerCase();return ap.some(e=>t.endsWith(e))}async function a_(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let ax=new S("utf-16le");async function aD(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let n=await aM(e,r);if(!n)continue;let a=(t=n).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 n=e.readUInt16LE(r),a=e.readUInt16LE(r+2),i=e.readUInt32LE(r+4);if(i<=0||r+i>e.length)break;if(1===n)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),n=e.readUInt32LE(20),a=(256&r)!=0,i=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=n+e.readUInt32LE(t);i.push(a?function(e,t){let[,r]=aE(e,t),[n,a]=aE(e,t+r),i=t+r+a;return e.subarray(i,i+n).toString("utf8")}(e,o):function(e,t){let[r,n]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),a=t+n;return ax.decode(e.subarray(a,a+2*r))}(e,o))}return i}(e.subarray(r,r+i));else if(258===n&&t){let n=function(e,t,r,n){if(r<36||t+r>e.length||"manifest"!==n[e.readUInt32LE(t+20)])return;let a=e.readUInt16LE(t+24),i=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+a;for(let t=0;t<o;t+=1){let r=s+t*i;if(r+20>e.length)break;if("package"!==n[e.readUInt32LE(r+4)])continue;let a=e.readUInt32LE(r+8);if(0xffffffff!==a)return n[a];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return n[l];break}}(e,r,a,t);if(n)return n}r+=i}}(t);if(a)return a}return await aO(e)}async function aM(e,t){try{let r=await T("unzip",["-p",e,t],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function aE(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function aO(e){let t=await ak();if(!t)return;let r=await T(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let n=r.stdout.match(/package:\s+name='([^']+)'/);return n?.[1]}async function ak(){if(void 0!==e)return e??void 0;try{for(let t of nj()){let r=p.join(t,"build-tools");try{for(let t of(await A.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let n=p.join(r,t,"aapt");try{return await A.access(n),e=n,n}catch{}}}catch{}}}catch{}e=null}async function aL(e,t){let r="url"===e.kind&&av(e.url),n=await ah({source:e,isInstallablePath:(e,t)=>{var r;let n;return t.isFile()&&(r=e,".apk"===(n=p.extname(r).toLowerCase())||".aab"===n)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),a=t?.resolveIdentity===!1?{}:await aC(n.installablePath);return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:a.packageName,cleanup:n.cleanup}}async function aC(e){let t=p.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await aD(e)}}let aP={settings:{type:"intent",value:"android.settings.SETTINGS"}},aR="android.intent.category.LAUNCHER",aT="android.intent.category.LEANBACK_LAUNCHER",a$="android.intent.category.DEFAULT",aF="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.";async function aU(e,t){let r=t.trim();if("package"===ad(r))return{type:"package",value:r};let n=aP[r.toLowerCase()];if(n)return n;let a=(await T("adb",nW(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===a.length)return{type:"package",value:a[0]};if(a.length>1)throw new k("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:a,hint:"Run agent-device apps --platform android to see the exact installed package names before retrying open."});throw new k("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:aF})}async function aG(e,t="all"){let r=await aV(e);return("user-installed"===t?(await aj(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:aq(e)}))}async function aV(e){let t=new Set;for(let r of aB(e,{includeFallbackWhenUnknown:!0})){let n=await T("adb",nW(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===n.exitCode&&0!==n.stdout.trim().length)for(let e of n.stdout.split("\n")){let r=e.trim();if(!r)continue;let n=r.split(/\s+/)[0],a=n.includes("/")?n.split("/")[0]:n;a&&t.add(a)}}return t}function aB(e,t={}){return"tv"===e.target?[aT]:"mobile"===e.target?[aR]:t.includeFallbackWhenUnknown?[aR,aT]:[aR]}async function aj(e){return(await T("adb",nW(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function aq(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),n=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let a=r[e];if(!t.has(a)){n=a;break}}return n.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function aH(e){let t=await aW(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await aW(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function aW(e,t){for(let r of t){let t=function(e){for(let t of[/mCurrentFocus=Window\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mFocusedApp=AppWindowToken\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/,/ResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/]){let r=t.exec(e);if(r)return{package:r[1],activity:r[2]}}return null}((await T("adb",nW(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function az(e,t,r){var n,a;let i;e.booted||await as(e.id);let o=t.trim();if(nX(o)){if(r)throw new k("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await T("adb",nW(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await aU(e,t),l=aB(e)[0]??aR;if("intent"===s.type){if(r)throw new k("INVALID_ARGS","Activity override requires a package name, not an intent");await T("adb",nW(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;try{await T("adb",nW(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",a$,"-c",l,"-n",t]))}catch(t){throw await aX(e,s.value,t),t}return}let u=await T("adb",nW(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",a$,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===u.exitCode&&(n=u.stdout,a=u.stderr,i=`${n}
|
|
13
|
-
${a}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(i)))return;let d=await aZ(e,s.value);if(!d){if(!await aK(e,s.value))throw aJ(s.value);throw new k("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:u.stdout,stderr:u.stderr})}await T("adb",nW(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",a$,"-c",l,"-n",d]))}function aJ(e){return new k("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:aF})}async function aK(e,t){let r=await T("adb",nW(e,["shell","pm","path",t]),{allowFailure:!0}),n=`${r.stdout}
|
|
14
|
-
${r.stderr}`;return!!(0===r.exitCode&&/\bpackage:/i.test(n))||(aY(n),!1)}async function aX(e,t,r){if(aY(r instanceof k?`${String(r.details?.stdout??"")}
|
|
15
|
-
${String(r.details?.stderr??"")}`:"")||!await aK(e,t))throw aJ(t)}function aY(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function aZ(e,t){for(let r of Array.from(new Set(aB(e,{includeFallbackWhenUnknown:!0})))){let n=await T("adb",nW(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==n.exitCode)continue;let a=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}(n.stdout);if(a)return a}return null}async function aQ(e){e.booted||await as(e.id)}async function a0(e,t){if("settings"===t.trim().toLowerCase())return void await T("adb",nW(e,["shell","am","force-stop","com.android.settings"]));let r=await aU(e,t);if("intent"===r.type)throw new k("INVALID_ARGS","Close requires a package name, not an intent");await T("adb",nW(e,["shell","am","force-stop",r.value]))}async function a1(e,t){let r=await aU(e,t);if("intent"===r.type)throw new k("INVALID_ARGS","App uninstall requires a package name, not an intent");let n=await T("adb",nW(e,["uninstall",r.value]),{allowFailure:!0});if(0!==n.exitCode){let e=`${n.stdout}
|
|
16
|
-
${n.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new k("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}return{package:r.value}}let a2=null;async function a3(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(a2?.key===e)return a2.invocation;if(await F("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return a2={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 u.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 a2={key:e,invocation:r},r}async function a4(e){let t=await a3();await T(t.cmd,[...t.prefixArgs,...e])}async function a5(e,t){let r,n=await u.mkdtemp(p.join(d.tmpdir(),"agent-device-aab-")),a=p.join(n,"bundle.apks"),i=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await a4(["build-apks","--bundle",t,"--output",a,"--mode",i]),await a4(["install-apks","--apks",a,"--device-id",e.id])}finally{await u.rm(n,{recursive:!0,force:!0})}}async function a8(e,t){".aab"===p.extname(t).toLowerCase()?await a5(e,t):await T("adb",nW(e,["install","-r",t]))}async function a6(e){return new Set((await T("adb",nW(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function a9(e,t){let r=Array.from(await a6(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function a7(e,t){e.booted||await as(e.id),await a8(e,t)}async function ie(e,t,r){let n=r?void 0:await a6(e);return await a7(e,t),r??(n?await a9(e,n):void 0)}async function it(e,t){e.booted||await as(e.id);let r=await aL({kind:"path",path:t});try{let t=await ie(e,r.installablePath,r.packageName),n=t?aq(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:n,launchTarget:t}}finally{await r.cleanup()}}async function ir(e,t,r){e.booted||await as(e.id);let{package:n}=await a1(e,t),a=await aL({kind:"path",path:r},{resolveIdentity:!1});try{return await a7(e,a.installablePath),{package:n}}finally{await a.cleanup()}}function ia(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,n=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),a=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*n),i=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(a,Math.max(1,r-2*i))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),u=Math.round(e.referenceHeight/2),d=(r,n,a,i)=>({direction:t,x1:r,y1:n,x2:a,y2:i,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return d(l,u-s,l,u+s);case"down":return d(l,u+s,l,u-s);case"left":return d(l-s,u,l+s,u);case"right":return d(l+s,u,l-s,u)}}function ii(e,t){let r=t.toLowerCase(),n=/<node[^>]+>/g,a=n.exec(e);for(;a;){let t=il(a[0]),i=(iu(t,"text")??"").toLowerCase(),o=(iu(t,"content-desc")??"").toLowerCase();if(i.includes(r)||o.includes(r)){let e=id(iu(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}a=n.exec(e)}return null}function io(e,t,r){let n=function(e){let t=0,r=0,n=[...e.children];for(;n.length>0;){let e=n.pop();t+=1,r=Math.max(r,e.depth),n.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(e),a=[],i=[],o=!1,s=r.depth??1/0,l=r.scope?function(e,t){let r=t.toLowerCase(),n=[...e.children],a=0;for(;a<n.length;){let e=n[a++],t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",o=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||o.includes(r))return e;n.push(...e.children)}return null}(e,r.scope):null,u=l?[l]:e.children,d=new Map,c=e=>{let t=d.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||c(t))return d.set(e,!0),!0;return d.set(e,!1),!1},p=(e,n,l,u=!1,d=!1)=>{if(a.length>=t){o=!0;return}if(n>s)return;let f=!!r.raw||function(e,t,r,n,a){var i;let o,s=ip(e.type),l=!!(e.label&&e.label.trim().length>0),u=!!(e.identifier&&e.identifier.trim().length>0),d=l&&!im(e.label??""),c=u&&!im(e.identifier??""),p=(o=(i=s).split(".").pop()??i).includes("layout")||"viewgroup"===o||"view"===o,f="imageview"===s||"imagebutton"===s;if(t.interactiveOnly)return!!(e.hittable||Z(s)&&n)||!!(d||c)&&!f&&(!p||!!a)&&(r||n||a);return t.compact?d||c||!!e.hittable:!p&&!f||!!e.hittable||!!d||!!c&&!!n||n}(e,r,u,c(e),d),m=l;f&&(m=a.length,i.push(e),a.push({index:m,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:n,parentIndex:l,...e.hiddenContentAbove?{hiddenContentAbove:!0}:{},...e.hiddenContentBelow?{hiddenContentBelow:!0}:{}}));let h=u||!!e.hittable,w=d||function(e){if(!e)return!1;let t=ip(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(p(t,n+1,m,h,w),o)return};for(let e of u)if(p(e,0,void 0,!1,!1),o)break;return o?{nodes:a,sourceNodes:i,truncated:o,analysis:n}:{nodes:a,sourceNodes:i,analysis:n}}function is(e){let t=il(e),r=e=>{let r=iu(t,e);if(null!==r)return"true"===r};return{text:iu(t,"text"),desc:iu(t,"content-desc"),resourceId:iu(t,"resource-id"),className:iu(t,"class"),bounds:iu(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function il(e){let t=new Map,r=e.indexOf(" "),n=e.lastIndexOf(">");if(r<0||n<=r)return t;let a=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,i=r;for(;i<n;){for(;i<n;){let t=e[i];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;i+=1}if(i>=n)break;let r=e[i];if("/"===r||">"===r)break;a.lastIndex=i;let o=a.exec(e);if(!o)break;t.set(o[1],o[3]),i=a.lastIndex}return t}function iu(e,t){return e.get(t)??null}function id(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),n=Number(t[2]);return{x:r,y:n,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-n)}}function ic(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],n=/<node\b[^>]*>|<\/node>/g,a=n.exec(e);for(;a;){let t=a[0];if(t.startsWith("</node")){r.length>1&&r.pop(),a=n.exec(e);continue}let i=is(t),o=id(i.bounds),s=r[r.length-1],l={type:i.className,label:i.text||i.desc,value:i.text,identifier:i.resourceId,rect:o,enabled:i.enabled,hittable:i.clickable??i.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),a=n.exec(e)}return t}function ip(e){return e?e.toLowerCase():""}function im(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}function ih(e){if(0===e.length)return null;let t=[...e].sort((e,t)=>e-t);return t[Math.floor(t.length/2)]??null}function iw(e,t){let r=Math.max(24,Math.round(.2*Math.min(e.size,t.size))),n=Math.max(48,Math.round(.15*Math.min(e.crossSize,t.crossSize)));return Math.abs(e.size-t.size)<=r&&Math.abs(e.crossSize-t.crossSize)<=n}function ig(e,t){return{start:e.y-t.y,size:e.height,crossSize:e.width}}async function iy(e,t={}){let r=await iI(e);if(!t.interactiveOnly){let n=function(e,t){let{sourceNodes:r,...n}=io(ic(e),800,t);return n}(r,t);return await iv(e,n.nodes),n}let n=ic(r),a=io(n,800,{...t,interactiveOnly:!1});await iv(e,a.nodes),function(e){if(0===e.length||e.some(e=>e.hiddenContentAbove||e.hiddenContentBelow))return;let t=new Map(el(eO(e)).nodes.filter(e=>e.hiddenContentAbove||e.hiddenContentBelow).map(e=>[e.index,e]));for(let r of e){let e=t.get(r.index);e&&(e.hiddenContentAbove&&(r.hiddenContentAbove=!0),e.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}(a.nodes),function(e){for(let[t,r]of e.sourceNodes.entries()){let n=e.nodes[t];n&&(n.hiddenContentAbove&&(r.hiddenContentAbove=!0),n.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}(a);let{sourceNodes:i,...o}=io(n,800,t);return o}async function iv(e,t){if(!t.some(e=>Z(e.type)))return;let r=await iN(e);r&&function(e,t){let r=function(e){let t={className:"root",rect:{x:0,y:0,width:0,height:0},children:[]},r=[{indent:-1,node:t}],n=/^(\s*)([\w.$]+)\{[^}]* (-?\d+),(-?\d+)-(-?\d+),(-?\d+) #/;for(let t of e.split("\n")){let e=n.exec(t);if(!e)continue;let a=e[1].length,i=Number(e[3]),o=Number(e[4]),s=Number(e[5]),l=Number(e[6]),u={className:e[2],rect:{x:i,y:o,width:Math.max(0,s-i),height:Math.max(0,l-o)},children:[]};for(;r.length>1&&a<=r[r.length-1].indent;)r.pop();r[r.length-1].node.children.push(u),r.push({indent:a,node:u})}return t.children.length>0?t:null}(t);if(!r)return;let n=function(e){let t=[],r=[e];for(;r.length>0;){let e=r.pop();if(Z(e.className)){let r=function(e){let t=e.children[0];if(!t)return null;let r=Math.max(t.rect.height,...t.children.map(e=>e.rect.y+e.rect.height)),n=t.children.filter(e=>e.rect.height>0).map(t=>ig(t.rect,e.rect)).sort((e,t)=>e.start-t.start);return 0===n.length?null:{rect:e.rect,contentExtent:r,contentBlocks:n}}(e);r&&t.push(r)}r.push(...e.children)}return t}(r);if(0!==n.length)for(let t of e){if(!t.rect||!Z(t.type))continue;let r=function(e,t){let r=null,n=1/0;for(let a of t){let t=Math.abs(a.rect.width-e.width)+Math.abs(a.rect.height-e.height);if(t>32)continue;let i=4*t+(Math.abs(a.rect.x-e.x)+Math.abs(a.rect.y-e.y));i<n&&(r=a,n=i)}return r}(t.rect,n);if(!r)continue;let a=function(e,t){let r=function(e,t){let r=t,n=new Set;for(;!n.has(r.index);){var a,i;n.add(r.index);let o=e.filter(e=>e.parentIndex===r.index&&e.rect);if(1!==o.length)return r;let s=o[0];if(a=s.rect,i=t.rect,a.x!==i.x||a.y!==i.y||a.width!==i.width||a.height!==i.height)return r;r=s}return t}(e,t);return e.filter(e=>e.parentIndex===r.index&&e.rect).map(e=>e.rect).filter(e=>e.height>0).sort((e,t)=>e.y-t.y).map(e=>ig(e,t.rect))}(e,t),i=function(e){let{viewportRect:t,visibleBlocks:r,nativeScrollView:n}=e;if(0===r.length||0===n.contentBlocks.length)return null;let a=function(e){if(0===e.contentBlocks.length)return null;let t=e.contentBlocks[0],r=e.contentBlocks[e.contentBlocks.length-1];if(!t||!r)return null;let n=ih(e.contentBlocks.map(e=>e.size))??e.rect.height,a=Math.max(48,Math.round(.5*n)),i=Math.max(24,Math.round(.25*n)),o=t.start>=a,s=e.contentExtent-(r.start+r.size)>=i;return o||s?{above:o,below:s}:null}(n),i=function(e,t){let r=new Map;for(let n of e)for(let e of t){if(!iw(n,e))continue;let t=n.start-e.start,a=8*Math.round(t/8),i=r.get(a)??[];i.push(t),r.set(a,i)}let n=null;for(let e of r.values())(!n||e.length>n.length)&&(n=e);if(!n||n.length<2)return null;let a=[...n].sort((e,t)=>e-t);return a[Math.floor(a.length/2)]??null}(n.contentBlocks,r)??function(e){let{nativeBlocks:t,visibleBlocks:r,viewportExtent:n,contentExtent:a}=e,i=[],o=[];for(let e of t)for(let t of r){if(!iw(e,t))continue;let r=e.start-t.start;16>=Math.abs(r)&&i.push(r),16>=Math.abs(r+n-a)&&o.push(r)}return o.length>0?ih(o):i.length>0?ih(i):null}({nativeBlocks:n.contentBlocks,visibleBlocks:r,viewportExtent:t.height,contentExtent:n.contentExtent});if(null===i)return a;let o=t.height;return{above:(a?.above??!1)||i>16,below:(a?.below??!1)||i+o<n.contentExtent-16}}({viewportRect:t.rect,visibleBlocks:a,nativeScrollView:r});i&&(i.above&&(t.hiddenContentAbove=!0),i.below&&(t.hiddenContentBelow=!0))}}(t,r)}async function iI(e){return H(()=>ib(e),{shouldRetry:iS})}async function ib(e){var t,r,n;let a,i,o=await T("adb",nW(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0}),s=iA(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",u=await T("adb",nW(e,["shell","uiautomator","dump",l]),{allowFailure:!0}),d=(t=l,r=u.stdout,n=u.stderr,a=`${r}
|
|
17
|
-
${n}`,i=/dumped to:\s*(\S+)/i.exec(a),i?.[1]??t),c=await T("adb",nW(e,["shell","cat",d])),p=iA(c.stdout,c.stderr);if(!p)throw new k("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return p}function iA(e,t){let r=`${e}
|
|
18
|
-
${t}`,n=r.indexOf("<?xml"),a=n>=0?n:r.indexOf("<hierarchy");if(a<0)return null;let i=r.lastIndexOf("</hierarchy>");if(i<0||i<a)return null;let o=r.slice(a,i+12).trim();return o.length>0?o:null}function iS(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 iN(e){try{let t=await T("adb",nW(e,["shell","dumpsys","activity","top"]),{allowFailure:!0,timeoutMs:8e3}),r=`${t.stdout}
|
|
19
|
-
${t.stderr}`.trim();return r.length>0?r:null}catch{return null}}async function i_(e,t,r){await T("adb",nW(e,["shell","input","tap",String(t),String(r)]))}async function ix(e,t,r,n,a,i=250){await T("adb",nW(e,["shell","input","swipe",String(t),String(r),String(n),String(a),String(i)]))}async function iD(e){await T("adb",nW(e,["shell","input","keyevent","4"]))}async function iM(e){await T("adb",nW(e,["shell","input","keyevent","3"]))}async function iE(e,t){let r=function(e){switch(e){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new k("INVALID_ARGS",`Unsupported Android rotation: ${e}`)}}(t);await T("adb",nW(e,["shell","settings","put","system","accelerometer_rotation","0"])),await T("adb",nW(e,["shell","settings","put","system","user_rotation",r]))}async function iO(e){await T("adb",nW(e,["shell","input","keyevent","187"]))}async function ik(e,t,r,n=800){await T("adb",nW(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(n)]))}async function iL(e,t,r=0){r>0&&Array.from(t).length>1?await iV(e,t,1,r):await iC(e,t)}async function iC(e,t){let r=iB(t);if(!r||"ok"!==await ij(e,t))try{let r=t.replace(/ /g,"%s");await T("adb",nW(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 iP(e,t,r){await i_(e,t,r)}async function iR(e,t,r,n,a=0){let i=Array.from(n).length,o=iB(n),s=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];!o&&a<=0&&s.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),(!o||a>0)&&s.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96});let l=null;for(let o of s){var u,d;await iP(e,t,r);let s=(u=i+o.clearPadding,d=o.minClear,Math.max(d,Math.min(o.maxClear,u)));if(await iq(e,s),"input_text"===o.strategy)await iL(e,n,a);else if("clipboard_paste"===o.strategy){if("ok"!==await ij(e,n))continue}else await iV(e,n,1,a>0?a:15);let c=await iT(e,t,r,n);if(l=c.actual,c.ok)return}throw new k("COMMAND_FAILED","Android fill verification failed",{expected:n,actual:l??null})}async function iT(e,t,r,n){let a=null;for(let i of[0,150,350])if(i>0&&await nK(i),function(e,t){if(e===t)return!0;let r=i$(e),n=i$(t);return!!r&&!!n&&(!!(r===n||r.includes(n))||n.includes(r)&&r.length>=Math.max(4,Math.floor(.8*n.length)))}(a=await iH(e,t,r),n))return{ok:!0,actual:a};return{ok:!1,actual:a}}function i$(e){return(e??"").replace(/\s+/g," ").trim()}async function iF(e,t,r){let n=await iG(e),a=ia({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:n.width,referenceHeight:n.height});return await T("adb",nW(e,["shell","input","swipe",String(a.x1),String(a.y1),String(a.x2),String(a.y2),"300"])),a}async function iU(e,t,r){let n=r?.maxScrolls??8,a="";try{a=await iI(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new k("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(ii(a,t))return{attempts:0};for(let r=1;r<=n;r+=1){await iF(e,"down",{amount:.5});let n="";try{n=await iI(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new k("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(ii(n,t))return{attempts:r};if(n===a)throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:r,stalled:!0});a=n}throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:n})}async function iG(e){let t=(await T("adb",nW(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 iV(e,t,r,n){let a=Math.max(1,Math.floor(r)),i=Array.from(t);for(let t=0;t<i.length;t+=a){let r=i.slice(t,t+a).join("");await iC(e,r),n>0&&t+a<i.length&&await nK(n)}}function iB(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 ij(e,t){let r=await T("adb",nW(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":nJ(r.stdout,r.stderr)?"unsupported":0===(await T("adb",nW(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await T("adb",nW(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function iq(e,t){let r=Math.max(0,t);await T("adb",nW(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let n=Math.min(24,r-t);await T("adb",nW(e,["shell","input","keyevent",...Array(n).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function iH(e,t,r){let n,a=await iI(e),i=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(n=i.exec(a));){let e=is(n[0]),a=id(e.bounds);if(!a)continue;let i=e.className??"",u=(e.text??"").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),d=e.focused??!1;if(!u)continue;let c=Math.max(1,a.width*a.height),p=t>=a.x&&t<=a.x+a.width&&r>=a.y&&r<=a.y+a.height;if(d&&iW(i)){(!o||c<=o.area)&&(o={text:u,area:c});continue}if(p&&iW(i)){(!s||c<=s.area)&&(s={text:u,area:c});continue}p&&(!l||c<=l.area)&&(l={text:u,area:c})}return o?.text??s?.text??l?.text??null}function iW(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iz(e){let t=await T("adb",nW(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],n=r[2]?.toLowerCase();e&&("true"===n||"false"===n)&&t.set(e,"true"===n)}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 n=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),a=n.length>0?n[n.length-1]?.[1]:void 0,i=a?`0x${a.toLowerCase()}`:void 0;return{visible:r,inputType:i,type:i?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let n=4080&t;return 32===n||208===n?"email":128===n||224===n||144===n?"password":"text"}(i):void 0}}(t.stdout)}async function iJ(e){let t=await iz(e),r=t,n=0;for(;r.visible&&n<2;)await T("adb",nW(e,["shell","input","keyevent","111"])),n+=1,await nK(120),r=await iz(e);if(t.visible&&r.visible)throw new k("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:n,inputType:r.inputType,type:r.type});return{attempts:n,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 iY(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 iX(e,t){await iY(e,["shell","cmd","clipboard","set","text",t],"write")}async function iY(e,t,r){let n=await T("adb",nW(e,t),{allowFailure:!0});if(nJ(n.stdout,n.stderr))throw new k("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==n.exitCode)throw new k("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});return n.stdout}let iZ=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iQ(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 i0(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: ${iZ.join("|")}`)}function i1(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 i2(e,t,r,n,a){switch(t.toLowerCase()){case"wifi":{let t=i4(r);await T("adb",nW(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=i4(r);await T("adb",nW(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await T("adb",nW(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=i4(r);await T("adb",nW(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await i5(e,r);await T("adb",nW(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 i3(e,t);return}case"permission":{if(!n)throw new k("INVALID_ARGS","permission setting requires an active app in session");let t=iQ(r),i=function(e,t){let r=i0(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.`)}(a?.permissionTarget,a?.permissionMode);if("notifications"===i.kind)return void await i6(e,n,t,i);let o="grant"===t?"grant":"revoke";if("photos"===i.type)return void await i8(e,n,o);await T("adb",nW(e,["shell","pm",o,n,i.value]));return}default:throw new k("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function i3(e,t){var r;let n,a,i=(r=e,a=[["shell","cmd","fingerprint","touch",n="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",n]],"emulator"===r.kind&&a.push(["emu","finger","touch",n]),a),o=[];for(let t of i){let r=await T("adb",nW(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 n;return t=e.stdout,r=e.stderr,(n=`${t}
|
|
20
|
-
${r}`.toLowerCase()).includes("unknown command")||n.includes("can't find service: fingerprint")||n.includes("service fingerprint was not found")||n.includes("fingerprint cmd unavailable")||n.includes("emu command is not supported")||n.includes("emulator console is not running")||n.includes("fingerprint")&&n.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 i4(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 i5(e,t){let r=i1(t);if("toggle"!==r)return r;let n=await T("adb",nW(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==n.exitCode)throw new k("COMMAND_FAILED","Failed to read current Android appearance",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});let a=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
|
|
21
|
-
${t}`);if(!r)return null;let n=r[1].toLowerCase();return"yes"===n?"dark":"no"===n?"light":"auto"===n?"auto":null}(n.stdout,n.stderr);if(!a)throw new k("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:n.stdout,stderr:n.stderr});return"auto"===a?"dark":"dark"===a?"light":"dark"}async function i8(e,t,r){let n=await i9(e),a=[];for(let i of null!==n&&n>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let n=await T("adb",nW(e,["shell","pm",r,t,i]),{allowFailure:!0});if(0===n.exitCode)return;a.push({permission:i,stderr:n.stderr,exitCode:n.exitCode})}throw new k("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:n,attempts:a})}async function i6(e,t,r,n){"grant"===r?await T("adb",nW(e,["shell","pm","grant",t,n.permission]),{allowFailure:!0}):(await T("adb",nW(e,["shell","pm","revoke",t,n.permission]),{allowFailure:!0}),"reset"===r&&(await T("adb",nW(e,["shell","pm","clear-permission-flags",t,n.permission,"user-set"]),{allowFailure:!0}),await T("adb",nW(e,["shell","pm","clear-permission-flags",t,n.permission,"user-fixed"]),{allowFailure:!0}))),await T("adb",nW(e,["shell","appops","set",t,n.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function i9(e){let t=await T("adb",nW(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 i7(e,t,r){let n="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,a=["shell","am","broadcast","-a",n,"-p",t],i="string"==typeof r.receiver?r.receiver.trim():"";i&&a.push("-n",i);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.`)}(a,e,t),s+=1);return await T("adb",nW(e,a)),{action:n,extrasCount:s}}let oe=Buffer.from([137,80,78,71,13,10,26,10]);async function ot(e,t){await or(e);try{await nK(1e3),await oa(e,t)}finally{await on(e).catch(()=>{})}}async function or(e){let t=t=>T("adb",nW(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 on(e){await T("adb",nW(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function oa(e,t){let r=await T("adb",nW(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new k("COMMAND_FAILED","Failed to capture screenshot");let n=r.stdoutBuffer.indexOf(oe);if(n<0)throw new k("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let a=function(e,t){let r=t+oe.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),n=r+4,a=e.toString("ascii",n,n+4),i=r+12+t;if(i>e.length)break;if("IEND"===a)return i;r=i}return null}(r.stdoutBuffer,n);if(!a)throw new k("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await u.writeFile(t,r.stdoutBuffer.subarray(n,a))}let oi=eX(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,Y.ios_boot.totalMs,5e3),oo=eX(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,Y.ios_boot.operationMs,1e3),os=eX(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),ol=eX(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),ou=eX(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),od=eX(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),oc=eX(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3),op=z(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK);async function of(e,t){let r=["devicectl",...e],n=await T("xcrun",r,{allowFailure:!0,timeoutMs:ol});if(0===n.exitCode)return;let a=String(n.stdout??""),i=String(n.stderr??"");throw new k("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:n.exitCode,stdout:a,stderr:i,deviceId:t.deviceId,hint:og(a,i)??ow})}async function om(e,t){let r=p.join(d.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),n=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],a=await T("xcrun",n,{allowFailure:!0,timeoutMs:ol});try{var i,o;if(0!==a.exitCode){let t=String(a.stdout??""),r=String(a.stderr??"");throw new k("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:og(t,r)??ow})}let s=await u.readFile(r,"utf8");return i=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let n="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t,a="string"==typeof e.url&&e.url.trim().length>0?e.url.trim():void 0;r.push({bundleId:t,name:n,url:a})}return r}(JSON.parse(s)),o=t,"user-installed"===o?i.filter(e=>!e.bundleId.startsWith("com.apple.")):i}catch(t){if(t instanceof k)throw t;throw new k("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await u.unlink(r).catch(()=>{})}}async function oh(e){let t=p.join(d.tmpdir(),`agent-device-ios-processes-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=["devicectl","device","info","processes","--device",e.id,"--json-output",t],n=await T("xcrun",r,{allowFailure:!0,timeoutMs:ol});try{if(0!==n.exitCode){let t=String(n.stdout??""),a=String(n.stderr??"");throw new k("COMMAND_FAILED","Failed to list iOS processes",{cmd:"xcrun",args:r,exitCode:n.exitCode,stdout:t,stderr:a,deviceId:e.id,hint:og(t,a)??ow})}let a=await u.readFile(t,"utf8");return function(e){let t=e?.result?.runningProcesses;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.executable?e.executable.trim():"",n="number"==typeof e.processIdentifier&&Number.isFinite(e.processIdentifier)?e.processIdentifier:NaN;t&&Number.isFinite(n)&&r.push({executable:t,pid:n})}return r}(JSON.parse(a))}catch(t){if(t instanceof k)throw t;throw new k("COMMAND_FAILED","Failed to parse iOS process list",{deviceId:e.id,cause:String(t)})}finally{await u.unlink(t).catch(()=>{})}}let ow="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function og(e,t){let r=`${e}
|
|
22
|
-
${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 oy(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 ov(e,t){let r=await T("xcrun",e6(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let n=r.stdout.trim();if(!n)return{installed:!1};let a=await T("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${n}/Info.plist`],{allowFailure:!0});if(0!==a.exitCode||!a.stdout.trim())return{installed:!0};let i=a.stdout.trim(),o=`${n}/${i}`,s=await T("otool",["-l",o],{allowFailure:!0});if(0!==s.exitCode)return{installed:!0};let l=s.stdout.toLowerCase();return{installed:!0,simulatorCompatible:l.includes("iossimulator")||l.includes("platform 7")}}function oI(e,t){if("simulator"!==e.kind)throw new k("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function ob(){await T("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:ou})}async function oA(e){let t,r;if("simulator"!==e.kind||"Booted"===await oN(e))return;let n=ec.fromTimeoutMs(oi);try{await eb(async({deadline:n})=>{if(n?.isExpired())throw new k("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:oi});let a=Math.max(1e3,n?.remainingMs()??oi),i=await T("xcrun",e6(e,["boot",e.id]),{allowFailure:!0,timeoutMs:a});t={stdout:String(i.stdout??""),stderr:String(i.stderr??""),exitCode:i.exitCode};let o=`${t.stdout}
|
|
23
|
-
${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 T("xcrun",e6(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:a});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new k("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let u=await oN(e);if("Booted"!==u)throw new k("COMMAND_FAILED","Simulator is still booting",{state:u})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let n=eY({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==n&&"CI_RESOURCE_STARVATION_SUSPECTED"!==n}},{deadline:n,phase:"boot",classifyReason:e=>eY({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(i){let a=eY({error:i,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:oi,elapsedMs:n.elapsedMs(),reason:a,hint:eZ(a),boot:t,bootstatus:r})}await ob()}async function oS(e){let t=e6(e,["shutdown",e.id]),r=await T("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function oN(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?e8(["list","devices","-j"]):e6(e,["list","devices","-j"]),n=await T("xcrun",r,{allowFailure:!0,timeoutMs:oo});if(0!==n.exitCode)return null;try{let e=JSON.parse(String(n.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 o_(e,t){try{let r=await T("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{var r,n;let a;return r=await u.readFile(e,"utf8"),n=t,tM(tD(r),(e,t)=>{void 0===a&&e===n&&"string"===t.name&&(a=t.text??void 0)}),a}catch{return}}async function ox(e,t){if("url"===e.kind&&!av(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 ah({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||av(e.url),signal:t?.signal}),n=await oM(r.installablePath,t),a=await oD(n.installPath);return{archivePath:r.archivePath??(r.installablePath.toLowerCase().endsWith(".ipa")?r.installablePath:void 0),installablePath:n.installPath,bundleId:a.bundleId,appName:a.appName,cleanup:async()=>{await n.cleanup(),await r.cleanup()}}}async function oD(e){let t=p.join(e,"Info.plist"),[r,n,a]=await Promise.all([o_(t,"CFBundleIdentifier"),o_(t,"CFBundleDisplayName"),o_(t,"CFBundleName")]);return{bundleId:r,appName:n??a}}async function oM(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await u.mkdtemp(p.join(d.tmpdir(),"agent-device-ios-ipa-")),n=async()=>{await u.rm(r,{recursive:!0,force:!0})};try{await T("ditto",["-x","-k",e,r]);let a=p.join(r,"Payload"),i=(await u.readdir(a,{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:p.join(a,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===i.length)return{installPath:i[0].installPath,cleanup:n};if(0===i.length)throw new k("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await oE(i);let o=t?.appIdentifierHint?.trim();if(o){let e=function(e,t){let r=t.toLowerCase(),n=e.filter(e=>e.bundleName.toLowerCase()===r);if(1===n.length)return n[0];if(n.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]}}(i,o);if(e)return{installPath:e.installPath,cleanup:n};throw new k("INVALID_ARGS",`Invalid IPA: found ${i.length} .app bundles under Payload and none matched "${o}". Available bundles: ${i.map(oO).join(", ")}`)}throw new k("INVALID_ARGS",`Invalid IPA: found ${i.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${i.map(oO).join(", ")}`)}catch(e){throw await n(),e}}async function oE(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await oD(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function oO(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function ok(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let oL="agent-device-macos-helper",oC="AGENT_DEVICE_MACOS_HELPER_BIN",oP=p.join(d.homedir(),".agent-device","macos-helper","current"),oR=p.join(oP,"manifest.json"),oT=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function o$(e){let t=e.trim();if(!oT.test(t))throw new k("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function oF(){return function(e){let t=p.dirname(e);for(;;){let e=p.join(t,"macos-helper");if(l(p.join(e,"Package.swift")))return e;let r=p.dirname(t);if(r===t)break;t=r}throw new k("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(w(import.meta.url))}async function oU(e){let t=await u.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let r=p.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await oU(r):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[r]:[]}))).flat().sort()}async function oG(e){let t=await oU(e),r=o("sha256");for(let n of t)r.update(p.relative(e,n)),r.update("\0"),r.update(await u.readFile(n)),r.update("\0");let n=await T("swift",["--version"],{allowFailure:!0,cwd:e,timeoutMs:1e4});return r.update("swift-version"),r.update("\0"),r.update(n.stdout||n.stderr||`exit:${n.exitCode}`),r.update("\0"),r.digest("hex")}async function oV(){try{let e=JSON.parse(await u.readFile(oR,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function oB(){let e=process.env[oC]?.trim();if(e)return e;let t=oF(),r=await oG(t),n=p.join(oP,oL);try{if(await oV()===r)return await u.access(n),n}catch{}let a=p.join(oF(),".build","release",oL);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await T("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await u.mkdir(oP,{recursive:!0});let i=`${n}.tmp`;return await u.copyFile(a,i),await u.rename(i,n),await u.chmod(n,493),await u.writeFile(oR,`${JSON.stringify({fingerprint:r},null,2)}
|
|
24
|
-
`,"utf8"),n}async function oj(e){let t=process.env[oC]?.trim();if("darwin"!==process.platform&&!t)throw new k("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let r=await oB(),n=await T(r,e,{allowFailure:!0,timeoutMs:3e4}),a=n.stdout.trim(),i=null;if(a)try{i=JSON.parse(a)}catch{i=null}if(0===n.exitCode&&i?.ok)return i.data;throw new k("COMMAND_FAILED",i&&!i.ok?i.error?.message??`macOS helper exited with code ${n.exitCode}`:a||n.stderr.trim()||`macOS helper exited with code ${n.exitCode}`,{helperPath:r,args:e,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,...i&&!i.ok?i.error?.details:{}})}async function oq(){return await oj(["app","frontmost"])}async function oH(e){return await oj(["app","quit","--bundle-id",o$(e)])}async function oW(e,t){return await oj(["permission",e,t])}async function oz(e,t={}){let r=["alert",e];return t.bundleId&&r.push("--bundle-id",o$(t.bundleId)),t.surface&&r.push("--surface",t.surface),await oj(r)}async function oJ(e,t={}){let r=["snapshot","--surface",e];return t.bundleId&&r.push("--bundle-id",o$(t.bundleId)),await oj(r)}async function oK(e,t,r={}){let n=["read","--x",String(e),"--y",String(t)];return r.bundleId&&n.push("--bundle-id",o$(r.bundleId)),r.surface&&n.push("--surface",r.surface),await oj(n)}async function oX(e,t,r={}){let n=["press","--x",String(e),"--y",String(t)];return r.bundleId&&n.push("--bundle-id",o$(r.bundleId)),r.surface&&n.push("--surface",r.surface),await oj(n)}async function oY(e,t={}){let r=["screenshot","--out",e];return t.surface&&r.push("--surface",t.surface),t.fullscreen&&r.push("--fullscreen"),await oj(r)}let oZ={settings:"com.apple.systempreferences"},oQ=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function o0(e,t){let r=["-b",e];return t&&r.push(t),r}async function o1(e){for(let t of[p.join(e,"Contents","Info.plist"),p.join(e,"Info.plist")]){let[e,r,n]=await Promise.all([o_(t,"CFBundleIdentifier"),o_(t,"CFBundleDisplayName"),o_(t,"CFBundleName")]);if(e||r||n)return{bundleId:e,appName:r??n}}return{}}async function o2(e){let t=e.trim(),r=oZ[t.toLowerCase()];if(r)return r;if(oQ.test(t))return t;let n=(await o7("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===n.length)return n[0].bundleId;if(n.length>1)throw new k("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:n});throw new k("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function o3(e,t,r){let n=r?.url?.trim();if(n){if(!nX(n))throw new k("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await o2(t);await T("open",o0(e,n));return}let a=t.trim();if(nX(a))return void await T("open",[a]);let i=r?.appBundleId??await o2(a);await T("open",o0(i))}async function o4(e,t){let r=await o2(t),n=await oH(r);if(n.running&&!n.terminated&&!n.forceTerminated)throw new k("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:r,running:n.running,terminated:n.terminated,forceTerminated:n.forceTerminated})}async function o5(){let e=await T("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 o8(e){let t=await T("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 o6(){let e=await T("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new 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 o9(e){let t=i1(e),r="toggle"===t?!await o6():"dark"===t,n=`tell application "System Events" to tell appearance preferences to set dark mode to ${r?"true":"false"}`,a=await T("osascript",["-e",n],{allowFailure:!0});if(0!==a.exitCode)throw new k("COMMAND_FAILED","Failed to set macOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}async function o7(e="all"){let t=["/Applications","/System/Applications",p.join(d.homedir(),"Applications")],r=new Set;for(let e of t){let t=await u.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let n=await T("find",[e,"-maxdepth","4","-type","d","-name","*.app"],{allowFailure:!0});if(0===n.exitCode)for(let e of n.stdout.split("\n")){let t=e.trim();t&&r.add(t)}}return ok((await Promise.all(Array.from(r).map(async e=>{let t=await o1(e).catch(()=>({})),r=t.bundleId;return r?{bundleId:r,name:t.appName??p.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let se=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],st={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"},sr={1:"searching",2:"failed",3:"active"},sn={0:"notSupported",1:"searching",2:"failed",3:"active"};function sa(e,t,r){return T("xcrun",e6(e,t),r)}async function si(e,t){var r,n;let a;await ss(e),t&&await sl(e,(a=[],(r=t).dataNetwork&&a.push("--dataNetwork",r.dataNetwork),r.wifiMode&&a.push("--wifiMode",r.wifiMode),void 0!==r.wifiBars&&("wifi"===r.dataNetwork||r.wifiMode)&&a.push("--wifiBars",r.wifiBars),r.cellularMode&&a.push("--cellularMode",r.cellularMode),void 0!==r.cellularBars&&(r.cellularMode||(n=r.dataNetwork)&&"hide"!==n&&"wifi"!==n||void 0!==r.operatorName)&&a.push("--cellularBars",r.cellularBars),void 0!==r.operatorName&&a.push("--operatorName",r.operatorName),a))}async function so(e){let t=await sa(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]),n=st[r];if(!n)throw new k("COMMAND_FAILED",`Unsupported simulator data network type: ${r}`);t.dataNetwork=n;continue}let n=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(r);if(n){let e=sr[Number(n[1])];e&&(t.wifiMode=e),t.wifiBars=n[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(r);if(a){let e=Number(a[1]),r=sn[e];if(!r)throw new k("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=r,t.cellularBars=a[2];continue}let i=/^Operator Name:\s*(.*)$/.exec(r);if(i){t.operatorName=i[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function ss(e){await sa(e,["status_bar",e.id,"clear"])}async function sl(e,t){0!==t.length&&await sa(e,["status_bar",e.id,"override",...t])}function su(e,t,r){D({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 sd(e,t,r){return T("xcrun",e6(e,t),r)}let sc={ensureBooted:oA,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await so(e),r=!0}catch(t){su(e,"snapshot_failed",t)}try{await ss(e),await sl(e,se)}catch(t){su(e,"prepare_failed",t)}return async()=>{await si(e,r?t:null)}},captureWithRetry:sm,runnerFallbackEnabled:op,captureWithRunner:sh,shouldFallbackToRunner:sA};async function sp(e,t,r,n){if("macos"===e.platform)return void await sh(e,t,r,n);if("simulator"===e.kind)return void await sf(e,t,r,n);try{await of(["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:"",n="string"==typeof t.stderr?t.stderr:"",a=`${e.message}
|
|
25
|
-
${r}
|
|
26
|
-
${n}`.toLowerCase();return a.includes("unknown option '--device'")||a.includes("unknown subcommand")&&a.includes("screenshot")||a.includes("unrecognized subcommand")&&a.includes("screenshot")}(t))throw t;sv(e,"devicectl_screenshot",t)}await sh(e,t,r,n)}async function sf(e,t,r,n,a=sc){if("simulator"!==e.kind)throw new k("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let i="object"==typeof n&&null!==n?n:a;await i.ensureBooted(e);let o=async()=>{};try{o=await i.prepareStatusBarForScreenshot(e)}catch(t){sI(e,"prepare_failed",t)}try{try{await i.captureWithRetry(e,t);return}catch(t){if(!i.shouldFallbackToRunner(t))throw t;if(!i.runnerFallbackEnabled){var s,l,u;let r,n;throw s=e,l=t,r=sb(l),D({level:"warn",phase:"ios_screenshot_fallback_skipped",data:{platform:s.platform,deviceKind:s.kind,deviceId:s.id,from:"simctl_screenshot",to:"runner",reason:"Simulator runner fallback is disabled to avoid XCTest automation instability during screenshot capture.",...r}}),n=(u=t)instanceof k?u:new k("COMMAND_FAILED","Failed to capture iOS screenshot: simulator screenshot retries exhausted",void 0,u),new k(n.code,n.message,{...n.details??{},hint:"Restart the simulator and retry. If simctl screenshots keep timing out and you accept the stability tradeoff, set AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK=1 to allow XCTest runner fallback."},n)}sv(e,"simctl_screenshot",t)}await i.captureWithRunner(e,t,r,"boolean"==typeof n?n:void 0)}finally{await o().catch(t=>sI(e,"restore_failed",t))}}async function sm(e,t){let r=ec.fromTimeoutMs(od);await eb(async({deadline:r})=>{await sd(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,r?.remainingMs()??od)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>sA(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function sh(e,t,r,n){let a=(await ru(e,{command:"screenshot",appBundleId:r,fullscreen:n})).message;if(!a)throw new k("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await u.copyFile(a,t):"simulator"===e.kind?await sg(e,a,t):await sw(e,a,t)}async function sw(e,t,r){let n=ec.fromTimeoutMs(oc),a={exitCode:1,stdout:"",stderr:""};for(let i of tG)if(0===(a=await T("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",i],{allowFailure:!0,timeoutMs:sy(n,oc,"runner screenshot copy")})).exitCode)return;let i=a.stderr.trim()||a.stdout.trim()||`devicectl exited with code ${a.exitCode}`;throw new k("COMMAND_FAILED",`Failed to capture iOS screenshot: ${i}`)}async function sg(e,t,r){let n=ec.fromTimeoutMs(oc),a="Unable to locate runner container for simulator screenshot";for(let i of tG){let o=await sd(e,["get_app_container",e.id,i,"data"],{allowFailure:!0,timeoutMs:sy(n,oc,"runner screenshot container lookup")});if(0!==o.exitCode){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=p.resolve(e),n=t.trim();if(!n)return[];let a=[],i=new Set,o=e=>{let t=p.normalize(e);i.has(t)||(i.add(t),a.push(t))},s=n.replace(/^\/+/,""),l=s.replace(/\\/g,"/");if(s&&o(p.join(r,s)),p.isAbsolute(n)&&o(p.normalize(n)),l.startsWith("tmp/"))o(p.join(r,l));else{let e=l.lastIndexOf("/tmp/");if(e>=0){let t=l.slice(e+1);o(p.join(r,t))}}let u=p.basename(n);return u&&o(p.join(r,"tmp",u)),a}(s,t))try{await u.copyFile(e,r);return}catch(e){a=e instanceof Error?e.message:String(e)}}throw new k("COMMAND_FAILED",`Failed to capture iOS screenshot: ${a}`)}function sy(e,t,r){let n=e.remainingMs();if(n>0)return n;throw new k("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function sv(e,t,r){let n=sb(r);D({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...n}})}function sI(e,t,r){D({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...sb(r)}})}function sb(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 sA(e){if(!(e instanceof k)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",n="string"==typeof t.stderr?t.stderr:"",a=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",i=`${e.message}
|
|
27
|
-
${r}
|
|
28
|
-
${n}
|
|
29
|
-
${a}`.toLowerCase();return i.includes("timeout waiting for screen surfaces")||i.includes("nsposixerrordomain")&&i.includes("code=60")&&i.includes("screenshot")||i.includes("timed out")&&i.includes("screenshot")}let sS={settings:"com.apple.Preferences"},sN=null;function s_(e,t,r){return T("xcrun",e6(e,t),r)}function sx(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function sD(e,t){if("macos"===e.platform)return await o2(t);let r=t.trim();if(r.includes("."))return r;let n=sS[r.toLowerCase()];if(n)return n;let a=("simulator"===e.kind?await sG(e):await om(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new k("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:a});throw new k("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function sM(e,t,r){if("macos"===e.platform)return void await o3(e,t,r);let n=r?.url?.trim();if(n){if(!nX(n))throw new k("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await oA(e),await s_(e,["openurl",e.id,n]);return}let a=nY(r?.appBundleId??await sD(e,t),n);if(!a)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 sK(e,a,{payloadUrl:n});return}let a=t.trim();if(nX(a)){if("simulator"===e.kind){await oA(e),await s_(e,["openurl",e.id,a]);return}let t=nY(r?.appBundleId,a);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 sK(e,t,{payloadUrl:a});return}let i=r?.appBundleId??await sD(e,t);"simulator"===e.kind?await sJ(e,i):await sK(e,i)}async function sE(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await oN(e)&&await oA(e)}async function sO(e,t){if("macos"===e.platform)return void await o4(e,t);let r=await sD(e,t);if("simulator"===e.kind){await oA(e);let t=e6(e,["terminate",e.id,r]),n=await T("xcrun",t,{allowFailure:!0});if(0!==n.exitCode){if(n.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new k("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}return}await of(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function sk(e,t){let r=await sD(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],n=await T("xcrun",t,{allowFailure:!0,timeoutMs:ol});if(0!==n.exitCode){let a=String(n.stdout??""),i=String(n.stderr??"");if(!sx(`${a}
|
|
30
|
-
${i}`.toLowerCase()))throw new k("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:n.exitCode,stdout:a,stderr:i,deviceId:e.id,hint:og(a,i)??ow})}return{bundleId:r}}await oA(e);let n=await s_(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==n.exitCode&&!sx(`${n.stdout}
|
|
31
|
-
${n.stderr}`.toLowerCase()))throw new k("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});return{bundleId:r}}async function sL(e,t,r){let n=await ox({kind:"path",path:t},r);try{return await sP(e,n.installablePath),{archivePath:n.archivePath,installablePath:n.installablePath,bundleId:n.bundleId,appName:n.appName,launchTarget:n.bundleId}}finally{await n.cleanup()}}async function sC(e,t,r){let{bundleId:n}=await sk(e,t);return await sL(e,r,{appIdentifierHint:t}),{bundleId:n}}async function sP(e,t){"simulator"!==e.kind?await of(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await oA(e),await s_(e,["install",e.id,t]))}async function sR(e){if("macos"===e.platform)return await o5();oI(e,"clipboard"),await oA(e);let t=await s_(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 sT(e,t){if("macos"===e.platform)return void await o8(t);oI(e,"clipboard"),await oA(e);let r=await s_(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 s$(e,t,r){oI(e,"push"),await oA(e);let n=await u.mkdtemp(p.join(d.tmpdir(),"agent-device-ios-push-")),a=p.join(n,"payload.apns");try{await u.writeFile(a,`${JSON.stringify(r)}
|
|
32
|
-
`,"utf8"),await s_(e,["push",e.id,t,a])}finally{await u.rm(n,{recursive:!0,force:!0})}}async function sF(e,t,r,n,a){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await o9(r);if("permission"===e){let e=iQ(r);if("deny"===e)throw new k("INVALID_ARGS",eo("permission"));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.")}(a?.permissionTarget);return await oW(e,t)}throw new k("INVALID_ARGS",eo(t))}oI(e,"settings"),await oA(e);let i=t.toLowerCase();switch(i){case"wifi":{let t=sV(r);await s_(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(sV(r)?await s_(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await s_(e,["status_bar",e.id,"clear"]));case"location":{let t=sV(r);if(!n)throw new k("INVALID_ARGS","location setting requires an active app in session");await s_(e,["privacy",e.id,t?"grant":"revoke","location",n]);return}case"faceid":case"touchid":{let t=sj[i],n=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,i);await sz(e,n,{settingName:i,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await sB(e,r);await s_(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!n)throw new k("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=iQ(r))?"revoke":o,i=function(e,t){let r=i0(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.`)}(a?.permissionTarget,a?.permissionMode);await sq(e,t,i,n);return}default:throw new k("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function sU(e,t="all"){return"macos"===e.platform?await o7(t):"simulator"===e.kind?ok(await sG(e),t):await om(e,t)}async function sG(e){let t=(await s_(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let r=null;if(t.startsWith("{"))try{r=JSON.parse(t)}catch{r=null}if(!r&&t.startsWith("{"))try{let e=await T("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}function sV(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 sB(e,t){let r=i1(t);if("toggle"!==r)return r;let n=await s_(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==n.exitCode)throw new k("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});let a=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
|
|
33
|
-
${t}`);if(!r)return null;let n=r[1].toLowerCase();return"dark"===n?"dark":"light"===n?"light":null}(n.stdout,n.stderr);if(!a)throw new k("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:n.stdout,stderr:n.stderr});return"dark"===a?"light":"dark"}let sj={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function sq(e,t,r,n){let a=await sW(e);if(!a.has(r))throw new k("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:n,hint:`Supported services: ${Array.from(a).sort().join(", ")}`});let i=["privacy",e.id,t,r,n],o="notifications"===r;if(!("reset"===t&&o))try{await s_(e,i);return}catch(t){if(!(o&&sH(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:n,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await s_(e,i);return}catch(e){if(!sH(e))throw e}try{await s_(e,["privacy",e.id,"reset","all",n])}catch(t){throw new k("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:n,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function sH(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 sW(e){let r=e3(e.simulatorSetPath),n=`${process.env.PATH??""}::${r??""}`;if(sN&&t===n)return sN;let a=await s_(e,["privacy","help"],{allowFailure:!0}),i=function(e){let t=new Set,r=!1;for(let n of e.split("\n")){let e=n.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let a=/^([a-z-]+)\s+-\s+/.exec(e);a&&t.add(a[1])}return t}(`${a.stdout}
|
|
34
|
-
${a.stderr}`);if(0===i.size)throw new k("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return sN=i,t=n,i}async function sz(e,t,r){let n=function(e,t,r){let n=r.length>0?r:["face"];switch(t){case"match":return n.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return n.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),a=[];for(let t of n){let r=e6(e,t),n=await T("xcrun",r,{allowFailure:!0});if(0===n.exitCode)return;a.push({args:r,stderr:n.stderr,stdout:n.stdout,exitCode:n.exitCode})}let i=a.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(a.length>0&&a.every(e=>{var t,r;let n;return t=e.stdout,r=e.stderr,(n=`${t}
|
|
35
|
-
${r}`.toLowerCase()).includes("unrecognized subcommand")||n.includes("unknown subcommand")||n.includes("not supported")||n.includes("unavailable")||n.includes("biometric")&&n.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:i});throw new k("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:i})}async function sJ(e,t){await oA(e);let r=0,n=ec.fromTimeoutMs(os);try{await eb(async({deadline:r})=>{var n;if(r?.isExpired())throw new k("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:os});let a=(n=["launch",e.id,t],e6(e,n)),i=await T("xcrun",a,{allowFailure:!0});if(0!==i.exitCode)throw new k("COMMAND_FAILED",`xcrun exited with code ${i.exitCode}`,{cmd:"xcrun",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!oy(e)&&(r+=1)<3},{deadline:n})}catch(r){if(oy(r)){var a;let n=(a=await ov(e,t)).installed?!1===a.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(n)}}throw r}}async function sK(e,t,r){let n=["device","process","launch","--device",e.id,t];r?.payloadUrl&&n.push("--payload-url",r.payloadUrl),await of(n,{action:"launch iOS app",deviceId:e.id})}async function sX(e,t,r,n){let a=n?.maxScrolls??48,i=await e({command:"findText",text:r});if(i?.found)return{attempts:0};let o=sY(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let n=1;n<=a;n+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let a=await e({command:"findText",text:r});if(a?.found)return{attempts:n};let i=sY(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(i===o)throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:n,stalled:!0});o=i}throw new k("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a})}function sY(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function sZ(e,t,r,n,a,i,o){if("tv"===t.target)return s1(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}}(a),appBundleId:r.appBundleId},n),i);let s=o??await sQ(e,t,r,n),l=ia({direction:a,amount:i?.amount,pixels:i?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return s1(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},n),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function sQ(e,t,r,n){let a=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},n),i=s0(a.x),o=s0(a.y),s=s0(a.referenceWidth),l=s0(a.referenceHeight);if(void 0===i||void 0===o||void 0===s||void 0===l)throw new k("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:i,originY:o,referenceWidth:s,referenceHeight:l}}function s0(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function s1(e,t){var r;let{x1:n,y1:a,x2:i,y2:o}={x1:s0((r=e).x),y1:s0(r.y),x2:s0(r.x2),y2:s0(r.y2)},s=s0(e.referenceWidth),l=s0(e.referenceHeight),u=void 0!==n&&void 0!==i?Math.round(Math.abs(i-n)):void 0,d=void 0!==a&&void 0!==o?Math.round(Math.abs(o-a)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:u&&u>0?u:d&&d>0?d:void 0;return{...void 0!==n?{x1:n}:{},...void 0!==a?{y1:a}:{},...void 0!==i?{x2:i}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}function s2(){return process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11"}let s3=null;async function s4(){if(s3)return s3;let e=s2();if("wayland"===e){if(await F("ydotool"))return s3={tool:"ydotool",display:e};throw new k("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await F("xdotool"))return s3={tool:"xdotool",display:e};throw new k("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function s5(...e){await T("xdotool",e,{allowFailure:!1,timeoutMs:1e4})}async function s8(...e){await T("ydotool",e,{allowFailure:!1,timeoutMs:1e4})}async function s6(e,t){let{tool:r}=await s4();"xdotool"===r?await s5("mousemove","--sync",String(e),String(t)):await s8("mousemove","--absolute","-x",String(e),"-y",String(t))}async function s9(e,t){let{tool:r}=await s4();"xdotool"===r?await s5("key","--clearmodifiers",e):await s8("key",...t)}async function s7(e,t,r,n){await s6(e,t);let{tool:a}=await s4();"xdotool"===a?await s5("click",r):await s8("click",n)}async function le(e,t){await s7(e,t,"1","0xC0")}async function lt(e,t){await s7(e,t,"3","0xC1")}async function lr(e,t){await s7(e,t,"2","0xC2")}async function ln(e,t){let{tool:r}=await s4();await s6(e,t),"xdotool"===r?await s5("click","--repeat","2","1"):(await s8("click","0xC0"),await s8("click","0xC0"))}async function la(e,t,r=800){let{tool:n}=await s4();await s6(e,t),"xdotool"===n?(await s5("mousedown","1"),await ld(r),await s5("mouseup","1")):(await s8("click","--down","0xC0"),await ld(r),await s8("click","--up","0xC0"))}async function li(e,t){await le(e,t)}async function lo(e,t,r,n,a=300){let{tool:i}=await s4();await s6(e,t),"xdotool"===i?(await s5("mousedown","1"),await s5("mousemove","--sync",String(r),String(n)),await ld(a),await s5("mouseup","1")):(await s8("click","--down","0xC0"),await s8("mousemove","--absolute","-x",String(r),"-y",String(n)),await ld(a),await s8("click","--up","0xC0"))}async function ls(e,t){let{tool:r}=await s4(),n=5;if(t?.pixels!=null?n="xdotool"===r?Math.max(1,Math.round(t.pixels/15)):Math.max(1,Math.round(t.pixels/40)):t?.amount!=null&&(n=Math.max(1,Math.round(5*(t.amount/.6)))),"xdotool"===r)await s5("click","--repeat",String(n),"up"===e?"4":"down"===e?"5":"left"===e?"6":"7");else if("up"===e||"down"===e){let t="up"===e?String(-n):String(n);await s8("mousemove","--wheel","-y",t)}else{let t="left"===e?String(-n):String(n);await s8("mousemove","--wheel","-x",t)}}async function ll(e,t=0){let{tool:r}=await s4();if("xdotool"===r){let r=["type"];t>0&&r.push("--delay",String(t)),r.push("--clearmodifiers","--",e),await s5(...r)}else await s8("type","--",e)}async function lu(e,t,r,n=0){await le(e,t),await ld(100),await s9("ctrl+a",["29:1","30:1","30:0","29:0"]),await ld(50),await ll(r,n)}function ld(e){return new Promise(t=>setTimeout(t,e))}function lc(e){let t=null;return{resolve:async function(){if(t)return t;let r="wayland"===s2()?"wayland":"x11";for(let n of"wayland"===r?e.wayland:e.x11)if(await F(n.command))return t={tool:n.tool,display:r};throw new k("TOOL_MISSING","wayland"===r?e.waylandError:e.x11Error)},resetCache:()=>{t=null}}}let lp=lc({wayland:[{tool:"grim",command:"grim"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],x11:[{tool:"scrot",command:"scrot"},{tool:"import",command:"import"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],waylandError:"grim or gnome-screenshot is required for screenshots on Wayland. Install via your package manager.",x11Error:"scrot, import (ImageMagick), or gnome-screenshot is required for screenshots on X11. Install via your package manager."});async function lf(e){let{tool:t}=await lp.resolve();switch(t){case"grim":await T("grim",[e]);break;case"scrot":await T("scrot",[e]);break;case"import":await T("import",["-window","root",e]);break;case"gnome-screenshot":await T("gnome-screenshot",["-f",e])}}async function lm(e){if(e.includes("://")||e.startsWith("/"))return void await T("xdg-open",[e]);if(await F(e)){T(e,[],{allowFailure:!0}).catch(t=>{D({level:"warn",phase:"linux_app_launch",data:{app:e,error:String(t)}})}),await new Promise(e=>setTimeout(e,500));return}await T("xdg-open",[e],{allowFailure:!0})}async function lh(e){await F("wmctrl")?await T("wmctrl",["-c",e],{allowFailure:!0}):await T("pkill",["-x",e],{allowFailure:!0})}async function lw(){await s9("alt+Left",["56:1","105:1","105:0","56:0"])}async function lg(){await s9("super+d",["125:1","32:1","32:0","125:0"])}lp.resetCache;let ly=lc({wayland:[{tool:"wl-clipboard",command:"wl-paste"}],x11:[{tool:"xclip",command:"xclip"},{tool:"xsel",command:"xsel"}],waylandError:"wl-paste (wl-clipboard) is required for clipboard access on Wayland. Install via your package manager.",x11Error:"xclip or xsel is required for clipboard access on X11. Install via your package manager."});async function lv(){let{tool:e}=await ly.resolve();switch(e){case"wl-clipboard":return(await T("wl-paste",["--no-newline"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xclip":return(await T("xclip",["-selection","clipboard","-o"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xsel":return(await T("xsel",["--clipboard","--output"],{allowFailure:!0,timeoutMs:5e3})).stdout}}async function lI(e){let{tool:t}=await ly.resolve();switch(t){case"wl-clipboard":await T("wl-copy",["--",e],{allowFailure:!1,timeoutMs:5e3});break;case"xclip":await T("xclip",["-selection","clipboard"],{allowFailure:!1,timeoutMs:5e3,stdin:e});break;case"xsel":await T("xsel",["--clipboard","--input"],{allowFailure:!1,timeoutMs:5e3,stdin:e})}}async function lb(){return"linux"!==process.platform?[]:[{platform:"linux",id:"local",name:c(),kind:"device",target:"desktop",booted:!0}]}ly.resetCache;let lA={"push button":"Button","toggle button":"Button","push button menu":"Button",label:"StaticText",static:"StaticText",caption:"StaticText",text:"TextField",entry:"TextField","password text":"TextField","spin button":"TextField",terminal:"TextArea","document text":"TextArea",paragraph:"TextArea",frame:"Window",window:"Window",dialog:"Dialog",alert:"Alert","file chooser":"Dialog","color chooser":"Dialog","font chooser":"Dialog",panel:"Group",filler:"Group",section:"Group",form:"Group",grouping:"Group","layered pane":"Group","glass pane":"Group","root pane":"Group","option pane":"Group","internal frame":"Group","desktop frame":"Group","block quote":"Group",article:"Group",comment:"Group",landmark:"Group",log:"Group",marquee:"Group",math:"Group",notification:"Group","content deletion":"Group","content insertion":"Group",mark:"Group",suggestion:"Group","scroll pane":"ScrollArea","scroll bar":"ScrollBar","menu bar":"MenuBar",menu:"Menu","popup menu":"Menu","menu item":"MenuItem","check menu item":"MenuItem","radio menu item":"MenuItem","tearoff menu item":"MenuItem","check box":"CheckBox","radio button":"RadioButton",switch:"Switch","combo box":"ComboBox","page tab":"Tab","page tab list":"TabList",table:"Table","tree table":"Table","table cell":"Cell","table row":"Row","table column header":"Cell","table row header":"Cell","column header":"Cell","row header":"Cell",list:"List","list item":"ListItem","list box":"List",tree:"Tree","tree item":"TreeItem","description list":"List","description term":"ListItem","description value":"ListItem","tool bar":"Toolbar","status bar":"StatusBar","info bar":"StatusBar",slider:"Slider","progress bar":"ProgressBar","level bar":"ProgressBar",image:"Image",icon:"Image",animation:"Image",canvas:"Image","drawing area":"Image",video:"Video",audio:"Audio",link:"Link",hyperlink:"Link",separator:"Separator",application:"Application","tool tip":"Tooltip",timer:"Timer",heading:"Heading",footnote:"Footnote","title bar":"TitleBar","date editor":"DateEditor",rating:"Slider"},lS="atspi-dump.py",lN=null;async function l_(e,t={}){let r;if("linux"!==process.platform)throw new k("UNSUPPORTED_PLATFORM","AT-SPI2 bridge is only available on Linux");if(!await F("python3"))throw new k("TOOL_MISSING","python3 is required for AT-SPI2 accessibility snapshots on Linux.");let n=t.maxNodes??1500,a=t.maxDepth??12,i=t.maxApps??24,o=[function(){if(lN)return lN;let e=p.dirname(w(import.meta.url));for(let t=0;t<5;t++){let r=p.join(e,"src","platforms","linux",lS);if(s.existsSync(r))return lN=r,r;if(0===t){let t=p.join(e,lS);if(s.existsSync(t))return lN=t,t}e=p.dirname(e)}throw new k("TOOL_MISSING",`Cannot find ${lS}. Ensure the agent-device package is installed correctly.`)}(),"--surface",e,"--max-nodes",String(n),"--max-depth",String(a),"--max-apps",String(i)],l=await T("python3",o,{allowFailure:!0,timeoutMs:3e4});if(0!==l.exitCode){let e=l.stderr.trim();if(e.includes("No module named")||e.includes("gi.require_version"))throw new k("TOOL_MISSING","AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.",{cause:e});throw new k("COMMAND_FAILED",`AT-SPI2 snapshot failed (exit ${l.exitCode}): ${e||l.stdout}`)}try{r=JSON.parse(l.stdout)}catch{throw new k("COMMAND_FAILED",`AT-SPI2 snapshot returned invalid JSON: ${l.stdout.slice(0,200)}`)}if(r.error)throw new k("COMMAND_FAILED",`AT-SPI2: ${r.error}`);return{nodes:(r.nodes??[]).map(e=>{let t,r;return{index:e.index,type:(r=lA[t=e.role.toLowerCase().trim()])||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0}}),truncated:r.truncated,surface:e}}async function lx(e){let t="desktop"===e?"desktop":"frontmost-app"===e||"app"===e?"frontmost-app":("menubar"===e&&D({level:"warn",phase:"linux_snapshot",data:{message:"menubar surface is not supported on Linux, falling back to desktop"}}),"desktop"),r=await l_(t);return{nodes:r.nodes,truncated:r.truncated}}function lD(e){return e?.clickButton??"primary"}function lM(e){return"primary"===e.button?null:"click"!==e.commandLabel?new k("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform&&"linux"!==e.platform?new k("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS and Linux`):"macos"===e.platform&&"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 lE=/^[A-Za-z0-9_.:-]{1,64}$/,lO=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function lk(e,t,r,n){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>n)throw new k("INVALID_ARGS",`${t} must be an integer between ${r} and ${n}`);return e}async function lL(e,t,r){for(let n=0;n<e;n+=1)await r(n),n<e-1&&t>0&&await lC(t)}async function lC(e){await new Promise(t=>setTimeout(t,e))}function lP(e,t){let r,n=t?.subject??"Payload",a=e.trim();if(!a)throw new k("INVALID_ARGS",`${n} cannot be empty`);let i=t?.expandPath?t.expandPath(a,t.cwd):a;try{if(!s.statSync(i).isFile())throw new k("INVALID_ARGS",`${n} path is not a file: ${i}`);return{kind:"file",path:i}}catch(t){if(t instanceof k)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new k("INVALID_ARGS",`${n} file is not readable: ${i}`);if(e&&"ENOENT"!==e)throw new k("COMMAND_FAILED",`Unable to read ${n} file: ${i}`,{cause:String(t)})}if((r=a.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:a};throw new k("INVALID_ARGS",`${n} file not found: ${i}`)}async function lR(e){let t=lP(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await lT(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 lT(e){try{return await u.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 l$=eX(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),lF=/^(iphone|ipad|ipod|appletv)/i,lU=/\b(iphone|ipad|ipod)\b/i,lG=/^appletv/i,lV=["apple tv","appletv","tvos"],lB=/^==\s*(.+?)\s*==$/,lj=/^(?<name>.+?)\s+\[(?<id>[^[\]]+)\]\s*$/;function lq(e){return(e??"").trim().toLowerCase()}function lH(e){return lq(e.hardwareProperties?.platform)}function lW(e){return e.includes("tvos")}function lz(e){let t=lq(e);return lV.some(e=>t.includes(e))}function lJ(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function lK(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function lX(e={}){let t,r,n=e3(e.simulatorSetPath),a=e.target;try{t=await T("xcrun",e8(["list","devices","-j"],{simulatorSetPath:n}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let i=lY(r,n),o=null,s=null,l=null;for(let e of i)a&&e.target!==a||(e.booted&&(o=o??e),"mobile"===e.target&&(s=s??e),l=l??e);return o??s??l}function lY(e,t){let r=[];for(let[n,a]of Object.entries(e.devices))if(function(e){let t=lq(e);return t.includes("ios")||t.includes("tvos")}(n))for(let e of a)e.isAvailable&&r.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:lW(lq(n))?"tv":"mobile",booted:"Booted"===e.state,...t?{simulatorSetPath:t}:{}});return r}function lZ(e,t){let r=new Set(e.map(e=>e.id)),n=[...e];for(let e of t)r.has(e.id)||(r.add(e.id),n.push(e));return n}async function lQ(){let e=null;try{e=p.join(d.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let t=await T("xcrun",["devicectl","list","devices","--json-output",e],{allowFailure:!0,timeoutMs:l$});if(0!==t.exitCode)return[];let r=await u.readFile(e,"utf8");return function(e){let t=[];for(let r of e.result?.devices??[]){if(!function(e){var t;let r=lH(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=lK(e),!!lF.test(t.trim())||lJ(e).some(lz))}(r))continue;let e=r.hardwareProperties?.udid??r.identifier??"",n=r.name??r.deviceProperties?.name??e;e&&t.push({platform:"ios",id:e,name:n,kind:"device",target:function(e){var t;return lW(lH(e))?"tv":(t=lK(e),lG.test(t.trim())||lJ(e).some(lz))?"tv":"mobile"}(r),booted:!0})}return t}(JSON.parse(r))}catch{return[]}finally{e&&await u.rm(e,{force:!0}).catch(()=>{})}}async function l0(){try{let e=await T("xcrun",["xctrace","list","devices"],{allowFailure:!0});if(0!==e.exitCode)return[];return function(e){let t=[],r=null;for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e)continue;let a=lB.exec(e);if(a){r=a[1]?.trim()??null;continue}if("Devices"!==r)continue;let i=lj.exec(e),o=i?.groups?.id?.trim()??"",s=i?.groups?.name?.trim()??"";if(!o||!s)continue;let l=function(e){return lz(e)?"tv":lU.test(e.trim())?"mobile":null}(s);l&&t.push({platform:"ios",id:o,name:s,kind:"device",target:l,booted:!0})}return t}(e.stdout)}catch{return[]}}async function l1(e={}){if("darwin"!==process.platform)throw new k("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await F("xcrun"))throw new k("TOOL_MISSING","xcrun not found in PATH");let t=e3(e.simulatorSetPath),r=await T("xcrun",e8(["list","devices","-j"],{simulatorSetPath:t})),n=[];try{let e=JSON.parse(r.stdout);n=lY(e,t)}catch(e){throw new k("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(n.push({platform:"macos",id:"host-macos-local",name:d.hostname(),kind:"device",target:"desktop",booted:!0}),t)return n;let[a,i]=await Promise.all([lQ(),l0()]);return n=lZ(n,a),lZ(n,i)}async function l2(e,t,r){let n,a=!!(t.udid||t.serial||t.deviceName);try{n=await tS(e,t,r)}catch(e){if(a||!(e instanceof k)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!a&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!n||"device"===n.kind)){let e=await lX({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(n)return n;throw new k("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function l3(e){let t=e.platform,r=tA({simulatorSetPath:e3(e.iosSimulatorDeviceSet),platform:t,target:e.target}),n=e5(e.androidDeviceAllowlist);return await x("resolve_target_device",async()=>{let a={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(a.target&&!a.platform)throw new k("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|linux|apple with --target mobile|tv|desktop.");if("linux"===a.platform){let e=await lb();return await tS(e,a)}if("android"===a.platform){await nz();let e=await ae({serialAllowlist:n});return await tS(e,a)}if(a.platform){let e=await l1({simulatorSetPath:r});return await l2(e,a,{simulatorSetPath:r})}let i=[];try{i.push(...await ae({serialAllowlist:n}))}catch{}try{i.push(...await l1({simulatorSetPath:r}))}catch{}try{i.push(...await lb())}catch{}return await tS(i,a,{simulatorSetPath:r})},{platform:t,target:e.target})}async function l4(e,t,r,n,a){let i={requestId:a?.requestId,appBundleId:a?.appBundleId,verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>az(e,t,r?.activity),openDevice:()=>aQ(e),close:t=>a0(e,t),tap:(t,r)=>i_(e,t,r),doubleTap:async(t,r)=>{await i_(e,t,r),await i_(e,t,r)},swipe:(t,r,n,a,i)=>ix(e,t,r,n,a,i),longPress:(t,r,n)=>ik(e,t,r,n),focus:(t,r)=>iP(e,t,r),type:(t,r)=>iL(e,t,r),fill:(t,r,n,a)=>iR(e,t,r,n,a),scroll:(t,r)=>iF(e,t,r),scrollIntoView:(t,r)=>iU(e,t,r),screenshot:t=>ot(e,t),back:t=>iD(e),home:()=>iM(e),rotate:t=>iE(e,t),appSwitcher:()=>iO(e),readClipboard:()=>iK(e),writeClipboard:t=>iX(e,t),setSetting:(t,r,n,a)=>i2(e,t,r,n,a)};case"linux":return{open:e=>lm(e),openDevice:()=>Promise.resolve(),close:e=>lh(e),tap:(e,t)=>le(e,t),doubleTap:(e,t)=>ln(e,t),swipe:(e,t,r,n,a)=>lo(e,t,r,n,a),longPress:(e,t,r)=>la(e,t,r),focus:(e,t)=>li(e,t),type:(e,t)=>ll(e,t),fill:(e,t,r,n)=>lu(e,t,r,n),scroll:(e,t)=>ls(e,t),scrollIntoView:()=>{throw new k("UNSUPPORTED_OPERATION","scrollIntoView not yet supported on Linux")},screenshot:e=>lf(e),back:()=>lw(),home:()=>lg(),rotate:()=>{throw new k("UNSUPPORTED_OPERATION","rotate not supported on Linux")},appSwitcher:()=>{throw new k("UNSUPPORTED_OPERATION","appSwitcher not yet supported on Linux")},readClipboard:()=>lv(),writeClipboard:e=>lI(e),setSetting:()=>{throw new k("UNSUPPORTED_OPERATION","setSetting not supported on Linux")}};case"ios":case"macos":{let r,n,{overrides:a,runnerOpts:i}=(r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},n=()=>{if(eW(t.requestId))throw eJ()},{runnerOpts:r,overrides:{tap:async(n,a)=>await ru(e,{command:"tap",x:n,y:a,appBundleId:t.appBundleId},r),doubleTap:async(n,a)=>await ru(e,{command:"tapSeries",x:n,y:a,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(n,a,i,o,s)=>await ru(e,{command:"drag",x:n,y:a,x2:i,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(n,a,i)=>await ru(e,{command:"longPress",x:n,y:a,durationMs:i,appBundleId:t.appBundleId},r),focus:async(n,a)=>await ru(e,{command:"tap",x:n,y:a,appBundleId:t.appBundleId},r),type:async(n,a)=>{await ru(e,{command:"type",text:n,delayMs:a,appBundleId:t.appBundleId},r)},fill:async(n,a,i,o)=>{let s=await ru(e,{command:"tap",x:n,y:a,appBundleId:t.appBundleId},r);return await ru(e,{command:"type",text:i,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},r),s},scroll:async(n,a)=>await sZ(ru,e,t,r,n,a),scrollIntoView:async(a,i)=>await sX(n=>ru(e,{...n,appBundleId:t.appBundleId},r),n,a,i)}});return{open:(t,r)=>sM(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>sE(e),close:t=>sO(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await oY(t,{surface:r.surface,fullscreen:r.fullscreen}):await sp(e,t,r?.appBundleId,r?.fullscreen)},back:async r=>{await ru(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},i)},home:async()=>{await ru(e,{command:"home",appBundleId:t.appBundleId},i)},rotate:async r=>{await ru(e,{command:"rotate",orientation:r,appBundleId:t.appBundleId},i)},appSwitcher:async()=>{await ru(e,{command:"appSwitcher",appBundleId:t.appBundleId},i)},readClipboard:()=>sR(e),writeClipboard:t=>sT(e,t),setSetting:(t,r,n,a)=>sF(e,t,r,n,a),...a}}default:throw new k("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,i);return D({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await x("platform_command",async()=>{switch(t){case"open":return l5(e,o,r,a);case"close":{let e=r[0];if(!e)return{closed:"session",...eh("Closed session")};return await o.close(e),{app:e,...eh(`Closed: ${e}`)}}case"press":return l8(e,o,r,a,i);case"swipe":return l6(e,o,r,a,i);case"longpress":{let e=Number(r[0]),t=Number(r[1]),n=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,n),{x:e,y:t,durationMs:n,...eh(`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,...eh(`Focused (${e}, ${t})`)}}case"type":{let e=function(e){let t=e[0]?.trim();if(!t||!t.startsWith("@")||t.length<3)return null;let r=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(r)||/^(?:ref|node|element|el)[\w-]*$/i.test(r)?t:null}(r);if(e)throw new k("INVALID_ARGS",`type does not accept a target ref like "${e}"`,{hint:`Use fill ${e} "text" to target that field, or press ${e} then type "text" to append.`});let t=r.join(" ");if(!t)throw new k("INVALID_ARGS","type requires text");let n=lk(a?.delayMs??0,"delay-ms",0,1e4);return await o.type(t,n),{text:t,delayMs:n,...eh(ul("Typed",t))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),n=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!n)throw new k("INVALID_ARGS","fill requires x y text");let i=lk(a?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,n,i),{x:e,y:t,text:n,delayMs:i,...eh(ul("Filled",n))}}case"scroll":return l9(o,r,a);case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new k("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:a?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...eh(`Scrolled into view: ${e}`)};return{text:e,...eh(`Scrolled into view: ${e}`)}}case"pinch":return l7(e,r,a,i);case"trigger-app-event":{let{eventName:t,payload:n}=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(!lE.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 n=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 n=JSON.stringify(r);if(Buffer.byteLength(n,"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:n}}(r),i=function(e,t,r){var n;let a,i=(a=("ios"===(n=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===n?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,a?.trim()||void 0);if(!i)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=i.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,n);return await o.open(i,{appBundleId:a?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link",...eh(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??n??`./screenshot-${Date.now()}.png`;return await u.mkdir(p.dirname(e),{recursive:!0}),await o.screenshot(e,{appBundleId:a?.appBundleId,fullscreen:a?.screenshotFullscreen,surface:a?.surface}),{path:e,...eh(`Saved screenshot: ${e}`)}}case"back":return await o.back(a?.backMode),{action:"back",mode:a?.backMode??"in-app",...eh("Back")};case"home":return await o.home(),{action:"home",...eh("Home")};case"rotate":{let e=function(e){if(void 0===e)throw new k("INVALID_ARGS","rotate requires an orientation argument. Use portrait|portrait-upside-down|landscape-left|landscape-right.");switch(e?.trim().toLowerCase()){case"portrait":return"portrait";case"portrait-upside-down":case"upside-down":return"portrait-upside-down";case"landscape-left":case"left":return"landscape-left";case"landscape-right":case"right":return"landscape-right";default:throw new k("INVALID_ARGS",`Invalid rotation: ${e}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}(r[0]);return await o.rotate(e),{action:"rotate",orientation:e,...eh(`Rotated to ${e}`)}}case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...eh("Opened app switcher")};case"clipboard":return ue(o,r);case"keyboard":return ut(e,o,r,a,i);case"settings":return ur(e,o,r,a);case"push":return un(e,r,a);case"snapshot":return ua(e,r,a,i);case"read":return ui(e,r,a,i);default:throw new k("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}async function l5(e,t,r,n){let a=r[0],i=r[1];if(r.length>2)throw new k("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!a)return await t.openDevice(),{app:null,...eh("Opened device")};if(void 0!==i){if("android"===e.platform)throw new k("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(nX(a))throw new k("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!nX(i))throw new k("INVALID_ARGS","open <app> <url> requires a valid URL target");return await t.open(a,{activity:n?.activity,appBundleId:n?.appBundleId,url:i}),{app:a,url:i,...eh(`Opened: ${a}`)}}return await t.open(a,{activity:n?.activity,appBundleId:n?.appBundleId}),{app:a,...eh(`Opened: ${a}`)}}async function l8(e,t,r,n,a){let i,[o,s]=r.map(Number);if(Number.isNaN(o)||Number.isNaN(s))throw new k("INVALID_ARGS","press requires x y");if("macos"===e.platform&&n?.surface&&"app"!==n.surface){let e=lD(n);if("primary"!==e)throw new k("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${n.surface} sessions.`);return await oX(o,s,{bundleId:n.appBundleId,surface:n.surface}),{x:o,y:s,...eh(uo({x:o,y:s}))}}let l=lD(n);if("primary"!==l){let t=lM({commandLabel:"click",platform:e.platform,button:l,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(t)throw t;return"linux"===e.platform?"secondary"===l?await lt(o,s):await lr(o,s):await ru(e,{command:"mouseClick",x:o,y:s,button:l,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{x:o,y:s,button:l,...eh(uo({x:o,y:s,button:l}))}}let u=lk(n?.count??1,"count",1,200),d=lk(n?.intervalMs??0,"interval-ms",0,1e4),c=lk(n?.holdMs??0,"hold-ms",0,1e4),p=lk(n?.jitterPx??0,"jitter-px",0,100),f=n?.doubleTap===!0;if(f&&c>0)throw new k("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&p>0)throw new k("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&u>1&&0===c&&0===p){let t=await ru(e,{command:"tapSeries",x:o,y:s,count:u,intervalMs:d,doubleTap:f,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId});return{x:o,y:s,count:u,intervalMs:d,holdMs:c,jitterPx:p,doubleTap:f,timingMode:"runner-series",...t,...eh(uo({x:o,y:s}))}}return await lL(u,d,async e=>{let[r,n]=function(e,t){if(t<=0)return[0,0];let[r,n]=lO[e%lO.length];return[r*t,n*t]}(e,p),a=o+r,l=s+n;if(f){i??=await t.doubleTap(a,l)??void 0;return}c>0?i??=await t.longPress(a,l,c)??void 0:i??=await t.tap(a,l)??void 0}),en({x:o,y:s,count:u,intervalMs:d,holdMs:c,jitterPx:p,doubleTap:f,...i},uo({x:o,y:s}))}async function l6(e,t,r,n,a){let i=Number(r[0]),o=Number(r[1]),s=Number(r[2]),l=Number(r[3]);if([i,o,s,l].some(Number.isNaN))throw new k("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let u=lk(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(u))):u,c=lk(n?.count??1,"count",1,200),p=lk(n?.pauseMs??0,"pause-ms",0,1e4),f=n?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new k("INVALID_ARGS",`Invalid pattern: ${f}`);if(("ios"===e.platform||"macos"===e.platform)&&c>1){let t=await ru(e,{command:"dragSeries",x:i,y:o,x2:s,y2:l,durationMs:d,count:c,pauseMs:p,pattern:f,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId});return{x1:i,y1:o,x2:s,y2:l,durationMs:u,effectiveDurationMs:d,timingMode:"runner-series",count:c,pauseMs:p,pattern:f,...t,...eh(us(c,f))}}return await lL(c,p,async e=>{"ping-pong"===f&&e%2==1?await t.swipe(s,l,i,o,d):await t.swipe(i,o,s,l,d)}),en({x1:i,y1:o,x2:s,y2:l,durationMs:u,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:c,pauseMs:p,pattern:f},us(c,f))}async function l9(e,t,r){let n=t[0],a=t[1]?Number(t[1]):void 0,i=r?.pixels;if(!n)throw new k("INVALID_ARGS","scroll requires direction");if(void 0!==a&&!Number.isFinite(a))throw new k("INVALID_ARGS","scroll amount must be a number");if(void 0!==a&&void 0!==i)throw new k("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let o=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new k("INVALID_ARGS",`Unknown direction: ${e}`)}}(n),s=await e.scroll(o,{amount:a,pixels:i});return en({direction:o,...void 0!==a?{amount:a}:{},...void 0!==i?{pixels:i}:{},...s},void 0!==i?`Scrolled ${o} by ${i}px`:void 0!==a?`Scrolled ${o} by ${a}`:`Scrolled ${o}`)}async function l7(e,t,r,n){if("android"===e.platform)throw new k("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&r?.surface&&"app"!==r.surface)throw new k("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let a=Number(t[0]),i=t[1]?Number(t[1]):void 0,o=t[2]?Number(t[2]):void 0;if(Number.isNaN(a)||a<=0)throw new k("INVALID_ARGS","pinch requires scale > 0");return await ru(e,{command:"pinch",scale:a,x:i,y:o,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId}),{scale:a,x:i,y:o,...eh(`Pinched to scale ${a}`)}}async function ue(e,t){let r=(t[0]??"").toLowerCase();if("read"!==r&&"write"!==r)throw new k("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===r){if(1!==t.length)throw new k("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:r,text:await e.readClipboard()}}if(t.length<2)throw new k("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let n=t.slice(1).join(" ");return await e.writeClipboard(n),{action:r,textLength:Array.from(n).length,...eh("Clipboard updated")}}async function ut(e,t,r,n,a){let i=(r[0]??"status").toLowerCase();if("status"!==i&&"get"!==i&&"dismiss"!==i)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"===i){let t=await iJ(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let t=await iz(e);return{platform:"android",action:"status",visible:t.visible,inputType:t.inputType,type:t.type}}if("ios"===e.platform){if("dismiss"!==i)throw new k("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let t=await ru(e,{command:"keyboardDismiss",appBundleId:n?.appBundleId},a);return{platform:"ios",action:"dismiss",wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,...eh(t.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new k("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}async function ur(e,t,r,n){var a;let[i,o,s,l,u]=r,d="permission"===i?{permissionTarget:s,permissionMode:l}:void 0;D({level:"debug",phase:"settings_apply",data:{setting:i,state:o,target:s,mode:l,platform:e.platform}});let c=await t.setSetting(i,o,u??n?.appBundleId,d);return c&&"object"==typeof c?en({setting:i,state:o,...c},("string"==typeof(a=c).message&&a.message.length>0?a.message:void 0)??`Updated setting: ${i}`):{setting:i,state:o,...eh(`Updated setting: ${i}`)}}async function un(e,t,r){let n=t[0]?.trim(),a=t[1]?.trim();if(!n||!a)throw new k("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await lR(a);if("ios"===e.platform)return await s$(e,n,i),{platform:"ios",bundleId:n,...eh(`Pushed notification to ${n}`)};let o=await i7(e,n,i);return{platform:"android",package:n,action:o.action,extrasCount:o.extrasCount,...eh(`Pushed notification to ${n}`)}}async function ua(e,t,r,n){if("linux"===e.platform){let e=await x("snapshot_capture",async()=>await lx(r?.surface),{backend:"linux-atspi"});return{nodes:e.nodes??[],truncated:e.truncated??!1,backend:"linux-atspi"}}if("android"!==e.platform){let t=await x("snapshot_capture",async()=>await ru(e,{command:"snapshot",appBundleId:r?.appBundleId,interactiveOnly:r?.snapshotInteractiveOnly,compact:r?.snapshotCompact,depth:r?.snapshotDepth,scope:r?.snapshotScope,raw:r?.snapshotRaw},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId}),{backend:"xctest"}),n=t.nodes??[];if(0===n.length&&"simulator"===e.kind)throw new k("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:n,truncated:t.truncated??!1,backend:"xctest"}}let a=await x("snapshot_capture",async()=>await iy(e,{interactiveOnly:r?.snapshotInteractiveOnly,compact:r?.snapshotCompact,depth:r?.snapshotDepth,scope:r?.snapshotScope,raw:r?.snapshotRaw}),{backend:"android"});return{nodes:a.nodes??[],truncated:a.truncated??!1,backend:"android",analysis:a.analysis}}async function ui(e,t,r,n){let[a,i]=t.map(Number);if(Number.isNaN(a)||Number.isNaN(i))throw new k("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await iH(e,a,i)??""};if("macos"===e.platform&&r?.surface&&"app"!==r.surface)return{action:"read",text:(await oK(a,i,{bundleId:r.appBundleId,surface:r.surface})).text};let o=await ru(e,{command:"readText",x:a,y:i,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId});return{action:"read",text:"string"==typeof o.text?o.text:"string"==typeof o.message?o.message:""}}function uo(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function us(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function ul(e,t){return`${e} ${Array.from(t).length} chars`}let uu=e=>"macos"!==e.platform,ud=e=>"macos"===e.platform||"simulator"===e.kind,uc={device:!0},up={},uf={alert:{apple:{simulator:!0,device:!0},android:{},linux:up,supports:ud},pinch:{apple:{simulator:!0,device:!0},android:{},linux:up,supports:ud},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:uu},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:uu},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc,supports:e=>"android"===e.platform||"linux"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc,supports:uu},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:uu},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:uu},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:uu},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:uu},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up},rotate:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up,supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:up},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:uc}};function um(e,t){let r=uf[e];if(!r)return!0;let n=tI(t.platform)?r.apple:"linux"===t.platform?r.linux:r.android;return!!n&&(!r.supports||!!r.supports(t))&&!0===n[t.kind??"unknown"]}function uh(e,t,r,n,a){return{requestId:a??$().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:n,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,screenshotFullscreen:t?.screenshotFullscreen,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:lD(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let uw=eX(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function ug(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(eT);await t(e);return}if("device"===e.kind)return void await uy(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(eL);await t(e.id)}}async function uy(e){let t=p.join(d.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(uw/1e3));try{let n=await T("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:uw+3e3}),a=String(n.stdout??""),i=String(n.stderr??""),o=await uv(t);if(0===n.exitCode){if(!o.parsed)throw new k("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:a,stderr:i,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new 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:a,stderr:i,exitCode:n.exitCode,tunnelState:o?.tunnelState,hint:uI(a,i)})}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??{},n=String(r.stdout??""),a=String(r.stderr??""),i=Number(r.timeoutMs??uw),o=`CoreDevice did not respond within ${i}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new k("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:i,stdout:n,stderr:a,hint:n||a?uI(n,a):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 u.rm(t,{force:!0}).catch(()=>{})}}async function uv(e){try{let t=await u.readFile(e,"utf8"),r=JSON.parse(t),n=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,n=t.device?.connectionProperties?.tunnelState,a="string"==typeof r?r:"string"==typeof n?n:void 0;return a?{tunnelState:a}:{}}(r);return{parsed:!0,tunnelState:n.tunnelState}}catch{return{parsed:!1}}}function uI(e,t){let r=og(e,t);return r||(`${e}
|
|
36
|
-
${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":ow)}let ub=eX(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),uA=new Map;async function uS(e){let t=await A.mkdtemp(p.join(d.tmpdir(),"agent-device-materialized-"));try{let r=await ux(e.installablePath,p.join(t,"installable")),n=e.archivePath?await ux(e.archivePath,p.join(t,"archive")):void 0,a=i.randomUUID(),o=e.ttlMs??ub,s=Date.now()+o,l=setTimeout(()=>{uN(a)},o);return uA.set(a,{rootPath:t,installablePath:r,archivePath:n,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:a,installablePath:r,...n?{archivePath:n}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await A.rm(t,{recursive:!0,force:!0}),e}}async function uN(e,t){let r=uA.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),uA.delete(e),await A.rm(r.rootPath,{recursive:!0,force:!0})}async function u_(e){let t=Array.from(uA.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await uN(e)}))}async function ux(e,t){let r=await A.stat(e);await A.mkdir(t,{recursive:!0});let n=p.join(t,p.basename(e));return r.isDirectory()?await A.cp(e,n,{recursive:!0}):await A.copyFile(e,n),n}function uD(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}async function uM(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 ug(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 n=await l3(e.flags??{});return await ug(n),n}async function uE(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);try{let e,i,o,s=(i=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"===i.kind?{source:{kind:"path",path:np(o,t.meta?.tenantId)},cleanup:()=>{nf(o)}}:{source:i,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new k("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),u=await uM({session:a,flags:t.flags});if(!um("install",u))return uD("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let d=ez(t.meta?.requestId);if("ios"===u.platform){let e,{installIosInstallablePath:i}=await Promise.resolve(eT),{prepareIosInstallArtifact:o}=await Promise.resolve(e$),c=await o(s.source,{signal:d});try{if(l.enabled&&(e=await uS({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:a?r:void 0,ttlMs:l.ttlMs})),await i(u,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=en(o,uO(o));return a&&n.recordAction(a,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await uN(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await Promise.resolve(eP),{installAndroidInstallablePathAndResolvePackageName:p}=await Promise.resolve(eC),f=await c(s.source,{signal:d});try{l.enabled&&(e=await uS({archivePath:f.archivePath,installablePath:f.installablePath,tenantId:t.meta?.tenantId,sessionName:a?r:void 0,ttlMs:l.ttlMs}));let i=await p(u,f.installablePath,f.packageName);if(!i)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(eC),s=o(i),d={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:i,...s?{appName:s}:{},launchTarget:i,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=en(d,uO(d));return a&&n.recordAction(a,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await uN(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await f.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:O(e)}}}function uO(e){return`Installed: ${eM(e)}`}async function uk(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 uN(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:O(e)}}}let uL=eX(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),uC=eX(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function uP(e,t,r){return t||uR(r)?null:uD("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function uR(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function uT(e){return"ios"===e.platform&&"simulator"===e.kind}async function u$(e,t){uT(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function uF(e){let t=uR(e.flags)||!e.session?await l3(e.flags??{}):await uU(e.session.device);return!1!==e.ensureReady&&await ug(t),t}async function uU(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 l3(t)}catch(e){if(!(e instanceof k)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await l3({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function uG(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 uV="shared_prefs/ReactNativeDevPrefs.xml",uB="debug_http_host",uj="dev_server_https",uq="RCT_jsLocation",uH="RCT_packager_scheme",uW="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.",uz='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function uJ(e){return void 0!==uK(e)}function uK(e){if(!e)return;let t=u6(e.metroHost),r=u7(e.metroPort),n="http",a=u6(e.bundleUrl);if(a){var i;let e;try{e=new h(a)}catch(e){throw new k("INVALID_ARGS",`Invalid runtime bundle URL: ${a}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=u6(e.hostname),r??=u7(e.port.length>0?Number(e.port):"https:"===(i=e.protocol)?443:"http:"===i?80:void 0),n="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:n}}async function uX(e){let{device:t,appId:r,runtime:n}=e;if(!r)return;let a=uK(n);if(a){if("android"===t.platform)return void await uZ(t,r,a);"ios"===t.platform&&"simulator"===t.kind&&await u2(t,r,a)}}async function uY(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await uQ(t,r);"ios"===t.platform&&"simulator"===t.kind&&await u3(t,r)}}async function uZ(e,t,r){var n,a,i,o,s,l;let u,d;u9(t);let c=(n=await u0(e,t),a=uB,i=`${r.host}:${r.port}`,u=` <string name="${de(a)}">${de(i)}</string>`,u5(u8(n,a),u));o=c,s=uj,l="https"===r.scheme,d=` <boolean name="${de(s)}" value="${l?"true":"false"}" />`,c=u5(u8(o,s),d),await u1(e,t,c)}async function uQ(e,t){u9(t);let r=await u0(e,t),n=u8(r,uB),a=u8(n,uj);a!==r&&await u1(e,t,a)}async function u0(e,t){let r=await T("adb",nW(e,["shell","run-as",t,"cat",uV]),{allowFailure:!0});return 0!==r.exitCode?uz:u4(r.stdout)}async function u1(e,t,r){let n=nW(e,["shell","run-as",t,"id"]),a=await T("adb",n,{allowFailure:!0});if(0!==a.exitCode){let e=dt(a.stdout,a.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:n,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:e?uW:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await T("adb",nW(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await T("adb",nW(e,["shell","run-as",t,"tee",uV]),{stdin:r.trimEnd()})}catch(n){let e=E(n);if("TOOL_MISSING"===e.code)throw e;let r=dt("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?uW:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function u2(e,t,r){await T("xcrun",e6(e,["spawn",e.id,"defaults","write",t,uq,"-string",`${r.host}:${r.port}`])),await T("xcrun",e6(e,["spawn",e.id,"defaults","write",t,uH,"-string",r.scheme]))}async function u3(e,t){await T("xcrun",e6(e,["spawn",e.id,"defaults","delete",t,uq]),{allowFailure:!0}),await T("xcrun",e6(e,["spawn",e.id,"defaults","delete",t,uH]),{allowFailure:!0})}function u4(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
37
|
-
`:uz}function u5(e,t){return u4(e).replace("</map>",`${t}
|
|
38
|
-
</map>`)}function u8(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return u4(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 u6(e){let t=e?.trim();return t&&t.length>0?t:void 0}function u9(e){if("binary"!==ad(e))return;let t=ac(e);throw new k("INVALID_ARGS",t,{package:e,hint:t})}function u7(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function de(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function dt(e,t){let r=`${e}
|
|
39
|
-
${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 dr=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function dn(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function da(e){let t=e?.trim();return t&&t.length>0?t:void 0}function di(e,t){if(void 0!==e){if("string"!=typeof e)throw new k("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return da(e)}}function ds(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 dl(e){if("ios"===e||"android"===e)return e}async function du(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:n,session:a}=e;!t||!a?.appBundleId||!uJ(r)||uJ(n)||await uY({device:a.device,appId:a.appBundleId})}async function dd(e){var t,r;let{req:n,sessionName:a,sessionStore:i}=e,o=(n.positionals?.[0]??"show").toLowerCase(),s=i.get(a),l=i.getRuntimeHints(a);if(!["set","show","clear"].includes(o))return uD("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){uJ(l)&&s?.appBundleId&&await uY({device:s.device,appId:s.appBundleId});let e=i.clearRuntimeHints(a);return{ok:!0,data:{session:a,cleared:e}}}if("show"===o)return{ok:!0,data:{session:a,configured:!!l,runtime:l}};let u=dl(n.flags?.platform??l?.platform??s?.device.platform);if(!u)return uD("INVALID_ARGS","runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first.");if(s&&s.device.platform!==u)return uD("INVALID_ARGS",`runtime set targets ${u}, but session "${a}" is already bound to ${s.device.platform}.`);let d={platform:(t=n.flags,r={platform:u,metroHost:da(t?.metroHost),metroPort:ds(t?.metroPort),bundleUrl:da(t?.bundleUrl),launchUrl:da(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===dn(d)?uD("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(i.setRuntimeHints(a,d),{ok:!0,data:{session:a,configured:!0,runtime:d}})}let dc="open-command-roundtrip",dp="Not implemented for this platform in this release.",df=new Set(["app","desktop","frontmost-app"]);async function dm(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await oq();return{appBundleId:t.bundleId,appName:t.appName}}let dh=[250,400];function dw(e,t,r=e.snapshot){if("android"!==e.device.platform)return;let n=r?.comparisonSafe===!0;e.androidSnapshotFreshness={action:t,markedAt:Date.now(),baselineCount:r?.nodes.length??0,baselineSignatures:n?dI(r?.nodes??[]):void 0,routeComparable:n}}function dg(e){if(!e||"android"!==e.device.platform)return;let t=e.androidSnapshotFreshness;if(t)return Date.now()-t.markedAt>2500?void delete e.androidSnapshotFreshness:t}function dy(e){e&&"android"===e.device.platform&&delete e.androidSnapshotFreshness}function dv(e){return"press"===e||"click"===e||"back"===e||"open"===e}function dI(e){return e.map(e=>[e.depth??0,e.type??"",e.role??"",e.label??"",e.value??"",e.identifier??"",!1===e.enabled?"disabled":"enabled",!0===e.selected?"selected":"unselected",!0===e.hittable?"hittable":"not-hittable"].join("|"))}function db(e,t){return!(e<12)&&t<=Math.floor(.2*e)}async function dA(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return nX(t)?"macos"===e.platform?void 0:"device"===e.kind?nY(r,t):void 0:await dS(e,t)}async function dS(e,t){try{let{resolveIosApp:r}=await Promise.resolve(eT);return await r(e,t)}catch{return}}async function dN(e,t){if(!("android"!==e.platform||!t||nX(t)))try{let{resolveAndroidApp:r}=await Promise.resolve(eC),n=await r(e,t);return"package"===n.type?n.value:void 0}catch{return}}async function d_(e,t,r,n){return await dA(e,t,r)??await n(e,t)??("android"===e.platform&&t&&nX(t)?r:void 0)}function dx(e){return uD("INVALID_ARGS",e)}function dD(e,t,r,n){try{return function(e){let{device:t,surfaceFlag:r,openTarget:n,existingSurface:a}=e;if(("macos"===t.platform||"linux"===t.platform)&&!r)return a??"app";if("linux"===t.platform){if(!r)return"app";let e=e_(r);if(!df.has(e))throw new k("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&n)throw new k("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new k("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let i=r?e_(r):"app";if("app"!==i&&"menubar"!==i&&n)throw new k("INVALID_ARGS",`open --surface ${i} does not accept an app target`);return i}({device:e,surfaceFlag:t,openTarget:r,existingSurface:n})}catch(e){return uD(e instanceof k?e.code:"INVALID_ARGS",String(e.message))}}function dM(e){let{shouldRelaunch:t,openTarget:r,surface:n,device:a}=e;return t?r&&nX(r)?dx("open --relaunch does not support URL targets."):"app"!==n?dx("open --relaunch is supported only for app surfaces."):"android"===a.platform&&r&&"binary"===ad(r)?dx(ac(r)):null:null}async function dE(e){let{req:t,sessionName:r,sessionStore:n,device:a,surface:i,openTarget:o,existingSession:s}=e;await ug(a);let{appBundleId:l,appName:u}=await dO({device:a,surface:i,openTarget:o,existingAppBundleId:s?.appBundleId}),d=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:n,device:a}=e,i=r.getRuntimeHints(n),o=function(e){let{runtime:t,sessionName:r,platform:n}=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 a=Object.keys(t).find(e=>!dr.includes(e));if(a)throw new k("INVALID_ARGS",`Invalid open runtime field: ${a}. Supported fields are ${dr.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,n),metroHost:di(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 ds(e)}}(t.metroPort),bundleUrl:di(t.bundleUrl,"bundleUrl"),launchUrl:di(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:n,platform:dl(a.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let n=e.getRuntimeHints(t);if(!n)return;let a=r?.platform,i=dl(a);if(n.platform&&r&&!i)throw new k("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${a}.`);if(n.platform&&i&&n.platform!==i)throw new k("INVALID_ARGS",`Session runtime hints target ${n.platform}, but session "${t}" is bound to ${a}. Clear the runtime hints or use a different session.`);return i&&n.platform!==i?{...n,platform:i}:n}(r,n,a),previousRuntime:i,replacedStoredRuntime:!1}:{runtime:o&&dn(o)>0?o:void 0,previousRuntime:i,replacedStoredRuntime:!0}}(e)}}catch(t){let e=E(t);return uD(e.code,e.message,e.details)}}({req:t,sessionStore:n,sessionName:r,device:a});if(!d.ok)return{type:"response",response:d};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=d.data;await du({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:u,runtime:d.data.runtime}}}async function dO(e){let{device:t,surface:r,openTarget:n,existingAppBundleId:a}=e,i=await dm(r);return{appBundleId:i.appBundleId??await d_(t,n,a,dN),appName:i.appName??n}}let dk=new Map;async function dL(e){let{device:t,closeTarget:r,outFlag:n,context:a}=e;"android"!==t.platform&&await rr(t.id),await l4(t,"close",[r],n,a),await u$(t,uL)}async function dC(e){let{runtime:t,device:r,req:n,logPath:a,appBundleId:i,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let u=s[0]?.trim();!u||nX(u)||await l4(r,"open",[l],n.flags?.out,{...uh(a,n.flags,i,o)})}async function dP(e){var t,r,n;let{req:a,sessionName:i,sessionStore:o,logPath:s,device:l,openTarget:u,openPositionals:d,appName:c,surface:p,appBundleId:f,runtime:m,existingSession:h}=e,w=a.flags?.relaunch===!0,g=h?.trace?.outPath;if(w&&u){let e=f??u;await dL({device:l,closeTarget:e,outFlag:a.flags?.out,context:{...uh(s,a.flags,f??h?.appBundleId,g)}})}await uX({device:l,appId:f,runtime:m});let y=Date.now();await l4(l,"open",d,a.flags?.out,{...uh(s,a.flags,f)}),await dC({runtime:m,device:l,req:a,logPath:s,appBundleId:f,traceLogPath:g,openPositionals:d});let v=u?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:dc,appTarget:u,appBundleId:f}:void 0;if(await u$(l,uC),eW(a.meta?.requestId)){let e=eJ();return uD(e.code,e.message,e.details)}h&&dw(h,"open",h.snapshot);let I=function(e){let{existingSession:t,sessionName:r,device:n,surface:a,appBundleId:i,appName:o,saveScript:s}=e;return t?{...t,device:n,surface:a,appBundleId:i,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:n,createdAt:Date.now(),surface:a,appBundleId:i,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:i,device:l,surface:p,appBundleId:f,appName:c,saveScript:!!a.flags?.saveScript});void 0!==a.runtime&&(t=o,r=i,(n=m)&&(0===dn(n)?t.clearRuntimeHints(r):t.setRuntimeHints(r,n)));let b=function(e){let{sessionName:t,appName:r,appBundleId:n,surface:a,startup:i,device:o,runtime:s,runtimeHintCount:l}=e,u={session:t,surface:a};return r&&(u.appName=r),n&&(u.appBundleId=n),i&&(u.startup=i),s&&l(s)>0&&(u.runtime=s),o&&(u.platform=o.platform,u.target=o.target??"mobile",u.device=o.name,u.id=o.id,u.kind=o.kind,"android"===o.platform&&(u.serial=o.id)),o?.platform==="ios"&&(u.device_udid=o.id,u.ios_simulator_device_set=o.simulatorSetPath??null),{...u,...eh(`Opened: ${r??n??t}`)}}({sessionName:i,appName:c,appBundleId:f,surface:p,startup:v,device:l,runtime:m,runtimeHintCount:dn});return o.recordAction(I,{command:"open",positionals:d,flags:a.flags??{},runtime:void 0!==a.runtime?m:void 0,result:b}),o.set(i,I),{ok:!0,data:b}}async function dR(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e;if(a.has(r)){let e=a.get(r);if(!e)return uD("SESSION_NOT_FOUND",`Session "${r}" not found.`);let i=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(i?e.appName:void 0),l=dD(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return i?dx("open --relaunch requires an app name or an active session app."):dx("Session already active. Close it first or pass a new --session name.");let u=dM({shouldRelaunch:i,openTarget:s,surface:l,device:e.device});if(u)return u;let d=await uU(e.device),c=await dE({req:t,sessionName:r,sessionStore:a,device:d,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await dP({req:t,sessionName:r,sessionStore:a,logPath:n,device:d,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let i=t.flags?.relaunch===!0,o=t.positionals?.[0];if(i&&!o)return dx("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:n}=e;return t?r&&nX(r)?dx("open --relaunch does not support URL targets."):"android"===n&&r&&"binary"===ad(r)?dx(ac(r)):null:null}({shouldRelaunch:i,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await l3(t.flags??{}),u=dD(l,t.flags?.surface,o);if("string"!=typeof u)return u;let d=dM({shouldRelaunch:i,openTarget:o,surface:u,device:l});return d||await tv(dk,l.id,async()=>{let e=a.toArray().find(e=>e.device.id===l.id);if(e)return uD("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name});let i=await dE({req:t,sessionName:r,sessionStore:a,device:l,surface:u,openTarget:o});return"response"===i.type?i.response:await dP({req:t,sessionName:r,sessionStore:a,logPath:n,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:i.details.appBundleId,appName:i.details.appName,runtime:i.details.runtime,surface:u})})}async function dT(e){let t=await T("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function d$(e){let{device:t,shutdownRequested:r}=e;if(r&&(uT(t)||"android"===t.platform&&"emulator"===t.kind))try{return uT(t)?await oS(t):await dT(t)}catch(t){let e=O(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function dF(e){if(await rr(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await oz("dismiss",t).catch(t=>{D({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function dU(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,i=a.get(r);if(!i)return uD("SESSION_NOT_FOUND","No active session");i.appLog&&await no(i.appLog),t.positionals&&t.positionals.length>0&&(("ios"===i.device.platform||"macos"===i.device.platform)&&await dF(i),await l4(i.device,"close",t.positionals,t.flags?.out,{...uh(n,t.flags,i.appBundleId,i.trace?.outPath)}),await u$(i.device,uL)),("ios"===i.device.platform||"macos"===i.device.platform)&&await dF(i),uJ(a.getRuntimeHints(r))&&i.appBundleId&&await uY({device:i.device,appId:i.appBundleId}).catch(()=>{}),a.recordAction(i,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...eh(`Closed: ${r}`)}}),t.flags?.saveScript&&(i.recordSession=!0),a.writeSessionLog(i),await u_(r).catch(()=>{}),a.delete(r);let o=await d$({device:i.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:en({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...eh(`Closed: ${r}`)}}}let dG=["platform","target","device","udid","serial","verbose","out"];function dV(e,t){let r=e??{};for(let e of dG)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let dB={ios:async(e,t,r)=>{let{reinstallIosApp:n}=await Promise.resolve(eT);return await n(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:n}=await Promise.resolve(eC);return await n(e,t,r)}},dj={ios:async(e,t,r)=>{let{installIosApp:n}=await Promise.resolve(eT),a=await n(e,r,{appIdentifierHint:t});return{bundleId:a.bundleId,appName:a.appName,launchTarget:a.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:n}=await Promise.resolve(eC),a=await n(e,r);return{package:a.packageName,appName:a.appName,launchTarget:a.launchTarget}}};async function dq(e){let{req:t,command:r,sessionName:n,sessionStore:a,deployOps:i}=e,o=a.get(n),l=t.flags??{},u=uP(r,o,l);if(u)return u;let d=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!d||!c)return uD("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let p=t.meta?.uploadedArtifactId;try{var f;let e,n=p?np(p,t.meta?.tenantId):rE.expandHome(c);if(!s.existsSync(n))return uD("INVALID_ARGS",`App binary not found: ${n}`);let u=await uF({session:o,flags:l,ensureReady:!1});if(!um(r,u))return uD("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===u.platform){let t=await i.ios(u,d,n),r=t.bundleId;e=r?{app:d,appPath:n,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:n,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await i.android(u,d,n),r=t.package;e=r?{app:d,appPath:n,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:n,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=en(e,(f=e,`Installed: ${f.appName??Q(f)}`));return o&&a.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{p&&nf(p)}}async function dH(e,t,r){let n=e.flags?.batchOnError??"stop";if("stop"!==n)return uD("INVALID_ARGS",`Unsupported batch on-error mode: ${n}.`);let a=e.flags?.batchMaxSteps??eI;if(!Number.isInteger(a)||a<1||a>1e3)return uD("INVALID_ARGS",`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`);try{let n=K(e.flags?.batchSteps,a),i=Date.now(),o=[];for(let a=0;a<n.length;a+=1){let i=n[a],s=await dW(e,t,i,r,a+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${i.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:i.command,positionals:i.positionals,executed:a,total:n.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:n.length,executed:n.length,totalDurationMs:Date.now()-i,results:o}}}catch(t){let e=E(t);return uD(e.code,e.message,e.details)}}async function dW(e,t,r,n,a){let i=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:n,batchMaxSteps:a,...i}=t??{};return dV(e,i)}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await n({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-i;return s.ok?{ok:!0,step:a,result:{step:a,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:a,error:s.error}}async function dz(e){let t,r,n,{deviceName:a,runtime:i,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:u}=e;if("darwin"!==process.platform)throw new k("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let d={simulatorSetPath:o??void 0};if(s){let e=await dJ({deviceName:a,runtime:i,simctlOpts:d});e?(t=e.udid,r=e.runtime,n=!1):(t=(await dK({deviceName:a,runtime:i,simctlOpts:d})).udid,r=await dX(t,d),n=!0)}else t=(await dK({deviceName:a,runtime:i,simctlOpts:d})).udid,r=await dX(t,d),n=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:a,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await u(e),c=!0}return{udid:t,device:a,runtime:r,created:n,booted:c}}async function dJ(e){let{deviceName:t,runtime:r,simctlOpts:n}=e,a=await T("xcrun",e8(["list","devices","-j"],n),{allowFailure:!0,timeoutMs:oo});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let[n,a]of Object.entries(e.devices??{}))if(!r||dY(n).includes(dY(r))){for(let e of a)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:n}}return null}catch{return null}}async function dK(e){let{deviceName:t,runtime:r,simctlOpts:n}=e,a=r?["create",t,t,r]:["create",t,t],i=await T("xcrun",e8(a,n),{allowFailure:!0});if(0!==i.exitCode)throw new k("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(i.stdout??""),stderr:String(i.stderr??""),exitCode:i.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(i.stdout??"").trim();if(!o)throw new k("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(i.stdout??""),stderr:String(i.stderr??"")});return{udid:o}}async function dX(e,t){let r=await T("xcrun",e8(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:oo});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,n]of Object.entries(t.devices??{}))if(n.some(t=>t.udid===e))return r;return""}catch{return""}}function dY(e){return e.toLowerCase().replace(/[._-]/g,"")}async function dZ(e){let{req:t,sessionName:r,sessionStore:n}=e;if("session_list"===t.command)return{ok:!0,data:{sessions:n.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,n=e.runtime,a=e3(e.iosSimulatorDeviceSet);if(!r)return uD("INVALID_ARGS","ensure-simulator requires --device <name>");let i=await dz({deviceName:r,runtime:n,simulatorSetPath:a,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:ug});return{ok:!0,data:{udid:i.udid,device:i.device,runtime:i.runtime,ios_simulator_device_set:a??null,created:i.created,booted:i.booted}}}catch(t){let e=E(t);return uD(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=e5(t.flags?.androidDeviceAllowlist),n=t.flags?.platform,a=tA({simulatorSetPath:e3(t.flags?.iosSimulatorDeviceSet),platform:n,target:t.flags?.target});if("android"===n){let{listAndroidDevices:t}=await Promise.resolve(eL);e.push(...await t({serialAllowlist:r}))}else if("ios"===n||"macos"===n){let{listAppleDevices:t}=await Promise.resolve(eR);e.push(...await t({simulatorSetPath:a}))}else{if("apple"!==n){let{listAndroidDevices:t}=await Promise.resolve(eL);try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await Promise.resolve(eR);try{e.push(...await t({simulatorSetPath:a}))}catch{}}let i="ios"===n||"macos"===n?e.filter(e=>e.platform===n):e,o=(t.flags?.target?i.filter(e=>(e.target??"mobile")===t.flags?.target):i).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=E(t);return uD(e.code,e.message,e.details)}if("apps"===t.command){let e=n.get(r),a=t.flags??{},i=uP(t.command,e,a);if(i)return i;let o=await uF({session:e,flags:a,ensureReady:!0});if(!um("apps",o))return uD("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(tI(o.platform)){let{listIosApps:e}=await Promise.resolve(eT);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(eC);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 dQ(e){let{ensureAndroidEmulatorBooted:t}=await Promise.resolve(eL);return await t(e)}let d0='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',d1='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function d2(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r),i=t.flags??{},o=i.platform;if(!a&&"string"==typeof i?.session&&i.session.trim().length>0)return uD("SESSION_NOT_FOUND","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=uP("appstate",a,i);if(s)return s;let l=(a?.device.platform==="ios"||a?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!uR(e))return!0;let r=e?.platform;return!(r&&!tb(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(i,a);if("ios"===o&&!l)return uD("SESSION_NOT_FOUND",d0);if("macos"===o&&!l)return uD("SESSION_NOT_FOUND",d1);if(l&&a){let e=a.appName??a.appBundleId;if(!a.appName&&!a.appBundleId){if("macos"===a.device.platform&&a.surface&&"app"!==a.surface&&"frontmost-app"!==a.surface)return{ok:!0,data:{platform:a.device.platform,appName:a.surface,appBundleId:a.appBundleId,source:"session",surface:a.surface}};let e="macos"===a.device.platform?"macOS":"iOS";return uD("COMMAND_FAILED",`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`)}return{ok:!0,data:{platform:a.device.platform,appName:e??"unknown",appBundleId:a.appBundleId,source:"session",surface:a.surface??"app",..."ios"===a.device.platform?{device_udid:a.device.id,ios_simulator_device_set:a.device.simulatorSetPath??null}:{}}}}let u=await uF({session:a,flags:i,ensureReady:!0});if("ios"===u.platform)return uD("SESSION_NOT_FOUND",d0);if("macos"===u.platform)return uD("SESSION_NOT_FOUND",d1);let{getAndroidAppState:d}=await Promise.resolve(eC),c=await d(u);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function d3(e){let{req:t,sessionName:r,sessionStore:n}=e;if("boot"===t.command){let e,a=n.get(r),i=t.flags??{},o=uP(t.command,a,i);if(o)return o;let s="android"===(i.platform??a?.device.platform),l=!0===i.headless;if(l&&!s)return uD("INVALID_ARGS","boot --headless is supported only for Android emulators.");let u=uG({flags:i,sessionDevice:a?.device}),d=s&&!!u,c=!1;try{e=await uF({session:a,flags:i,ensureReady:!1})}catch(r){let t=E(r);if(s&&l&&!u&&"DEVICE_NOT_FOUND"===t.code)return uD("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!d||"DEVICE_NOT_FOUND"!==t.code||!u)throw r;e=await dQ({avdName:u,serial:i.serial,headless:l}),c=!0}if(i.target&&(e.target??"mobile")!==i.target)return uD("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${i.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return uD("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=uG({flags:i,sessionDevice:a?.device,resolvedDevice:e});if(!t)return uD("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await dQ({avdName:t,serial:i.serial,headless:!0})}await ug(e)}else("android"!==e.platform||!0!==e.booted)&&await ug(e);return um("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:uD("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await d2({req:t,sessionName:r,sessionStore:n}):null}function d4(e){return Math.round(10*e)/10}let d5="adb-shell-dumpsys-cpuinfo",d8="adb-shell-dumpsys-meminfo";async function d6(e,t){try{let r=await T("adb",nW(e,["shell","dumpsys","cpuinfo"]),{timeoutMs:15e3});return function(e,t,r){let n=new Set,a=0;for(let r of e.split("\n")){var i,o;let e=r.trim();if(0===e.length)continue;let s=e.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!s)continue;let l=Number(s[1]),u=s[2];Number.isFinite(l)&&(i=u,o=t,i===o||i.startsWith(`${o}:`))&&(a+=l,n.add(u))}return{usagePercent:d4(a),measuredAt:r,method:d5,matchedProcesses:[...n]}}(r.stdout,t,new Date().toISOString())}catch(e){throw d7("cpu",t,e)}}async function d9(e,t){try{let r=await T("adb",nW(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new k("COMMAND_FAILED",`Android meminfo did not find a running process for ${t}`,{metric:"memory",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf."});let n=ce(e,"TOTAL PSS")??function(e){for(let t of e.split("\n")){let e=t.trim();if(!/^TOTAL\b(?!\s+PSS:)/.test(e))continue;let r=e.split(/\s+/).slice(1).find(e=>null!==ct(e));if(!r)break;return ct(r)??void 0}}(e);if(void 0===n)throw new k("COMMAND_FAILED",`Failed to parse Android meminfo output for ${t}`,{metric:"memory",package:t,hint:"Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging."});return{totalPssKb:n,totalRssKb:ce(e,"TOTAL RSS"),measuredAt:r,method:d8}}(r.stdout,t,new Date().toISOString())}catch(e){throw d7("memory",t,e)}}function d7(e,t,r){return r instanceof k&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new k(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof k?r:new k("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function ce(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(n)return ct(n[1])??void 0}function ct(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let cr="ps-process-snapshot",cn="ps-process-snapshot",ca="xctrace-activity-monitor",ci="xctrace-activity-monitor";async function co(e,t){if("ios"===e.platform&&"device"===e.kind)return await cu(e,t);let r=await cl(e,t),n=await ch(e,r);if(0===n.length)throw new k("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,hint:"Run open <app> for this session again to ensure the Apple app is active, then retry perf."});let a=new Date().toISOString(),i=rp(n.map(e=>p.basename(cw(e.command))));return cg({usagePercent:n.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:n.reduce((e,t)=>e+t.rssKb,0),measuredAt:a,matchedProcesses:i,cpuMethod:cr,memoryMethod:cn})}async function cs(e){let t=tD(e),r=cy(t,e=>"schema"===e.name&&"activity-monitor-process-live"===e.attributes.name);if(!r)throw new k("COMMAND_FAILED","Failed to parse xctrace activity-monitor-process-live schema");let n=r.children.filter(e=>"col"===e.name).map(e=>{let t;return t=e.children.find(e=>"mnemonic"===e.name),t?.text??null??""}),a=n.indexOf("pid"),i=n.indexOf("process"),o=n.indexOf("cpu-total"),s=n.indexOf("memory-real");if(a<0||i<0||o<0||s<0)throw new k("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let l=function e(t,r){let n=[];for(let a of t)r(a)&&n.push(a),n.push(...e(a.children,r));return n}(t,e=>"row"===e.name),u=[],d=new Map;for(let e of l){var c,p;let t=e.children;if(0===t.length)continue;for(let e of t){let t=cy(e.children,e=>"pid"===e.name&&"string"==typeof e.attributes.id);if(t?.attributes.id){let e=Number(t.text);d.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&d.set(e.attributes.id,{numberValue:cv(e),processName:cb(e)})}let r=cI(t[a],d),n=(c=t[i],p=d,c?c.attributes.ref?p.get(c.attributes.ref)?.processName??null:cb(c):null);null!==r&&Number.isFinite(r)&&n&&u.push({pid:r,processName:n,cpuTimeNs:cI(t[o],d),residentMemoryBytes:cI(t[s],d)})}return u}async function cl(e,t){let r="macos"===e.platform?await cf(t):await cm(e,t),n="macos"===e.platform?p.join(r,"Contents","Info.plist"):p.join(r,"Info.plist"),a=await o_(n,"CFBundleExecutable");if(!a)throw new k("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:a,executablePath:"macos"===e.platform?p.join(r,"Contents","MacOS",a):void 0}}async function cu(e,t){let r=await cd(e,t),n=await cc(e,t),a=await cc(e,t),i=cp(await cs(n.xml),r,t,e),o=cp(await cs(a.xml),r,t,e),s=a.capturedAtMs-n.capturedAtMs;if(s<=0)throw new k("COMMAND_FAILED",`Invalid Activity Monitor sample window for ${t}`,{appBundleId:t,deviceId:e.id});if(null===i.cpuTimeNs||null===o.cpuTimeNs||null===o.residentMemoryBytes)throw new k("COMMAND_FAILED",`Incomplete Activity Monitor sample for ${t}`,{appBundleId:t,deviceId:e.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});return cg({usagePercent:Math.max(0,o.cpuTimeNs-i.cpuTimeNs)/(1e6*s)*100,residentMemoryKb:o.residentMemoryBytes/1024,measuredAt:new Date(a.capturedAtMs).toISOString(),matchedProcesses:o.matchedProcesses,cpuMethod:ca,memoryMethod:ci})}async function cd(e,t){let r=(await om(e,"all")).find(e=>e.bundleId===t);if(!r)throw new k("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new k("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let n=r.url.replace(/\/$/,""),a=w(n),i=(await oh(e)).filter(e=>e.executable.startsWith(`${n}/`));if(0===i.length)throw new k("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,deviceId:e.id,appBundlePath:a,hint:"Run open <app> for this session again to ensure the iOS app is active, then retry perf."});return i}async function cc(e,t){let r=await u.mkdtemp(p.join(d.tmpdir(),"agent-device-ios-perf-")),n=p.join(r,"sample.trace"),a=p.join(r,"activity-monitor-process-live.xml");try{let r=["xctrace","record","--template","Activity Monitor","--device",e.id,"--all-processes","--time-limit","1s","--output",n,"--quiet","--no-prompt"],i=await T("xcrun",r,{allowFailure:!0,timeoutMs:6e4}),o=Date.now();if(0!==i.exitCode)throw new k("COMMAND_FAILED",`Failed to record iOS device Activity Monitor sample for ${t}`,{cmd:"xcrun",args:r,exitCode:i.exitCode,stdout:i.stdout,stderr:i.stderr,appBundleId:t,deviceId:e.id,hint:cA(i.stdout,i.stderr)});let s=["xctrace","export","--input",n,"--xpath",'/trace-toc/run/data/table[@schema="activity-monitor-process-live"]',"--output",a],l=await T("xcrun",s,{allowFailure:!0,timeoutMs:15e3});if(0!==l.exitCode)throw new k("COMMAND_FAILED",`Failed to export iOS device perf sample for ${t}`,{cmd:"xcrun",args:s,exitCode:l.exitCode,stdout:l.stdout,stderr:l.stderr,appBundleId:t,deviceId:e.id,hint:cA(l.stdout,l.stderr)});return{capturedAtMs:o,xml:await u.readFile(a,"utf8")}}finally{await u.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function cp(e,t,r,n){let a=new Set(t.map(e=>e.pid)),i=new Set(t.map(e=>p.basename(w(e.executable)))),o=e.filter(e=>a.has(e.pid)||i.has(e.processName));if(0===o.length)throw new k("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:n.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let s=new Map;for(let e of o){let t=s.get(e.pid);if(!t){s.set(e.pid,e);continue}s.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:cS(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:cS(t.residentMemoryBytes,e.residentMemoryBytes)})}let l=[...s.values()],u=l.map(e=>e.cpuTimeNs).filter(e=>null!==e),d=l.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:u.length>0?u.reduce((e,t)=>e+t,0):null,residentMemoryBytes:d.length>0?d.reduce((e,t)=>e+t,0):null,matchedProcesses:rp(l.map(e=>e.processName))}}async function cf(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await T("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new k("COMMAND_FAILED",`Failed to resolve macOS app bundle for ${e}`,{appBundleId:e,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let n=r.stdout.split("\n").map(e=>e.trim()).find(e=>e.endsWith(".app"));if(!n)throw new k("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return n}async function cm(e,t){let r=e6(e,["get_app_container",e.id,t,"app"]),n=await T("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==n.exitCode)throw new k("COMMAND_FAILED",`Failed to resolve iOS simulator app container for ${t}`,{appBundleId:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,hint:"Ensure the iOS simulator app is installed and booted, then retry perf."});let a=n.stdout.trim();if(0===a.length)throw new k("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return a}async function ch(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:e6(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let n=e.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!n)continue;let a=Number(n[1]),i=Number(n[2]),o=Number(n[3]),s=n[4].trim();Number.isFinite(a)&&Number.isFinite(i)&&Number.isFinite(o)&&t.push({pid:a,cpuPercent:i,rssKb:o,command:s})}return t})((await T("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,n;let a;return r=e.command,n=t,a=cw(r),!!(n.executablePath&&(a===n.executablePath||r.startsWith(`${n.executablePath} `)))||p.basename(a)===n.executableName})}function cw(e){let[t=""]=e.trim().split(/\s+/,1);return t}function cg(e){return{cpu:{usagePercent:d4(e.usagePercent),measuredAt:e.measuredAt,method:e.cpuMethod,matchedProcesses:e.matchedProcesses},memory:{residentMemoryKb:Math.round(e.residentMemoryKb),measuredAt:e.measuredAt,method:e.memoryMethod,matchedProcesses:e.matchedProcesses}}}function cy(e,t){for(let r of e){if(t(r))return r;let e=cy(r.children,t);if(e)return e}}function cv(e){if(!e||e.children.some(e=>"sentinel"===e.name)||!e.text)return null;let t=Number(e.text);return Number.isFinite(t)?t:null}function cI(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:cv(e):null}function cb(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function cA(e,t){let r=og(e,t);if(r)return r;let n=`${e}
|
|
40
|
-
${t}`.toLowerCase();return n.includes("no device matched")||n.includes("failed to find device")?ow:n.includes("timed out")?"Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.":"Ensure the iOS device is unlocked, trusted, visible to xctrace, and the target app stays active while perf samples it."}function cS(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function cN(e){var t;let r=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===dc&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:dc,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(e.actions),n=r.at(-1),a=n?{available:!0,lastDurationMs:n.durationMs,lastMeasuredAt:n.measuredAt,method:dc,sampleCount:r.length,samples:r}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:dc},i={session:e.name,platform:e.device.platform,device:e.device.name,deviceId:e.device.id,metrics:{startup:a,fps:{available:!1,reason:dp},memory:{available:!1,reason:dp},cpu:{available:!1,reason:dp}},sampling:{startup:{method:dc,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"},...function(e){if("android"===e.device.platform)return{memory:{method:d8,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:d5,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"}};var t=e.device;if("ios"===t.platform&&"device"===t.kind)return{memory:{method:ci,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:ca,description:"Recent CPU usage snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"percent"}};let r="macos"===t.platform?"host ps for the running macOS app executable resolved from the bundle ID.":"xcrun simctl spawn ps for the running iOS simulator app executable resolved from the bundle ID.";return{memory:{method:cn,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:cr,description:`Recent CPU usage snapshot from ${r}`,unit:"percent"}}}(e)}};if("android"!==(t=e).device.platform&&"ios"!==t.device.platform&&"macos"!==t.device.platform)return i;if(!e.appBundleId){let t="android"===e.device.platform?"No Android app package is associated with this session. Run open <app> first.":"No Apple app bundle ID is associated with this session. Run open <app> first.";return i.metrics.memory={available:!1,reason:t},i.metrics.cpu={available:!1,reason:t},i}let[o,s]=await c_(e);return i.metrics.memory=cx(o),i.metrics.cpu=cx(s),i}async function c_(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,n]=await Promise.allSettled([d9(e.device,t),d6(e.device,t)]);return[r,n]}try{let r=await co(e.device,t);return[{status:"fulfilled",value:r.memory},{status:"fulfilled",value:r.cpu}]}catch(e){return[{status:"rejected",reason:e},{status:"rejected",reason:e}]}}function cx(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=O(e.reason);return{available:!1,reason:t.message,error:t}}let cD=["path","start","stop","doctor","mark","clear"],cM=`logs requires ${cD.slice(0,-1).join(", ")}, or ${cD.at(-1)}`,cE=["dump","log"],cO=`network requires ${cE.join(" or ")}`,ck=["summary","headers","body","all"],cL=`network include mode must be one of: ${ck.join(", ")}`;async function cC(e){let{req:t}=e;return"perf"===t.command?cP(e):"logs"===t.command?cR(e):"network"===t.command?cG(e):null}async function cP(e){let{sessionName:t,sessionStore:r}=e,n=r.get(t);if(!n)return uD("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await cN(n)}}catch(e){return{ok:!1,error:O(e)}}}async function cR(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(!a)return uD("SESSION_NOT_FOUND","logs requires an active session");if(!um("logs",a.device))return uD("UNSUPPORTED_OPERATION","logs is not supported on this device");let i=(t.positionals?.[0]??"path").toLowerCase(),o=!!t.flags?.restart;return cD.includes(i)?o&&"clear"!==i?uD("INVALID_ARGS","logs --restart is only supported with logs clear"):"path"===i?function(e,t,r){let n=r.resolveAppLogPath(t),a=function(e){if(!s.existsSync(e))return{exists:!1,sizeBytes:0};let t=s.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(n);return{ok:!0,data:{path:n,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android",sizeBytes: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>'}}}(a,r,n):"doctor"===i?cT(a,r,n):"mark"===i?function(e,t,r){let n,a=e.positionals?.slice(1).join(" ")??"",i=r.resolveAppLogPath(t);return nt(i),n=`[agent-device][mark][${new Date().toISOString()}] ${a.trim()||"marker"}
|
|
41
|
-
`,s.appendFileSync(i,n,"utf8"),{ok:!0,data:{path:i,marked:!0}}}(t,r,n):"clear"===i?c$(a,r,n,o):"start"===i?cF(a,r,n):"stop"===i?cU(a,r,n):uD("INVALID_ARGS",cM):uD("INVALID_ARGS",cM)}async function cT(e,t,r){let n=r.resolveAppLogPath(t),a=await ns(e.device,e.appBundleId);return{ok:!0,data:{path:n,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:a.checks,notes:a.notes}}}async function c$(e,t,r,n){if(e.appLog&&!n)return uD("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(n&&!e.appBundleId)return uD("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let a=r.resolveAppLogPath(t);if(!n)return{ok:!0,data:nl(a)};e.appLog&&await no(e.appLog);let i=nl(a),o=r.resolveAppLogPidPath(t);try{let n=await na(e.device,e.appBundleId,a,o);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:a,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{...i,restarted:!0}}}catch(n){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:O(n)}}}async function cF(e,t,r){if(e.appLog)return uD("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return uD("INVALID_ARGS","logs start requires an app session; run open <app> first");let n=r.resolveAppLogPath(t),a=r.resolveAppLogPidPath(t);try{let i=await na(e.device,e.appBundleId,n,a);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:i.backend,outPath:n,startedAt:i.startedAt,getState:i.getState,stop:i.stop,wait:i.wait}}),{ok:!0,data:{path:n,started:!0}}}catch(e){return{ok:!1,error:O(e)}}}async function cU(e,t,r){if(!e.appLog)return uD("INVALID_ARGS","no app log stream active");let n=e.appLog.outPath;return await no(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:n,stopped:!0}}}async function cG(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(!a)return uD("SESSION_NOT_FOUND","network requires an active session");if(!um("network",a.device))return uD("UNSUPPORTED_OPERATION","network is not supported on this device");let i=(t.positionals?.[0]??"dump").toLowerCase();if(!cE.includes(i))return uD("INVALID_ARGS",cO);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return uD("INVALID_ARGS","network dump limit must be an integer in range 1..200");let s=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return uD("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let n=(r??t??"summary").toLowerCase();return ck.includes(n)?{ok:!0,include:n}:uD("INVALID_ARGS",cL)}(t);if(!s.ok)return s;let{include:l}=s,u=await nr({device:a.device,appBundleId:a.appBundleId,appLogState:a.appLog?.getState(),appLogStartedAt:a.appLog?.startedAt,appLogPath:n.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...u.dump,active:!!a.appLog,state:a.appLog?.getState()??"inactive",backend:u.backend,notes:u.notes}}}let cV=new Set(["ios","android","macos","linux"]);function cB(e,t,r){let n=e[t];if(void 0!==n)throw new k("INVALID_ARGS",n===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(n)} vs ${String(r)}.`);e[t]=r}function cj(e){return!!e&&!Number.isNaN(Number(e))}let cq=/[*?[\]{}]/;async function cH(e){let t,{filePath:r,sessionName:n,requestId:a,timeoutMs:i,platform:o,runReplay:s,cleanupSession:l}=e;ej(a);let u=new Set,d=!1,c=s({filePath:r,sessionName:n,platform:o,requestId:a,artifactPaths:u}).catch(e=>{let t=E(e);return uD(t.code,t.message)}).finally(()=>{eH(a)});try{return"number"==typeof i?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{d=!0,eq(a),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(i,[...u]))},i)})]):await c}finally{t&&clearTimeout(t),d&&(await cW(c)||D({level:"warn",phase:"test_timeout_cleanup_race",data:{session:n,requestId:a,graceMs:2e3}}));try{await l(n)}catch(e){D({level:"warn",phase:"test_cleanup_failed",data:{session:n,error:E(e).message}})}}}async function cW(e){return await Promise.race([e.then(()=>!0),N(2e3).then(()=>!1)])}async function cz(e){let{req:t,sessionName:r,runReplay:n,cleanupSession:a}=e;if((t.positionals?.length??0)===0)return uD("INVALID_ARGS","test requires at least one path or glob");try{var i,o,l,u,d,c;let e,f,m,h,w,g=function(e){let{inputs:t,cwd:r,platformFilter:n}=e,a=r??process.cwd(),i=[...new Set(t.flatMap(e=>(function(e,t){var r,n;let a=rE.expandHome(e,t);if(s.existsSync(a)){let t=s.statSync(a);if(t.isDirectory())return s.globSync("**/*.ad",{cwd:a}).map(e=>p.join(a,e));if(t.isFile()){if(".ad"!==p.extname(a))throw new k("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[a]}return[]}if(r=e,!cq.test(r)&&(n=a,!cq.test(n)))throw new k("INVALID_ARGS",`test input not found: ${e}`);let i=p.isAbsolute(a)?a:e;return s.globSync(i,{cwd:p.isAbsolute(a)?void 0:t}).map(e=>p.isAbsolute(e)?e:p.resolve(t,e)).filter(e=>".ad"===p.extname(e)&&function(e){try{return s.statSync(e).isFile()}catch{return!1}}(e))})(e,a)))].map(e=>p.normalize(e)).sort((e,t)=>e.localeCompare(t)),o=[];for(let e of i){var l,u;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 n=t.match(/(?:^|\s)platform=([^\s]+)/);if(n){let e=n[1];e&&cV.has(e)&&cB(r,"platform",e)}let a=t.match(/(?:^|\s)timeout=(\d+)/);if(a){let e=Number(a[1]);Number.isFinite(e)&&e>=1&&cB(r,"timeoutMs",Math.floor(e))}let i=t.match(/(?:^|\s)retries=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=0&&cB(r,"retries",Math.floor(e))}}return r}(s.readFileSync(e,"utf8"));if(!n){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 ${n}`});continue}l=n,u=t.platform,("apple"===l?"apple"===u||"ios"===u||"macos"===u:u===l)&&o.push({kind:"run",path:e,metadata:t})}if(0===o.filter(e=>"run"===e.kind).length){let e=n?` for --platform ${n}`:"";throw new k("INVALID_ARGS",`No .ad tests matched${e}.`)}return o}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),y=(i=t.meta?.requestId,(i?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),v=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:n}=e,a=rE.expandHome(t??".agent-device/test-artifacts",r);return p.join(a,n)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),I=[],b=Date.now(),A=0;for(let e of g){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}A+=1;let i=await cJ({entry:e,sessionName:r,suiteInvocationId:y,caseIndex:A-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(o=t.flags?.timeoutMs,l=e.metadata.timeoutMs,"number"==typeof o?o:l),suiteArtifactsDir:v,runReplay:n,cleanupSession:a});if(I.push(i),t.flags?.failFast===!0)break}let S=(u=g.length,d=I,c=Date.now()-b,e=d.filter(e=>"passed"===e.status).length,m=(f=d.filter(e=>"failed"===e.status)).length,h=d.filter(e=>"skipped"===e.status).length,w=e+m,{total:u,executed:w,passed:e,failed:m,skipped:h,notRun:Math.max(0,u-w-h),durationMs:c,failures:f,tests:d});return{ok:!0,data:S}}catch(t){let e=E(t);return uD(e.code,e.message)}}async function cJ(e){var t,r;let n,a,{entry:i,sessionName:o,suiteInvocationId:l,caseIndex:u,cwd:d,requestId:c,retries:f,timeoutMs:m,suiteArtifactsDir:h,runReplay:w,cleanupSession:g}=e,y=Date.now(),v=p.join(h,(t=i.path,(0===(a=d?p.relative(d,t):p.basename(t)).length||a.startsWith("..")?p.basename(t):a).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",b=0;for(let e=0;e<=f;e+=1){b=e+1;let t=function(e,t,r,n,a=0){let i=p.basename(r,p.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${n+1}${i?`-${i}`:""}:attempt-${a+1}`}(o,l,i.path,u,e),a=p.join(v,`attempt-${b}`);r=i.path,s.mkdirSync(a,{recursive:!0}),s.copyFileSync(r,p.join(a,"replay.ad"));let d=function(e){let{requestId:t,suiteInvocationId:r,filePath:n,caseIndex:a,attemptIndex:i}=e;return eB(`${t??r}:test:${a+1}:${p.basename(n)}:attempt:${i+1}`,r)}({requestId:c,suiteInvocationId:l,filePath:i.path,caseIndex:u,attemptIndex:e}),h=await cH({filePath:i.path,sessionName:t,requestId:d,timeoutMs:m,platform:i.metadata.platform,runReplay:w,cleanupSession:g});if(!function(e){let{response:t,filePath:r,sessionName:n,attempts:a,maxAttempts:i,attemptArtifactsDir:o}=e,l=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||l.push(t.error.logPath);let u=function(e,t){let r=[],n=new Map;for(let a of e){if(!function(e){try{return s.statSync(e).isFile()}catch{return!1}}(a))continue;let e=function(e,t){let r=p.extname(e),n=r?e.slice(0,-r.length):e,a=t.get(e)??0;return(t.set(e,a+1),0===a)?e:`${n}-${a+1}${r}`}(p.basename(a),n),i=p.join(t,e);p.resolve(a)!==p.resolve(i)&&s.copyFileSync(a,i),r.push(i)}return r}(l,o),d=[`file: ${r}`,`session: ${n}`,`attempt: ${a}/${i}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;d.push(`replayed: ${e}`,`healed: ${r}`)}else d.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&d.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&d.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&d.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&d.push("timeoutMode: cooperative");u.length>0&&d.push(`copiedArtifacts: ${u.map(e=>p.basename(e)).join(", ")}`);let c=p.join(o,"result.txt"),f=`${d.join("\n")}
|
|
42
|
-
`;s.writeFileSync(c,f),t.ok||s.writeFileSync(p.join(o,"failure.txt"),f)}({response:h,filePath:i.path,sessionName:t,attempts:b,maxAttempts:f+1,attemptArtifactsDir:a}),n=h,I=t,h.ok)break}let A=Date.now()-y;if(n?.ok)return{file:i.path,session:I,status:"passed",durationMs:A,attempts:b,artifactsDir:v,replayed:"number"==typeof n.data?.replayed?n.data.replayed:0,healed:"number"==typeof n.data?.healed?n.data.healed:0};let S=n?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:n?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:i.path,session:I,status:"failed",durationMs:A,attempts:b,artifactsDir:v,error:S}}function cK(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),n=(e.value??"").toLowerCase(),a=(e.identifier??"").toLowerCase();return t.includes(r)||n.includes(r)||a.includes(r)})??null}function cX(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&&cY(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,n=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||!cY(t))continue;let a=Math.abs(e.rect.y+e.rect.height/2-r);(!n||a<n.distance)&&(n={label:t,distance:a})}return n?.label}(e,t)??(r&&cY(r)?r:void 0)}function cY(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function cZ(e){let t=[],r=[];for(let n of e){let e=n.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let a=cQ(n.type??""),i=[n.label,n.value,n.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!i&&cY(i);if(("group"===a||"ioscontentgroup"===a)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...n,depth:s})}return r}function cQ(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 c0(e,t){let r=cQ(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 c1(e,t){if(t.hittable)return t;let r=t,n=new Set;for(;void 0!==r.parentIndex&&!n.has(r.ref);){n.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}function c2(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let c3=new Set(["id","role","text","label","value","appname","windowtitle"]),c4=new Set(["visible","hidden","editable","selected","enabled","hittable"]),c5=new Set([...c3,...c4]);function c8(e){let t=e.trim();if(!t)throw new k("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",n=null;for(let a=0;a<e.length;a+=1){let i=e[a];if(('"'===i||"'"===i)&&!pn(e,a)){n=pt(n,i),r+=i;continue}if(!n&&"|"===i&&"|"===e[a+1]){let n=r.trim();if(!n)throw new k("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(n),r="",a+=1;continue}r+=i}let a=r.trim();if(!a)throw new k("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(a),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="",n=null;for(let a=0;a<e.length;a+=1){let i=e[a];if(('"'===i||"'"===i)&&!pn(e,a)){n=pt(n,i),r+=i;continue}if(!n&&/\s/.test(i)){r.trim()&&t.push(r.trim()),r="";continue}r+=i}if(n)throw new k("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim()&&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(pe)}})(e))}}function c6(e){try{return c8(e)}catch{return null}}function c9(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,n=0,a=[];for(;n<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 c5.has(e)}return c5.has(t.toLowerCase())}(e[n]);){n+=1;let t=e.slice(0,n).join(" ").trim();t&&c6(t)&&a.push(n)}if(0===a.length)return null;let i=a[a.length-1];if(r){for(let t=a.length-1;t>=0;t-=1)if(a[t]<e.length){i=a[t];break}}let o=e.slice(0,i).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(i)}:null}function c7(e){let t=e[0]??"",r=c9(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function pe(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(!c4.has(r))throw new k("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let n=t.slice(0,r).trim().toLowerCase(),a=t.slice(r+1).trim();if(!c5.has(n))throw new k("INVALID_ARGS",`Unknown selector key: ${n}`);if(!a)throw new k("INVALID_ARGS",`Missing selector value for key: ${n}`);if(c4.has(n)){let e,t="true"===(e=pr(a).toLowerCase())||"false"!==e&&null;if(null===t)throw new k("INVALID_ARGS",`Invalid boolean value for ${n}: ${a}`);return{key:n,value:t}}return{key:n,value:pr(a)}}function pt(e,t){return e?e===t?null:e:t}function pr(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function pn(e,t){let r=0;for(let n=t-1;n>=0&&"\\"===e[n];n-=1)r+=1;return r%2==1}function pa(e,t,r,n={}){let a=po(r);if(!a)return{matches:[],score:0};let i=0,o=[];for(let r of e){if(n.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 pi(e.label,r);case"value":return pi(e.value,r);case"id":return pi(e.identifier,r);default:return Math.max(pi(e.label,r),pi(e.value,r),pi(e.identifier,r))}}(r,t,a);if(!(e<=0)){if(e>i){i=e,o.length=0,o.push(r);continue}e===i&&o.push(r)}}return{matches:o,score:i}}function pi(e,t){let r=po(e??"");return r?r===t?2:+!!r.includes(t):0}function po(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function ps(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return pd(e.identifier,String(t.value));case"role":return pd(cQ(e.type??""),String(t.value));case"label":return pd(e.label,String(t.value));case"value":return pd(e.value,String(t.value));case"text":return pd(c2(e),String(t.value));case"appname":return pd(e.appName,String(t.value));case"windowtitle":return pd(e.windowTitle,String(t.value));case"visible":return pl(e)===!!t.value;case"hidden":return!pl(e)==!!t.value;case"editable":return pu(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 pl(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function pu(e,t){return c0(e.type??"",t)&&!1!==e.enabled}function pd(e,t){return po(e??"")===po(t)}function pc(e,t,r){let n=r.requireRect??!1,a=r.requireUnique??!0,i=[];for(let o=0;o<t.selectors.length;o+=1){let s=t.selectors[o],l=function(e,t,r,n){let a=0,i=null,o=null,s=!1;for(let l of e){if(n&&!l.rect||!ps(l,t,r))continue;if(a+=1,i??=l,!o){o=l;continue}let e=function(e,t){let r=e.depth??0,n=t.depth??0;if(r!==n)return r>n?1:-1;let a=pm(e),i=pm(t);return a!==i?a<i?1:-1:0}(l,o);e>0?(o=l,s=!1):0===e&&(s=!0)}return{count:a,firstNode:i,disambiguated:s?null:o}}(e,s,r.platform,n);if(i.push({selector:s.raw,matches:l.count}),0!==l.count&&l.firstNode){if(a&&1!==l.count){if(!r.disambiguateAmbiguous||!l.disambiguated)continue;return{node:l.disambiguated,selector:s,selectorIndex:o,matches:l.count,diagnostics:i}}return{node:l.firstNode,selector:s,selectorIndex:o,matches:l.count,diagnostics:i}}}return null}function pp(e,t,r){let n=r.requireRect??!1,a=[];for(let i=0;i<t.selectors.length;i+=1){let o=t.selectors[i],s=function(e,t,r,n){let a=0;for(let i of e)(!n||i.rect)&&ps(i,t,r)&&(a+=1);return a}(e,o,r.platform,n);if(a.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:i,selector:o,matches:s,diagnostics:a}}return null}function pf(e,t,r){if(0===t.length)return`Selector did not match: ${e.raw}`;let n=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return r.unique??!0?`Selector did not resolve uniquely (${n})`:`Selector did not match (${n})`}function pm(e){return e.rect?e.rect.width*e.rect.height:1/0}function ph(e,t,r={}){let n=[],a=cQ(e.type??""),i=pg(e.identifier),o=pg(e.label),s=pg(e.value),l=pg(c2(e)),u="fill"===r.action;i&&n.push(`id=${pw(i)}`),a&&o&&n.push(u?`role=${pw(a)} label=${pw(o)} editable=true`:`role=${pw(a)} label=${pw(o)}`),o&&n.push(u?`label=${pw(o)} editable=true`:`label=${pw(o)}`),s&&n.push(u?`value=${pw(s)} editable=true`:`value=${pw(s)}`),l&&l!==o&&l!==s&&n.push(u?`text=${pw(l)} editable=true`:`text=${pw(l)}`),a&&u&&!n.some(e=>e.includes("editable=true"))&&n.push(`role=${pw(a)} editable=true`);let d=rp(n);return 0===d.length&&a&&d.push(u?`role=${pw(a)} editable=true`:`role=${pw(a)}`),0===d.length&&pl(e)&&d.push("visible=true"),d}function pw(e){return JSON.stringify(e)}function pg(e){if(!e)return null;let t=e.trim();return t||null}function py(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),n=c9(r?e.slice(0,-1):e.slice());return!n||n.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:n.selectorExpression,selectorTimeout:r?t:null}}async function pv(e){let{action:t,sessionName:r,logPath:n,sessionStore:a}=e;if(!(rg(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let i=a.get(r);if(!i)return null;let o=(function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),rg(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}=c7(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=py(e.positionals??[]);r&&t.push(r)}return rp(t).filter(e=>e.trim().length>0)})(t).map(e=>c6(e)).filter(e=>null!==e);if(0===o.length)return null;let s=rg(t.command)||"fill"===t.command,l=rg(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await pI(i,t,n,s,a);for(let e of o){let r=pc(u.nodes,e,{platform:i.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let n=ph(r.node,i.device.platform,{action:rg(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(rg(t.command))return{...t,positionals:[n]};if("fill"===t.command){let e=rc(t);if(!e)continue;return{...t,positionals:[n,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,n]}}if("is"===t.command){let{predicate:e,split:r}=c7(t.positionals);if(!e)continue;let a=r?.rest.join(" ").trim()??"",i=[e,n];return"text"===e&&a.length>0&&i.push(a),{...t,positionals:i}}if("wait"===t.command){let{selectorTimeout:e}=py(t.positionals??[]),r=[n];return e&&r.push(e),{...t,positionals:r}}}return null}async function pI(e,t,r,n,a){let i=await l4(e.device,"snapshot",[],t.flags?.out,{...uh(r,{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n},e.appBundleId,e.trace?.outPath)}),o=i?.nodes??[],s={nodes:eO(t.flags?.snapshotRaw?o:cZ(o)),truncated:i?.truncated,createdAt:Date.now(),backend:i?.backend};return e.snapshot=s,a.set(e.name,e),s}async function pb(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e,o=t.positionals?.[0];if(!o)return uD("INVALID_ARGS","replay requires a path");let l="",u=new Set;try{l=rE.expandHome(o,t.meta?.cwd);let e=s.readFileSync(l,"utf8"),d=e.trimStart()[0];if("{"===d||"["===d)return uD("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let c=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let n=r+1,a=!1;for(;n<e.length;){let t=e[n];if('"'===t&&!a)break;a="\\"===t&&!a,"\\"!==t&&(a=!1),n+=1}if(n>=e.length)throw new k("INVALID_ARGS",`Invalid replay script line: ${e}`);let i=e.slice(r,n+1);t.push(JSON.parse(i)),r=n+1;continue}let n=r;for(;n<e.length&&!/\s/.test(e[n]);)n+=1;t.push(e.slice(r,n)),r=n}return t}(t);if(0===r.length)return null;let[n,...a]=r;if("context"===n)return null;let i={ts:Date.now(),command:n,positionals:[],flags:{}};if("snapshot"===n){i.positionals=[];for(let e=0;e<a.length;e+=1){let t=a[e];if("-i"===t){i.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){i.flags.snapshotCompact=!0;continue}if("--raw"===t){i.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<a.length){let t=Number(a[e+1]);Number.isFinite(t)&&t>=0&&(i.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<a.length){i.flags.snapshotScope=a[e+1],e+=1;continue}if("--backend"===t&&e+1<a.length){e+=1;continue}}return i}if("open"===n){let e=function(e){var t;let r=[],n={};for(let t of e){if("--relaunch"===t){n.relaunch=!0;continue}r.push(t)}let a=rx(r);return{positionals:a.positionals,flags:n,runtime:(t=a.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?a.flags:void 0}}(a);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i.runtime=e.runtime,i}if("runtime"===n){let e=rx(a);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i}if(rg(n)){let e=r_(n,a);if(Object.assign(i.flags,e.flags),0===e.positionals.length)return i;let t=e.positionals[0];if(t.startsWith("@"))return i.positionals=[t],e.positionals[1]&&(i.result={refLabel:e.positionals[1]}),i;let r=e.positionals[0],o=e.positionals[1];return cj(r)&&cj(o)&&e.positionals.length>=2?i.positionals=[r,o]:i.positionals=[e.positionals.join(" ")],i}if("fill"===n){let e=r_(n,a);if(Object.assign(i.flags,e.flags),e.positionals.length<2)return i.positionals=e.positionals,i;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(i.positionals=[t,e.positionals.slice(2).join(" ")],i.result={refLabel:e.positionals[1]}):i.positionals=[t,e.positionals[1]],i):(i.positionals=[t,e.positionals.slice(1).join(" ")],i)}if("get"===n){if(a.length<2)return i.positionals=a,i;let e=a[0],t=a[1];return t.startsWith("@")?(i.positionals=[e,t],a[2]&&(i.result={refLabel:a[2]})):i.positionals=[e,a.slice(1).join(" ")],i}if("swipe"===n||"type"===n){let e=r_(n,a);return Object.assign(i.flags,e.flags),i.positionals=e.positionals,i}if("record"===n){let e=[];for(let t=0;t<a.length;t+=1){let r=a[t];if("--hide-touches"===r){i.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<a.length){let e=Number(a[t+1]);Number.isFinite(e)&&(i.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return i.positionals=e,i}if("screenshot"===n){let e=[];for(let t of a){if("--fullscreen"===t){i.flags.screenshotFullscreen=!0;continue}e.push(t)}return i.positionals=e,i}return i.positionals=a,i}(r);e&&t.push(e)}return t}(e),p=t.flags?.replayUpdate===!0,f=0;for(let e=0;e<c.length;e+=1){let o=c[e];if(!o||"replay"===o.command)continue;let s=await pA({req:t,sessionName:r,action:o,invoke:i});if(s.ok){pN(s).forEach(e=>u.add(e));continue}if(!p)return pS(s,o,e,l,[...u]);let d=await pv({action:o,sessionName:r,logPath:n,sessionStore:a});if(!d)return pS(s,o,e,l,[...u]);if(c[e]=d,!(s=await pA({req:t,sessionName:r,action:d,invoke:i})).ok)return pS(s,d,e,l,[...u]);pN(s).forEach(e=>u.add(e)),f+=1}return p&&f>0&&function(e,t,r){let n=[];if(r){let e=r.device.kind?` kind=${r.device.kind}`:"",t=r.device.target?` target=${r.device.target}`:"";n.push(`context platform=${r.device.platform}${t} device=${rI(r.device.name)}${e} theme=unknown`)}for(let e of t)n.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",rv(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return rM(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(rb(r));return rS(t,e.flags),t.join(" ")}if("record"===e.command)return rN(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(rv(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}for(let r of e.positionals??[])t.push(rv(r));return rA(t,e),t.join(" ")}(e));let a=`${n.join("\n")}
|
|
43
|
-
`,i=`${e}.tmp-${process.pid}-${Date.now()}`;s.writeFileSync(i,a),s.renameSync(i,e)}(l,c,a.get(r)),{ok:!0,data:{replayed:c.length,healed:f,session:r,artifactPaths:[...u]}}}catch(t){let e=E(t);return uD(e.code,e.message,u.size>0?{artifactPaths:[...u]}:void 0)}}async function pA(e){var t;let{req:r,sessionName:n,action:a,invoke:i}=e;return await i({token:r.token,session:n,command:a.command,positionals:a.positionals??[],flags:(t=r.flags,dV(t,{...a.flags??{}})),runtime:a.runtime,meta:r.meta})}function pS(e,t,r,n,a=[]){let i;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${i=(t.positionals??[]).map(e=>rv(e)),[t.command,...i].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:n,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:a}}}}function pN(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,n="string"==typeof r.path?r.path:void 0;e?t.push(e):n&&t.push(n)}return[...new Set(t.filter(e=>(function(e){try{return s.statSync(e).isFile()}catch{return!1}})(e)))]}async function p_(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e;return"replay"===t.command?await pb({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}):"test"===t.command?await cz({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await pb({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:n,sessionStore:a,invoke:async e=>{var t;return t=await i(e),l&&pN(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{a.get(e)&&await dU({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:n,sessionStore:a})}}):null}let px=new Set(["session_list","ensure-simulator","devices","apps"]),pD=new Set(["boot","appstate"]),pM=new Set(["perf","logs","network"]),pE=new Set(["replay","test"]);async function pO(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,command:i,positionals:o,recordPositionals:s,deriveNextSession:l}=e,u=a.get(r),d=t.flags??{},c=uP(i,u,d);if(c)return c;let p=await uF({session:u,flags:d,ensureReady:!0});if(!um(i,p))return uD("UNSUPPORTED_OPERATION",`${i} is not supported on this device`);let f=await l4(p,i,o,t.flags?.out,{...uh(n,t.flags,u?.appBundleId,u?.trace?.outPath)});if(u){let e=l?await l(u,f,p):u;a.recordAction(e,{command:i,positionals:s??o,flags:t.flags??{},result:f??{}}),e!==u&&a.set(r,e)}return{ok:!0,data:f??{}}}async function pk(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,i=a.get(r),o=t.flags??{},s=uP("clipboard",i,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return uD("INVALID_ARGS","clipboard requires a subcommand: read or write");let u=await uF({session:i,flags:o,ensureReady:!0});if(!um("clipboard",u))return uD("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let d=await l4(u,"clipboard",t.positionals??[],t.flags?.out,{...uh(n,t.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:d??{}}),{ok:!0,data:{platform:u.platform,...d??{}}}}async function pL(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e;if(px.has(t.command))return await dZ({req:t,sessionName:r,sessionStore:a});if("runtime"===t.command)return await dd({req:t,sessionName:r,sessionStore:a});if(pD.has(t.command))return await d3({req:t,sessionName:r,sessionStore:a});if("clipboard"===t.command)return await pk({req:t,sessionName:r,logPath:n,sessionStore:a});if("keyboard"===t.command){let e=a.get(r),i=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==i||"ios"!==(t.flags??{}).platform?await pO({req:t,sessionName:r,logPath:n,sessionStore:a,command:"keyboard",positionals:t.positionals??[]}):uD("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(pM.has(t.command))return await cC({req:t,sessionName:r,sessionStore:a});if("install"===t.command||"reinstall"===t.command)return await dq({req:t,command:t.command,sessionName:r,sessionStore:a,deployOps:"install"===t.command?dj:dB});if("install_source"===t.command)return await uE({req:t,sessionName:r,sessionStore:a});if("release_materialized_paths"===t.command)return await uk({req:t});if("push"===t.command){let e,i=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return i&&o?await pO({req:t,sessionName:r,logPath:n,sessionStore:a,command:"push",positionals:[i,"file"===(e=lP(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>rE.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[i,o]}):uD("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await pO({req:t,sessionName:r,logPath:n,sessionStore:a,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,n=r?await d_(e.device,r,e.appBundleId,dN)??e.appBundleId:e.appBundleId;return{...e,appBundleId:n}}}):"open"===t.command?await dR({req:t,sessionName:r,logPath:n,sessionStore:a}):pE.has(t.command)?await p_({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}):"batch"===t.command?await dH(t,r,i):"close"===t.command?await dU({req:t,sessionName:r,logPath:n,sessionStore:a}):null}function pC(e,t){let r=ed(e.type??"Element"),n=ee(e,r),a=!1===e.enabled?"disabled":"enabled",i=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,n,a,i,o].join("|")}function pP(e,t){return t.flatten?e.map(e=>({text:ek(e,0,!1),comparable:pC(e,0)})):es(e).map(e=>({text:e.text,comparable:pC(e.node,e.depth)}))}function pR(e,t){return e.get(t)??0}async function pT(e){let t=dg(e.session);if(t&&"android"===e.device.platform)return await pF(e,t);let r=await p$(e);return dy(e.session),{snapshot:pV(r,e.flags),analysis:r.analysis}}async function p$(e){let{device:t,session:r,flags:n,outPath:a,logPath:i,snapshotScope:o}=e;if("linux"===t.platform){let e=await lx(r?.surface);return pB({nodes:e.nodes,truncated:e.truncated,backend:"linux-atspi"},{snapshotDepth:n?.snapshotDepth,snapshotInteractiveOnly:n?.snapshotInteractiveOnly,snapshotScope:o})}return"macos"===t.platform&&r?.surface&&"app"!==r.surface?pB(await oJ(r.surface,{bundleId:"menubar"===r.surface?r.appBundleId:void 0}),{snapshotDepth:n?.snapshotDepth,snapshotInteractiveOnly:n?.snapshotInteractiveOnly,snapshotScope:o}):await l4(t,"snapshot",[],a,{...uh(i,{...n,snapshotScope:o},r?.appBundleId,r?.trace?.outPath)})}async function pF(e,t){let r=await pU(e),n=pG(r,t,e.flags),a=0;for(let i of dh){if(!n)break;await new Promise(e=>setTimeout(e,i)),r=await pU(e),a+=1,n=pG(r,t,e.flags)}return n||dy(e.session),{snapshot:r.snapshot,analysis:r.data.analysis,freshness:a>0||n?{action:t.action,retryCount:a,staleAfterRetries:!!n,reason:n??void 0}:void 0}}async function pU(e){let t=await p$(e);return{data:t,snapshot:pV(t,e.flags)}}function pG(e,t,r){let n=r?.snapshotInteractiveOnly===!0,a=e.data.analysis;return n&&0===e.snapshot.nodes.length&&a&&a.rawNodeCount>=12?"empty-interactive":db(t.baselineCount,e.snapshot.nodes.length)?e.snapshot.nodes.some(e=>!0===e.hittable||!!e.label?.trim()||!!e.value?.trim()||!!e.identifier?.trim())?null:"sharp-drop":t.routeComparable&&dv(t.action)&&function(e,t){if(!e||0===e.length)return!1;let r=Math.max(e.length,t.length);if(r<12)return!1;let n=dI(t),a=Math.min(e.length,n.length),i=0;for(let t=0;t<a;t+=1)e[t]===n[t]&&(i+=1);let o=Math.max(0,n.length-e.length),s=Math.max(0,e.length-n.length),l=Math.max(3,Math.floor(.15*r));return i>=Math.floor(.9*r)&&o<=l&&s<=l}(t.baselineSignatures,e.snapshot.nodes)?"stuck-route":null}function pV(e,t){let r=e?.nodes??[],n=ey(t?.snapshotRaw?r:cZ(r));return{nodes:eO(t?.snapshotScope&&e?.backend!=="macos-helper"?pj(n,t.snapshotScope):n),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend,comparisonSafe:e?.backend==="android"&&t?.snapshotInteractiveOnly!==!0&&t?.snapshotCompact!==!0&&"number"!=typeof t?.snapshotDepth&&!t?.snapshotScope}}function pB(e,t){var r,n;let a=e.nodes??[];return t.snapshotScope&&(a=pj(a,t.snapshotScope)),t.snapshotInteractiveOnly&&(a=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 n 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")}(n))continue;let e=n;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:pq(e.filter(e=>r.has(e.index)))}(a)),"number"==typeof t.snapshotDepth&&(r=a,n=t.snapshotDepth,a=pq(r.filter(e=>(e.depth??0)<=n))),{...e,nodes:a}}function pj(e,t){let r=cK(eO(e),t);if(!r)return[];let n=e.findIndex(e=>e.index===r.index);if(-1===n)return[];let a=e[n]?.depth??0,i=[];for(let t=n;t<e.length;t+=1){let r=e[t];if(!r)continue;let o=r.depth??0;if(t>n&&o<=a)break;i.push(r)}return pq(i,a)}function pq(e,t=0){let r=new Map;for(let[t,n]of e.entries())r.set(n.index,t);return e.map((e,n)=>({...e,index:n,depth:Math.max(0,(e.depth??0)-t),parentIndex:"number"==typeof e.parentIndex?r.get(e.parentIndex):void 0}))}function pH(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return uD("INVALID_ARGS","Ref scope requires an existing snapshot in session.");let r=ev(e.trim());if(!r)return uD("INVALID_ARGS",`Invalid ref scope: ${e}`);let n=em(t.snapshot.nodes,r),a=n?cX(n,t.snapshot.nodes):void 0;return a?{ok:!0,scope:a}:uD("COMMAND_FAILED",`Ref ${e} not found or has no label`)}async function pW(e,t,r){let n=e.get(t),a=n?.device??await l3(r??{});return n||await ug(a),{session:n,device:a}}async function pz(e,t,r){let n=!e&&"ios"===t.platform;try{return await r()}finally{n&&await rr(t.id)}}function pJ(e,t,r,n){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function pK(e){let{session:t,sessionName:r,device:n,snapshot:a,appBundleId:i}=e;return t?{...t,snapshot:a}:{name:r,device:n,createdAt:Date.now(),appBundleId:i,snapshot:a,actions:[]}}function pX(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function pY(e){let{parsed:t,req:r,sessionName:n,logPath:a,sessionStore:i,session:o,device:s}=e;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),pJ(i,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!um("wait",s))return uD("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===t.kind)return await pZ({device:s,logPath:a,parsed:t,req:r,session:o,sessionName:n,sessionStore:i});let l=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return uD("INVALID_ARGS","Ref wait requires an existing snapshot in session.");let r=ev(e.rawRef);if(!r)return uD("INVALID_ARGS",`Invalid ref: ${e.rawRef}`);let n=em(t.snapshot.nodes,r),a=n?cX(n,t.snapshot.nodes):void 0;return a?{ok:!0,text:a,timeoutMs:e.timeoutMs}:uD("COMMAND_FAILED",`Ref ${e.rawRef} not found or has no label`)}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:uD("INVALID_ARGS","wait requires text")}(t,o);return l.ok?await pQ({device:s,logPath:a,req:r,session:o,sessionStore:i,text:l.text,timeoutMs:l.timeoutMs}):l}async function pZ(e){let{device:t,logPath:r,parsed:n,req:a,session:i,sessionName:o,sessionStore:s}=e,l=n.timeoutMs??1e4,u=Date.now();for(;Date.now()-u<l;){let e=pp((await p0({device:t,logPath:r,req:a,session:i,sessionName:o,sessionStore:s})).nodes,n.selector,{platform:t.platform});if(e)return p1(s,i,a,{selector:e.selector.raw,waitedMs:Date.now()-u});await new Promise(e=>setTimeout(e,300))}return uD("COMMAND_FAILED",`wait timed out for selector: ${n.selectorExpression}`)}async function pQ(e){let{device:t,logPath:r,req:n,session:a,sessionStore:i,text:o,timeoutMs:s}=e,l=s??1e4,u=Date.now();for(;Date.now()-u<l;){if("macos"===t.platform&&a?.surface&&"app"!==a.surface){if(cK((await p0({device:t,logPath:r,req:n,session:a,sessionName:a?.name??n.session??"default",sessionStore:i})).nodes,o))return p1(i,a,n,{text:o,waitedMs:Date.now()-u})}else if(tI(t.platform)){let e=await ru(t,{command:"findText",text:o,appBundleId:a?.appBundleId},{verbose:n.flags?.verbose,logPath:r,traceLogPath:a?.trace?.outPath,requestId:n.meta?.requestId});if(e?.found)return pJ(i,a,n,{text:o,waitedMs:Date.now()-u}),{ok:!0,data:{text:o,waitedMs:Date.now()-u}}}else if("android"===t.platform&&cK((await p0({device:t,logPath:r,req:n,session:a,sessionName:a?.name??n.session??"default",sessionStore:i})).nodes,o))return pJ(i,a,n,{text:o,waitedMs:Date.now()-u}),{ok:!0,data:{text:o,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return uD("COMMAND_FAILED",`wait timed out for text: ${o}`)}async function p0(e){let{device:t,logPath:r,req:n,session:a,sessionName:i,sessionStore:o}=e,{snapshot:s}=await pT({device:t,session:a,flags:{...n.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:n.flags?.out,logPath:r});return a&&(a.snapshot=s,o.set(i,a)),s}function p1(e,t,r,n){return pJ(e,t,r,n),{ok:!0,data:n}}async function p2(e){let{req:t,logPath:r,sessionStore:n,session:a,device:i}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=a?"frontmost-app"===a.surface?{surface:"frontmost-app"}:{bundleId:a.appBundleId,surface:a.surface}:{};if(!um("alert",i))return uD("UNSUPPORTED_OPERATION","alert is not supported on this device");if("macos"===i.platform){let e=async()=>await oz("wait"===o?"get":o,s);if("wait"===o){let r=pX(t.positionals?.[1])??1e4,i=Date.now();for(;Date.now()-i<r;){try{let r=await e();return pJ(n,a,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return uD("COMMAND_FAILED","alert wait timed out")}let r="accept"===o||"dismiss"===o?o:"get";if("accept"===r||"dismiss"===r){let e,i=Date.now();for(;Date.now()-i<2e3;){try{let e=await oz(r,s);return pJ(n,a,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 p3(e)}let i=await oz("get",s);return pJ(n,a,t,i),{ok:!0,data:i}}if("wait"===o){let e=pX(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await ru(i,{command:"alert",action:"get",appBundleId:a?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:a?.trace?.outPath,requestId:t.meta?.requestId});return pJ(n,a,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return uD("COMMAND_FAILED","alert wait timed out")}let l="accept"===o||"dismiss"===o?o:"get",u={verbose:t.flags?.verbose,logPath:r,traceLogPath:a?.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 ru(i,{command:"alert",action:l,appBundleId:a?.appBundleId},u);return pJ(n,a,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 p3(e)}let d=await ru(i,{command:"alert",action:l,appBundleId:a?.appBundleId},u);return pJ(n,a,t,d),{ok:!0,data:d}}function p3(e){if(!(e instanceof k))return e;let t=String(e.message??"").toLowerCase();return t.includes("alert not found")||t.includes("no alert")?new k(e.code,e.message,{...e.details??{},hint:"If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref."}):e}async function p4(e){let{req:t,logPath:r,sessionStore:n,session:a,device:i,parsed:o}=e,{setting:s,state:l,permissionTarget:u}=o;if(!um("settings",i))return uD("UNSUPPORTED_OPERATION","settings is not supported on this device");if("macos"===i.platform&&!j(s))return uD("INVALID_ARGS",eo(s));let d=a?.appBundleId,c="permission"===s?[s,l,u??"",t.positionals?.[3]??"",d??""]:[s,l,d??""],p=await l4(i,"settings",c,t.flags?.out,{...uh(r,t.flags,d,a?.trace?.outPath)});return pJ(n,a,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}let p5=new Set(["snapshot","diff","wait","alert","settings"]);async function p8(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,i=t.command;if(!p5.has(i))return null;if("snapshot"===i){let{session:e,device:i}=await pW(a,r,t.flags);if(!um("snapshot",i))return uD("UNSUPPORTED_OPERATION","snapshot is not supported on this device");let o=pH(t.flags?.snapshotScope,e);return o.ok?await pz(e,i,async()=>{let s=await pT({device:i,session:e,flags:t.flags,outPath:t.flags?.out,logPath:n,snapshotScope:o.scope}),l=p6({capture:s,flags:t.flags,session:e}),u=function(e){var t;let{nodes:r,backend:n,snapshotRaw:a}=e;if(a||"macos-helper"===(t=n)||"linux-atspi"===t)return{partial:!1,visibleNodeCount:r.length,totalNodeCount:r.length,reasons:[]};let i=el(r),o=new Set;return i.hiddenCount>0&&o.add("offscreen-nodes"),i.nodes.some(e=>e.hiddenContentAbove)&&o.add("scroll-hidden-above"),i.nodes.some(e=>e.hiddenContentBelow)&&o.add("scroll-hidden-below"),{partial:o.size>0,visibleNodeCount:i.nodes.length,totalNodeCount:r.length,reasons:[...o]}}({nodes:s.snapshot.nodes,backend:s.snapshot.backend,snapshotRaw:t.flags?.snapshotRaw}),d=pK({session:e,sessionName:r,device:i,snapshot:s.snapshot,appBundleId:e?.appBundleId});return pJ(a,d,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),a.set(r,d),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,visibility:u,...l.length>0?{warnings:l}:{},appName:d.appBundleId?d.appName??d.appBundleId:void 0,appBundleId:d.appBundleId}}}):o}if("diff"===i)return t.positionals?.[0]!=="snapshot"?uD("INVALID_ARGS","diff currently supports only: diff snapshot"):await p9({req:t,sessionName:r,logPath:n,sessionStore:a});if("wait"===i){let{session:e,device:i}=await pW(a,r,t.flags),o=function(e){if(0===e.length)return null;let t=pX(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=pX(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=pX(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=pX(e[e.length-1]),n=c9(null!==r?e.slice(0,-1):e.slice());if(n&&0===n.rest.length){let e=c6(n.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:n.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!o)return uD("INVALID_ARGS","wait requires a duration or text");let s=()=>pY({parsed:o,req:t,sessionName:r,logPath:n,sessionStore:a,session:e,device:i});return"sleep"===o.kind?await s():await pz(e,i,s)}if("alert"===i){let{session:e,device:i}=await pW(a,r,t.flags);return await pz(e,i,async()=>await p2({req:t,logPath:n,sessionStore:a,session:e,device:i}))}if("settings"===i){let e,i,o,s=(e=t.positionals?.[0]?.toLowerCase(),i=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&i&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:i,permissionTarget:o}}:uD("INVALID_ARGS",J));if(!s.ok)return s;let{session:l,device:u}=await pW(a,r,t.flags);return await pz(l,u,async()=>await p4({req:t,logPath:n,sessionStore:a,session:l,device:u,parsed:s.parsed}))}return null}function p6(e){let{capture:t,flags:r,session:n}=e,a=[],i=t.analysis,o=r?.snapshotInteractiveOnly===!0;"android"===t.snapshot.backend&&o&&0===t.snapshot.nodes.length&&i&&i.rawNodeCount>=12&&(a.push(`Interactive snapshot is empty after filtering ${i.rawNodeCount} raw Android nodes. Likely causes: depth too low, transient route change, or collector filtering.`),"number"==typeof r?.snapshotDepth&&i.maxDepth>=r.snapshotDepth+2&&a.push(`Interactive output is empty at depth ${r.snapshotDepth}; retry without -d.`));let s=n?.snapshot;return!t.freshness&&s&&Date.now()-s.createdAt<=2e3&&db(s.nodes.length,t.snapshot.nodes.length)&&a.push("Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once."),t.freshness?.staleAfterRetries&&"android"===t.snapshot.backend&&("stuck-route"===t.freshness.reason?a.push(`Recent ${t.freshness.action} was followed by a nearly identical snapshot after ${t.freshness.retryCount} automatic retr${1===t.freshness.retryCount?"y":"ies"}. If you expected navigation or submit, the tree may still be stale. Use screenshot as visual truth, wait briefly, then re-snapshot once.`):"sharp-drop"===t.freshness.reason&&a.push("Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once.")),rp(a)}async function p9(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,{session:i,device:o}=await pW(a,r,t.flags);if(!um("diff",o))return uD("UNSUPPORTED_OPERATION","diff is not supported on this device");let s=pH(t.flags?.snapshotScope,i);if(!s.ok)return s;let l=t.flags?.snapshotInteractiveOnly===!0;return await pz(i,o,async()=>{let e=await pT({device:o,session:i,flags:t.flags,outPath:t.flags?.out,logPath:n,snapshotScope:s.scope}),u=e.snapshot,d=p6({capture:e,flags:t.flags,session:i});if(!i?.snapshot){let e=function(e,t={}){return pP(e,t).length}(u.nodes,{flatten:l}),n=pK({session:i,sessionName:r,device:o,snapshot:u,appBundleId:i?.appBundleId});return pJ(a,n,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e}}),a.set(r,n),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e},lines:[],...d.length>0?{warnings:d}:{}}}}let c=function(e,t,r={}){let n=function(e,t){let r=e.length,n=t.length,a=r+n,i=new Map,o=[];i.set(1,0);for(let s=0;s<=a;s+=1){o.push(new Map(i));for(let a=-s;a<=s;a+=2){let l=a===-s||a!==s&&pR(i,a-1)<pR(i,a+1)?pR(i,a+1):pR(i,a-1)+1,u=l-a;for(;l<r&&u<n&&e[l].comparable===t[u].comparable;)l+=1,u+=1;if(i.set(a,l),l>=r&&u>=n)return function(e,t,r,n,a){let i=[],o=n,s=a;for(let n=e.length-1;n>=0;n-=1){let a=e[n],l=o-s,u=l===-n||l!==n&&pR(a,l-1)<pR(a,l+1)?l+1:l-1,d=pR(a,u),c=d-u;for(;o>d&&s>c;)i.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===n)break;o===d?(i.push({kind:"added",text:r[c].text}),s=c):(i.push({kind:"removed",text:t[d].text}),o=d)}return i.reverse(),i}(o,e,t,r,n)}}return[]}(pP(e,r),pP(t,r)),a={additions:0,removals:0,unchanged:0};for(let e of n)"added"===e.kind&&(a.additions+=1),"removed"===e.kind&&(a.removals+=1),"unchanged"===e.kind&&(a.unchanged+=1);return{summary:a,lines:n}}(i.snapshot.nodes,u.nodes,{flatten:l}),p={...i,snapshot:u};return pJ(a,p,t,{mode:"snapshot",baselineInitialized:!1,summary:c.summary}),a.set(r,p),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:c.summary,lines:c.lines,...d.length>0?{warnings:d}:{}}}})}function p7(e){let{session:t,refInput:r,fallbackLabel:n,requireRect:a,invalidRefMessage:i,notFoundMessage:o}=e;if(!t.snapshot)return uD("INVALID_ARGS","No snapshot in session. Run snapshot first.");let s=ev(r);if(!s)return uD("INVALID_ARGS",i);let l=em(t.snapshot.nodes,s);return((!l||a&&!l.rect)&&n.length>0&&(l=cK(t.snapshot.nodes,n)),l&&(!a||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:uD("COMMAND_FAILED",o)}function fe(e){let t=ft(e);if(!t)return null;let r=eD(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function ft(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),n=Number(e.width),a=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(n)&&Number.isFinite(a)&&!(n<0)&&!(a<0)?{x:t,y:r,width:n,height:a}:null}async function fr(e){let{session:t,refInput:r,fallbackLabel:n,commandLabel:a,promoteToHittableAncestor:i,invalidRefMessage:o,missingBoundsMessage:s,invalidBoundsMessage:l,reqFlags:u,sessionStore:d,contextFromFlags:c,captureSnapshotForSession:p,resolveRefTarget:f}=e,m=f({session:t,refInput:r,fallbackLabel:n,requireRect:!0,invalidRefMessage:o,notFoundMessage:s});if(!m.ok)return m;let{ref:h}=m.target,w=i?fn(m.target.snapshotNodes,m.target.node):m.target.node,g=m.target.snapshotNodes,y=fe(w.rect);if(!y){let e=await p(t,u,d,c,{interactiveOnly:!0}),r=em(e.nodes,h),a=n.length>0?cK(e.nodes,n):null,o=r&&i?fn(e.nodes,r):r,s=a&&i?fn(e.nodes,a):a,l=fe(s?.rect),f=fe(o?.rect)?o:l?s:o??s,m=fe(f?.rect);f&&m&&(w=f,g=e.nodes,y=m)}if(!y)return uD("COMMAND_FAILED",l);let v=w.rect?ei(w,g):null;return w.rect&&v&&!B(w,g)?{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${r} is off-screen and not safe to ${a}`,hint:`Run scrollintoview ${r}, then retry ${a} with the returned currentRef or a fresh snapshot.`,details:{reason:"offscreen_ref",ref:h,rect:w.rect,viewport:v}}}:{ok:!0,target:{ref:h,node:w,snapshotNodes:g,point:y}}}function fn(e,t){let r=function(e,t){let r=ft(t.rect);if(!r)return null;let n=t,a=new Set;for(;!a.has(n.ref);){a.add(n.ref);let t=e.filter(e=>{if(e.parentIndex!==n.index||!e.hittable)return!1;let t=ft(e.rect);return!!t&&fa(t,r)});if(1!==t.length)break;n=t[0]}return n===t?null:n}(e,t);if(r?.rect&&fe(r.rect))return r;let n=c1(e,t);return n?.rect&&fe(n.rect)?!function(e,t,r){var n,a,i,o;let s,l,u,d=ft(e.rect),c=ft(t.rect);if(!d||!c)return!1;let p=function(e,t){let r=eD(t),n=e.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}).map(e=>ft(e.rect)).filter(e=>null!==e);if(0===n.length)return null;let a=n.filter(e=>X(e,r.x,r.y));return ew(a.length>0?a:n)}(r,d);return!!p&&(n=c,a=p,s=(i=n,o=a,Math.max(0,Math.min(i.x+i.width,o.x+o.width)-Math.max(i.x,o.x))*Math.max(0,Math.min(i.y+i.height,o.y+o.height)-Math.max(i.y,o.y))),l=n.width*n.height,u=a.width*a.height,!(s<=0)&&!(l<=0)&&!(u<=0)&&!!(s/u>=.9)&&!!(s/l>=.8))&&!fa(d,c)}(t,n,e)?n:t:t}function fa(e,t){return .5>=Math.abs(e.x-t.x)&&.5>=Math.abs(e.y-t.y)&&.5>=Math.abs(e.width-t.width)&&.5>=Math.abs(e.height-t.height)}async function fi(e){let{device:t,node:r,flags:n,appBundleId:a,traceOutPath:i,surface:o,contextFromFlags:s}=e,l=ea(r),u=fe(r.rect);if(!u)return l;try{let e=await l4(t,"read",[String(u.x),String(u.y)],void 0,{...s(n,a,i),surface:o}),d=e&&"object"==typeof e?e:void 0,c="string"==typeof d?.text?d.text:"";if(c.trim())return c;return D({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return D({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 fo(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return uD("INVALID_ARGS","find requires a locator or text");let{locator:l,query:u,action:d,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 n=e[r]??"",a=e.slice(r+1);if(0===a.length)return{locator:t,query:n,action:"click"};let i=a[0].toLowerCase();if("get"===i){let e=a[1]?.toLowerCase();if("text"===e)return{locator:t,query:n,action:"get_text"};if("attrs"===e)return{locator:t,query:n,action:"get_attrs"};throw new k("INVALID_ARGS","find get only supports text or attrs")}if("wait"===i)return{locator:t,query:n,action:"wait",timeoutMs:pX(a[1])??void 0};if("exists"===i)return{locator:t,query:n,action:"exists"};if("click"===i)return{locator:t,query:n,action:"click"};if("focus"===i)return{locator:t,query:n,action:"focus"};if("fill"===i)return{locator:t,query:n,action:"fill",value:a.slice(1).join(" ")};if("type"===i)return{locator:t,query:n,action:"type",value:a.slice(1).join(" ")};throw new k("INVALID_ARGS",`Unsupported find action: ${a[0]}`)}(s);if(!u)return uD("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return uD("INVALID_ARGS","find accepts only one of --first or --last");let f=a.get(r);if(!f&&"exists"!==d&&"wait"!==d&&"get_text"!==d&&"get_attrs"!==d)return uD("SESSION_NOT_FOUND","No active session. Run open first.");let m=f?.device??await l3(t.flags??{});f||await ug(m);let h="role"!==l?u:void 0,w="click"===d||"focus"===d||"fill"===d||"type"===d,g=0,y=null,v=async()=>{let e=Date.now();if(y&&e-g<750&&!dg(f))return{nodes:y};let{snapshot:i}=await pT({device:m,session:f,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:n,snapshotScope:h}),o=i.nodes;return g=e,y=o,f&&(f.snapshot=i,a.set(r,f)),{nodes:o,truncated:i.truncated,backend:i.backend}},I={req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i,session:f,device:m,command:o,locator:l,query:u};if("wait"===d)return fs(I,v,l,u,p);let{nodes:b}=await v(),A=pa(b,l,u,{requireRect:w});if(w&&A.matches.length>1)if(t.flags?.findFirst)A.matches=[A.matches[0]];else{if(!t.flags?.findLast){var S,N,_;let e;return S=A.matches,N=l,_=u,e=S.slice(0,8).map(e=>{let t=c2(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),uD("AMBIGUOUS_MATCH",`find matched ${S.length} elements for ${N} "${_}". Use a more specific locator or selector.`,{locator:N,query:_,matches:S.length,candidates:e})}A.matches=[A.matches[A.matches.length-1]]}let x=A.matches[0]??null;if(!x)return uD("COMMAND_FAILED","find did not match any element");let D="click"===d||"focus"===d||"fill"===d||"type"===d?c1(b,x)??x:x,M=`@${D.ref}`,E={node:x,resolvedNode:D,ref:M,nodes:b,actionFlags:{...t.flags??{},noRecord:!0}},O={exists:()=>fl(I),get_text:()=>fu(I,E),get_attrs:()=>fd(I,E),click:()=>fc(I,E),fill:()=>fp(I,E,c),focus:()=>ff(I,E),type:()=>fm(I,E,c)}[d];return O?O():null}async function fs(e,t,r,n,a){let{req:i,sessionStore:o,session:s,command:l}=e,u=a??1e4,d=Date.now();for(;Date.now()-d<u;){let{nodes:e}=await t();if(pa(e,r,n,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:i.positionals??[],flags:i.flags??{},result:{found:!0,waitedMs:Date.now()-d}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return uD("COMMAND_FAILED","find wait timed out")}async function fl(e){let{req:t,sessionStore:r,session:n,command:a}=e;return n&&r.recordAction(n,{command:a,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function fu(e,t){let{req:r,sessionStore:n,session:a,command:i,device:o,logPath:s}=e,l=await fi({device:o,node:t.node,flags:r.flags,appBundleId:a?.appBundleId,traceOutPath:a?.trace?.outPath,surface:a?.surface,contextFromFlags:(e,t,r)=>uh(s,e,t,r)});return a&&n.recordAction(a,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function fd(e,t){let{req:r,sessionStore:n,session:a,command:i}=e;return a&&n.recordAction(a,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function fc(e,t){let{req:r,sessionName:n,sessionStore:a,session:i,invoke:o,command:s,locator:l,query:u}=e,d=await o({token:r.token,session:n,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!d.ok)return d;let c=t.resolvedNode.rect?eD(t.resolvedNode.rect):null,p={ref:t.ref,locator:l,query:u};return c&&(p.x=c.x,p.y=c.y),i&&a.recordAction(i,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:u}}),{ok:!0,data:p}}async function fp(e,t,r){let{req:n,sessionName:a,sessionStore:i,session:o,invoke:s,command:l}=e;if(!r)return uD("INVALID_ARGS","find fill requires text");let u=await s({token:n.token,session:a,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return u.ok&&o&&i.recordAction(o,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{ref:t.ref,action:"fill"}}),u}async function ff(e,t){let{req:r,sessionStore:n,session:a,device:i,command:o,logPath:s}=e,l=t.node.rect?eD(t.node.rect):null;if(!l)return uD("COMMAND_FAILED","matched element has no bounds");let u=await l4(i,"focus",[String(l.x),String(l.y)],r.flags?.out,{...uh(s,r.flags,a?.appBundleId,a?.trace?.outPath)});return a&&n.recordAction(a,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:u??{ref:t.ref}}}async function fm(e,t,r){let{req:n,sessionStore:a,session:i,device:o,command:s,logPath:l}=e;if(!r)return uD("INVALID_ARGS","find type requires text");let u=t.node.rect?eD(t.node.rect):null;if(!u)return uD("COMMAND_FAILED","matched element has no bounds");await l4(o,"focus",[String(u.x),String(u.y)],n.flags?.out,{...uh(l,n.flags,i?.appBundleId,i?.trace?.outPath)});let d=await l4(o,"type",[r],n.flags?.out,{...uh(l,n.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:s,positionals:n.positionals??[],flags:n.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:d??{ref:t.ref}}}let fh=`
|
|
1
|
+
let e,t;import r from"node:crypto";import a,{promises as i}from"node:fs";import n from"node:path";import{spawn as o}from"node:child_process";import s from"node:http";import{fileURLToPath as l,pathToFileURL as d}from"node:url";import"node:https";import u from"node:os";import c from"node:fs/promises";import{setTimeout as f}from"node:timers/promises";import{PNG as p}from"pngjs";import m from"node:net";import{resolveAppleSimulatorSetPathForSelector as h,buildSimctlArgs as g,dispatchCommand as w,isNodeVisibleInEffectiveViewport as v,isAgentDeviceDaemonProcess as y,handleSnapshotCommands as I,isNodeEditable as S,resolveSelectorChain as A,registerRequestAbort as b,resolveSessionIsolationMode as _,errorResponse as N,pickLargestRect as x,successText as M,uniqueStrings as k,withKeyedLock as D,DEFAULT_BATCH_MAX_STEPS as P,parseSerialAllowlist as L,extractNodeReadText as R,getAndroidScreenSize as O,rect_visibility_containsPoint as E,extractNodeText as C,IOS_DEVICECTL_DEFAULT_HINT as $,captureSnapshotData as T,isRequestCanceled as F,resolveRequestTrackingId as U,abortAllIosRunnerSessions as G,getRunnerSessionSnapshot as V,formatAndroidInstalledPackageRequiredMessage as q,resolveViewportRect as j,tryParseSelectorChain as B,readVersion as H,clearRequestCanceled as K,parseXmlDocumentSync as z,findNearestHittableAncestor as W,IOS_SIMCTL_LIST_TIMEOUT_MS as J,listIosDeviceApps as Z,readProcessStartTime as Y,withDiagnosticsScope as X,isApplePlatform as Q,resolveInstallFromSourceResultTarget as ee,centerOfRect as et,resolveAndroidSerialAllowlist as er,isFillableType as ea,attachRefs as ei,listIosDeviceProcesses as en,buildScrollGesturePlan as eo,splitSelectorFromArgs as es,readProcessCommand as el,parseSessionSurface as ed,resolveDaemonServerMode as eu,validateAndNormalizeBatchSteps as ec,IOS_RUNNER_CONTAINER_BUNDLE_IDS as ef,buttonTag as ep,hasRuntimeTransportHints as em,resolveDeployResultTarget as eh,inferFillText as eg,buildSelectorChainForNode as ew,withSuccessText as ev,shutdownSimulator as ey,stopIosRunnerSession as eI,formatSelectorFailure as eS,createRequestCanceledError as eA,isNavigationSensitiveAction as eb,resolveIosDevicectlHint as e_,getClickButtonValidationError as eN,isNodeVisible as ex,findNodeByRef as eM,snapshotAndroid as ek,withDiagnosticTimer as eD,pruneGroupNodes as eP,applyRuntimeHintsToApp as eL,resolveTargetDevice as eR,stopAllIosRunnerSessions as eO,findSelectorChainMatch as eE,normalizeRef as eC,classifyAndroidAppTarget as e$,getAndroidAppState as eT,runMacOsAlertAction as eF,isDeepLinkTarget as eU,clearRuntimeHintsFromApp as eG,contextFromFlags as eV,parseFindArgs as eq,resolveDaemonCodeSignature as ej,captureSnapshot as eB,parseSelectorChain as eH,normalizeTenantId as eK,resolveClickButton as ez,resolveTimeoutMs as eW,buildSnapshotState as eJ,openAndroidApp as eZ,distanceFromSafeViewportBand as eY,splitIsSelectorArgs as eX,adbArgs as eQ,resolveRefLabel as e0,resolvePayloadInput as e1,resolveEffectiveViewportRect as e2,resolveIosSimulatorDeviceSetPath as e5,markRequestCanceled as e4,resolveIosDeviceDeepLinkBundleId as e3,runIosRunnerCommand as e8,resolveUserPath as e6,ensureDeviceReady as e9,getDiagnosticsMeta as e7,readInfoPlistString as te,getActiveAndroidSnapshotFreshness as tt,buildSimctlArgsForDevice as tr,findBestMatchesByLocator as ta,emitDiagnostic as ti,resolveFrontmostMacOsApp as tn,findNodeByLabel as to,matchesPlatformSelector as ts,isCommandSupportedOnDevice as tl,resolveDaemonPaths as td,flushDiagnosticsToSessionFile as tu,normalizeType as tc,normalizePlatformSelector as tf,decodePng as tp,markAndroidSnapshotFreshness as tm,getRequestSignal as th}from"./155.js";import{runCmdBackground as tg,runCmd as tw,asAppError as tv,normalizeError as ty,AppError as tI}from"./818.js";let tS=/^-?\d+(\.\d+)?$/,tA=/^[^\s"\\]+$/,tb=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),t_=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tN=new Map([["--delay-ms","delayMs"]]);function tx(e){return"click"===e||"press"===e}function tM(e){return"type"===e||"fill"===e}function tk(e){return tP(e,tL)}function tD(e){return JSON.stringify(e)}function tP(e,t){return t(e)?e:tD(e)}function tL(e){return tR(e)&&e.startsWith("@")||tS.test(e)}function tR(e){return tA.test(e)}function tO(e,t){let r=t.flags??{};if(tx(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}tM(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tE(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",tP(t.metroHost,tR)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tP(t.bundleUrl,tR)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tP(t.launchUrl,tR)))}function tC(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tP(r,tR)),a))e.push(tk(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function t$(e,t){let r=[],a={},i=tx(e)?tb:"swipe"===e?t_:tM(e)?tN:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tx(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tx(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=tF(t[n+1]);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 tT(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let i=e[a];if("--platform"===i&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===i&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===i&&a+1<e.length){let t=tF(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function tF(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tU(e,t){for(let r of t.positionals??[])e.push(tk(r));t.flags?.relaunch&&e.push("--relaunch"),tE(e,t.runtime)}class tG{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=tG.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 t={};for(let r of tV)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),ti({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=n.dirname(t);a.existsSync(r)||a.mkdirSync(r,{recursive:!0});let i=function(e,t){let r=[],a=e.device.kind?` kind=${e.device.kind}`:"";for(let i of(r.push(`context platform=${e.device.platform} device=${tD(e.device.name)}${a} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(tx(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tk(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tk(a)),tO(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tk(r)),tO(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tk(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tk(a)),e.positionals.length>1&&t.push(tk(i)),tO(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tk(r)),t.push(tk(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tk(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",tk(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tk(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}if("open"===e.command)return tU(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tP(r,tR)),tE(t,e.flags),t.join(" ")}if("record"===e.command)return tC(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tk(r));return tO(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
2
|
+
`}(e,this.buildOptimizedActions(e));a.writeFileSync(t,i)}catch{}}defaultTracePath(e){let t=tG.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return n.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return n.join(this.sessionsDir,tG.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return n.join(this.sessionsDir,tG.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return e6(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return tG.expandHome(e.saveScriptPath);a.existsSync(this.sessionsDir)||a.mkdirSync(this.sessionsDir,{recursive:!0});let t=tG.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return n.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let a=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(a.length>0&&(tx(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tx(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=eg(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(tx(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}}let tV=["platform","device","udid","serial","out","verbose","metroHost","metroPort","bundleUrl","launchUrl","snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw","screenshotFullscreen","relaunch","saveScript","noRecord","fps","hideTouches","count","intervalMs","delayMs","holdMs","jitterPx","doubleTap","clickButton","pauseMs","pattern"],tq="app-log.pid";function tj(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}}function tB(e,t){if(!e)return;let r=n.dirname(e);a.existsSync(r)||a.mkdirSync(r,{recursive:!0});let i={pid:t,startTime:Y(t)??void 0,command:el(t)??void 0};a.writeFileSync(e,`${JSON.stringify(i)}
|
|
3
|
+
`)}function tH(e){if(e&&a.existsSync(e))try{a.unlinkSync(e)}catch{}}async function tK(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function tz(e){await new Promise(t=>setTimeout(t,e))}function tW(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}
|
|
4
|
+
`)},flush:()=>{a&&(i(a),a="")}}}function tJ(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})}function tZ(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new tI("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function tY(e,t){let r=(await tw("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function tX(e,t){var r,a;let i;tZ(t);let n=await tY(e,t),o=await tw("adb",["-s",e,"logcat","-d","-v","time","-t","4000"],{allowFailure:!0,timeoutMs:3e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=function(e,t,r){let a=new Set;for(let i of(r&&a.add(r),e.split("\n")))if(i.includes(t))for(let e of function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=[RegExp(`\\bStart proc\\s+(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`\\b(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`${r}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,"i"),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${r}`,"i")],i=[];for(let t of a){let r=t.exec(e),a=r?.[1];a&&/^\d+$/.test(a)&&i.push(a)}return i}(i,t))a.add(e);return[...a]}(o.stdout,t,n);if(0===s.length)return null;let l=(r=o.stdout,a=t,i=new Set(s),r.split("\n").filter(e=>{var t;let r;if(!e.trim())return!1;if(e.includes(a))return!0;let n=(t=e,r=/\(\s*(\d+)\)\s*:/.exec(t),r?.[1]??null);return!!n&&i.has(n)}).join("\n"));return 0===l.trim().length?null:{pid:n,text:l,recoveredPids:s}}async function tQ(e,t,r,a,i){let n,s,l="recovering",d=!1,u=(async()=>{try{for(;!d;){let u=await tY(e,t);if(!u){l="recovering",await tz(1e3);continue}let c=o("adb",["-s",e,"logcat","-v","time","--pid",u],{stdio:["ignore","pipe","pipe"]});n=c;let f=tW(r,{redactionPatterns:a});if(s=tJ(c,r,{endStreamOnClose:!1,writer:f}),"number"==typeof c.pid&&(tB(i,c.pid),l="active"),await s,tH(i),n=void 0,s=void 0,d)break;l="recovering",await tz(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tH(i)}})();return{backend:"android",getState:()=>l,startedAt:Date.now(),wait:u,stop:async()=>{d=!0,n&&!n.killed&&n.kill("SIGINT"),s&&await tK(s),n&&!n.killed&&n.kill("SIGKILL"),await tK(u),tH(i)}}}function t0(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}"`}async function t1(e){let{deviceId:t,appBundleId:r,startedAt:a,simulatorSetPath:i}=e,n=g(["spawn",t,"log","show","--style","compact","--info","--predicate",t0(r)],{simulatorSetPath:i});"number"==typeof a&&Number.isFinite(a)&&a>0?n.push("--start",`@${Math.floor(a/1e3)}`):n.push("--last","5m");let o=await tw("xcrun",n,{allowFailure:!0,timeoutMs:4e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=o.stdout.split("\n").map(e=>e.trimEnd()).filter(e=>{let t=e.trim();return t.length>0&&!t.startsWith("Timestamp Ty Process[PID:TID]")});return 0===s.length?null:{text:`${s.join("\n")}
|
|
5
|
+
`,recoveredLineCount:s.length}}async function t2(e,t,r,a,i,n){let s="active",l=o("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return g(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",t0(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:i}),{stdio:["ignore","pipe","pipe"]}),d=tW(r,{redactionPatterns:a});"number"==typeof l.pid&&tB(n,l.pid);let u=tJ(l,r,{endStreamOnClose:!0,writer:d}).then(e=>(0!==e.exitCode&&(s="failed"),tH(n),e));return{backend:"ios-simulator",getState:()=>s,startedAt:Date.now(),wait:u,stop:async()=>{l.killed||l.kill("SIGINT"),await tK(u),l.killed||l.kill("SIGKILL"),await tK(u),tH(n)}}}async function t5(e,t,r,a){let i="active",n=o("log",["stream","--style","compact","--predicate",t0(e)],{stdio:["ignore","pipe","pipe"]}),s=tW(t,{redactionPatterns:r});"number"==typeof n.pid&&tB(a,n.pid);let l=tJ(n,t,{endStreamOnClose:!0,writer:s}).then(e=>(0!==e.exitCode&&(i="failed"),tH(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tK(l),n.killed||n.kill("SIGKILL"),await tK(l),tH(a)}}}async function t4(e,t,r,a){let i="active",n=o("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),s=tW(t,{redactionPatterns:r});"number"==typeof n.pid&&tB(a,n.pid);let l=tJ(n,t,{endStreamOnClose:!0,writer:s}).then(e=>(0!==e.exitCode&&(i="failed"),tH(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tK(l),n.killed||n.kill("SIGKILL"),await tK(l),tH(a)}}}let t3=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),t8=/https?:\/\/[^\s"'<>\])]+/i,t6=[/\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 t9(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>re(e)));for(let e of t.entries){let t=re(e);if(!i.has(t)&&(i.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function t7(e,t){let r=ru(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=ru(t?.maxPayloadChars,2048,64,16384),o=ru(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),d=s.slice(l),u=[];for(let e=d.length-1;e>=0&&u.length<r;e-=1){let t=d[e];if(!t?.trim())continue;let r=function(e,t,r,a,i,n){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=ro(s,["method","httpMethod"]),d=ro(s,["url","requestUrl"]),u=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=t3.exec(o),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=t8.exec(o),h=d??m?.[0];if(!h)return null;let g=u??rr(o)??void 0;if(!(l||f?.[1]||c?.[1]||void 0!==g||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let w={method:p,url:h,status:g,timestamp:ra(o),packetId:ri(o)??void 0,durationMs:rn(o)??void 0,raw:rd(o,n),line:r};if("android"===a&&function(e,t,r){let a=rt(t,r,5),i=e.packetId??a.map(e=>ri(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?rt(t,r,12).filter(e=>ri(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>ra(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>rr(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>rn(e)).find(e=>"number"==typeof e))}(w,e,t),"headers"===i||"all"===i){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return rl(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(w.headers=rd(e,n))}if("body"===i||"all"===i){let e=rs(o,s,["requestBody","body","payload","request"]),t=rs(o,s,["responseBody","response"]);e&&(w.requestBody=rd(e,n)),t&&(w.responseBody=rd(t,n))}return w}(d,e,l+e+1,a,i,n);r&&u.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:d.length,matchedLines:u.length,entries:u,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:o}}}function re(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function rt(e,t,r){let a=[],i=Math.max(0,t-r),n=Math.min(e.length-1,t+r);for(let t=i;t<=n;t+=1){let r=e[t]?.trim();r&&a.push(r)}return a}function rr(e){for(let t of t6){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function ra(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function ri(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function rn(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function ro(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 rs(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return rl(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 rl(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function rd(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function ru(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function rc(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 rf(e){let t=n.dirname(e);a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),function(e,t){if(a.existsSync(e)&&!(a.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,i=`${e}.${r}`;a.existsSync(t)&&(a.existsSync(i)&&a.unlinkSync(i),a.renameSync(t,i))}}(e,{maxBytes:rc("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rc("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rp(e){var t,r,i,n;let o,s,l,d,{device:u,appBundleId:c,appLogState:f,appLogStartedAt:p,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v}=e,y="macos"===u.platform?"macos":"ios"===u.platform?"device"===u.kind?"ios-device":"ios-simulator":"android",I=(t={backend:y,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v},o=ru(t?.maxEntries,25,1,200),s=t?.include??"summary",l=ru(t?.maxPayloadChars,2048,64,16384),d=ru(t?.maxScanLines,4e3,100,2e4),a.existsSync(m)?t7(a.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:s,limits:{maxEntries:o,maxPayloadChars:l,maxScanLines:d}}),S=[],A=await rm({device:u,appBundleId:c,appLogPath:m,appLogState:f});if(A){let e=await tX(u.id,c);if(e){let t=t7(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v});t.entries.length>0&&(I=t9(t,I,h),S.push((r=A,i=e.recoveredPids,"stale-active"===r.reason?`Session app log stream was still bound to prior Android PID ${r.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${i.join(", ")}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${i.join(", ")}.`)))}}if("ios"===u.platform&&"simulator"===u.kind&&c&&0===I.entries.length){let e=await rg({deviceId:u.id,appBundleId:c,startedAt:p,simulatorSetPath:u.simulatorSetPath,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v});e&&(e.dump.entries.length>0?(I=t9(e.dump,I,h),S.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&S.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===f?S.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==f&&0===S.length&&("ios"===u.platform&&"simulator"===u.kind?S.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):S.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===I.entries.length&&S.push("ios"===(n=u).platform&&"simulator"===n.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===n.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:y,dump:I,notes:S}}async function rm(e){let{device:t,appBundleId:r,appLogPath:i,appLogState:o}=e;if("android"!==t.platform||!r)return null;if(void 0!==o&&"active"!==o)return{reason:"inactive"};if("active"!==o)return null;let s=function(e){let t=function(e){if(!e||!a.existsSync(e))return null;try{return tj(a.readFileSync(e,"utf8"))}catch{return null}}(e)?.command;if(!t)return null;let r=/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(t);return r?.[1]??null}(n.join(n.dirname(i),tq));if(!s)return null;let l=await tY(t.id,r);return l&&l!==s?{reason:"stale-active",trackedPid:s}:null}async function rh(e,t,r,i){rf(r);let n=a.createWriteStream(r,{flags:"a"}),o=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 t4(e.id,n,o,i):await t2(e.id,t,n,o,e.simulatorSetPath,i);if("android"===e.platform)return tZ(t),await tQ(e.id,t,n,o,i);if("macos"===e.platform)return await t5(t,n,o,i);throw n.end(),new tI("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rg(e){let t=await t1({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:t7(t.text,{path:`${e.appLogPath} (simctl log show recovery)`,backend:"ios-simulator",maxEntries:e.maxEntries,include:e.include,maxPayloadChars:e.maxPayloadChars,maxScanLines:e.maxScanLines}),recoveredLineCount:t.recoveredLineCount}:null}async function rw(e){await e.stop(),await tK(e.wait)}async function rv(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 tw("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await tw("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 tw("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 tw("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await tw("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function ry(e){let t=n.dirname(e),r=n.basename(e);a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),a.existsSync(e)?a.truncateSync(e,0):a.writeFileSync(e,"","utf8");let i=0;for(let e of a.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let o=e.slice(r.length+1);if(/^\d+$/.test(o))try{a.unlinkSync(n.join(t,e)),i+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:i}}let rI=new Map;function rS(e){let t=rI.get(e);if(t&&(clearTimeout(t.timer),rI.delete(e),t.deleteAfterDownload))try{a.rmSync(t.artifactPath,{force:!0})}catch{}}let rA=new Map;function rb(e,t){let r=rA.get(e);if(!r)throw new tI("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tI("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function r_(e){let t=rA.get(e);t&&(clearTimeout(t.timer),rA.delete(e),a.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rN(e){let t=await rx(e);await tw("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=n.join(e.tempDir,t);if(!a.existsSync(r))throw new tI("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rx(e){let t=await tw("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new tI("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 tI("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rM),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 tI("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new tI("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 tI("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 tI("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 tI("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await tw("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new tI("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rM(e){if(e.includes("\0"))throw new tI("INVALID_ARGS",`Invalid archive entry: ${e}`);if(n.posix.isAbsolute(e))throw new tI("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=n.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new tI("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rk=eW(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rD(e,t){return new Promise((r,i)=>{let n,o=a.createWriteStream(t),s=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,u=e=>{if(!l){if(l=!0,n&&clearTimeout(n),e){o.destroy(),a.rmSync(t,{force:!0}),i(e);return}r()}},c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let e=new tI("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rk});s(e),o.destroy(e),u(e)},rk)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new tI("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");s(e),o.destroy(e),u(e)}}),e.on("error",u),e.on("aborted",()=>{u(new tI("COMMAND_FAILED","Artifact transfer was interrupted"))}),o.on("error",u),o.on("finish",()=>u()),c(),e.pipe(o)})}async function rP(e){let t,r=e.headers["x-artifact-type"],i=e.headers["x-artifact-filename"];if(!r||!i)throw new tI("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new tI("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 tI("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let o=function(e){let t=e.trim(),r=n.basename(t);if(!r||"."===r||".."===r)throw new tI("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(i),s=(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"),a.mkdtempSync(n.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=n.join(s,o);return await rD(e,t),{artifactPath:t,tempDir:s}}let t=n.join(s,"artifact.tar");await rD(e,t);let i=await rN({archivePath:t,tempDir:s,platform:"ios",expectedRootName:o});return a.rmSync(t,{force:!0}),{artifactPath:i,tempDir:s}}catch(e){throw a.rmSync(s,{recursive:!0,force:!0}),e}}let rL=new Set(["agent_device.command","agent-device.command"]),rR=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rO=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rE={"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"},rC=new Set([...rL,...rR,...rO,...Object.keys(rE)]);function r$(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rT(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rF(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rU(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 rG(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rV(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rq(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=ty(new tI("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=ty(new tI(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=eK(r.tenantId);if(!e){let e=ty(new tI("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:r$(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rj(){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=n.isAbsolute(t)?t:n.resolve(t);try{e=await import(d(a).href)}catch(e){throw new tI("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 tI("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rB(e){let t=await rj(),{handleRequest:r,token:a}=e;return s.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 rH(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rK(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||rT(i,r$(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rT(i,r$(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rT(i,r$(a.id??null,-32600,"Invalid Request"),400);if(!rC.has(a.method))return void rT(i,r$(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rT(i,r$(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rL.has(e))return{token:rU(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(rR.has(e)){let e,a=rG(t,"platform");if("ios"!==a&&"android"!==a)throw new tI("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rU(t,r),session:rG(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rG(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new tI("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new tI("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 tI("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 tI("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 tI("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new tI("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rV(t,"retentionMs")}}}if(rO.has(e)){let e=rG(t,"materializationId")?.trim();if(!e)throw new tI("INVALID_ARGS","Invalid params: materializationId is required");return{token:rU(t,r),session:rG(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rG(t,"requestId"),materializationId:e}}}let a=rE[e];if(a)return{token:rU(t,r),session:rG(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rG(t,"tenantId")??rG(t,"tenant"),runId:rG(t,"runId"),leaseId:rG(t,"leaseId"),leaseTtlMs:rV(t,"ttlMs"),leaseBackend:rG(t,"backend")}};throw new tI("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rL.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rT(i,r$(a.id??null,-32602,"Invalid params: command is required"),400);o=U(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},b(o);let d=()=>{i.writableFinished||e4(o)};e.on("aborted",d),i.on("close",d);let u=await rq(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rT(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 rT(i,{jsonrpc:"2.0",id:a.id??null,result:c});rT(i,r$(a.id??null,-32e3,c.error.message,c.error),rF(c.error.code))}catch(t){let e=ty(t);rT(i,r$(a.id??null,-32e3,e.message,e),rF(e.code))}finally{K(o)}})})}async function rH(e,t,a,i){try{var n;let o,s,l=rU({},e.headers),d=rz(l,i);if(d){t.statusCode=rF(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await rq(a,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await rP(e),f=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},o=r.randomUUID(),(s=setTimeout(()=>{r_(o)},3e5)).unref(),rA.set(o,{artifactPath:n.artifactPath,tempDir:n.tempDir,tenantId:n.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:f}))}catch(r){let e=ty(r);t.statusCode=rF(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rK(e,t,r,i){let n=e.url?.slice("/upload/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let o=rU({},e.headers),s=rz(o,i);if(s){t.statusCode=rF(s.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.message,code:s.code}));return}let l=await rq(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:o,session:"default",command:"download_artifact",positionals:[n]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let d=function(e,t){let r=rI.get(e);if(!r)throw new tI("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tI("UNAUTHORIZED","Artifact belongs to a different tenant");if(!a.existsSync(r.artifactPath))throw rS(e),new tI("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),u=a.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=ty(e);t.statusCode=rF(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rS(n)}),u.pipe(t)}catch(r){let e=ty(r);t.statusCode=rF(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rz(e,t){return t&&e!==t?ty(new tI("UNAUTHORIZED","Invalid token")):null}function rW(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rJ(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rZ(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new tI("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rY{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=rZ(e.backend),a=eK(e.tenantId);if(!a)throw new tI("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=rW(e.runId);if(!i)throw new tI("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(a,i,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,n);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),d={leaseId:r.randomBytes(16).toString("hex"),tenantId:a,runId:i,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+n};return this.leases.set(d.leaseId,d),this.runBindings.set(o,d.leaseId),{...d}}heartbeatLease(e){let t=rJ(e.leaseId);if(!t)throw new tI("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new tI("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=rJ(e.leaseId);if(!t)throw new tI("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=rZ(e.backend),r=eK(e.tenantId);if(!r)throw new tI("INVALID_ARGS","tenant isolation requires tenant id.");let a=rW(e.runId);if(!a)throw new tI("INVALID_ARGS","tenant isolation requires run id.");let i=rJ(e.leaseId);if(!i)throw new tI("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new tI("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new tI("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 tI("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 tI("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=eK(t),i=rW(r);if(t&&!a)throw new tI("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new tI("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 tI("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rX=eW(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),rQ=new Map;async function r0(e){let t=await c.mkdtemp(n.join(u.tmpdir(),"agent-device-materialized-"));try{let a=await r5(e.installablePath,n.join(t,"installable")),i=e.archivePath?await r5(e.archivePath,n.join(t,"archive")):void 0,o=r.randomUUID(),s=e.ttlMs??rX,l=Date.now()+s,d=setTimeout(()=>{r1(o)},s);return rQ.set(o,{rootPath:t,installablePath:a,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:l,timer:d}),{materializationId:o,installablePath:a,...i?{archivePath:i}:{},expiresAt:new Date(l).toISOString()}}catch(e){throw await c.rm(t,{recursive:!0,force:!0}),e}}async function r1(e,t){let r=rQ.get(e);if(!r)throw new tI("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tI("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),rQ.delete(e),await c.rm(r.rootPath,{recursive:!0,force:!0})}async function r2(e){let t=Array.from(rQ.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await r1(e)}))}async function r5(e,t){let r=await c.stat(e);await c.mkdir(t,{recursive:!0});let a=n.join(t,n.basename(e));return r.isDirectory()?await c.cp(e,a,{recursive:!0}):await c.copyFile(e,a),a}async function r4(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 tI("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await e9(e.session.device),e.session.device}if(!r)throw new tI("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await eR(e.flags??{});return await e9(a),a}async function r3(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 tI("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new tI("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new tI("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:rb(o,t.meta?.tenantId)},cleanup:()=>{r_(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 tI("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await r4({session:i,flags:t.flags});if(!tl("install",d))return N("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let u=th(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await import("./155.js"),{prepareIosInstallArtifact:o}=await import("./155.js"),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await r0({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 tI("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=ev(o,r8(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await r1(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await import("./155.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("./155.js"),p=await c(s.source,{signal:u});try{l.enabled&&(e=await r0({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await f(d,p.installablePath,p.packageName);if(!n)throw new tI("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await import("./155.js"),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=ev(u,r8(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await r1(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:ty(e)}}}function r8(e){return`Installed: ${ee(e)}`}async function r6(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new tI("INVALID_ARGS","release_materialized_paths requires a materializationId");return await r1(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:ty(e)}}}let r9=eW(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),r7=eW(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function ae(e,t,r){return t||at(r)?null:N("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function at(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function ar(e){return"ios"===e.platform&&"simulator"===e.kind}async function aa(e,t){ar(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function ai(e){let t=at(e.flags)||!e.session?await eR(e.flags??{}):await an(e.session.device);return!1!==e.ensureReady&&await e9(t),t}async function an(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 eR(t)}catch(e){if(!(e instanceof tI)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await eR({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function ao(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 as=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function al(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function ad(e){let t=e?.trim();return t&&t.length>0?t:void 0}function au(e,t){if(void 0!==e){if("string"!=typeof e)throw new tI("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return ad(e)}}function ac(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new tI("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function af(e){if("ios"===e||"android"===e)return e}async function ap(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!em(r)||em(a)||await eG({device:i.device,appId:i.appBundleId})}async function am(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 N("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){em(l)&&s?.appBundleId&&await eG({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=af(tf(a.flags?.platform)??l?.platform??s?.device.platform);if(!d)return N("INVALID_ARGS","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 N("INVALID_ARGS",`runtime set targets ${d}, but session "${i}" is already bound to ${s.device.platform}.`);let u={platform:(t=a.flags,r={platform:d,metroHost:ad(t?.metroHost),metroPort:ac(t?.metroPort),bundleUrl:ad(t?.bundleUrl),launchUrl:ad(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===al(u)?N("INVALID_ARGS","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 ah="open-command-roundtrip",ag="Not implemented for this platform in this release.",aw=new Set(["app","desktop","frontmost-app"]);async function av(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await tn();return{appBundleId:t.bundleId,appName:t.appName}}async function ay(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return eU(t)?"macos"===e.platform?void 0:"device"===e.kind?e3(r,t):void 0:await aI(e,t)}async function aI(e,t){try{let{resolveIosApp:r}=await import("./155.js");return await r(e,t)}catch{return}}async function aS(e,t){if(!("android"!==e.platform||!t||eU(t)))try{let{resolveAndroidApp:r}=await import("./155.js"),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function aA(e,t,r,a){return await ay(e,t,r)??await a(e,t)??("android"===e.platform&&t&&eU(t)?r:void 0)}function ab(e){return N("INVALID_ARGS",e)}function a_(e,t,r,a){try{return function(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:i}=e;if(("macos"===t.platform||"linux"===t.platform)&&!r)return i??"app";if("linux"===t.platform){if(!r)return"app";let e=ed(r);if(!aw.has(e))throw new tI("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new tI("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new tI("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let n=r?ed(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new tI("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return N(e instanceof tI?e.code:"INVALID_ARGS",String(e.message))}}function aN(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&eU(r)?ab("open --relaunch does not support URL targets."):"app"!==a?ab("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===e$(r)?ab(q(r)):null:null}async function ax(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await e9(i);let{appBundleId:l,appName:d}=await aM({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 tI("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!as.includes(e));if(i)throw new tI("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${as.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new tI("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new tI("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:au(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new tI("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return ac(e)}}(t.metroPort),bundleUrl:au(t.bundleUrl,"bundleUrl"),launchUrl:au(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:af(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=af(i);if(a.platform&&r&&!n)throw new tI("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 tI("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&&al(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=tv(t);return N(e.code,e.message,e.details)}}({req:t,sessionStore:a,sessionName:r,device:i});if(!u.ok)return{type:"response",response:u};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await ap({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function aM(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await av(r);return{appBundleId:n.appBundleId??await aA(t,a,i,aS),appName:n.appName??a}}let ak=new Map;async function aD(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await eI(t.id),await w(t,"close",[r],a,i),await aa(t,r9)}async function aP(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||eU(d)||await w(r,"open",[l],a.flags?.out,{...eV(i,a.flags,n,o)})}async function aL(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:f,appBundleId:p,runtime:m,existingSession:h}=e,g=i.flags?.relaunch===!0,v=h?.trace?.outPath;if(g&&d){let e=p??d;await aD({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...eV(s,i.flags,p??h?.appBundleId,v)}})}await eL({device:l,appId:p,runtime:m});let y=Date.now();await w(l,"open",u,i.flags?.out,{...eV(s,i.flags,p)}),await aP({runtime:m,device:l,req:i,logPath:s,appBundleId:p,traceLogPath:v,openPositionals:u});let I=d?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:ah,appTarget:d,appBundleId:p}:void 0;if(await aa(l,r7),F(i.meta?.requestId)){let e=eA();return N(e.code,e.message,e.details)}h&&tm(h,"open",h.snapshot);let S=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:f,appBundleId:p,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===al(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,...M(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:p,surface:f,startup:I,device:l,runtime:m,runtimeHintCount:al});return o.recordAction(S,{command:"open",positionals:u,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:A}),o.set(n,S),{ok:!0,data:A}}async function aR(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return N("SESSION_NOT_FOUND",`Session "${r}" not found.`);let n=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(n?e.appName:void 0),l=a_(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?ab("open --relaunch requires an app name or an active session app."):ab("Session already active. Close it first or pass a new --session name.");let d=aN({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await an(e.device),c=await ax({req:t,sessionName:r,sessionStore:i,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await aL({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 ab("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&eU(r)?ab("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===e$(r)?ab(q(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await eR(t.flags??{}),d=a_(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=aN({shouldRelaunch:n,openTarget:o,surface:d,device:l});return u||await D(ak,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return N("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name});let n=await ax({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:o});return"response"===n.type?n.response:await aL({req:t,sessionName:r,sessionStore:i,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:n.details.appBundleId,appName:n.details.appName,runtime:n.details.runtime,surface:d})})}async function aO(e){let t=await tw("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 aE(e){let{device:t,shutdownRequested:r}=e;if(r&&(ar(t)||"android"===t.platform&&"emulator"===t.kind))try{return ar(t)?await ey(t):await aO(t)}catch(t){let e=ty(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function aC(e){if(await eI(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await eF("dismiss",t).catch(t=>{ti({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function a$(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return N("SESSION_NOT_FOUND","No active session");n.appLog&&await rw(n.appLog),t.positionals&&t.positionals.length>0&&(("ios"===n.device.platform||"macos"===n.device.platform)&&await aC(n),await w(n.device,"close",t.positionals,t.flags?.out,{...eV(a,t.flags,n.appBundleId,n.trace?.outPath)}),await aa(n.device,r9)),("ios"===n.device.platform||"macos"===n.device.platform)&&await aC(n),em(i.getRuntimeHints(r))&&n.appBundleId&&await eG({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...M(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await r2(r).catch(()=>{}),i.delete(r);let o=await aE({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:ev({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...M(`Closed: ${r}`)}}}let aT=["platform","target","device","udid","serial","verbose","out"];function aF(e,t){let r=e??{};for(let e of aT)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let aU={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await import("./155.js");return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await import("./155.js");return await a(e,t,r)}},aG={ios:async(e,t,r)=>{let{installIosApp:a}=await import("./155.js"),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 import("./155.js"),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function aV(e){let{req:t,command:r,sessionName:i,sessionStore:n,deployOps:o}=e,s=n.get(i),l=t.flags??{},d=ae(r,s,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return N("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let f=t.meta?.uploadedArtifactId;try{var p;let e,i=f?rb(f,t.meta?.tenantId):tG.expandHome(c);if(!a.existsSync(i))return N("INVALID_ARGS",`App binary not found: ${i}`);let d=await ai({session:s,flags:l,ensureReady:!1});if(!tl(r,d))return N("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await o.ios(d,u,i),r=t.bundleId;e=r?{app:u,appPath:i,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:i,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await o.android(d,u,i),r=t.package;e=r?{app:u,appPath:i,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:i,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=ev(e,(p=e,`Installed: ${p.appName??eh(p)}`));return s&&n.recordAction(s,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&r_(f)}}async function aq(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return N("INVALID_ARGS",`Unsupported batch on-error mode: ${a}.`);let i=e.flags?.batchMaxSteps??P;if(!Number.isInteger(i)||i<1||i>1e3)return N("INVALID_ARGS",`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`);try{let a=ec(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await aj(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=tv(t);return N(e.code,e.message,e.details)}}async function aj(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{};return aF(e,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 aB(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new tI("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await aH({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await aK({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await az(t,u),a=!0)}else t=(await aK({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await az(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 aH(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await tw("xcrun",g(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:J});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||aW(a).includes(aW(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 aK(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await tw("xcrun",g(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new tI("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 tI("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function az(e,t){let r=await tw("xcrun",g(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:J});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 aW(e){return e.toLowerCase().replace(/[._-]/g,"")}async function aJ(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=e5(e.iosSimulatorDeviceSet);if(!r)return N("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await aB({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:e9});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=tv(t);return N(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=er(t.flags?.androidDeviceAllowlist),a=tf(t.flags?.platform),i=h({simulatorSetPath:e5(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("./155.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("./155.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("./155.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("./155.js");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=tv(t);return N(e.code,e.message,e.details)}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=ae(t.command,e,i);if(n)return n;let o=await ai({session:e,flags:i,ensureReady:!0});if(!tl("apps",o))return N("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(Q(o.platform)){let{listIosApps:e}=await import("./155.js");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 import("./155.js");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 aZ(e){let{ensureAndroidEmulatorBooted:t}=await import("./155.js");return await t(e)}let aY='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',aX='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function aQ(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=tf(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return N("SESSION_NOT_FOUND","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=ae("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(!at(e))return!0;let r=tf(e?.platform);return!(r&&!ts(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(n,i);if("ios"===o&&!l)return N("SESSION_NOT_FOUND",aY);if("macos"===o&&!l)return N("SESSION_NOT_FOUND",aX);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 N("COMMAND_FAILED",`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 ai({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return N("SESSION_NOT_FOUND",aY);if("macos"===d.platform)return N("SESSION_NOT_FOUND",aX);let{getAndroidAppState:u}=await import("./155.js"),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function a0(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=ae(t.command,i,n);if(o)return o;let s="android"===(tf(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!s)return N("INVALID_ARGS","boot --headless is supported only for Android emulators.");let d=ao({flags:n,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await ai({session:i,flags:n,ensureReady:!1})}catch(r){let t=tv(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return N("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await aZ({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return N("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return N("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=ao({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return N("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await aZ({avdName:t,serial:n.serial,headless:!0})}await e9(e)}else("android"!==e.platform||!0!==e.booted)&&await e9(e);return tl("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:N("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await aQ({req:t,sessionName:r,sessionStore:a}):null}function a1(e){return Math.round(10*e)/10}let a2="adb-shell-dumpsys-cpuinfo",a5="adb-shell-dumpsys-meminfo";async function a4(e,t){try{let r=await tw("adb",eQ(e,["shell","dumpsys","cpuinfo"]),{timeoutMs:15e3});return function(e,t,r){let a=new Set,i=0;for(let r of e.split("\n")){var n,o;let e=r.trim();if(0===e.length)continue;let s=e.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!s)continue;let l=Number(s[1]),d=s[2];Number.isFinite(l)&&(n=d,o=t,n===o||n.startsWith(`${o}:`))&&(i+=l,a.add(d))}return{usagePercent:a1(i),measuredAt:r,method:a2,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw a8("cpu",t,e)}}async function a3(e,t){try{let r=await tw("adb",eQ(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new tI("COMMAND_FAILED",`Android meminfo did not find a running process for ${t}`,{metric:"memory",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf."});let a=a6(e,"TOTAL PSS")??function(e){for(let t of e.split("\n")){let e=t.trim();if(!/^TOTAL\b(?!\s+PSS:)/.test(e))continue;let r=e.split(/\s+/).slice(1).find(e=>null!==a9(e));if(!r)break;return a9(r)??void 0}}(e);if(void 0===a)throw new tI("COMMAND_FAILED",`Failed to parse Android meminfo output for ${t}`,{metric:"memory",package:t,hint:"Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging."});return{totalPssKb:a,totalRssKb:a6(e,"TOTAL RSS"),measuredAt:r,method:a5}}(r.stdout,t,new Date().toISOString())}catch(e){throw a8("memory",t,e)}}function a8(e,t,r){return r instanceof tI&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new tI(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof tI?r:new tI("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function a6(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return a9(a[1])??void 0}function a9(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let a7="ps-process-snapshot",ie="ps-process-snapshot",it="xctrace-activity-monitor",ir="xctrace-activity-monitor";async function ia(e,t){if("ios"===e.platform&&"device"===e.kind)return await is(e,t);let r=await io(e,t),a=await im(e,r);if(0===a.length)throw new tI("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,hint:"Run open <app> for this session again to ensure the Apple app is active, then retry perf."});let i=new Date().toISOString(),o=k(a.map(e=>n.basename(ih(e.command))));return ig({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:o,cpuMethod:a7,memoryMethod:ie})}async function ii(e){let t=z(e),r=iw(t,e=>"schema"===e.name&&"activity-monitor-process-live"===e.attributes.name);if(!r)throw new tI("COMMAND_FAILED","Failed to parse xctrace activity-monitor-process-live schema");let a=r.children.filter(e=>"col"===e.name).map(e=>{let t;return t=e.children.find(e=>"mnemonic"===e.name),t?.text??null??""}),i=a.indexOf("pid"),n=a.indexOf("process"),o=a.indexOf("cpu-total"),s=a.indexOf("memory-real");if(i<0||n<0||o<0||s<0)throw new tI("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let l=function e(t,r){let a=[];for(let i of t)r(i)&&a.push(i),a.push(...e(i.children,r));return a}(t,e=>"row"===e.name),d=[],u=new Map;for(let e of l){var c,f;let t=e.children;if(0===t.length)continue;for(let e of t){let t=iw(e.children,e=>"pid"===e.name&&"string"==typeof e.attributes.id);if(t?.attributes.id){let e=Number(t.text);u.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&u.set(e.attributes.id,{numberValue:iv(e),processName:iI(e)})}let r=iy(t[i],u),a=(c=t[n],f=u,c?c.attributes.ref?f.get(c.attributes.ref)?.processName??null:iI(c):null);null!==r&&Number.isFinite(r)&&a&&d.push({pid:r,processName:a,cpuTimeNs:iy(t[o],u),residentMemoryBytes:iy(t[s],u)})}return d}async function io(e,t){let r="macos"===e.platform?await ic(t):await ip(e,t),a="macos"===e.platform?n.join(r,"Contents","Info.plist"):n.join(r,"Info.plist"),i=await te(a,"CFBundleExecutable");if(!i)throw new tI("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?n.join(r,"Contents","MacOS",i):void 0}}async function is(e,t){let r=await il(e,t),a=await id(e,t),i=await id(e,t),n=iu(await ii(a.xml),r,t,e),o=iu(await ii(i.xml),r,t,e),s=i.capturedAtMs-a.capturedAtMs;if(s<=0)throw new tI("COMMAND_FAILED",`Invalid Activity Monitor sample window for ${t}`,{appBundleId:t,deviceId:e.id});if(null===n.cpuTimeNs||null===o.cpuTimeNs||null===o.residentMemoryBytes)throw new tI("COMMAND_FAILED",`Incomplete Activity Monitor sample for ${t}`,{appBundleId:t,deviceId:e.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});return ig({usagePercent:Math.max(0,o.cpuTimeNs-n.cpuTimeNs)/(1e6*s)*100,residentMemoryKb:o.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:o.matchedProcesses,cpuMethod:it,memoryMethod:ir})}async function il(e,t){let r=(await Z(e,"all")).find(e=>e.bundleId===t);if(!r)throw new tI("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new tI("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let a=r.url.replace(/\/$/,""),i=l(a),n=(await en(e)).filter(e=>e.executable.startsWith(`${a}/`));if(0===n.length)throw new tI("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,deviceId:e.id,appBundlePath:i,hint:"Run open <app> for this session again to ensure the iOS app is active, then retry perf."});return n}async function id(e,t){let r=await i.mkdtemp(n.join(u.tmpdir(),"agent-device-ios-perf-")),a=n.join(r,"sample.trace"),o=n.join(r,"activity-monitor-process-live.xml");try{let r=["xctrace","record","--template","Activity Monitor","--device",e.id,"--all-processes","--time-limit","1s","--output",a,"--quiet","--no-prompt"],n=await tw("xcrun",r,{allowFailure:!0,timeoutMs:6e4}),s=Date.now();if(0!==n.exitCode)throw new tI("COMMAND_FAILED",`Failed to record iOS device Activity Monitor sample for ${t}`,{cmd:"xcrun",args:r,exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,appBundleId:t,deviceId:e.id,hint:iS(n.stdout,n.stderr)});let l=["xctrace","export","--input",a,"--xpath",'/trace-toc/run/data/table[@schema="activity-monitor-process-live"]',"--output",o],d=await tw("xcrun",l,{allowFailure:!0,timeoutMs:15e3});if(0!==d.exitCode)throw new tI("COMMAND_FAILED",`Failed to export iOS device perf sample for ${t}`,{cmd:"xcrun",args:l,exitCode:d.exitCode,stdout:d.stdout,stderr:d.stderr,appBundleId:t,deviceId:e.id,hint:iS(d.stdout,d.stderr)});return{capturedAtMs:s,xml:await i.readFile(o,"utf8")}}finally{await i.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function iu(e,t,r,a){let i=new Set(t.map(e=>e.pid)),o=new Set(t.map(e=>n.basename(l(e.executable)))),s=e.filter(e=>i.has(e.pid)||o.has(e.processName));if(0===s.length)throw new tI("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:a.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let d=new Map;for(let e of s){let t=d.get(e.pid);if(!t){d.set(e.pid,e);continue}d.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:iA(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iA(t.residentMemoryBytes,e.residentMemoryBytes)})}let u=[...d.values()],c=u.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=u.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:c.length>0?c.reduce((e,t)=>e+t,0):null,residentMemoryBytes:f.length>0?f.reduce((e,t)=>e+t,0):null,matchedProcesses:k(u.map(e=>e.processName))}}async function ic(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await tw("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new tI("COMMAND_FAILED",`Failed to resolve macOS app bundle for ${e}`,{appBundleId:e,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let a=r.stdout.split("\n").map(e=>e.trim()).find(e=>e.endsWith(".app"));if(!a)throw new tI("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function ip(e,t){let r=tr(e,["get_app_container",e.id,t,"app"]),a=await tw("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new tI("COMMAND_FAILED",`Failed to resolve iOS simulator app container for ${t}`,{appBundleId:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Ensure the iOS simulator app is installed and booted, then retry perf."});let i=a.stdout.trim();if(0===i.length)throw new tI("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return i}async function im(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:tr(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let a=e.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!a)continue;let i=Number(a[1]),n=Number(a[2]),o=Number(a[3]),s=a[4].trim();Number.isFinite(i)&&Number.isFinite(n)&&Number.isFinite(o)&&t.push({pid:i,cpuPercent:n,rssKb:o,command:s})}return t})((await tw("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let i;return r=e.command,a=t,i=ih(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||n.basename(i)===a.executableName})}function ih(e){let[t=""]=e.trim().split(/\s+/,1);return t}function ig(e){return{cpu:{usagePercent:a1(e.usagePercent),measuredAt:e.measuredAt,method:e.cpuMethod,matchedProcesses:e.matchedProcesses},memory:{residentMemoryKb:Math.round(e.residentMemoryKb),measuredAt:e.measuredAt,method:e.memoryMethod,matchedProcesses:e.matchedProcesses}}}function iw(e,t){for(let r of e){if(t(r))return r;let e=iw(r.children,t);if(e)return e}}function iv(e){if(!e||e.children.some(e=>"sentinel"===e.name)||!e.text)return null;let t=Number(e.text);return Number.isFinite(t)?t:null}function iy(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:iv(e):null}function iI(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function iS(e,t){let r=e_(e,t);if(r)return r;let a=`${e}
|
|
6
|
+
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?$:a.includes("timed out")?"Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.":"Ensure the iOS device is unlocked, trusted, visible to xctrace, and the target app stays active while perf samples it."}function iA(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function ib(e){var t;let r=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===ah&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:ah,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(e.actions),a=r.at(-1),i=a?{available:!0,lastDurationMs:a.durationMs,lastMeasuredAt:a.measuredAt,method:ah,sampleCount:r.length,samples:r}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:ah},n={session:e.name,platform:e.device.platform,device:e.device.name,deviceId:e.device.id,metrics:{startup:i,fps:{available:!1,reason:ag},memory:{available:!1,reason:ag},cpu:{available:!1,reason:ag}},sampling:{startup:{method:ah,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"},...function(e){if("android"===e.device.platform)return{memory:{method:a5,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:a2,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"}};var t=e.device;if("ios"===t.platform&&"device"===t.kind)return{memory:{method:ir,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:it,description:"Recent CPU usage snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"percent"}};let r="macos"===t.platform?"host ps for the running macOS app executable resolved from the bundle ID.":"xcrun simctl spawn ps for the running iOS simulator app executable resolved from the bundle ID.";return{memory:{method:ie,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:a7,description:`Recent CPU usage snapshot from ${r}`,unit:"percent"}}}(e)}};if("android"!==(t=e).device.platform&&"ios"!==t.device.platform&&"macos"!==t.device.platform)return n;if(!e.appBundleId){let t="android"===e.device.platform?"No Android app package is associated with this session. Run open <app> first.":"No Apple app bundle ID is associated with this session. Run open <app> first.";return n.metrics.memory={available:!1,reason:t},n.metrics.cpu={available:!1,reason:t},n}let[o,s]=await i_(e);return n.metrics.memory=iN(o),n.metrics.cpu=iN(s),n}async function i_(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,a]=await Promise.allSettled([a3(e.device,t),a4(e.device,t)]);return[r,a]}try{let r=await ia(e.device,t);return[{status:"fulfilled",value:r.memory},{status:"fulfilled",value:r.cpu}]}catch(e){return[{status:"rejected",reason:e},{status:"rejected",reason:e}]}}function iN(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=ty(e.reason);return{available:!1,reason:t.message,error:t}}let ix=["path","start","stop","doctor","mark","clear"],iM=`logs requires ${ix.slice(0,-1).join(", ")}, or ${ix.at(-1)}`,ik=["dump","log"],iD=`network requires ${ik.join(" or ")}`,iP=["summary","headers","body","all"],iL=`network include mode must be one of: ${iP.join(", ")}`;async function iR(e){let{req:t}=e;return"perf"===t.command?iO(e):"logs"===t.command?iE(e):"network"===t.command?iU(e):null}async function iO(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return N("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await ib(a)}}catch(e){return{ok:!1,error:ty(e)}}}async function iE(e){let{req:t,sessionName:r,sessionStore:i}=e,n=i.get(r);if(!n)return N("SESSION_NOT_FOUND","logs requires an active session");if(!tl("logs",n.device))return N("UNSUPPORTED_OPERATION","logs is not supported on this device");let o=(t.positionals?.[0]??"path").toLowerCase(),s=!!t.flags?.restart;return ix.includes(o)?s&&"clear"!==o?N("INVALID_ARGS","logs --restart is only supported with logs clear"):"path"===o?function(e,t,r){let i=r.resolveAppLogPath(t),n=function(e){if(!a.existsSync(e))return{exists:!1,sizeBytes:0};let t=a.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(i);return{ok:!0,data:{path:i,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android",sizeBytes:n.sizeBytes,modifiedAt:n.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}(n,r,i):"doctor"===o?iC(n,r,i):"mark"===o?function(e,t,r){let i,n=e.positionals?.slice(1).join(" ")??"",o=r.resolveAppLogPath(t);return rf(o),i=`[agent-device][mark][${new Date().toISOString()}] ${n.trim()||"marker"}
|
|
7
|
+
`,a.appendFileSync(o,i,"utf8"),{ok:!0,data:{path:o,marked:!0}}}(t,r,i):"clear"===o?i$(n,r,i,s):"start"===o?iT(n,r,i):"stop"===o?iF(n,r,i):N("INVALID_ARGS",iM):N("INVALID_ARGS",iM)}async function iC(e,t,r){let a=r.resolveAppLogPath(t),i=await rv(e.device,e.appBundleId);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}async function i$(e,t,r,a){if(e.appLog&&!a)return N("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return N("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let i=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:ry(i)};e.appLog&&await rw(e.appLog);let n=ry(i),o=r.resolveAppLogPidPath(t);try{let a=await rh(e.device,e.appBundleId,i,o);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:i,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}}),{ok:!0,data:{...n,restarted:!0}}}catch(a){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:ty(a)}}}async function iT(e,t,r){if(e.appLog)return N("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return N("INVALID_ARGS","logs start requires an app session; run open <app> first");let a=r.resolveAppLogPath(t),i=r.resolveAppLogPidPath(t);try{let n=await rh(e.device,e.appBundleId,a,i);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:a,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{path:a,started:!0}}}catch(e){return{ok:!1,error:ty(e)}}}async function iF(e,t,r){if(!e.appLog)return N("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await rw(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function iU(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return N("SESSION_NOT_FOUND","network requires an active session");if(!tl("network",i.device))return N("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!ik.includes(n))return N("INVALID_ARGS",iD);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return N("INVALID_ARGS","network dump limit must be an integer in range 1..200");let s=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return N("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return iP.includes(a)?{ok:!0,include:a}:N("INVALID_ARGS",iL)}(t);if(!s.ok)return s;let{include:l}=s,d=await rp({device:i.device,appBundleId:i.appBundleId,appLogState:i.appLog?.getState(),appLogStartedAt:i.appLog?.startedAt,appLogPath:a.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...d.dump,active:!!i.appLog,state:i.appLog?.getState()??"inactive",backend:d.backend,notes:d.notes}}}let iG=new Set(["ios","android","macos","linux"]);function iV(e,t,r){let a=e[t];if(void 0!==a)throw new tI("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 iq(e){return!!e&&!Number.isNaN(Number(e))}let ij=/[*?[\]{}]/;async function iB(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,runReplay:s,cleanupSession:l}=e;b(i);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:i,artifactPaths:d}).catch(e=>{let t=tv(e);return N(t.code,t.message)}).finally(()=>{K(i)});try{return"number"==typeof n?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,e4(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 iH(c)||ti({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await l(a)}catch(e){ti({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:tv(e).message}})}}}async function iH(e){return await Promise.race([e.then(()=>!0),f(2e3).then(()=>!1)])}async function iK(e){let{req:t,sessionName:r,runReplay:i,cleanupSession:o}=e;if((t.positionals?.length??0)===0)return N("INVALID_ARGS","test requires at least one path or glob");try{var s,l,d,u,c,f;let e,p,m,h,g,w=function(e){let{inputs:t,cwd:r,platformFilter:i}=e,o=r??process.cwd(),s=[...new Set(t.flatMap(e=>(function(e,t){var r,i;let o=tG.expandHome(e,t);if(a.existsSync(o)){let t=a.statSync(o);if(t.isDirectory())return a.globSync("**/*.ad",{cwd:o}).map(e=>n.join(o,e));if(t.isFile()){if(".ad"!==n.extname(o))throw new tI("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[o]}return[]}if(r=e,!ij.test(r)&&(i=o,!ij.test(i)))throw new tI("INVALID_ARGS",`test input not found: ${e}`);let s=n.isAbsolute(o)?o:e;return a.globSync(s,{cwd:n.isAbsolute(o)?void 0:t}).map(e=>n.isAbsolute(e)?e:n.resolve(t,e)).filter(e=>".ad"===n.extname(e)&&function(e){try{return a.statSync(e).isFile()}catch{return!1}}(e))})(e,o)))].map(e=>n.normalize(e)).sort((e,t)=>e.localeCompare(t)),l=[];for(let e of s){var d,u;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&&iG.has(e)&&iV(r,"platform",e)}let i=t.match(/(?:^|\s)timeout=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=1&&iV(r,"timeoutMs",Math.floor(e))}let n=t.match(/(?:^|\s)retries=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=0&&iV(r,"retries",Math.floor(e))}}return r}(a.readFileSync(e,"utf8"));if(!i){l.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){l.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${i}`});continue}d=i,u=t.platform,("apple"===d?"apple"===u||"ios"===u||"macos"===u:u===d)&&l.push({kind:"run",path:e,metadata:t})}if(0===l.filter(e=>"run"===e.kind).length){let e=i?` for --platform ${i}`:"";throw new tI("INVALID_ARGS",`No .ad tests matched${e}.`)}return l}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),v=(s=t.meta?.requestId,(s?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),y=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:a}=e,i=tG.expandHome(t??".agent-device/test-artifacts",r);return n.join(i,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:v}),I=[],S=Date.now(),A=0;for(let e of w){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}A+=1;let a=await iz({entry:e,sessionName:r,suiteInvocationId:v,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:(l=t.flags?.timeoutMs,d=e.metadata.timeoutMs,"number"==typeof l?l:d),suiteArtifactsDir:y,runReplay:i,cleanupSession:o});if(I.push(a),t.flags?.failFast===!0)break}let b=(u=w.length,c=I,f=Date.now()-S,e=c.filter(e=>"passed"===e.status).length,m=(p=c.filter(e=>"failed"===e.status)).length,h=c.filter(e=>"skipped"===e.status).length,g=e+m,{total:u,executed:g,passed:e,failed:m,skipped:h,notRun:Math.max(0,u-g-h),durationMs:f,failures:p,tests:c});return{ok:!0,data:b}}catch(t){let e=tv(t);return N(e.code,e.message)}}async function iz(e){var t,r;let i,o,{entry:s,sessionName:l,suiteInvocationId:d,caseIndex:u,cwd:c,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:g,cleanupSession:w}=e,v=Date.now(),y=n.join(h,(t=s.path,(0===(o=c?n.relative(c,t):n.basename(t)).length||o.startsWith("..")?n.basename(t):o).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",S=0;for(let e=0;e<=p;e+=1){S=e+1;let t=function(e,t,r,a,i=0){let o=n.basename(r,n.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${o?`-${o}`:""}:attempt-${i+1}`}(l,d,s.path,u,e),o=n.join(y,`attempt-${S}`);r=s.path,a.mkdirSync(o,{recursive:!0}),a.copyFileSync(r,n.join(o,"replay.ad"));let c=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:o}=e;return U(`${t??r}:test:${i+1}:${n.basename(a)}:attempt:${o+1}`,r)}({requestId:f,suiteInvocationId:d,filePath:s.path,caseIndex:u,attemptIndex:e}),h=await iB({filePath:s.path,sessionName:t,requestId:c,timeoutMs:m,platform:s.metadata.platform,runReplay:g,cleanupSession:w});if(!function(e){let{response:t,filePath:r,sessionName:i,attempts:o,maxAttempts:s,attemptArtifactsDir:l}=e,d=[...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||d.push(t.error.logPath);let u=function(e,t){let r=[],i=new Map;for(let o of e){if(!function(e){try{return a.statSync(e).isFile()}catch{return!1}}(o))continue;let e=function(e,t){let r=n.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}`}(n.basename(o),i),s=n.join(t,e);n.resolve(o)!==n.resolve(s)&&a.copyFileSync(o,s),r.push(s)}return r}(d,l),c=[`file: ${r}`,`session: ${i}`,`attempt: ${o}/${s}`,`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;c.push(`replayed: ${e}`,`healed: ${r}`)}else c.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&c.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&c.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&c.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&c.push("timeoutMode: cooperative");u.length>0&&c.push(`copiedArtifacts: ${u.map(e=>n.basename(e)).join(", ")}`);let f=n.join(l,"result.txt"),p=`${c.join("\n")}
|
|
8
|
+
`;a.writeFileSync(f,p),t.ok||a.writeFileSync(n.join(l,"failure.txt"),p)}({response:h,filePath:s.path,sessionName:t,attempts:S,maxAttempts:p+1,attemptArtifactsDir:o}),i=h,I=t,h.ok)break}let A=Date.now()-v;if(i?.ok)return{file:s.path,session:I,status:"passed",durationMs:A,attempts:S,artifactsDir:y,replayed:"number"==typeof i.data?.replayed?i.data.replayed:0,healed:"number"==typeof i.data?.healed?i.data.healed:0};let b=i?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:i?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:s.path,session:I,status:"failed",durationMs:A,attempts:S,artifactsDir:y,error:b}}function iW(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=es(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 iJ(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(tx(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),tx(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}=eX(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=iW(e.positionals??[]);r&&t.push(r)}return k(t).filter(e=>e.trim().length>0)})(t).map(e=>B(e)).filter(e=>null!==e);if(0===o.length)return null;let s=tx(t.command)||"fill"===t.command,l=tx(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await iZ(n,t,a,s,i);for(let e of o){let r=A(d.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=ew(r.node,n.device.platform,{action:tx(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tx(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=eg(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}=eX(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}=iW(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function iZ(e,t,r,a,i){let n=await w(e.device,"snapshot",[],t.flags?.out,{...eV(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:ei(t.flags?.snapshotRaw?o:eP(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return e.snapshot=s,i.set(e.name,e),s}async function iY(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,invoke:o}=e,s=t.positionals?.[0];if(!s)return N("INVALID_ARGS","replay requires a path");let l="",d=new Set;try{l=tG.expandHome(s,t.meta?.cwd);let e=a.readFileSync(l,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return N("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let c=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,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 tI("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=tT(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=tT(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tx(a)){let e=t$(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 iq(r)&&iq(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=t$(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=t$(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}if("screenshot"===a){let e=[];for(let t of i){if("--fullscreen"===t){n.flags.screenshotFullscreen=!0;continue}e.push(t)}return n.positionals=e,n}return n.positionals=i,n}(r);e&&t.push(e)}return t}(e),f=t.flags?.replayUpdate===!0,p=0;for(let e=0;e<c.length;e+=1){let a=c[e];if(!a||"replay"===a.command)continue;let s=await iX({req:t,sessionName:r,action:a,invoke:o});if(s.ok){i0(s).forEach(e=>d.add(e));continue}if(!f)return iQ(s,a,e,l,[...d]);let u=await iJ({action:a,sessionName:r,logPath:i,sessionStore:n});if(!u)return iQ(s,a,e,l,[...d]);if(c[e]=u,!(s=await iX({req:t,sessionName:r,action:u,invoke:o})).ok)return iQ(s,u,e,l,[...d]);i0(s).forEach(e=>d.add(e)),p+=1}return f&&p>0&&function(e,t,r){let i=[];if(r){let e=r.device.kind?` kind=${r.device.kind}`:"",t=r.device.target?` target=${r.device.target}`:"";i.push(`context platform=${r.device.platform}${t} device=${tD(r.device.name)}${e} theme=unknown`)}for(let e of t)i.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tk(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tU(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tP(r,tR));return tE(t,e.flags),t.join(" ")}if("record"===e.command)return tC(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tk(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}for(let r of e.positionals??[])t.push(tk(r));return tO(t,e),t.join(" ")}(e));let n=`${i.join("\n")}
|
|
9
|
+
`,o=`${e}.tmp-${process.pid}-${Date.now()}`;a.writeFileSync(o,n),a.renameSync(o,e)}(l,c,n.get(r)),{ok:!0,data:{replayed:c.length,healed:p,session:r,artifactPaths:[...d]}}}catch(t){let e=tv(t);return N(e.code,e.message,d.size>0?{artifactPaths:[...d]}:void 0)}}async function iX(e){var t;let{req:r,sessionName:a,action:i,invoke:n}=e;return await n({token:r.token,session:a,command:i.command,positionals:i.positionals??[],flags:(t=r.flags,aF(t,{...i.flags??{}})),runtime:i.runtime,meta:r.meta})}function iQ(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=>tk(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 i0(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 a.statSync(e).isFile()}catch{return!1}})(e)))]}async function i1(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await iY({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await iK({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await iY({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&&i0(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{i.get(e)&&await a$({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let i2=new Set(["session_list","ensure-simulator","devices","apps"]),i5=new Set(["boot","appstate"]),i4=new Set(["perf","logs","network"]),i3=new Set(["replay","test"]);async function i8(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=ae(n,d,u);if(c)return c;let f=await ai({session:d,flags:u,ensureReady:!0});if(!tl(n,f))return N("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await w(f,n,o,t.flags?.out,{...eV(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,p,f):d;i.recordAction(e,{command:n,positionals:s??o,flags:t.flags??{},result:p??{}}),e!==d&&i.set(r,e)}return{ok:!0,data:p??{}}}async function i6(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=ae("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return N("INVALID_ARGS","clipboard requires a subcommand: read or write");let d=await ai({session:n,flags:o,ensureReady:!0});if(!tl("clipboard",d))return N("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let u=await w(d,"clipboard",t.positionals??[],t.flags?.out,{...eV(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 i9(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(i2.has(t.command))return await aJ({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await am({req:t,sessionName:r,sessionStore:i});if(i5.has(t.command))return await a0({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await i6({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"!==tf((t.flags??{}).platform)?await i8({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):N("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(i4.has(t.command))return await iR({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await aV({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?aG:aU});if("install_source"===t.command)return await r3({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await r6({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await i8({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=e1(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tG.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):N("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await i8({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 aA(e.device,r,e.appBundleId,aS)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await aR({req:t,sessionName:r,logPath:a,sessionStore:i}):i3.has(t.command)?await i1({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await aq(t,r,n):"close"===t.command?await a$({req:t,sessionName:r,logPath:a,sessionStore:i}):null}function i7(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return N("INVALID_ARGS","No snapshot in session. Run snapshot first.");let s=eC(r);if(!s)return N("INVALID_ARGS",n);let l=eM(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=to(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:N("COMMAND_FAILED",o)}function ne(e){let t=nt(e);if(!t)return null;let r=et(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function nt(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}async function nr(e){let{session:t,refInput:r,fallbackLabel:a,commandLabel:i,promoteToHittableAncestor:n,invalidRefMessage:o,missingBoundsMessage:s,invalidBoundsMessage:l,reqFlags:d,sessionStore:u,contextFromFlags:c,captureSnapshotForSession:f,resolveRefTarget:p}=e,m=p({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:o,notFoundMessage:s});if(!m.ok)return m;let{ref:h}=m.target,g=n?na(m.target.snapshotNodes,m.target.node):m.target.node,w=m.target.snapshotNodes,y=ne(g.rect);if(!y){let e=await f(t,d,u,c,{interactiveOnly:!0}),r=eM(e.nodes,h),i=a.length>0?to(e.nodes,a):null,o=r&&n?na(e.nodes,r):r,s=i&&n?na(e.nodes,i):i,l=ne(s?.rect),p=ne(o?.rect)?o:l?s:o??s,m=ne(p?.rect);p&&m&&(g=p,w=e.nodes,y=m)}if(!y)return N("COMMAND_FAILED",l);let I=g.rect?e2(g,w):null;return g.rect&&I&&!v(g,w)?{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${r} is off-screen and not safe to ${i}`,hint:`Run scrollintoview ${r}, then retry ${i} with the returned currentRef or a fresh snapshot.`,details:{reason:"offscreen_ref",ref:h,rect:g.rect,viewport:I}}}:{ok:!0,target:{ref:h,node:g,snapshotNodes:w,point:y}}}function na(e,t){let r=function(e,t){let r=nt(t.rect);if(!r)return null;let a=t,i=new Set;for(;!i.has(a.ref);){i.add(a.ref);let t=e.filter(e=>{if(e.parentIndex!==a.index||!e.hittable)return!1;let t=nt(e.rect);return!!t&&ni(t,r)});if(1!==t.length)break;a=t[0]}return a===t?null:a}(e,t);if(r?.rect&&ne(r.rect))return r;let a=W(e,t);return a?.rect&&ne(a.rect)?!function(e,t,r){var a,i,n,o;let s,l,d,u=nt(e.rect),c=nt(t.rect);if(!u||!c)return!1;let f=function(e,t){let r=et(t),a=e.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}).map(e=>nt(e.rect)).filter(e=>null!==e);if(0===a.length)return null;let i=a.filter(e=>E(e,r.x,r.y));return x(i.length>0?i:a)}(r,u);return!!f&&(a=c,i=f,s=(n=a,o=i,Math.max(0,Math.min(n.x+n.width,o.x+o.width)-Math.max(n.x,o.x))*Math.max(0,Math.min(n.y+n.height,o.y+o.height)-Math.max(n.y,o.y))),l=a.width*a.height,d=i.width*i.height,!(s<=0)&&!(l<=0)&&!(d<=0)&&!!(s/d>=.9)&&!!(s/l>=.8))&&!ni(u,c)}(t,a,e)?a:t:t}function ni(e,t){return .5>=Math.abs(e.x-t.x)&&.5>=Math.abs(e.y-t.y)&&.5>=Math.abs(e.width-t.width)&&.5>=Math.abs(e.height-t.height)}async function nn(e){let{device:t,node:r,flags:a,appBundleId:i,traceOutPath:n,surface:o,contextFromFlags:s}=e,l=R(r),d=ne(r.rect);if(!d)return l;try{let e=await w(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 ti({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return ti({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 no(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 N("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:u,value:c,timeoutMs:f}=eq(s);if(!d)return N("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return N("INVALID_ARGS","find accepts only one of --first or --last");let p=i.get(r);if(!p&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return N("SESSION_NOT_FOUND","No active session. Run open first.");let m=p?.device??await eR(t.flags??{});p||await e9(m);let h="role"!==l?d:void 0,g="click"===u||"focus"===u||"fill"===u||"type"===u,w=0,v=null,y=async()=>{let e=Date.now();if(v&&e-w<750&&!tt(p))return{nodes:v};let{snapshot:n}=await eB({device:m,session:p,flags:{...t.flags,snapshotInteractiveOnly:g,snapshotCompact:g},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=n.nodes;return w=e,v=o,p&&(p.snapshot=n,i.set(r,p)),{nodes:o,truncated:n.truncated,backend:n.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:p,device:m,command:o,locator:l,query:d};if("wait"===u)return ns(I,y,l,d,f);let{nodes:S}=await y(),A=ta(S,l,d,{requireRect:g});if(g&&A.matches.length>1)if(t.flags?.findFirst)A.matches=[A.matches[0]];else{if(!t.flags?.findLast){var b,_,x;let e;return b=A.matches,_=l,x=d,e=b.slice(0,8).map(e=>{let t=C(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),N("AMBIGUOUS_MATCH",`find matched ${b.length} elements for ${_} "${x}". Use a more specific locator or selector.`,{locator:_,query:x,matches:b.length,candidates:e})}A.matches=[A.matches[A.matches.length-1]]}let M=A.matches[0]??null;if(!M)return N("COMMAND_FAILED","find did not match any element");let k="click"===u||"focus"===u||"fill"===u||"type"===u?W(S,M)??M:M,D=`@${k.ref}`,P={node:M,resolvedNode:k,ref:D,nodes:S,actionFlags:{...t.flags??{},noRecord:!0}},L={exists:()=>nl(I),get_text:()=>nd(I,P),get_attrs:()=>nu(I,P),click:()=>nc(I,P),fill:()=>nf(I,P,c),focus:()=>np(I,P),type:()=>nm(I,P,c)}[u];return L?L():null}async function ns(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,d=i??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(ta(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{found:!0,waitedMs:Date.now()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return N("COMMAND_FAILED","find wait timed out")}async function nl(e){let{req:t,sessionStore:r,session:a,command:i}=e;return a&&r.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function nd(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await nn({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eV(s,e,t,r)});return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function nu(e,t){let{req:r,sessionStore:a,session:i,command:n}=e;return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function nc(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:d}=e,u=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?et(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:d};return c&&(f.x=c.x,f.y=c.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:f}}async function nf(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return N("INVALID_ARGS","find fill requires text");let d=await s({token:a.token,session:i,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return d.ok&&o&&n.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),d}async function np(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?et(t.node.rect):null;if(!l)return N("COMMAND_FAILED","matched element has no bounds");let d=await w(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eV(s,r.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:d??{ref:t.ref}}}async function nm(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return N("INVALID_ARGS","find type requires text");let d=t.node.rect?et(t.node.rect):null;if(!d)return N("COMMAND_FAILED","matched element has no bounds");await w(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...eV(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let u=await w(o,"type",[r],a.flags?.out,{...eV(l,a.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:s,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:u??{ref:t.ref}}}let nh=`
|
|
44
10
|
import Foundation
|
|
45
11
|
import AVFoundation
|
|
46
12
|
|
|
@@ -64,11 +30,11 @@ Task {
|
|
|
64
30
|
|
|
65
31
|
semaphore.wait()
|
|
66
32
|
exit(exitCode)
|
|
67
|
-
`.trim();async function
|
|
68
|
-
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(n))return fv(e);return!1}catch(t){if(t instanceof k&&"TOOL_MISSING"===t.code)return fv(e);throw t}}async function fy(e,t={}){let r=t.pollMs??150,n=t.attempts??12;for(let t=0;t<n;t+=1){if(await fg(e))return;await new Promise(e=>setTimeout(e,r))}}function fv(e){try{let t=s.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=s.openSync(e,"r");try{let e=s.fstatSync(t).size,r=0,n=[];for(;r+8<=e&&n.length<16;){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r))break;let a=e.readUInt32BE(0),i=e.toString("latin1",4,8);if(n.push(i),1===a){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r+8))break;a=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(a)||a<=0)break;r+=a}return n}finally{s.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function fI(e){let t=p.parse(e);return p.join(t.dir,`${t.name}.gesture-telemetry.json`)}function fb(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function fA(e){let t=p.dirname(w(import.meta.url)),r=[w(new URL(`./${e}`,import.meta.url)),p.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),p.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),p.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(s.existsSync(e))return e;throw new 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})}async function fS(e){let{videoPath:t,scriptPath:r,scriptArgs:n,commandDescription:a}=e;await fw(t),await fy(t);let i=s.mkdtempSync(p.join(d.tmpdir(),"agent-device-record-overlay-")),o=p.join(i,`input${p.extname(t)||".mp4"}`),l=p.join(i,p.basename(t)),u=p.join(i,"home"),c=p.join(i,"module-cache");s.copyFileSync(t,o),s.mkdirSync(u,{recursive:!0}),s.mkdirSync(c,{recursive:!0});try{await T("xcrun",["swift",r,"--input",o,"--output",l,...n],{timeoutMs:12e4,env:{...process.env,HOME:u,CLANG_MODULE_CACHE_PATH:c}}),await fy(l),s.copyFileSync(l,t)}catch(n){let e=n instanceof k?n:new k("COMMAND_FAILED",String(n),void 0,n instanceof Error?n:void 0);throw new k("COMMAND_FAILED",a,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{s.rmSync(i,{recursive:!0,force:!0})}}async function fN(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await fS({videoPath:t,scriptPath:n??=fA("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function f_(e){let{videoPath:t,telemetryPath:n,targetLabel:a="recording"}=e;await fS({videoPath:t,scriptPath:r??=fA("recording-overlay.swift"),scriptArgs:["--events",n],commandDescription:`Failed to add touch overlays to the ${a}`})}function fx(e){return e instanceof Error?e.message:String(e)}function fD(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function fM(e){let{recording:t,deps:r,trimStartMs:n,targetLabel:a}=e,i=function(e){var t,r,n;let a,i,{recording:o,trimStartMs:l}=e,u=(a=fI((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:l}).videoPath),i={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(n=t.trimStartMs??0)>0?fb(r.flatMap(e=>{let t=e.tMs-n,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):fb(r))},s.writeFileSync(a,JSON.stringify(i,null,2)),a);return o.telemetryPath=u,u}({recording:t,trimStartMs:n});if(t.showTouches){let e=function(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}();if(e)t.overlayWarning=e;else try{await r.overlayRecordingTouches({videoPath:t.outPath,telemetryPath:i,targetLabel:a})}catch(e){t.overlayWarning=`failed to overlay recording touches: ${fx(e)}`}}}async function fE(e,t,r){let n=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===n.exitCode&&n.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function fO(e,t,r){for(let n=0;n<40;n+=1){if(!await fE(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await fE(e,t,r)}async function fk(e,t,r){let n,a=0;for(let i=0;i<20;i+=1){let i=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===i.exitCode?i.stdout.trim():"";if(o.length>0&&o===n){if((a+=1)>=4)return}else a=0;n=o,await new Promise(e=>setTimeout(e,250))}}async function fL(e,t,r,n){for(let a=0;a<8;a+=1){let i=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===i.exitCode?Number(i.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await fE(e,t,n))break;if(a+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function fC(e){let t,{deps:r,deviceId:n,remotePath:a,outPath:i}=e;for(let e=0;e<2;e+=1){try{s.rmSync(i,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",n,"pull",a,i],{allowFailure:!0});if(0!==o.exitCode)t=fD(o,"adb pull");else{await r.waitForStableFile(i,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(i);if(D({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:n,remotePath:a,outPath:i,attempt:e+1,fileSize:(()=>{try{return s.statSync(i).size}catch{return 0}})(),playable:t}}),t)return;D({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:n,remotePath:a,outPath:i,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function fP(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function fR(e,t,r){let n=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return D({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:n.exitCode,stdout:n.stdout.trim(),stderr:n.stderr.trim()}}),!(0!==n.exitCode&&await fE(e,t,r))&&await fO(e,t,r)}async function fT(e){var t;let r,{deps:n,device:a,recordingBase:i}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await n.runCmd("adb",["-s",a.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${fD(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 fP(n,a.id,e);continue}if(D({level:"debug",phase:"record_start_android_started",data:{deviceId:a.id,remotePath:e,remotePid:r}}),await fL(n,a.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...i,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await fR(n,a.id,r),await fP(n,a.id,e)}return uD("COMMAND_FAILED",o)}async function f$(e){let t,r,{deps:n,device:a,recording:i}=e;D({level:"debug",phase:"record_stop_android_enter",data:{deviceId:a.id,remotePath:i.remotePath,remotePid:i.remotePid}});let o=await n.runCmd("adb",["-s",a.id,"shell","kill","-2",i.remotePid],{allowFailure:!0});if(D({level:"debug",phase:"record_stop_android_signal",data:{deviceId:a.id,remotePath:i.remotePath,remotePid:i.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await fE(n,a.id,i.remotePid)&&!await fR(n,a.id,i.remotePid)&&(t=`failed to stop recording: ${fD(o,"adb shell kill")}`):await fO(n,a.id,i.remotePid)||await fR(n,a.id,i.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${i.remotePid} did not exit`),!t){await fk(n,a.id,i.remotePath);let e=await fC({deps:n,deviceId:a.id,remotePath:i.remotePath,outPath:i.outPath});if(e)return await s(),uD("COMMAND_FAILED",e);await fM({recording:i,deps:n,targetLabel:"Android recording"})}if(await s(),t)return uD("COMMAND_FAILED",t);if(r)return uD("COMMAND_FAILED",r);return null;async function s(){let e=await n.runCmd("adb",["-s",a.id,"shell","rm","-f",i.remotePath],{allowFailure:!0});D({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:a.id,remotePath:i.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${fD(e,"adb shell rm")}`)}}function fF(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function fU(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function fG(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i}=e,o=fF(r);if(o)try{await i.runIosRunnerCommand(n,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},fU(t,a,r))}catch(e){D({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:n.id,session:r.name,appBundleId:o,error:fx(e)}})}}async function fV(e){let t,r,{req:n,activeSession:a,sessionStore:i,device:o,logPath:s,deps:l,fpsFlag:u,recordingBase:d,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=fU(n,s,a),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:u,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(n){var w,g;if(!fx(n).toLowerCase().includes("recording already in progress"))return uD("COMMAND_FAILED",`failed to start recording: ${fx(n)}`);D({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:a.name,error:fx(n)}});let e=(w=o.id,g=a.name,i.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return uD("COMMAND_FAILED",`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 uD("COMMAND_FAILED",`failed to start recording: ${fx(e)}`)}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...d}}async function fB(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await i.runIosRunnerCommand(n,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},fU(t,a,r))}catch(e){return uD("COMMAND_FAILED",`failed to start recording: ${fx(e)}`)}return{platform:"macos-runner",...s}}async function fj(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i,recording:o}=e,s=fF(r);try{await i.runIosRunnerCommand(n,{command:"recordStop",appBundleId:s},fU(t,a,r))}catch(e){D({level:"warn",phase:"record_stop_runner_failed",data:{platform:n.platform,kind:n.kind,deviceId:n.id,session:r.name,error:fx(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of tG)if(0===(l=await i.runCmd("xcrun",["devicectl","device","copy","from","--device",n.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 uD("COMMAND_FAILED",`failed to copy recording from device: ${e}`)}let u="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);return u>0&&await i.trimRecordingStart({videoPath:o.outPath,trimStartMs:u}),await fM({recording:o,deps:i,trimStartMs:u,targetLabel:"iOS recording"}),null}async function fq(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i,recording:o}=e,s=fF(r);try{await i.runIosRunnerCommand(n,{command:"recordStop",appBundleId:s},fU(t,a,r))}catch(e){D({level:"warn",phase:"record_stop_runner_failed",data:{platform:n.platform,kind:n.kind,deviceId:n.id,session:r.name,error:fx(e)}})}return await fM({recording:o,deps:i,targetLabel:"macOS recording"}),null}async function fH(e){for(let t=0;t<2;t+=1){try{if(s.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function fW(e){let t,r,{req:n,activeSession:a,device:i,logPath:o,deps:s,recordingBase:l,resolvedOut:u}=e;await fG({req:n,activeSession:a,device:i,logPath:o,deps:s});let{child:d,wait:c}=s.runCmdBackground("xcrun",e6(i,["io",i.id,"recordVideo",u]),{allowFailure:!0}),p=await fH(u);try{let e=Date.now(),l=await s.runIosRunnerCommand(i,{command:"uptime",appBundleId:fF(a)},{verbose:n.flags?.verbose,logPath:o,traceLogPath:a.trace?.outPath}),u=Date.now();t=Math.round((e+u)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:d,wait:c,...l,startedAt:p,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function fz(e){let t,{req:r,sessionName:n,sessionStore:a,activeSession:i,device:o,logPath:l,deps:u}=e;if(i.recording)return uD("INVALID_ARGS","recording already in progress");let d=r.flags?.fps;if(void 0!==d&&(!Number.isInteger(d)||d<1||d>120))return uD("INVALID_ARGS","fps must be an integer between 1 and 120");if(!um("record",o))return uD("UNSUPPORTED_OPERATION","record is not supported on this device");let c=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,f=rE.expandHome(c,r.meta?.cwd),m={outPath:f,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(s.mkdirSync(p.dirname(f),{recursive:!0}),s.rmSync(f,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=fF(i);if(!e)return uD("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await fV({req:r,activeSession:i,sessionStore:a,device:o,logPath:l,deps:u,fpsFlag:d,recordingBase:m,appBundleId:e})}else if("macos"===o.platform){let e=fF(i);if(!e)return uD("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await fB({req:r,activeSession:i,device:o,logPath:l,deps:u,fpsFlag:d,recordingBase:m,appBundleId:e})}else t="ios"===o.platform?await fW({req:r,activeSession:i,device:o,logPath:l,deps:u,recordingBase:m,resolvedOut:f}):await fT({deps:u,device:o,recordingBase:m});return"ok"in t?t:(i.recording=t,a.set(n,i),a.recordAction(i,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??c,showTouches:t.showTouches}})}async function fJ(e){let{deps:t,device:r,recording:n}=e;if("android"===n.platform)return await f$({deps:t,device:r,recording:n});n.child.kill("SIGINT");let a=await n.wait;return 0!==a.exitCode?uD("COMMAND_FAILED",`failed to stop recording: ${fD(a,"simctl recordVideo")}`):(await fM({recording:n,deps:t,targetLabel:"iOS recording"}),null)}async function fK(e){var t;let r,{req:n,activeSession:a,device:i,logPath:o,deps:s}=e;if(!a.recording)return uD("INVALID_ARGS","no active recording");let l=a.recording,u=l.invalidatedReason;a.recording=void 0;let d="ios-device-runner"===l.platform?await fj({req:n,activeSession:a,device:i,logPath:o,deps:s,recording:l}):"macos-runner"===l.platform?await fq({req:n,activeSession:a,device:i,logPath:o,deps:s,recording:l}):await fJ({deps:s,device:i,recording:l});return d||(u?uD("COMMAND_FAILED",u):(r=[{field:"outPath",path:(t=l).outPath,localPath:t.clientOutPath,fileName:p.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return fI(e.clientOutPath)}(t),fileName:p.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function fX(e){let{req:t,sessionName:r,sessionStore:n,logPath:a}=e,i={runCmd:T,runCmdBackground:L,runIosRunnerCommand:ru,waitForStableFile:fw,isPlayableVideo:fg,trimRecordingStart:fN,overlayRecordingTouches:f_},o=n.get(r),s=o?.device??await l3(t.flags??{});o||await ug(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},u=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(u))return uD("INVALID_ARGS","record requires start|stop");if("start"===u)return fz({req:t,sessionName:r,sessionStore:n,activeSession:l,device:s,logPath:a,deps:i});let d=await fK({req:t,activeSession:l,device:s,logPath:a,deps:i});return d.ok&&n.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:d.data?.outPath,showTouches:d.data?.showTouches}}),d}async function fY(e){let{req:t,sessionName:r,sessionStore:n,logPath:a}=e,i=t.command;if("record"===i)return fX({req:t,sessionName:r,sessionStore:n,logPath:a});if("trace"===i){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return uD("INVALID_ARGS","trace requires start|stop");let a=n.get(r);if(!a)return uD("SESSION_NOT_FOUND","No active session");if("start"===e){if(a.trace)return uD("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??n.defaultTracePath(a),r=rE.expandHome(e);return s.mkdirSync(p.dirname(r),{recursive:!0}),s.appendFileSync(r,""),a.trace={outPath:r,startedAt:Date.now()},n.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!a.trace)return uD("INVALID_ARGS","no active trace");let o=a.trace.outPath;if(t.positionals?.[1]){let e=rE.expandHome(t.positionals[1]);s.mkdirSync(p.dirname(e),{recursive:!0}),s.existsSync(o)?s.renameSync(o,e):s.appendFileSync(e,""),o=e}return a.trace=void 0,n.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function fZ(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 fQ=new WeakMap;function f0(e){if(!e)return;let t=fQ.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)&&f1(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(f1);if(0===r.length)return;let n=Math.max(...r.map(e=>e.x+e.width)),a=Math.max(...r.map(e=>e.y+e.height));if(!(n<=0)&&!(a<=0))return{x:0,y:0,width:n,height:a}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return fQ.set(e,r),r}function f1(e){return!!e&&e.width>0&&e.height>0}let f2={referenceWidth:1e3,referenceHeight:1e3};function f3(e,t,r,n,a={},i=Date.now(),o=Date.now()){var s,l,u;let d,c,p=e.recording;if(!p)return;let f={...a,...n??{}},m=f6(f.effectiveDurationMs)??f6(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:f6(f.gestureStartUptimeMs),gestureEndUptimeMs:f6(f.gestureEndUptimeMs),fallbackStartedAtMs:i,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:f6(f.gestureStartUptimeMs),gestureEndUptimeMs:f6(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:i,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===f6(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=f9(f6(t.count),1)??1,r=!0===t.doubleTap,n=f9(f6(t.holdMs),1);return 1===e&&!r&&void 0===n}default:return!1}}(t,f)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return fZ(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):fZ(h),y=(l=e.snapshot,d=f6((u=f).referenceWidth),c=f6(u.referenceHeight),void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:f0(l)),v=function(e,t,r,n,a,i){switch(e){case"click":case"press":return function(e,t,r,n){let a=f7(t,e);if(!a)return[];let{x:i,y:o}=a,s=f9(f6(t.count),1)??1,l=f9(f6(t.intervalMs),0)??0,u=!0===t.doubleTap,d=f9(f6(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==d&&d>0){c.push(f5(t,i,o,d,n));continue}c.push(f4(t,i,o,n)),u&&c.push(f4(t+90,i,o,n))}return c}(t,r,n,i);case"fill":case"focus":return function(e,t,r,n){let a=f7(t,e);if(!a)return[];let{x:i,y:o}=a;return[f4(r,i,o,n)]}(t,r,n,i);case"longpress":return function(e,t,r,n,a){let i=f7(t,e);if(!i)return[];let{x:o,y:s}=i;return[f5(r,o,s,mt(n,[f6(t.durationMs),f6(e[2])],800),a)]}(t,r,n,a,i);case"scroll":return function(e,t,r,n,a){let i=me(t,e),o=f8(t.contentDirection)??f8(t.direction);if(!i||!o)return[];let{x1:s,y1:l,x2:u,y2:d}=i,c=mt(n,[],250),p=f6(t.amount)??f6(e[1]),f=f6(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:u,y2:d,...a,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{},...void 0!==f?{pixels:f}:{}}]}(t,r,n,a,i);case"swipe":return function(e,t,r,n,a){let i=me(t,e);if(!i)return[];let{x1:o,y1:s,x2:l,y2:u}=i,d=mt(n,[f6(t.effectiveDurationMs),f6(t.durationMs),f6(e[4])],250),c=f9(f6(t.count),1)??1,p=f9(f6(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,n=t?l:o,i=t?u:s,c=t?o:l,h=t?s:u,w=r+e*(d+p);if("back-swipe"===function(e,t,r,n,a){if(!a||Math.abs(r-e)<=1.25*Math.abs(n-t))return"swipe";let i=.08*a.referenceWidth;return e<=i&&r>e||e>=a.referenceWidth-i&&r<e?"back-swipe":"swipe"}(n,i,c,h,a)){m.push({kind:"back-swipe",tMs:w,x:n,y:i,x2:c,y2:h,...a,durationMs:d,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"}(n,c,a)});continue}m.push({kind:"swipe",tMs:w,x:n,y:i,x2:c,y2:h,...a,durationMs:d})}return m}(t,r,n,a,i);case"pinch":return function(e,t,r,n,a){let i=f7(t,e,1),o=f6(t.scale)??f6(e[0]);if(!i||void 0===o||o<=0)return[];let{x:s,y:l}=i;return[{kind:"pinch",tMs:r,x:s,y:l,...a,scale:o,durationMs:mt(n,[],280)}]}(t,r,n,a,i);default:return[]}}(t,r,f,g,w,y);0!==v.length&&(p.gestureEvents.push(...v),D({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:v.length,tMs:g,gestureDurationMs:w,kinds:v.map(e=>e.kind)}}))}function f4(e,t,r,n){return{kind:"tap",tMs:e,x:t,y:r,...n}}function f5(e,t,r,n,a){return{kind:"longpress",tMs:e,x:t,y:r,...a,durationMs:n}}function f8(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 f6(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 f9(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function f7(e,t,r=0){let n=f6(e.x)??f6(t[r]),a=f6(e.y)??f6(t[r+1]);if(void 0!==n&&void 0!==a)return{x:n,y:a}}function me(e,t){let r=f6(e.x1)??f6(t[0]),n=f6(e.y1)??f6(t[1]),a=f6(e.x2)??f6(t[2]),i=f6(e.y2)??f6(t[3]);if(void 0!==r&&void 0!==n&&void 0!==a&&void 0!==i)return{x1:r,y1:n,x2:a,y2:i}}function mt(e,t,r){return f9(e,1)??t.map(e=>f9(e,1)).find(e=>void 0!==e)??r}function mr(e){var t,r,n;let a,i,{data:o,fallbackX:s,fallbackY:l,referenceFrame:u,extra:d}=e,c=(t=d,r=s,n=l,a="string"==typeof t?.ref?t.ref:void 0,i="string"==typeof t?.button?t.button:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:a?i&&"primary"!==i?`Clicked ${i} @${a} (${r}, ${n})`:`Tapped @${a} (${r}, ${n})`:void 0)??("string"==typeof o?.message?o.message:void 0));return{x:s,y:l,...u??{},...d??{},...o??{},...eh(c)}}async function mn(e){let{session:t,sessionStore:r,requestCommand:n,requestPositionals:a,flags:i,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:u,afterDispatch:d,buildPayloads:c}=e,p=await ma({session:t,flags:i,contextFromFlags:o,command:s,positionals:l,outPath:u});await d?.(p.data);let{result:f,responseData:m=f}=await c(p.data);return function(e){let{session:t,sessionStore:r,command:n,positionals:a,flags:i,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:u}=e;return r.recordAction(t,{command:n,positionals:a,flags:i??{},result:o}),dv(n)&&dw(t,n),f3(t,n,a,o,i??{},l,u),{ok:!0,data:s}}({session:t,sessionStore:r,command:n,positionals:a,flags:i,result:f,responseData:m,actionStartedAt:p.actionStartedAt,actionFinishedAt:p.actionFinishedAt})}async function ma(e){let{session:t,flags:r,contextFromFlags:n,command:a,positionals:i,outPath:o}=e,s=Date.now(),l={...n(r,t.appBundleId,t.trace?.outPath)},u=await l4(t.device,a,i,o,l);return{data:u&&"object"==typeof u?u:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function mi(e){let{session:t,flags:r,sessionStore:n,contextFromFlags:a,captureSnapshotForSession:i}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await iG(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=f0(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=f0(await i(t,r,n,a,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function mo(e){try{return await mi(e)}catch(t){D({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function ms(e){return f0({nodes:e,createdAt:0})}function ml(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:uD("UNSUPPORTED_OPERATION",`${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 mu(e){let{req:t,sessionName:r,sessionStore:n,contextFromFlags:a,captureSnapshotForSession:i,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=n.get(r),u=t.command,d="click"===u?"click":"press";if(!l)return uD("SESSION_NOT_FOUND","No active session. Run open first.");let c=ml(l,d);if(c)return c;if(!um("press",l.device))return uD("UNSUPPORTED_OPERATION","press is not supported on this device");let p=lD(t.flags),f="primary"===p?{}:{button:p};if("primary"!==p){let e=lM({commandLabel:d,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 uD(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return mn({session:l,sessionStore:n,requestCommand:u,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:a,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,afterDispatch:async()=>{await md(l,"coordinate tap")},buildPayloads:async e=>{let r=await mo({session:l,flags:t.flags,sessionStore:n,contextFromFlags:a,captureSnapshotForSession:i}),o=mr({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 fr({session:l,refInput:w,fallbackLabel:r,commandLabel:d,promoteToHittableAncestor:!0,invalidRefMessage:`${d} 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:n,contextFromFlags:a,captureSnapshotForSession:i,resolveRefTarget:o});if(!c.ok)return c;let{ref:p,node:m,snapshotNodes:g,point:y}=c.target,v=cX(m,g),I=ph(m,l.device.platform,{action:h}),{x:b,y:A}=y;return mn({session:l,sessionStore:n,requestCommand:u,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:a,interactionCommand:"press",interactionPositionals:[String(b),String(A)],outPath:t.flags?.out,afterDispatch:async()=>{await md(l,`@${p}`)},buildPayloads:e=>{let t=mr({data:e,fallbackX:b,fallbackY:A,referenceFrame:ms(g),extra:{ref:p,refLabel:v,selectorChain:I,...f}});return{result:t,responseData:t}}})}let g=(t.positionals??[]).join(" ").trim();if(!g)return uD("INVALID_ARGS",`${d} requires @ref, selector expression, or x y coordinates`);let y=c8(g),v=await i(l,t.flags,n,a,{interactiveOnly:!0}),I=await x("selector_resolve",()=>pc(v.nodes,y,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:u});if(!I||!I.node.rect)return uD("COMMAND_FAILED",pf(y,I?.diagnostics??[],{unique:!0}));let b=fn(v.nodes,I.node),A=fe(b.rect);if(!A)return uD("COMMAND_FAILED",`Selector ${I.selector.raw} resolved to invalid bounds`);let{x:S,y:N}=A,_=ph(b,l.device.platform,{action:h}),D=cX(b,v.nodes);return mn({session:l,sessionStore:n,requestCommand:u,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:a,interactionCommand:"press",interactionPositionals:[String(S),String(N)],outPath:t.flags?.out,afterDispatch:async()=>{await md(l,I.selector.raw)},buildPayloads:e=>{let t=mr({data:e,fallbackX:S,fallbackY:N,referenceFrame:ms(v.nodes),extra:{selector:I.selector.raw,selectorChain:_,refLabel:D,...f}});return{result:t,responseData:t}}})}async function md(e,t){if("android"!==e.device.platform||!e.appBundleId)return;let r=await aH(e.device),n=r.package?.trim();if(n&&n!==e.appBundleId){var a;if("com.android.settings"===(a=n)||"com.android.systemui"===a||"com.google.android.permissioncontroller"===a||a.includes("launcher"))throw new k("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${n}. The tap likely escaped the app.`,{expectedPackage:e.appBundleId,foregroundPackage:n,activity:r.activity,hint:"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."})}}async function mc(e){let{req:t,sessionName:r,sessionStore:n,contextFromFlags:a,captureSnapshotForSession:i,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=n.get(r);if(l){let e=ml(l,"fill");if(e)return e}if(l&&!um("fill",l.device))return uD("UNSUPPORTED_OPERATION","fill is not supported on this device");if(t.positionals?.[0]?.startsWith("@")){if(!l)return uD("SESSION_NOT_FOUND","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]:"",u=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!u)return uD("INVALID_ARGS","fill requires text after ref");let d=await fr({session:l,refInput:t.positionals[0],fallbackLabel:r,commandLabel:"fill",promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:n,contextFromFlags:a,captureSnapshotForSession:i,resolveRefTarget:o});if(!d.ok)return d;let{ref:c,node:p,snapshotNodes:f,point:m}=d.target,h=p.type??"",w=h&&!c0(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,g=cX(p,f),y=ph(p,l.device.platform,{action:"fill"}),{x:v,y:I}=m;return mn({session:l,sessionStore:n,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:a,interactionCommand:"fill",interactionPositionals:[String(v),String(I),u],outPath:t.flags?.out,buildPayloads:e=>{let t=mr({data:e,fallbackX:v,fallbackY:I,referenceFrame:ms(f),extra:{ref:c,refLabel:g,selectorChain:y,text:u}}),r={...e??{ref:c,x:v,y:I}};return w&&(t.warning=w,r.warning=w),{result:t,responseData:r}}})}if(!l)return uD("SESSION_NOT_FOUND","No active session. Run open first.");let u=c9(t.positionals??[],{preferTrailingValue:!0});if(u){if(0===u.rest.length)return uD("INVALID_ARGS","fill requires text after selector");let e=u.rest.join(" ").trim();if(!e)return uD("INVALID_ARGS","fill requires text after selector");let r=c8(u.selectorExpression),o=await i(l,t.flags,n,a,{interactiveOnly:!0}),s=await x("selector_resolve",()=>pc(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return uD("COMMAND_FAILED",pf(r,s?.diagnostics??[],{unique:!0}));let d=s.node,c=s.node.rect,p=d.type??"",f=p&&!c0(p,l.device.platform)?`fill target ${s.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=eD(c),w=ph(d,l.device.platform,{action:"fill"});return mn({session:l,sessionStore:n,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:a,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=mr({data:t,fallbackX:m,fallbackY:h,referenceFrame:ms(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:w,refLabel:cX(d,o.nodes)}});return f&&(r.warning=f),{result:r,responseData:r}}})}return uD("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}async function mp(e){switch(e.req.command){case"press":case"click":return await mu(e);case"fill":return await mc(e);default:return null}}let mf=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function mm(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,n]of mf)void 0!==e[r]&&t.push(n);return t}(t);return 0===r.length?null:uD("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function mh(e,t,r,n,a){let i={...t??{},snapshotInteractiveOnly:a.interactiveOnly,snapshotCompact:a.interactiveOnly},o=n(i,e.appBundleId,e.trace?.outPath),{snapshot:s}=await pT({device:e.device,session:e,flags:i,outPath:i.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function mw(e){let{command:t,selectorExpression:r,session:n,flags:a,sessionStore:i,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:u,disambiguateAmbiguous:d}=e,c=c8(r),p=await mh(n,a,i,o,{interactiveOnly:s}),f=await x("selector_resolve",()=>pc(p.nodes,c,{platform:n.device.platform,requireRect:l,requireUnique:u,disambiguateAmbiguous:d}),{command:t});return f&&(!l||f.node.rect)?{ok:!0,chain:c,snapshot:p,resolved:f}:{ok:!1,error:{code:"COMMAND_FAILED",message:pf(c,f?.diagnostics??[],{unique:u})}}}async function mg(e){let{req:t,sessionName:r,sessionStore:n,contextFromFlags:a}=e,i=t.positionals?.[0];if("text"!==i&&"attrs"!==i)return uD("INVALID_ARGS","get only supports text or attrs");let o=n.get(r);if(!o)return uD("SESSION_NOT_FOUND","No active session. Run open first.");if(!um("get",o.device))return uD("UNSUPPORTED_OPERATION","get is not supported on this device");let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=mm("get",t.flags);if(e)return e;let r=p7({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;let{ref:l,node:u}=r.target,d=ph(u,o.device.platform,{action:"get"});if("attrs"===i)return n.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,selectorChain:d}}),{ok:!0,data:{ref:l,node:u}};let c=await fi({device:o.device,node:u,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:a});return n.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:my(c),selectorChain:d}}),{ok:!0,data:{ref:l,text:c,node:u}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return uD("INVALID_ARGS","get requires @ref or selector expression");let u=await mw({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:n,contextFromFlags:a,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===i});if(!u.ok)return u;let{resolved:d}=u,c=d.node,p=ph(c,o.device.platform,{action:"get"});if("attrs"===i)return n.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:d.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:d.selector.raw,node:c}};let f=await fi({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:a});return n.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:f,refLabel:my(f),selector:d.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:d.selector.raw,text:f,node:c}}}function my(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function mv(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 mI(e){let{req:t,sessionName:r,sessionStore:n,contextFromFlags:a}=e,i=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(i))return uD("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let o=n.get(r);if(!o)return uD("SESSION_NOT_FOUND","No active session. Run open first.");if(!um("is",o.device))return uD("UNSUPPORTED_OPERATION","is is not supported on this device");let{split:s}=c7(t.positionals);if(!s)return uD("INVALID_ARGS","is requires a selector expression");let l=s.rest.join(" ").trim();if("text"===i&&!l)return uD("INVALID_ARGS","is text requires expected text value");if("text"!==i&&s.rest.length>0)return uD("INVALID_ARGS",`is ${i} does not accept trailing values`);let u=c8(s.selectorExpression);if("exists"===i){let e=pp((await mh(o,t.flags,n,a,{interactiveOnly:!1})).nodes,u,{platform:o.device.platform});return e?(n.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:i,selector:e.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:i,pass:!0,selector:e.selector.raw,matches:e.matches}}):uD("COMMAND_FAILED",pf(u,[],{unique:!1}))}let d=await mw({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:n,contextFromFlags:a,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!d.ok)return d;let{resolved:c}=d,p=function(e){let{predicate:t,node:r,nodes:n,expectedText:a,platform:i}=e,o=c2(r),s=pu(r,i),l=!0===r.selected,u="text"===t?pl(r):function(e,t){if(!0===e.hittable)return!0;if(mv(e.rect))return B(e,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),n=e,a=new Set;for(;"number"==typeof n.parentIndex&&!a.has(n.index);){a.add(n.index);let e=r.get(n.parentIndex);if(!e)break;if(function(e){let t=cQ(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||mv(e.rect))}(e))return e;n=e}return null}(e,t);return!!r&&(!0===r.hittable||!!mv(r.rect)&&B(r,t))}(r,n),d=!1;switch(t){case"visible":d=u;break;case"hidden":d=!u;break;case"editable":d=s;break;case"selected":d=l;break;case"text":d=o===(a??"")}let c="text"===t?`expected="${a??""}" actual="${o}"`:`actual=${JSON.stringify({visible:u,editable:s,selected:l})}`;return{pass:d,actualText:o,details:c}}({predicate:i,node:c.node,nodes:d.snapshot.nodes,expectedText:l,platform:o.device.platform});return p.pass?(n.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:i,selector:c.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,text:"text"===i?p.actualText:void 0}}),{ok:!0,data:{predicate:i,pass:!0,selector:c.selector.raw}}):uD("COMMAND_FAILED",`is ${i} failed for selector ${c.selector.raw}: ${p.details}`)}function mb(e,t){var r,n;let a=Math.max(1,t.height),i=Math.max(1,t.width),o=t.y,s=t.y+a,l=t.x,u=t.x+i,d=s-.25*a,c=Math.max(8,.1*i),p=e.y+e.height/2,f=e.x+e.width/2;if(p>=o+.25*a&&p<=d)return null;let m=Math.round((r=f,n=l+c,Math.min(u-c,Math.max(n,r)))),h=Math.round(o+.86*a),w=Math.round(o+.14*a);return p>d?{x:m,startY:h,endY:w,direction:"down"}:{x:m,startY:w,endY:h,direction:"up"}}async function mA(e){var t;let r,n,a,{req:i,sessionName:o,sessionStore:s,contextFromFlags:l}=e,u=s.get(o);if(!u)return uD("SESSION_NOT_FOUND","No active session. Run open first.");if(!um("scrollintoview",u.device))return uD("UNSUPPORTED_OPERATION","scrollintoview is not supported on this device");let d=i.positionals?.[0]??"";if(!d.startsWith("@"))return null;let c=mm("scrollintoview",i.flags);if(c)return c;let p=i.positionals&&i.positionals.length>1?i.positionals.slice(1).join(" ").trim():"",f=(r=p7({session:u,refInput:t=d,fallbackLabel:p,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${t} not found or has no bounds`})).ok?mS(t,0,r.target):"COMMAND_FAILED"!==r.error.code?r:mN(t,0,{message:r.error.message});if(!f.ok)return f;let{ref:m}=f.state,{currentRef:h,node:w,snapshotNodes:g,viewportRect:y}=f.state,v=cX(w,g),I=ph(w,u.device.platform,{action:"get"}),b=p||v||w.label||"";if(!mb(w.rect,y)){let e=m_({ref:m,currentRef:h,attempts:0,alreadyVisible:!0});return s.recordAction(u,{command:i.command,positionals:i.positionals??[],flags:i.flags??{},result:{refLabel:v,selectorChain:I,...e}}),{ok:!0,data:e}}let A=i.flags?.maxScrolls??48,S=0,N=0,_=et(w.rect,y);for(;S<A;){let e=mb(w.rect,y);if(!e)break;n=e.direction,a=await l4(u.device,"swipe",[String(e.x),String(e.startY),String(e.x),String(e.endY),"16"],i.flags?.out,{...l(i.flags,u.appBundleId,u.trace?.outPath),count:1,pauseMs:0,pattern:"one-way"}),S+=1,await mh(u,i.flags,s,l,{interactiveOnly:!0});let t=function(e){let{session:t,targetInput:r,fallbackLabel:n,attempts:a,ref:i,selectorChain:o,platform:s}=e;if(t.snapshot){let e=function(e,t,r,n){for(let r of t){let t=pc(e,c8(r),{platform:n,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?cK(e,r):null}(t.snapshot.nodes,o,n,s);if(e)return mS(r,a,{ref:i,node:e,snapshotNodes:t.snapshot.nodes},{currentRef:e.ref})}let l=p7({session:t,refInput:r,fallbackLabel:n,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${r} not found or has no bounds`});return l.ok?mS(r,a,l.target,{ref:i,currentRef:l.target.node.ref,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${a} scroll${1===a?"":"s"}`}):"COMMAND_FAILED"!==l.error.code?l:mN(r,a,{message:`scrollintoview lost track of ${r} after ${a} scroll${1===a?"":"s"}`,ref:i})}({session:u,targetInput:d,fallbackLabel:b,attempts:S,ref:m,selectorChain:I,platform:u.device.platform});if(!t.ok)return t;({currentRef:h,node:w,snapshotNodes:g,viewportRect:y}=t.state);let r=et(w.rect,y);if(0===r)break;if(r>=_){if((N+=1)>=2)return mN(d,S,{message:`scrollintoview made no progress toward ${d} after ${S} scroll${1===S?"":"s"}`,ref:m,stalled:!0})}else N=0;_=r}if(et(w.rect,y)>0)return mN(d,S,{message:`scrollintoview reached --max-scrolls=${A} before ${d} entered view`,ref:m,maxScrolls:A});let x=m_({data:a,ref:m,currentRef:h,attempts:S,direction:n});return s.recordAction(u,{command:i.command,positionals:i.positionals??[],flags:i.flags??{},result:{refLabel:v,selectorChain:I,...x}}),{ok:!0,data:x}}function mS(e,t,r,n={}){let{ref:a,currentRef:i,missingBoundsMessage:o}=n,s=r.node;if(!s.rect)return mN(e,t,{message:o??`Ref ${e} not found or has no bounds`,ref:a??r.ref});let l=eu(r.snapshotNodes,s.rect);return l?{ok:!0,state:{ref:a??r.ref,currentRef:i??r.node.ref,node:s,snapshotNodes:r.snapshotNodes,viewportRect:l}}:uD("COMMAND_FAILED",`scrollintoview could not infer viewport for ${e}`)}function mN(e,t,r={}){let{message:n,...a}=r;return uD("COMMAND_FAILED","string"==typeof n?n:`scrollintoview could not find ${e}`,{reason:"not_found",attempts:t,...a})}function m_(e){let{data:t,ref:r,currentRef:n,attempts:a,alreadyVisible:i,direction:o}=e;return{...t??{},ref:r,currentRef:n,attempts:a,...i?{alreadyVisible:i}:{},...o?{direction:o}:{},...eh(`Scrolled into view: @${r}`)}}async function mx(e){let t=await mp({...e,captureSnapshotForSession:mh,resolveRefTarget:p7,refSnapshotFlagGuardResponse:mm});if(t)return t;switch(e.req.command){case"get":return await mg(e);case"is":return await mI(e);case"scrollintoview":return await mA(e);default:return null}}function mD(e){return{tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend}}async function mM(e){let{req:t,leaseRegistry:r}=e,n=mD(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:n.tenantId??"",runId:n.runId??"",backend:n.leaseBackend,ttlMs:n.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:n.leaseId??"",tenantId:n.tenantId,runId:n.runId,ttlMs:n.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:n.leaseId??"",tenantId:n.tenantId,runId:n.runId})};default:return null}}function mE(e,t){if(!t)return[];let r=[],n=e.device,a=t.platform;if(a&&!tb(n.platform,a)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(n.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==n.platform||t.udid!==n.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==n.platform||t.serial!==n.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==n.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),a=n.simulatorSetPath?.trim();("ios"!==n.platform||"simulator"!==n.kind||e!==a)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=e4(t.androidDeviceAllowlist);"android"===n.platform&&e.has(n.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function mO(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 mk=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],mL=/\bis(?:n't| not)\s+responding\b/i,mC=/^close app$/i;async function mP(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await mR(t),r=function(e){if(mU(e))return e.find(e=>{let t=mF(e);return t.length>0&&mC.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:n,y:a}=eD(r.rect),i=await T("adb",nW(t.device,["shell","input","tap",String(Math.round(n)),String(Math.round(a))]),{allowFailure:!0});if(0!==i.exitCode)return D({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:i.exitCode,stdout:i.stdout.trim(),stderr:i.stderr.trim()}}),"failed";if(!await mT(t))return D({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await az(t.device,t.appBundleId),!await m$(t,t.appBundleId)))return D({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return D({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:n,y:a}}),"recovered"}catch(e){return D({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 mR(e){return eO(cZ((await iy(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function mT(e){for(let t=0;t<12;t+=1){if(!mU(await mR(e)))return!0;await mG(500)}return!mU(await mR(e))}async function m$(e,t){for(let r=0;r<12;r+=1){if((await aH(e.device)).package===t)return!0;await mG(500)}return(await aH(e.device)).package===t}function mF(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 mU(e){return e.some(e=>{let t=mF(e);return t.length>0&&mL.test(t)})}function mG(e){return new Promise(t=>setTimeout(t,e))}let mV=[255,59,48,255],mB=[255,214,10,255],mj=[0,0,0,255],mq={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 mH(e){let t=eE(await u.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,n={}){let a=function(e){let t=null;for(let r of e)mz(r)&&mZ(r.rect)&&(!t||mQ(r.rect)>mQ(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,n=-1/0,a=-1/0;for(let i of e)i.rect&&mZ(i.rect)&&(t=Math.min(t,i.rect.x),r=Math.min(r,i.rect.y),n=Math.max(n,i.rect.x+i.rect.width),a=Math.max(a,i.rect.y+i.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||n<=t||a<=r?null:{x:t,y:r,width:n-t,height:a-r}}(e.filter(e=>{var t;return mZ(e.rect)&&!("image"===cQ((t=e).type??"")&&!mJ(t.label))}))}(e.nodes),i=new Map;for(let n of e.nodes){if(!function(e){let t=[e.label,e.value].some(mK)||mX(e.identifier);return mW(e)?t:t&&function(e){let t=cQ(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(n))continue;let o=function(e,t){if(function(e){return mW(e)&&!mz(e)}(t)&&mZ(t.rect))return t;let r=function(e,t){let r=t,n=new Set;for(;void 0!==r.parentIndex&&!n.has(r.ref);){;n.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(mW(t)&&!mz(t)&&mZ(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&mZ(r.rect))return r;if(t.hittable&&mZ(t.rect)&&!mz(t))return t;let n=c1(e,t);return n?.rect&&mZ(n.rect)&&!mz(n)?n:null}(e.nodes,n);if(!o?.rect||!mZ(o.rect))continue;let s=function(e,t,r){let n=mY(e);if(e.ref!==t.ref&&n)return n;let a=function(e,t){let r=null;for(let n of t){if(n.ref===e.ref||!function(e,t,r){let n=e;for(;void 0!==n.parentIndex;){let e=r[n.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;n=e}return!1}(n,e,t))continue;let a=mY(n);if(!a)continue;let i=function(e){let t=0;return cQ(e.type??"").includes("text")&&(t+=2),mK(e.label)&&(t+=2),mK(e.value)&&(t+=1),t}(n);(!r||i>r.score)&&(r={label:a,score:i})}return r?.label}(t,r);return a||(mY(t)??cX(t,r))}(n,o,e.nodes),l=function(e,t,r){let n=0;return e.ref===t.ref&&(n+=4),t.hittable&&(n+=3),mW(t)&&(n+=3),mW(e)&&(n+=2),r&&(n+=2),mX(t.identifier)&&(n+=1),mJ(t.value)&&(n+=1),n}(n,o,s),u=function(e,t,r,n){if(!e)return m2({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,n);let a=r/e.width,i=n/e.height;return m2({x:Math.round((t.x-e.x)*a),y:Math.round((t.y-e.y)*i),width:Math.max(1,Math.round(t.width*a)),height:Math.max(1,Math.round(t.height*i))},r,n)}(a,o.rect,t,r);if(!mZ(u))continue;let d=i.get(o.ref);(!d||l>d.score)&&i.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:u,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>mQ(e.overlayRect)-mQ(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(m0(e.overlayRect,r.overlayRect)||m0(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}mQ(r.overlayRect)<mQ(t[e].overlayRect)&&(t[e]=r)}return t})([...i.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let n=e.overlayRect.x-t.overlayRect.x;return 0!==n?n:m1(e.ref,t.ref)}).slice(0,n.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let n=e.overlayRect.x-t.overlayRect.x;return 0!==n?n:m1(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:eD(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var n,a;(function(e,t,r){for(let n=0;n<2;n+=1)m4(e,t.x,t.x+t.width-1,t.y+n,r),m4(e,t.x,t.x+t.width-1,t.y+t.height-1-n,r),m5(e,t.x+n,t.y,t.y+t.height-1,r),m5(e,t.x+t.width-1-n,t.y,t.y+t.height-1,r)})(n=t,(a=e).overlayRect,mV),function(e,t,r){let n=6+5*r.length+ +Math.max(0,r.length-1),a=m3(t.x,0,Math.max(0,e.width-n)),i=t.y-11-2,o=i>=0?i:m3(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,n,a){for(let i=0;i<11;i+=1)for(let o=0;o<n;o+=1)m8(e,t+o,r+i,a)})(e,a,o,n,mB),function(e,t,r,n,a){let i=t;for(let t of n.toLowerCase()){let n=mq[t];if(n)for(let t=0;t<n.length;t+=1)for(let o=0;o<n[t].length;o+=1)"1"===n[t][o]&&m8(e,i+o,r+t,a);i+=6}}(e,a+3,o+2,r,mj)}(n,a.overlayRect,a.ref)}return await u.writeFile(e.screenshotPath,_.sync.write(t)),r}function mW(e){let t=[e.type,e.role,e.subrole].map(e=>cQ(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 mz(e){let t=[e.type,e.role,e.subrole].map(e=>cQ(e??"")).join(" ");return t.includes("application")||t.includes("window")}function mJ(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function mK(e){var t;let r;return!!mJ(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function mX(e){var t;return"string"==typeof e&&!!mK(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function mY(e){let t=[e.label,e.value].find(mK);return t?t.trim():mX(e.identifier)?e.identifier.trim():void 0}function mZ(e){return!!(e&&e.width>0&&e.height>0)}function mQ(e){return e.width*e.height}function m0(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 m1(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function m2(e,t,r){let n=m3(e.x,0,Math.max(0,t-1)),a=m3(e.y,0,Math.max(0,r-1)),i=Math.max(1,t-n),o=Math.max(1,r-a);return{x:n,y:a,width:m3(e.width,1,i),height:m3(e.height,1,o)}}function m3(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function m4(e,t,r,n,a){for(let i=t;i<=r;i+=1)m8(e,i,n,a)}function m5(e,t,r,n,a){for(let i=r;i<=n;i+=1)m8(e,t,i,a)}function m8(e,t,r,n){if(t<0||r<0||t>=e.width||r>=e.height)return;let a=(e.width*r+t)*4;e.data[a]=n[0],e.data[a+1]=n[1],e.data[a+2]=n[2],e.data[a+3]=n[3]}let m6=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),m9=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),m7=new Set(m9),he=new Map;function ht(e,t,r,n){let a=$().requestId;return{...uh(e,t,r,n,a),requestId:a}}async function hr(e,t,r){let n=r.get(t);if(n)return`device:${n.device.id}`;if("open"===e.command||uR(e.flags))try{let t=await l3(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function hn(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,leaseRegistry:i,invoke:o,contextFromFlags:s}=e,l=await mM({req:t,leaseRegistry:i});if(l)return l;let u=await pL({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:o});if(u)return u;let d=await p8({req:t,sessionName:r,logPath:n,sessionStore:a});if(d)return d;let c=await fY({req:t,sessionName:r,sessionStore:a,logPath:n});if(c)return c;let p=await fo({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:o});if(p)return p;let f=await mx({req:t,sessionName:r,sessionStore:a,contextFromFlags:s});return f||null}async function ha(e){var t;let r,n,a,i,o,s,l,{req:u,session:d,logPath:c,sessionStore:p}=e,f=u.command;if(!um(f,d.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${f} is not supported on this device`}};if("android"===d.device.platform&&d.recording&&"record"!==f&&"failed"===await mP({session:d}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:m,resolvedOut:h,recordedPositionals:w,recordedFlags:g}=(r=(t=u).command,n=t.positionals??[],a=t.flags?.out,i="screenshot"===r&&n[0]?[rE.expandHome(n[0],t.meta?.cwd),...n.slice(1)]:n,o="screenshot"===r&&a?rE.expandHome(a,t.meta?.cwd):a,s="screenshot"===r?i:n,l="screenshot"===r&&o?{...t.flags??{},out:o}:t.flags??{},{resolvedPositionals:i,resolvedOut:o,recordedPositionals:s,recordedFlags:l}),y=Date.now(),v={...ht(c,u.flags,d.appBundleId,d.trace?.outPath),surface:d.surface},I=await l4(d.device,f,m,h,{...v});return"screenshot"===f&&u.flags?.overlayRefs&&"string"==typeof I?.path&&await hi(d,I,c),function(e){let{session:t,sessionStore:r,command:n,resolvedPositionals:a,recordedPositionals:i,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:u,flags:d}=e,c=function(e,t,r,n){if("scroll"!==t)return n;let a=f0(e.snapshot),i={...n??{}},o=f8(i.direction)??f8(r[0]);if(!o)return n;let s=f6(i.amount)??f6(r[1]),l=f6(i.pixels),u=me(i,[]),d=f6(i.referenceWidth),c=f6(i.referenceHeight),p=void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:a??f2;if(u&&(u.x1!==u.x2||u.y1!==u.y2))return{...i,x1:u.x1,y1:u.y1,x2:u.x2,y2:u.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250};let f=ia({direction:o,amount:s,pixels:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return{...i,x1:f.x1,y1:f.y1,x2:f.x2,y2:f.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==f.pixels?{pixels:f.pixels}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250}}(t,n,a,s);f3(t,n,a,c,d,l,u),r.recordAction(t,{command:n,positionals:i,flags:o,result:s??{}})}({session:d,sessionStore:p,command:f,resolvedPositionals:m,recordedPositionals:w,recordedFlags:g,data:I,actionStartedAt:y,actionFinishedAt:Date.now(),flags:u.flags??{}}),dv(f)&&dw(d,f),{ok:!0,data:I??{}}}async function hi(e,t,r){let n=pV(await p$({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=n;let a=await mH({screenshotPath:t.path,snapshot:n});t.overlayRefs=a}function ho(e){s.existsSync(e)&&s.unlinkSync(e)}function hs(e){if(!s.existsSync(e))return null;try{let t=JSON.parse(s.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function hl(e){let t=hs(e);if(!t||t.pid===process.pid)try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}function hu(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:hd,infoPath:hc,lockPath:hp,logPath:hf,sessionsDir:hm}=eN(process.env.AGENT_DEVICE_STATE_DIR),hh=ex(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var hw=hm;if(s.existsSync(hw))for(let e of s.readdirSync(hw,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=p.join(hw,e.name,rk);if(s.existsSync(t))try{let e=rL(s.readFileSync(t,"utf8"));if(e&&function(e){let t,r=eS(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let n=V(e.pid);return!!n&&!!((t=n.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||n===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{rP(t)}}let hg=new rE(hm),hy=new nG({maxActiveSimulatorLeases:hu(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:hu(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:hu(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:hu(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),hv=eg(),hI=i.randomBytes(24).toString("hex"),hb=eS(process.pid)??void 0,hA=G(),hS=function(e){let{logPath:t,token:r,sessionStore:n,leaseRegistry:a,trackDownloadableArtifact:i}=e;async function o(e){let s=!!(e.meta?.debug||e.flags?.verbose);return await P({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:s,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:O(new k("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=ef(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,n=q(r);if(r&&!n)throw new k("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!n)throw new k("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let a=e.session||"default";return a.startsWith(`${n}:`)?{...e,meta:{...e.meta,tenantId:n,sessionIsolation:t}}:{...e,session:`${n}:${a}`,meta:{...e.meta,tenantId:n,sessionIsolation:t}}}(e);D({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let s=r.command,l=mD(r);m9.has(s)||r.meta?.sessionIsolation!=="tenant"||a.assertLeaseAdmission({tenantId:l.tenantId,runId:l.runId,leaseId:l.leaseId,backend:l.leaseBackend});let u=function(e,t){var r;let n,a=e.session||"default";if(r=e,n=r.flags?.session,"string"==typeof n&&n.trim().length>0||"default"!==a||t.has(a))return a;let i=t.toArray();return 1===i.length?i[0].name:a}(r,n),d=m7.has(s)?null:await hr(r,u,n),c=async()=>{let e=n.get(u);e&&(!function(e){var t,r;let n,a=e.recording;if(!a||"ios"!==e.device.platform)return;let i=(t=e.device.id,(n=t8.get(t))?{sessionId:n.sessionId,alive:!!(r=n.child.pid)&&eA(r)}:null);if(!a.runnerSessionId){i?.alive&&(a.runnerSessionId=i.sessionId);return}if(!i?.alive){a.invalidatedReason??="iOS runner session exited during recording";return}i.sessionId!==a.runnerSessionId&&(a.invalidatedReason??="iOS runner session restarted during recording")}(e),n.set(u,e));let l=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let n={...e.flags??{}},a=t?mE(t,n):function(e,t,r){var n,a;let i=[];if(void 0!==e.platform&&t&&(n=e.platform,a=t,n&&a&&n!==a&&("apple"===n?!tI(a):"apple"!==a||!tI(n)))&&i.push({key:"platform",value:e.platform}),"open"===r)return i;for(let t of mk){let r=e[t];"string"==typeof r&&r.trim().length>0&&i.push({key:t,value:r})}return i}(n,e.meta?.lockPlatform,e.command);if(0===a.length)return!t&&e.meta?.lockPlatform&&void 0===n.platform&&(n.platform=e.meta.lockPlatform),{...e,flags:n};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(n,a),n.platform=t.device.platform):function(e,t){for(let t of mk)delete e[t];t&&(e.platform=t)}(n,e.meta?.lockPlatform),{...e,flags:n};throw new k("INVALID_ARGS",`${e.command} cannot override session lock policy with ${a.map(mO).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),d=e=>(function(e,t,r){let n=$();if(!t.ok){D({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=U({force:!0})??void 0;return{ok:!1,error:O(new k(t.error.code,t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:n.diagnosticId,logPath:e})}}return D({level:"info",phase:"request_success"}),U(),{ok:!0,data:function(e,t,r){var n,a;let i;if(!t)return t;let o=(n=e,a=t,i=Array.isArray(a.artifacts)?[...a.artifacts]:[],"screenshot"!==n.command||i.some(e=>e?.field==="path")||"string"!=typeof a.path||i.push({field:"path",path:a.path,localPath:n.meta?.clientArtifactPaths?.path,fileName:p.basename(n.meta?.clientArtifactPaths?.path??a.path)}),i.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===o.length?t:{...t,artifacts:o.map(t=>{let n=t.path;return{field:t.field,artifactId:r({artifactPath:n,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(l,e,i);if(e?.recording?.invalidatedReason&&"record"!==s&&"close"!==s)return d({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||l.meta?.lockPolicy||m6.has(s)||function(e,t){let r=mE(e,t);if(0!==r.length){var n;let t,a,i;throw new k("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(n=e).device.platform,a=n.device.name.trim(),i=n.device.id,`${t} device "${a}" (${i})`)} and cannot be used with ${r.map(mO).join(", ")}. Use a different --session name or close this session first.`)}}(e,l.flags);let c=await hn({req:l,sessionName:u,logPath:t,sessionStore:n,leaseRegistry:a,invoke:o,contextFromFlags:(e,r,a)=>({...ht(t,e,r,a),surface:n.get(u)?.surface})});if(c)return d(c);let f=n.get(u);if(!f)return d({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await ha({req:l,session:f,sessionName:u,logPath:t,sessionStore:n});return d(m)};if(!d)return await c();return await tv(he,d,c)}catch(r){D({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=$(),t=U({force:!0})??void 0;return{ok:!1,error:O(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return o}({logPath:hf,token:hI,sessionStore:hg,leaseRegistry:hy,trackDownloadableArtifact:function(e){let t=i.randomUUID(),r=setTimeout(()=>{nd(t)},9e5);return r.unref(),nu.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){s.existsSync(e)||s.mkdirSync(e,{recursive:!0});let n=JSON.stringify(r,null,2),a=()=>{try{return s.writeFileSync(t,n,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(a())return!0;let i=hs(t);if(i?.pid&&i.pid!==process.pid&&W(i.pid,i.processStartTime))return!1;try{s.unlinkSync(t)}catch{}return a()}(hd,hp,{pid:process.pid,version:hv,startedAt:Date.now(),processStartTime:hb})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var n;let a;if("socket"===hh||"dual"===hh){let t=f.createServer(e=>{let t="",r=0,n=new Set,a=!1,i=()=>{if(!a&&0!==r){for(let e of(a=!0,n))eq(e);D({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await rn(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){D({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",i),e.on("error",i),e.on("data",async a=>{let i=(t+=a).indexOf("\n");for(;-1!==i;){let a,o,s=t.slice(0,i).trim();if(t=t.slice(i+1),0===s.length){i=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=eB(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},n.add(o),ej(o),eW(o))throw eJ();a=await hS(e)}catch(e){a={ok:!1,error:O(e)}}finally{r-=1,o&&(n.delete(o),eH(o))}e.destroyed||e.write(`${JSON.stringify(a)}
|
|
69
|
-
`),
|
|
33
|
+
`.trim();async function ng(e,t={}){let r,i=t.pollMs??150,n=t.attempts??12,o=0;for(let t=0;t<n;t+=1){let t=0;try{t=a.statSync(e).size}catch{t=0}if(t>0&&t===r){if((o+=1)>=2)return}else o=0;r=t,await new Promise(e=>setTimeout(e,i))}}async function nw(e){try{var t,r;let a,i=await tw("swift",["-",e],{stdin:nh,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
|
|
34
|
+
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return ny(e);return!1}catch(t){if(t instanceof tI&&"TOOL_MISSING"===t.code)return ny(e);throw t}}async function nv(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nw(e))return;await new Promise(e=>setTimeout(e,r))}}function ny(e){try{let t=a.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=a.openSync(e,"r");try{let e=a.fstatSync(t).size,r=0,i=[];for(;r+8<=e&&i.length<16;){let e=Buffer.alloc(8);if(8>a.readSync(t,e,0,8,r))break;let n=e.readUInt32BE(0),o=e.toString("latin1",4,8);if(i.push(o),1===n){let e=Buffer.alloc(8);if(8>a.readSync(t,e,0,8,r+8))break;n=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(n)||n<=0)break;r+=n}return i}finally{a.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function nI(e){let t=n.parse(e);return n.join(t.dir,`${t.name}.gesture-telemetry.json`)}function nS(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nA(e){let t=n.dirname(l(import.meta.url)),r=[l(new URL(`./${e}`,import.meta.url)),n.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(a.existsSync(e))return e;throw new tI("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})}async function nb(e){let{videoPath:t,scriptPath:r,scriptArgs:i,commandDescription:o}=e;await ng(t),await nv(t);let s=a.mkdtempSync(n.join(u.tmpdir(),"agent-device-record-overlay-")),l=n.join(s,`input${n.extname(t)||".mp4"}`),d=n.join(s,n.basename(t)),c=n.join(s,"home"),f=n.join(s,"module-cache");a.copyFileSync(t,l),a.mkdirSync(c,{recursive:!0}),a.mkdirSync(f,{recursive:!0});try{await tw("xcrun",["swift",r,"--input",l,"--output",d,...i],{timeoutMs:12e4,env:{...process.env,HOME:c,CLANG_MODULE_CACHE_PATH:f}}),await nv(d),a.copyFileSync(d,t)}catch(a){let e=a instanceof tI?a:new tI("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new tI("COMMAND_FAILED",o,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{a.rmSync(s,{recursive:!0,force:!0})}}async function n_(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nb({videoPath:r,scriptPath:t??=nA("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nN(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nb({videoPath:r,scriptPath:e??=nA("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function nx(e){return e instanceof Error?e.message:String(e)}function nM(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function nk(e){let{recording:t,deps:r,trimStartMs:i,targetLabel:n}=e,o=function(e){var t,r,i;let n,o,{recording:s,trimStartMs:l}=e,d=(n=nI((t={videoPath:s.outPath,events:s.gestureEvents,trimStartMs:l}).videoPath),o={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(i=t.trimStartMs??0)>0?nS(r.flatMap(e=>{let t=e.tMs-i,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):nS(r))},a.writeFileSync(n,JSON.stringify(o,null,2)),n);return s.telemetryPath=d,d}({recording:t,trimStartMs:i});if(t.showTouches){let e=function(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}();if(e)t.overlayWarning=e;else try{await r.overlayRecordingTouches({videoPath:t.outPath,telemetryPath:o,targetLabel:n})}catch(e){t.overlayWarning=`failed to overlay recording touches: ${nx(e)}`}}}async function nD(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 nP(e,t,r){for(let a=0;a<40;a+=1){if(!await nD(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await nD(e,t,r)}async function nL(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 nR(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 nD(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function nO(e){let t,{deps:r,deviceId:i,remotePath:n,outPath:o}=e;for(let e=0;e<2;e+=1){try{a.rmSync(o,{force:!0})}catch{}let s=await r.runCmd("adb",["-s",i,"pull",n,o],{allowFailure:!0});if(0!==s.exitCode)t=nM(s,"adb pull");else{await r.waitForStableFile(o,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(o);if(ti({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:i,remotePath:n,outPath:o,attempt:e+1,fileSize:(()=>{try{return a.statSync(o).size}catch{return 0}})(),playable:t}}),t)return;ti({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:i,remotePath:n,outPath:o,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 nE(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function nC(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return ti({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 nD(e,t,r))&&await nP(e,t,r)}async function n$(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: ${nM(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 nE(a,i.id,e);continue}if(ti({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await nR(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 nC(a,i.id,r),await nE(a,i.id,e)}return N("COMMAND_FAILED",o)}async function nT(e){let t,r,{deps:a,device:i,recording:n}=e;ti({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(ti({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 nD(a,i.id,n.remotePid)&&!await nC(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${nM(o,"adb shell kill")}`):await nP(a,i.id,n.remotePid)||await nC(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await nL(a,i.id,n.remotePath);let e=await nO({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),N("COMMAND_FAILED",e);await nk({recording:n,deps:a,targetLabel:"Android recording"})}if(await s(),t)return N("COMMAND_FAILED",t);if(r)return N("COMMAND_FAILED",r);return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});ti({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: ${nM(e,"adb shell rm")}`)}}function nF(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function nU(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function nG(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=nF(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},nU(t,i,r))}catch(e){ti({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:nx(e)}})}}async function nV(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=nU(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:f,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 g,w;if(!nx(a).toLowerCase().includes("recording already in progress"))return N("COMMAND_FAILED",`failed to start recording: ${nx(a)}`);ti({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:nx(a)}});let e=(g=o.id,w=i.name,n.toArray().find(e=>e.name!==w&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===g&&e.recording?.platform==="ios-device-runner"));if(e)return N("COMMAND_FAILED",`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 N("COMMAND_FAILED",`failed to start recording: ${nx(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function nq(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},nU(t,i,r))}catch(e){return N("COMMAND_FAILED",`failed to start recording: ${nx(e)}`)}return{platform:"macos-runner",...s}}async function nj(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=nF(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nU(t,i,r))}catch(e){ti({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nx(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of ef)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 N("COMMAND_FAILED",`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);return d>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:d}),await nk({recording:o,deps:n,trimStartMs:d,targetLabel:"iOS recording"}),null}async function nB(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=nF(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nU(t,i,r))}catch(e){ti({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nx(e)}})}return await nk({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function nH(e){for(let t=0;t<2;t+=1){try{if(a.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 nK(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await nG({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:u,wait:c}=s.runCmdBackground("xcrun",tr(n,["io",n.id,"recordVideo",d]),{allowFailure:!0}),f=await nH(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:nF(i)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:i.trace?.outPath}),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:u,wait:c,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function nz(e){let t,{req:r,sessionName:i,sessionStore:o,activeSession:s,device:l,logPath:d,deps:u}=e;if(s.recording)return N("INVALID_ARGS","recording already in progress");let c=r.flags?.fps;if(void 0!==c&&(!Number.isInteger(c)||c<1||c>120))return N("INVALID_ARGS","fps must be an integer between 1 and 120");if(!tl("record",l))return N("UNSUPPORTED_OPERATION","record is not supported on this device");let f=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,p=tG.expandHome(f,r.meta?.cwd),m={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(a.mkdirSync(n.dirname(p),{recursive:!0}),a.rmSync(p,{force:!0}),"ios"===l.platform&&"device"===l.kind){let e=nF(s);if(!e)return N("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await nV({req:r,activeSession:s,sessionStore:o,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:m,appBundleId:e})}else if("macos"===l.platform){let e=nF(s);if(!e)return N("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await nq({req:r,activeSession:s,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:m,appBundleId:e})}else t="ios"===l.platform?await nK({req:r,activeSession:s,device:l,logPath:d,deps:u,recordingBase:m,resolvedOut:p}):await n$({deps:u,device:l,recordingBase:m});return"ok"in t?t:(s.recording=t,o.set(i,s),o.recordAction(s,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??f,showTouches:t.showTouches}})}async function nW(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await nT({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;return 0!==i.exitCode?N("COMMAND_FAILED",`failed to stop recording: ${nM(i,"simctl recordVideo")}`):(await nk({recording:a,deps:t,targetLabel:"iOS recording"}),null)}async function nJ(e){var t;let r,{req:a,activeSession:i,device:o,logPath:s,deps:l}=e;if(!i.recording)return N("INVALID_ARGS","no active recording");let d=i.recording,u=d.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===d.platform?await nj({req:a,activeSession:i,device:o,logPath:s,deps:l,recording:d}):"macos-runner"===d.platform?await nB({req:a,activeSession:i,device:o,logPath:s,deps:l,recording:d}):await nW({deps:l,device:o,recording:d});return c||(u?N("COMMAND_FAILED",u):(r=[{field:"outPath",path:(t=d).outPath,localPath:t.clientOutPath,fileName:n.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return nI(e.clientOutPath)}(t),fileName:n.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function nZ(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:tw,runCmdBackground:tg,runIosRunnerCommand:e8,waitForStableFile:ng,isPlayableVideo:nw,trimRecordingStart:n_,overlayRecordingTouches:nN},o=a.get(r),s=o?.device??await eR(t.flags??{});o||await e9(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return N("INVALID_ARGS","record requires start|stop");if("start"===d)return nz({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await nJ({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 nY(e){let{req:t,sessionName:r,sessionStore:i,logPath:o}=e,s=t.command;if("record"===s)return nZ({req:t,sessionName:r,sessionStore:i,logPath:o});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return N("INVALID_ARGS","trace requires start|stop");let o=i.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session");if("start"===e){if(o.trace)return N("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??i.defaultTracePath(o),r=tG.expandHome(e);return a.mkdirSync(n.dirname(r),{recursive:!0}),a.appendFileSync(r,""),o.trace={outPath:r,startedAt:Date.now()},i.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!o.trace)return N("INVALID_ARGS","no active trace");let l=o.trace.outPath;if(t.positionals?.[1]){let e=tG.expandHome(t.positionals[1]);a.mkdirSync(n.dirname(e),{recursive:!0}),a.existsSync(l)?a.renameSync(l,e):a.appendFileSync(e,""),l=e}return o.trace=void 0,i.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l}}),{ok:!0,data:{trace:"stopped",outPath:l}}}return null}function nX(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 nQ=new WeakMap;function n0(e){if(!e)return;let t=nQ.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)&&n1(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(n1);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 nQ.set(e,r),r}function n1(e){return!!e&&e.width>0&&e.height>0}let n2={referenceWidth:1e3,referenceHeight:1e3};function n5(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,f=e.recording;if(!f)return;let p={...i,...a??{}},m=n6(p.effectiveDurationMs)??n6(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:n6(p.gestureStartUptimeMs),gestureEndUptimeMs:n6(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:n6(p.gestureStartUptimeMs),gestureEndUptimeMs:n6(p.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),w="ios"===e.device.platform&&void 0===n6(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=n9(n6(t.count),1)??1,r=!0===t.doubleTap,a=n9(n6(t.holdMs),1);return 1===e&&!r&&void 0===a}default:return!1}}(t,p)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return nX(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):nX(h),v=(l=e.snapshot,u=n6((d=p).referenceWidth),c=n6(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:n0(l)),y=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=n7(t,e);if(!i)return[];let{x:n,y:o}=i,s=n9(n6(t.count),1)??1,l=n9(n6(t.intervalMs),0)??0,d=!0===t.doubleTap,u=n9(n6(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(n3(t,n,o,u,a));continue}c.push(n4(t,n,o,a)),d&&c.push(n4(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=n7(t,e);if(!i)return[];let{x:n,y:o}=i;return[n4(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=n7(t,e);if(!n)return[];let{x:o,y:s}=n;return[n3(r,o,s,ot(a,[n6(t.durationMs),n6(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=oe(t,e),o=n8(t.contentDirection)??n8(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=ot(a,[],250),f=n6(t.amount)??n6(e[1]),p=n6(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==f?{amount:f}:{},...void 0!==p?{pixels:p}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=oe(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=ot(a,[n6(t.effectiveDurationMs),n6(t.durationMs),n6(e[4])],250),c=n9(n6(t.count),1)??1,f=n9(n6(t.pauseMs),0)??0,p="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===p&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,g=r+e*(u+f);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:g,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:g,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=n7(t,e,1),o=n6(t.scale)??n6(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:ot(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,w,g,v);0!==y.length&&(f.gestureEvents.push(...y),ti({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:y.length,tMs:w,gestureDurationMs:g,kinds:y.map(e=>e.kind)}}))}function n4(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function n3(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function n8(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 n6(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 n9(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function n7(e,t,r=0){let a=n6(e.x)??n6(t[r]),i=n6(e.y)??n6(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function oe(e,t){let r=n6(e.x1)??n6(t[0]),a=n6(e.y1)??n6(t[1]),i=n6(e.x2)??n6(t[2]),n=n6(e.y2)??n6(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 ot(e,t,r){return n9(e,1)??t.map(e=>n9(e,1)).find(e=>void 0!==e)??r}function or(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??{},...M(c)}}async function oa(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:i,flags:n,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,afterDispatch:u,buildPayloads:c}=e,f=await oi({session:t,flags:n,contextFromFlags:o,command:s,positionals:l,outPath:d});await u?.(f.data);let{result:p,responseData:m=p}=await c(f.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}),eb(a)&&tm(t,a),n5(t,a,i,o,n??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:i,flags:n,result:p,responseData:m,actionStartedAt:f.actionStartedAt,actionFinishedAt:f.actionFinishedAt})}async function oi(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 w(t.device,i,n,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function on(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 O(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=n0(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=n0(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oo(e){try{return await on(e)}catch(t){ti({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function os(e){return n0({nodes:e,createdAt:0})}function ol(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:N("UNSUPPORTED_OPERATION",`${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 od(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 N("SESSION_NOT_FOUND","No active session. Run open first.");let c=ol(l,u);if(c)return c;if(!tl("press",l.device))return N("UNSUPPORTED_OPERATION","press is not supported on this device");let f=ez(t.flags),p=ep(f);if("primary"!==f){let e=eN({commandLabel:u,platform:l.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(e)return N(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return oa({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,afterDispatch:async()=>{await ou(l,"coordinate tap")},buildPayloads:async e=>{let r=await oo({session:l,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}),o=or({data:e,fallbackX:m.x,fallbackY:m.y,referenceFrame:r,extra:p});return{result:o,responseData:o}}});let h="click",g=t.positionals?.[0]??"";if(g.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 nr({session:l,refInput:g,fallbackLabel:r,commandLabel:u,promoteToHittableAncestor:!0,invalidRefMessage:`${u} 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,resolveRefTarget:o});if(!c.ok)return c;let{ref:f,node:m,snapshotNodes:w,point:v}=c.target,y=e0(m,w),I=ew(m,l.device.platform,{action:h}),{x:S,y:A}=v;return oa({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(S),String(A)],outPath:t.flags?.out,afterDispatch:async()=>{await ou(l,`@${f}`)},buildPayloads:e=>{let t=or({data:e,fallbackX:S,fallbackY:A,referenceFrame:os(w),extra:{ref:f,refLabel:y,selectorChain:I,...p}});return{result:t,responseData:t}}})}let w=(t.positionals??[]).join(" ").trim();if(!w)return N("INVALID_ARGS",`${u} requires @ref, selector expression, or x y coordinates`);let v=eH(w),y=await n(l,t.flags,a,i,{interactiveOnly:!0}),I=await eD("selector_resolve",()=>A(y.nodes,v,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:d});if(!I||!I.node.rect)return N("COMMAND_FAILED",eS(v,I?.diagnostics??[],{unique:!0}));let S=na(y.nodes,I.node),b=ne(S.rect);if(!b)return N("COMMAND_FAILED",`Selector ${I.selector.raw} resolved to invalid bounds`);let{x:_,y:x}=b,M=ew(S,l.device.platform,{action:h}),k=e0(S,y.nodes);return oa({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(_),String(x)],outPath:t.flags?.out,afterDispatch:async()=>{await ou(l,I.selector.raw)},buildPayloads:e=>{let t=or({data:e,fallbackX:_,fallbackY:x,referenceFrame:os(y.nodes),extra:{selector:I.selector.raw,selectorChain:M,refLabel:k,...p}});return{result:t,responseData:t}}})}async function ou(e,t){if("android"!==e.device.platform||!e.appBundleId)return;let r=await eT(e.device),a=r.package?.trim();if(a&&a!==e.appBundleId){var i;if("com.android.settings"===(i=a)||"com.android.systemui"===i||"com.google.android.permissioncontroller"===i||i.includes("launcher"))throw new tI("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${a}. The tap likely escaped the app.`,{expectedPackage:e.appBundleId,foregroundPackage:a,activity:r.activity,hint:"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."})}}async function oc(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=ol(l,"fill");if(e)return e}if(l&&!tl("fill",l.device))return N("UNSUPPORTED_OPERATION","fill is not supported on this device");if(t.positionals?.[0]?.startsWith("@")){if(!l)return N("SESSION_NOT_FOUND","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 N("INVALID_ARGS","fill requires text after ref");let u=await nr({session:l,refInput:t.positionals[0],fallbackLabel:r,commandLabel:"fill",promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!u.ok)return u;let{ref:c,node:f,snapshotNodes:p,point:m}=u.target,h=f.type??"",g=h&&!ea(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,w=e0(f,p),v=ew(f,l.device.platform,{action:"fill"}),{x:y,y:I}=m;return oa({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=or({data:e,fallbackX:y,fallbackY:I,referenceFrame:os(p),extra:{ref:c,refLabel:w,selectorChain:v,text:d}}),r={...e??{ref:c,x:y,y:I}};return g&&(t.warning=g,r.warning=g),{result:t,responseData:r}}})}if(!l)return N("SESSION_NOT_FOUND","No active session. Run open first.");let d=es(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return N("INVALID_ARGS","fill requires text after selector");let e=d.rest.join(" ").trim();if(!e)return N("INVALID_ARGS","fill requires text after selector");let r=eH(d.selectorExpression),o=await n(l,t.flags,a,i,{interactiveOnly:!0}),s=await eD("selector_resolve",()=>A(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return N("COMMAND_FAILED",eS(r,s?.diagnostics??[],{unique:!0}));let u=s.node,c=s.node.rect,f=u.type??"",p=f&&!ea(f,l.device.platform)?`fill target ${s.selector.raw} resolved to "${f}", attempting fill anyway.`:void 0,{x:m,y:h}=et(c),g=ew(u,l.device.platform,{action:"fill"});return oa({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=or({data:t,fallbackX:m,fallbackY:h,referenceFrame:os(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:g,refLabel:e0(u,o.nodes)}});return p&&(r.warning=p),{result:r,responseData:r}}})}return N("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}async function of(e){switch(e.req.command){case"press":case"click":return await od(e);case"fill":return await oc(e);default:return null}}let op=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function om(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of op)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:N("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function oh(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 eB({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 og(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=eH(r),f=await oh(a,i,n,o,{interactiveOnly:s}),p=await eD("selector_resolve",()=>A(f.nodes,c,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return p&&(!l||p.node.rect)?{ok:!0,chain:c,snapshot:f,resolved:p}:{ok:!1,error:{code:"COMMAND_FAILED",message:eS(c,p?.diagnostics??[],{unique:d})}}}async function ow(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return N("INVALID_ARGS","get only supports text or attrs");let o=a.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!tl("get",o.device))return N("UNSUPPORTED_OPERATION","get is not supported on this device");let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=om("get",t.flags);if(e)return e;let r=i7({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;let{ref:l,node:d}=r.target,u=ew(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 nn({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:ov(c),selectorChain:u}}),{ok:!0,data:{ref:l,text:c,node:d}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return N("INVALID_ARGS","get requires @ref or selector expression");let d=await og({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;let{resolved:u}=d,c=u.node,f=ew(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:f}}),{ok:!0,data:{selector:u.selector.raw,node:c}};let p=await nn({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:p,refLabel:ov(p),selector:u.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:u.selector.raw,text:p,node:c}}}function ov(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function oy(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 oI(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 N("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let o=a.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!tl("is",o.device))return N("UNSUPPORTED_OPERATION","is is not supported on this device");let{split:s}=eX(t.positionals);if(!s)return N("INVALID_ARGS","is requires a selector expression");let l=s.rest.join(" ").trim();if("text"===n&&!l)return N("INVALID_ARGS","is text requires expected text value");if("text"!==n&&s.rest.length>0)return N("INVALID_ARGS",`is ${n} does not accept trailing values`);let d=eH(s.selectorExpression);if("exists"===n){let e=eE((await oh(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}}):N("COMMAND_FAILED",eS(d,[],{unique:!1}))}let u=await og({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;let{resolved:c}=u,f=function(e){let{predicate:t,node:r,nodes:a,expectedText:i,platform:n}=e,o=C(r),s=S(r,n),l=!0===r.selected,d="text"===t?ex(r):function(e,t){if(!0===e.hittable)return!0;if(oy(e.rect))return v(e,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=tc(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||oy(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!oy(r.rect)&&v(r,t))}(r,a),u=!1;switch(t){case"visible":u=d;break;case"hidden":u=!d;break;case"editable":u=s;break;case"selected":u=l;break;case"text":u=o===(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 f.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?f.actualText:void 0}}),{ok:!0,data:{predicate:n,pass:!0,selector:c.selector.raw}}):N("COMMAND_FAILED",`is ${n} failed for selector ${c.selector.raw}: ${f.details}`)}function oS(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),f=e.y+e.height/2,p=e.x+e.width/2;if(f>=o+.25*i&&f<=u)return null;let m=Math.round((r=p,a=l+c,Math.min(d-c,Math.max(a,r)))),h=Math.round(o+.86*i),g=Math.round(o+.14*i);return f>u?{x:m,startY:h,endY:g,direction:"down"}:{x:m,startY:g,endY:h,direction:"up"}}async function oA(e){var t;let r,a,i,{req:n,sessionName:o,sessionStore:s,contextFromFlags:l}=e,d=s.get(o);if(!d)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!tl("scrollintoview",d.device))return N("UNSUPPORTED_OPERATION","scrollintoview is not supported on this device");let u=n.positionals?.[0]??"";if(!u.startsWith("@"))return null;let c=om("scrollintoview",n.flags);if(c)return c;let f=n.positionals&&n.positionals.length>1?n.positionals.slice(1).join(" ").trim():"",p=(r=i7({session:d,refInput:t=u,fallbackLabel:f,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${t} not found or has no bounds`})).ok?ob(t,0,r.target):"COMMAND_FAILED"!==r.error.code?r:o_(t,0,{message:r.error.message});if(!p.ok)return p;let{ref:m}=p.state,{currentRef:h,node:g,snapshotNodes:v,viewportRect:y}=p.state,I=e0(g,v),S=ew(g,d.device.platform,{action:"get"}),b=f||I||g.label||"";if(!oS(g.rect,y)){let e=oN({ref:m,currentRef:h,attempts:0,alreadyVisible:!0});return s.recordAction(d,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:{refLabel:I,selectorChain:S,...e}}),{ok:!0,data:e}}let _=n.flags?.maxScrolls??48,x=0,M=0,k=eY(g.rect,y);for(;x<_;){let e=oS(g.rect,y);if(!e)break;a=e.direction,i=await w(d.device,"swipe",[String(e.x),String(e.startY),String(e.x),String(e.endY),"16"],n.flags?.out,{...l(n.flags,d.appBundleId,d.trace?.outPath),count:1,pauseMs:0,pattern:"one-way"}),x+=1,await oh(d,n.flags,s,l,{interactiveOnly:!0});let t=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=A(e,eH(r),{platform:a,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?to(e,r):null}(t.snapshot.nodes,o,a,s);if(e)return ob(r,i,{ref:n,node:e,snapshotNodes:t.snapshot.nodes},{currentRef:e.ref})}let l=i7({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${r} not found or has no bounds`});return l.ok?ob(r,i,l.target,{ref:n,currentRef:l.target.node.ref,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${i} scroll${1===i?"":"s"}`}):"COMMAND_FAILED"!==l.error.code?l:o_(r,i,{message:`scrollintoview lost track of ${r} after ${i} scroll${1===i?"":"s"}`,ref:n})}({session:d,targetInput:u,fallbackLabel:b,attempts:x,ref:m,selectorChain:S,platform:d.device.platform});if(!t.ok)return t;({currentRef:h,node:g,snapshotNodes:v,viewportRect:y}=t.state);let r=eY(g.rect,y);if(0===r)break;if(r>=k){if((M+=1)>=2)return o_(u,x,{message:`scrollintoview made no progress toward ${u} after ${x} scroll${1===x?"":"s"}`,ref:m,stalled:!0})}else M=0;k=r}if(eY(g.rect,y)>0)return o_(u,x,{message:`scrollintoview reached --max-scrolls=${_} before ${u} entered view`,ref:m,maxScrolls:_});let D=oN({data:i,ref:m,currentRef:h,attempts:x,direction:a});return s.recordAction(d,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:{refLabel:I,selectorChain:S,...D}}),{ok:!0,data:D}}function ob(e,t,r,a={}){let{ref:i,currentRef:n,missingBoundsMessage:o}=a,s=r.node;if(!s.rect)return o_(e,t,{message:o??`Ref ${e} not found or has no bounds`,ref:i??r.ref});let l=j(r.snapshotNodes,s.rect);return l?{ok:!0,state:{ref:i??r.ref,currentRef:n??r.node.ref,node:s,snapshotNodes:r.snapshotNodes,viewportRect:l}}:N("COMMAND_FAILED",`scrollintoview could not infer viewport for ${e}`)}function o_(e,t,r={}){let{message:a,...i}=r;return N("COMMAND_FAILED","string"==typeof a?a:`scrollintoview could not find ${e}`,{reason:"not_found",attempts:t,...i})}function oN(e){let{data:t,ref:r,currentRef:a,attempts:i,alreadyVisible:n,direction:o}=e;return{...t??{},ref:r,currentRef:a,attempts:i,...n?{alreadyVisible:n}:{},...o?{direction:o}:{},...M(`Scrolled into view: @${r}`)}}async function ox(e){let t=await of({...e,captureSnapshotForSession:oh,resolveRefTarget:i7,refSnapshotFlagGuardResponse:om});if(t)return t;switch(e.req.command){case"get":return await ow(e);case"is":return await oI(e);case"scrollintoview":return await oA(e);default:return null}}function oM(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 ok(e){let{req:t,leaseRegistry:r}=e,a=oM(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 oD(e,t){if(!t)return[];let r=[],a=e.device,i=tf(t.platform);if(i&&!ts(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=L(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function oP(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 oL=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],oR=/\bis(?:n't| not)\s+responding\b/i,oO=/^close app$/i;async function oE(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oC(t),r=function(e){if(oU(e))return e.find(e=>{let t=oF(e);return t.length>0&&oO.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=et(r.rect),n=await tw("adb",eQ(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return ti({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 o$(t))return ti({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eZ(t.device,t.appBundleId),!await oT(t,t.appBundleId)))return ti({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return ti({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 ti({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 oC(e){return ei(eP((await ek(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function o$(e){for(let t=0;t<12;t+=1){if(!oU(await oC(e)))return!0;await oG(500)}return!oU(await oC(e))}async function oT(e,t){for(let r=0;r<12;r+=1){if((await eT(e.device)).package===t)return!0;await oG(500)}return(await eT(e.device)).package===t}function oF(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 oU(e){return e.some(e=>{let t=oF(e);return t.length>0&&oR.test(t)})}function oG(e){return new Promise(t=>setTimeout(t,e))}let oV=[255,59,48,255],oq=[255,214,10,255],oj=[0,0,0,255],oB={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 oH(e){let t=tp(await i.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)oz(r)&&oX(r.rect)&&(!t||oQ(r.rect)>oQ(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&&oX(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 oX(e.rect)&&!("image"===tc((t=e).type??"")&&!oW(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(oJ)||oZ(e.identifier);return oK(e)?t:t&&function(e){let t=tc(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 oK(e)&&!oz(e)}(t)&&oX(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(oK(t)&&!oz(t)&&oX(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&oX(r.rect))return r;if(t.hittable&&oX(t.rect)&&!oz(t))return t;let a=W(e,t);return a?.rect&&oX(a.rect)&&!oz(a)?a:null}(e.nodes,a);if(!o?.rect||!oX(o.rect))continue;let s=function(e,t,r){let a=oY(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=oY(a);if(!i)continue;let n=function(e){let t=0;return tc(e.type??"").includes("text")&&(t+=2),oJ(e.label)&&(t+=2),oJ(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(oY(t)??e0(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),oK(t)&&(a+=3),oK(e)&&(a+=2),r&&(a+=2),oZ(t.identifier)&&(a+=1),oW(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return o2({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 o2({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(!oX(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)=>oQ(e.overlayRect)-oQ(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(o0(e.overlayRect,r.overlayRect)||o0(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}oQ(r.overlayRect)<oQ(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:o1(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:o1(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:et(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,n;(function(e,t,r){for(let a=0;a<2;a+=1)o4(e,t.x,t.x+t.width-1,t.y+a,r),o4(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),o3(e,t.x+a,t.y,t.y+t.height-1,r),o3(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(n=e).overlayRect,oV),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=o5(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:o5(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,i){for(let n=0;n<11;n+=1)for(let o=0;o<a;o+=1)o8(e,t+o,r+n,i)})(e,i,o,a,oq),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=oB[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]&&o8(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,oj)}(a,n.overlayRect,n.ref)}return await i.writeFile(e.screenshotPath,p.sync.write(t)),r}function oK(e){let t=[e.type,e.role,e.subrole].map(e=>tc(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 oz(e){let t=[e.type,e.role,e.subrole].map(e=>tc(e??"")).join(" ");return t.includes("application")||t.includes("window")}function oW(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function oJ(e){var t;let r;return!!oW(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function oZ(e){var t;return"string"==typeof e&&!!oJ(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function oY(e){let t=[e.label,e.value].find(oJ);return t?t.trim():oZ(e.identifier)?e.identifier.trim():void 0}function oX(e){return!!(e&&e.width>0&&e.height>0)}function oQ(e){return e.width*e.height}function o0(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 o1(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function o2(e,t,r){let a=o5(e.x,0,Math.max(0,t-1)),i=o5(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:o5(e.width,1,n),height:o5(e.height,1,o)}}function o5(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function o4(e,t,r,a,i){for(let n=t;n<=r;n+=1)o8(e,n,a,i)}function o3(e,t,r,a,i){for(let n=r;n<=a;n+=1)o8(e,t,n,i)}function o8(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 o6=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),o9=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),o7=new Set(o9),se=new Map;function st(e,t,r,a){let i=e7().requestId;return{...eV(e,t,r,a,i),requestId:i}}async function sr(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||at(e.flags))try{let t=await eR(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function sa(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await ok({req:t,leaseRegistry:n});if(l)return l;let d=await i9({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(d)return d;let u=await I({req:t,sessionName:r,logPath:a,sessionStore:i});if(u)return u;let c=await nY({req:t,sessionName:r,sessionStore:i,logPath:a});if(c)return c;let f=await no({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await ox({req:t,sessionName:r,sessionStore:i,contextFromFlags:s});return p||null}async function si(e){var t;let r,a,i,n,o,s,l,{req:d,session:u,logPath:c,sessionStore:f}=e,p=d.command;if(!tl(p,u.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${p} is not supported on this device`}};if("android"===u.device.platform&&u.recording&&"record"!==p&&"failed"===await oE({session:u}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:m,resolvedOut:h,recordedPositionals:g,recordedFlags:v}=(r=(t=d).command,a=t.positionals??[],i=t.flags?.out,n="screenshot"===r&&a[0]?[tG.expandHome(a[0],t.meta?.cwd),...a.slice(1)]:a,o="screenshot"===r&&i?tG.expandHome(i,t.meta?.cwd):i,s="screenshot"===r?n:a,l="screenshot"===r&&o?{...t.flags??{},out:o}:t.flags??{},{resolvedPositionals:n,resolvedOut:o,recordedPositionals:s,recordedFlags:l}),y=Date.now(),I={...st(c,d.flags,u.appBundleId,u.trace?.outPath),surface:u.surface},S=await w(u.device,p,m,h,{...I});return"screenshot"===p&&d.flags?.overlayRefs&&"string"==typeof S?.path&&await sn(u,S,c),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:i,recordedPositionals:n,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:d,flags:u}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let i=n0(e.snapshot),n={...a??{}},o=n8(n.direction)??n8(r[0]);if(!o)return a;let s=n6(n.amount)??n6(r[1]),l=n6(n.pixels),d=oe(n,[]),u=n6(n.referenceWidth),c=n6(n.referenceHeight),f=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:i??n2;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:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250};let p=eo({direction:o,amount:s,pixels:l,referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight});return{...n,x1:p.x1,y1:p.y1,x2:p.x2,y2:p.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==p.pixels?{pixels:p.pixels}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250}}(t,a,i,s);n5(t,a,i,c,u,l,d),r.recordAction(t,{command:a,positionals:n,flags:o,result:s??{}})}({session:u,sessionStore:f,command:p,resolvedPositionals:m,recordedPositionals:g,recordedFlags:v,data:S,actionStartedAt:y,actionFinishedAt:Date.now(),flags:d.flags??{}}),eb(p)&&tm(u,p),{ok:!0,data:S??{}}}async function sn(e,t,r){let a=eJ(await T({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=a;let i=await oH({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}function so(e){a.existsSync(e)&&a.unlinkSync(e)}function ss(e){if(!a.existsSync(e))return null;try{let t=JSON.parse(a.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function sl(e){let t=ss(e);if(!t||t.pid===process.pid)try{a.existsSync(e)&&a.unlinkSync(e)}catch{}}function sd(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:su,infoPath:sc,lockPath:sf,logPath:sp,sessionsDir:sm}=td(process.env.AGENT_DEVICE_STATE_DIR),sh=eu(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sg=sm;if(a.existsSync(sg))for(let e of a.readdirSync(sg,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=n.join(sg,e.name,tq);if(a.existsSync(t))try{let e=tj(a.readFileSync(t,"utf8"));if(e&&function(e){let t,r=Y(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=el(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{tH(t)}}let sw=new tG(sm),sv=new rY({maxActiveSimulatorLeases:sd(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sd(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sd(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sd(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),sy=H(),sI=r.randomBytes(24).toString("hex"),sS=Y(process.pid)??void 0,sA=ej(),sb=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:o}=e;async function s(e){let l=!!(e.meta?.debug||e.flags?.verbose);return await X({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:l,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:ty(new tI("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=_(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=eK(r);if(r&&!a)throw new tI("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new tI("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);ti({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let l=r.command,d=oM(r);o9.has(l)||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=o7.has(l)?null:await sr(r,u,a),f=async()=>{let e=a.get(u);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=V(e.device.id);if(!t.runnerSessionId){r?.alive&&(t.runnerSessionId=r.sessionId);return}if(!r?.alive){t.invalidatedReason??="iOS runner session exited during recording";return}r.sessionId!==t.runnerSessionId&&(t.invalidatedReason??="iOS runner session restarted during recording")}(e),a.set(u,e));let d=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?oD(t,a):function(e,t,r){var a,i;let n=[],o=tf(t);if(void 0!==e.platform&&o&&(a=tf(e.platform),i=o,a&&i&&a!==i&&("apple"===a?!Q(i):"apple"!==i||!Q(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of oL){let r=e[t];"string"==typeof r&&r.trim().length>0&&n.push({key:t,value:r})}return n}(a,e.meta?.lockPlatform,e.command);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 oL)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new tI("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(oP).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),c=e=>(function(e,t,r){let a=e7();if(!t.ok){ti({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=tu({force:!0})??void 0;return{ok:!1,error:ty(new tI(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 ti({level:"info",phase:"request_success"}),tu(),{ok:!0,data:function(e,t,r){var a,i;let o;if(!t)return t;let s=(a=e,i=t,o=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||o.some(e=>e?.field==="path")||"string"!=typeof i.path||o.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:n.basename(a.meta?.clientArtifactPaths?.path??i.path)}),o.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===s.length?t:{...t,artifacts:s.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(d,e,o);if(e?.recording?.invalidatedReason&&"record"!==l&&"close"!==l)return c({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||d.meta?.lockPolicy||o6.has(l)||function(e,t){let r=oD(e,t);if(0!==r.length){var a;let t,i,n;throw new tI("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(oP).join(", ")}. Use a different --session name or close this session first.`)}}(e,d.flags);let f=await sa({req:d,sessionName:u,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...st(t,e,r,i),surface:a.get(u)?.surface})});if(f)return c(f);let p=a.get(u);if(!p)return c({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await si({req:d,session:p,sessionName:u,logPath:t,sessionStore:a});return c(m)};if(!c)return await f();return await D(se,c,f)}catch(r){ti({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=e7(),t=tu({force:!0})??void 0;return{ok:!1,error:ty(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return s}({logPath:sp,token:sI,sessionStore:sw,leaseRegistry:sv,trackDownloadableArtifact:function(e){let t=r.randomUUID(),a=setTimeout(()=>{rS(t)},9e5);return a.unref(),rI.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:a}),t}});!async function(){let e,t;if(!function(e,t,r){a.existsSync(e)||a.mkdirSync(e,{recursive:!0});let i=JSON.stringify(r,null,2),n=()=>{try{return a.writeFileSync(t,i,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(n())return!0;let o=ss(t);if(o?.pid&&o.pid!==process.pid&&y(o.pid,o.processStartTime))return!1;try{a.unlinkSync(t)}catch{}return n()}(su,sf,{pid:process.pid,version:sy,startedAt:Date.now(),processStartTime:sS})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var i;let n;if("socket"===sh||"dual"===sh){let t=m.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))e4(e);ti({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await G(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){ti({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",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=U(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),b(o),F(o))throw eA();i=await sb(e)}catch(e){i={ok:!1,error:ty(e)}}finally{r-=1,o&&(a.delete(o),K(o))}e.destroyed||e.write(`${JSON.stringify(i)}
|
|
35
|
+
`),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 tI("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===sh||"dual"===sh){let e=await rB({handleRequest:sb,token:sI});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 tI("COMMAND_FAILED","Failed to bind HTTP server"))})})}i={socketPort:e,httpPort:t,token:sI,version:sy,codeSignature:sA,processStartTime:sS},a.existsSync(su)||a.mkdirSync(su,{recursive:!0}),a.writeFileSync(sp,""),n=i.socketPort&&i.httpPort?"dual":i.httpPort?"http":"socket",a.writeFileSync(sc,JSON.stringify({port:i.socketPort,httpPort:i.httpPort,transport:n,token:i.token,pid:process.pid,version:i.version,codeSignature:i.codeSignature,processStartTime:i.processStartTime,stateDir:su},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
|
|
70
36
|
`),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
|
|
71
|
-
`)}catch(t){let e=
|
|
72
|
-
`),r))try{t.close(()=>{})}catch{}
|
|
73
|
-
`),
|
|
74
|
-
`),
|
|
37
|
+
`)}catch(t){let e=tv(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
|
|
38
|
+
`),r))try{t.close(()=>{})}catch{}so(sc),sl(sf),process.exit(1);return}let n=!1,o=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},s=async()=>{if(!n){for(let e of(n=!0,await o(),sw.toArray()))sw.writeSessionLog(e);await eO(),so(sc),sl(sf),process.exit(0)}};process.on("SIGINT",()=>{s()}),process.on("SIGTERM",()=>{s()}),process.on("SIGHUP",()=>{s()}),process.on("uncaughtException",e=>{let t=e instanceof tI?e:tv(e);process.stderr.write(`Daemon error: ${t.message}
|
|
39
|
+
`),s()}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof tI?t:tv(t);process.stderr.write(`Daemon error: ${r.message}
|
|
40
|
+
`),s()})}();
|