agent-device 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ 3feeee326a4b94a45d9097ac66cd5a7b2d09b02be88c38cd6a6e8be587adc9b2 agent-device-android-multitouch-helper-0.16.1.apk
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "android-multitouch-helper",
3
- "version": "0.16.0",
4
- "assetName": "agent-device-android-multitouch-helper-0.16.0.apk",
5
- "sha256": "5f6a857083f2c71e12bbf6a6fdc2b25ce4a548333e8706b74a4f0e439fa4248d",
3
+ "version": "0.16.1",
4
+ "assetName": "agent-device-android-multitouch-helper-0.16.1.apk",
5
+ "sha256": "3feeee326a4b94a45d9097ac66cd5a7b2d09b02be88c38cd6a6e8be587adc9b2",
6
6
  "packageName": "com.callstack.agentdevice.multitouchhelper",
7
- "versionCode": 16000,
7
+ "versionCode": 16001,
8
8
  "instrumentationRunner": "com.callstack.agentdevice.multitouchhelper/.MultiTouchInstrumentation",
9
9
  "statusProtocol": "android-multitouch-helper-v1"
10
10
  }
@@ -0,0 +1 @@
1
+ d59fb15b0ff87e7997fb24e281ebe4a4bb14323273f2a5c70616dbfcda26cd18 agent-device-android-snapshot-helper-0.16.1.apk
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "android-snapshot-helper",
3
- "version": "0.16.0",
4
- "releaseTag": "v0.16.0",
5
- "assetName": "agent-device-android-snapshot-helper-0.16.0.apk",
3
+ "version": "0.16.1",
4
+ "releaseTag": "v0.16.1",
5
+ "assetName": "agent-device-android-snapshot-helper-0.16.1.apk",
6
6
  "apkUrl": null,
7
- "sha256": "e023c8211025186424fba7fce9f03f502d64d5f7cc2a205499e3ad03073ac21f",
8
- "checksumName": "agent-device-android-snapshot-helper-0.16.0.apk.sha256",
7
+ "sha256": "d59fb15b0ff87e7997fb24e281ebe4a4bb14323273f2a5c70616dbfcda26cd18",
8
+ "checksumName": "agent-device-android-snapshot-helper-0.16.1.apk.sha256",
9
9
  "packageName": "com.callstack.agentdevice.snapshothelper",
10
- "versionCode": 16000,
10
+ "versionCode": 16001,
11
11
  "instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
12
12
  "minSdk": 23,
13
13
  "targetSdk": 36,
package/dist/src/1769.js CHANGED
@@ -1,7 +1,7 @@
1
- import{promises as e}from"node:fs";import t from"node:os";import a from"node:path";import{asAppError as n,AppError as i}from"./9152.js";import{emitDiagnostic as r}from"./3622.js";import{runCmd as o,resolveFileOverridePath as s,whichCmd as l,runCmdDetached as d}from"./9818.js";import{ensureAndroidSdkPathConfigured as u,resolveAndroidArchivePackageName as c}from"./7651.js";import{sleep as p}from"./4829.js";import{createAndroidPortReverseManager as f,resolveAndroidAdbProvider as m,installAndroidAdbPackage as w,resolveAndroidAdbExecutor as h}from"./9639.js";import{materializeInstallablePath as A,isTrustedInstallSourceUrl as y}from"./989.js";let g=["mCurrentFocus=Window{","mFocusedApp=AppWindowToken{","mResumedActivity:","ResumedActivity:"],v=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,b=/([^{}]*\bis(?:n't| not)\s+responding[^{}]*)/i,M=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/;function _(e){let t=new Set;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;let n=e.split(/\s+/)[0]??"";if(!n.includes("/"))continue;let i=n.split("/")[0]??"";i.includes(".")&&i&&t.add(i)}return Array.from(t)}function I(e){return e.split("\n").map(e=>{let t=e.trim();return t.startsWith("package:")?t.slice(8):t}).filter(Boolean)}function N(e){return O(e,e=>(function(e){for(let t of e.trim().split(/\s+/)){let e=t.indexOf("/");if(e<=0)continue;let a=k(t.slice(0,e),!1),n=k(t.slice(e+1),!0);if(a&&n&&a.length===e)return{package:a,activity:n}}return null})(e))}function O(e,t){let a=e.split("\n");for(let e of g)for(let n of a){let a=n.indexOf(e);if(-1===a)continue;let i=n.trim(),r=t(n.slice(a+e.length),i);if(r)return r}return null}function k(e,t){let a=0;for(;a<e.length&&function(e,t){if(!e)return!1;let a=e.charCodeAt(0);return a>=48&&a<=57||a>=65&&a<=90||a>=97&&a<=122||"_"===e||"."===e||t&&"$"===e}(e[a],t);)a+=1;return e.slice(0,a)}function C(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let a=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!a)return!1;let n=a[1]?.toLowerCase(),i=a[2]??"";return"http"!==n&&"https"!==n&&"ws"!==n&&"wss"!==n&&"ftp"!==n&&"ftps"!==n||i.startsWith("//")}function D(e,t){let a,n=e?.trim();return n?n:"http"===(a=t.trim().split(":")[0]?.toLowerCase())||"https"===a?"com.apple.mobilesafari":void 0}function L(e={}){let t=e.ttlMs??3e4,a=e.nowMs??Date.now,n=new Map,i=e=>{var t;let a=[(t=e).platform,t.deviceId,""].join("\0");for(let e of n.keys())e.startsWith(a)&&n.delete(e)};return{get(e,t){let i=x(e,t),r=n.get(i);if(r)return r.expiresAtMs<=a()?void n.delete(i):r.value},set:(e,i,r)=>(n.set(x(e,i),{value:r,expiresAtMs:a()+t}),r),clear(e){i(e)},async invalidateWhile(e,t){i(e);try{return await t()}finally{i(e)}}}}function x(e,t){return[e.platform,e.deviceId,e.variant??"",t.trim().toLowerCase()].join("\0")}function E(e){return["1","true","yes","on"].includes((e??"").trim().toLowerCase())}class T{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new T(t,e)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return 0>=this.remainingMs(e)}}async function S(e,t={},a={}){let n,r={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=r.maxAttempts;t+=1){if(a.signal?.aborted)throw new i("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(a.deadline?.isExpired()&&t>1)break;try{let n=await e({attempt:t,maxAttempts:r.maxAttempts,deadline:a.deadline});return a.onEvent?.({phase:a.phase,event:"succeeded",attempt:t,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs()}),P({phase:a.phase,event:"succeeded",attempt:t,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs()}),n}catch(d){n=d;let e=a.classifyReason?.(d),i={phase:a.phase,event:"attempt_failed",attempt:t,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs(),reason:e};if(a.onEvent?.(i),P(i),t>=r.maxAttempts||r.shouldRetry&&!r.shouldRetry(d,t))break;let o=function(e,t,a,n){let i=Math.min(t,e*2**(n-1));return Math.max(0,i+i*a*(2*Math.random()-1))}(r.baseDelayMs,r.maxDelayMs,r.jitter,t),s=a.deadline?Math.min(o,a.deadline.remainingMs()):o;if(s<=0)break;let l={phase:a.phase,event:"retry_scheduled",attempt:t,maxAttempts:r.maxAttempts,delayMs:s,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs(),reason:e};a.onEvent?.(l),P(l),await function(e,t){return new Promise(a=>{if(t?.aborted)return void a();let n=!1,i=()=>{n||(n=!0,t&&t.removeEventListener("abort",o),a())},r=setTimeout(i,e);function o(){clearTimeout(r),i()}t&&t.addEventListener("abort",o,{once:!0})})}(s,a.signal)}}let o={phase:a.phase,event:"exhausted",attempt:r.maxAttempts,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs(),reason:a.classifyReason?.(n)};if(a.onEvent?.(o),P(o),n)throw n;throw new i("COMMAND_FAILED","retry failed")}async function R(e,t={}){return S(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function P(e){r({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}})}function F(e){return e?.trim()||void 0}function U(e){return F(e)}function $(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function B(e,t=process.env){let a=F(e)??F(t.AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST);if(a)return $(a)}function W(e){let t=e.error?n(e.error):null,a=e.context?.platform,i=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===a?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let r=t?.details??{},o="string"==typeof r.message?r.message:void 0,s="string"==typeof r.stdout?r.stdout:void 0,l="string"==typeof r.stderr?r.stderr:void 0,d=r.boot&&"object"==typeof r.boot?r.boot:null,u=r.bootstatus&&"object"==typeof r.bootstatus?r.bootstatus:null,c=[e.message,t?.message,e.stdout,e.stderr,o,s,l,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0,"string"==typeof u?.stdout?u.stdout:void 0,"string"==typeof u?.stderr?u.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===a&&(c.includes("runner did not accept connection")||"connect"===i&&(c.includes("timed out")||c.includes("timeout")||c.includes("econnrefused")||c.includes("connection refused")||c.includes("fetch failed")||c.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===a&&"boot"===i&&(c.includes("timed out")||c.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===a&&"boot"===i&&(c.includes("timed out")||c.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":c.includes("resource temporarily unavailable")||c.includes("killed: 9")||c.includes("cannot allocate memory")||c.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===a&&(c.includes("device not found")||c.includes("no devices")||c.includes("device offline")||c.includes("offline")||c.includes("unauthorized")||c.includes("not authorized")||c.includes("unable to locate device")||c.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||c.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function V(e){switch(e){case"IOS_BOOT_TIMEOUT":return"Retry simulator boot and inspect simctl bootstatus logs; in CI reduce parallel jobs or use a larger runner.";case"IOS_RUNNER_CONNECT_TIMEOUT":return"Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.";case"ANDROID_BOOT_TIMEOUT":return"Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.";case"ADB_TRANSPORT_UNAVAILABLE":return"Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.";case"CI_RESOURCE_STARVATION_SUSPECTED":return"CI machine may be resource constrained; reduce parallel jobs or use a larger runner.";case"IOS_TOOL_MISSING":return"Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.";case"BOOT_COMMAND_FAILED":return"Inspect command stderr/stdout for the failing boot phase and retry after environment validation.";default:return"Retry once and inspect verbose logs for the failing phase."}}let G=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];async function j(e,t,a){let n=Array(e.length),i=0,r=Math.min(t,e.length);return await Promise.all(Array.from({length:r},async()=>{for(;i<e.length;){let t=i;i+=1,n[t]=await a(e[t])}})),n}function K(e){return`${e.stdout}
2
- ${e.stderr}`}function H(e,t){return["-s",e,...t]}function z(e){return e.startsWith("emulator-")}function q(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function Z(e,t=1e4){return o("adb",H(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function J(e,t){let a=t.replace(/_/g," ").trim();if(!z(e))return a||e;let n=await Q(e);return n?n.replace(/_/g," "):a||e}async function X(e,t,a){try{return await a("adb",H(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var i;if("COMMAND_FAILED"===(i=n(e)).code&&"number"==typeof i.details?.timeoutMs)return;throw e}}async function Q(e,t=o){for(let a of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let n=await X(e,["shell","getprop",a],t);if(!n)continue;let i=n.stdout.trim();if(0===n.exitCode&&i.length>0)return i}let a=await X(e,["emu","avd","name"],t);if(!a)return;let n=function(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}(a.stdout);if(0===a.exitCode&&n)return n}async function Y(e,t){let a=K(await o("adb",H(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:1e4})).toLowerCase();return!!a.includes("true")||!a.includes("false")&&null}async function ee(e){return(await j(G,2,async t=>await Y(e,t))).some(e=>!0===e)}async function et(e){var t;let a;return"tv"===((a=K(await o("adb",H(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:1e4})).toLowerCase()).includes("tv")||a.includes("leanback")?"tv":null)||await ee(e)?"tv":(t=K(await o("adb",H(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:1e4})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function ea(e={}){if(await u(),!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??B(void 0),a=(await en()).filter(e=>!t||t.has(e.serial));return await j(a,3,async({serial:e,rawModel:t})=>{let[a,n,i]=await Promise.all([J(e,t),es(e),et(e)]);return{platform:"android",id:e,name:a,kind:z(e)?"emulator":"device",target:i,booted:n}})}async function en(){return(await o("adb",["devices","-l"],{timeoutMs:1e4})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).flatMap(e=>{let t=e[0];return void 0===t||"device"!==e[1]?[]:[{serial:t,rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}]})}async function ei(){let e=await o("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:1e4});if(0!==e.exitCode)throw new i("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function er(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await eo(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await p(1e3)}throw new i("COMMAND_FAILED","Android emulator did not appear in time",{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:"Check emulator logs and verify the AVD can start from command line."})}async function eo(e,t){let a=q(e);for(let e of(await en()).filter(e=>(!t||e.serial===t)&&z(e.serial)))if(q(e.rawModel)===a||q(await J(e.serial,e.rawModel))===a)return e.serial}async function es(e){try{let t=await Z(e);return"1"===t.stdout.trim()}catch{return!1}}async function el(e){var t,a;let n;await u();let r=e.avdName.trim();if(!r)throw new i("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let o=e.timeoutMs??12e4;if(!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH");if(!await l("emulator"))throw new i("TOOL_MISSING","emulator not found in PATH");let s=await ei(),c=function(e,t){let a=e.find(e=>e===t);if(a)return a;let n=q(t);return e.find(e=>q(e)===n)}(s,r);if(!c)throw new i("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:r,availableAvds:s,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let p=Date.now(),f=(t=await ea(),a=e.serial,n=q(c),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!a||e.id===a)&&q(e.name)===n));if(!f){let t=["-avd",c];e.headless&&t.push("-no-window","-no-audio"),d("emulator",t)}let m=f??await er({avdName:c,serial:e.serial,timeoutMs:o}),w=Math.max(1e3,o-(Date.now()-p));await ed(m.id,w);let h=(await ea()).find(e=>e.id===m.id);return h?{...h,name:c,booted:!0}:{...m,name:c,booted:!0}}async function ed(e,t=6e4){let a,r=T.fromTimeoutMs(t),o=Math.max(1,Math.ceil(t/1e3)),s=!1;try{await S(async({deadline:n})=>{if(n?.isExpired())throw s=!0,new i("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:r.elapsedMs(),message:"timeout"});let o=Math.max(1e3,n?.remainingMs()??t),l=await Z(e,Math.min(o,1e4));if(a=l,"1"!==l.stdout.trim())throw new i("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode})},{maxAttempts:o,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=W({error:e,stdout:a?.stdout,stderr:a?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:r,phase:"boot",classifyReason:e=>W({error:e,stdout:a?.stdout,stderr:a?.stderr,context:{platform:"android",phase:"boot"}})})}catch(f){let o=n(f),l=a?.stdout,d=a?.stderr,u=a?.exitCode,c=W({error:f,stdout:l,stderr:d,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===c&&"Android device is still booting"===o.message&&(c="ANDROID_BOOT_TIMEOUT");let p={serial:e,timeoutMs:t,elapsedMs:r.elapsedMs(),reason:c,hint:V(c),stdout:l,stderr:d,exitCode:u};if(s||"ANDROID_BOOT_TIMEOUT"===c)throw new i("COMMAND_FAILED","Android device did not finish booting in time",p);if("TOOL_MISSING"===o.code)throw new i("TOOL_MISSING",o.message,{...p,...o.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===c)throw new i("COMMAND_FAILED",o.message,{...p,...o.details??{}});throw new i(o.code,o.message,{...p,...o.details??{}},o.cause)}}async function eu(e,t,a){return await h(e)(t,a)}function ec(e){return{platform:"android",id:e,name:e,kind:e.startsWith("emulator-")?"emulator":"device",booted:!0}}async function ep(){if(await u(),!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH")}let ef=/\.(?:apk|aab)$/i,em=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function ew(e){var t,a;let n=e.trim();return 0===n.length?"other":ef.test(n)?n.includes("/")||n.includes("\\")||n.startsWith(".")||n.startsWith("~")||(t=n,!em.test(t))?"binary":"package":(a=n,em.test(a))?"package":"other"}function eh(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}async function eA(e,t){let n="url"===e.kind&&y(e.url),i=await A({source:e,isInstallablePath:(e,t)=>{var n;let i;return t.isFile()&&(n=e,".apk"===(i=a.extname(n).toLowerCase())||".aab"===i)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await ey(i.installablePath);return{archivePath:i.archivePath,installablePath:i.installablePath,packageName:e.packageName,cleanup:i.cleanup}}catch(e){throw await i.cleanup(),e}}async function ey(e){let t=a.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await c(e)}}let eg={settings:{type:"intent",value:"android.settings.SETTINGS"}},ev="android.intent.category.LAUNCHER",eb="android.intent.category.LEANBACK_LAUNCHER",eM="android.intent.category.DEFAULT",e_="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.",eI=new Set(["localhost","127.0.0.1","::1","[::1]"]),eN=L();function eO(e){return{platform:"android",deviceId:e.id,variant:e.target??""}}async function ek(e,t){let a=t.trim();if("package"===ew(a))return{type:"package",value:a};let n=eg[a.toLowerCase()];if(n)return n;let r=eO(e),o=eN.get(r,a);if(o)return o;let s=(await eu(e,["shell","pm","list","packages"])).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(a.toLowerCase())),l=s[0];if(void 0!==l&&1===s.length)return eN.set(r,a,{type:"package",value:l});if(s.length>1)throw new i("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:s,hint:"Run agent-device apps --platform android to see the exact installed package names before retrying open."});throw new i("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:e_})}async function eC(e,t){let a=await eD(e);return("user-installed"===t?(await ex(e)).filter(e=>a.has(e)):Array.from(a)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:eE(e)}))}async function eD(e){let t=new Set;for(let a of eL(e,{includeFallbackWhenUnknown:!0})){let n=await eu(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",a],{allowFailure:!0});if(0===n.exitCode&&0!==n.stdout.trim().length)for(let e of _(n.stdout))t.add(e)}return t}function eL(e,t={}){return"tv"===e.target?[eb]:"mobile"===e.target?[ev]:t.includeFallbackWhenUnknown?[ev,eb]:[ev]}async function ex(e){return I((await eu(e,["shell","pm","list","packages","-3"])).stdout)}function eE(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),a=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),n=a[a.length-1]??e;for(let e=a.length-1;e>=0;e-=1){let i=a[e];if(i&&!t.has(i)){n=i;break}}return n.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function eT(e){let t=await eR(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let a=await eR(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return a||{}}async function eS(e){return await eP(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]])}async function eR(e,t){for(let a of t){let t=N((await eu(e,a,{allowFailure:!0})).stdout??"");if(t)return t}return null}async function eP(e,t){for(let a of t){let t=O((await eu(e,a,{allowFailure:!0})).stdout??"",(e,t)=>(function(e,t){let a=e.split("}")[0]?.trim()??e.trim(),n=v.exec(a);if(n){let e=n[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=b.exec(a);if(!i)return null;let r=i[1];if(void 0===r)return null;let o=r.trim().replace(/\s+/g," "),s=M.exec(o)?.[1];return{...s?{package:s}:{},focusedWindow:o,raw:t}})(e,t));if(t)return t}return null}async function eF(e,t){let a=function(e){let t;try{t=new URL(e)}catch{return null}let a=t.hostname.toLowerCase();if(!eI.has(a)||!t.port)return null;let n=Number(t.port);return Number.isInteger(n)?`tcp:${n}`:null}(t);if(!a)return;let n=f(m(e));try{await n.ensure({local:a,remote:a})}catch(t){let e={localPort:a.replace("tcp:",""),operation:`adb reverse ${a} ${a}`};throw t instanceof i&&Object.assign(e,{hint:t.details?.hint,diagnosticId:t.details?.diagnosticId,logPath:t.details?.logPath}),new i("COMMAND_FAILED",`Failed to ensure Android port reverse ${a} before opening localhost URL`,e,t)}}async function eU(e,t,a){var n;e.booted||await ed(e.id);let i="string"==typeof(n=a)?{activity:n}:n??{},r=i.activity,o=t.trim();if(C(o))return void await e$(e,o,i);if(void 0!==i.url)return void await eB(e,t,i);let s=await ek(e,t),l=eL(e)[0]??ev;"intent"===s.type?await eW(e,s.value,r):r?await eV(e,s.value,r,l):await eG(e,s.value,l)}async function e$(e,t,a){var n;let r;if(a.activity)throw new i("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await eF(e,t),await eu(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",t,...(n=a.appBundleId,(r=n?.trim())?["-p",r]:[])])}async function eB(e,t,a){if(a.activity)throw new i("INVALID_ARGS","Activity override is not supported when opening an app-bound deep link URL");let n=a.url?.trim()??"";if(!C(n))throw new i("INVALID_ARGS","Android app-bound open requires a valid URL target");let r=await eK(e,t,"app-bound open");await eu(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",n,"-p",r])}async function eW(e,t,a){if(a)throw new i("INVALID_ARGS","Activity override requires a package name, not an intent");await eu(e,["shell","am","start","-W","-a",t])}async function eV(e,t,a,n){let i=a.includes("/")?a:`${t}/${a.startsWith(".")?a:`.${a}`}`;try{await eu(e,ej(i,n))}catch(a){throw await eq(e,t,a),a}}async function eG(e,t,a){let n=await eu(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eM,"-c",a,"-p",t],{allowFailure:!0});if(0===n.exitCode&&!eX(n.stdout,n.stderr))return;let r=await eJ(e,t);if(!r){if(!await ez(e,t))throw eH(t);throw new i("COMMAND_FAILED",`Failed to launch ${t}`,{stdout:n.stdout,stderr:n.stderr})}await eu(e,ej(r,a))}function ej(e,t){return["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eM,"-c",t,"-n",e]}async function eK(e,t,a){let n=await ek(e,t);if("intent"===n.type)throw new i("INVALID_ARGS",`Android ${a} requires a package name, not an intent`);return n.value}function eH(e){return new i("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:e_})}async function ez(e,t){let a=await eu(e,["shell","pm","path",t],{allowFailure:!0}),n=`${a.stdout}
3
- ${a.stderr}`;return!!(0===a.exitCode&&/\bpackage:/i.test(n))||(eZ(n),!1)}async function eq(e,t,a){if(eZ(a instanceof i?`${String(a.details?.stdout??"")}
4
- ${String(a.details?.stderr??"")}`:"")||!await ez(e,t))throw eH(t)}function eZ(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function eJ(e,t){for(let a of Array.from(new Set(eL(e,{includeFallbackWhenUnknown:!0})))){let n=await eu(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",a,t],{allowFailure:!0});if(0!==n.exitCode)continue;let i=eQ(n.stdout);if(i)return i}return null}function eX(e,t){let a=`${e}
5
- ${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(a)}function eQ(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let a=t[e];if(void 0===a||!a.includes("/"))continue;let n=a.split(/\s+/)[0];if(void 0!==n)return n}return null}async function eY(e){e.booted||await ed(e.id)}async function e0(e,t){if("settings"===t.trim().toLowerCase())return void await eu(e,["shell","am","force-stop","com.android.settings"]);let a=await ek(e,t);if("intent"===a.type)throw new i("INVALID_ARGS","Close requires a package name, not an intent");await eu(e,["shell","am","force-stop",a.value])}async function e1(e,t){let a=await ek(e,t);if("intent"===a.type)throw new i("INVALID_ARGS","App uninstall requires a package name, not an intent");let n=await eu(e,["uninstall",a.value],{allowFailure:!0});if(0!==n.exitCode){let e=`${n.stdout}
6
- ${n.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new i("COMMAND_FAILED",`adb uninstall failed for ${a.value}`,{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}return{package:a.value}}let e2=null;async function e9(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(e2?.key===e)return e2.invocation;if(await l("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return e2={key:e,invocation:t},t}let t=await s(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,"AGENT_DEVICE_BUNDLETOOL_JAR");if(!t)throw new i("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");let a={cmd:"java",prefixArgs:["-jar",t]};return e2={key:e,invocation:a},a}async function e4(e){let t=await e9();await o(t.cmd,[...t.prefixArgs,...e])}async function e3(n,i){let r=m(n),o="universal";if(r.installBundle)return void await r.installBundle(i,{mode:o});let s=await e.mkdtemp(a.join(t.tmpdir(),"agent-device-aab-")),l=a.join(s,"bundle.apks");try{await e4(["build-apks","--bundle",i,"--output",l,"--mode",o]),await e4(["install-apks","--apks",l,"--device-id",n.id])}finally{await e.rm(s,{recursive:!0,force:!0})}}async function e8(e,t){".aab"===a.extname(t).toLowerCase()?await e3(e,t):await w(t,{device:e,replace:!0})}async function e6(e){return new Set((await eu(e,["shell","pm","list","packages"])).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function e5(e,t){let a=Array.from(await e6(e)).filter(e=>!t.has(e));if(1===a.length)return a[0]}async function e7(e,t){await eN.invalidateWhile(eO(e),async()=>{e.booted||await ed(e.id),await e8(e,t)})}async function te(e,t,a){let n=a?void 0:await e6(e);return await e7(e,t),a??(n?await e5(e,n):void 0)}async function tt(e,t){e.booted||await ed(e.id);let a=await eA({kind:"path",path:t});try{let t=await te(e,a.installablePath,a.packageName),n=t?eE(t):void 0;return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:t,appName:n,launchTarget:t}}finally{await a.cleanup()}}async function ta(e,t,a){return await eN.invalidateWhile(eO(e),async()=>{e.booted||await ed(e.id);let{package:n}=await e1(e,t),i=await eA({kind:"path",path:a},{resolveIdentity:!1});try{await e7(e,i.installablePath)}finally{await i.cleanup()}return{package:n}})}async function tn(e,t={}){let a=["logcat","-d","-v","time"];void 0!==t.lines&&a.push("-t",String(Math.max(1,Math.floor(t.lines))));let n=await e(a,{allowFailure:!0,timeoutMs:t.timeoutMs,signal:t.signal});if(0!==n.exitCode)throw new i("COMMAND_FAILED","Failed to capture Android logcat",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});return n.stdout}function ti(e,t={}){if(!e.spawn)throw new i("UNSUPPORTED_OPERATION","Android ADB provider does not support streams",{capability:"adb.spawn"});let a=["logcat","-v","time"];t.pid&&a.push("--pid",t.pid);let n=e.spawn(a,{stdio:["ignore","pipe","pipe"],signal:t.signal});return t.output&&n.stdout&&n.stdout.pipe(t.output,{end:!1}),n}let tr=new Set(["com.google.android.inputmethod.latin","com.samsung.android.honeyboard","com.touchtype.swiftkey","com.microsoft.swiftkey"]);function to(e){let t=tl(e.packageName),a=(e.resourceId??"").toLowerCase(),n=tl(e.activeInputMethodPackage);if(t&&n&&t===n)return{inputMethodOwned:!0,source:"active-input-method"};if(n&&a.startsWith(`${n}:id/`))return{inputMethodOwned:!0,source:"active-input-method-resource"};if(t&&tr.has(t))return{inputMethodOwned:!0,source:"known-ime-package"};for(let e of tr)if(a.startsWith(`${e}:id/`))return{inputMethodOwned:!0,source:"known-ime-resource"};return{inputMethodOwned:!1,source:"app"}}function ts(e){return to(e).inputMethodOwned}function tl(e){return(e??"").trim().toLowerCase()||void 0}async function td(e){return await tu(h(e))}async function tu(e){let t=await e(["shell","dumpsys","input_method"],{allowFailure:!0});if(0!==t.exitCode)throw new i("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t,a=function(e){let t=new Map;for(let a of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=a[1],n=a[2]?.toLowerCase();e&&("true"===n||"false"===n)&&t.set(e,"true"===n)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),n=a??!1;if(null===a){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(n=(1&e)!=0)}}let i=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),o=i.length>0?i[i.length-1]?.[1]:void 0,s=o?`0x${o.toLowerCase()}`:void 0,l=tf(e,/\bpackageName=([A-Za-z0-9_.]+)\b/g),d=tf(e,/\b(?:resourceId|resource-id)=([^\s,}]+)/g),u=function(e){for(let t of[/\bmCurMethodId=([^\s]+)/i,/\bmCurId=([^\s]+)/i,/\bmCurrentInputMethodId=([^\s]+)/i,/\bcurMethodId=([^\s]+)/i]){let a=e.match(t),n=function(e){let t=(e??"").trim();if(!t)return;let a=(t.split("/")[0]??"").match(/[a-zA-Z0-9_.]+/);return tl(a?.[0])}(a?.[1]);if(n)return n}}(e),c=function(e,t,a){return e||t?to({packageName:e,resourceId:t,activeInputMethodPackage:a}).inputMethodOwned?"ime":"app":"unknown"}(l,d,u);return!u&&((t=tl(l))&&tr.has(t)||function(e){let t=(e??"").toLowerCase();for(let e of tr)if(t.startsWith(`${e}:id/`))return!0;return!1}(d))&&r({level:"warn",phase:"android_input_ownership_fallback",data:{focusedPackage:l,focusedResourceId:d}}),{visible:n,inputType:s,type:s?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let a=15&t;if(2===a)return"number";if(3===a)return"phone";if(4===a)return"datetime";if(1!==a)return"unknown";let n=4080&t;return 32===n||208===n?"email":128===n||224===n||144===n?"password":"text"}(s):void 0,inputMethodPackage:u,focusedPackage:l,focusedResourceId:d,inputOwner:c}}(t.stdout)}async function tc(e){return await tp(h(e))}async function tp(e){let t=await tu(e),a=t,n=0;for(;a.visible&&n<2;)await e(["shell","input","keyevent","111"]),n+=1,await p(120),a=await tu(e);if(t.visible&&a.visible)throw new i("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:n,inputType:a.inputType,type:a.type,inputMethodPackage:a.inputMethodPackage,focusedPackage:a.focusedPackage,focusedResourceId:a.focusedResourceId,inputOwner:a.inputOwner});return{attempts:n,wasVisible:t.visible,dismissed:t.visible&&!a.visible,visible:a.visible,inputType:a.inputType,type:a.type,inputMethodPackage:a.inputMethodPackage,focusedPackage:a.focusedPackage,focusedResourceId:a.focusedResourceId,inputOwner:a.inputOwner}}function tf(e,t){let a;for(let n of e.matchAll(t))a=n[1];return a}async function tm(e){return await tw(h(e))}async function tw(e){let t,a;return(a=(t=(await ty(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?a[1]??"":"null"===t.trim().toLowerCase()?"":t}async function th(e,t){await tA(h(e),t)}async function tA(e,t){await ty(e,["shell","cmd","clipboard","set","text",t],"write")}async function ty(e,t,a){var n,r;let o,s=await e(t,{allowFailure:!0});if(n=s.stdout,r=s.stderr,(o=`${n}
7
- ${r}`.toLowerCase()).includes("no shell command implementation")||o.includes("unknown command"))throw new i("UNSUPPORTED_OPERATION",`Android shell clipboard ${a} is not supported on this device.`);if(0!==s.exitCode)throw new i("COMMAND_FAILED",`Failed to ${a} Android clipboard text`,{stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode});return s.stdout}export{T as Deadline,ec as androidDeviceForSerial,V as bootFailureHint,tn as captureAndroidLogcatWithAdb,ew as classifyAndroidAppTarget,W as classifyBootFailure,e0 as closeAndroidApp,L as createAppResolutionCache,tc as dismissAndroidKeyboard,tp as dismissAndroidKeyboardWithAdb,ep as ensureAdb,el as ensureAndroidEmulatorBooted,eh as formatAndroidInstalledPackageRequiredMessage,eT as getAndroidAppState,eS as getAndroidBlockingDialogFocus,td as getAndroidKeyboardState,tu as getAndroidKeyboardStatusWithAdb,eE as inferAndroidAppName,tt as installAndroidApp,te as installAndroidInstallablePathAndResolvePackageName,eX as isAmStartError,ts as isAndroidInputMethodOwnedNode,C as isDeepLinkTarget,E as isEnvTruthy,eC as listAndroidApps,ea as listAndroidDevices,eU as openAndroidApp,eY as openAndroidDevice,N as parseAndroidForegroundApp,eQ as parseAndroidLaunchComponent,_ as parseAndroidLaunchablePackages,I as parseAndroidUserInstalledPackages,$ as parseSerialAllowlist,eA as prepareAndroidInstallArtifact,tm as readAndroidClipboardText,tw as readAndroidClipboardWithAdb,ta as reinstallAndroidApp,ek as resolveAndroidApp,B as resolveAndroidSerialAllowlist,D as resolveIosDeviceDeepLinkBundleId,U as resolveIosSimulatorDeviceSetPath,S as retryWithPolicy,eu as runAndroidAdb,ti as streamAndroidLogcatWithAdb,ed as waitForAndroidBoot,R as withRetry,th as writeAndroidClipboardText,tA as writeAndroidClipboardWithAdb};
1
+ import{promises as e}from"node:fs";import t from"node:os";import a from"node:path";import{asAppError as n,AppError as i}from"./9152.js";import{emitDiagnostic as r}from"./3622.js";import{runCmd as o,resolveFileOverridePath as s,whichCmd as l,runCmdDetached as d}from"./9818.js";import{ensureAndroidSdkPathConfigured as u,resolveAndroidArchivePackageName as c}from"./7651.js";import{sleep as p}from"./4829.js";import{createAndroidPortReverseManager as f,resolveAndroidAdbProvider as m,installAndroidAdbPackage as w,resolveAndroidAdbExecutor as h}from"./9639.js";import{materializeInstallablePath as A,isTrustedInstallSourceUrl as y}from"./989.js";let g=["mCurrentFocus=Window{","mFocusedApp=AppWindowToken{","mResumedActivity:","ResumedActivity:"],v=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,b=/([^{}]*\bis(?:n't| not)\s+responding[^{}]*)/i,M=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/;function _(e){let t=new Set;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;let n=e.split(/\s+/)[0]??"";if(!n.includes("/"))continue;let i=n.split("/")[0]??"";i.includes(".")&&i&&t.add(i)}return Array.from(t)}function I(e){return e.split("\n").map(e=>{let t=e.trim();return t.startsWith("package:")?t.slice(8):t}).filter(Boolean)}function O(e){return N(e,e=>(function(e){for(let t of e.trim().split(/\s+/)){let e=t.indexOf("/");if(e<=0)continue;let a=C(t.slice(0,e),!1),n=C(t.slice(e+1),!0);if(a&&n&&a.length===e)return{package:a,activity:n}}return null})(e))}function N(e,t){let a=e.split("\n");for(let e of g)for(let n of a){let a=n.indexOf(e);if(-1===a)continue;let i=n.trim(),r=t(n.slice(a+e.length),i);if(r)return r}return null}function C(e,t){let a=0;for(;a<e.length&&function(e,t){if(!e)return!1;let a=e.charCodeAt(0);return a>=48&&a<=57||a>=65&&a<=90||a>=97&&a<=122||"_"===e||"."===e||t&&"$"===e}(e[a],t);)a+=1;return e.slice(0,a)}function D(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let a=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!a)return!1;let n=a[1]?.toLowerCase(),i=a[2]??"";return"http"!==n&&"https"!==n&&"ws"!==n&&"wss"!==n&&"ftp"!==n&&"ftps"!==n||i.startsWith("//")}function k(e,t){let a,n=e?.trim();return n?n:"http"===(a=t.trim().split(":")[0]?.toLowerCase())||"https"===a?"com.apple.mobilesafari":void 0}function T(e={}){let t=e.ttlMs??3e4,a=e.nowMs??Date.now,n=new Map,i=e=>{var t;let a=[(t=e).platform,t.deviceId,""].join("\0");for(let e of n.keys())e.startsWith(a)&&n.delete(e)};return{get(e,t){let i=E(e,t),r=n.get(i);if(r)return r.expiresAtMs<=a()?void n.delete(i):r.value},set:(e,i,r)=>(n.set(E(e,i),{value:r,expiresAtMs:a()+t}),r),clear(e){i(e)},async invalidateWhile(e,t){i(e);try{return await t()}finally{i(e)}}}}function E(e,t){return[e.platform,e.deviceId,e.variant??"",t.trim().toLowerCase()].join("\0")}function L(e){return["1","true","yes","on"].includes((e??"").trim().toLowerCase())}class x{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new x(t,e)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return 0>=this.remainingMs(e)}}async function S(e,t={},a={}){let n,r={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=r.maxAttempts;t+=1){if(a.signal?.aborted)throw new i("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(a.deadline?.isExpired()&&t>1)break;try{let n=await e({attempt:t,maxAttempts:r.maxAttempts,deadline:a.deadline});return a.onEvent?.({phase:a.phase,event:"succeeded",attempt:t,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs()}),P({phase:a.phase,event:"succeeded",attempt:t,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs()}),n}catch(d){n=d;let e=a.classifyReason?.(d),i={phase:a.phase,event:"attempt_failed",attempt:t,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs(),reason:e};if(a.onEvent?.(i),P(i),t>=r.maxAttempts||r.shouldRetry&&!r.shouldRetry(d,t))break;let o=function(e,t,a,n){let i=Math.min(t,e*2**(n-1));return Math.max(0,i+i*a*(2*Math.random()-1))}(r.baseDelayMs,r.maxDelayMs,r.jitter,t),s=a.deadline?Math.min(o,a.deadline.remainingMs()):o;if(s<=0)break;let l={phase:a.phase,event:"retry_scheduled",attempt:t,maxAttempts:r.maxAttempts,delayMs:s,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs(),reason:e};a.onEvent?.(l),P(l),await function(e,t){return new Promise(a=>{if(t?.aborted)return void a();let n=!1,i=()=>{n||(n=!0,t&&t.removeEventListener("abort",o),a())},r=setTimeout(i,e);function o(){clearTimeout(r),i()}t&&t.addEventListener("abort",o,{once:!0})})}(s,a.signal)}}let o={phase:a.phase,event:"exhausted",attempt:r.maxAttempts,maxAttempts:r.maxAttempts,elapsedMs:a.deadline?.elapsedMs(),remainingMs:a.deadline?.remainingMs(),reason:a.classifyReason?.(n)};if(a.onEvent?.(o),P(o),n)throw n;throw new i("COMMAND_FAILED","retry failed")}async function R(e,t={}){return S(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function P(e){r({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}})}function U(e){return e?.trim()||void 0}function F(e){return U(e)}function B(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function $(e,t=process.env){let a=U(e)??U(t.AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST);if(a)return B(a)}let W=new Set(["IOS_BOOT_TIMEOUT","IOS_RUNNER_CONNECT_TIMEOUT","IOS_TOOL_MISSING","ANDROID_BOOT_TIMEOUT","ADB_TRANSPORT_UNAVAILABLE","CI_RESOURCE_STARVATION_SUSPECTED"]);function V(e){return W.has(e.toUpperCase())}function G(e){let t=e.error?n(e.error):null,a=e.context?.platform,i=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===a?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let r=t?.details??{},o="string"==typeof r.message?r.message:void 0,s="string"==typeof r.stdout?r.stdout:void 0,l="string"==typeof r.stderr?r.stderr:void 0,d=r.boot&&"object"==typeof r.boot?r.boot:null,u=r.bootstatus&&"object"==typeof r.bootstatus?r.bootstatus:null,c=[e.message,t?.message,e.stdout,e.stderr,o,s,l,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0,"string"==typeof u?.stdout?u.stdout:void 0,"string"==typeof u?.stderr?u.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===a&&(c.includes("runner did not accept connection")||"connect"===i&&(c.includes("timed out")||c.includes("timeout")||c.includes("econnrefused")||c.includes("connection refused")||c.includes("fetch failed")||c.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===a&&"boot"===i&&(c.includes("timed out")||c.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===a&&"boot"===i&&(c.includes("timed out")||c.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":c.includes("resource temporarily unavailable")||c.includes("killed: 9")||c.includes("cannot allocate memory")||c.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===a&&(c.includes("device not found")||c.includes("no devices")||c.includes("device offline")||c.includes("offline")||c.includes("unauthorized")||c.includes("not authorized")||c.includes("unable to locate device")||c.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||c.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function j(e){switch(e){case"IOS_BOOT_TIMEOUT":return"Retry simulator boot and inspect simctl bootstatus logs; in CI reduce parallel jobs or use a larger runner.";case"IOS_RUNNER_CONNECT_TIMEOUT":return"Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.";case"ANDROID_BOOT_TIMEOUT":return"Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.";case"ADB_TRANSPORT_UNAVAILABLE":return"Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.";case"CI_RESOURCE_STARVATION_SUSPECTED":return"CI machine may be resource constrained; reduce parallel jobs or use a larger runner.";case"IOS_TOOL_MISSING":return"Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.";case"BOOT_COMMAND_FAILED":return"Inspect command stderr/stdout for the failing boot phase and retry after environment validation.";default:return"Retry once and inspect verbose logs for the failing phase."}}let K=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];async function H(e,t,a){let n=Array(e.length),i=0,r=Math.min(t,e.length);return await Promise.all(Array.from({length:r},async()=>{for(;i<e.length;){let t=i;i+=1,n[t]=await a(e[t])}})),n}function z(e){return`${e.stdout}
2
+ ${e.stderr}`}function q(e,t){return["-s",e,...t]}function Z(e){return e.startsWith("emulator-")}function J(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function X(e,t=1e4){return o("adb",q(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function Q(e,t){let a=t.replace(/_/g," ").trim();if(!Z(e))return a||e;let n=await ee(e);return n?n.replace(/_/g," "):a||e}async function Y(e,t,a){try{return await a("adb",q(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var i;if("COMMAND_FAILED"===(i=n(e)).code&&"number"==typeof i.details?.timeoutMs)return;throw e}}async function ee(e,t=o){for(let a of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let n=await Y(e,["shell","getprop",a],t);if(!n)continue;let i=n.stdout.trim();if(0===n.exitCode&&i.length>0)return i}let a=await Y(e,["emu","avd","name"],t);if(!a)return;let n=function(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}(a.stdout);if(0===a.exitCode&&n)return n}async function et(e,t){let a=z(await o("adb",q(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:1e4})).toLowerCase();return!!a.includes("true")||!a.includes("false")&&null}async function ea(e){return(await H(K,2,async t=>await et(e,t))).some(e=>!0===e)}async function en(e){var t;let a;return"tv"===((a=z(await o("adb",q(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:1e4})).toLowerCase()).includes("tv")||a.includes("leanback")?"tv":null)||await ea(e)?"tv":(t=z(await o("adb",q(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:1e4})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function ei(e={}){if(await u(),!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??$(void 0),a=(await er()).filter(e=>!t||t.has(e.serial));return await H(a,3,async({serial:e,rawModel:t})=>{let[a,n,i]=await Promise.all([Q(e,t),ed(e),en(e)]);return{platform:"android",id:e,name:a,kind:Z(e)?"emulator":"device",target:i,booted:n}})}async function er(){return(await o("adb",["devices","-l"],{timeoutMs:1e4})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).flatMap(e=>{let t=e[0];return void 0===t||"device"!==e[1]?[]:[{serial:t,rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}]})}async function eo(){let e=await o("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:1e4});if(0!==e.exitCode)throw new i("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function es(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await el(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await p(1e3)}throw new i("COMMAND_FAILED","Android emulator did not appear in time",{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:"Check emulator logs and verify the AVD can start from command line."})}async function el(e,t){let a=J(e);for(let e of(await er()).filter(e=>(!t||e.serial===t)&&Z(e.serial)))if(J(e.rawModel)===a||J(await Q(e.serial,e.rawModel))===a)return e.serial}async function ed(e){try{let t=await X(e);return"1"===t.stdout.trim()}catch{return!1}}async function eu(e){var t,a;let n;await u();let r=e.avdName.trim();if(!r)throw new i("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let o=e.timeoutMs??12e4;if(!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH");if(!await l("emulator"))throw new i("TOOL_MISSING","emulator not found in PATH");let s=await eo(),c=function(e,t){let a=e.find(e=>e===t);if(a)return a;let n=J(t);return e.find(e=>J(e)===n)}(s,r);if(!c)throw new i("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:r,availableAvds:s,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let p=Date.now(),f=(t=await ei(),a=e.serial,n=J(c),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!a||e.id===a)&&J(e.name)===n));if(!f){let t=["-avd",c];e.headless&&t.push("-no-window","-no-audio"),d("emulator",t)}let m=f??await es({avdName:c,serial:e.serial,timeoutMs:o}),w=Math.max(1e3,o-(Date.now()-p));await ec(m.id,w);let h=(await ei()).find(e=>e.id===m.id);return h?{...h,name:c,booted:!0}:{...m,name:c,booted:!0}}async function ec(e,t=6e4){let a,r=x.fromTimeoutMs(t),o=Math.max(1,Math.ceil(t/1e3)),s=!1;try{await S(async({deadline:n})=>{if(n?.isExpired())throw s=!0,new i("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:r.elapsedMs(),message:"timeout"});let o=Math.max(1e3,n?.remainingMs()??t),l=await X(e,Math.min(o,1e4));if(a=l,"1"!==l.stdout.trim())throw new i("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode})},{maxAttempts:o,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=G({error:e,stdout:a?.stdout,stderr:a?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:r,phase:"boot",classifyReason:e=>G({error:e,stdout:a?.stdout,stderr:a?.stderr,context:{platform:"android",phase:"boot"}})})}catch(f){let o=n(f),l=a?.stdout,d=a?.stderr,u=a?.exitCode,c=G({error:f,stdout:l,stderr:d,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===c&&"Android device is still booting"===o.message&&(c="ANDROID_BOOT_TIMEOUT");let p={serial:e,timeoutMs:t,elapsedMs:r.elapsedMs(),reason:c,hint:j(c),stdout:l,stderr:d,exitCode:u};if(s||"ANDROID_BOOT_TIMEOUT"===c)throw new i("COMMAND_FAILED","Android device did not finish booting in time",p);if("TOOL_MISSING"===o.code)throw new i("TOOL_MISSING",o.message,{...p,...o.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===c)throw new i("COMMAND_FAILED",o.message,{...p,...o.details??{}});throw new i(o.code,o.message,{...p,...o.details??{}},o.cause)}}async function ep(e,t,a){return await h(e)(t,a)}function ef(e){return{platform:"android",id:e,name:e,kind:e.startsWith("emulator-")?"emulator":"device",booted:!0}}async function em(){if(await u(),!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH")}let ew=/\.(?:apk|aab)$/i,eh=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function eA(e){var t,a;let n=e.trim();return 0===n.length?"other":ew.test(n)?n.includes("/")||n.includes("\\")||n.startsWith(".")||n.startsWith("~")||(t=n,!eh.test(t))?"binary":"package":(a=n,eh.test(a))?"package":"other"}function ey(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}async function eg(e,t){let n="url"===e.kind&&y(e.url),i=await A({source:e,isInstallablePath:(e,t)=>{var n;let i;return t.isFile()&&(n=e,".apk"===(i=a.extname(n).toLowerCase())||".aab"===i)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await ev(i.installablePath);return{archivePath:i.archivePath,installablePath:i.installablePath,packageName:e.packageName,cleanup:i.cleanup}}catch(e){throw await i.cleanup(),e}}async function ev(e){let t=a.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await c(e)}}let eb={settings:{type:"intent",value:"android.settings.SETTINGS"}},eM="android.intent.category.LAUNCHER",e_="android.intent.category.LEANBACK_LAUNCHER",eI="android.intent.category.DEFAULT",eO="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.",eN=new Set(["localhost","127.0.0.1","::1","[::1]"]),eC=T();function eD(e){return{platform:"android",deviceId:e.id,variant:e.target??""}}async function ek(e,t){let a=t.trim();if("package"===eA(a))return{type:"package",value:a};let n=eb[a.toLowerCase()];if(n)return n;let r=eD(e),o=eC.get(r,a);if(o)return o;let s=(await ep(e,["shell","pm","list","packages"])).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(a.toLowerCase())),l=s[0];if(void 0!==l&&1===s.length)return eC.set(r,a,{type:"package",value:l});if(s.length>1)throw new i("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:s,hint:"Run agent-device apps --platform android to see the exact installed package names before retrying open."});throw new i("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:eO})}async function eT(e,t){let a=await eE(e);return("user-installed"===t?(await ex(e)).filter(e=>a.has(e)):Array.from(a)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:eS(e)}))}async function eE(e){let t=new Set;for(let a of eL(e,{includeFallbackWhenUnknown:!0})){let n=await ep(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",a],{allowFailure:!0});if(0===n.exitCode&&0!==n.stdout.trim().length)for(let e of _(n.stdout))t.add(e)}return t}function eL(e,t={}){return"tv"===e.target?[e_]:"mobile"===e.target?[eM]:t.includeFallbackWhenUnknown?[eM,e_]:[eM]}async function ex(e){return I((await ep(e,["shell","pm","list","packages","-3"])).stdout)}function eS(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),a=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),n=a[a.length-1]??e;for(let e=a.length-1;e>=0;e-=1){let i=a[e];if(i&&!t.has(i)){n=i;break}}return n.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function eR(e){let t=await eU(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let a=await eU(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return a||{}}async function eP(e){return await eF(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]])}async function eU(e,t){for(let a of t){let t=O((await ep(e,a,{allowFailure:!0})).stdout??"");if(t)return t}return null}async function eF(e,t){for(let a of t){let t=N((await ep(e,a,{allowFailure:!0})).stdout??"",(e,t)=>(function(e,t){let a=e.split("}")[0]?.trim()??e.trim(),n=v.exec(a);if(n){let e=n[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=b.exec(a);if(!i)return null;let r=i[1];if(void 0===r)return null;let o=r.trim().replace(/\s+/g," "),s=M.exec(o)?.[1];return{...s?{package:s}:{},focusedWindow:o,raw:t}})(e,t));if(t)return t}return null}async function eB(e,t){let a=function(e){let t;try{t=new URL(e)}catch{return null}let a=t.hostname.toLowerCase();if(!eN.has(a)||!t.port)return null;let n=Number(t.port);return Number.isInteger(n)?`tcp:${n}`:null}(t);if(!a)return;let n=f(m(e));try{await n.ensure({local:a,remote:a})}catch(t){let e={localPort:a.replace("tcp:",""),operation:`adb reverse ${a} ${a}`};throw t instanceof i&&Object.assign(e,{hint:t.details?.hint,diagnosticId:t.details?.diagnosticId,logPath:t.details?.logPath}),new i("COMMAND_FAILED",`Failed to ensure Android port reverse ${a} before opening localhost URL`,e,t)}}async function e$(e,t,a){var n;e.booted||await ec(e.id);let i="string"==typeof(n=a)?{activity:n}:n??{},r=i.activity,o=t.trim();if(D(o))return void await eW(e,o,i);if(void 0!==i.url)return void await eV(e,t,i);let s=await ek(e,t),l=eL(e)[0]??eM;"intent"===s.type?await eG(e,s.value,r):r?await ej(e,s.value,r,l):await eK(e,s.value,l)}async function eW(e,t,a){var n;let r;if(a.activity)throw new i("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await eB(e,t),await ep(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",t,...(n=a.appBundleId,(r=n?.trim())?["-p",r]:[])])}async function eV(e,t,a){if(a.activity)throw new i("INVALID_ARGS","Activity override is not supported when opening an app-bound deep link URL");let n=a.url?.trim()??"";if(!D(n))throw new i("INVALID_ARGS","Android app-bound open requires a valid URL target");let r=await ez(e,t,"app-bound open");await ep(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",n,"-p",r])}async function eG(e,t,a){if(a)throw new i("INVALID_ARGS","Activity override requires a package name, not an intent");await ep(e,["shell","am","start","-W","-a",t])}async function ej(e,t,a,n){let i=a.includes("/")?a:`${t}/${a.startsWith(".")?a:`.${a}`}`;try{await ep(e,eH(i,n))}catch(a){throw await eJ(e,t,a),a}}async function eK(e,t,a){let n=await ep(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eI,"-c",a,"-p",t],{allowFailure:!0});if(0===n.exitCode&&!eY(n.stdout,n.stderr))return;let r=await eQ(e,t);if(!r){if(!await eZ(e,t))throw eq(t);throw new i("COMMAND_FAILED",`Failed to launch ${t}`,{stdout:n.stdout,stderr:n.stderr})}await ep(e,eH(r,a))}function eH(e,t){return["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eI,"-c",t,"-n",e]}async function ez(e,t,a){let n=await ek(e,t);if("intent"===n.type)throw new i("INVALID_ARGS",`Android ${a} requires a package name, not an intent`);return n.value}function eq(e){return new i("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:eO})}async function eZ(e,t){let a=await ep(e,["shell","pm","path",t],{allowFailure:!0}),n=`${a.stdout}
3
+ ${a.stderr}`;return!!(0===a.exitCode&&/\bpackage:/i.test(n))||(eX(n),!1)}async function eJ(e,t,a){if(eX(a instanceof i?`${String(a.details?.stdout??"")}
4
+ ${String(a.details?.stderr??"")}`:"")||!await eZ(e,t))throw eq(t)}function eX(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function eQ(e,t){for(let a of Array.from(new Set(eL(e,{includeFallbackWhenUnknown:!0})))){let n=await ep(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",a,t],{allowFailure:!0});if(0!==n.exitCode)continue;let i=e0(n.stdout);if(i)return i}return null}function eY(e,t){let a=`${e}
5
+ ${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(a)}function e0(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let a=t[e];if(void 0===a||!a.includes("/"))continue;let n=a.split(/\s+/)[0];if(void 0!==n)return n}return null}async function e1(e){e.booted||await ec(e.id)}async function e2(e,t){if("settings"===t.trim().toLowerCase())return void await ep(e,["shell","am","force-stop","com.android.settings"]);let a=await ek(e,t);if("intent"===a.type)throw new i("INVALID_ARGS","Close requires a package name, not an intent");await ep(e,["shell","am","force-stop",a.value])}async function e9(e,t){let a=await ek(e,t);if("intent"===a.type)throw new i("INVALID_ARGS","App uninstall requires a package name, not an intent");let n=await ep(e,["uninstall",a.value],{allowFailure:!0});if(0!==n.exitCode){let e=`${n.stdout}
6
+ ${n.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new i("COMMAND_FAILED",`adb uninstall failed for ${a.value}`,{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}return{package:a.value}}let e4=null;async function e3(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(e4?.key===e)return e4.invocation;if(await l("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return e4={key:e,invocation:t},t}let t=await s(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,"AGENT_DEVICE_BUNDLETOOL_JAR");if(!t)throw new i("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");let a={cmd:"java",prefixArgs:["-jar",t]};return e4={key:e,invocation:a},a}async function e8(e){let t=await e3();await o(t.cmd,[...t.prefixArgs,...e])}async function e6(n,i){let r=m(n),o="universal";if(r.installBundle)return void await r.installBundle(i,{mode:o});let s=await e.mkdtemp(a.join(t.tmpdir(),"agent-device-aab-")),l=a.join(s,"bundle.apks");try{await e8(["build-apks","--bundle",i,"--output",l,"--mode",o]),await e8(["install-apks","--apks",l,"--device-id",n.id])}finally{await e.rm(s,{recursive:!0,force:!0})}}async function e5(e,t){".aab"===a.extname(t).toLowerCase()?await e6(e,t):await w(t,{device:e,replace:!0})}async function e7(e){return new Set((await ep(e,["shell","pm","list","packages"])).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function te(e,t){let a=Array.from(await e7(e)).filter(e=>!t.has(e));if(1===a.length)return a[0]}async function tt(e,t){await eC.invalidateWhile(eD(e),async()=>{e.booted||await ec(e.id),await e5(e,t)})}async function ta(e,t,a){let n=a?void 0:await e7(e);return await tt(e,t),a??(n?await te(e,n):void 0)}async function tn(e,t){e.booted||await ec(e.id);let a=await eg({kind:"path",path:t});try{let t=await ta(e,a.installablePath,a.packageName),n=t?eS(t):void 0;return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:t,appName:n,launchTarget:t}}finally{await a.cleanup()}}async function ti(e,t,a){return await eC.invalidateWhile(eD(e),async()=>{e.booted||await ec(e.id);let{package:n}=await e9(e,t),i=await eg({kind:"path",path:a},{resolveIdentity:!1});try{await tt(e,i.installablePath)}finally{await i.cleanup()}return{package:n}})}async function tr(e,t={}){let a=["logcat","-d","-v","time"];void 0!==t.lines&&a.push("-t",String(Math.max(1,Math.floor(t.lines))));let n=await e(a,{allowFailure:!0,timeoutMs:t.timeoutMs,signal:t.signal});if(0!==n.exitCode)throw new i("COMMAND_FAILED","Failed to capture Android logcat",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});return n.stdout}function to(e,t={}){if(!e.spawn)throw new i("UNSUPPORTED_OPERATION","Android ADB provider does not support streams",{capability:"adb.spawn"});let a=["logcat","-v","time"];t.pid&&a.push("--pid",t.pid);let n=e.spawn(a,{stdio:["ignore","pipe","pipe"],signal:t.signal});return t.output&&n.stdout&&n.stdout.pipe(t.output,{end:!1}),n}let ts=new Set(["com.google.android.inputmethod.latin","com.samsung.android.honeyboard","com.touchtype.swiftkey","com.microsoft.swiftkey"]);function tl(e){let t=tu(e.packageName),a=(e.resourceId??"").toLowerCase(),n=tu(e.activeInputMethodPackage);if(t&&n&&t===n)return{inputMethodOwned:!0,source:"active-input-method"};if(n&&a.startsWith(`${n}:id/`))return{inputMethodOwned:!0,source:"active-input-method-resource"};if(t&&ts.has(t))return{inputMethodOwned:!0,source:"known-ime-package"};for(let e of ts)if(a.startsWith(`${e}:id/`))return{inputMethodOwned:!0,source:"known-ime-resource"};return{inputMethodOwned:!1,source:"app"}}function td(e){return tl(e).inputMethodOwned}function tu(e){return(e??"").trim().toLowerCase()||void 0}async function tc(e){return await tp(h(e))}async function tp(e){let t=await e(["shell","dumpsys","input_method"],{allowFailure:!0});if(0!==t.exitCode)throw new i("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t,a=function(e){let t=new Map;for(let a of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=a[1],n=a[2]?.toLowerCase();e&&("true"===n||"false"===n)&&t.set(e,"true"===n)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),n=a??!1;if(null===a){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(n=(1&e)!=0)}}let i=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),o=i.length>0?i[i.length-1]?.[1]:void 0,s=o?`0x${o.toLowerCase()}`:void 0,l=tw(e,/\bpackageName=([A-Za-z0-9_.]+)\b/g),d=tw(e,/\b(?:resourceId|resource-id)=([^\s,}]+)/g),u=function(e){for(let t of[/\bmCurMethodId=([^\s]+)/i,/\bmCurId=([^\s]+)/i,/\bmCurrentInputMethodId=([^\s]+)/i,/\bcurMethodId=([^\s]+)/i]){let a=e.match(t),n=function(e){let t=(e??"").trim();if(!t)return;let a=(t.split("/")[0]??"").match(/[a-zA-Z0-9_.]+/);return tu(a?.[0])}(a?.[1]);if(n)return n}}(e),c=function(e,t,a){return e||t?tl({packageName:e,resourceId:t,activeInputMethodPackage:a}).inputMethodOwned?"ime":"app":"unknown"}(l,d,u);return!u&&((t=tu(l))&&ts.has(t)||function(e){let t=(e??"").toLowerCase();for(let e of ts)if(t.startsWith(`${e}:id/`))return!0;return!1}(d))&&r({level:"warn",phase:"android_input_ownership_fallback",data:{focusedPackage:l,focusedResourceId:d}}),{visible:n,inputType:s,type:s?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let a=15&t;if(2===a)return"number";if(3===a)return"phone";if(4===a)return"datetime";if(1!==a)return"unknown";let n=4080&t;return 32===n||208===n?"email":128===n||224===n||144===n?"password":"text"}(s):void 0,inputMethodPackage:u,focusedPackage:l,focusedResourceId:d,inputOwner:c}}(t.stdout)}async function tf(e){return await tm(h(e))}async function tm(e){let t=await tp(e),a=t,n=0;for(;a.visible&&n<2;)await e(["shell","input","keyevent","111"]),n+=1,await p(120),a=await tp(e);if(t.visible&&a.visible)throw new i("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:n,inputType:a.inputType,type:a.type,inputMethodPackage:a.inputMethodPackage,focusedPackage:a.focusedPackage,focusedResourceId:a.focusedResourceId,inputOwner:a.inputOwner});return{attempts:n,wasVisible:t.visible,dismissed:t.visible&&!a.visible,visible:a.visible,inputType:a.inputType,type:a.type,inputMethodPackage:a.inputMethodPackage,focusedPackage:a.focusedPackage,focusedResourceId:a.focusedResourceId,inputOwner:a.inputOwner}}function tw(e,t){let a;for(let n of e.matchAll(t))a=n[1];return a}async function th(e){return await tA(h(e))}async function tA(e){let t,a;return(a=(t=(await tv(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?a[1]??"":"null"===t.trim().toLowerCase()?"":t}async function ty(e,t){await tg(h(e),t)}async function tg(e,t){await tv(e,["shell","cmd","clipboard","set","text",t],"write")}async function tv(e,t,a){var n,r;let o,s=await e(t,{allowFailure:!0});if(n=s.stdout,r=s.stderr,(o=`${n}
7
+ ${r}`.toLowerCase()).includes("no shell command implementation")||o.includes("unknown command"))throw new i("UNSUPPORTED_OPERATION",`Android shell clipboard ${a} is not supported on this device.`);if(0!==s.exitCode)throw new i("COMMAND_FAILED",`Failed to ${a} Android clipboard text`,{stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode});return s.stdout}export{x as Deadline,ef as androidDeviceForSerial,j as bootFailureHint,tr as captureAndroidLogcatWithAdb,eA as classifyAndroidAppTarget,G as classifyBootFailure,e2 as closeAndroidApp,T as createAppResolutionCache,tf as dismissAndroidKeyboard,tm as dismissAndroidKeyboardWithAdb,em as ensureAdb,eu as ensureAndroidEmulatorBooted,ey as formatAndroidInstalledPackageRequiredMessage,eR as getAndroidAppState,eP as getAndroidBlockingDialogFocus,tc as getAndroidKeyboardState,tp as getAndroidKeyboardStatusWithAdb,eS as inferAndroidAppName,tn as installAndroidApp,ta as installAndroidInstallablePathAndResolvePackageName,eY as isAmStartError,td as isAndroidInputMethodOwnedNode,D as isDeepLinkTarget,L as isEnvTruthy,V as isInfrastructureBootFailureReason,eT as listAndroidApps,ei as listAndroidDevices,e$ as openAndroidApp,e1 as openAndroidDevice,O as parseAndroidForegroundApp,e0 as parseAndroidLaunchComponent,_ as parseAndroidLaunchablePackages,I as parseAndroidUserInstalledPackages,B as parseSerialAllowlist,eg as prepareAndroidInstallArtifact,th as readAndroidClipboardText,tA as readAndroidClipboardWithAdb,ti as reinstallAndroidApp,ek as resolveAndroidApp,$ as resolveAndroidSerialAllowlist,k as resolveIosDeviceDeepLinkBundleId,F as resolveIosSimulatorDeviceSetPath,S as retryWithPolicy,ep as runAndroidAdb,to as streamAndroidLogcatWithAdb,ec as waitForAndroidBoot,R as withRetry,ty as writeAndroidClipboardText,tg as writeAndroidClipboardWithAdb};
package/dist/src/89.js CHANGED
@@ -1 +1 @@
1
- var t;let e;import{DEFAULT_BATCH_MAX_STEPS as r}from"./1231.js";import{jsonSchemaField as a,stringField as i,batchCommandNames as n,toSelectorSnapshotOptions as o,booleanSchema as s,integerSchema as p,assertAllowedKeys as c,requiredEnum as d,looseObjectField as l,requiredField as u,listMcpExposedCommandNames as m,readFieldInput as h,commonToClientOptions as g,integerField as f,numberField as y,booleanField as b,readInputRecord as v,repeatedFields as w,stringSchema as x,stringArrayField as M,toClientElementTarget as S,customField as k,optionalEnum as I,enumField as P,toRepeatedOptions as R,pointField as U,command_input_readPoint as C,toClientInteractionTarget as E,interactionTargetField as T,fieldsInputSchema as j,requiredNumber as A,selectorSnapshotFields as F,elementTargetField as N,readCommonInput as O,looseObjectSchema as B,optionalInteger as H}from"./2099.js";function D(t){return{...t,invoke:async(e,r)=>await t.run(e,t.readInput(r))}}function L(t,e,r,a){return D({name:t,description:e,inputSchema:j(r),readInput:t=>h(t,r),run:a})}let _=["app","frontmost-app","desktop","menubar"],$=["duration","text","ref","selector"],G=["start","stop"],q=[L("devices","List available devices.",{},(t,e)=>t.devices.list(e)),L("boot","Boot or prepare a selected device without using CLI positional arguments.",{headless:b("Boot without showing simulator UI when supported.")},(t,e)=>t.devices.boot(e)),L("apps","List installed apps.",{appsFilter:P(["user-installed","all"])},(t,e)=>t.apps.list(e)),L("session","List active sessions.",{action:P(["list"])},async(t,{action:e,...r})=>({sessions:await t.sessions.list(r)})),L("open","Open an app, deep link, URL, or platform surface.",{app:i("App name, bundle id, package, or URL."),url:i("Optional URL passed with an app shell."),surface:P(_),activity:i("Android activity name."),launchConsole:i("Launch console mode."),relaunch:b("Force relaunch."),saveScript:a({oneOf:[s(),x()]}),noRecord:b("Do not record this action.")},(t,e)=>t.apps.open(e)),L("close","Close an app or end the active session.",{app:i("Optional app to close."),shutdown:b("Shutdown the session/device where supported."),saveScript:a({oneOf:[s(),x()]})},(t,e)=>e.app?t.apps.close(e):t.sessions.close(function(t){let{app:e,...r}=t;return r}(e))),L("install","Install an app binary.",{app:u(i()),appPath:u(i("Path to app binary."))},(t,e)=>t.apps.install(e)),L("reinstall","Reinstall an app binary.",{app:u(i()),appPath:u(i("Path to app binary."))},(t,e)=>t.apps.reinstall(e)),L("install-from-source","Install an app from a structured source.",{source:u(a(B("Install source object."))),retainPaths:b(),retentionMs:f()},(t,e)=>t.apps.installFromSource(e)),L("push","Deliver a push payload.",{app:u(i()),payload:u(a({oneOf:[x(),B()]}))},(t,e)=>t.apps.push(e)),L("trigger-app-event","Trigger an app-defined event.",{event:u(i()),payload:l()},(t,e)=>t.apps.triggerEvent(e)),L("snapshot","Capture an accessibility snapshot.",{interactiveOnly:b(),compact:b(),depth:f(),scope:i(),raw:b(),forceFull:b()},(t,e)=>t.capture.snapshot(e)),L("screenshot","Capture a screenshot.",{path:i("Output path."),overlayRefs:b(),fullscreen:b(),maxSize:f(),stabilize:b(),surface:P(_)},(t,e)=>t.capture.screenshot(e)),L("diff","Diff accessibility snapshots.",{kind:u(a({type:"string",const:"snapshot"})),out:i(),interactiveOnly:b(),compact:b(),depth:f(),scope:i(),raw:b()},(t,e)=>t.capture.diff(e)),L("wait","Wait for duration, text, ref, or selector.",{kind:P($),durationMs:f(),text:i(),ref:i(),selector:i(),timeoutMs:f(),depth:f(),scope:i(),raw:b()},(t,e)=>{var r;let a;return t.command.wait((I(r=e,"kind",$),a={...r},delete a.kind,a))}),L("alert","Inspect or handle platform alerts.",{action:P(["get","accept","dismiss","wait"]),timeoutMs:f()},(t,e)=>t.command.alert(e)),L("appstate","Show foreground app or activity.",{},(t,e)=>t.command.appState(e)),L("back","Navigate back.",{mode:P(["in-app","system"])},(t,e)=>t.command.back(e)),L("home","Go to the home screen.",{},(t,e)=>t.command.home(e)),L("rotate","Rotate device orientation.",{orientation:u(P(["portrait","portrait-upside-down","landscape-left","landscape-right"]))},(t,e)=>t.command.rotate(e)),L("app-switcher","Open the app switcher.",{},(t,e)=>t.command.appSwitcher(e)),L("keyboard","Inspect or dismiss the keyboard.",{action:P(["status","dismiss"])},(t,e)=>t.command.keyboard(e)),L("clipboard","Read or write clipboard text.",{action:u(P(["read","write"])),text:i()},(t,e)=>t.command.clipboard(e)),L("react-native","Run supported React Native app automation helpers.",{action:u(P(["dismiss-overlay"]))},(t,e)=>t.command.reactNative(e)),L("replay","Replay a recorded session.",{path:u(i()),update:b(),backend:i(),env:M()},(t,e)=>t.replay.run(e)),L("test","Run one or more .ad scripts.",{paths:u(M()),update:b(),env:M(),failFast:b(),timeoutMs:f(),retries:f(),artifactsDir:i(),reportJunit:i()},(t,e)=>t.replay.test(e)),L("perf","Show session performance metrics.",{},(t,e)=>t.observability.perf(e)),L("logs","Manage session app logs.",{action:P(["path","start","stop","doctor","mark","clear"]),message:i(),restart:b()},(t,e)=>t.observability.logs(e)),L("network","Show recent HTTP traffic.",{action:P(["dump","log"]),limit:f(),include:P(["summary","headers","body","all"])},(t,e)=>t.observability.network(e)),L("record","Start or stop screen recording.",{action:u(P(G)),path:i(),fps:f(),quality:a(p()),hideTouches:b()},(t,e)=>t.recording.record(e)),L("trace","Start or stop trace capture.",{action:u(P(G)),path:i()},(t,e)=>t.recording.trace(e)),L("settings","Change OS settings and app permissions.",{setting:u(i()),state:u(i()),latitude:y(),longitude:y(),permission:i(),mode:P(["full","limited"])},(t,e)=>t.settings.update(e)),L("metro","Prepare Metro runtime or reload React Native apps.",{action:u(P(["prepare","reload"])),projectRoot:i(),kind:a(x()),publicBaseUrl:i(),proxyBaseUrl:i(),bearerToken:i(),bridgeScope:a({type:"object",additionalProperties:!0}),launchUrl:i(),port:f(),listenHost:i(),statusHost:i(),startupTimeoutMs:f(),probeTimeoutMs:f(),reuseExisting:b(),installDependenciesIfNeeded:b(),runtimeFilePath:i(),logPath:i(),metroHost:i(),metroPort:f(),bundleUrl:i(),timeoutMs:f()},async(t,e)=>{var r,a,i;return"prepare"===e.action?await t.metro.prepare({projectRoot:(r=e).projectRoot,kind:r.kind,publicBaseUrl:r.publicBaseUrl,proxyBaseUrl:r.proxyBaseUrl,bearerToken:r.bearerToken,bridgeScope:r.bridgeScope??((a=r).tenant&&a.runId&&a.leaseId?{tenantId:a.tenant,runId:a.runId,leaseId:a.leaseId}:void 0),port:r.port,listenHost:r.listenHost,statusHost:r.statusHost,startupTimeoutMs:r.startupTimeoutMs,probeTimeoutMs:r.probeTimeoutMs,reuseExisting:r.reuseExisting,installDependenciesIfNeeded:r.installDependenciesIfNeeded,runtimeFilePath:r.runtimeFilePath}):await t.metro.reload({metroHost:(i=e).metroHost,metroPort:i.metroPort,bundleUrl:i.bundleUrl,timeoutMs:i.timeoutMs})})],K=["pan","fling","pinch","rotate","transform"],z=["up","down","left","right"],J={target:u(T()),button:P(["primary","secondary","middle"],"Pointer button for platforms that support mouse buttons."),...F(),...w()},W={target:u(T()),...F(),...w()},X={target:u(T()),text:u(i("Text to enter into the target.")),delayMs:f("Delay between typed characters.",{min:0}),...F()},Y={target:u(T()),durationMs:f("Long press duration in milliseconds.",{min:0}),...F()},Q={from:u(U("Swipe start point.")),to:u(U("Swipe end point.")),durationMs:f("Swipe duration in milliseconds.",{min:0}),count:f("Number of swipe repetitions.",{min:1}),pauseMs:f("Pause between repeated swipes.",{min:0}),pattern:P(["one-way","ping-pong"])},V={x:u(y("X coordinate.")),y:u(y("Y coordinate."))},Z={text:u(i("Text to type.")),delayMs:f("Delay between typed characters.",{min:0})},tt={direction:u(P(["up","down","left","right","top","bottom"])),amount:y("Platform scroll amount."),pixels:f("Pixel scroll amount.",{min:0})},te={format:u(P(["text","attrs"])),target:u(N()),...F()},tr={predicate:u(P(["visible","hidden","exists","editable","selected","text"])),selector:u(i()),value:i(),...F()},ta={locator:P(["any","text","label","value","role","id"]),query:u(i()),action:P(["click","focus","exists","getText","getAttrs","wait","fill","type"]),value:i(),timeoutMs:f(),first:b(),last:b(),depth:f(),raw:b()},ti={kind:u(P(K,"Gesture variant.")),direction:P(z,"Fling direction."),origin:U("Gesture origin point."),delta:U("Movement delta for pan or transform gestures."),distance:f("Fling distance.",{min:0}),scale:y("Pinch or transform scale."),degrees:y("Rotation in degrees."),velocity:f("Rotate gesture velocity.",{min:0}),durationMs:f("Gesture duration in milliseconds.",{min:0})};function tn(t,e){return void 0===t[e]?void 0:C(t,e)}let to=[D({name:"click",description:"Click or tap a semantic UI target by ref, selector, or point.",inputSchema:j(J),readInput:t=>h(t,J),run:(t,e)=>{var r;return t.interactions.click({...g(r=e),...E(r.target),...o(r),...R(r),button:r.button})}}),D({name:"press",description:"Press a semantic UI target by ref, selector, or point.",inputSchema:j(W),readInput:t=>h(t,W),run:(t,e)=>{var r;return t.interactions.press({...g(r=e),...E(r.target),...o(r),...R(r)})}}),D({name:"fill",description:"Fill text into a semantic UI target by ref, selector, or point.",inputSchema:j(X),readInput:t=>h(t,X),run:(t,e)=>{var r;return t.interactions.fill({...g(r=e),...E(r.target),...o(r),text:r.text,delayMs:r.delayMs})}}),L("longpress","Long press by ref, selector, or point.",Y,(t,e)=>{var r;return t.interactions.longPress({...g(r=e),...E(r.target),...o(r),durationMs:r.durationMs})}),L("swipe","Swipe between two points.",Q,(t,e)=>t.interactions.swipe(e)),L("focus","Focus input at coordinates.",V,(t,e)=>t.interactions.focus(e)),L("type","Type text in the focused field.",Z,(t,e)=>t.interactions.type(e)),L("scroll","Scroll in a direction or to an edge.",tt,(t,e)=>t.interactions.scroll(e)),L("get","Get element text or attributes.",te,(t,e)=>{var r;return t.interactions.get({...g(r=e),...S(r.target),...o(r),format:r.format})}),L("is","Assert UI state.",tr,(t,e)=>t.interactions.is(e)),L("find","Find an element and optionally act on it.",ta,(t,e)=>t.interactions.find(e)),D({name:"gesture",description:"Run a structured gesture.",inputSchema:j(ti),readInput:function(t){let e=v(t),r=O(e),a=d(e,"kind",K);return"pan"===a?{...r,kind:a,origin:C(e,"origin"),delta:C(e,"delta"),durationMs:H(e,"durationMs",{min:0})}:"fling"===a?{...r,kind:a,direction:d(e,"direction",z),origin:C(e,"origin"),distance:H(e,"distance",{min:0}),durationMs:H(e,"durationMs",{min:0})}:"pinch"===a?{...r,kind:a,scale:A(e,"scale"),origin:tn(e,"origin")}:"rotate"===a?{...r,kind:a,degrees:A(e,"degrees"),origin:tn(e,"origin"),velocity:H(e,"velocity",{min:0})}:{...r,kind:a,origin:C(e,"origin"),delta:C(e,"delta"),scale:A(e,"scale"),degrees:A(e,"degrees"),durationMs:H(e,"durationMs",{min:0})}},run:async(t,e)=>{var r,a,i,n,o;switch(e.kind){case"pan":return await t.interactions.pan({...g(r=e),x:r.origin.x,y:r.origin.y,dx:r.delta.x,dy:r.delta.y,durationMs:r.durationMs});case"fling":return await t.interactions.fling({...g(a=e),direction:a.direction,x:a.origin.x,y:a.origin.y,distance:a.distance,durationMs:a.durationMs});case"pinch":return await t.interactions.pinch({...g(i=e),scale:i.scale,x:i.origin?.x,y:i.origin?.y});case"rotate":return await t.interactions.rotateGesture({...g(n=e),degrees:n.degrees,x:n.origin?.x,y:n.origin?.y,velocity:n.velocity});case"transform":return await t.interactions.transformGesture({...g(o=e),x:o.origin.x,y:o.origin.y,dx:o.delta.x,dy:o.delta.y,scale:o.scale,degrees:o.degrees,durationMs:o.durationMs})}}}),...q,D({name:"batch",description:"Run multiple structured command steps in one daemon request.",inputSchema:j(e={steps:u(k({type:"array",description:"Structured batch steps. Each step uses a command name and the same input object as that command tool.",items:{type:"object",properties:{command:{type:"string",enum:t=n,description:"Command name to run with structured input."},input:{type:"object",additionalProperties:!0,description:"Structured command input for the nested command. Use the matching MCP tool schema for this object."},runtime:{type:"object",additionalProperties:!0,description:"Optional per-step runtime payload."}},required:["command","input"],additionalProperties:!1}},(e,r)=>(function(t,e){if(!Array.isArray(t))throw Error("Expected steps to be an array.");return t.map((t,r)=>{var a,i,n;let o;return a=t,i=r+1,n=e,c(o=function(t,e){if(!t||"object"!=typeof t||Array.isArray(t))throw Error(`Invalid batch step ${e}.`);return t}(a,i),["command","input","runtime"],`Batch step ${i}`),{command:d(o,"command",n),input:function(t,e){let r=t.input;if(!r||"object"!=typeof r||Array.isArray(r))throw Error(`Batch step ${e} input must be an object.`);return r}(o,i),...function(t,e){let r=t.runtime;if(void 0!==r&&(!r||"object"!=typeof r||Array.isArray(r)))throw Error(`Batch step ${e} runtime must be an object.`);return void 0===r?{}:{runtime:r}}(o,i)}})})(e[r],t))),onError:P(["stop"],"Batch failure policy."),maxSteps:f("Maximum number of steps accepted for this batch.",{min:1,max:1e3}),out:i("Optional output path for command artifacts.")}),readInput:t=>(function(t,e){let a=h(t,e),i=a.maxSteps??r;if(!Number.isInteger(i)||i<1||i>1e3)throw Error(`Invalid batch maxSteps: ${String(a.maxSteps)}`);if(a.steps.length>i)throw Error(`batch has ${a.steps.length} steps; max allowed is ${i}.`);return{...a}})(t,e),run:(t,e)=>{var r;return t.batch.run({...g(r=e),steps:r.steps,onError:r.onError,maxSteps:r.maxSteps,out:r.out})}})],ts=new Map(to.map(t=>[t.name,t]));function tp(){return m().map(t=>{var e;if(!tl(t))throw Error(`Missing command for MCP-exposed command: ${t}`);return e=t,ts.get(e)})}function tc(){return to.map(t=>t.name)}function td(){return[...to]}function tl(t){return ts.has(t)}async function tu(t,e,r){var a;return await (a=e,ts.get(a)).invoke(t,r)}export{tl as isCommandName,td as listCommandDefinitions,tc as listCommandNames,tp as listMcpToolDefinitions,tu as runCommand};
1
+ var t;let e;import{DEFAULT_BATCH_MAX_STEPS as r}from"./1231.js";import{jsonSchemaField as a,stringField as i,batchCommandNames as n,toSelectorSnapshotOptions as o,booleanSchema as s,integerSchema as p,assertAllowedKeys as c,requiredEnum as d,looseObjectField as l,requiredField as u,listMcpExposedCommandNames as m,readFieldInput as h,commonToClientOptions as g,integerField as f,numberField as y,booleanField as b,readInputRecord as v,repeatedFields as w,stringSchema as x,stringArrayField as M,toClientElementTarget as S,customField as k,optionalEnum as I,enumField as P,toRepeatedOptions as R,pointField as U,command_input_readPoint as C,toClientInteractionTarget as E,interactionTargetField as T,fieldsInputSchema as j,requiredNumber as A,selectorSnapshotFields as F,elementTargetField as N,readCommonInput as O,looseObjectSchema as B,optionalInteger as H}from"./2099.js";function D(t){return{...t,invoke:async(e,r)=>await t.run(e,t.readInput(r))}}function L(t,e,r,a){return D({name:t,description:e,inputSchema:j(r),readInput:t=>h(t,r),run:a})}let _=["app","frontmost-app","desktop","menubar"],$=["duration","text","ref","selector"],G=["start","stop"],q=[L("devices","List available devices.",{},(t,e)=>t.devices.list(e)),L("boot","Boot or prepare a selected device without using CLI positional arguments.",{headless:b("Boot without showing simulator UI when supported.")},(t,e)=>t.devices.boot(e)),L("apps","List installed apps.",{appsFilter:P(["user-installed","all"])},(t,e)=>t.apps.list(e)),L("session","List active sessions.",{action:P(["list"])},async(t,{action:e,...r})=>({sessions:await t.sessions.list(r)})),L("open","Open an app, deep link, URL, or platform surface.",{app:i("App name, bundle id, package, or URL."),url:i("Optional URL passed with an app shell."),surface:P(_),activity:i("Android activity name."),launchConsole:i("Launch console mode."),relaunch:b("Force relaunch."),saveScript:a({oneOf:[s(),x()]}),noRecord:b("Do not record this action.")},(t,e)=>t.apps.open(e)),L("close","Close an app or end the active session.",{app:i("Optional app to close."),shutdown:b("Shutdown the session/device where supported."),saveScript:a({oneOf:[s(),x()]})},(t,e)=>e.app?t.apps.close(e):t.sessions.close(function(t){let{app:e,...r}=t;return r}(e))),L("install","Install an app binary.",{app:u(i()),appPath:u(i("Path to app binary."))},(t,e)=>t.apps.install(e)),L("reinstall","Reinstall an app binary.",{app:u(i()),appPath:u(i("Path to app binary."))},(t,e)=>t.apps.reinstall(e)),L("install-from-source","Install an app from a structured source.",{source:u(a(B("Install source object."))),retainPaths:b(),retentionMs:f()},(t,e)=>t.apps.installFromSource(e)),L("push","Deliver a push payload.",{app:u(i()),payload:u(a({oneOf:[x(),B()]}))},(t,e)=>t.apps.push(e)),L("trigger-app-event","Trigger an app-defined event.",{event:u(i()),payload:l()},(t,e)=>t.apps.triggerEvent(e)),L("snapshot","Capture an accessibility snapshot.",{interactiveOnly:b(),compact:b(),depth:f(),scope:i(),raw:b(),forceFull:b()},(t,e)=>t.capture.snapshot(e)),L("screenshot","Capture a screenshot.",{path:i("Output path."),overlayRefs:b(),fullscreen:b(),maxSize:f(),stabilize:b(),surface:P(_)},(t,e)=>t.capture.screenshot(e)),L("diff","Diff accessibility snapshots.",{kind:u(a({type:"string",const:"snapshot"})),out:i(),interactiveOnly:b(),compact:b(),depth:f(),scope:i(),raw:b()},(t,e)=>t.capture.diff(e)),L("wait","Wait for duration, text, ref, or selector.",{kind:P($),durationMs:f(),text:i(),ref:i(),selector:i(),timeoutMs:f(),depth:f(),scope:i(),raw:b()},(t,e)=>{var r;let a;return t.command.wait((I(r=e,"kind",$),a={...r},delete a.kind,a))}),L("alert","Inspect or handle platform alerts.",{action:P(["get","accept","dismiss","wait"]),timeoutMs:f()},(t,e)=>t.command.alert(e)),L("appstate","Show foreground app or activity.",{},(t,e)=>t.command.appState(e)),L("back","Navigate back.",{mode:P(["in-app","system"])},(t,e)=>t.command.back(e)),L("home","Go to the home screen.",{},(t,e)=>t.command.home(e)),L("rotate","Rotate device orientation.",{orientation:u(P(["portrait","portrait-upside-down","landscape-left","landscape-right"]))},(t,e)=>t.command.rotate(e)),L("app-switcher","Open the app switcher.",{},(t,e)=>t.command.appSwitcher(e)),L("keyboard","Inspect or dismiss the keyboard.",{action:P(["status","dismiss"])},(t,e)=>t.command.keyboard(e)),L("clipboard","Read or write clipboard text.",{action:u(P(["read","write"])),text:i()},(t,e)=>t.command.clipboard(e)),L("react-native","Run supported React Native app automation helpers.",{action:u(P(["dismiss-overlay"]))},(t,e)=>t.command.reactNative(e)),L("replay","Replay a recorded session.",{path:u(i()),update:b(),backend:i(),maestro:b(),env:M()},(t,e)=>t.replay.run(e)),L("test","Run one or more replay scripts.",{paths:u(M()),update:b(),backend:i(),maestro:b(),env:M(),failFast:b(),timeoutMs:f(),retries:f(),artifactsDir:i(),reportJunit:i()},(t,e)=>t.replay.test(e)),L("perf","Show session performance metrics.",{},(t,e)=>t.observability.perf(e)),L("logs","Manage session app logs.",{action:P(["path","start","stop","doctor","mark","clear"]),message:i(),restart:b()},(t,e)=>t.observability.logs(e)),L("network","Show recent HTTP traffic.",{action:P(["dump","log"]),limit:f(),include:P(["summary","headers","body","all"])},(t,e)=>t.observability.network(e)),L("record","Start or stop screen recording.",{action:u(P(G)),path:i(),fps:f(),quality:a(p()),hideTouches:b()},(t,e)=>t.recording.record(e)),L("trace","Start or stop trace capture.",{action:u(P(G)),path:i()},(t,e)=>t.recording.trace(e)),L("settings","Change OS settings and app permissions.",{setting:u(i()),state:u(i()),latitude:y(),longitude:y(),permission:i(),mode:P(["full","limited"])},(t,e)=>t.settings.update(e)),L("metro","Prepare Metro runtime or reload React Native apps.",{action:u(P(["prepare","reload"])),projectRoot:i(),kind:a(x()),publicBaseUrl:i(),proxyBaseUrl:i(),bearerToken:i(),bridgeScope:a({type:"object",additionalProperties:!0}),launchUrl:i(),port:f(),listenHost:i(),statusHost:i(),startupTimeoutMs:f(),probeTimeoutMs:f(),reuseExisting:b(),installDependenciesIfNeeded:b(),runtimeFilePath:i(),logPath:i(),metroHost:i(),metroPort:f(),bundleUrl:i(),timeoutMs:f()},async(t,e)=>{var r,a,i;return"prepare"===e.action?await t.metro.prepare({projectRoot:(r=e).projectRoot,kind:r.kind,publicBaseUrl:r.publicBaseUrl,proxyBaseUrl:r.proxyBaseUrl,bearerToken:r.bearerToken,bridgeScope:r.bridgeScope??((a=r).tenant&&a.runId&&a.leaseId?{tenantId:a.tenant,runId:a.runId,leaseId:a.leaseId}:void 0),port:r.port,listenHost:r.listenHost,statusHost:r.statusHost,startupTimeoutMs:r.startupTimeoutMs,probeTimeoutMs:r.probeTimeoutMs,reuseExisting:r.reuseExisting,installDependenciesIfNeeded:r.installDependenciesIfNeeded,runtimeFilePath:r.runtimeFilePath}):await t.metro.reload({metroHost:(i=e).metroHost,metroPort:i.metroPort,bundleUrl:i.bundleUrl,timeoutMs:i.timeoutMs})})],K=["pan","fling","pinch","rotate","transform"],z=["up","down","left","right"],J={target:u(T()),button:P(["primary","secondary","middle"],"Pointer button for platforms that support mouse buttons."),...F(),...w()},W={target:u(T()),...F(),...w()},X={target:u(T()),text:u(i("Text to enter into the target.")),delayMs:f("Delay between typed characters.",{min:0}),...F()},Y={target:u(T()),durationMs:f("Long press duration in milliseconds.",{min:0}),...F()},Q={from:u(U("Swipe start point.")),to:u(U("Swipe end point.")),durationMs:f("Swipe duration in milliseconds.",{min:0}),count:f("Number of swipe repetitions.",{min:1}),pauseMs:f("Pause between repeated swipes.",{min:0}),pattern:P(["one-way","ping-pong"])},V={x:u(y("X coordinate.")),y:u(y("Y coordinate."))},Z={text:u(i("Text to type.")),delayMs:f("Delay between typed characters.",{min:0})},tt={direction:u(P(["up","down","left","right","top","bottom"])),amount:y("Platform scroll amount."),pixels:f("Pixel scroll amount.",{min:0})},te={format:u(P(["text","attrs"])),target:u(N()),...F()},tr={predicate:u(P(["visible","hidden","exists","editable","selected","text"])),selector:u(i()),value:i(),...F()},ta={locator:P(["any","text","label","value","role","id"]),query:u(i()),action:P(["click","focus","exists","getText","getAttrs","wait","fill","type"]),value:i(),timeoutMs:f(),first:b(),last:b(),depth:f(),raw:b()},ti={kind:u(P(K,"Gesture variant.")),direction:P(z,"Fling direction."),origin:U("Gesture origin point."),delta:U("Movement delta for pan or transform gestures."),distance:f("Fling distance.",{min:0}),scale:y("Pinch or transform scale."),degrees:y("Rotation in degrees."),velocity:f("Rotate gesture velocity.",{min:0}),durationMs:f("Gesture duration in milliseconds.",{min:0})};function tn(t,e){return void 0===t[e]?void 0:C(t,e)}let to=[D({name:"click",description:"Click or tap a semantic UI target by ref, selector, or point.",inputSchema:j(J),readInput:t=>h(t,J),run:(t,e)=>{var r;return t.interactions.click({...g(r=e),...E(r.target),...o(r),...R(r),button:r.button})}}),D({name:"press",description:"Press a semantic UI target by ref, selector, or point.",inputSchema:j(W),readInput:t=>h(t,W),run:(t,e)=>{var r;return t.interactions.press({...g(r=e),...E(r.target),...o(r),...R(r)})}}),D({name:"fill",description:"Fill text into a semantic UI target by ref, selector, or point.",inputSchema:j(X),readInput:t=>h(t,X),run:(t,e)=>{var r;return t.interactions.fill({...g(r=e),...E(r.target),...o(r),text:r.text,delayMs:r.delayMs})}}),L("longpress","Long press by ref, selector, or point.",Y,(t,e)=>{var r;return t.interactions.longPress({...g(r=e),...E(r.target),...o(r),durationMs:r.durationMs})}),L("swipe","Swipe between two points.",Q,(t,e)=>t.interactions.swipe(e)),L("focus","Focus input at coordinates.",V,(t,e)=>t.interactions.focus(e)),L("type","Type text in the focused field.",Z,(t,e)=>t.interactions.type(e)),L("scroll","Scroll in a direction or to an edge.",tt,(t,e)=>t.interactions.scroll(e)),L("get","Get element text or attributes.",te,(t,e)=>{var r;return t.interactions.get({...g(r=e),...S(r.target),...o(r),format:r.format})}),L("is","Assert UI state.",tr,(t,e)=>t.interactions.is(e)),L("find","Find an element and optionally act on it.",ta,(t,e)=>t.interactions.find(e)),D({name:"gesture",description:"Run a structured gesture.",inputSchema:j(ti),readInput:function(t){let e=v(t),r=O(e),a=d(e,"kind",K);return"pan"===a?{...r,kind:a,origin:C(e,"origin"),delta:C(e,"delta"),durationMs:H(e,"durationMs",{min:0})}:"fling"===a?{...r,kind:a,direction:d(e,"direction",z),origin:C(e,"origin"),distance:H(e,"distance",{min:0}),durationMs:H(e,"durationMs",{min:0})}:"pinch"===a?{...r,kind:a,scale:A(e,"scale"),origin:tn(e,"origin")}:"rotate"===a?{...r,kind:a,degrees:A(e,"degrees"),origin:tn(e,"origin"),velocity:H(e,"velocity",{min:0})}:{...r,kind:a,origin:C(e,"origin"),delta:C(e,"delta"),scale:A(e,"scale"),degrees:A(e,"degrees"),durationMs:H(e,"durationMs",{min:0})}},run:async(t,e)=>{var r,a,i,n,o;switch(e.kind){case"pan":return await t.interactions.pan({...g(r=e),x:r.origin.x,y:r.origin.y,dx:r.delta.x,dy:r.delta.y,durationMs:r.durationMs});case"fling":return await t.interactions.fling({...g(a=e),direction:a.direction,x:a.origin.x,y:a.origin.y,distance:a.distance,durationMs:a.durationMs});case"pinch":return await t.interactions.pinch({...g(i=e),scale:i.scale,x:i.origin?.x,y:i.origin?.y});case"rotate":return await t.interactions.rotateGesture({...g(n=e),degrees:n.degrees,x:n.origin?.x,y:n.origin?.y,velocity:n.velocity});case"transform":return await t.interactions.transformGesture({...g(o=e),x:o.origin.x,y:o.origin.y,dx:o.delta.x,dy:o.delta.y,scale:o.scale,degrees:o.degrees,durationMs:o.durationMs})}}}),...q,D({name:"batch",description:"Run multiple structured command steps in one daemon request.",inputSchema:j(e={steps:u(k({type:"array",description:"Structured batch steps. Each step uses a command name and the same input object as that command tool.",items:{type:"object",properties:{command:{type:"string",enum:t=n,description:"Command name to run with structured input."},input:{type:"object",additionalProperties:!0,description:"Structured command input for the nested command. Use the matching MCP tool schema for this object."},runtime:{type:"object",additionalProperties:!0,description:"Optional per-step runtime payload."}},required:["command","input"],additionalProperties:!1}},(e,r)=>(function(t,e){if(!Array.isArray(t))throw Error("Expected steps to be an array.");return t.map((t,r)=>{var a,i,n;let o;return a=t,i=r+1,n=e,c(o=function(t,e){if(!t||"object"!=typeof t||Array.isArray(t))throw Error(`Invalid batch step ${e}.`);return t}(a,i),["command","input","runtime"],`Batch step ${i}`),{command:d(o,"command",n),input:function(t,e){let r=t.input;if(!r||"object"!=typeof r||Array.isArray(r))throw Error(`Batch step ${e} input must be an object.`);return r}(o,i),...function(t,e){let r=t.runtime;if(void 0!==r&&(!r||"object"!=typeof r||Array.isArray(r)))throw Error(`Batch step ${e} runtime must be an object.`);return void 0===r?{}:{runtime:r}}(o,i)}})})(e[r],t))),onError:P(["stop"],"Batch failure policy."),maxSteps:f("Maximum number of steps accepted for this batch.",{min:1,max:1e3}),out:i("Optional output path for command artifacts.")}),readInput:t=>(function(t,e){let a=h(t,e),i=a.maxSteps??r;if(!Number.isInteger(i)||i<1||i>1e3)throw Error(`Invalid batch maxSteps: ${String(a.maxSteps)}`);if(a.steps.length>i)throw Error(`batch has ${a.steps.length} steps; max allowed is ${i}.`);return{...a}})(t,e),run:(t,e)=>{var r;return t.batch.run({...g(r=e),steps:r.steps,onError:r.onError,maxSteps:r.maxSteps,out:r.out})}})],ts=new Map(to.map(t=>[t.name,t]));function tp(){return m().map(t=>{var e;if(!tl(t))throw Error(`Missing command for MCP-exposed command: ${t}`);return e=t,ts.get(e)})}function tc(){return to.map(t=>t.name)}function td(){return[...to]}function tl(t){return ts.has(t)}async function tu(t,e,r){var a;return await (a=e,ts.get(a)).invoke(t,r)}export{tl as isCommandName,td as listCommandDefinitions,tc as listCommandNames,tp as listMcpToolDefinitions,tu as runCommand};
package/dist/src/cli.js CHANGED
@@ -467,18 +467,15 @@ ${v}${(function(e){let t=[],n=[],o=new Map(e.map(e=>[e.node.index,e.node])),r=e=
467
467
  `:"";if(!l)return`${d}${p}${s} additions, ${a} removals, ${i} unchanged
468
468
  `;let f=`${(n=String(s),t("green",n))} additions, ${t("red",String(a))} removals, ${t("dim",String(i))} unchanged`;return`${d}${p}${f}
469
469
  `})(r)),!0}if("screenshot"!==e[0])return!1;let s=n.baseline;if(!s||"string"!=typeof s)throw new K("INVALID_ARGS","diff screenshot requires --baseline <path>");let a=ea(s),i="string"==typeof n.out?ea(n.out):void 0,l=e[1];if(e.length>2)throw new K("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let c=R({backend:(r=o,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(n),captureScreenshot:async(e,t,n)=>{let o=await r.capture.screenshot({path:t,session:e.session,overlayRefs:n?.overlayRefs,fullscreen:n?.fullscreen,stabilize:n?.stabilize,surface:n?.surface});return{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}}}}),artifacts:el(),sessions:{get:e=>({name:e}),set:()=>{}},policy:O()}),d=await c.capture.diffScreenshot({session:n.session,baseline:{kind:"path",path:a},current:l?{kind:"path",path:ea(l)}:{kind:"live"},...i?{out:{kind:"path",path:i}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(n.threshold),overlayRefs:n.overlayRefs,surface:n.surface});return tz(n,d,()=>{var e,n,o,r;let s,a,i,l,c,u,p,f;return s=e4(),a=!0===d.match,i=d.dimensionMismatch,(l=[]).push(...function(e,n){if(!0===e.match){let e=n?t("green","✓"):"✓";return[`${e} Screenshots match.`]}let o=e.dimensionMismatch,r=n?t("red","✗"):"✗";if(o){let e=o.expected,t=o.actual;return[`${r} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let s=e5(e.differentPixels),a=e5(e.mismatchPercentage),i=0===a&&s>0?"<0.01":String(a),l=`${i}% pixels differ`;return[`${r} ${n?t("red",l):l}`]}(d,s)),l.push(...function(e,n,o){if(n)return[];let r=[];if(e.diffPath){let n=e8(e.diffPath),s=o?t("dim","Diff image:"):"Diff image:",a=o?t("green",n):n;r.push(` ${s} ${a}`)}if(e.currentOverlayPath){let n=e8(e.currentOverlayPath),s=o?t("dim","Current overlay:"):"Current overlay:",a=o?t("green",n):n,i=e5(e.currentOverlayRefCount),l=i>0?` (${i} refs)`:"";r.push(` ${s} ${a}${l}`)}return r}(d,a,s)),a||i||(l.push(...(e=d,n=s,c=e5(e.differentPixels),u=e5(e.totalPixels),p=n?t("red",String(c)):String(c),[` ${p} different / ${u} total pixels`])),l.push(...(o=d,r=s,0===(f=function(e){let t=[];for(let n of(e.ocr?.movementClusters??[]).slice(0,2))t.push(`text movement cluster: ${function(e){let t=e.slice(0,4).map(e=>JSON.stringify(e)),n=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${n}`}(n.texts)} dx=${e3(n.xRange)}px dy=${e3(n.yRange)}px`);let n=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);n.length>0&&t.push(`non-text controls: ${n.map(e2).join("; ")}`);let o=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return o.length>0&&t.push(`non-text boundaries: ${o.map(e2).join("; ")}`),t.slice(0,6)}(o)).length?[]:[` ${e6("Hints:",r)}`,...f.map(e=>` - ${e}`)])),l.push(...function(e,t){let n=Array.isArray(e.regions)?e.regions:[];if(0===n.length)return[];let o=[` ${e6("Changed regions:",t)}`];for(let e of n.slice(0,5))o.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),n=e.rect,o=[` ${e.index}. ${e.location} x=${n.x} y=${n.y} ${n.width}x${n.height}, ${t}% of diff, change=${e.dominantChange}`],r=function(e){let t=[e.size?`size=${e.size}`:null,e.shape?`shape=${e.shape}`:null,"number"==typeof e.densityPercentage?`density=${e.densityPercentage}%`:null,e.averageBaselineColorHex&&e.averageCurrentColorHex?`avgColor=${e.averageBaselineColorHex}->${e.averageCurrentColorHex}`:null,"number"==typeof e.baselineLuminance&&"number"==typeof e.currentLuminance?`luminance=${e.baselineLuminance}->${e.currentLuminance}`:null].filter(e=>null!==e);return t.length>0?t.join(" "):null}(e);r&&o.push(` ${r}`);let s=e.currentOverlayMatches?.[0];if(s){let e=s.label?` "${s.label}"`:"";o.push(` overlaps @${s.ref}${e}, ${s.regionCoveragePercentage}% of region`)}return o}(e));return o}(d,s)),l.push(...function(e,t){let n=e.ocr?.matches??[];if(0===n.length)return[];let o=n.slice(0,8),r=[` ${e6(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${o.length}/${n.length}; px):`,t)}`,` ${e6("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of o.entries()){let n=t.delta;r.push(` ${e+1} | ${JSON.stringify(t.text)} | ${e1(n.x)},${e1(n.y)} | ${e1(n.width)},${e1(n.height)} | ${e0(t.baselineRect)} | ${e0(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return r}(d,s)),l.push(...function(e,t){let n=e.nonTextDeltas??[];if(0===n.length)return[];let o=n.slice(0,8),r=[` ${e6(`Non-text visual deltas (showing ${o.length}/${n.length}; px):`,t)}`,` ${e6("item | region | slot | kind | bboxCurrent | nearestText",t)}`];for(let e of o)r.push(` ${e.index} | ${e.regionIndex?`r${e.regionIndex}`:"-"} | ${e.slot} | ${e.likelyKind} | ${e0(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return r}(d,s))),`${l.join("\n")}
470
- `}),!0};function nf(e){let t=e.attempts>1?` after ${e.attempts} attempts`:"",n=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FAIL ${e.file}${t}${n}
470
+ `}),!0};function nf(e){var t;let n=e.attempts>1?` after ${e.attempts} attempts`:"",o=e.durationMs>0?` (${e.durationMs}ms)`:"";for(let r of(process.stdout.write(`FAIL ${e.file}${n}${o}
471
471
  `),process.stdout.write(` ${e.error?.message??"Unknown test failure"}
472
- `),e.error?.hint&&process.stdout.write(` hint: ${e.error.hint}
473
- `),e.artifactsDir&&process.stdout.write(` artifacts: ${e.artifactsDir}
474
- `),e.error?.logPath&&process.stdout.write(` log: ${e.error.logPath}
475
- `),e.error?.diagnosticId&&process.stdout.write(` diagnostic: ${e.error.diagnosticId}
476
- `)}function nm(e){return"passed"===e.status&&e.attempts>1}function nh(e){return(Math.max(0,e)/1e3).toFixed(3)}function ng(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}let nv=Object.fromEntries(Object.keys(ni).map(e=>{var t;return[e,(t=e,async({positionals:e,flags:n,client:o})=>{var r,s;let{cliOutput:a}=await nd({client:o,command:t,positionals:e,flags:n});if(!a)throw Error(`Missing CLI output formatter for command: ${t}`);return r=n,s=a,!r.json&&s.stderr&&process.stderr.write(s.stderr),tz(r,r.json?s.jsonData??s.data:s.data,()=>s.text),!0})]})),nw=Object.fromEntries(Object.entries(Object.fromEntries(eo().filter(function(e){return!(e in nv)&&"screenshot"!==e&&"diff"!==e}).map(e=>[e,async({client:t,positionals:n,flags:o})=>("test"===e&&(({json:o.json}).json||process.stderr.write("Running replay suite...\n")),await nc({client:t,command:e,positionals:n,flags:o}))]))).map(([t,n])=>{var r,s;return[t,(r=t,s=n,async({positionals:t,flags:n,client:a})=>{var i,l,c;let d=await s({client:a,positionals:t,flags:n}),u=(i=r,l=n,c=d,"test"===i?function(t){let{suite:n,json:r,verbose:s,reportJunit:a}=t;return(a&&function(t,n){let r=e.dirname(t);try{o.mkdirSync(r,{recursive:!0}),o.writeFileSync(t,function(t){let n=['<?xml version="1.0" encoding="UTF-8"?>',"<testsuites>",` <testsuite name="agent-device replay suite" tests="${t.total}" failures="${t.failed}" skipped="${t.skipped}" time="${nh(t.durationMs)}">`];for(let o of t.tests)n.push(...function(t){let n=ng(e.basename(t.file)),o=ng("."===e.dirname(t.file)?t.file:e.dirname(t.file)),r=ng(t.file),s=nh(t.durationMs),a=[` <testcase classname="${o}" name="${n}" file="${r}" time="${s}">`];"failed"===t.status?a.push(` <failure message="${ng(t.error.message)}">${ng(function(e){let t=[e.error.message];e.error.hint&&t.push(`hint: ${e.error.hint}`),e.error.diagnosticId&&t.push(`diagnosticId: ${e.error.diagnosticId}`),e.error.logPath&&t.push(`logPath: ${e.error.logPath}`),e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`);let n=e.error.details?JSON.stringify(e.error.details,null,2):void 0;return n&&t.push(`details: ${n}`),t.join("\n")}(t))}</failure>`):"skipped"===t.status&&a.push(` <skipped message="${ng(t.message)}" />`);let i=function(e){let t=[`status: ${e.status}`,`durationMs: ${e.durationMs}`];return"attempts"in e&&t.push(`attempts: ${e.attempts}`),"session"in e&&t.push(`session: ${e.session}`),"replayed"in e&&t.push(`replayed: ${e.replayed}`),"healed"in e&&t.push(`healed: ${e.healed}`),"artifactsDir"in e&&e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`),"passed"===e.status&&e.attempts>1&&t.push("flaky: true"),t.join("\n")}(t);return i&&a.push(` <system-out>${ng(i)}</system-out>`),a.push(" </testcase>"),a}(o));return n.push(" </testsuite>"),n.push("</testsuites>"),`${n.join("\n")}
477
- `}(n),"utf8")}catch(n){let e=n instanceof Error?n.message:String(n);throw new K("COMMAND_FAILED",`Failed to write JUnit report to ${t}: ${e}`)}}(a,n),r)?(eX({success:!0,data:n}),+(n.failed>0)):function(e,t={}){let n=e.tests.filter(nm);if(t.verbose)for(let t of e.tests)!function(e){if("failed"===e.status)return nf(e);let t="passed"===e.status?nm(e)?"FLAKY":"PASS":"skipped"===e.status?"SKIP":"INFO",n="attempts"in e&&e.attempts>1?` after ${e.attempts} attempts`:"",o=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`${t} ${e.file}${n}${o}
472
+ `),t=e,[t.error?.hint?`hint: ${t.error.hint}`:"",t.artifactsDir?`artifacts: ${t.artifactsDir}`:"",t.error?.logPath?`log: ${t.error.logPath}`:"",t.error?.diagnosticId?`diagnostic: ${t.error.diagnosticId}`:""].filter(Boolean)))process.stdout.write(` ${r}
473
+ `)}function nm(e){return"passed"===e.status&&e.attempts>1}function nh(e,t,n={}){n.includeMessage&&e.push(`errorMessage: ${t.message}`),t.hint&&e.push(`hint: ${t.hint}`),t.diagnosticId&&e.push(`diagnosticId: ${t.diagnosticId}`),t.logPath&&e.push(`logPath: ${t.logPath}`),!1!==n.includeDetails&&ng(e,t,n.detailsIndent)}function ng(e,t,n){let o=t.details?JSON.stringify(t.details,null,n):void 0;o&&e.push(`details: ${o}`)}function nv(e,t){t&&e.push(t)}function nw(e){return(Math.max(0,e)/1e3).toFixed(3)}function ny(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}let nb=Object.fromEntries(Object.keys(ni).map(e=>{var t;return[e,(t=e,async({positionals:e,flags:n,client:o})=>{var r,s;let{cliOutput:a}=await nd({client:o,command:t,positionals:e,flags:n});if(!a)throw Error(`Missing CLI output formatter for command: ${t}`);return r=n,s=a,!r.json&&s.stderr&&process.stderr.write(s.stderr),tz(r,r.json?s.jsonData??s.data:s.data,()=>s.text),!0})]})),nI=Object.fromEntries(Object.entries(Object.fromEntries(eo().filter(function(e){return!(e in nb)&&"screenshot"!==e&&"diff"!==e}).map(e=>[e,async({client:t,positionals:n,flags:o})=>("test"===e&&(({json:o.json}).json||process.stderr.write("Running replay suite...\n")),await nc({client:t,command:e,positionals:n,flags:o}))]))).map(([t,n])=>{var r,s;return[t,(r=t,s=n,async({positionals:t,flags:n,client:a})=>{var i,l,c;let d=await s({client:a,positionals:t,flags:n}),u=(i=r,l=n,c=d,"test"===i?function(t){let{suite:n,json:r,verbose:s,reportJunit:a}=t;return(a&&function(t,n){let r=e.dirname(t);try{o.mkdirSync(r,{recursive:!0}),o.writeFileSync(t,function(t){let n=['<?xml version="1.0" encoding="UTF-8"?>',"<testsuites>",` <testsuite name="agent-device replay suite" tests="${t.total}" failures="${t.failed}" skipped="${t.skipped}" time="${nw(t.durationMs)}">`];for(let o of t.tests)n.push(...function(t){let n=ny(e.basename(t.file)),o=ny("."===e.dirname(t.file)?t.file:e.dirname(t.file)),r=ny(t.file),s=nw(t.durationMs),a=[` <testcase classname="${o}" name="${n}" file="${r}" time="${s}">`];"failed"===t.status?a.push(` <failure message="${ny(t.error.message)}">${ny(function(e){let t=[e.error.message];return nh(t,e.error,{includeDetails:!1}),e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`),ng(t,e.error,2),t.join("\n")}(t))}</failure>`):"skipped"===t.status&&a.push(` <skipped message="${ny(t.message)}" />`);let i=function(e){let t=[`status: ${e.status}`,`durationMs: ${e.durationMs}`];return function(e,t){var n,o;nv(e,"attempts"in t?`attempts: ${t.attempts}`:void 0),nv(e,"session"in t?`session: ${t.session}`:void 0),nv(e,"replayed"in t?`replayed: ${t.replayed}`:void 0),nv(e,"healed"in t?`healed: ${t.healed}`:void 0),nv(e,"artifactsDir"in t&&t.artifactsDir?`artifactsDir: ${t.artifactsDir}`:void 0),"failed"===t.status&&(n=e,o=t,n.push(`errorCode: ${o.error.code}`),nh(n,o.error,{includeMessage:!0})),nv(e,nm(t)?"flaky: true":void 0)}(t,e),t.join("\n")}(t);return i&&a.push(` <system-out>${ny(i)}</system-out>`),a.push(" </testcase>"),a}(o));return n.push(" </testsuite>"),n.push("</testsuites>"),`${n.join("\n")}
474
+ `}(n),"utf8")}catch(n){let e=n instanceof Error?n.message:String(n);throw new K("COMMAND_FAILED",`Failed to write JUnit report to ${t}: ${e}`)}}(a,n),r)?(eX({success:!0,data:n}),+(n.failed>0)):function(e,t={}){let n=e.tests.filter(nm);if(t.verbose)for(let t of e.tests)!function(e){var t;if("failed"===e.status)return nf(e);let n="passed"===(t=e).status?t.attempts>1?"FLAKY":"PASS":"skipped"===t.status?"SKIP":"INFO",o="attempts"in e&&e.attempts>1?` after ${e.attempts} attempts`:"",r=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`${n} ${e.file}${o}${r}
478
475
  `),"skipped"===e.status&&process.stdout.write(` ${e.message??"skipped"}
479
476
  `)}(t);else{for(let t of e.failures)nf(t);for(let e of n)!function(e){let t=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FLAKY ${e.file} after ${e.attempts} attempts${t}
480
477
  `)}(e)}let o="number"==typeof e.durationMs?e.durationMs:void 0,r=n.length>0?`, ${n.length} flaky`:"";return process.stdout.write(`Test summary: ${e.passed} passed, ${e.failed} failed${r}${void 0!==o?` in ${o}ms`:""}
481
- `),+(e.failed>0)}(n,{verbose:s})}({suite:c,verbose:l.verbose,json:l.json,reportJunit:l.reportJunit}):(tz(l,c,()=>w(c)),0));return 0!==u&&process.exit(u),!0})]})),ny={connect:tJ,disconnect:tW,connection:tZ,auth:t1,screenshot:nu,diff:np,...nv,...nw};async function nb(e){let t=ny[e.command];if(!t)return!1;let n={...e.flags};return E(e.command,n),await t({...e,flags:n})}function nI(e,t,n){return n||(e.push(t),"")}async function nx(e,t,n){let{flags:o}=t,r=function(e){var t;if(!e?.metroProxyBaseUrl||"android-instance"!==(t=e.leaseBackend)&&"ios-instance"!==t)return null;let n=[],o={serverBaseUrl:nI(n,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:nI(n,"metroBearerToken",e.metroBearerToken),tenantId:nI(n,"tenant",e.tenant),runId:nI(n,"runId",e.runId),leaseId:nI(n,"leaseId",e.leaseId)};if(n.length>0)throw new K("INVALID_ARGS",`react-devtools remote bridge requires ${n.join(", ")}.`,{missing:n});return o}(o);if(!r)return n();let s=t.stateDir??process.cwd(),a=t.session??o?.session??"default",i=o?.remoteConfig??`${r.tenantId}:${r.runId}:${r.leaseId}`;if("stop"===e[0])try{return await n()}finally{await tn({projectRoot:t.cwd??process.cwd(),stateDir:s,profileKey:i,consumerKey:a})}return await tt({projectRoot:t.cwd??process.cwd(),stateDir:s,serverBaseUrl:r.serverBaseUrl,bearerToken:r.bearerToken,bridgeScope:{tenantId:r.tenantId,runId:r.runId,leaseId:r.leaseId},session:a,profileKey:i,consumerKey:a,env:t.env??process.env}),await n()}async function nA(e,t={}){let n=t.cwd??process.cwd(),o=t.env??process.env,r=await nx(e,t,async()=>(await et("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:n,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var s,a=t.flags;return 0!==r&&"wait"===(s=e)[0]&&s.includes("--connected")&&"ios-instance"===a?.leaseBackend&&process.stderr.write("Hint: Remote iOS React DevTools connects during JavaScript startup.\nIf the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.\n"),r}function n$(e,t={}){let n=nk(t),o={...e};return n.defaultPlatform&&void 0===o.platform&&(o.platform=n.defaultPlatform),o}function nk(e){var t,n,o,r;let s,a=e.env??process.env,i=e.inheritedPlatform??e.configuredPlatform??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("ios"===t||"android"===t||"apple"===t)return t;throw new K("INVALID_ARGS",`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}(a.AGENT_DEVICE_PLATFORM),l="string"==typeof(t=e.configuredSession??a.AGENT_DEVICE_SESSION)&&t.trim().length>0;return{defaultPlatform:i,lockPolicy:(n=e.policyOverrides,o=a,r=l,(s=n?.sessionLock??n?.sessionLockConflicts??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new K("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}(o.AGENT_DEVICE_SESSION_LOCK))||(n?.sessionLocked===!0||r?"reject":void 0))}}let nS={sendToDaemon:ed},nC=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),nD=new Set(["connect","connection","close","disconnect","metro","session"]);async function nN(t,n=nS){let r=W(),s=f(),a=t.includes("--debug")||t.includes("--verbose")||t.includes("-v"),i=t.includes("--json"),l=function(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith("--session=")){let e=n.slice(10).trim();return e.length>0?e:null}if("--session"===n){let n=e[t+1]?.trim();if(n&&!n.startsWith("-"))return n;break}}return null}(t)??process.env.AGENT_DEVICE_SESSION??"default";await Z({session:l,requestId:r,command:t[0],debug:a},async()=>{var l,c,d,p,f,m,h,g,v,w,b,I,x,A,$,k,S;let C,R,U,P,O,T,j;try{let n,r,s,a,i,y,I,x;l={cwd:process.cwd(),env:process.env},n=function(e){let t={json:!1,help:!1,version:!1},n=null,o=[],r=[],s=!0;for(let l=0;l<e.length;l+=1){var a,i;let c=e[l];if(s&&"--"===c){s=!1;continue}if(!s){n?o.push(c):n=eP(c);continue}let d=c.startsWith("--"),u=c.startsWith("-")&&c.length>1;if(!d&&!u){n?o.push(c):n=eP(c);continue}let[p,f]=d?eR(c):[c,void 0],m=N(p);if(a=n,i=m,"react-devtools"===a&&(!i||!eD(i.key,a))){o.push(c);continue}if(!m){if(function(e,t,n){var o;if(o=n,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=_(e);if(!r||r.allowsExtraPositionals)return!0;let s=r.positionalArgs??[];return 0!==s.length&&(t.length<s.length||s.some(e=>e.includes("?")))}(n,o,c)){n?o.push(c):n=c;continue}throw new K("INVALID_ARGS",`Unknown flag: ${p}`)}let h=function(e,t,n,o){if(void 0!==e.setValue){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==n){if(0===n.trim().length)throw new K("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:n,consumeNext:!1}}return void 0===o||e_(o)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(o)?{value:!0,consumeNext:!1}:{value:o,consumeNext:!0}}let r=n??o;if(void 0===r||void 0===n&&e_(r))throw new K("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===n};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:r,consumeNext:void 0===n}}let s=Number(r);if(!Number.isFinite(s)||"number"==typeof e.min&&s<e.min||"number"==typeof e.max&&s>e.max)throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:Math.floor(s),consumeNext:void 0===n}}(m,p,f,e[l+1]);h.consumeNext&&(l+=1);let g=t[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:void 0===g?[h.value]:[g,h.value];t[m.key]=e}else t[m.key]=h.value;r.push({key:m.key,token:p})}return{command:n,positionals:o,flags:t,warnings:[],providedFlags:r}}(t),r=l?.env??process.env,s=l?.cwd??process.cwd(),p=n.command,a=null!==p&&(c={remoteConfig:n.flags.remoteConfig,cwd:s,env:r}).remoteConfig?{...th(M({configPath:c.remoteConfig,cwd:c.cwd,env:c.env}).profile),remoteConfig:c.remoteConfig}:{},I=ep((i=(d={command:n.command,cwd:s,cliFlags:n.flags,env:r}).env??process.env,y=ep({},function(e){let t={};for(let n of e)ep(t,function(e,t){let n,r;if(!o.existsSync(e)){if(t)throw new K("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{n=o.readFileSync(e,"utf8")}catch(t){throw new K("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{r=JSON.parse(n)}catch(t){throw new K("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!r||"object"!=typeof r||Array.isArray(r))throw new K("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let n={};for(let[o,r]of Object.entries(e)){if("installSource"===o){n.installSource=u(r,t);continue}let e=eC.get(o);if(!e)throw new K("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new K("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);n[o]=F(eN(e),r,t,o)}return n}(r,`config file ${e}`)}(n.path,n.required));return t}((f=d.cwd,m=d.cliFlags.config,h=i,(x=m??h.AGENT_DEVICE_CONFIG)?[{path:(g=x,v=f,w=h,ea(g,{cwd:v,env:w})),required:!0}]:[{path:(b=h,e.join(ei("~",{env:b}),".agent-device","config.json")),required:!1},{path:e.resolve(f,"agent-device.json"),required:!1}]))),ep(y,function(e,t){var n,o,r;let s={};for(let a of eS.filter(e=>e.config.enabled&&e.supportsCommand(t))){if("installSource"===a.key)continue;let t=a.env.names.map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);t&&(s[a.key]=(n=t.value,o=`environment variable ${t.name}`,r=t.name,F(eN(a),n,o,r)))}return s}(i,d.command))),a),C={...function(e,t){let n=t?.strictFlags??!0,o=[...e.warnings],r=ep({json:!1,help:!1,version:!1},t?.defaultFlags??{});ep(r,e.flags);let s=e.providedFlags.filter(t=>!eD(t.key,e.command));if(s.length>0){var a,i;let t=s.map(e=>e.token),l=(a=e.command,i=t,a?1===i.length?`Flag ${i[0]} is not supported for command ${a}.`:`Flags ${i.join(", ")} are not supported for command ${a}.`:1===i.length?`Flag ${i[0]} requires a command that supports it.`:`Flags ${i.join(", ")} require a command that supports them.`);if(n)throw new K("INVALID_ARGS",l);for(let e of(o.push(l),s))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eD(t,e.command)||delete r[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new K("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),E(e.command,r),"batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new K("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:n,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(n,{strictFlags:l?.strictFlags,defaultFlags:I}),providedFlags:n.providedFlags}}catch(t){Q({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=H(t,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});i?eX({success:!1,error:e}):eY(e,{showDetails:a}),process.exit(1);return}for(let e of C.warnings)process.stderr.write(`Warning: ${e}
478
+ `),+(e.failed>0)}(n,{verbose:s})}({suite:c,verbose:l.verbose,json:l.json,reportJunit:l.reportJunit}):(tz(l,c,()=>w(c)),0));return 0!==u&&process.exit(u),!0})]})),nx={connect:tJ,disconnect:tW,connection:tZ,auth:t1,screenshot:nu,diff:np,...nb,...nI};async function nA(e){let t=nx[e.command];if(!t)return!1;let n={...e.flags};return E(e.command,n),await t({...e,flags:n})}function n$(e,t,n){return n||(e.push(t),"")}async function nk(e,t,n){let{flags:o}=t,r=function(e){var t;if(!e?.metroProxyBaseUrl||"android-instance"!==(t=e.leaseBackend)&&"ios-instance"!==t)return null;let n=[],o={serverBaseUrl:n$(n,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:n$(n,"metroBearerToken",e.metroBearerToken),tenantId:n$(n,"tenant",e.tenant),runId:n$(n,"runId",e.runId),leaseId:n$(n,"leaseId",e.leaseId)};if(n.length>0)throw new K("INVALID_ARGS",`react-devtools remote bridge requires ${n.join(", ")}.`,{missing:n});return o}(o);if(!r)return n();let s=t.stateDir??process.cwd(),a=t.session??o?.session??"default",i=o?.remoteConfig??`${r.tenantId}:${r.runId}:${r.leaseId}`;if("stop"===e[0])try{return await n()}finally{await tn({projectRoot:t.cwd??process.cwd(),stateDir:s,profileKey:i,consumerKey:a})}return await tt({projectRoot:t.cwd??process.cwd(),stateDir:s,serverBaseUrl:r.serverBaseUrl,bearerToken:r.bearerToken,bridgeScope:{tenantId:r.tenantId,runId:r.runId,leaseId:r.leaseId},session:a,profileKey:i,consumerKey:a,env:t.env??process.env}),await n()}async function nS(e,t={}){let n=t.cwd??process.cwd(),o=t.env??process.env,r=await nk(e,t,async()=>(await et("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:n,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var s,a=t.flags;return 0!==r&&"wait"===(s=e)[0]&&s.includes("--connected")&&"ios-instance"===a?.leaseBackend&&process.stderr.write("Hint: Remote iOS React DevTools connects during JavaScript startup.\nIf the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.\n"),r}function nC(e,t={}){let n=nD(t),o={...e};return n.defaultPlatform&&void 0===o.platform&&(o.platform=n.defaultPlatform),o}function nD(e){var t,n,o,r;let s,a=e.env??process.env,i=e.inheritedPlatform??e.configuredPlatform??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("ios"===t||"android"===t||"apple"===t)return t;throw new K("INVALID_ARGS",`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}(a.AGENT_DEVICE_PLATFORM),l="string"==typeof(t=e.configuredSession??a.AGENT_DEVICE_SESSION)&&t.trim().length>0;return{defaultPlatform:i,lockPolicy:(n=e.policyOverrides,o=a,r=l,(s=n?.sessionLock??n?.sessionLockConflicts??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new K("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}(o.AGENT_DEVICE_SESSION_LOCK))||(n?.sessionLocked===!0||r?"reject":void 0))}}let nN={sendToDaemon:ed},nR=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),nU=new Set(["connect","connection","close","disconnect","metro","session"]);async function n_(t,n=nN){let r=W(),s=f(),a=t.includes("--debug")||t.includes("--verbose")||t.includes("-v"),i=t.includes("--json"),l=function(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith("--session=")){let e=n.slice(10).trim();return e.length>0?e:null}if("--session"===n){let n=e[t+1]?.trim();if(n&&!n.startsWith("-"))return n;break}}return null}(t)??process.env.AGENT_DEVICE_SESSION??"default";await Z({session:l,requestId:r,command:t[0],debug:a},async()=>{var l,c,d,p,f,m,h,g,v,w,b,I,x,A,$,k,S;let C,R,U,P,O,T,j;try{let n,r,s,a,i,y,I,x;l={cwd:process.cwd(),env:process.env},n=function(e){let t={json:!1,help:!1,version:!1},n=null,o=[],r=[],s=!0;for(let l=0;l<e.length;l+=1){var a,i;let c=e[l];if(s&&"--"===c){s=!1;continue}if(!s){n?o.push(c):n=eP(c);continue}let d=c.startsWith("--"),u=c.startsWith("-")&&c.length>1;if(!d&&!u){n?o.push(c):n=eP(c);continue}let[p,f]=d?eR(c):[c,void 0],m=N(p);if(a=n,i=m,"react-devtools"===a&&(!i||!eD(i.key,a))){o.push(c);continue}if(!m){if(function(e,t,n){var o;if(o=n,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=_(e);if(!r||r.allowsExtraPositionals)return!0;let s=r.positionalArgs??[];return 0!==s.length&&(t.length<s.length||s.some(e=>e.includes("?")))}(n,o,c)){n?o.push(c):n=c;continue}throw new K("INVALID_ARGS",`Unknown flag: ${p}`)}let h=function(e,t,n,o){if(void 0!==e.setValue){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==n){if(0===n.trim().length)throw new K("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:n,consumeNext:!1}}return void 0===o||e_(o)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(o)?{value:!0,consumeNext:!1}:{value:o,consumeNext:!0}}let r=n??o;if(void 0===r||void 0===n&&e_(r))throw new K("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===n};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:r,consumeNext:void 0===n}}let s=Number(r);if(!Number.isFinite(s)||"number"==typeof e.min&&s<e.min||"number"==typeof e.max&&s>e.max)throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:Math.floor(s),consumeNext:void 0===n}}(m,p,f,e[l+1]);h.consumeNext&&(l+=1);let g=t[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:void 0===g?[h.value]:[g,h.value];t[m.key]=e}else t[m.key]=h.value;r.push({key:m.key,token:p})}return{command:n,positionals:o,flags:t,warnings:[],providedFlags:r}}(t),r=l?.env??process.env,s=l?.cwd??process.cwd(),p=n.command,a=null!==p&&(c={remoteConfig:n.flags.remoteConfig,cwd:s,env:r}).remoteConfig?{...th(M({configPath:c.remoteConfig,cwd:c.cwd,env:c.env}).profile),remoteConfig:c.remoteConfig}:{},I=ep((i=(d={command:n.command,cwd:s,cliFlags:n.flags,env:r}).env??process.env,y=ep({},function(e){let t={};for(let n of e)ep(t,function(e,t){let n,r;if(!o.existsSync(e)){if(t)throw new K("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{n=o.readFileSync(e,"utf8")}catch(t){throw new K("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{r=JSON.parse(n)}catch(t){throw new K("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!r||"object"!=typeof r||Array.isArray(r))throw new K("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let n={};for(let[o,r]of Object.entries(e)){if("installSource"===o){n.installSource=u(r,t);continue}let e=eC.get(o);if(!e)throw new K("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new K("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);n[o]=F(eN(e),r,t,o)}return n}(r,`config file ${e}`)}(n.path,n.required));return t}((f=d.cwd,m=d.cliFlags.config,h=i,(x=m??h.AGENT_DEVICE_CONFIG)?[{path:(g=x,v=f,w=h,ea(g,{cwd:v,env:w})),required:!0}]:[{path:(b=h,e.join(ei("~",{env:b}),".agent-device","config.json")),required:!1},{path:e.resolve(f,"agent-device.json"),required:!1}]))),ep(y,function(e,t){var n,o,r;let s={};for(let a of eS.filter(e=>e.config.enabled&&e.supportsCommand(t))){if("installSource"===a.key)continue;let t=a.env.names.map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);t&&(s[a.key]=(n=t.value,o=`environment variable ${t.name}`,r=t.name,F(eN(a),n,o,r)))}return s}(i,d.command))),a),C={...function(e,t){let n=t?.strictFlags??!0,o=[...e.warnings],r=ep({json:!1,help:!1,version:!1},t?.defaultFlags??{});ep(r,e.flags);let s=e.providedFlags.filter(t=>!eD(t.key,e.command));if(s.length>0){var a,i;let t=s.map(e=>e.token),l=(a=e.command,i=t,a?1===i.length?`Flag ${i[0]} is not supported for command ${a}.`:`Flags ${i.join(", ")} are not supported for command ${a}.`:1===i.length?`Flag ${i[0]} requires a command that supports it.`:`Flags ${i.join(", ")} require a command that supports them.`);if(n)throw new K("INVALID_ARGS",l);for(let e of(o.push(l),s))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eD(t,e.command)||delete r[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new K("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),E(e.command,r),"batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new K("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:n,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(n,{strictFlags:l?.strictFlags,defaultFlags:I}),providedFlags:n.providedFlags}}catch(t){Q({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=H(t,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});i?eX({success:!1,error:e}):eY(e,{showDetails:a}),process.exit(1);return}for(let e of C.warnings)process.stderr.write(`Warning: ${e}
482
479
  `);C.flags.version&&(process.stdout.write(`${s}
483
480
  `),process.exit(0));let G="help"===C.command,q=C.flags.help;if(G||q){G&&C.positionals.length>1&&(eY(new K("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=G?C.positionals[0]:C.command;e||(process.stdout.write(`${eE()}
484
481
  `),process.exit(0));let t=function(e){var t,n;let o,r=(o=ew[e])?`${o.body}
@@ -497,7 +494,7 @@ Usage:
497
494
  ${c.join("\n\n")}
498
495
  `}(eP(e));t&&(process.stdout.write(t),process.exit(0)),eY(new K("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${eE()}
499
496
  `),process.exit(1)}C.command||(process.stdout.write(`${eE()}
500
- `),process.exit(1));let{command:z,positionals:J}=C,W=new Set(C.providedFlags.map(e=>e.key));try{U=(R=nk({policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session})).lockPolicy?{...C.flags}:n$(C.flags,{policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session}),P=y(U.stateDir),O=U.session??"default",I={command:z,explicitFlagKeys:W,stateDir:P.baseDir,session:O,remoteConfig:U.remoteConfig,hasResolvedSession:void 0!==U.session},j=(T="connect"===I.command||"connection"===I.command?null:function(e){let t=e.validateRemoteConfigHash??!0,n=e.remoteConfig?B({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=to(e)??(e.allowActiveFallback?td({stateDir:e.stateDir}):null);if(!o||n&&o.remoteConfigPath!==n)return null;if(t&&ti(o.remoteConfigPath)!==o.remoteConfigHash)throw new K("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:o.remoteConfigPath});let r=function(e,t){try{return M({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(!1===t.validateRemoteConfigHash)return{};throw e}}(o,e);return{runtime:o.runtime,flags:{...r,remoteConfig:o.remoteConfigPath,daemonBaseUrl:o.daemon?.baseUrl??r.daemonBaseUrl,daemonTransport:o.daemon?.transport??r.daemonTransport,daemonServerMode:o.daemon?.serverMode??r.daemonServerMode,tenant:o.tenant,sessionIsolation:"tenant",runId:o.runId,leaseId:o.leaseId,leaseBackend:o.leaseBackend,session:o.session,platform:o.platform??r.platform,target:o.target??r.target}}}({stateDir:I.stateDir,session:I.session,remoteConfig:I.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!I.explicitFlagKeys.has("session")&&(!I.remoteConfig||"disconnect"===I.command||!I.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==I.command}))?function(e,t,n){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(n.has(e)||(o[e]=r));return o}(U,T.flags,W):U}catch(t){let e=H(V(t),{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});C.flags.json?eX({success:!1,error:e}):eY(e,{showDetails:C.flags.verbose}),process.exit(1);return}let Z=null;try{let e;if("react-devtools"===z){let e=await nA(J,{flags:j,stateDir:P.baseDir,session:j.session??O,cwd:process.cwd(),env:process.env});process.exit(e);return}eu({command:z,currentVersion:s,stateDir:P.baseDir,flags:j});let t=T?.runtime,a=(e,t)=>({session:e.session??O,requestId:r,stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,tenant:e.tenant,sessionIsolation:e.sessionIsolation,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,runtime:t,lockPolicy:R.lockPolicy,lockPlatform:R.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===z){if(J.length>0)throw new K("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t,n,r,s="";if(e.steps)s=e.steps;else if(e.stepsFile)try{s=o.readFileSync(e.stepsFile,"utf8")}catch(n){let t=n instanceof Error?n.message:String(n);throw new K("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}var a,i=s;try{r=JSON.parse(i)}catch{throw new K("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(r)||0===r.length)throw new K("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return a=r,t=!1,n=a.map((e,n)=>{var o,r,s,a,i,l;let c;if(o=e,null!==o&&"object"==typeof o&&!Array.isArray(o)&&"input"in o&&!("positionals"in o)&&!("flags"in o))return e;let d=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Invalid batch step ${t}.`);var n=e,o=t;let r=Object.keys(n).filter(e=>!["command","positionals","flags","runtime"].includes(e));if(r.length>0)throw new K("INVALID_ARGS",`Batch step ${o} has unknown legacy field(s): ${r.join(", ")}.`);let s=function(e,t){let n="string"==typeof e?e.trim().toLowerCase():"";if(!n)throw new K("INVALID_ARGS",`Batch step ${t} requires command.`);if(er(n))return n;throw new K("INVALID_ARGS",`Batch step ${t} command is not available through command batch: ${String(e)}`)}(e.command,t),a=function(e,t){if(void 0!==e){if(!Array.isArray(e)||e.some(e=>"string"!=typeof e))throw new K("INVALID_ARGS",`Batch step ${t} positionals must contain only strings.`);return e}}(e.positionals,t),i=function(e,t){if(void 0!==e){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Batch step ${t} flags must be an object.`);return e}}(e.flags,t);return{command:s,...void 0===a?{}:{positionals:a},...void 0===i?{}:{flags:i},...void 0===e.runtime?{}:{runtime:e.runtime}}}(e,n+1);return t=!0,c=(s=(r=d).command,a=r.positionals??[],l=r.flags,i={json:!1,help:!1,version:!1,...l},nl[s](a,i)),{command:r.command,input:c,...void 0===r.runtime?{}:{runtime:r.runtime}}}),t&&process.stderr.write('Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.\n'),n}(U)}if(x=z,"auth"!==x&&"connection"!==x&&(j=(await tD({command:z,flags:j,stateDir:P.baseDir,env:process.env})).flags),j.remoteConfig&&(A=z,!nD.has(A))){let o=ec(a(j,t),{transport:n.sendToDaemon}),r=await tw({command:z,flags:j,client:o,runtime:t,batchSteps:e,forceRuntimePrepare:function(e){for(let t of nC)if(e.has(t))return!0;return!1}(W)});j=r.flags,t=r.runtime}$={command:z,flags:j,runtime:t,explicitFlagKeys:W,hadConnectionDefaults:!!T},!("open"===$.command&&!$.runtime&&!$.flags.bundleUrl&&!$.flags.metroHost&&!$.flags.metroPort&&!$.flags.remoteConfig&&!$.hadConnectionDefaults&&((k=$.explicitFlagKeys).has("daemonBaseUrl")||k.has("daemonTransport")||k.has("tenant")||k.has("sessionIsolation")||k.has("runId")||k.has("leaseId")||k.has("leaseBackend")))||process.stderr.write("Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.\n");let i=j.daemonBaseUrl;Z=!j.verbose||j.json||i?null:function(e){try{let t=o.existsSync(e)?o.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&o.existsSync(e))try{let n=o.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=o.openSync(e,"r");try{let e=Buffer.alloc(n.size-t);o.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{o.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}(P.logPath);let l=ec(a(j,t),{transport:n.sendToDaemon});if("batch"===z){if(!e)throw new K("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,input:R.lockPolicy&&void 0===U.platform?{...e.input}:n$(e.input,{policyOverrides:j,configuredPlatform:j.platform,configuredSession:j.session,inheritedPlatform:j.platform})}));if(await nb({command:z,positionals:J,flags:{...j,batchSteps:t},client:l}))return}else if("runtime"===z)throw new K("INVALID_ARGS","runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.");else if(await nb({command:z,positionals:J,flags:j,client:l}))return;throw new K("INVALID_ARGS",`Unknown command: ${z}`)}catch(n){let e=V(n),t=H(e,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});if("close"===z&&"COMMAND_FAILED"===(S=e).code&&(S.details?.kind==="daemon_startup_failed"||S.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof S.details?.infoPath||"string"==typeof S.details?.lockPath))){j.json&&eX({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(j.json)eX({success:!1,error:t});else if(eY(t,{showDetails:j.verbose}),j.verbose)try{let e=P.logPath;if(o.existsSync(e)){let t=o.readFileSync(e,"utf8").split("\n"),n=t.slice(Math.max(0,t.length-200)).join("\n");n.trim().length>0&&process.stderr.write(`
497
+ `),process.exit(1));let{command:z,positionals:J}=C,W=new Set(C.providedFlags.map(e=>e.key));try{U=(R=nD({policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session})).lockPolicy?{...C.flags}:nC(C.flags,{policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session}),P=y(U.stateDir),O=U.session??"default",I={command:z,explicitFlagKeys:W,stateDir:P.baseDir,session:O,remoteConfig:U.remoteConfig,hasResolvedSession:void 0!==U.session},j=(T="connect"===I.command||"connection"===I.command?null:function(e){let t=e.validateRemoteConfigHash??!0,n=e.remoteConfig?B({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=to(e)??(e.allowActiveFallback?td({stateDir:e.stateDir}):null);if(!o||n&&o.remoteConfigPath!==n)return null;if(t&&ti(o.remoteConfigPath)!==o.remoteConfigHash)throw new K("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:o.remoteConfigPath});let r=function(e,t){try{return M({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(!1===t.validateRemoteConfigHash)return{};throw e}}(o,e);return{runtime:o.runtime,flags:{...r,remoteConfig:o.remoteConfigPath,daemonBaseUrl:o.daemon?.baseUrl??r.daemonBaseUrl,daemonTransport:o.daemon?.transport??r.daemonTransport,daemonServerMode:o.daemon?.serverMode??r.daemonServerMode,tenant:o.tenant,sessionIsolation:"tenant",runId:o.runId,leaseId:o.leaseId,leaseBackend:o.leaseBackend,session:o.session,platform:o.platform??r.platform,target:o.target??r.target}}}({stateDir:I.stateDir,session:I.session,remoteConfig:I.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!I.explicitFlagKeys.has("session")&&(!I.remoteConfig||"disconnect"===I.command||!I.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==I.command}))?function(e,t,n){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(n.has(e)||(o[e]=r));return o}(U,T.flags,W):U}catch(t){let e=H(V(t),{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});C.flags.json?eX({success:!1,error:e}):eY(e,{showDetails:C.flags.verbose}),process.exit(1);return}let Z=null;try{let e;if("react-devtools"===z){let e=await nS(J,{flags:j,stateDir:P.baseDir,session:j.session??O,cwd:process.cwd(),env:process.env});process.exit(e);return}eu({command:z,currentVersion:s,stateDir:P.baseDir,flags:j});let t=T?.runtime,a=(e,t)=>({session:e.session??O,requestId:r,stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,tenant:e.tenant,sessionIsolation:e.sessionIsolation,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,runtime:t,lockPolicy:R.lockPolicy,lockPlatform:R.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===z){if(J.length>0)throw new K("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t,n,r,s="";if(e.steps)s=e.steps;else if(e.stepsFile)try{s=o.readFileSync(e.stepsFile,"utf8")}catch(n){let t=n instanceof Error?n.message:String(n);throw new K("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}var a,i=s;try{r=JSON.parse(i)}catch{throw new K("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(r)||0===r.length)throw new K("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return a=r,t=!1,n=a.map((e,n)=>{var o,r,s,a,i,l;let c;if(o=e,null!==o&&"object"==typeof o&&!Array.isArray(o)&&"input"in o&&!("positionals"in o)&&!("flags"in o))return e;let d=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Invalid batch step ${t}.`);var n=e,o=t;let r=Object.keys(n).filter(e=>!["command","positionals","flags","runtime"].includes(e));if(r.length>0)throw new K("INVALID_ARGS",`Batch step ${o} has unknown legacy field(s): ${r.join(", ")}.`);let s=function(e,t){let n="string"==typeof e?e.trim().toLowerCase():"";if(!n)throw new K("INVALID_ARGS",`Batch step ${t} requires command.`);if(er(n))return n;throw new K("INVALID_ARGS",`Batch step ${t} command is not available through command batch: ${String(e)}`)}(e.command,t),a=function(e,t){if(void 0!==e){if(!Array.isArray(e)||e.some(e=>"string"!=typeof e))throw new K("INVALID_ARGS",`Batch step ${t} positionals must contain only strings.`);return e}}(e.positionals,t),i=function(e,t){if(void 0!==e){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Batch step ${t} flags must be an object.`);return e}}(e.flags,t);return{command:s,...void 0===a?{}:{positionals:a},...void 0===i?{}:{flags:i},...void 0===e.runtime?{}:{runtime:e.runtime}}}(e,n+1);return t=!0,c=(s=(r=d).command,a=r.positionals??[],l=r.flags,i={json:!1,help:!1,version:!1,...l},nl[s](a,i)),{command:r.command,input:c,...void 0===r.runtime?{}:{runtime:r.runtime}}}),t&&process.stderr.write('Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.\n'),n}(U)}if(x=z,"auth"!==x&&"connection"!==x&&(j=(await tD({command:z,flags:j,stateDir:P.baseDir,env:process.env})).flags),j.remoteConfig&&(A=z,!nU.has(A))){let o=ec(a(j,t),{transport:n.sendToDaemon}),r=await tw({command:z,flags:j,client:o,runtime:t,batchSteps:e,forceRuntimePrepare:function(e){for(let t of nR)if(e.has(t))return!0;return!1}(W)});j=r.flags,t=r.runtime}$={command:z,flags:j,runtime:t,explicitFlagKeys:W,hadConnectionDefaults:!!T},!("open"===$.command&&!$.runtime&&!$.flags.bundleUrl&&!$.flags.metroHost&&!$.flags.metroPort&&!$.flags.remoteConfig&&!$.hadConnectionDefaults&&((k=$.explicitFlagKeys).has("daemonBaseUrl")||k.has("daemonTransport")||k.has("tenant")||k.has("sessionIsolation")||k.has("runId")||k.has("leaseId")||k.has("leaseBackend")))||process.stderr.write("Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.\n");let i=j.daemonBaseUrl;Z=!j.verbose||j.json||i?null:function(e){try{let t=o.existsSync(e)?o.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&o.existsSync(e))try{let n=o.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=o.openSync(e,"r");try{let e=Buffer.alloc(n.size-t);o.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{o.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}(P.logPath);let l=ec(a(j,t),{transport:n.sendToDaemon});if("batch"===z){if(!e)throw new K("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,input:R.lockPolicy&&void 0===U.platform?{...e.input}:nC(e.input,{policyOverrides:j,configuredPlatform:j.platform,configuredSession:j.session,inheritedPlatform:j.platform})}));if(await nA({command:z,positionals:J,flags:{...j,batchSteps:t},client:l}))return}else if("runtime"===z)throw new K("INVALID_ARGS","runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.");else if(await nA({command:z,positionals:J,flags:j,client:l}))return;throw new K("INVALID_ARGS",`Unknown command: ${z}`)}catch(n){let e=V(n),t=H(e,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});if("close"===z&&"COMMAND_FAILED"===(S=e).code&&(S.details?.kind==="daemon_startup_failed"||S.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof S.details?.infoPath||"string"==typeof S.details?.lockPath))){j.json&&eX({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(j.json)eX({success:!1,error:t});else if(eY(t,{showDetails:j.verbose}),j.verbose)try{let e=P.logPath;if(o.existsSync(e)){let t=o.readFileSync(e,"utf8").split("\n"),n=t.slice(Math.max(0,t.length-200)).join("\n");n.trim().length>0&&process.stderr.write(`
501
498
  [daemon log]
502
499
  ${n}
503
- `)}}catch{}Z&&Z(),process.exit(1)}finally{Z&&Z()}})}n(process.argv[1]??"").href===import.meta.url&&nN(process.argv.slice(2)).catch(e=>{eY(H(V(e)),{showDetails:!0}),process.exit(1)});export{nN as runCli};
500
+ `)}}catch{}Z&&Z(),process.exit(1)}finally{Z&&Z()}})}n(process.argv[1]??"").href===import.meta.url&&n_(process.argv.slice(2)).catch(e=>{eY(H(V(e)),{showDetails:!0}),process.exit(1)});export{n_ as runCli};