agent-device 0.11.2 → 0.11.3

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.
@@ -11,8 +11,8 @@ ${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found n
11
11
  ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function r6(e){await new Promise(t=>setTimeout(t,e))}function r9(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let a=r[1]?.toLowerCase(),i=r[2]??"";return"http"!==a&&"https"!==a&&"ws"!==a&&"wss"!==a&&"ftp"!==a&&"ftps"!==a||i.startsWith("//")}function r7(e,t){let r,a=e?.trim();return a?a:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}let ae=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function at(e){return`${e.stdout}
12
12
  ${e.stderr}`}function ar(e,t){return["-s",e,...t]}function aa(e){return e.startsWith("emulator-")}function ai(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function an(e,t=eA){return O("adb",ar(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function ao(e,t){let r=t.replace(/_/g," ").trim();if(!aa(e))return r||e;let a=await al(e);return a?a.replace(/_/g," "):r||e}async function as(e,t,r){try{return await r("adb",ar(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=P(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function al(e,t=O){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await as(e,["shell","getprop",r],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let r=await as(e,["emu","avd","name"],t);if(!r)return;let a=function(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}(r.stdout);if(0===r.exitCode&&a)return a}async function ad(e,t){let r=at(await O("adb",ar(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eA})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function au(e){return(await Promise.all(ae.map(async t=>await ad(e,t)))).some(e=>!0===e)}async function ac(e){var t;let r;return"tv"===((r=at(await O("adb",ar(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eA})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await au(e)?"tv":(t=at(await O("adb",ar(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eA})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function af(e={}){if(await r3(),!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??ez(void 0),r=(await ap()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,i]=await Promise.all([ao(e,t),ag(e),ac(e)]);return{platform:"android",id:e,name:r,kind:aa(e)?"emulator":"device",target:i,booted:a}}))}async function ap(){return(await O("adb",["devices","-l"],{timeoutMs:eA})).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 am(){let e=await O("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eA});if(0!==e.exitCode)throw new $("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function ah(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await aw(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await new Promise(e=>setTimeout(e,1e3))}throw new $("COMMAND_FAILED","Android emulator did not appear in time",{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:"Check emulator logs and verify the AVD can start from command line."})}async function aw(e,t){let r=ai(e);for(let e of(await ap()).filter(e=>(!t||e.serial===t)&&aa(e.serial)))if(ai(e.rawModel)===r||ai(await ao(e.serial,e.rawModel))===r)return e.serial}async function ag(e){try{let t=await an(e);return"1"===t.stdout.trim()}catch{return!1}}async function av(e){var t,r;let a;await r3();let i=e.avdName.trim();if(!i)throw new $("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH");if(!await V("emulator"))throw new $("TOOL_MISSING","emulator not found in PATH");let o=await am(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let a=ai(t);return e.find(e=>ai(e)===a)}(o,i);if(!s)throw new $("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:i,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),d=(t=await af(),r=e.serial,a=ai(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&ai(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),x("emulator",t)}let u=d??await ah({avdName:s,serial:e.serial,timeoutMs:n}),c=Math.max(1e3,n-(Date.now()-l));await ay(u.id,c);let f=(await af()).find(e=>e.id===u.id);return f?{...f,name:s,booted:!0}:{...u,name:s,booted:!0}}async function ay(e,t=6e4){let r,a=eb.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await eS(async({deadline:i})=>{if(i?.isExpired())throw n=!0,new $("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),message:"timeout"});let o=Math.max(1e3,i?.remainingMs()??t),s=await an(e,Math.min(o,eA));if(r=s,"1"!==s.stdout.trim())throw new $("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:i,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=eU({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>eU({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=P(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eU({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===i.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),reason:d,hint:eV(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new $("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new $("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new $("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new $(i.code,i.message,{...u,...i.details??{}},i.cause)}}let aI=/\.(?:apk|aab)$/i,aA=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function ab(e){var t,r;let a=e.trim();return 0===a.length?"other":aI.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!aA.test(t))?"binary":"package":(r=a,aA.test(r))?"package":"other"}function aS(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let a_=[".zip",".tar",".tar.gz",".tgz"],aN=eF(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),aD=["1","true","yes","on"];async function ax(e){let t=[];try{let r=await aM(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await aC(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:a.archivePath,installablePath:a.installablePath,cleanup:async()=>{await a$(t)}}}catch(e){throw await a$(t),e}}async function aM(e,t){if("path"===e.kind)return{localPath:R(e.path),cleanup:async()=>{}};let r=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-source-"));try{return{localPath:await aE(r,e.url,e.headers,t),cleanup:async()=>{await d.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(r,{recursive:!0,force:!0}),e}}async function aE(e,t,r,a){let i;try{i=new URL(t)}catch{throw new $("INVALID_ARGS",`Invalid source URL: ${t}`)}await ak(i);let n=a?.signal;if(n?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,s=()=>{o.abort(n?.reason)};n?.addEventListener("abort",s,{once:!0});let l=a?.downloadTimeoutMs??aN,u=setTimeout(()=>{o.abort(Error("download timeout"))},l);try{let t=await fetch(i,{headers:r,redirect:"follow",signal:o.signal});if(!t.ok)throw new $("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:i.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),i=a?.[1]?.trim();if(i)return c.basename(i);let n=c.basename(t.pathname);return n||"downloaded-artifact.bin"}(t,i),n=c.join(e,a),s=t.body;if(!s)throw new $("COMMAND_FAILED","Download response body was empty",{url:i.toString()});let l=await d.open(n,"w");try{for await(let e of s)await l.write(e)}finally{await l.close()}return n}catch(e){if(n?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new $("COMMAND_FAILED",`App source download timed out after ${l}ms`,{timeoutMs:l,url:i.toString()},e);throw e}finally{n?.removeEventListener("abort",s),clearTimeout(u)}}async function ak(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new $("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!aD.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||aL(t))throw new $("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await v.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>aL(e.address)))throw new $("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function aO(e){var t,r,a,i;let n=e instanceof URL?e:new URL(e),o=n.hostname.toLowerCase();if(!o)return!1;let s=n.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,i=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(i))}function aL(e){let t,r=f.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,a]=t;return 10===r||127===r||169===r&&254===a||172===r&&!!(a>=16)&&!!(a<=31)||192===r&&168===a}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function aC(e,t){let r=await d.stat(e).catch(()=>null);if(!r)throw new $("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&aT(e)){if(!t.allowArchiveExtraction)throw new $("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await aR(e);return t.registerCleanup(r.cleanup),await aC(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await aP(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new $("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await aP(e,(e,t)=>t.isFile()&&aT(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new $("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await aR(a[0]);return t.registerCleanup(e.cleanup),await aC(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new $("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new $("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function aP(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let i=await d.readdir(e.path,{withFileTypes:!0});for(let n of(i.sort((e,t)=>e.name.localeCompare(t.name)),i)){let i=c.join(e.path,n.name);if(t(i,n)){r.push(i);continue}n.isDirectory()&&e.depth<5&&a.push({path:i,depth:e.depth+1})}}return r}async function aR(e){let t=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await O("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await O("tar",["-xzf",e,"-C",t]):await O("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await d.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(t,{recursive:!0,force:!0}),e}}function aT(e){let t=e.toLowerCase();return a_.some(e=>t.endsWith(e))}async function a$(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let aF=new I("utf-16le");async function aU(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await aV(e,r);if(!a)continue;let i=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),i=e.readUInt16LE(r+2),n=e.readUInt32LE(r+4);if(n<=0||r+n>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),i=(256&r)!=0,n=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);n.push(i?function(e,t){let[,r]=aG(e,t),[a,i]=aG(e,t+r),n=t+r+i;return e.subarray(n,n+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),i=t+a;return aF.decode(e.subarray(i,i+2*r))}(e,o))}return n}(e.subarray(r,r+n));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let i=e.readUInt16LE(t+24),n=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let r=s+t*n;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let i=e.readUInt32LE(r+8);if(0xffffffff!==i)return a[i];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,i,t);if(a)return a}r+=n}}(t);if(i)return i}return await aj(e)}async function aV(e,t){try{let r=await O("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 aG(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function aj(e){let t=await aB();if(!t)return;let r=await O(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function aB(){if(void 0!==e)return e??void 0;try{for(let t of r1()){let r=c.join(t,"build-tools");try{for(let t of(await y.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=c.join(r,t,"aapt");try{return await y.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function aq(e,t){let r="url"===e.kind&&aO(e.url),a=await ax({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=c.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await aH(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function aH(e){let t=c.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await aU(e)}}let aW={settings:{type:"intent",value:"android.settings.SETTINGS"}},az="android.intent.category.LAUNCHER",aJ="android.intent.category.LEANBACK_LAUNCHER",aK="android.intent.category.DEFAULT";async function aX(e,t){let r=t.trim();if("package"===ab(r))return{type:"package",value:r};let a=aW[r.toLowerCase()];if(a)return a;let i=(await O("adb",r4(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new $("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:i});throw new $("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function aY(e,t="all"){let r=await aZ(e);return("user-installed"===t?(await a0(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:a1(e)}))}async function aZ(e){let t=new Set;for(let r of aQ(e,{includeFallbackWhenUnknown:!0})){let a=await O("adb",r4(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],i=a.includes("/")?a.split("/")[0]:a;i&&t.add(i)}}return t}function aQ(e,t={}){return"tv"===e.target?[aJ]:"mobile"===e.target?[az]:t.includeFallbackWhenUnknown?[az,aJ]:[az]}async function a0(e){return(await O("adb",r4(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function a1(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let i=r[e];if(!t.has(i)){a=i;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function a2(e){let t=await a3(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await a3(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function a3(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 O("adb",r4(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function a4(e,t,r){var a,i;let n;e.booted||await ay(e.id);let o=t.trim();if(r9(o)){if(r)throw new $("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await aX(e,t),l=aQ(e)[0]??az;if("intent"===s.type){if(r)throw new $("INVALID_ARGS","Activity override requires a package name, not an intent");await O("adb",r4(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-n",t]));return}let d=await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,i=d.stderr,n=`${a}
13
13
  ${i}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)))return;let u=await a8(e,s.value);if(!u)throw new $("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr});await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-n",u]))}async function a8(e,t){for(let r of Array.from(new Set(aQ(e,{includeFallbackWhenUnknown:!0})))){let a=await O("adb",r4(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=function(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}(a.stdout);if(i)return i}return null}async function a5(e){e.booted||await ay(e.id)}async function a6(e,t){if("settings"===t.trim().toLowerCase())return void await O("adb",r4(e,["shell","am","force-stop","com.android.settings"]));let r=await aX(e,t);if("intent"===r.type)throw new $("INVALID_ARGS","Close requires a package name, not an intent");await O("adb",r4(e,["shell","am","force-stop",r.value]))}async function a9(e,t){let r=await aX(e,t);if("intent"===r.type)throw new $("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await O("adb",r4(e,["uninstall",r.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
14
- ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new $("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let a7=null;async function ie(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(a7?.key===e)return a7.invocation;if(await V("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return a7={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new $("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await d.access(t)}catch{throw new $("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return a7={key:e,invocation:r},r}async function it(e){let t=await ie();await O(t.cmd,[...t.prefixArgs,...e])}async function ir(e,t){let r,a=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-aab-")),i=c.join(a,"bundle.apks"),n=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await it(["build-apks","--bundle",t,"--output",i,"--mode",n]),await it(["install-apks","--apks",i,"--device-id",e.id])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function ia(e,t){".aab"===c.extname(t).toLowerCase()?await ir(e,t):await O("adb",r4(e,["install","-r",t]))}async function ii(e){return new Set((await O("adb",r4(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function io(e,t){let r=Array.from(await ii(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function is(e,t){e.booted||await ay(e.id),await ia(e,t)}async function il(e,t,r){let a=r?void 0:await ii(e);return await is(e,t),r??(a?await io(e,a):void 0)}async function id(e,t){e.booted||await ay(e.id);let r=await aq({kind:"path",path:t});try{let t=await il(e,r.installablePath,r.packageName),a=t?a1(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function iu(e,t,r){e.booted||await ay(e.id);let{package:a}=await a9(e,t),i=await aq({kind:"path",path:r},{resolveIdentity:!1});try{return await is(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function ic(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,a=function(e){if(void 0===e)return .6;if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),i=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*a),n=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(i,Math.max(1,r-2*n))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(r,a,i,n)=>({direction:t,x1:r,y1:a,x2:i,y2:n,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return u(l,d-s,l,d+s);case"down":return u(l,d+s,l,d-s);case"left":return u(l-s,d,l+s,d);case"right":return u(l+s,d,l-s,d)}}function ip(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,i=a.exec(e);for(;i;){let t=ih(i[0]),n=(iw(t,"text")??"").toLowerCase(),o=(iw(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=ig(iw(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}i=a.exec(e)}return null}function im(e){let t=ih(e),r=e=>{let r=iw(t,e);if(null!==r)return"true"===r};return{text:iw(t,"text"),desc:iw(t,"content-desc"),resourceId:iw(t,"resource-id"),className:iw(t,"class"),bounds:iw(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function ih(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,n=r;for(;n<a;){for(;n<a;){let t=e[n];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;n+=1}if(n>=a)break;let r=e[n];if("/"===r||">"===r)break;i.lastIndex=n;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),n=i.lastIndex}return t}function iw(e,t){return e.get(t)??null}function ig(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),a=Number(t[2]);return{x:r,y:a,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-a)}}function iv(e){return e?e.toLowerCase():""}function iy(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function iI(e,t={}){return function(e,t){let r=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=a.exec(e);continue}let n=im(t),o=ig(n.bounds),s=r[r.length-1],l={type:n.className,label:n.text||n.desc,value:n.text,identifier:n.resourceId,rect:o,enabled:n.enabled,hittable:n.clickable??n.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),i=a.exec(e)}return t}(e),a=[],i=!1,n=t.depth??1/0,o=t.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children];for(;a.length>0;){let e=a.shift(),t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",n=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||n.includes(r))return e;a.push(...e.children)}return null}(r,t.scope):null,s=o?[o]:r.children,l=new Map,d=e=>{let t=l.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||d(t))return l.set(e,!0),!0;return l.set(e,!1),!1},u=(e,r,o,s=!1,l=!1)=>{var c,f,p,m,h,w;let g,v,y,I,A,b,S,_;if(a.length>=800){i=!0;return}if(r>n)return;let N=!!t.raw||(c=e,f=t,p=s,m=d(e),h=l,v=iv(c.type),y=!!(c.label&&c.label.trim().length>0),I=!!(c.identifier&&c.identifier.trim().length>0),A=y&&!iy(c.label??""),b=I&&!iy(c.identifier??""),S=(g=(w=v).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,_="imageview"===v||"imagebutton"===v,f.interactiveOnly?!!c.hittable||!!(A||b)&&!_&&(!S||!!h)&&(p||m||h):f.compact?A||b||!!c.hittable:!S&&!_||!!c.hittable||!!A||!!b&&!!m||m),D=o;N&&(D=a.length,a.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:r,parentIndex:o}));let x=s||!!e.hittable,M=l||function(e){if(!e)return!1;let t=iv(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(u(t,r+1,D,x,M),i)return};for(let e of s)if(u(e,0,void 0,!1,!1),i)break;return i?{nodes:a,truncated:i}:{nodes:a}}(await iA(e),t)}async function iA(e){return e_(()=>ib(e),{shouldRetry:i_})}async function ib(e){var t,r,a;let i,n,o=await O("adb",r4(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=iS(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await O("adb",r4(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,a=l.stderr,i=`${r}
15
- ${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),u=await O("adb",r4(e,["shell","cat",d])),c=iS(u.stdout,u.stderr);if(!c)throw new $("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return c}function iS(e,t){let r=`${e}
14
+ ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new $("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let a7=null;async function ie(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(a7?.key===e)return a7.invocation;if(await V("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return a7={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new $("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await d.access(t)}catch{throw new $("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return a7={key:e,invocation:r},r}async function it(e){let t=await ie();await O(t.cmd,[...t.prefixArgs,...e])}async function ir(e,t){let r,a=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-aab-")),i=c.join(a,"bundle.apks"),n=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await it(["build-apks","--bundle",t,"--output",i,"--mode",n]),await it(["install-apks","--apks",i,"--device-id",e.id])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function ia(e,t){".aab"===c.extname(t).toLowerCase()?await ir(e,t):await O("adb",r4(e,["install","-r",t]))}async function ii(e){return new Set((await O("adb",r4(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function io(e,t){let r=Array.from(await ii(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function is(e,t){e.booted||await ay(e.id),await ia(e,t)}async function il(e,t,r){let a=r?void 0:await ii(e);return await is(e,t),r??(a?await io(e,a):void 0)}async function id(e,t){e.booted||await ay(e.id);let r=await aq({kind:"path",path:t});try{let t=await il(e,r.installablePath,r.packageName),a=t?a1(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function iu(e,t,r){e.booted||await ay(e.id);let{package:a}=await a9(e,t),i=await aq({kind:"path",path:r},{resolveIdentity:!1});try{return await is(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function ic(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,a=function(e){if(void 0===e)return .6;if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),i=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*a),n=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(i,Math.max(1,r-2*n))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(r,a,i,n)=>({direction:t,x1:r,y1:a,x2:i,y2:n,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return u(l,d-s,l,d+s);case"down":return u(l,d+s,l,d-s);case"left":return u(l-s,d,l+s,d);case"right":return u(l+s,d,l-s,d)}}function ip(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,i=a.exec(e);for(;i;){let t=ih(i[0]),n=(iw(t,"text")??"").toLowerCase(),o=(iw(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=ig(iw(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}i=a.exec(e)}return null}function im(e){let t=ih(e),r=e=>{let r=iw(t,e);if(null!==r)return"true"===r};return{text:iw(t,"text"),desc:iw(t,"content-desc"),resourceId:iw(t,"resource-id"),className:iw(t,"class"),bounds:iw(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function ih(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,n=r;for(;n<a;){for(;n<a;){let t=e[n];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;n+=1}if(n>=a)break;let r=e[n];if("/"===r||">"===r)break;i.lastIndex=n;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),n=i.lastIndex}return t}function iw(e,t){return e.get(t)??null}function ig(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),a=Number(t[2]);return{x:r,y:a,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-a)}}function iv(e){return e?e.toLowerCase():""}function iy(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function iI(e,t={}){return function(e,t){let r=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=a.exec(e);continue}let n=im(t),o=ig(n.bounds),s=r[r.length-1],l={type:n.className,label:n.text||n.desc,value:n.text,identifier:n.resourceId,rect:o,enabled:n.enabled,hittable:n.clickable??n.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),i=a.exec(e)}return t}(e),a=[],i=!1,n=t.depth??1/0,o=t.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children];for(;a.length>0;){let e=a.shift(),t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",n=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||n.includes(r))return e;a.push(...e.children)}return null}(r,t.scope):null,s=o?[o]:r.children,l=new Map,d=e=>{let t=l.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||d(t))return l.set(e,!0),!0;return l.set(e,!1),!1},u=(e,r,o,s=!1,l=!1)=>{var c,f,p,m,h,w;let g,v,y,I,A,b,S,_;if(a.length>=800){i=!0;return}if(r>n)return;let N=!!t.raw||(c=e,f=t,p=s,m=d(e),h=l,v=iv(c.type),y=!!(c.label&&c.label.trim().length>0),I=!!(c.identifier&&c.identifier.trim().length>0),A=y&&!iy(c.label??""),b=I&&!iy(c.identifier??""),S=(g=(w=v).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,_="imageview"===v||"imagebutton"===v,f.interactiveOnly?!!c.hittable||!!(A||b)&&!_&&(!S||!!h)&&(p||m||h):f.compact?A||b||!!c.hittable:!S&&!_||!!c.hittable||!!A||!!b&&!!m||m),D=o;N&&(D=a.length,a.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:r,parentIndex:o}));let x=s||!!e.hittable,M=l||function(e){if(!e)return!1;let t=iv(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(u(t,r+1,D,x,M),i)return};for(let e of s)if(u(e,0,void 0,!1,!1),i)break;return i?{nodes:a,truncated:i}:{nodes:a}}(await iA(e),t)}async function iA(e){return e_(()=>ib(e),{shouldRetry:i_})}async function ib(e){var t,r,a;let i,n,o=await O("adb",r4(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0}),s=iS(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",d=await O("adb",r4(e,["shell","uiautomator","dump",l]),{allowFailure:!0}),u=(t=l,r=d.stdout,a=d.stderr,i=`${r}
15
+ ${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),c=await O("adb",r4(e,["shell","cat",u])),f=iS(c.stdout,c.stderr);if(!f)throw new $("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return f}function iS(e,t){let r=`${e}
16
16
  ${t}`,a=r.indexOf("<?xml"),i=a>=0?a:r.indexOf("<hierarchy");if(i<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<i)return null;let o=r.slice(i,n+12).trim();return o.length>0?o:null}function i_(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.details?.stderr??""}`.toLowerCase();return!!(t.includes("device offline")||t.includes("device not found")||t.includes("transport error")||t.includes("connection reset")||t.includes("broken pipe")||t.includes("timed out")||t.includes("no such file or directory"))}async function iN(e,t,r){await O("adb",r4(e,["shell","input","tap",String(t),String(r)]))}async function iD(e,t,r,a,i,n=250){await O("adb",r4(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function ix(e){await O("adb",r4(e,["shell","input","keyevent","4"]))}async function iM(e){await O("adb",r4(e,["shell","input","keyevent","3"]))}async function iE(e){await O("adb",r4(e,["shell","input","keyevent","187"]))}async function ik(e,t,r,a=800){await O("adb",r4(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function iO(e,t,r=0){r>0&&Array.from(t).length>1?await iF(e,t,1,r):await iL(e,t)}async function iL(e,t){let r=iU(t);if(!r||"ok"!==await iV(e,t))try{let r=t.replace(/ /g,"%s");await O("adb",r4(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return!!(t.includes("exception occurred while executing 'text'")||t.includes("nullpointerexception")&&t.includes("inputshellcommand.sendtext"))}(e))throw new $("COMMAND_FAILED","Non-ASCII text input is not supported on this Android shell. Install an ADB keyboard IME or use ASCII input.",{textPreview:t.slice(0,32)},e instanceof Error?e:void 0);throw e}}async function iC(e,t,r){await iN(e,t,r)}async function iP(e,t,r,a,i=0){let n=Array.from(a).length,o=iU(a),s=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];!o&&i<=0&&s.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),(!o||i>0)&&s.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96});let l=null;for(let o of s){var d,u;await iC(e,t,r);let s=(d=n+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await iG(e,s),"input_text"===o.strategy)await iO(e,a,i);else if("clipboard_paste"===o.strategy){if("ok"!==await iV(e,a))continue}else await iF(e,a,1,i>0?i:15);if((l=await ij(e,t,r))===a)return}throw new $("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function iR(e,t,r){let a=await i$(e),i=ic({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await O("adb",r4(e,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"])),i}async function iT(e,t,r){let a=r?.maxScrolls??8,i="";try{i=await iA(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new $("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(ip(i,t))return{attempts:0};for(let r=1;r<=a;r+=1){await iR(e,"down",{amount:.5});let a="";try{a=await iA(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new $("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(ip(a,t))return{attempts:r};if(a===i)throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:r,stalled:!0});i=a}throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:a})}async function i$(e){let t=(await O("adb",r4(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new $("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iF(e,t,r,a){let i=Math.max(1,Math.floor(r)),n=Array.from(t);for(let t=0;t<n.length;t+=i){let r=n.slice(t,t+i).join("");await iL(e,r),a>0&&t+i<n.length&&await r6(a)}}function iU(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 iV(e,t){let r=await O("adb",r4(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":r5(r.stdout,r.stderr)?"unsupported":0===(await O("adb",r4(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await O("adb",r4(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function iG(e,t){let r=Math.max(0,t);await O("adb",r4(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let a=Math.min(24,r-t);await O("adb",r4(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function ij(e,t,r){let a,i=await iA(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=im(a[0]),i=ig(e.bounds);if(!i)continue;let n=e.className??"",d=(e.text??"").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"),u=e.focused??!1;if(!d)continue;let c=Math.max(1,i.width*i.height),f=t>=i.x&&t<=i.x+i.width&&r>=i.y&&r<=i.y+i.height;if(u&&iB(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(f&&iB(n)){(!s||c<=s.area)&&(s={text:d,area:c});continue}f&&(!l||c<=l.area)&&(l={text:d,area:c})}return o?.text??s?.text??l?.text??null}function iB(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iq(e){let t=await O("adb",r4(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),i=a.length>0?a[a.length-1]?.[1]:void 0,n=i?`0x${i.toLowerCase()}`:void 0;return{visible:r,inputType:n,type:n?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(n):void 0}}(t.stdout)}async function iH(e){let t=await iq(e),r=t,a=0;for(;r.visible&&a<2;)await O("adb",r4(e,["shell","input","keyevent","111"])),a+=1,await r6(120),r=await iq(e);if(t.visible&&r.visible)throw new $("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:a,inputType:r.inputType,type:r.type});return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function iW(e){let t,r;return(r=(t=(await iJ(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 iz(e,t){await iJ(e,["shell","cmd","clipboard","set","text",t],"write")}async function iJ(e,t,r){let a=await O("adb",r4(e,t),{allowFailure:!0});if(r5(a.stdout,a.stderr))throw new $("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new $("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let iK=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iX(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new $("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iY(e){let t=e?.trim().toLowerCase();if("camera"===t||"microphone"===t||"photos"===t||"contacts"===t||"contacts-limited"===t||"notifications"===t||"calendar"===t||"location"===t||"location-always"===t||"media-library"===t||"motion"===t||"reminders"===t||"siri"===t)return t;throw new $("INVALID_ARGS",`permission setting requires a target: ${iK.join("|")}`)}function iZ(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new $("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function iQ(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=i1(r);await O("adb",r4(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=i1(r);await O("adb",r4(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await O("adb",r4(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=i1(r);await O("adb",r4(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await i2(e,r);await O("adb",r4(e,["shell","cmd","uimode","night","dark"===t?"yes":"no"]));return}case"fingerprint":{let t=function(e){let t=e.trim().toLowerCase();if("match"===t)return"match";if("nonmatch"===t)return"nonmatch";throw new $("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await i0(e,t);return}case"permission":{if(!a)throw new $("INVALID_ARGS","permission setting requires an active app in session");let t=iX(r),n=function(e,t){let r=iY(e);if(t?.trim())throw new $("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===r)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===r)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===r)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===r)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new $("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===n.kind)return void await i4(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await i3(e,a,o);await O("adb",r4(e,["shell","pm",o,a,n.value]));return}default:throw new $("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function i0(e,t){var r;let a,i,n=(r=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of n){let r=await O("adb",r4(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
17
17
  ${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new $("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 $("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function i1(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 $("INVALID_ARGS",`Invalid setting state: ${e}`)}async function i2(e,t){let r=iZ(t);if("toggle"!==r)return r;let a=await O("adb",r4(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new $("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
18
18
  ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new $("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"auto"===i?"dark":"dark"===i?"light":"dark"}async function i3(e,t,r){let a=await i8(e),i=[];for(let n of null!==a&&a>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let a=await O("adb",r4(e,["shell","pm",r,t,n]),{allowFailure:!0});if(0===a.exitCode)return;i.push({permission:n,stderr:a.stderr,exitCode:a.exitCode})}throw new $("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function i4(e,t,r,a){"grant"===r?await O("adb",r4(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await O("adb",r4(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await O("adb",r4(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await O("adb",r4(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await O("adb",r4(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function i8(e){let t=await O("adb",r4(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 i5(e,t,r){let a="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,i=["shell","am","broadcast","-a",a,"-p",t],n="string"==typeof r.receiver?r.receiver.trim():"";n&&i.push("-n",n);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new $("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 $("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await O("adb",r4(e,i)),{action:a,extrasCount:s}}let i6=Buffer.from([137,80,78,71,13,10,26,10]);async function i9(e,t){await i7(e);try{await r6(1e3),await nt(e,t)}finally{await ne(e).catch(()=>{})}}async function i7(e){let t=t=>O("adb",r4(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 ne(e){await O("adb",r4(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function nt(e,t){let r=await O("adb",r4(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new $("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(i6);if(a<0)throw new $("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let i=function(e,t){let r=t+i6.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),a=r+4,i=e.toString("ascii",a,a+4),n=r+12+t;if(n>e.length)break;if("IEND"===i)return n;r=n}return null}(r.stdoutBuffer,a);if(!i)throw new $("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await d.writeFile(t,r.stdoutBuffer.subarray(a,i))}let nr=eF(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,eI,5e3),na=eF(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,ey,1e3),ni=eF(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),nn=eF(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),no=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),ns=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),nl=eF(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function nd(e,t){let r=["devicectl",...e],a=await O("xcrun",r,{allowFailure:!0,timeoutMs:nn});if(0===a.exitCode)return;let i=String(a.stdout??""),n=String(a.stderr??"");throw new $("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:t.deviceId,hint:nf(i,n)??nc})}async function nu(e,t){let r=c.join(u.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),a=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],i=await O("xcrun",a,{allowFailure:!0,timeoutMs:nn});try{var n,o;if(0!==i.exitCode){let t=String(i.stdout??""),r=String(i.stderr??"");throw new $("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:i.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:nf(t,r)??nc})}let s=await d.readFile(r,"utf8");return n=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let a="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:a})}return r}(JSON.parse(s)),o=t,"user-installed"===o?n.filter(e=>!e.bundleId.startsWith("com.apple.")):n}catch(t){if(t instanceof $)throw t;throw new $("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await d.unlink(r).catch(()=>{})}}let nc="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function nf(e,t){let r=`${e}
@@ -29,7 +29,7 @@ ${a.stderr}`.toLowerCase()))throw new $("COMMAND_FAILED",`simctl uninstall faile
29
29
  `,"utf8"),await oI(e,["push",e.id,t,i])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function oC(e,t,r,a,i){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await n3(r);if("permission"===e){let e=iX(r);if("deny"===e)throw new $("INVALID_ARGS",U("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new $("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(i?.permissionTarget);return await nG(e,t)}throw new $("INVALID_ARGS",U(t))}nh(e,"settings"),await ng(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=oT(r);await oI(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(oT(r)?await oI(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await oI(e,["status_bar",e.id,"clear"]));case"location":{let t=oT(r);if(!a)throw new $("INVALID_ARGS","location setting requires an active app in session");await oI(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=oF[n],a=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new $("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,n);await oj(e,a,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await o$(e,r);await oI(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new $("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=iX(r))?"revoke":o,n=function(e,t){let r=iY(e);if("photos"!==r&&t?.trim())throw new $("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 $("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new $("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(i?.permissionTarget,i?.permissionMode);await oU(e,t,n,a);return}default:throw new $("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function oP(e,t="all"){return"macos"===e.platform?await n4(t):"simulator"===e.kind?nD(await oR(e),t):await nu(e,t)}async function oR(e){let t=(await oI(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 O("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 oT(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 $("INVALID_ARGS",`Invalid setting state: ${e}`)}async function o$(e,t){let r=iZ(t);if("toggle"!==r)return r;let a=await oI(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new $("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
30
30
  ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new $("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let oF={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function oU(e,t,r,a){let i=await oG(e);if(!i.has(r))throw new $("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(i).sort().join(", ")}`});let n=["privacy",e.id,t,r,a],o="notifications"===r;if(!("reset"===t&&o))try{await oI(e,n);return}catch(t){if(!(o&&oV(t)))throw t;throw new $("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:a,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await oI(e,n);return}catch(e){if(!oV(e))throw e}try{await oI(e,["privacy",e.id,"reset","all",a])}catch(t){throw new $("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:a,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function oV(e){if(!(e instanceof $)||"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 oG(e){let r=eH(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(oy&&t===a)return oy;let i=await oI(e,["privacy","help"],{allowFailure:!0}),n=function(e){let t=new Set,r=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let i=/^([a-z-]+)\s+-\s+/.exec(e);i&&t.add(i[1])}return t}(`${i.stdout}
31
31
  ${i.stderr}`);if(0===n.size)throw new $("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return oy=n,t=a,n}async function oj(e,t,r){let a=function(e,t,r){let a=r.length>0?r:["face"];switch(t){case"match":return a.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return a.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),i=[];for(let t of a){let r=eK(e,t),a=await O("xcrun",r,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:r,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let n=i.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(i.length>0&&i.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
32
- ${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new $("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new $("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function oB(e,t){await ng(e);let r=0,a=eb.fromTimeoutMs(ni);try{await eS(async({deadline:r})=>{var a;if(r?.isExpired())throw new $("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:ni});let i=(a=["launch",e.id,t],eK(e,a)),n=await O("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new $("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!np(e)&&(r+=1)<3},{deadline:a})}catch(r){if(np(r)){var i;let a=(i=await nm(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function oq(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await nd(a,{action:"launch iOS app",deviceId:e.id})}async function oH(e,t,r,a){let i=a?.maxScrolls??48,n=await e({command:"findText",text:r});if(n?.found)return{attempts:0};let o=oW(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let a=1;a<=i;a+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let i=await e({command:"findText",text:r});if(i?.found)return{attempts:a};let n=oW(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(n===o)throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a,stalled:!0});o=n}throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:i})}function oW(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function oz(e,t,r,a,i,n,o){if("tv"===t.target)return oX(await e(t,{command:"swipe",direction:function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left";default:return e}}(i),appBundleId:r.appBundleId},a),n);let s=o??await oJ(e,t,r,a),l=ic({direction:i,amount:n?.amount,pixels:n?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return oX(await e(t,{command:"drag",x:s.originX+l.x1,y:s.originY+l.y1,x2:s.originX+l.x2,y2:s.originY+l.y2,appBundleId:r.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function oJ(e,t,r,a){let i=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},a),n=oK(i.x),o=oK(i.y),s=oK(i.referenceWidth),l=oK(i.referenceHeight);if(void 0===n||void 0===o||void 0===s||void 0===l)throw new $("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:n,originY:o,referenceWidth:s,referenceHeight:l}}function oK(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function oX(e,t){var r;let{x1:a,y1:i,x2:n,y2:o}={x1:oK((r=e).x),y1:oK(r.y),x2:oK(r.x2),y2:oK(r.y2)},s=oK(e.referenceWidth),l=oK(e.referenceHeight),d=void 0!==a&&void 0!==n?Math.round(Math.abs(n-a)):void 0,u=void 0!==i&&void 0!==o?Math.round(Math.abs(o-i)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:d&&d>0?d:u&&u>0?u:void 0;return{...void 0!==a?{x1:a}:{},...void 0!==i?{y1:i}:{},...void 0!==n?{x2:n}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}function oY(e){return e?.clickButton??"primary"}function oZ(e){return"primary"===e.button?null:"click"!==e.commandLabel?new $("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new $("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new $("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new $("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let oQ=/^[A-Za-z0-9_.:-]{1,64}$/,o0=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function o1(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new $("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function o2(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await o3(t)}async function o3(e){await new Promise(t=>setTimeout(t,e))}function o4(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new $("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!s.statSync(n).isFile())throw new $("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof $)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new $("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new $("COMMAND_FAILED",`Unable to read ${a} file: ${n}`,{cause:String(t)})}if((r=i.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:i};throw new $("INVALID_ARGS",`${a} file not found: ${n}`)}async function o8(e){let t=o4(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await o5(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new $("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function o5(e){try{return await d.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new $("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new $("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new $("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new $("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let o6=eF(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),o9=/^(iphone|ipad|ipod|appletv)/i,o7=/^appletv/i,se=["apple tv","appletv","tvos"];function st(e){return(e??"").trim().toLowerCase()}function sr(e){return st(e.hardwareProperties?.platform)}function sa(e){return e.includes("tvos")}function si(e){return sa(st(e))?"tv":"mobile"}function sn(e){let t=st(e);return t.includes("ios")||t.includes("tvos")}function so(e){let t=st(e);return se.some(e=>t.includes(e))}function ss(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function sl(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function sd(e={}){let t,r,a=eH(e.simulatorSetPath),i=e.target;try{t=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!sn(e))continue;let r=si(e);if(!i||r===i)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...a?{simulatorSetPath:a}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function su(e={}){if("darwin"!==process.platform)throw new $("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await V("xcrun"))throw new $("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eH(e.simulatorSetPath),a=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(sn(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:si(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new $("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(t.push({platform:"macos",id:"host-macos-local",name:u.hostname(),kind:"device",target:"desktop",booted:!0}),r)return t;let i=null;try{i=c.join(u.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await O("xcrun",["devicectl","list","devices","--json-output",i],{allowFailure:!0,timeoutMs:o6});if(0!==e.exitCode)return t;let r=await d.readFile(i,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(function(e){var t;let r=sr(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=sl(e),!!o9.test(t.trim())||ss(e).some(so))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",a=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:a,kind:"device",target:function(e){var t;return sa(sr(e))?"tv":(t=sl(e),o7.test(t.trim())||ss(e).some(so))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{i&&await d.rm(i,{force:!0}).catch(()=>{})}return t}async function sc(e,t,r){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await tu(e,t,r)}catch(e){if(i||!(e instanceof $)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!i&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!a||"device"===a.kind)){let e=await sd({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new $("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function sf(e){let t=e.platform,r=td({simulatorSetPath:eH(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=ez(e.androidDeviceAllowlist);return await X("resolve_target_device",async()=>{let i={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(i.target&&!i.platform)throw new $("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await r8();let e=await af({serialAllowlist:a});return await tu(e,i)}if(i.platform){let e=await su({simulatorSetPath:r});return await sc(e,i,{simulatorSetPath:r})}let n=[];try{n.push(...await af({serialAllowlist:a}))}catch{}try{n.push(...await su({simulatorSetPath:r}))}catch{}return await tu(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function sp(e,t,r,a,i){let n={requestId:i?.requestId,appBundleId:i?.appBundleId,verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>a4(e,t,r?.activity),openDevice:()=>a5(e),close:t=>a6(e,t),tap:(t,r)=>iN(e,t,r),doubleTap:async(t,r)=>{await iN(e,t,r),await iN(e,t,r)},swipe:(t,r,a,i,n)=>iD(e,t,r,a,i,n),longPress:(t,r,a)=>ik(e,t,r,a),focus:(t,r)=>iC(e,t,r),type:(t,r)=>iO(e,t,r),fill:(t,r,a,i)=>iP(e,t,r,a,i),scroll:(t,r)=>iR(e,t,r),scrollIntoView:(t,r)=>iT(e,t,r),screenshot:t=>i9(e,t),back:t=>ix(e),home:()=>iM(e),appSwitcher:()=>iE(e),readClipboard:()=>iW(e),writeClipboard:t=>iz(e,t),setSetting:(t,r,a,i)=>iQ(e,t,r,a,i)};case"ios":case"macos":{let r,a,{overrides:i,runnerOpts:n}=(r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},a=()=>{if(eP(t.requestId))throw eT()},{runnerOpts:r,overrides:{tap:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),doubleTap:async(a,i)=>await tz(e,{command:"tapSeries",x:a,y:i,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(a,i,n,o,s)=>await tz(e,{command:"drag",x:a,y:i,x2:n,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(a,i,n)=>await tz(e,{command:"longPress",x:a,y:i,durationMs:n,appBundleId:t.appBundleId},r),focus:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),type:async(a,i)=>{await tz(e,{command:"type",text:a,delayMs:i,appBundleId:t.appBundleId},r)},fill:async(a,i,n,o)=>{let s=await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r);return await tz(e,{command:"type",x:a,y:i,text:n,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},r),s},scroll:async(a,i)=>await oz(tz,e,t,r,a,i),scrollIntoView:async(i,n)=>await oH(a=>tz(e,{...a,appBundleId:t.appBundleId},r),a,i,n)}});return{open:(t,r)=>oS(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>o_(e),close:t=>oN(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await nW(t,{surface:r.surface,fullscreen:r.fullscreen}):await os(e,t,r?.appBundleId,r?.fullscreen)},back:async r=>{await tz(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},n)},home:async()=>{await tz(e,{command:"home",appBundleId:t.appBundleId},n)},appSwitcher:async()=>{await tz(e,{command:"appSwitcher",appBundleId:t.appBundleId},n)},readClipboard:()=>ok(e),writeClipboard:t=>oO(e,t),setSetting:(t,r,a,i)=>oC(e,t,r,a,i),...i}}default:throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,n);return Q({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await X("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new $("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null,...Y("Opened device")};if(void 0!==a){if("android"===e.platform)throw new $("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(r9(t))throw new $("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId,url:a}),{app:t,url:a,...Y(`Opened: ${t}`)}}return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId}),{app:t,...Y(`Opened: ${t}`)}}case"close":{let e=r[0];if(!e)return{closed:"session",...Y("Closed session")};return await o.close(e),{app:e,...Y(`Closed: ${e}`)}}case"press":{let t,[a,n]=r.map(Number);if(Number.isNaN(a)||Number.isNaN(n))throw new $("INVALID_ARGS","press requires x y");if("macos"===e.platform&&i?.surface&&"app"!==i.surface){let e=oY(i);if("primary"!==e)throw new $("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${i.surface} sessions.`);return await nH(a,n,{bundleId:i.appBundleId,surface:i.surface}),{x:a,y:n,...Y(sm({x:a,y:n}))}}let s=oY(i);if("primary"!==s){let t=oZ({commandLabel:"click",platform:e.platform,button:s,count:i?.count,intervalMs:i?.intervalMs,holdMs:i?.holdMs,jitterPx:i?.jitterPx,doubleTap:i?.doubleTap});if(t)throw t;return await tz(e,{command:"mouseClick",x:a,y:n,button:s,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{x:a,y:n,button:s,...Y(sm({x:a,y:n,button:s}))}}let l=o1(i?.count??1,"count",1,200),d=o1(i?.intervalMs??0,"interval-ms",0,1e4),u=o1(i?.holdMs??0,"hold-ms",0,1e4),c=o1(i?.jitterPx??0,"jitter-px",0,100),f=i?.doubleTap===!0;if(f&&u>0)throw new $("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&c>0)throw new $("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&l>1&&0===u&&0===c){let t=await tz(e,{command:"tapSeries",x:a,y:n,count:l,intervalMs:d,doubleTap:f,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:f,timingMode:"runner-series",...t,...Y(sm({x:a,y:n}))}}return await o2(l,d,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=o0[e%o0.length];return[r*t,a*t]}(e,c),s=a+r,l=n+i;if(f){t??=await o.doubleTap(s,l)??void 0;return}u>0?t??=await o.longPress(s,l,u)??void 0:t??=await o.tap(s,l)??void 0}),T({x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:f,...t},sm({x:a,y:n}))}case"swipe":{let t=Number(r[0]),a=Number(r[1]),n=Number(r[2]),s=Number(r[3]);if([t,a,n,s].some(Number.isNaN))throw new $("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=o1(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=o1(i?.count??1,"count",1,200),c=o1(i?.pauseMs??0,"pause-ms",0,1e4),f=i?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new $("INVALID_ARGS",`Invalid pattern: ${f}`);if(("ios"===e.platform||"macos"===e.platform)&&u>1){let r=await tz(e,{command:"dragSeries",x:t,y:a,x2:n,y2:s,durationMs:d,count:u,pauseMs:c,pattern:f,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:f,...r,...Y(sh(u,f))}}return await o2(u,c,async e=>{"ping-pong"===f&&e%2==1?await o.swipe(n,s,t,a,d):await o.swipe(t,a,n,s,d)}),T({x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:f},sh(u,f))}case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a,...Y(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t,...Y(`Focused (${e}, ${t})`)}}case"type":{let e=r.join(" ");if(!e)throw new $("INVALID_ARGS","type requires text");let t=o1(i?.delayMs??0,"delay-ms",0,1e4);return await o.type(e,t),{text:e,delayMs:t,...Y(sw("Typed",e))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new $("INVALID_ARGS","fill requires x y text");let n=o1(i?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,a,n),{x:e,y:t,text:a,delayMs:n,...Y(sw("Filled",a))}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0,a=i?.pixels;if(!e)throw new $("INVALID_ARGS","scroll requires direction");if(void 0!==t&&!Number.isFinite(t))throw new $("INVALID_ARGS","scroll amount must be a number");if(void 0!==t&&void 0!==a)throw new $("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let n=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new $("INVALID_ARGS",`Unknown direction: ${e}`)}}(e),s=await o.scroll(n,{amount:t,pixels:a});return T({direction:n,...void 0!==t?{amount:t}:{},...void 0!==a?{pixels:a}:{},...s},void 0!==a?`Scrolled ${n} by ${a}px`:void 0!==t?`Scrolled ${n} by ${t}`:`Scrolled ${n}`)}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new $("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:i?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...Y(`Scrolled into view: ${e}`)};return{text:e,...Y(`Scrolled into view: ${e}`)}}case"pinch":{if("android"===e.platform)throw new $("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&i?.surface&&"app"!==i.surface)throw new $("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let t=Number(r[0]),a=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new $("INVALID_ARGS","pinch requires scale > 0");return await tz(e,{command:"pinch",scale:t,x:a,y:n,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{scale:t,x:a,y:n,...Y(`Pinched to scale ${t}`)}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new $("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oQ.test(t))throw new $("INVALID_ARGS",`Invalid trigger-app-event event name: ${t}`,{hint:"Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash."});if(e.length>2)throw new $("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(r);if(Buffer.byteLength(a,"utf8")>8192)throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),n=function(e,t,r){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new $("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new $("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await o.open(n,{appBundleId:i?.appBundleId}),{event:t,eventUrl:n,transport:"deep-link",...Y(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await d.mkdir(c.dirname(e),{recursive:!0}),await o.screenshot(e,{appBundleId:i?.appBundleId,fullscreen:i?.screenshotFullscreen,surface:i?.surface}),{path:e,...Y(`Saved screenshot: ${e}`)}}case"back":return await o.back(i?.backMode),{action:"back",mode:i?.backMode??"in-app",...Y("Back")};case"home":return await o.home(),{action:"home",...Y("Home")};case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...Y("Opened app switcher")};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new $("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new $("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await o.readClipboard()}}if(r.length<2)throw new $("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await o.writeClipboard(t),{action:e,textLength:Array.from(t).length,...Y("Clipboard updated")}}case"keyboard":{let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new $("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new $("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===t){let t=await iH(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let r=await iq(e);return{platform:"android",action:"status",visible:r.visible,inputType:r.inputType,type:r.type}}if("ios"===e.platform){if("dismiss"!==t)throw new $("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let r=await tz(e,{command:"keyboardDismiss",appBundleId:i?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:r.wasVisible,dismissed:r.dismissed,visible:r.visible,...Y(r.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new $("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}case"settings":{var s;let[t,a,n,l,d]=r,u="permission"===t?{permissionTarget:n,permissionMode:l}:void 0;Q({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:n,mode:l,platform:e.platform}});let c=await o.setSetting(t,a,d??i?.appBundleId,u);return c&&"object"==typeof c?T({setting:t,state:a,...c},("string"==typeof(s=c).message&&s.message.length>0?s.message:void 0)??`Updated setting: ${t}`):{setting:t,state:a,...Y(`Updated setting: ${t}`)}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new $("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await o8(a);if("ios"===e.platform)return await oL(e,t,i),{platform:"ios",bundleId:t,...Y(`Pushed notification to ${t}`)};let n=await i5(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount,...Y(`Pushed notification to ${t}`)}}case"snapshot":{if("android"!==e.platform){let t=await X("snapshot_capture",async()=>await tz(e,{command:"snapshot",appBundleId:i?.appBundleId,interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new $("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await X("snapshot_capture",async()=>await iI(e,{interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}case"read":{let[t,a]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(a))throw new $("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await ij(e,t,a)??""};if("macos"===e.platform&&i?.surface&&"app"!==i.surface)return{action:"read",text:(await nq(t,a,{bundleId:i.appBundleId,surface:i.surface})).text};let n=await tz(e,{command:"readText",x:t,y:a,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{action:"read",text:"string"==typeof n.text?n.text:"string"==typeof n.message?n.message:""}}default:throw new $("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}function sm(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function sh(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function sw(e,t){return`${e} ${Array.from(t).length} chars`}let sg=e=>"macos"!==e.platform,sv=e=>"macos"===e.platform||"simulator"===e.kind,sy={alert:{apple:{simulator:!0,device:!0},android:{},supports:sv},pinch:{apple:{simulator:!0,device:!0},android:{},supports:sv},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function sI(e,t){let r=sy[e];if(!r)return!0;let a=ts(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function sA(e,t,r,a,i){return{requestId:i??J().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,screenshotFullscreen:t?.screenshotFullscreen,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:oY(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let sb=eF(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function sS(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(eh);await t(e);return}if("device"===e.kind)return void await s_(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(ec);await t(e.id)}}async function s_(e){let t=c.join(u.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(sb/1e3));try{let a=await O("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:sb+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await sN(t);if(0===a.exitCode){if(!o.parsed)throw new $("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,tunnelState:t,hint:"Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry."});return}throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:n,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sD(i,n)})}catch(t){if(t instanceof $&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),i=String(r.stderr??""),n=Number(r.timeoutMs??sb),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?sD(a,i):o},t)}throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,hint:"Reconnect the device, keep it unlocked, and retry."},t instanceof Error?t:void 0)}finally{await d.rm(t,{force:!0}).catch(()=>{})}}async function sN(e){try{let t=await d.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof r?r:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sD(e,t){let r=nf(e,t);return r||(`${e}
32
+ ${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new $("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new $("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function oB(e,t){await ng(e);let r=0,a=eb.fromTimeoutMs(ni);try{await eS(async({deadline:r})=>{var a;if(r?.isExpired())throw new $("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:ni});let i=(a=["launch",e.id,t],eK(e,a)),n=await O("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new $("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!np(e)&&(r+=1)<3},{deadline:a})}catch(r){if(np(r)){var i;let a=(i=await nm(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function oq(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await nd(a,{action:"launch iOS app",deviceId:e.id})}async function oH(e,t,r,a){let i=a?.maxScrolls??48,n=await e({command:"findText",text:r});if(n?.found)return{attempts:0};let o=oW(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let a=1;a<=i;a+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let i=await e({command:"findText",text:r});if(i?.found)return{attempts:a};let n=oW(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(n===o)throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a,stalled:!0});o=n}throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:i})}function oW(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function oz(e,t,r,a,i,n,o){if("tv"===t.target)return oX(await e(t,{command:"swipe",direction:function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left";default:return e}}(i),appBundleId:r.appBundleId},a),n);let s=o??await oJ(e,t,r,a),l=ic({direction:i,amount:n?.amount,pixels:n?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return oX(await e(t,{command:"drag",x:s.originX+l.x1,y:s.originY+l.y1,x2:s.originX+l.x2,y2:s.originY+l.y2,appBundleId:r.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function oJ(e,t,r,a){let i=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},a),n=oK(i.x),o=oK(i.y),s=oK(i.referenceWidth),l=oK(i.referenceHeight);if(void 0===n||void 0===o||void 0===s||void 0===l)throw new $("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:n,originY:o,referenceWidth:s,referenceHeight:l}}function oK(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function oX(e,t){var r;let{x1:a,y1:i,x2:n,y2:o}={x1:oK((r=e).x),y1:oK(r.y),x2:oK(r.x2),y2:oK(r.y2)},s=oK(e.referenceWidth),l=oK(e.referenceHeight),d=void 0!==a&&void 0!==n?Math.round(Math.abs(n-a)):void 0,u=void 0!==i&&void 0!==o?Math.round(Math.abs(o-i)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:d&&d>0?d:u&&u>0?u:void 0;return{...void 0!==a?{x1:a}:{},...void 0!==i?{y1:i}:{},...void 0!==n?{x2:n}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}function oY(e){return e?.clickButton??"primary"}function oZ(e){return"primary"===e.button?null:"click"!==e.commandLabel?new $("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new $("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new $("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new $("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let oQ=/^[A-Za-z0-9_.:-]{1,64}$/,o0=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function o1(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new $("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function o2(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await o3(t)}async function o3(e){await new Promise(t=>setTimeout(t,e))}function o4(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new $("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!s.statSync(n).isFile())throw new $("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof $)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new $("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new $("COMMAND_FAILED",`Unable to read ${a} file: ${n}`,{cause:String(t)})}if((r=i.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:i};throw new $("INVALID_ARGS",`${a} file not found: ${n}`)}async function o8(e){let t=o4(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await o5(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new $("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function o5(e){try{return await d.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new $("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new $("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new $("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new $("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let o6=eF(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),o9=/^(iphone|ipad|ipod|appletv)/i,o7=/^appletv/i,se=["apple tv","appletv","tvos"];function st(e){return(e??"").trim().toLowerCase()}function sr(e){return st(e.hardwareProperties?.platform)}function sa(e){return e.includes("tvos")}function si(e){return sa(st(e))?"tv":"mobile"}function sn(e){let t=st(e);return t.includes("ios")||t.includes("tvos")}function so(e){let t=st(e);return se.some(e=>t.includes(e))}function ss(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function sl(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function sd(e={}){let t,r,a=eH(e.simulatorSetPath),i=e.target;try{t=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!sn(e))continue;let r=si(e);if(!i||r===i)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...a?{simulatorSetPath:a}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function su(e={}){if("darwin"!==process.platform)throw new $("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await V("xcrun"))throw new $("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eH(e.simulatorSetPath),a=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(sn(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:si(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new $("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(t.push({platform:"macos",id:"host-macos-local",name:u.hostname(),kind:"device",target:"desktop",booted:!0}),r)return t;let i=null;try{i=c.join(u.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await O("xcrun",["devicectl","list","devices","--json-output",i],{allowFailure:!0,timeoutMs:o6});if(0!==e.exitCode)return t;let r=await d.readFile(i,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(function(e){var t;let r=sr(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=sl(e),!!o9.test(t.trim())||ss(e).some(so))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",a=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:a,kind:"device",target:function(e){var t;return sa(sr(e))?"tv":(t=sl(e),o7.test(t.trim())||ss(e).some(so))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{i&&await d.rm(i,{force:!0}).catch(()=>{})}return t}async function sc(e,t,r){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await tu(e,t,r)}catch(e){if(i||!(e instanceof $)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!i&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!a||"device"===a.kind)){let e=await sd({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new $("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function sf(e){let t=e.platform,r=td({simulatorSetPath:eH(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=ez(e.androidDeviceAllowlist);return await X("resolve_target_device",async()=>{let i={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(i.target&&!i.platform)throw new $("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await r8();let e=await af({serialAllowlist:a});return await tu(e,i)}if(i.platform){let e=await su({simulatorSetPath:r});return await sc(e,i,{simulatorSetPath:r})}let n=[];try{n.push(...await af({serialAllowlist:a}))}catch{}try{n.push(...await su({simulatorSetPath:r}))}catch{}return await tu(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function sp(e,t,r,a,i){let n={requestId:i?.requestId,appBundleId:i?.appBundleId,verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>a4(e,t,r?.activity),openDevice:()=>a5(e),close:t=>a6(e,t),tap:(t,r)=>iN(e,t,r),doubleTap:async(t,r)=>{await iN(e,t,r),await iN(e,t,r)},swipe:(t,r,a,i,n)=>iD(e,t,r,a,i,n),longPress:(t,r,a)=>ik(e,t,r,a),focus:(t,r)=>iC(e,t,r),type:(t,r)=>iO(e,t,r),fill:(t,r,a,i)=>iP(e,t,r,a,i),scroll:(t,r)=>iR(e,t,r),scrollIntoView:(t,r)=>iT(e,t,r),screenshot:t=>i9(e,t),back:t=>ix(e),home:()=>iM(e),appSwitcher:()=>iE(e),readClipboard:()=>iW(e),writeClipboard:t=>iz(e,t),setSetting:(t,r,a,i)=>iQ(e,t,r,a,i)};case"ios":case"macos":{let r,a,{overrides:i,runnerOpts:n}=(r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},a=()=>{if(eP(t.requestId))throw eT()},{runnerOpts:r,overrides:{tap:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),doubleTap:async(a,i)=>await tz(e,{command:"tapSeries",x:a,y:i,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(a,i,n,o,s)=>await tz(e,{command:"drag",x:a,y:i,x2:n,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(a,i,n)=>await tz(e,{command:"longPress",x:a,y:i,durationMs:n,appBundleId:t.appBundleId},r),focus:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),type:async(a,i)=>{await tz(e,{command:"type",text:a,delayMs:i,appBundleId:t.appBundleId},r)},fill:async(a,i,n,o)=>{let s=await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r);return await tz(e,{command:"type",text:n,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},r),s},scroll:async(a,i)=>await oz(tz,e,t,r,a,i),scrollIntoView:async(i,n)=>await oH(a=>tz(e,{...a,appBundleId:t.appBundleId},r),a,i,n)}});return{open:(t,r)=>oS(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>o_(e),close:t=>oN(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await nW(t,{surface:r.surface,fullscreen:r.fullscreen}):await os(e,t,r?.appBundleId,r?.fullscreen)},back:async r=>{await tz(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},n)},home:async()=>{await tz(e,{command:"home",appBundleId:t.appBundleId},n)},appSwitcher:async()=>{await tz(e,{command:"appSwitcher",appBundleId:t.appBundleId},n)},readClipboard:()=>ok(e),writeClipboard:t=>oO(e,t),setSetting:(t,r,a,i)=>oC(e,t,r,a,i),...i}}default:throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,n);return Q({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await X("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new $("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null,...Y("Opened device")};if(void 0!==a){if("android"===e.platform)throw new $("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(r9(t))throw new $("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId,url:a}),{app:t,url:a,...Y(`Opened: ${t}`)}}return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId}),{app:t,...Y(`Opened: ${t}`)}}case"close":{let e=r[0];if(!e)return{closed:"session",...Y("Closed session")};return await o.close(e),{app:e,...Y(`Closed: ${e}`)}}case"press":{let t,[a,n]=r.map(Number);if(Number.isNaN(a)||Number.isNaN(n))throw new $("INVALID_ARGS","press requires x y");if("macos"===e.platform&&i?.surface&&"app"!==i.surface){let e=oY(i);if("primary"!==e)throw new $("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${i.surface} sessions.`);return await nH(a,n,{bundleId:i.appBundleId,surface:i.surface}),{x:a,y:n,...Y(sm({x:a,y:n}))}}let s=oY(i);if("primary"!==s){let t=oZ({commandLabel:"click",platform:e.platform,button:s,count:i?.count,intervalMs:i?.intervalMs,holdMs:i?.holdMs,jitterPx:i?.jitterPx,doubleTap:i?.doubleTap});if(t)throw t;return await tz(e,{command:"mouseClick",x:a,y:n,button:s,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{x:a,y:n,button:s,...Y(sm({x:a,y:n,button:s}))}}let l=o1(i?.count??1,"count",1,200),d=o1(i?.intervalMs??0,"interval-ms",0,1e4),u=o1(i?.holdMs??0,"hold-ms",0,1e4),c=o1(i?.jitterPx??0,"jitter-px",0,100),f=i?.doubleTap===!0;if(f&&u>0)throw new $("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&c>0)throw new $("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&l>1&&0===u&&0===c){let t=await tz(e,{command:"tapSeries",x:a,y:n,count:l,intervalMs:d,doubleTap:f,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:f,timingMode:"runner-series",...t,...Y(sm({x:a,y:n}))}}return await o2(l,d,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=o0[e%o0.length];return[r*t,a*t]}(e,c),s=a+r,l=n+i;if(f){t??=await o.doubleTap(s,l)??void 0;return}u>0?t??=await o.longPress(s,l,u)??void 0:t??=await o.tap(s,l)??void 0}),T({x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:f,...t},sm({x:a,y:n}))}case"swipe":{let t=Number(r[0]),a=Number(r[1]),n=Number(r[2]),s=Number(r[3]);if([t,a,n,s].some(Number.isNaN))throw new $("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=o1(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=o1(i?.count??1,"count",1,200),c=o1(i?.pauseMs??0,"pause-ms",0,1e4),f=i?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new $("INVALID_ARGS",`Invalid pattern: ${f}`);if(("ios"===e.platform||"macos"===e.platform)&&u>1){let r=await tz(e,{command:"dragSeries",x:t,y:a,x2:n,y2:s,durationMs:d,count:u,pauseMs:c,pattern:f,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:f,...r,...Y(sh(u,f))}}return await o2(u,c,async e=>{"ping-pong"===f&&e%2==1?await o.swipe(n,s,t,a,d):await o.swipe(t,a,n,s,d)}),T({x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:f},sh(u,f))}case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a,...Y(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t,...Y(`Focused (${e}, ${t})`)}}case"type":{let e=r.join(" ");if(!e)throw new $("INVALID_ARGS","type requires text");let t=o1(i?.delayMs??0,"delay-ms",0,1e4);return await o.type(e,t),{text:e,delayMs:t,...Y(sw("Typed",e))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new $("INVALID_ARGS","fill requires x y text");let n=o1(i?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,a,n),{x:e,y:t,text:a,delayMs:n,...Y(sw("Filled",a))}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0,a=i?.pixels;if(!e)throw new $("INVALID_ARGS","scroll requires direction");if(void 0!==t&&!Number.isFinite(t))throw new $("INVALID_ARGS","scroll amount must be a number");if(void 0!==t&&void 0!==a)throw new $("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let n=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new $("INVALID_ARGS",`Unknown direction: ${e}`)}}(e),s=await o.scroll(n,{amount:t,pixels:a});return T({direction:n,...void 0!==t?{amount:t}:{},...void 0!==a?{pixels:a}:{},...s},void 0!==a?`Scrolled ${n} by ${a}px`:void 0!==t?`Scrolled ${n} by ${t}`:`Scrolled ${n}`)}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new $("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:i?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...Y(`Scrolled into view: ${e}`)};return{text:e,...Y(`Scrolled into view: ${e}`)}}case"pinch":{if("android"===e.platform)throw new $("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&i?.surface&&"app"!==i.surface)throw new $("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let t=Number(r[0]),a=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new $("INVALID_ARGS","pinch requires scale > 0");return await tz(e,{command:"pinch",scale:t,x:a,y:n,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{scale:t,x:a,y:n,...Y(`Pinched to scale ${t}`)}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new $("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oQ.test(t))throw new $("INVALID_ARGS",`Invalid trigger-app-event event name: ${t}`,{hint:"Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash."});if(e.length>2)throw new $("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(r);if(Buffer.byteLength(a,"utf8")>8192)throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),n=function(e,t,r){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new $("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new $("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await o.open(n,{appBundleId:i?.appBundleId}),{event:t,eventUrl:n,transport:"deep-link",...Y(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await d.mkdir(c.dirname(e),{recursive:!0}),await o.screenshot(e,{appBundleId:i?.appBundleId,fullscreen:i?.screenshotFullscreen,surface:i?.surface}),{path:e,...Y(`Saved screenshot: ${e}`)}}case"back":return await o.back(i?.backMode),{action:"back",mode:i?.backMode??"in-app",...Y("Back")};case"home":return await o.home(),{action:"home",...Y("Home")};case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...Y("Opened app switcher")};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new $("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new $("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await o.readClipboard()}}if(r.length<2)throw new $("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await o.writeClipboard(t),{action:e,textLength:Array.from(t).length,...Y("Clipboard updated")}}case"keyboard":{let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new $("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new $("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===t){let t=await iH(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let r=await iq(e);return{platform:"android",action:"status",visible:r.visible,inputType:r.inputType,type:r.type}}if("ios"===e.platform){if("dismiss"!==t)throw new $("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let r=await tz(e,{command:"keyboardDismiss",appBundleId:i?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:r.wasVisible,dismissed:r.dismissed,visible:r.visible,...Y(r.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new $("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}case"settings":{var s;let[t,a,n,l,d]=r,u="permission"===t?{permissionTarget:n,permissionMode:l}:void 0;Q({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:n,mode:l,platform:e.platform}});let c=await o.setSetting(t,a,d??i?.appBundleId,u);return c&&"object"==typeof c?T({setting:t,state:a,...c},("string"==typeof(s=c).message&&s.message.length>0?s.message:void 0)??`Updated setting: ${t}`):{setting:t,state:a,...Y(`Updated setting: ${t}`)}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new $("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await o8(a);if("ios"===e.platform)return await oL(e,t,i),{platform:"ios",bundleId:t,...Y(`Pushed notification to ${t}`)};let n=await i5(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount,...Y(`Pushed notification to ${t}`)}}case"snapshot":{if("android"!==e.platform){let t=await X("snapshot_capture",async()=>await tz(e,{command:"snapshot",appBundleId:i?.appBundleId,interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new $("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await X("snapshot_capture",async()=>await iI(e,{interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}case"read":{let[t,a]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(a))throw new $("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await ij(e,t,a)??""};if("macos"===e.platform&&i?.surface&&"app"!==i.surface)return{action:"read",text:(await nq(t,a,{bundleId:i.appBundleId,surface:i.surface})).text};let n=await tz(e,{command:"readText",x:t,y:a,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{action:"read",text:"string"==typeof n.text?n.text:"string"==typeof n.message?n.message:""}}default:throw new $("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}function sm(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function sh(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function sw(e,t){return`${e} ${Array.from(t).length} chars`}let sg=e=>"macos"!==e.platform,sv=e=>"macos"===e.platform||"simulator"===e.kind,sy={alert:{apple:{simulator:!0,device:!0},android:{},supports:sv},pinch:{apple:{simulator:!0,device:!0},android:{},supports:sv},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function sI(e,t){let r=sy[e];if(!r)return!0;let a=ts(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function sA(e,t,r,a,i){return{requestId:i??J().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,screenshotFullscreen:t?.screenshotFullscreen,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:oY(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let sb=eF(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function sS(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(eh);await t(e);return}if("device"===e.kind)return void await s_(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(ec);await t(e.id)}}async function s_(e){let t=c.join(u.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(sb/1e3));try{let a=await O("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:sb+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await sN(t);if(0===a.exitCode){if(!o.parsed)throw new $("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,tunnelState:t,hint:"Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry."});return}throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:n,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sD(i,n)})}catch(t){if(t instanceof $&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),i=String(r.stderr??""),n=Number(r.timeoutMs??sb),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?sD(a,i):o},t)}throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,hint:"Reconnect the device, keep it unlocked, and retry."},t instanceof Error?t:void 0)}finally{await d.rm(t,{force:!0}).catch(()=>{})}}async function sN(e){try{let t=await d.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof r?r:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sD(e,t){let r=nf(e,t);return r||(`${e}
33
33
  ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":nc)}let sx=eF(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),sM=new Map;async function sE(e){let t=await y.mkdtemp(c.join(u.tmpdir(),"agent-device-materialized-"));try{let r=await sL(e.installablePath,c.join(t,"installable")),a=e.archivePath?await sL(e.archivePath,c.join(t,"archive")):void 0,i=n.randomUUID(),o=e.ttlMs??sx,s=Date.now()+o,l=setTimeout(()=>{sk(i)},o);return sM.set(i,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:i,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await y.rm(t,{recursive:!0,force:!0}),e}}async function sk(e,t){let r=sM.get(e);if(!r)throw new $("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new $("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),sM.delete(e),await y.rm(r.rootPath,{recursive:!0,force:!0})}async function sO(e){let t=Array.from(sM.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await sk(e)}))}async function sL(e,t){let r=await y.stat(e);await y.mkdir(t,{recursive:!0});let a=c.join(t,c.basename(e));return r.isDirectory()?await y.cp(e,a,{recursive:!0}):await y.copyFile(e,a),a}async function sC(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new $("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await sS(e.session.device),e.session.device}if(!r)throw new $("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await sf(e.flags??{});return await sS(a),a}async function sP(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 $("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new $("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new $("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:r_(o,t.meta?.tenantId)},cleanup:()=>{rN(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 $("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await sC({session:i,flags:t.flags});if(!sI("install",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let u=eR(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await Promise.resolve(eh),{prepareIosInstallArtifact:o}=await Promise.resolve(ew),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await sE({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 $("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=T(o,sR(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await sk(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await Promise.resolve(ep),{installAndroidInstallablePathAndResolvePackageName:f}=await Promise.resolve(ef),p=await c(s.source,{signal:u});try{l.enabled&&(e=await sE({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 $("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await Promise.resolve(ef),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=T(u,sR(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await sk(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:q(e)}}}function sR(e){return`Installed: ${es(e)}`}async function sT(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new $("INVALID_ARGS","release_materialized_paths requires a materializationId");return await sk(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:q(e)}}}let s$=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),sF=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function sU(e,t,r){return t||sV(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function sV(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function sG(e){return"ios"===e.platform&&"simulator"===e.kind}async function sj(e,t){sG(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function sB(e){let t=sV(e.flags)||!e.session?await sf(e.flags??{}):await sq(e.session.device);return!1!==e.ensureReady&&await sS(t),t}async function sq(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 sf(t)}catch(e){if(!(e instanceof $)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await sf({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function sH(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 sW="shared_prefs/ReactNativeDevPrefs.xml",sz="debug_http_host",sJ="dev_server_https",sK="RCT_jsLocation",sX="RCT_packager_scheme",sY="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",sZ='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function sQ(e){return void 0!==s0(e)}function s0(e){if(!e)return;let t=lr(e.metroHost),r=li(e.metroPort),a="http",i=lr(e.bundleUrl);if(i){var n;let e;try{e=new p(i)}catch(e){throw new $("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=lr(e.hostname),r??=li(e.port.length>0?Number(e.port):"https:"===(n=e.protocol)?443:"http:"===n?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function s1(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=s0(a);if(i){if("android"===t.platform)return void await s3(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await s6(t,r,i)}}async function s2(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await s4(t,r);"ios"===t.platform&&"simulator"===t.kind&&await s9(t,r)}}async function s3(e,t,r){var a,i,n,o,s,l;let d,u;la(t);let c=(a=await s8(e,t),i=sz,n=`${r.host}:${r.port}`,d=` <string name="${ln(i)}">${ln(n)}</string>`,le(lt(a,i),d));o=c,s=sJ,l="https"===r.scheme,u=` <boolean name="${ln(s)}" value="${l?"true":"false"}" />`,c=le(lt(o,s),u),await s5(e,t,c)}async function s4(e,t){la(t);let r=await s8(e,t),a=lt(r,sz),i=lt(a,sJ);i!==r&&await s5(e,t,i)}async function s8(e,t){let r=await O("adb",r4(e,["shell","run-as",t,"cat",sW]),{allowFailure:!0});return 0!==r.exitCode?sZ:s7(r.stdout)}async function s5(e,t,r){let a=r4(e,["shell","run-as",t,"id"]),i=await O("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=lo(i.stdout,i.stderr);throw new $("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?sY:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await O("adb",r4(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await O("adb",r4(e,["shell","run-as",t,"tee",sW]),{stdin:r.trimEnd()})}catch(a){let e=P(a);if("TOOL_MISSING"===e.code)throw e;let r=lo("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new $("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?sY:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function s6(e,t,r){await O("xcrun",eK(e,["spawn",e.id,"defaults","write",t,sK,"-string",`${r.host}:${r.port}`])),await O("xcrun",eK(e,["spawn",e.id,"defaults","write",t,sX,"-string",r.scheme]))}async function s9(e,t){await O("xcrun",eK(e,["spawn",e.id,"defaults","delete",t,sK]),{allowFailure:!0}),await O("xcrun",eK(e,["spawn",e.id,"defaults","delete",t,sX]),{allowFailure:!0})}function s7(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
34
34
  `:sZ}function le(e,t){return s7(e).replace("</map>",`${t}
35
35
  </map>`)}function lt(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return s7(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 lr(e){let t=e?.trim();return t&&t.length>0?t:void 0}function la(e){if("binary"!==ab(e))return;let t=aS(e);throw new $("INVALID_ARGS",t,{package:e,hint:t})}function li(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function ln(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function lo(e,t){let r=`${e}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-device",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "Unified control plane for physical and virtual devices via an agent-driven CLI.",
5
5
  "license": "MIT",
6
6
  "author": "Callstack",