agent-device 0.16.4 → 0.16.6

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.
Files changed (75) hide show
  1. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.4.apk → agent-device-android-multitouch-helper-0.16.6.apk} +0 -0
  2. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.6.apk.sha256 +1 -0
  3. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.4.manifest.json → agent-device-android-multitouch-helper-0.16.6.manifest.json} +4 -4
  4. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.6.apk +0 -0
  5. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.6.apk.sha256 +1 -0
  6. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.4.manifest.json → agent-device-android-snapshot-helper-0.16.6.manifest.json} +6 -6
  7. package/dist/src/1010.js +1 -0
  8. package/dist/src/1231.js +1 -1
  9. package/dist/src/1352.js +1 -0
  10. package/dist/src/1998.js +1 -0
  11. package/dist/src/208.js +1 -1
  12. package/dist/src/221.js +6 -6
  13. package/dist/src/2415.js +31 -0
  14. package/dist/src/2805.js +1 -0
  15. package/dist/src/5186.js +1 -0
  16. package/dist/src/5310.js +1 -0
  17. package/dist/src/5792.js +1 -0
  18. package/dist/src/6085.js +1 -0
  19. package/dist/src/6629.js +1 -0
  20. package/dist/src/8114.js +4 -0
  21. package/dist/src/8133.js +1 -0
  22. package/dist/src/8502.js +1 -0
  23. package/dist/src/8699.js +1 -0
  24. package/dist/src/8806.js +7 -0
  25. package/dist/src/940.js +1 -1
  26. package/dist/src/9404.js +1 -0
  27. package/dist/src/9471.js +1 -0
  28. package/dist/src/9533.js +1 -0
  29. package/dist/src/9542.js +3 -3
  30. package/dist/src/9639.js +1 -1
  31. package/dist/src/9671.js +1 -0
  32. package/dist/src/android-adb.js +1 -1
  33. package/dist/src/android-snapshot-helper.d.ts +2 -1
  34. package/dist/src/android-snapshot-helper.js +1 -1
  35. package/dist/src/android.js +5 -0
  36. package/dist/src/apple.js +1 -0
  37. package/dist/src/apps.js +13 -0
  38. package/dist/src/args.js +449 -0
  39. package/dist/src/batch.js +1 -1
  40. package/dist/src/cli.js +36 -492
  41. package/dist/src/command-metadata.js +1 -0
  42. package/dist/src/command-surface.js +1 -0
  43. package/dist/src/contracts.d.ts +1 -0
  44. package/dist/src/devices.js +1 -0
  45. package/dist/src/devices~1.js +1 -0
  46. package/dist/src/devices~2.js +1 -0
  47. package/dist/src/find.js +1 -0
  48. package/dist/src/finders.d.ts +1 -0
  49. package/dist/src/generic.js +9 -0
  50. package/dist/src/index.d.ts +12 -0
  51. package/dist/src/input-actions.js +1 -0
  52. package/dist/src/input-actions~1.js +1 -0
  53. package/dist/src/interaction.js +1 -0
  54. package/dist/src/internal/bin.js +5 -2
  55. package/dist/src/internal/daemon.js +1 -100
  56. package/dist/src/lease.js +1 -0
  57. package/dist/src/linux.js +1 -0
  58. package/dist/src/notifications.js +1 -0
  59. package/dist/src/react-native.js +1 -0
  60. package/dist/src/record-trace.js +26 -0
  61. package/dist/src/recording-provider.js +1 -0
  62. package/dist/src/selector-runtime.js +1 -0
  63. package/dist/src/selectors.d.ts +1 -0
  64. package/dist/src/server.js +1 -1
  65. package/dist/src/session.js +29 -0
  66. package/dist/src/snapshot.js +2 -0
  67. package/package.json +4 -1
  68. package/server.json +2 -2
  69. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.4.apk.sha256 +0 -1
  70. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.4.apk +0 -0
  71. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.4.apk.sha256 +0 -1
  72. package/dist/src/1769.js +0 -7
  73. package/dist/src/6277.js +0 -4
  74. package/dist/src/7519.js +0 -1
  75. package/dist/src/89.js +0 -1
@@ -0,0 +1,29 @@
1
+ import{__webpack_require__ as e}from"./rslib-runtime.js";import t,{promises as r}from"node:fs";import n from"node:os";import a from"node:path";import{fileURLToPath as i}from"node:url";import{setTimeout as o}from"node:timers/promises";import{parseAllDocuments as s}from"yaml";import l from"node:vm";import{asAppError as u,normalizeError as c,AppError as d}from"./9152.js";import{runXcrun as p,resolveAppleSimulatorSetPathForSelector as f,dispatchCommand as m,appendAppLogMarker as h,selectorTargetsSessionDevice as g,resolveCommandDevice as w,hasExplicitSessionFlag as y,hasRuntimeTransportHints as v,inferFillText as A,formatPortableActionLine as b,stopIosRunnerSession as S,requireSessionOrExplicitSelector as I,isTouchTargetCommand as _,cleanupUploadedArtifact as N,isClickLikeCommand as M,refreshSessionDeviceIfNeeded as x,createRequestCanceledError as D,resolveIosDevicectlHint as k,registerRequestAbort as O,errorResponse as R,IOS_SIMULATOR_POST_OPEN_SETTLE_MS as L,parseReplayOpenFlags as $,IOS_SIMULATOR_POST_CLOSE_SETTLE_MS as P,settleIosSimulator as F,uniqueStrings as C,applyRuntimeHintsToApp as E,withKeyedLock as V,resolveTargetDevice as U,getAppLogPathMetadata as T,parseReplayRuntimeFlags as G,setSessionSnapshot as j,getSnapshotReferenceFrame as q,clearRuntimeHintsFromApp as K,handleCloseCommand as H,clearAppLogFiles as B,readSessionNetworkCapture as W,cleanupRetainedMaterializedPaths as z,IOS_DEVICECTL_DEFAULT_HINT as J,buildSnapshotState as X,context_contextFromFlags as Y,listDeviceInventory as Z,SessionStore as Q,formatScriptStringLiteral as ee,formatScriptActionSummary as et,isRequestCanceled as er,resolveRequestTrackingId as en,retainMaterializedPaths as ea,runAppLogDoctor as ei,resolvePayloadInput as eo,prepareUploadedArtifact as es,stopAppLog as el,markRequestCanceled as eu,ensureDeviceReady as ec,prewarmIosRunnerSession as ed,clearRequestCanceled as ep,resolveAndroidEmulatorAvdName as ef,buildSimctlArgsForDevice as em,parseReplaySeriesFlags as eh,parseXmlDocumentSync as eg,resolveFrontmostMacOsApp as ew,runAppleToolCommand as ey,listIosDeviceApps as ev,isCommandSupportedOnDevice as eA,isApplePlatform as eb,listIosDeviceProcesses as eS,normalizePlatformSelector as eI,getRequestSignal as e_,startAppLog as eN,markAndroidSnapshotFreshness as eM,emitRequestProgress as ex}from"./2415.js";import{withSuccessText as eD,successText as ek}from"./1998.js";import{splitNonEmptyTrimmedLines as eO,resolveDeployResultTarget as eR,resolveInstallFromSourceResultTarget as eL}from"./2805.js";import{parseSessionSurface as e$,MAESTRO_COMPAT_TRACKER_URL as eP,MAESTRO_NEW_ISSUE_URL as eF}from"./1352.js";import{resolveAndroidAdbExecutor as eC}from"./9639.js";import{resolveIosSimulatorDeviceSetPath as eE,classifyAndroidAppTarget as eV,resolveIosDeviceDeepLinkBundleId as eU,isInfrastructureBootFailureReason as eT,isWebUrl as eG,resolveAndroidSerialAllowlist as ej,isDeepLinkTarget as eq,formatAndroidInstalledPackageRequiredMessage as eK,listAndroidApps as eH}from"./8806.js";import{runBatch as eB,mergeParentFlags as eW}from"./1231.js";import{assertResolvedAppsFilter as ez}from"./1393.js";import{listIosApps as eJ,readInfoPlistString as eX}from"./apps.js";import{readScreenshotScriptFlag as eY}from"./5310.js";import{emitDiagnostic as eZ}from"./7599.js";import{runCmdSync as eQ}from"./9818.js";import{splitSelectorFromArgs as e0,extractNodeText as e1,findSnapshotAncestor as e2,isDescendantOfSnapshotNode as e3,splitIsSelectorArgs as e5,tryParseSelectorChain as e6,parseSelectorChain as e8,resolveSelectorChain as e9,buildSelectorChainForNode as e4,buildSnapshotNodeByIndex as e7,matchesSelector as te,normalizeType as tt}from"./940.js";import{normalizeText as tr}from"./7556.js";import{pointFromPercent as tn,clampToRange as ta,buildSwipeGesturePlan as ti,interiorCoordinate as to,evaluateIsPredicate as ts,pointInsideRect as tl,detectReactNativeOverlay as tu,clampGesturePoint as tc}from"./9533.js";import{sleep as td}from"./4829.js";import{INTERNAL_COMMANDS as tp,DAEMON_COMMAND_GROUPS as tf,PUBLIC_COMMANDS as tm}from"./5792.js";import{trimRuntimeValue as th}from"./8656.js";var tg={};async function tw(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new d("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await ec(e.session.device),e.session.device}if(!r)throw new d("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let n=await U(e.flags??{});return await ec(n),n}async function ty(e){let{prepared:t,retention:r,req:n,session:a,sessionName:i}=e;if(r.enabled)return await ea({archivePath:t.archivePath,installablePath:t.installablePath,tenantId:n.meta?.tenantId,sessionName:a?i:void 0,ttlMs:r.ttlMs})}function tv(e){return e?{...e.archivePath?{archivePath:e.archivePath}:{},installablePath:e.installablePath,materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}}async function tA(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);try{let e,i,o=(e=function(e){let t=e.meta?.installSource;if(!t)throw new d("INVALID_ARGS","install_from_source requires a source payload");switch(t.kind){case"url":if(!t.url||0===t.url.trim().length)throw new d("INVALID_ARGS","install_from_source url source requires a non-empty url");return t;case"path":if(!t.path||0===t.path.trim().length)throw new d("INVALID_ARGS","install_from_source path source requires a non-empty path");return t;case"github-actions-artifact":throw new d("UNSUPPORTED_OPERATION","install_from_source github-actions-artifact sources require a compatible remote daemon");default:throw new d("UNSUPPORTED_OPERATION",`install_from_source ${String(t.kind)} sources require a compatible remote daemon`)}}(t),(i=t.meta?.uploadedArtifactId)&&"path"===e.kind?{source:{kind:"path",path:es(i,t.meta?.tenantId)},cleanup:()=>{N(i)}}:{source:e,cleanup:()=>{}}),s=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new d("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),l=await tw({session:a,flags:t.flags});if(!eA("install",l))return R("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let u=e_(t.meta?.requestId),c=async(e,i)=>{let l;try{var u;l=await ty({prepared:e,retention:s,req:t,session:a,sessionName:r});let o=await i(l),c=eD(o,(u=o,`Installed: ${eL(u)}`));return!function(e){let{session:t,sessionStore:r,req:n,data:a}=e;t&&r.recordAction(t,{command:"install_source",positionals:[],flags:n.flags??{},result:a})}({session:a,sessionStore:n,req:t,data:c}),{ok:!0,data:c}}catch(e){throw l&&await z(l.materializationId,t.meta?.tenantId).catch(()=>{}),e}finally{await e.cleanup(),o.cleanup()}};if("ios"===l.platform){let{installIosInstallablePath:e}=await import("./apps.js"),{prepareIosInstallArtifact:t}=await import("./apps.js"),r=await t(o.source,{signal:u});return await c(r,async t=>{if(await e(l,r.installablePath),!r.bundleId)throw new d("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");return{...tv(t),bundleId:r.bundleId,...r.appName?{appName:r.appName}:{},launchTarget:r.bundleId}})}let{prepareAndroidInstallArtifact:p}=await import("./8806.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("./8806.js"),m=await p(o.source,{signal:u});return await c(m,async e=>{let t=await f(l,m.installablePath,m.packageName);if(!t)throw new d("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:r}=await import("./8806.js"),n=r(t);return{...tv(e),packageName:t,...n?{appName:n}:{},launchTarget:t}})}catch(e){return{ok:!1,error:c(e)}}}async function tb(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new d("INVALID_ARGS","release_materialized_paths requires a materializationId");return await z(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:c(e)}}}e.r(tg),e.d(tg,{SESSION_COMMAND_HANDLERS:()=>iF,handleSessionCommands:()=>iV});let tS=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function tI(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function t_(e,t){if(void 0!==e){if("string"!=typeof e)throw new d("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return th(e)}}function tN(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new d("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function tM(e){if("ios"===e||"android"===e)return e}async function tx(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:n,session:a}=e;!t||!a?.appBundleId||!v(r)||v(n)||await K({device:a.device,appId:a.appBundleId})}async function tD(e){var t,r;let{req:n,sessionName:a,sessionStore:i}=e,o=(n.positionals?.[0]??"show").toLowerCase(),s=i.get(a),l=i.getRuntimeHints(a);if(!["set","show","clear"].includes(o))return R("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){v(l)&&s?.appBundleId&&await K({device:s.device,appId:s.appBundleId});let e=i.clearRuntimeHints(a);return{ok:!0,data:{session:a,cleared:e}}}if("show"===o)return{ok:!0,data:{session:a,configured:!!l,runtime:l}};let u=tM(eI(n.flags?.platform)??l?.platform??s?.device.platform);if(!u)return R("INVALID_ARGS","runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first.");if(s&&s.device.platform!==u)return R("INVALID_ARGS",`runtime set targets ${u}, but session "${a}" is already bound to ${s.device.platform}.`);let c={platform:(t=n.flags,r={platform:u,metroHost:th(t?.metroHost),metroPort:tN(t?.metroPort),bundleUrl:th(t?.bundleUrl),launchUrl:th(t?.launchUrl)}).platform??l?.platform,metroHost:r.metroHost??l?.metroHost,metroPort:r.metroPort??l?.metroPort,bundleUrl:r.bundleUrl??l?.bundleUrl,launchUrl:r.launchUrl??l?.launchUrl};return 0===tI(c)?R("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(i.setRuntimeHints(a,c),{ok:!0,data:{session:a,configured:!0,runtime:c}})}let tk="open-command-roundtrip",tO="Not implemented for this platform in this release.",tR=new Set(["app","desktop","frontmost-app"]);async function tL(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await ew();return{appBundleId:t.bundleId,appName:t.appName}}function t$(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}function tP(e){return Math.round(10*e)/10}function tF(e){return Math.round(10*e)/10}let tC="adb-shell-dumpsys-gfxinfo-framestats";function tE(e,t,r){let n=t.get(r);if(void 0===n)return null;let a=Number(e[n]);return Number.isFinite(a)?a:null}function tV(e){return 0===e.length?{}:{firstFrameNs:Math.min(...e.map(e=>e.intendedVsyncNs)),lastFrameNs:Math.max(...e.map(e=>e.frameCompletedNs))}}function tU(e,t){if(void 0!==e&&void 0!==t)return Math.max(0,Math.round((t-e)/1e6))}function tT(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=e.match(RegExp(`^\\s*${r}:\\s*([0-9][0-9,]*)`,"im"));if(!n)return;let a=n[1];return void 0===a?void 0:t$(a)??void 0}async function tG(e,t,r={}){var n,a,i,o,s,l,u,c;let p=eC(e,r.adb);try{let u,c,f,m,h,g,w,y,v,A,b,S=(n=(await p(["shell","dumpsys","gfxinfo",t,"framestats"],{timeoutMs:15e3})).stdout,a=new Date().toISOString(),function(e,t){if(/no process found for:/i.test(e))throw new d("COMMAND_FAILED",`Android gfxinfo did not find a running process for ${t}`,{metric:"fps",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf after the interaction you want to inspect."})}(n,t),f=function(e){let t=e.split(/\nProfile data in ms:\n/i)[0]??"",r=tT(t,"Total frames rendered"),n=t.match(/^\s*Janky frames:\s*([0-9][0-9,]*)\s*\(([0-9.]+)%\)/im);if(void 0===r||!n)return;let a=n[1],i=n[2];if(void 0===a||void 0===i)return;let o=t$(a)??void 0,s=Number(i);if(void 0===o||!Number.isFinite(s)||r<0)return;let l=tT(t,"Uptime"),u=tT(t,"Stats since");return{droppedFramePercent:tP(s),droppedFrameCount:o,totalFrameCount:r,sampleWindowMs:function(e){let{uptimeMs:t,statsSinceNs:r}=e;if(void 0===t||void 0===r)return;let n=t-Math.round(r/1e6);return n>=0?n:void 0}({uptimeMs:l,statsSinceNs:u}),uptimeMs:l,statsSinceNs:u}}(n),m=function(e){let t=[],r=null;for(let a of e.split("\n")){var n;let e=a.trim();if(0===e.length||"---PROFILEDATA---"===e)continue;let i=e.split(",").map(e=>e.trim());if((n=i).includes("IntendedVsync")&&n.includes("FrameCompleted")){r=new Map(i.map((e,t)=>[e,t]));continue}let o=function(e,t){if(!t||e.length<t.size)return;let r=tE(e,t,"Flags"),n=tE(e,t,"IntendedVsync"),a=tE(e,t,"FrameCompleted");if(0===r&&null!==n&&null!==a&&!(n<=0)&&!(a<=n))return{intendedVsyncNs:n,frameCompletedNs:a,durationNs:a-n}}(i,r);o&&t.push(o)}return t.sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs)}(n),h=function(e,t,r){let n=function(e){var t;let r=(t=e.map(e=>e.intendedVsyncNs),[...new Set(t.filter(e=>Number.isFinite(e)))].sort((e,t)=>e-t)),n=[];for(let e=1;e<r.length;e+=1){let t=r[e]-r[e-1];t>=4e6&&t<=5e7&&n.push(t)}if(0!==n.length){let e,t;return e=[...n].sort((e,t)=>e-t),t=Math.floor(e.length/2),e.length%2==1?e[t]:(e[t-1]+e[t])/2}}(e);if(t||0!==e.length||function(e){throw new d("COMMAND_FAILED",`Failed to parse Android framestats output for ${e}`,{metric:"fps",package:e,hint:"Retry perf after exercising the app screen. If the problem persists, capture adb shell dumpsys gfxinfo <package> framestats output for debugging."})}(r),t||void 0!==n)return n;throw new d("COMMAND_FAILED",`Failed to infer Android frame deadline from framestats output for ${r}`,{metric:"fps",package:r,hint:"Retry perf after a longer interaction window so consecutive Android frame timestamps are available."})}(m,f,t),g=Date.parse(a),w=function(e){let{frames:t,measuredAtMs:r,summary:n}=e,a=tV(t),i=n?.statsSinceNs,o=i??a.firstFrameNs,s=tU(o,a.lastFrameNs),l=n?.sampleWindowMs??s;if(!Number.isFinite(r)||n?.uptimeMs===void 0||void 0===o)return{sampleWindowMs:l,windowStartNs:o};let u=r-n.uptimeMs;return{sampleWindowMs:l,windowStartNs:o,windowStartedAt:new Date(u+o/1e6).toISOString(),windowEndedAt:function(e){let{deviceBootWallClockMs:t,measuredAtMs:r,summaryStartNs:n,lastFrameNs:a}=e;return void 0!==n?new Date(r).toISOString():void 0===a?void 0:new Date(t+a/1e6).toISOString()}({deviceBootWallClockMs:u,measuredAtMs:r,summaryStartNs:i,lastFrameNs:a.lastFrameNs}),timestampSource:"estimated-from-device-uptime"}}({frames:m,measuredAtMs:g,summary:f}),y=function(e){let{frames:t,frameDeadlineNs:r,summaryDroppedFrameCount:n}=e;return void 0!==n?n<=0?[]:[...t].sort((e,t)=>t.durationNs-e.durationNs).slice(0,n).sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs):void 0===r?[]:t.filter(e=>e.durationNs>r)}({frames:m,frameDeadlineNs:h,summaryDroppedFrameCount:f?.droppedFrameCount}),v=f?.sampleWindowMs??w.sampleWindowMs??function(e){if(0===e.length)return;let t=tV(e);return tU(t.firstFrameNs,t.lastFrameNs)}(m),i=f,o=m,s=y,u=i?.totalFrameCount??o.length,c=i?.droppedFrameCount??s.length,A={totalFrameCount:u,droppedFrameCount:c,droppedFramePercent:i?.droppedFramePercent??(u>0?tP(c/u*100):0)},b=function(e){let{droppedFrames:t,timing:r,measuredAtMs:n,summary:a}=e;if(0===t.length)return;let i=function(e){let{frames:t,windowStartNs:r,measuredAtMs:n,uptimeMs:a}=e;if(0===t.length||void 0===r)return[];let i=[],o=[];for(let e of t){let t=o.at(-1);if(!t||e.intendedVsyncNs-t.frameCompletedNs<=5e8){o.push(e);continue}i.push(o),o=[e]}return o.length>0&&i.push(o),i.map(e=>(function(e){let{frames:t,windowStartNs:r,measuredAtMs:n,uptimeMs:a}=e,i=Math.min(...t.map(e=>e.intendedVsyncNs)),o=Math.max(...t.map(e=>e.frameCompletedNs)),s=Math.max(0,Math.round((i-r)/1e6)),l=Math.max(s,Math.round((o-r)/1e6)),u=void 0!==a&&Number.isFinite(n)?n-a:void 0;return{startOffsetMs:s,endOffsetMs:l,startAt:void 0===u?void 0:new Date(u+i/1e6).toISOString(),endAt:void 0===u?void 0:new Date(u+o/1e6).toISOString(),missedDeadlineFrameCount:t.length,worstFrameMs:tF(Math.max(...t.map(e=>e.durationNs))/1e6)}})({frames:e,windowStartNs:r,measuredAtMs:n,uptimeMs:a})).sort((e,t)=>t.missedDeadlineFrameCount-e.missedDeadlineFrameCount||t.worstFrameMs-e.worstFrameMs).slice(0,3).sort((e,t)=>e.startOffsetMs-t.startOffsetMs)}({frames:t,windowStartNs:r.windowStartNs,measuredAtMs:n,uptimeMs:a?.uptimeMs});return i.length>0?i:void 0}({droppedFrames:y,timing:w,measuredAtMs:g,summary:f}),{...A,sampleWindowMs:v,...(l=h,{frameDeadlineMs:void 0===l?void 0:tF(l/1e6),refreshRateHz:void 0===l?void 0:tF(1e9/l)}),windowStartedAt:w.windowStartedAt,windowEndedAt:w.windowEndedAt,timestampSource:w.timestampSource,measuredAt:a,method:tC,source:f?"android-gfxinfo-summary":"framestats-rows",worstWindows:b&&b.length>0?b:void 0});return await tj(e,t,r),S}catch(e){throw u=t,(c=e)instanceof d?new d(c.code,c.message,{...c.details??{},metric:"fps",package:u},c):new d("COMMAND_FAILED",`Failed to sample Android fps for ${u}`,{metric:"fps",package:u},c)}}async function tj(e,t,r={}){let n=eC(e,r.adb);try{await n(["shell","dumpsys","gfxinfo",t,"reset"],{allowFailure:!0,timeoutMs:3e3})}catch{}}let tq="adb-shell-dumpsys-cpuinfo",tK="adb-shell-dumpsys-meminfo";async function tH(e,t,r={}){let n=eC(e,r.adb);try{let e=await n(["shell","dumpsys","cpuinfo"],{timeoutMs:15e3});return function(e,t,r){let n=new Set,a=0;for(let r of eO(e)){var i,o;let e=r.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!e)continue;let s=e[1],l=e[2];if(void 0===s||void 0===l)continue;let u=Number(s);Number.isFinite(u)&&(i=l,o=t,i===o||i.startsWith(`${o}:`))&&(a+=u,n.add(l))}return{usagePercent:tP(a),measuredAt:r,method:tq,matchedProcesses:[...n]}}(e.stdout,t,new Date().toISOString())}catch(e){throw tW("cpu",t,e)}}async function tB(e,t,r={}){let n=eC(e,r.adb);try{let e=await n(["shell","dumpsys","meminfo",t],{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new d("COMMAND_FAILED",`Android meminfo did not find a running process for ${t}`,{metric:"memory",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf."});let n=tz(e,"TOTAL PSS")??function(e){for(let t of e.split("\n")){let e=t.trim();if(!/^TOTAL\b(?!\s+PSS:)/.test(e))continue;let r=e.split(/\s+/).slice(1).find(e=>null!==t$(e));if(!r)break;return t$(r)??void 0}}(e);if(void 0===n)throw new d("COMMAND_FAILED",`Failed to parse Android meminfo output for ${t}`,{metric:"memory",package:t,hint:"Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging."});return{totalPssKb:n,totalRssKb:tz(e,"TOTAL RSS"),measuredAt:r,method:tK}}(e.stdout,t,new Date().toISOString())}catch(e){throw tW("memory",t,e)}}function tW(e,t,r){return r instanceof d?new d(r.code,r.message,{...r.details??{},metric:e,package:t},r):new d("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function tz(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(!n)return;let a=n[1];return void 0===a?void 0:t$(a)??void 0}async function tJ(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return eq(t)?"macos"===e.platform?void 0:"device"===e.kind?eU(r,t):eG(t)?void 0:r??await tX(e,t):await tY(e,t)}async function tX(e,t){try{let{resolveIosSimulatorDeepLinkBundleId:r}=await import("./apps.js");return await r(e,t)}catch{return}}async function tY(e,t){try{let{resolveIosApp:r}=await import("./apps.js");return await r(e,t)}catch{return}}async function tZ(e,t){if(!("android"!==e.platform||!t||eq(t)))try{let{resolveAndroidApp:r}=await import("./8806.js"),n=await r(e,t);return"package"===n.type?n.value:void 0}catch{return}}async function tQ(e,t,r){if(r||"android"!==e.platform||!t||!eq(t))return r;try{let{getAndroidAppState:t}=await import("./8806.js"),n=await t(e);return n.package?.trim()||r}catch{return r}}async function t0(e,t,r,n){return await tJ(e,t,r)??await n(e,t)??("android"===e.platform&&t&&eq(t)?r:void 0)}function t1(e){return R("INVALID_ARGS",e)}function t2(e,t,r,n){try{return function(e){let{device:t,surfaceFlag:r,openTarget:n,existingSurface:a}=e;if(("macos"===t.platform||"linux"===t.platform)&&!r)return a??"app";if("linux"===t.platform){if(!r)return"app";let e=e$(r);if(!tR.has(e))throw new d("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&n)throw new d("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new d("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let i=r?e$(r):"app";if("app"!==i&&"menubar"!==i&&n)throw new d("INVALID_ARGS",`open --surface ${i} does not accept an app target`);return i}({device:e,surfaceFlag:t,openTarget:r,existingSurface:n})}catch(e){return R(e instanceof d?e.code:"INVALID_ARGS",String(e.message))}}function t3(e){let{shouldRelaunch:t,openTarget:r,surface:n,device:a}=e;return t?r&&eq(r)?t1("open --relaunch does not support URL targets."):"app"!==n?t1("open --relaunch is supported only for app surfaces."):"android"===a.platform&&r&&"binary"===eV(r)?t1(eK(r)):null:null}async function t5(e){let{req:t,sessionName:r,sessionStore:n,device:a,surface:i,openTarget:o,existingSession:s}=e;await ec(a);let{appBundleId:l,appName:c}=await t6({device:a,surface:i,openTarget:o,existingAppBundleId:s?.appBundleId}),p=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:n,device:a}=e,i=r.getRuntimeHints(n),o=function(e){let{runtime:t,sessionName:r,platform:n}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new d("INVALID_ARGS","open runtime must be an object.");let a=Object.keys(t).find(e=>!tS.includes(e));if(a)throw new d("INVALID_ARGS",`Invalid open runtime field: ${a}. Supported fields are ${tS.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new d("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new d("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,n),metroHost:t_(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new d("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return tN(e)}}(t.metroPort),bundleUrl:t_(t.bundleUrl,"bundleUrl"),launchUrl:t_(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:n,platform:tM(a.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let n=e.getRuntimeHints(t);if(!n)return;let a=r?.platform,i=tM(a);if(n.platform&&r&&!i)throw new d("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${a}.`);if(n.platform&&i&&n.platform!==i)throw new d("INVALID_ARGS",`Session runtime hints target ${n.platform}, but session "${t}" is bound to ${a}. Clear the runtime hints or use a different session.`);return i&&n.platform!==i?{...n,platform:i}:n}(r,n,a),previousRuntime:i,replacedStoredRuntime:!1}:{runtime:o&&tI(o)>0?o:void 0,previousRuntime:i,replacedStoredRuntime:!0}}(e)}}catch(t){let e=u(t);return R(e.code,e.message,e.details)}}({req:t,sessionStore:n,sessionName:r,device:a});if(!p.ok)return{type:"response",response:p};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=p.data;await tx({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:c,runtime:p.data.runtime}}}async function t6(e){let{device:t,surface:r,openTarget:n,existingAppBundleId:a}=e,i=await tL(r);return{appBundleId:i.appBundleId??await t0(t,n,a,tZ),appName:i.appName??n}}let t8=new Map;async function t9(e){let{device:t,closeTarget:r,outFlag:n,context:a}=e;"android"!==t.platform&&await S(t.id),await m(t,"close",[r],n,a),await F(t,P)}async function t4(e){var t,r;let n,{runtime:a,device:i,req:o,logPath:s,appBundleId:l,traceLogPath:u,openPositionals:c}=e,d=a?.launchUrl;if(!d||0===c.length||c.length>1)return;let p=c[0]?.trim();!p||eq(p)||await m(i,"open",[d],o.flags?.out,{...(t=s,r=o.flags,n=Y(t,r,l,u),delete n.launchConsole,delete n.launchArgs,n)})}async function t7(e){var t,r,n,a;let i,{req:o,sessionName:s,sessionStore:l,logPath:u,device:c,openTarget:d,openPositionals:p,appName:f,surface:h,appBundleId:g,runtime:w,existingSession:y}=e,v=o.flags?.relaunch===!0,A=y?.trace?.outPath,b=g,S=Date.now(),I={};if(v&&d){let e=b??d,t=Date.now();await t9({device:c,closeTarget:e,outFlag:o.flags?.out,context:{...Y(u,o.flags,b??y?.appBundleId,A)}}),I.relaunchCloseDurationMs=Math.max(0,Date.now()-t)}let _=Date.now();await E({device:c,appId:b,runtime:w}),I.runtimeHintsDurationMs=Math.max(0,Date.now()-_);let N="ios"===c.platform&&"app"===h&&p.length>0,M={verbose:o.flags?.verbose,logPath:u,traceLogPath:A,requestId:o.meta?.requestId};N&&b&&(I.runnerPrewarmKind="session",I.runnerPrewarmScheduled=!0,i=ed(c,M));let x=Date.now();await m(c,"open",p,o.flags?.out,{...Y(u,o.flags,b)}),I.openDispatchDurationMs=Math.max(0,Date.now()-x);let k=Date.now();if(await t4({runtime:w,device:c,req:o,logPath:u,appBundleId:b,traceLogPath:A,openPositionals:p}),I.launchUrlDurationMs=Math.max(0,Date.now()-k),v&&i){let e=Date.now();await i,I.runnerPrewarmWaited=!0,I.runnerPrewarmDurationMs=Math.max(0,Date.now()-e)}else i&&(I.runnerPrewarmWaited=!1);b=await tQ(c,d,b),"android"===c.platform&&b&&await tj(c,b);let O=d?(t=b,{durationMs:Math.max(0,Date.now()-x),measuredAt:new Date().toISOString(),method:tk,appTarget:d,appBundleId:t}):void 0,$=Date.now();if(await F(c,L),I.postOpenSettleDurationMs=Math.max(0,Date.now()-$),er(o.meta?.requestId)){let e=D();return R(e.code,e.message,e.details)}y&&eM(y,"open",y.snapshot);let P=function(e){let{existingSession:t,sessionName:r,device:n,surface:a,appBundleId:i,appName:o,saveScript:s}=e;return t?{...t,device:n,surface:a,appBundleId:i,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:n,createdAt:Date.now(),surface:a,appBundleId:i,appName:o,recordSession:s,actions:[]}}({existingSession:y,sessionName:s,device:c,surface:h,appBundleId:b,appName:f,saveScript:!!o.flags?.saveScript});void 0!==o.runtime&&(r=l,n=s,(a=w)&&(0===tI(a)?r.clearRuntimeHints(n):r.setRuntimeHints(n,a))),I.totalDurationMs=Math.max(0,Date.now()-S);let C=function(e){let{sessionName:t,appName:r,appBundleId:n,surface:a,startup:i,timing:o,device:s,runtime:l,runtimeHintCount:u}=e,c={session:t,surface:a};return r&&(c.appName=r),n&&(c.appBundleId=n),i&&(c.startup=i),o&&(c.timing=o),l&&u(l)>0&&(c.runtime=l),s&&(c.platform=s.platform,c.target=s.target??"mobile",c.device=s.name,c.id=s.id,c.kind=s.kind,"android"===s.platform&&(c.serial=s.id)),s?.platform==="ios"&&(c.device_udid=s.id,c.ios_simulator_device_set=s.simulatorSetPath??null),{...c,...ek(`Opened: ${r??n??t}`)}}({sessionName:s,appName:f,appBundleId:b,surface:h,startup:O,timing:I,device:c,runtime:w,runtimeHintCount:tI});return l.recordAction(P,{command:"open",positionals:p,flags:o.flags??{},runtime:void 0!==o.runtime?w:void 0,result:C}),l.set(s,P),{ok:!0,data:C}}async function re(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e;if(a.has(r)){let e=a.get(r);if(!e)return R("SESSION_NOT_FOUND",`Session "${r}" not found.`);let i=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(i?e.appName:void 0),l=t2(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return i?t1("open --relaunch requires an app name or an active session app."):t1("Session already active. Close it first or pass a new --session name.");let u=t3({shouldRelaunch:i,openTarget:s,surface:l,device:e.device});if(u)return u;let c=await x(e.device),d=await t5({req:t,sessionName:r,sessionStore:a,device:c,surface:l,openTarget:s,existingSession:e});return"response"===d.type?d.response:await t7({req:t,sessionName:r,sessionStore:a,logPath:n,device:c,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:d.details.appBundleId,appName:d.details.appName,runtime:d.details.runtime,surface:l,existingSession:e})}let i=t.flags?.relaunch===!0,o=t.positionals?.[0];if(i&&!o)return t1("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:n}=e;return t?r&&eq(r)?t1("open --relaunch does not support URL targets."):"android"===n&&r&&"binary"===eV(r)?t1(eK(r)):null:null}({shouldRelaunch:i,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await U(t.flags??{}),u=t2(l,t.flags?.surface,o);if("string"!=typeof u)return u;let c=t3({shouldRelaunch:i,openTarget:o,surface:u,device:l});return c||await V(t8,l.id,async()=>{let e=a.toArray().find(e=>e.device.id===l.id);if(e)return R("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name,hint:`Run agent-device session list and reuse --session ${e.name}, or close that session before opening a new one on this device.`});let i=await t5({req:t,sessionName:r,sessionStore:a,device:l,surface:u,openTarget:o});return"response"===i.type?i.response:await t7({req:t,sessionName:r,sessionStore:a,logPath:n,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:i.details.appBundleId,appName:i.details.appName,runtime:i.details.runtime,surface:u})})}let rt={ios:async(e,t,r)=>{let{reinstallIosApp:n}=await import("./apps.js");return await n(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:n}=await import("./8806.js");return await n(e,t,r)}},rr={ios:async(e,t,r)=>{let{installIosApp:n}=await import("./apps.js"),a=await n(e,r,{appIdentifierHint:t});return{bundleId:a.bundleId,appName:a.appName,launchTarget:a.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:n}=await import("./8806.js"),a=await n(e,r);return{package:a.packageName,appName:a.appName,launchTarget:a.launchTarget}}};async function rn(e){let{req:r,command:n,sessionName:a,sessionStore:i,deployOps:o}=e,s=i.get(a),l=r.flags??{},u=I(n,s,l);if(u)return u;let c=r.positionals?.[0]?.trim(),d=r.positionals?.[1]?.trim();if(!c||!d)return R("INVALID_ARGS",`${n} requires: ${n} <app> <path-to-app-binary>`);let p=r.meta?.uploadedArtifactId;try{var f;let e,a=p?es(p,r.meta?.tenantId):Q.expandHome(d);if(!t.existsSync(a))return R("INVALID_ARGS",`App binary not found: ${a}`);let u=await w({session:s,flags:l,ensureReady:!1});if(!eA(n,u))return R("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);if("ios"===u.platform){let t=await o.ios(u,c,a),r=t.bundleId;e=r?{app:c,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await o.android(u,c,a),r=t.package;e=r?{app:c,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=eD(e,(f=e,`Installed: ${f.appName??eR(f)}`));return s&&i.recordAction(s,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:m??{}}),{ok:!0,data:m}}finally{p&&N(p)}}async function ra(e,t,r){return await eB(e,t,r)}async function ri(e){let{req:t,sessionName:r,sessionStore:n}=e;if("session_list"===t.command)return{ok:!0,data:{sessions:n.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",surface:e.surface??"app",device:e.device.name,id:e.device.id,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("devices"===t.command)try{let e=ej(t.flags?.androidDeviceAllowlist),r=eI(t.flags?.platform),n=f({simulatorSetPath:eE(t.flags?.iosSimulatorDeviceSet),platform:r,target:t.flags?.target}),a=await Z({platform:r,target:t.flags?.target,deviceName:t.flags?.device,udid:t.flags?.udid,serial:t.flags?.serial,iosSimulatorSetPath:n,androidSerialAllowlist:e?Array.from(e).sort():void 0}),i=r?a.filter(e=>{var t,n;return t=e,!(n=r)||("apple"===n?eb(t.platform):t.platform===n)}):a,o=(t.flags?.target?i.filter(e=>(e.target??"mobile")===t.flags?.target):i).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=u(t);return R(e.code,e.message,e.details)}if("apps"===t.command){let e=n.get(r),a=t.flags??{},i=I(t.command,e,a);if(i)return i;let o=await w({session:e,flags:a,ensureReady:!0});if(!eA("apps",o))return R("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=ez(t.flags?.appsFilter);return eb(o.platform)?{ok:!0,data:{apps:(await eJ(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}:{ok:!0,data:{apps:(await eH(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function ro(e){let{ensureAndroidEmulatorBooted:t}=await import("./8806.js");return await t(e)}let rs='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',rl='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function ru(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r),i=t.flags??{},o=eI(i.platform);if(!a&&y(i))return R("SESSION_NOT_FOUND","ios"===o?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`);let s=I("appstate",a,i);if(s)return s;let l=eb(a?.device.platform)&&g(i,a);if("ios"===o&&!l)return R("SESSION_NOT_FOUND",rs);if("macos"===o&&!l)return R("SESSION_NOT_FOUND",rl);if(l&&a){let e=a.appName??a.appBundleId;if(!a.appName&&!a.appBundleId){if("macos"===a.device.platform&&a.surface&&"app"!==a.surface&&"frontmost-app"!==a.surface)return{ok:!0,data:{platform:a.device.platform,appName:a.surface,appBundleId:a.appBundleId,source:"session",surface:a.surface}};let e="macos"===a.device.platform?"macOS":"iOS";return R("COMMAND_FAILED",`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`)}return{ok:!0,data:{platform:a.device.platform,appName:e??"unknown",appBundleId:a.appBundleId,source:"session",surface:a.surface??"app",..."ios"===a.device.platform?{device_udid:a.device.id,ios_simulator_device_set:a.device.simulatorSetPath??null}:{}}}}let u=await w({session:a,flags:i,ensureReady:!0});if("ios"===u.platform)return R("SESSION_NOT_FOUND",rs);if("macos"===u.platform)return R("SESSION_NOT_FOUND",rl);let{getAndroidAppState:c}=await import("./8806.js"),d=await c(u);return{ok:!0,data:{platform:"android",package:d.package,activity:d.activity}}}async function rc(e){let{req:t,sessionName:r,sessionStore:n}=e;if("boot"===t.command){let e,a=n.get(r),i=t.flags??{},o=I(t.command,a,i);if(o)return o;let s="android"===(eI(i.platform)??a?.device.platform),l=!0===i.headless;if(l&&!s)return R("INVALID_ARGS","boot --headless is supported only for Android emulators.");let c=ef({flags:i,sessionDevice:a?.device}),d=s&&!!c,p=!1;try{e=await w({session:a,flags:i,ensureReady:!1})}catch(r){let t=u(r);if(s&&l&&!c&&"DEVICE_NOT_FOUND"===t.code)return R("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!d||"DEVICE_NOT_FOUND"!==t.code||!c)throw r;e=await ro({avdName:c,serial:i.serial,headless:l}),p=!0}if(i.target&&(e.target??"mobile")!==i.target)return R("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${i.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return R("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!p){let t=ef({flags:i,sessionDevice:a?.device,resolvedDevice:e});if(!t)return R("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await ro({avdName:t,serial:i.serial,headless:!0})}await ec(e)}else("android"!==e.platform||!0!==e.booted)&&await ec(e);return eA("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:R("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await ru({req:t,sessionName:r,sessionStore:n}):null}function rd(e,t){for(let r of e){if(t(r))return r;let e=rd(r.children,t);if(e)return e}}function rp(e,t){let r=[];for(let n of e)t(n)&&r.push(n),r.push(...rp(n.children,t));return r}function rf(e,t){let r=rd(e,e=>"schema"===e.name&&e.attributes.name===t);return r?r.children.filter(e=>"col"===e.name).map(e=>{let t;return t=e.children.find(e=>"mnemonic"===e.name),t?.text??null??""}):[]}function rm(e){if(!e||e.children.some(e=>"sentinel"===e.name)||!e.text)return null;let t=Number(e.text);return Number.isFinite(t)?t:null}function rh(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:rm(e):null}let rg="xctrace-animation-hitches";function rw(e,t){let r=eg(e),n=rf(r,t);return{rows:0===n.length?[]:rp(r,e=>"row"===e.name),schema:n}}function ry(e,t){for(let r of e)ry(r.children,t),r.attributes.id&&t.set(r.attributes.id,{numberValue:rm(r),process:rv(r)})}function rv(e){if(!e||e.children.some(e=>"sentinel"===e.name))return null;let t=rm(rd(e.children,e=>"pid"===e.name)),r=(e.attributes.fmt??"").replace(/\s+\(\d+\)$/,"").trim();return null===t&&0===r.length?null:{pid:t??void 0,name:r.length>0?r:void 0}}let rA="ps-process-snapshot",rb="ps-process-snapshot",rS="xctrace-activity-monitor",rI="xctrace-activity-monitor";async function r_(e,t){if("ios"===e.platform&&"device"===e.kind)return await rP(e,t);let r=await r$(e,t),n=await rT(e,r);if(0===n.length)throw new d("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,hint:"Run open <app> for this session again to ensure the Apple app is active, then retry perf."});let a=new Date().toISOString();return rG({usagePercent:n.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:n.reduce((e,t)=>e+t.rssKb,0),measuredAt:a,matchedProcesses:[r.executableName],cpuMethod:rA,memoryMethod:rb})}async function rN(e,t){var r;let n,o,s,l,u,c;if("ios"!==e.platform||"device"!==e.kind)throw new d("COMMAND_FAILED","Apple frame-health sampling is currently available only on connected iOS devices.",{metric:"fps",platform:e.platform,deviceKind:e.kind});let p=await rF(e,t),f=await rM(e,t,p);return n=rw((r={hitchesXml:f.hitchesXml,frameLifetimesXml:f.frameLifetimesXml,displayInfoXml:f.displayInfoXml,processIds:p.map(e=>e.pid),processNames:C(p.map(e=>a.basename(i(e.executable)))),windowStartedAt:f.windowStartedAt,windowEndedAt:f.windowEndedAt,measuredAt:f.windowEndedAt}).frameLifetimesXml,"hitches-frame-lifetimes").rows.length,o=function(e){if(!e)return;let{rows:t,schema:r}=rw(e,"device-display-info"),n=r.indexOf("max-refresh-rate");if(n<0)return;let a=new Map;for(let e of t){ry(e.children,a);let t=rh(e.children[n],a);if(null!==t&&t>0)return t}}(r.displayInfoXml),l=(s=(function(e){let t,r,n=eg(e),a=Object.values(r={start:(t=rf(n,"hitches")).indexOf("start"),duration:t.indexOf("duration"),process:t.indexOf("process"),isSystem:t.indexOf("is-system")}).every(e=>e>=0)?r:null;if(!a)return[];let i=new Map;return rp(n,e=>"row"===e.name).map(e=>(function(e,t,r){var n,a,i;let o;if(ry(e.children,r),!0===(n=e.children[t.isSystem],null===(o=rh(n,r))?null:0!==o))return null;let s=rh(e.children[t.start],r),l=rh(e.children[t.duration],r);if(null===s||null===l)return null;let u=(a=e.children[t.process],i=r,a?a.attributes.ref?i.get(a.attributes.ref)?.process??null:rv(a):null);return{startNs:s,durationNs:l,pid:u?.pid,processName:u?.name}})(e,a,i)).filter(e=>!!e)})(r.hitchesXml).filter(e=>{var t,n,a;return t=e,n=r.processIds,a=r.processNames,!!(void 0!==t.pid&&n.includes(t.pid))||!!t.processName&&a.includes(t.processName)})).length,u=Math.max(0,Math.round(Date.parse(r.windowEndedAt)-Date.parse(r.windowStartedAt))),c=function(e,t){if(0===e.length)return[];let r=[...e].sort((e,t)=>e.startNs-t.startNs),n=[],a=[];for(let e of r){let t=a.at(-1);if(!t||e.startNs-(t.startNs+t.durationNs)<=5e8){a.push(e);continue}n.push(a),a=[e]}return a.length>0&&n.push(a),n.map(e=>{var r,n;let a,i,o,s;return r=e,n=t,a=Math.min(...r.map(e=>e.startNs)),i=Math.max(...r.map(e=>e.startNs+e.durationNs)),s=Math.max(o=Math.max(0,Math.round(a/1e6)),Math.round(i/1e6)),{startOffsetMs:o,endOffsetMs:s,startAt:new Date(n+o).toISOString(),endAt:new Date(n+s).toISOString(),missedDeadlineFrameCount:r.length,worstFrameMs:tP(Math.max(...r.map(e=>e.durationNs))/1e6)}}).sort((e,t)=>t.missedDeadlineFrameCount-e.missedDeadlineFrameCount||t.worstFrameMs-e.worstFrameMs).slice(0,3).sort((e,t)=>e.startOffsetMs-t.startOffsetMs)}(s,Date.parse(r.windowStartedAt)),{droppedFramePercent:n>0?tP(l/n*100):0,droppedFrameCount:l,totalFrameCount:n,sampleWindowMs:u,windowStartedAt:r.windowStartedAt,windowEndedAt:r.windowEndedAt,measuredAt:r.measuredAt,method:rg,matchedProcesses:[...new Set(s.map(e=>e.processName).filter(e=>"string"==typeof e&&e.length>0))],frameDeadlineMs:void 0===o?void 0:tP(1e3/o),refreshRateHz:o,worstWindows:c.length>0?c:void 0}}async function rM(e,t,i){let o=await r.mkdtemp(a.join(n.tmpdir(),"agent-device-ios-frame-perf-")),s=a.join(o,"animation-hitches.trace"),l=a.join(o,"hitches.xml"),u=a.join(o,"frame-lifetimes.xml"),c=a.join(o,"display-info.xml");try{let n=await rx({device:e,appBundleId:t,tracePath:s,template:"Animation Hitches",duration:"2s",targetPids:i.map(e=>e.pid),validateTraceOutput:!0,failureMessage:`Failed to record iOS frame-health sample for ${t}`});await rO(e,t,s,"hitches",l),await rO(e,t,s,"hitches-frame-lifetimes",u);let a=await rR(e,t,s,"device-display-info",c);return{windowStartedAt:n.startedAt,windowEndedAt:n.endedAt,hitchesXml:await r.readFile(l,"utf8"),frameLifetimesXml:await r.readFile(u,"utf8"),displayInfoXml:a?await r.readFile(c,"utf8"):void 0}}finally{await r.rm(o,{recursive:!0,force:!0}).catch(()=>{})}}async function rx(e){let{device:t,appBundleId:r,tracePath:n,template:a,duration:i}=e,o=e.allProcesses?["--all-processes"]:(e.targetPids??[]).flatMap(e=>["--attach",String(e)]),s=["xctrace","record","--template",a,"--device",t.id,...o,"--time-limit",i,"--output",n,"--quiet","--no-prompt"],l=await rD(s,e.tracePath);if(0===l.result.exitCode)return e.validateTraceOutput&&await rk(e,l.result.stdout,l.result.stderr),{startedAt:l.startedAt,endedAt:l.endedAt,capturedAtMs:l.capturedAtMs};throw new d("COMMAND_FAILED",e.failureMessage,{cmd:"xcrun",args:s,exitCode:l.result.exitCode,stdout:l.result.stdout,stderr:l.result.stderr,appBundleId:r,deviceId:t.id,hint:rq(l.result.stdout,l.result.stderr)})}async function rD(e,t){let n;for(let a=1;a<=3;a+=1){a>1&&(await r.rm(t,{recursive:!0,force:!0}).catch(()=>{}),await new Promise(e=>setTimeout(e,1500)));let i=new Date().toISOString(),o=await p(e,{allowFailure:!0,timeoutMs:6e4});if(n={result:o,startedAt:i,endedAt:new Date().toISOString(),capturedAtMs:Date.now()},0===o.exitCode||!function(e){let t=`${e.stdout}
2
+ ${e.stderr}`.toLowerCase();return t.includes("_lockkperf")||t.includes("could not lock kperf")||t.includes("likely another session just started")}(o))break}return n}async function rk(e,t,n){let a=await r.stat(e.tracePath).catch(()=>null);if(!(a?.isDirectory()===!0?(await r.readdir(e.tracePath).catch(()=>[])).length>0:(a?.size??0)>0))throw new d("COMMAND_FAILED",`${e.failureMessage}: xctrace produced no trace data`,{tracePath:e.tracePath,appBundleId:e.appBundleId,deviceId:e.device.id,stdout:t,stderr:n,hint:"Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf."})}async function rO(e,t,r,n,a){let i=["xctrace","export","--input",r,"--xpath",`/trace-toc/run/data/table[@schema="${n}"]`,"--output",a],o=await p(i,{allowFailure:!0,timeoutMs:15e3});if(0!==o.exitCode)throw new d("COMMAND_FAILED",`Failed to export iOS device ${n} data`,{cmd:"xcrun",args:i,exitCode:o.exitCode,stdout:o.stdout,stderr:o.stderr,appBundleId:t,deviceId:e.id,hint:rq(o.stdout,o.stderr)})}async function rR(e,t,r,n,a){try{return await rO(e,t,r,n,a),!0}catch{return!1}}async function rL(e){let t=eg(e),r=rf(t,"activity-monitor-process-live");if(0===r.length)throw new d("COMMAND_FAILED","Failed to parse xctrace activity-monitor-process-live schema");let n=r.indexOf("pid"),a=r.indexOf("process"),i=r.indexOf("cpu-total"),o=r.indexOf("memory-real");if(n<0||a<0||i<0||o<0)throw new d("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let s=rp(t,e=>"row"===e.name),l=[],u=new Map;for(let e of s){var c,p;let t=e.children;if(0===t.length)continue;for(let e of t){let t=rd(e.children,e=>"pid"===e.name&&"string"==typeof e.attributes.id);if(t?.attributes.id){let e=Number(t.text);u.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&u.set(e.attributes.id,{numberValue:rm(e),processName:rj(e)})}let r=rh(t[n],u),s=(c=t[a],p=u,c?c.attributes.ref?p.get(c.attributes.ref)?.processName??null:rj(c):null);null!==r&&Number.isFinite(r)&&s&&l.push({pid:r,processName:s,cpuTimeNs:rh(t[i],u),residentMemoryBytes:rh(t[o],u)})}return l}async function r$(e,t){let r="macos"===e.platform?await rV(t):await rU(e,t),n="macos"===e.platform?a.join(r,"Contents","Info.plist"):a.join(r,"Info.plist"),i=await eX(n,"CFBundleExecutable");if(!i)throw new d("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?a.join(r,"Contents","MacOS",i):a.join(r,i)}}async function rP(e,t){let r=await rF(e,t),n=await rC(e,t),a=await rC(e,t),i=rE(await rL(n.xml),r,t,e),o=rE(await rL(a.xml),r,t,e),s=a.capturedAtMs-n.capturedAtMs;if(s<=0)throw new d("COMMAND_FAILED",`Invalid Activity Monitor sample window for ${t}`,{appBundleId:t,deviceId:e.id});if(null===i.cpuTimeNs||null===o.cpuTimeNs||null===o.residentMemoryBytes)throw new d("COMMAND_FAILED",`Incomplete Activity Monitor sample for ${t}`,{appBundleId:t,deviceId:e.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});return rG({usagePercent:Math.max(0,o.cpuTimeNs-i.cpuTimeNs)/(1e6*s)*100,residentMemoryKb:o.residentMemoryBytes/1024,measuredAt:new Date(a.capturedAtMs).toISOString(),matchedProcesses:o.matchedProcesses,cpuMethod:rS,memoryMethod:rI})}async function rF(e,t){let r=(await ev(e,"all")).find(e=>e.bundleId===t);if(!r)throw new d("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new d("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let n=r.url.replace(/\/$/,""),a=i(n),o=(await eS(e)).filter(e=>e.executable.startsWith(`${n}/`));if(0===o.length)throw new d("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,deviceId:e.id,appBundlePath:a,hint:"Run open <app> for this session again to ensure the iOS app is active, then retry perf."});return o}async function rC(e,t){let i=await r.mkdtemp(a.join(n.tmpdir(),"agent-device-ios-perf-")),o=a.join(i,"sample.trace"),s=a.join(i,"activity-monitor-process-live.xml");try{let n=await rx({device:e,appBundleId:t,tracePath:o,template:"Activity Monitor",duration:"1s",allProcesses:!0,failureMessage:`Failed to record iOS device Activity Monitor sample for ${t}`});return await rO(e,t,o,"activity-monitor-process-live",s),{capturedAtMs:n.capturedAtMs,xml:await r.readFile(s,"utf8")}}finally{await r.rm(i,{recursive:!0,force:!0}).catch(()=>{})}}function rE(e,t,r,n){let o=new Set(t.map(e=>e.pid)),s=new Set(t.map(e=>a.basename(i(e.executable)))),l=e.filter(e=>o.has(e.pid)||s.has(e.processName));if(0===l.length)throw new d("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:n.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let u=new Map;for(let e of l){let t=u.get(e.pid);if(!t){u.set(e.pid,e);continue}u.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:rK(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:rK(t.residentMemoryBytes,e.residentMemoryBytes)})}let c=[...u.values()],p=c.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=c.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:p.length>0?p.reduce((e,t)=>e+t,0):null,residentMemoryBytes:f.length>0?f.reduce((e,t)=>e+t,0):null,matchedProcesses:C(c.map(e=>e.processName))}}async function rV(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await ey("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new d("COMMAND_FAILED",`Failed to resolve macOS app bundle for ${e}`,{appBundleId:e,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let n=r.stdout.split("\n").map(e=>e.trim()).find(e=>e.endsWith(".app"));if(!n)throw new d("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return n}async function rU(e,t){let r=em(e,["get_app_container",e.id,t,"app"]),n=await p(r,{allowFailure:!0,timeoutMs:15e3});if(0!==n.exitCode)throw new d("COMMAND_FAILED",`Failed to resolve iOS simulator app container for ${t}`,{appBundleId:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,hint:"Ensure the iOS simulator app is installed and booted, then retry perf."});let a=n.stdout.trim();if(0===a.length)throw new d("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return a}async function rT(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:em(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of eO(e)){let e=r.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!e)continue;let[n,a,i,o]=e.slice(1);if(void 0===n||void 0===a||void 0===i||void 0===o)continue;let s=Number(n),l=Number(a),u=Number(i),c=o.trim();Number.isFinite(s)&&Number.isFinite(l)&&Number.isFinite(u)&&t.push({pid:s,cpuPercent:l,rssKb:u,command:c})}return t})(("macos"===e.platform?await ey("ps",r,{timeoutMs:15e3}):await p(r,{timeoutMs:15e3})).stdout).filter(e=>{var r,n;let i;return r=e.command,n=t,i=function(e){let[t=""]=e.trim().split(/\s+/,1);return t}(r),!!(n.executablePath&&(r===n.executablePath||i===n.executablePath||r.startsWith(`${n.executablePath} `)))||a.basename(i)===n.executableName})}function rG(e){return{cpu:{usagePercent:tP(e.usagePercent),measuredAt:e.measuredAt,method:e.cpuMethod,matchedProcesses:e.matchedProcesses},memory:{residentMemoryKb:Math.round(e.residentMemoryKb),measuredAt:e.measuredAt,method:e.memoryMethod,matchedProcesses:e.matchedProcesses}}}function rj(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function rq(e,t){let r=k(e,t);if(r)return r;let n=`${e}
3
+ ${t}`.toLowerCase();return n.includes("no device matched")||n.includes("failed to find device")?J:n.includes("timed out")?"Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.":"Ensure the iOS device is unlocked, trusted, visible to xctrace, and the target app stays active while perf samples it."}function rK(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function rH(e,t={}){var r,n,a;let i,o,s,l,u=(s=(o=(i=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===tk&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:tk,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}((r=e).actions)).at(-1))?{available:!0,lastDurationMs:o.durationMs,lastMeasuredAt:o.measuredAt,method:tk,sampleCount:i.length,samples:i}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:tk},{session:r.name,platform:r.device.platform,device:r.device.name,deviceId:r.device.id,metrics:{startup:s,fps:{available:!1,reason:"Dropped-frame sampling is currently available only on Android."},memory:{available:!1,reason:tO},cpu:{available:!1,reason:tO}},sampling:{startup:{method:tk,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"},...function(e){if("android"===e.device.platform)return{memory:{method:tK,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:tq,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"},fps:{method:tC,description:"Rendered-frame health from the current adb shell dumpsys gfxinfo <package> framestats window. Dropped frames use Android gfxinfo janky-frame/frame-deadline data when available; this is not video recording FPS.",unit:"percent",primaryField:"droppedFramePercent",window:"since previous Android gfxinfo reset or app process start",resetsAfterRead:!0,relatedActionsLimit:12}};var t=e.device;let r="ios"===t.platform&&"device"===t.kind?{method:rg,description:"Rendered-frame hitch health from xctrace Animation Hitches on connected iOS devices. Dropped frames are counted from native hitch rows for the attached app process, with total frames from the same trace frame-lifetime table.",unit:"percent",primaryField:"droppedFramePercent",window:"short 2s xctrace Animation Hitches record of the active app process",resetsAfterRead:!1}:{method:rg,description:"Unavailable on iOS simulators and macOS because local Apple tooling does not expose reliable app frame hitches for these targets.",unit:"percent",primaryField:"droppedFramePercent"};if("ios"===t.platform&&"device"===t.kind)return{fps:r,memory:{method:rI,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:rS,description:"Recent CPU usage snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"percent"}};let n="macos"===t.platform?"host ps for the running macOS app executable resolved from the bundle ID.":"xcrun simctl spawn ps for the running iOS simulator app executable resolved from the bundle ID.";return{fps:r,memory:{method:rb,description:`Resident memory snapshot from ${n}`,unit:"kB"},cpu:{method:rA,description:`Recent CPU usage snapshot from ${n}`,unit:"percent"}}}(r)}});return"android"!==(n=e).device.platform&&"ios"!==n.device.platform&&"macos"!==n.device.platform||(e.appBundleId?"android"===e.device.platform?await rB(u,e,t):await rW(u,e):(a=u,l="android"===e.device.platform?"No Android app package is associated with this session. Run open <app> first.":"No Apple app bundle ID is associated with this session. Run open <app> first.",a.metrics.fps={available:!1,reason:l},a.metrics.memory={available:!1,reason:l},a.metrics.cpu={available:!1,reason:l})),u}async function rB(e,t,r){let n=await rz(t,r);e.metrics.memory=rY(n.memory),e.metrics.cpu=rY(n.cpu),e.metrics.fps=rZ(rY(n.fps),t)}async function rW(e,t){let r=await rJ(t);e.metrics.memory=rY(r.memory),e.metrics.cpu=rY(r.cpu),e.metrics.fps=rZ(rY(r.fps),t)}async function rz(e,t){let r=e.appBundleId,n={adb:t.androidAdb},[a,i,o]=await Promise.allSettled([tB(e.device,r,n),tH(e.device,r,n),tG(e.device,r,n)]);return{memory:a,cpu:i,fps:o}}async function rJ(e){let t=e.appBundleId,r=await rX(rN(e.device,t)),n=await rX(r_(e.device,t));if("fulfilled"===n.status){let e=n.value;return{memory:{status:"fulfilled",value:e.memory},cpu:{status:"fulfilled",value:e.cpu},fps:r}}return{memory:{status:"rejected",reason:n.reason},cpu:{status:"rejected",reason:n.reason},fps:r}}async function rX(e){try{return{status:"fulfilled",value:await e}}catch(e){return{status:"rejected",reason:e}}}function rY(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=c(e.reason);return{available:!1,reason:t.message,error:t}}function rZ(e,t){var r,n;let a,i;if(!0!==e.available)return e;let o=(r=t.actions,a=rQ((n=e).windowStartedAt),i=rQ(n.windowEndedAt)??rQ(n.measuredAt),void 0===a||void 0===i?[]:r.filter(e=>e.ts>=a&&e.ts<=i).map(e=>({command:e.command,at:new Date(e.ts).toISOString(),offsetMs:Math.max(0,Math.round(e.ts-a)),target:function(e){let t=e.result;if(t)for(let e of["refLabel","ref","appName","appBundleId"]){let r=t[e];if("string"==typeof r&&r.length>0)return r}}(e)})).slice(-12));return 0===o.length?e:{...e,relatedActions:o}}function rQ(e){if("string"!=typeof e)return;let t=Date.parse(e);return Number.isFinite(t)?t:void 0}let r0=["path","start","stop","doctor","mark","clear"],r1=`logs requires ${r0.slice(0,-1).join(", ")}, or ${r0.at(-1)}`,r2=["dump","log"],r3=`network requires ${r2.join(" or ")}`,r5=["summary","headers","body","all"],r6=`network include mode must be one of: ${r5.join(", ")}`;async function r8(e){let{req:t}=e;return"perf"===t.command?r9(e):"logs"===t.command?r4(e):"network"===t.command?nn(e):null}async function r9(e){let{sessionName:t,sessionStore:r,androidAdbExecutor:n}=e,a=r.get(t);if(!a)return R("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await rH(a,{androidAdb:n})}}catch(e){return{ok:!1,error:c(e)}}}async function r4(e){var t,r,n;let a,i,{req:o,sessionName:s,sessionStore:l}=e,u=l.get(s);if(!u)return R("SESSION_NOT_FOUND","logs requires an active session");if(!eA("logs",u.device))return R("UNSUPPORTED_OPERATION","logs is not supported on this device");let c=(o.positionals?.[0]??"path").toLowerCase(),d=!!o.flags?.restart;return r0.includes(c)?d&&"clear"!==c?R("INVALID_ARGS","logs --restart is only supported with logs clear"):"path"===c?function(e,t,r){let n=r.resolveAppLogPath(t),a=T(n);return{ok:!0,data:{path:n,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android",sizeBytes:a.sizeBytes,modifiedAt:a.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}(u,s,l):"doctor"===c?r7(u,s,l):"mark"===c?(t=o,r=s,n=l,a=t.positionals?.slice(1).join(" ")??"",h(i=n.resolveAppLogPath(r),a),{ok:!0,data:{path:i,marked:!0}}):"clear"===c?ne(u,s,l,d):"start"===c?nt(u,s,l):"stop"===c?nr(u,s,l):R("INVALID_ARGS",r1):R("INVALID_ARGS",r1)}async function r7(e,t,r){let n=r.resolveAppLogPath(t),a=await ei(e.device,e.appBundleId);return{ok:!0,data:{path:n,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:a.checks,notes:a.notes}}}async function ne(e,t,r,n){if(e.appLog&&!n)return R("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(n&&!e.appBundleId)return R("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let a=r.resolveAppLogPath(t);if(!n)return{ok:!0,data:B(a)};e.appLog&&await el(e.appLog);let i=B(a),o=r.resolveAppLogPidPath(t);try{let n=await eN(e.device,e.appBundleId,a,o);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:a,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{...i,restarted:!0}}}catch(n){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:c(n)}}}async function nt(e,t,r){if(e.appLog)return R("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return R("INVALID_ARGS","logs start requires an app session; run open <app> first");let n=r.resolveAppLogPath(t),a=r.resolveAppLogPidPath(t);try{let i=await eN(e.device,e.appBundleId,n,a);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:i.backend,outPath:n,startedAt:i.startedAt,getState:i.getState,stop:i.stop,wait:i.wait}}),{ok:!0,data:{path:n,started:!0}}}catch(e){return{ok:!1,error:c(e)}}}async function nr(e,t,r){if(!e.appLog)return R("INVALID_ARGS","no app log stream active");let n=e.appLog.outPath;return await el(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:n,stopped:!0}}}async function nn(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(!a)return R("SESSION_NOT_FOUND","network requires an active session");if(!eA("network",a.device))return R("UNSUPPORTED_OPERATION","network is not supported on this device");let i=(t.positionals?.[0]??"dump").toLowerCase();if(!r2.includes(i))return R("INVALID_ARGS",r3);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return R("INVALID_ARGS","network dump limit must be an integer in range 1..200");let s=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return R("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let n=(r??t??"summary").toLowerCase();return r5.includes(n)?{ok:!0,include:n}:R("INVALID_ARGS",r6)}(t);if(!s.ok)return s;let{include:l}=s,u=await W({device:a.device,appBundleId:a.appBundleId,appLogState:a.appLog?.getState(),appLogStartedAt:a.appLog?.startedAt,appLogPath:n.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...u.dump,active:!!a.appLog,state:a.appLog?.getState()??"inactive",backend:u.backend,notes:u.notes}}}let na=/^[A-Z_][A-Z0-9_]*$/,ni=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_.]*)(?::-((?:[^}\\]|\\.)*))?\}/g,no="AD_VAR_";function ns(e){return e.startsWith("AD_")}function nl(e){return new d("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function nu(e){let t={};for(let[r,n]of Object.entries(e)){if("string"!=typeof n||!r.startsWith(no))continue;let e=r.slice(no.length);0!==e.length&&na.test(e)&&(ns(e)||(t[e]=n))}return t}function nc(e){let t={};for(let r of e){let e=r.indexOf("=");if(e<=0)throw new d("INVALID_ARGS",`Invalid -e entry "${r}": expected KEY=VALUE.`);let n=r.slice(0,e);if(!na.test(n))throw new d("INVALID_ARGS",`Invalid -e key "${n}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(ns(n))throw nl(n);t[n]=r.slice(e+1)}return t}function nd(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):[]}function np(e){if(e&&"object"==typeof e&&!Array.isArray(e)){let t={};for(let[r,n]of Object.entries(e))"string"==typeof n&&(t[r]=n);return t}return process.env}function nf(e,t,r){return e.replace(ni,(e,n,a,i)=>{if(n)return"${";if(!a)return e;if(Object.prototype.hasOwnProperty.call(t.values,a))return String(t.values[a]);if(void 0!==i)return i.replace(/\\(.)/g,"$1");throw new d("INVALID_ARGS",`Unresolved variable \${${a}} at ${r.file}:${r.line}.`)})}function nm(e,t,r){return e?function e(t,r,n){return"string"==typeof t?nf(t,r,n):Array.isArray(t)?t.map(t=>e(t,r,n)):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).map(([t,a])=>[t,e(a,r,n)])):t}(e,t,r):e}let nh=new Set(["ios","android","macos","linux"]),ng=new Set(["mobile","tv","desktop"]);function nw(e){let t=e.split(/\r?\n/),r={};for(let[e,n]of t.entries()){let t=n.trim();if(0===t.length||t.startsWith("#"))continue;if(ny(t)){!function(e,t,r){let{key:n,value:a}=function(e,t){let r=e.slice(3).replace(/^[\s]+/,""),n=r.indexOf("=");if(n<=0)throw new d("INVALID_ARGS",`Invalid env directive on line ${t}: expected "env KEY=VALUE".`);let a=r.slice(0,n);if(!na.test(a))throw new d("INVALID_ARGS",`Invalid env key "${a}" on line ${t}: keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(a.startsWith("AD_"))throw new d("INVALID_ARGS",`Invalid env key "${a}" on line ${t}: the AD_* namespace is reserved for built-in variables. Rename ${a} to avoid the AD_ prefix.`);return{key:a,value:function(e,t){if(0===e.length)return"";if(e.startsWith('"'))try{let t=JSON.parse(e);if("string"!=typeof t)throw Error("not a string literal");return t}catch{throw new d("INVALID_ARGS",`Invalid quoted env value on line ${t}.`)}return e}(r.slice(n+1),t)}}(t,r),i=e.env??{};if(Object.prototype.hasOwnProperty.call(i,n))throw new d("INVALID_ARGS",`Duplicate env directive "${n}" on line ${r}.`);i[n]=a,e.env=i}(r,t,e+1);continue}if(!t.startsWith("context "))break;let a=t.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&nh.has(e)&&nv(r,"platform",e)}let i=t.match(/(?:^|\s)target=([^\s]+)/);if(i){let e=i[1];e&&ng.has(e)&&nv(r,"target",e)}let o=t.match(/(?:^|\s)timeout=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=1&&nv(r,"timeoutMs",Math.floor(e))}let s=t.match(/(?:^|\s)retries=(\d+)/);if(s){let e=Number(s[1]);Number.isFinite(e)&&e>=0&&nv(r,"retries",Math.floor(e))}}return r}function ny(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function nv(e,t,r){let n=e[t];if(void 0!==n)throw new d("INVALID_ARGS",n===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(n)} vs ${String(r)}.`);e[t]=r}function nA(e){return!!e&&!Number.isNaN(Number(e))}let nb=/[*?[\]{}]/;function nS(e){return"maestro"===e}let nI=["failed to start daemon","runner did not accept connection","xcodebuild exited early","device is offline","device offline","device unauthorized"];function n_(e){var t,r,n,a;let i,o,s="ok"in(t=e)?t.ok?null:t.error:"failed"===t.status?t.error:null;return!!s&&(r=s.details,"timeout_cleanup_pending"===(i="string"==typeof r?.reason?r.reason:"")||!!i&&eT(i)||(n=s.code,a=s.message,o=`${n}
4
+ ${a}`.toLowerCase(),nI.some(e=>o.includes(e))))}async function nN(e){let r,n,{filePath:i,sessionName:o,requestId:s,timeoutMs:l,platform:u,target:d,artifactsDir:p,runReplay:f,cleanupSession:m}=e;O(s);let h=new Set,g=!1,w=Date.now(),y=function(e){let{artifactsDir:r,artifactPaths:n,filePath:i,sessionName:o,requestId:s,timeoutMs:l,platform:u,target:c}=e;if(!r)return;let d=a.join(r,"replay-timing.ndjson");return t.mkdirSync(a.dirname(d),{recursive:!0}),t.writeFileSync(d,""),n.add(d),nD(d,{type:"replay_test_attempt_start",ts:new Date().toISOString(),replayPath:i,session:o,requestId:s,timeoutMs:l,platform:u,target:c}),d}({artifactsDir:p,artifactPaths:h,filePath:i,sessionName:o,requestId:s,timeoutMs:l,platform:u,target:d}),v=f({filePath:i,sessionName:o,platform:u,target:d,requestId:s,artifactsDir:p,artifactPaths:h,tracePath:y}).catch(e=>({ok:!1,error:c(e)})).finally(()=>{ep(s)});try{return n="number"==typeof l?await Promise.race([v,new Promise(e=>{r=setTimeout(()=>{g=!0,eu(s),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(l,[...h]))},l)})]):await v,nD(y,{type:"replay_test_attempt_stop",ts:new Date().toISOString(),session:o,ok:n.ok,timedOut:g,durationMs:Date.now()-w,errorCode:n.ok?void 0:n.error.code}),n}finally{var A;r&&clearTimeout(r),g&&(await nM(v)||((A=n)&&!A.ok&&(A.error.details={...A.error.details??{},reason:"timeout_cleanup_pending",timeoutCleanupPending:!0}),eZ({level:"warn",phase:"test_timeout_cleanup_race",data:{session:o,requestId:s,graceMs:2e3}}),nx({replayPromise:v,cleanupSession:m,sessionName:o,requestId:s})));let e=Date.now();try{nD(y,{type:"replay_test_cleanup_start",ts:new Date().toISOString(),session:o}),await m(o),nD(y,{type:"replay_test_cleanup_stop",ts:new Date().toISOString(),session:o,ok:!0,durationMs:Date.now()-e})}catch(r){let t=c(r);nD(y,{type:"replay_test_cleanup_stop",ts:new Date().toISOString(),session:o,ok:!1,durationMs:Date.now()-e,errorCode:t.code}),eZ({level:"warn",phase:"test_cleanup_failed",data:{session:o,error:t.message}})}}}async function nM(e){return await Promise.race([e.then(()=>!0),o(2e3).then(()=>!1)])}async function nx(e){let{replayPromise:t,cleanupSession:r,sessionName:n,requestId:a}=e;try{await t}finally{try{await r(n)}catch(e){eZ({level:"warn",phase:"test_late_cleanup_failed",data:{session:n,requestId:a,error:c(e).message}})}}}function nD(e,r){e&&t.appendFileSync(e,`${JSON.stringify(r)}
5
+ `)}async function nk(e){let{req:r,sessionName:n,runReplay:i,cleanupSession:o}=e;if((r.positionals?.length??0)===0)return R("INVALID_ARGS","test requires at least one path or glob");try{var s,l,c,p,f,m;let e,u,h,g,w,y=function(e){var r,n,i;let{inputs:o,cwd:s,platformFilter:l,replayBackend:u}=e,c=(r=u,new Set(nS(r)?[".ad",".yaml",".yml"]:[".ad"])),p=s??process.cwd(),f=[...new Set(o.flatMap(e=>(function(e,r,n){var i,o;let s=Q.expandHome(e,r);if(t.existsSync(s)){let r=t.statSync(s);if(r.isDirectory())return[...n].map(e=>`**/*${e}`).flatMap(e=>t.globSync(e,{cwd:s}).map(e=>a.join(s,e)));if(r.isFile()){if(!n.has(a.extname(s)))throw new d("INVALID_ARGS",`test does not support this file type: ${e}`);return[s]}return[]}if(i=e,!nb.test(i)&&(o=s,!nb.test(o)))throw new d("INVALID_ARGS",`test input not found: ${e}`);let l=a.isAbsolute(s)?s:e;return t.globSync(l,{cwd:a.isAbsolute(s)?void 0:r}).map(e=>a.isAbsolute(e)?e:a.resolve(r,e)).filter(e=>n.has(a.extname(e))&&function(e){try{return t.statSync(e).isFile()}catch{return!1}}(e))})(e,p,c)))].map(e=>a.normalize(e)).sort((e,t)=>e.localeCompare(t)),m=[];for(let e of f){let r=nw(t.readFileSync(e,"utf8"));if(!l){m.push({kind:"run",path:e,metadata:r});continue}if(!r.platform){nS(u)?m.push({kind:"run",path:e,metadata:r}):m.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${l}`});continue}n=l,i=r.platform,("apple"===n?"apple"===i||"ios"===i||"macos"===i:i===n)&&m.push({kind:"run",path:e,metadata:r})}if(0===m.filter(e=>"run"===e.kind).length){let e=l?` for --platform ${l}`:"";throw new d("INVALID_ARGS",`No replay tests matched${e}.`)}return m}({inputs:r.positionals,cwd:r.meta?.cwd,platformFilter:r.flags?.platform,replayBackend:r.flags?.replayBackend}),v=(s=r.meta?.requestId,(s?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),A=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:n}=e,i=Q.expandHome(t??".agent-device/test-artifacts",r);return a.join(i,n)}({artifactsDir:"string"==typeof r.flags?.artifactsDir?r.flags.artifactsDir:void 0,cwd:r.meta?.cwd,suiteInvocationId:v}),b=[],S=Date.now(),I=0;for(let[e,t]of y.entries()){if("skip"===t.kind){ex({type:"replay-test",file:t.path,status:"skip",index:e+1,total:y.length,message:t.message}),b.push({file:t.path,status:"skipped",durationMs:0,reason:t.reason,message:t.message});continue}I+=1;let a=await nO({entry:t,sessionName:n,suiteInvocationId:v,caseIndex:I-1,cwd:r.meta?.cwd,requestId:r.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(r.flags?.retries,t.metadata.retries),timeoutMs:(l=r.flags?.timeoutMs,c=t.metadata.timeoutMs,"number"==typeof l?l:c),suiteArtifactsDir:A,suiteIndex:e+1,suiteTotal:y.length,runReplay:i,cleanupSession:o});if(b.push(a),r.flags?.failFast===!0||n_(a))break}let _=(p=y.length,f=b,m=Date.now()-S,e=f.filter(e=>"passed"===e.status).length,h=(u=f.filter(e=>"failed"===e.status)).length,g=f.filter(e=>"skipped"===e.status).length,w=e+h,{total:p,executed:w,passed:e,failed:h,skipped:g,notRun:Math.max(0,p-w-g),durationMs:m,failures:u,tests:f});return{ok:!0,data:_}}catch(t){let e=u(t);return R(e.code,e.message)}}async function nO(e){var r,n;let i,o,{entry:s,sessionName:l,suiteInvocationId:u,caseIndex:c,cwd:d,requestId:p,retries:f,timeoutMs:m,suiteArtifactsDir:h,suiteIndex:g,suiteTotal:w,runReplay:y,cleanupSession:v}=e,A=Date.now(),b=a.join(h,(r=s.path,(0===(o=d?a.relative(d,r):a.basename(r)).length||o.startsWith("..")?a.basename(r):o).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),S="",I=0;for(let e=0;e<=f;e+=1){I=e+1;let r=function(e,t,r,n,i=0){let o=a.basename(r,a.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${n+1}${o?`-${o}`:""}:attempt-${i+1}`}(l,u,s.path,c,e),o=a.join(b,`attempt-${I}`);n=s.path,t.mkdirSync(o,{recursive:!0}),function(e,r){let n=a.join(r,"replay.ad");if(t.copyFileSync(e,n),!function(e){let t=a.extname(e).toLowerCase();return".yml"===t||".yaml"===t}(e))return;let i=a.join(r,a.basename(e));a.resolve(i)!==a.resolve(n)&&t.copyFileSync(e,i)}(n,o);let d=function(e){let{requestId:t,suiteInvocationId:r,filePath:n,caseIndex:i,attemptIndex:o}=e;return en(`${t??r}:test:${i+1}:${a.basename(n)}:attempt:${o+1}`,r)}({requestId:p,suiteInvocationId:u,filePath:s.path,caseIndex:c,attemptIndex:e}),h=await nN({filePath:s.path,sessionName:r,requestId:d,timeoutMs:m,platform:s.metadata.platform,target:s.metadata.target,artifactsDir:o,runReplay:y,cleanupSession:v});if(!function(e){let{response:r,filePath:n,sessionName:i,attempts:o,maxAttempts:s,attemptArtifactsDir:l}=e,u=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(r)];r.ok||"string"!=typeof r.error.logPath||u.push(r.error.logPath);let c=function(e,r){let n=[],i=new Map;for(let o of e){if(!function(e){try{return t.statSync(e).isFile()}catch{return!1}}(o))continue;let e=function(e,t){let r=a.extname(e),n=r?e.slice(0,-r.length):e,i=t.get(e)??0;return(t.set(e,i+1),0===i)?e:`${n}-${i+1}${r}`}(a.basename(o),i),s=a.join(r,e);a.resolve(o)!==a.resolve(s)&&t.copyFileSync(o,s),n.push(s)}return n}(u,l),d=[`file: ${n}`,`session: ${i}`,`attempt: ${o}/${s}`,`status: ${r.ok?"passed":"failed"}`];if(r.ok){let e="number"==typeof r.data?.replayed?r.data.replayed:0,t="number"==typeof r.data?.healed?r.data.healed:0;d.push(`replayed: ${e}`,`healed: ${t}`)}else d.push(`code: ${r.error.code}`,`message: ${r.error.message}`),r.error.hint&&d.push(`hint: ${r.error.hint}`),r.error.diagnosticId&&d.push(`diagnosticId: ${r.error.diagnosticId}`),r.error.logPath&&d.push(`logPath: ${r.error.logPath}`),r.error.details?.reason==="timeout"&&d.push("timeoutMode: cooperative");c.length>0&&d.push(`copiedArtifacts: ${c.map(e=>a.basename(e)).join(", ")}`);let p=a.join(l,"result.txt"),f=`${d.join("\n")}
6
+ `;t.writeFileSync(p,f),r.ok||t.writeFileSync(a.join(l,"failure.txt"),f)}({response:h,filePath:s.path,sessionName:r,attempts:I,maxAttempts:f+1,attemptArtifactsDir:o}),i=h,S=r,h.ok||n_(h)||e>=f)break;ex({type:"replay-test",file:s.path,status:"fail",index:g,total:w,attempt:I,maxAttempts:f+1,retrying:!0,message:h.error.message})}let _=Date.now()-A;if(i?.ok)return ex({type:"replay-test",file:s.path,status:"pass",index:g,total:w,attempt:I,maxAttempts:f+1,durationMs:_,artifactsDir:b}),{file:s.path,session:S,status:"passed",durationMs:_,attempts:I,artifactsDir:b,replayed:"number"==typeof i.data?.replayed?i.data.replayed:0,healed:"number"==typeof i.data?.healed?i.data.healed:0};let N=i?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:i?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return ex({type:"replay-test",file:s.path,status:"fail",index:g,total:w,attempt:I,maxAttempts:f+1,durationMs:_,artifactsDir:b,message:N.message}),{file:s.path,session:S,status:"failed",durationMs:_,attempts:I,artifactsDir:b,error:N}}function nR(e,t=[],r){return{ts:Date.now(),command:e,positionals:t,flags:r??{}}}function nL(e,t,r){let n=new Set(r),a=Object.keys(e).filter(e=>!n.has(e));if(a.length>0)throw nG(`Maestro ${t} field "${a[0]}" is not supported yet.`)}function n$(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function nP(e){return e.map((e,t)=>{if("string"==typeof e||n$(e))return e;throw new d("INVALID_ARGS",`Unsupported Maestro command at index ${t+1}: expected a scalar or one-key map.`)})}function nF(e,t){if(null==e)return{};if(!n$(e))throw new d("INVALID_ARGS",`${t} expects a map.`);let r={};for(let[t,n]of Object.entries(e))("string"==typeof n||"number"==typeof n||"boolean"==typeof n)&&(r[t]=String(n));return r}function nC(e,t){return n$(e)&&"number"==typeof e.timeout&&Number.isFinite(e.timeout)?Math.max(0,Math.floor(e.timeout)):t}function nE(e,t){if(e.appId)return e.appId;throw new d("INVALID_ARGS",`${t} requires appId in the Maestro flow config.`)}function nV(e,t){if("string"==typeof t)return t;throw new d("INVALID_ARGS",`${e} expects a string value.`)}function nU(e,t){return e.replace(/\$\{([A-Za-z_][A-Za-z0-9_.]*)\}/g,(e,r)=>Object.prototype.hasOwnProperty.call(t.env,r)?String(t.env[r]):e)}function nT(e){throw nG(`Maestro command "${e}" is not supported yet.`)}function nG(e){throw new d("INVALID_ARGS",`${e} See supported/unsupported Maestro compatibility at ${eP}. If this syntax matters for your flows, comment there or open a focused issue at ${eF}.`)}function nj(e,t,r){var n,a;if(null==e)return nR("open",[nU(nE(t,"launchApp"),r)]);if("string"==typeof e)return nR("open",[nU(e,r)]);if(!n$(e))throw new d("INVALID_ARGS","launchApp expects a string or map.");nL(e,"launchApp",["appId","stopApp","clearState","clearKeychain","arguments","permissions","launchArguments"]),nB(e,"permissions"),nB(e,"clearKeychain");let i=nU("string"==typeof e.appId?e.appId:nE(t,"launchApp"),r),o=(n=e,a=r,[...nK(n.arguments,"launchApp.arguments",a),...nK(n.launchArguments,"launchApp.launchArguments",a)]),s=!0===e.clearState;return nR("open",[i],{...!s&&(!0===e.stopApp||o.length>0)?{relaunch:!0}:{},...s?{clearAppState:!0}:{},...o.length>0?{launchArgs:o}:{}})}function nq(e,t,r){if(null==e)return nR("close",[nU(nE(t,"stopApp"),r)]);if("string"==typeof e)return nR("close",[nU(e,r)]);throw new d("INVALID_ARGS","stopApp expects a string appId or no value.")}function nK(e,t,r){if(null==e)return[];if("string"==typeof e)return[nU(e,r)];if(Array.isArray(e))return e.map((e,n)=>nH(e,`${t}[${n}]`,r));if(n$(e))return Object.entries(e).flatMap(([e,n])=>[nU(e,r),nH(n,`${t}.${e}`,r)]);throw new d("INVALID_ARGS",`${t} expects a string, list, or map.`)}function nH(e,t,r){if("string"==typeof e)return nU(e,r);if("number"==typeof e||"boolean"==typeof e)return String(e);throw new d("INVALID_ARGS",`${t} must be a string, number, or boolean.`)}function nB(e,t){if(void 0!==e[t])throw nG(`Maestro launchApp field "${t}" is not supported yet.`)}function nW(e){let t=e.match(/^(\d+),(\d+)$/);if(!t)throw nG('Only absolute Maestro point selectors like "100,200" are supported.');return{x:Number(t[1]),y:Number(t[2])}}function nz(e){let t=e.match(/^\s*(\d+)\s*,\s*(\d+)\s*$/);if(t)return{kind:"absolute",x:Number(t[1]),y:Number(t[2])};let r=e.match(/^\s*(\d+(?:\.\d+)?)%\s*,\s*(\d+(?:\.\d+)?)%\s*$/);if(r)return{kind:"percent",x:Number(r[1]),y:Number(r[2])};throw nG('Only Maestro swipe coordinates like "100,200" or "50%,75%" are supported.')}let nJ="__maestroRunScript",nX="__maestroAssertVisible",nY="__maestroAssertNotVisible",nZ="__maestroPressEnter",nQ="__maestroWaitForAnimationToEnd",n0="__maestroScrollUntilVisible",n1="__maestroSwipeScreen",n2="__maestroSwipeOn",n3="__maestroTapOn",n5="__maestroTapPointPercent";function n6(e){if(null==e)return nR("type",["\b".repeat(50)]);if("number"==typeof e&&Number.isInteger(e)&&e>0)return nR("type",["\b".repeat(e)]);if(!n$(e))throw new d("INVALID_ARGS","eraseText expects empty, a positive count, or a map.");if(nL(e,"eraseText",["charactersToErase"]),void 0===e.charactersToErase)return nR("type",["\b".repeat(50)]);if("number"!=typeof e.charactersToErase||!Number.isInteger(e.charactersToErase)||e.charactersToErase<=0)throw new d("INVALID_ARGS","eraseText.charactersToErase must be a positive integer.");return nR("type",["\b".repeat(e.charactersToErase)])}function n8(e){return"number"==typeof e&&Number.isFinite(e)?String(Math.max(16,Math.floor(e))):void 0}function n9(e,t){let r=e.toLowerCase();switch(r){case"up":case"down":case"left":case"right":return r;default:throw nG(`Maestro ${t} must be UP, DOWN, LEFT, or RIGHT.`)}}function n4(e){return n9(e,"swipe direction")}function n7(e,t,r=[],n){if("string"==typeof e)return ae(nU(e,n));if(!n$(e))throw new d("INVALID_ARGS",`${t} expects a string or selector map.`);nL(e,t,["id","text","enabled","selected",...r]);let a=[],i=[];if("boolean"==typeof e.enabled&&i.push(ar("enabled",String(e.enabled))),"boolean"==typeof e.selected&&i.push(ar("selected",String(e.selected))),"string"==typeof e.id&&a.push(ar("id",nU(e.id,n)),...i),"string"==typeof e.text&&0===a.length)return ae(nU(e.text,n),i);if("string"==typeof e.label&&0===a.length&&a.push(ar("label",nU(e.label,n)),...i),0===a.length&&i.length>0&&a.push(...i),0===a.length)throw new d("INVALID_ARGS",`${t} selector map must include one of id, text, label, enabled, or selected.`);return a.join(" ")}function ae(e,t=[]){return[[ar("label",e),...t].join(" "),[ar("text",e),...t].join(" "),[ar("id",e),...t].join(" ")].join(" || ")}function at(e){let t=n8(e.duration);return t?[t]:[]}function ar(e,t){return`${e}=${JSON.stringify(t)}`}function an(e){var t,r;if(!n$(e))return;let n={},a="number"==typeof(t=e.repeat)&&Number.isInteger(t)&&t>0?t:void 0,i="number"==typeof(r=e.delay)&&Number.isInteger(r)&&r>=0?r:void 0;return a&&a>1&&(n.count=a),void 0!==i&&(n.intervalMs=i),!0===e.optional&&(n.maestro={optional:!0}),Object.keys(n).length>0?n:void 0}function aa(e){let t=an(e)??{};return{...t,maestro:{...t.maestro??{},allowNonHittableCoordinateFallback:!0}}}function ai(e){let t={doubleTap:!0};return n$(e)&&"number"==typeof e.delay&&Number.isInteger(e.delay)&&(t.intervalMs=Math.max(0,e.delay)),t}class ao{index=0;tokens;context;constructor(e,t){this.tokens=e,this.context=t}parse(){let e=this.parseOr();if(this.peek())throw new d("INVALID_ARGS","Unsupported trailing runFlow.when.true expression.");return e}parseOr(){let e=this.parseAnd();for(;this.consumeOperator("||");)e=this.parseAnd()||e;return e}parseAnd(){let e=this.parsePrimary();for(;this.consumeOperator("&&");)e=this.parsePrimary()&&e;return e}parsePrimary(){let e=this.peek();if(!e)throw new d("INVALID_ARGS","Incomplete runFlow.when.true expression.");if("boolean"===e.type)return this.index+=1,e.value;if("paren"===e.type&&"("===e.value){this.index+=1;let e=this.parseOr();if(!this.consumeParen(")"))throw new d("INVALID_ARGS","Unclosed runFlow.when.true parenthesis.");return e}return this.parsePlatformComparison()}parsePlatformComparison(){this.expectPlatform();let e=this.expectEqualityOperator(),t=this.expectString().toLowerCase(),r=this.context.platform;return"=="===e?r===t:r!==t}expectPlatform(){if(this.peek()?.type!=="platform")throw new d("INVALID_ARGS","runFlow.when.true supports maestro.platform comparisons.");this.index+=1}expectEqualityOperator(){let e=this.peek();if(e?.type==="operator"&&("=="===e.value||"!="===e.value))return this.index+=1,e.value;throw new d("INVALID_ARGS","runFlow.when.true comparison requires == or !=.")}expectString(){let e=this.peek();if(e?.type==="string")return this.index+=1,e.value;throw new d("INVALID_ARGS","runFlow.when.true comparison requires a string literal.")}consumeOperator(e){let t=this.peek();return t?.type==="operator"&&t.value===e&&(this.index+=1,!0)}consumeParen(e){let t=this.peek();return t?.type==="paren"&&t.value===e&&(this.index+=1,!0)}peek(){return this.tokens[this.index]}}function as(e,t,r){return{...nR(e,t),replayControl:r}}function al(e,t,r){let n="string"==typeof e?nU(e,t):e,a="number"==typeof n?n:"string"==typeof n&&/^\d+$/.test(n)?Number(n):void 0;if(void 0===a||!Number.isInteger(a)||a<0)throw new d("INVALID_ARGS",`${r} must be a non-negative integer or \${VAR} resolving to one.`);return a}let au=`
7
+ const fs = require('node:fs');
8
+ const input = JSON.parse(fs.readFileSync(0, 'utf8'));
9
+ if (typeof fetch !== 'function') {
10
+ console.error('global fetch is required for Maestro runScript http helpers');
11
+ process.exit(1);
12
+ }
13
+ fetch(input.url, {
14
+ method: input.method,
15
+ headers: input.headers,
16
+ body: input.body,
17
+ }).then(async response => {
18
+ process.stdout.write(JSON.stringify({
19
+ status: response.status,
20
+ body: await response.text(),
21
+ headers: Object.fromEntries(response.headers.entries()),
22
+ }));
23
+ }).catch(error => {
24
+ console.error(error && error.stack ? error.stack : String(error));
25
+ process.exit(1);
26
+ });
27
+ `;function ac(e){if("string"!=typeof e)throw new d("COMMAND_FAILED",`Maestro runScript json() expected a string body, received ${typeof e}.`);if(0===e.trim().length)throw new d("COMMAND_FAILED","Maestro runScript json() received an empty body. Check the preceding http response status and setup server output.");try{return JSON.parse(e,ad)}catch(t){throw new d("COMMAND_FAILED",`Maestro runScript json() could not parse response body: ${t instanceof Error?t.message:String(t)}`,{bodyPreview:e.slice(0,1e3)},t instanceof Error?t:void 0)}}function ad(e,t){return"__proto__"===e||"constructor"===e||"prototype"===e?void 0:t}let ap={launchApp:({value:e,config:t,context:r})=>[nj(e,t,r)],tapOn:({value:e,context:t})=>[function(e,t){if("string"==typeof e)return nR(n3,[ae(nU(e,t))],aa(e));if(n$(e)&&"string"==typeof e.point){nL(e,"tapOn",["point","repeat","delay","optional","label"]);let t=nz(e.point);return"percent"===t.kind?nR(n5,[String(t.x),String(t.y)],an(e)):nR("click",[String(t.x),String(t.y)],an(e))}n$(e)&&nL(e,"tapOn",["id","text","childOf","enabled","index","selected","repeat","delay","optional","label"]);let r=aa(e);return nR(n3,[n7(e,"tapOn",["repeat","delay","optional","label","index","childOf"],t),...function(e,t){if(!n$(e))return[];let r={};if(void 0!==e.index){if("number"!=typeof e.index||!Number.isInteger(e.index)||e.index<0)throw new d("INVALID_ARGS","tapOn.index must be a non-negative integer.");r.index=e.index}return void 0!==e.childOf&&(r.childOf=n7(e.childOf,"tapOn.childOf",[],t)),Object.keys(r).length>0?[JSON.stringify(r)]:[]}(e,t)],r)}(e,t)],doubleTapOn:({value:e,context:t})=>[function(e,t){if(n$(e)&&"string"==typeof e.point){nL(e,"doubleTapOn",["point","delay"]);let t=nW(e.point);return nR("click",[String(t.x),String(t.y)],ai(e))}return n$(e)&&nL(e,"doubleTapOn",["id","text","enabled","selected","delay"]),nR("click",[n7(e,"doubleTapOn",["delay"],t)],ai(e))}(e,t)],longPressOn:({value:e,context:t})=>[function(e,t){if(n$(e)&&"string"==typeof e.point){nL(e,"longPressOn",["point"]);let t=nW(e.point);return nR("longpress",[String(t.x),String(t.y),"3000"])}return n$(e)&&nL(e,"longPressOn",["id","text","enabled","selected"]),nR("click",[n7(e,"longPressOn",[],t)],{holdMs:3e3})}(e,t)],inputText:({value:e,context:t})=>[nR("type",[nU(function(e){if("string"==typeof e)return e;if(!n$(e))throw new d("INVALID_ARGS","inputText expects a string or map.");if(nL(e,"inputText",["text","label"]),"string"!=typeof e.text)throw new d("INVALID_ARGS","inputText map requires a string text field.");return e.text}(e),t)])],eraseText:({value:e})=>[n6(e)],pasteText:({value:e,context:t,name:r})=>[nR("type",[nU(nV(r,e),t)])],openLink:({value:e,config:t,context:r,name:n})=>{var a,i,o,s,l,u;let c;return[(a=e,i=t,o=r,s=n,c=nU((l=a,u=s,"string"==typeof l?l:n$(l)?(nL(l,u,["link"]),nV(`${u}.link`,l.link)):nV(u,l)),o),("ios"===o.platform||"android"===o.platform)&&i.appId?nR("open",[nU(nE(i,s),o),c]):nR("open",[c]))]},assertVisible:({value:e,context:t,name:r})=>[nR(nX,[n7(e,r,[],t),"5000"])],assertNotVisible:({value:e,context:t,name:r})=>[nR(nY,[n7(e,r,[],t)])],extendedWaitUntil:({value:e,context:t})=>(function(e,t){if(!n$(e))throw new d("INVALID_ARGS","extendedWaitUntil expects a map.");nL(e,"extendedWaitUntil",["visible","notVisible","timeout"]);let r=e.visible??e.notVisible;if(void 0===r)throw nG("Only Maestro extendedWaitUntil.visible/notVisible is supported.");let n=n7(r,"extendedWaitUntil",[],t),a=String(nC(e,3e4));return void 0!==e.notVisible?[nR(nY,[n,a])]:[nR(nX,[n,a])]})(e,t),takeScreenshot:({value:e,context:t,name:r})=>[nR("screenshot",[nU(nV(r,e),t)])],scroll:({value:e})=>[function(e){if(null!=e)throw nG("Maestro scroll options are not supported yet.");return nR("scroll",["down"])}(e)],scrollUntilVisible:({value:e,context:t})=>(function(e,t){if("string"==typeof e)return[nR(n0,[ae(nU(e,t)),"5000","down"])];if(!n$(e))throw new d("INVALID_ARGS","scrollUntilVisible expects a string or map.");nL(e,"scrollUntilVisible",["element","direction","timeout"]);let r=n7(e.element,"scrollUntilVisible.element",[],t),n="string"==typeof e.direction?n9(e.direction,"scrollUntilVisible.direction"):"down";return[nR(n0,[r,String(nC(e,5e3)),n])]})(e,t),swipe:({value:e,context:t})=>[function(e,t){var r,n,a;let i;if(!n$(e))throw new d("INVALID_ARGS","swipe expects a map.");nL(e,"swipe",["start","end","direction","duration","from","label"]);let o=e.from??("string"==typeof e.label?e.label:void 0);return void 0!==o?(r=e,n=o,a=t,i=n4("string"==typeof r.direction?r.direction:"up"),nR(n2,[n7(n,"swipe.from",[],a),i,...at(r)])):"string"==typeof e.direction?nR(n1,["direction",n4(e.direction),...at(e)]):function(e){let{start:t,end:r}=function(e){if("string"==typeof e.start&&"string"==typeof e.end)return{start:nz(e.start),end:nz(e.end)};throw nG("Only Maestro swipe start/end coordinates are supported.")}(e);var n=t,a=r,i=n8(e.duration);if("absolute"===n.kind&&"absolute"===a.kind)return nR("swipe",[String(n.x),String(n.y),String(a.x),String(a.y),...i?[i]:[]]);if("percent"===n.kind&&"percent"===a.kind)return nR(n1,["percent",String(n.x),String(n.y),String(a.x),String(a.y),...i?[i]:[]]);throw nG("Maestro swipe start/end must both be absolute pixels or both be percentages.")}(e)}(e,t)],hideKeyboard:()=>[nR("keyboard",["dismiss"])],pressKey:({value:e})=>[function(e){let t=nV("pressKey",e).toLowerCase();if("back"===t)return nR("back");if("enter"===t||"return"===t)return nR(nZ);if("home"===t)return nR("home");throw nG(`Maestro pressKey "${t}" is not supported yet.`)}(e)],back:()=>[nR("back")],waitForAnimationToEnd:({value:e})=>[nR(nQ,[String(nC(e,15e3))])],stopApp:({value:e,config:t,context:r})=>[nq(e,t,r)],runScript:({value:e,context:t})=>{let r;return[nR(nJ,[function(e,t){if(a.isAbsolute(e))return e;if(!t.baseDir)throw new d("INVALID_ARGS","runScript file paths require replay input to have a source path.");return a.resolve(t.baseDir,e)}((r=function(e,t){if("string"==typeof e)return{file:nU(e,t),env:{}};if(!n$(e))throw new d("INVALID_ARGS","runScript expects a file path string or map.");return nL(e,"runScript",["file","env"]),{file:nU(nV("runScript.file",e.file),t),env:Object.fromEntries(Object.entries(nF(e.env,"runScript.env")).map(([e,r])=>[e,nU(r,t)]))}}(e,t)).file,t)],{...Object.keys(r.env).length>0?{maestro:{runScriptEnv:r.env}}:{}})]},runFlow:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){if("string"==typeof e)return n.parseRunFlowFile(nU(e,r),r).actions;if(!n$(e))throw new d("INVALID_ARGS","runFlow expects a file path string or map.");nL(e,"runFlow",["file","commands","env","when","label"]);let i=function(e,t){var r,n;if(null==e)return{shouldRun:!0};if(!n$(e))throw new d("INVALID_ARGS","runFlow.when expects a map.");return(nL(e,"runFlow.when",["platform","visible","notVisible","true"]),!function(e,t){if(void 0!==e.true&&!function(e,t){let r;if("boolean"==typeof e)return e;if("string"!=typeof e)throw new d("INVALID_ARGS","runFlow.when.true expects a boolean or expression string.");return new ao(function(e){let t=[],r=0;for(;r<e.length;){var n,a;let i=e.slice(r),o=(n=i,/^\s+/.exec(n)?.[0].length??0);if(o>0){r+=o;continue}let s=function(e){let t="maestro.platform";return e.startsWith(t)?{token:{type:"platform"},length:t.length}:null}(a=i)??function(e){let t=/^(==|!=|&&|\|\|)/.exec(e)?.[1];return t?{token:{type:"operator",value:t},length:t.length}:null}(a)??function(e){let t=e[0];return"("===t||")"===t?{token:{type:"paren",value:t},length:1}:null}(a)??function(e){let t=/^(['"])(.*?)\1/.exec(e);return t?{token:{type:"string",value:t[2]??""},length:t[0].length}:null}(a)??function(e){let t=/^(true|false)\b/.exec(e)?.[1];return t?{token:{type:"boolean",value:"true"===t},length:t.length}:null}(a);if(s){t.push(s.token),r+=s.length;continue}throw new d("INVALID_ARGS",`Unsupported runFlow.when.true expression near "${i.slice(0,24)}".`)}return t}((r=nU(e,t).trim()).startsWith("${")&&r.endsWith("}")?r.slice(2,-1).trim():r),{platform:t.platform}).parse()}(e.true,t))return!1;if(void 0===e.platform)return!0;let r=function(e,t){if("string"!=typeof e)throw new d("INVALID_ARGS",`${t} expects Android, iOS, or Web.`);let r=e.trim().toLowerCase();if("android"===r||"ios"===r||"web"===r)return r;throw new d("INVALID_ARGS",`${t} expects Android, iOS, or Web.`)}(e.platform,"runFlow.when.platform");if(!t.platform)throw new d("INVALID_ARGS","Maestro runFlow.when.platform requires replay to be run with --platform ios|android.");return r===t.platform}(e,t))?{shouldRun:!1}:{shouldRun:!0,...(r=e,n=t,{...void 0!==r.visible?{visibleSelector:n7(r.visible,"runFlow.when.visible",[],n)}:{},...void 0!==r.notVisible?{notVisibleSelector:n7(r.notVisible,"runFlow.when.notVisible",[],n)}:{}})}}(e.when,r);if(!i.shouldRun)return[];let o={...r,env:{...r.env,...nF(e.env,"runFlow.env"),...r.envOverrides}};return function(e,t){let{visibleSelector:r,notVisibleSelector:n}=t;if(!r&&!n)return e;if(r&&n)throw nG("Maestro runFlow.when cannot combine visible and notVisible yet.");let a=r?"visible":"notVisible",i=r??n??"";return[as("runFlow.when",[a,i],{kind:"maestroRunFlowWhen",mode:a,selector:i,actions:e})]}(function(e,t,r,n,a){if("string"==typeof e.file)return n.parseRunFlowFile(nU(e.file,r),r).actions;if(Array.isArray(e.commands))return a(nP(e.commands),t,r,n);throw new d("INVALID_ARGS","runFlow map requires either file or commands.")}(e,t,o,n,a),i)})(e,t,r,n,ah),repeat:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){var i;if(!n$(e))throw new d("INVALID_ARGS","repeat expects a map.");if(nL(e,"repeat",["times","commands","while"]),void 0!==e.while)throw nG("Maestro repeat.while is not supported yet. Only deterministic repeat.times is supported.");let o=(i=e.times,al(i,r,"repeat.times"));if(!Array.isArray(e.commands))throw new d("INVALID_ARGS","repeat requires a commands list.");if(o>1e3)throw new d("INVALID_ARGS","repeat.times must be <= 1000 for deterministic replay expansion.");let s=nP(e.commands);return Array.from({length:o}).flatMap(()=>a(s,t,r,n))})(e,t,r,n,ah),retry:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){var i,o;if(!n$(e))throw new d("INVALID_ARGS","retry expects a map.");if(nL(e,"retry",["maxRetries","commands"]),!Array.isArray(e.commands))throw new d("INVALID_ARGS","retry requires a commands list.");let s=(i=e.maxRetries,o=r,void 0===i?1:al(i,o,"retry.maxRetries")),l=a(nP(e.commands),t,r,n);return[as("retry",[String(s)],{kind:"retry",maxRetries:s,actions:l})]})(e,t,r,n,ah)},af={launchApp:(e,t)=>[nj(void 0,e,t)],scroll:()=>[nR("scroll",["down"])],hideKeyboard:()=>[nR("keyboard",["dismiss"])],eraseText:()=>[n6(void 0)],back:()=>[nR("back")],waitForAnimationToEnd:()=>[nR(nQ,["15000"])],stopApp:(e,t)=>[nq(void 0,e,t)]};function am(e,t,r,n,a){try{return function(e,t,r,n){if("string"==typeof e){var a,i,o;let n;return a=e,i=t,o=r,(n=af[a])?n(i,o):nT(a)}let s=Object.entries(e);if(1!==s.length)throw new d("INVALID_ARGS","Maestro command maps must contain exactly one command.");let[l,u]=s[0],c=ap[l];return c?c({value:u,config:t,context:r,deps:n,name:l}):nT(l)}(e,t,n,a)}catch(e){if(e instanceof d&&!/\bline \d+\b/.test(e.message))throw new d(e.code,`${e.message} (line ${r})`,e.details);throw e}}function ah(e,t,r,n){return e.flatMap((e,a)=>am(e,t,a+1,r,n))}function ag(e,t){let{config:r,commands:n}=function(e){if(0===e.length)throw new d("INVALID_ARGS","Maestro flow is empty.");if(Array.isArray(e[0]))return{config:{},commands:nP(e[0])};let t=function(e){if(!n$(e))throw new d("INVALID_ARGS","Maestro flow config must be a YAML map.");return{..."string"==typeof e.appId&&e.appId.length>0?{appId:e.appId}:{},...n$(e.env)?{env:nF(e.env,"env")}:{},...Array.isArray(e.onFlowStart)?{onFlowStart:nP(e.onFlowStart)}:{},...Array.isArray(e.onFlowComplete)?{onFlowComplete:nP(e.onFlowComplete)}:{}}}(e[0]),r=e[1];if(!Array.isArray(r))throw new d("INVALID_ARGS","Maestro flow must contain a command list after the YAML document separator.");return{config:t,commands:nP(r)}}(function(e){let t=s(e);for(let e of t)if(e.errors.length>0){let t=e.errors[0]?.message??"Invalid Maestro YAML flow.";throw new d("INVALID_ARGS",`Invalid Maestro YAML flow: ${t}`)}return t.map(e=>e.toJSON()).filter(e=>null!==e)}(e)),a={...t,env:{...t.env,...r.env??{},...t.envOverrides}},{actions:i,actionLines:o}=function(e){let{config:t,commands:r,commandLines:n,context:a}=e,i=[...t.onFlowStart??[],...r,...t.onFlowComplete??[]],o=[...Array.from({length:t.onFlowStart?.length??0},()=>1),...n,...Array.from({length:t.onFlowComplete?.length??0},()=>n.at(-1)??1)],s=[],l=[];for(let[e,r]of i.entries()){let n=o[e]??e+1,i=am(r,t,n,a,{parseRunFlowFile:aw});s.push(...i),i.forEach(()=>l.push(n))}return function(e,t){let r=[],n=[];for(let a=0;a<e.length;a+=1){let i=e[a],o=function(e,t,r){var n;let a=function(e,t,r){let n=e[r],a=e[r+1],i=e[r+2];if(i?.command!==nZ||n.flags?.maestro?.optional===!0)return null;let o=function(e){if(e?.command!=="type"||e.flags&&Object.keys(e.flags).length>0)return null;let[t,...r]=e.positionals??[];return r.length>0||"string"!=typeof t?null:t}(a),s=function(e){if(e?.command!==n3)return null;let[t,...r]=e.positionals??[];return r.length>0||"string"!=typeof t?null:t}(n);return a&&null!==o&&null!==s?{action:n,nextAction:a,pressEnterAction:i,tapSelector:s,typedAfterTap:o,line:t[r]??1}:null}(e,t,r);if(!a)return null;let{action:i,nextAction:o,pressEnterAction:s,tapSelector:l,typedAfterTap:u,line:c}=a;return(n=l,/\b(input|textfield|textarea|field|email|password|username|search|query)\b/i.test(n.replace(/([a-z])([A-Z])/g,"$1 $2")))?{actions:[{...i,command:"wait",positionals:[l,"30000"]},{...o,command:"fill",positionals:[l,u],flags:i.flags},s],actionLines:[c,c,t[r+2]??c],consumed:3}:{actions:[function(e){let t={...e.flags?.maestro??{}};return delete t.allowNonHittableCoordinateFallback,{...e,flags:{...e.flags??{},maestro:{...t}}}}(i)],actionLines:[c],consumed:1}}(e,t,a);if(o){r.push(...o.actions),n.push(...o.actionLines),a+=o.consumed-1;continue}r.push(i),n.push(t[a]??1)}return{actions:r,actionLines:n}}(s,l)}({config:r,commands:n,commandLines:function(e){let t=e.split(/\r?\n/),r=t.findIndex(e=>"---"===e.trim()),n=-1===r?0:r+1,a=[];for(let e=n;e<t.length;e+=1)/^-\s+/.test(t[e]??"")&&a.push(e+1);return a}(e),context:a});return{actions:i,actionLines:o,metadata:{env:r.env}}}function aw(e,r){let n=function(e,t){if(a.isAbsolute(e))return e;if(!t.baseDir)throw new d("INVALID_ARGS","runFlow file paths require replay input to have a source path.");return a.resolve(t.baseDir,e)}(e,r);if(r.visitedPaths.has(n))throw new d("INVALID_ARGS",`Maestro runFlow cycle detected at ${n}.`);let i=t.readFileSync(n,"utf8"),o=new Set(r.visitedPaths);return o.add(n),ag(i,{...r,baseDir:a.dirname(n),visitedPaths:o})}let ay={maestro:{parse:function(e,t={}){var r;let n;return ag(e,(n=(r=t).visitedPaths??new Set,r.sourcePath&&n.add(a.resolve(r.sourcePath)),{baseDir:r.sourcePath?a.dirname(r.sourcePath):void 0,platform:function(e){if(e){let t;return"android"===(t=e.trim().toLowerCase())?"android":"ios"===t?"ios":void 0}}(r.platform),env:{},envOverrides:r.env??{},visitedPaths:n}))}}};function av(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=void 0!==t&&/^\d+$/.test(t)?t:null,n=e0(null!==r?e.slice(0,-1):e.slice());return!n||n.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:n.selectorExpression,selectorTimeout:r}}async function aA(e){let{action:t,sessionName:r,logPath:n,sessionStore:a}=e;if(!(_(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let i=a.get(r);if(!i)return null;let o=(function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),_(e.command)){let r=function(e){let t=e.positionals??[];if("longpress"!==e.command)return t;let r=t.at(-1);return t.length>1&&ab(r)?t.slice(0,-1):t}(e),n=r[0]??"";n&&!n.startsWith("@")&&t.push(r.join(" "))}if("fill"===e.command){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&Number.isNaN(Number(r))&&t.push(r)}if("get"===e.command){let r=e.positionals?.[1]??"";r&&!r.startsWith("@")&&t.push(e.positionals.slice(1).join(" "))}if("is"===e.command){let{split:r}=e5(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=av(e.positionals??[]);r&&t.push(r)}return C(t).filter(e=>e.trim().length>0)})(t).map(e=>e6(e)).filter(e=>null!==e);if(0===o.length)return null;let s=_(t.command)||"fill"===t.command,l=_(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await aS(i,t,n,s,a);for(let e of o){let r=e9(u.nodes,e,{platform:i.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let n=e4(r.node,i.device.platform,{action:"fill"===t.command?"fill":_(t.command)?"click":"get"}).join(" || ");if(_(t.command))return{...t,positionals:"longpress"===t.command?function(e,t){let r="number"==typeof e.result?.durationMs?String(e.result.durationMs):function(e){let t=e.at(-1);return e.length>1&&ab(t)?t:void 0}(e.positionals??[]);return r?[t,r]:[t]}(t,n):[n]};if("fill"===t.command){let e=A(t);if(!e)continue;return{...t,positionals:[n,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,n]}}if("is"===t.command){let{predicate:e,split:r}=e5(t.positionals);if(!e)continue;let a=r?.rest.join(" ").trim()??"",i=[e,n];return"text"===e&&a.length>0&&i.push(a),{...t,positionals:i}}if("wait"===t.command){let{selectorTimeout:e}=av(t.positionals??[]),r=[n];return e&&r.push(e),{...t,positionals:r}}}return null}function ab(e){return void 0!==e&&""!==e.trim()&&Number.isFinite(Number(e))}async function aS(e,t,r,n,a){let i=X(await m(e.device,"snapshot",[],t.flags?.out,{...Y(r,{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n},e.appBundleId,e.trace?.outPath)}),{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n});return j(e,i),a.set(e.name,e),i}let aI=new WeakMap,a_=new WeakMap;function aN(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}async function aM(e){var t;let r,n=await e.invoke({...e.baseReq,command:"snapshot",positionals:[],flags:{...e.baseReq.flags,noRecord:!0,snapshotRaw:!0,snapshotForceFull:!0}});return n.ok&&e.scope&&(t=e.scope,(r=q(ax(n.data)))&&aI.set(t,r)),n}function ax(e){if("object"==typeof e&&null!==e&&Array.isArray(e.nodes))return e}let aD=new Map([["button",0],["link",0],["textfield",0],["textview",0],["searchfield",0],["switch",0],["slider",0],["cell",1],["statictext",2]]);function ak(e,t,r,n){let a=a$(e,t,r),i=aO({nodes:e.nodes,matches:a,platform:r}),o=aC(e.nodes,i.matches,void 0,aL(t),n,!0);return o?{ok:!0,node:o.node,rect:o.rect,matches:i.matches.length}:{ok:!1,message:a.length>0?i.blockedByReactNativeOverlay?`Maestro selector matched ${a.length} element(s), but React Native overlay is covering app content: ${t}`:`Maestro selector matched ${a.length} element(s), but none were visible: ${t}`:`Maestro selector did not match: ${t}`}}function aO(e){let t=e.matches.filter(t=>ts({predicate:"visible",node:t,nodes:e.nodes,platform:e.platform}).pass),r=function(e,t){let r=tu(e);if(!r.detected||!r.redBox)return{matches:t,blockedByReactNativeOverlay:!1};let n=new Set([...r.dismissNodes,...r.minimizeNodes,...r.collapsedNodes].map(e=>e.index)),a=t.filter(e=>n.has(e.index));return{matches:a,blockedByReactNativeOverlay:t.length>0&&0===a.length}}(e.nodes,t);return{matches:r.matches,blockedByReactNativeOverlay:r.blockedByReactNativeOverlay}}function aR(e){return e?.platform==="android"?"android":"ios"}function aL(e){let t=e8(e).selectors.flatMap(e=>e.terms);if(0===t.length||!t.some(e=>"label"===e.key||"text"===e.key)||!t.every(e=>["label","text","id"].includes(e.key)))return null;let r=t.map(e=>"string"==typeof e.value?e.value:""),n=r[0];return n&&r.every(e=>e===n)?n:null}function a$(e,t,r){for(let n of e8(t).selectors){let t=e.nodes.filter(e=>(function(e,t,r){return!!te(e,t,r)||t.terms.every(t=>(function(e,t,r){var n,a,i;return"string"!=typeof t.value||"id"!==(n=t.key)&&"label"!==n&&"text"!==n&&"value"!==n?te(e,{raw:t.key,terms:[t]},r):aP((a=e,"id"===(i=t.key)?a.identifier:"label"===i?a.label:"value"===i?a.value:e1(a)),t.value)})(e,t,r))})(e,n,r));if(t.length>0)return t}return[]}function aP(e,t){var r;let n=e??"",a=tr(n),i=tr(t);if(a===i||function(e,t){if(!e||!t||!e.startsWith(t))return!1;let r=e.at(t.length);return","===r||":"===r||";"===r}(a,i))return!0;if(r=t,!/(?:\.\*|\.\+|\[[^\]]+\]|\([^)]*\)|\||\^|\$|\\[dDsSwWbB])/.test(r))return!1;try{return new RegExp(t).test(n)}catch{return!1}}function aF(e,t,r){if(t.rect&&t.rect.width>0&&t.rect.height>0)return{rect:t.rect,inherited:!1};if(t.rect)return null;let n=function(e,t,r){let n=t;for(;"number"==typeof n.parentIndex&&(n=r.get(n.parentIndex)??e[n.parentIndex]);)if(n.rect)return n.rect.width>0&&n.rect.height>0?n.rect:null;return null}(e,t,r);return n?{rect:n,inherited:!0}:null}function aC(e,t,r,n,a,i=!1,o=!1,s){var l,u,c,d,p,f,m,h,g,w,y,v,A,b,S,I,_,N,M;let x,D,k,O,R=e7(e),L=(l=e,u=t,c=R,d=n,p=r,f=a,m=i,k=(D=(x=u.map(e=>{var t;let r;return(r=aF(l,t=e,c))?{node:t,rect:r.rect,inheritedRect:r.inherited}:null}).filter(e=>!!e)).filter(e=>!e.inheritedRect)).length>0?D:x,d&&void 0===p?(h=k,g=f,w=m,O=h.filter(e=>{var t,r;let n,a;return t=e.rect,r=g,n=r?.referenceWidth??1/0,a=r?.referenceHeight??1/0,t.x<n&&t.y<a&&t.x+t.width>0&&t.y+t.height>0}),w||O.length>0?O:h):x),$=function(e,t,r,n,a,i){var o,s,l,u,c,d,p;if(void 0!==r)return t[r]??null;let f=(o=e,s=t,l=n,u=a,c=i,u&&l?function(e,t,r,n){let a=t.filter(e=>0===aH(e.node,r));if(a.length>=2){let t=aV(e,a,r,n);if(t)return t}let i=t.filter(e=>1===aH(e.node,r));return a.length>0||i.length<2?null:aV(e,i,r,n)}(o,s,l,c)??aE(o,s,l,c):aE(o,s,l,c));return(d=f,p=n,a&&p&&d)?function(e,t,r){var n,a,i,o,s,l,u,c,d,p,f,m,h,g,w,y,v;let A,b,S,I,_,N,M,x;if(n=t,a=r,!(("other"===(A=tt(n.node.type??""))||"scrollview"===A||"scroll-area"===A)&&!(n.rect.width<120)&&!(n.rect.height<32)&&!(n.rect.height>80)&&1>=aH(n.node,a)))return null;let D=(i=e,o=t,s=r,i.filter(e=>{var t,r,n,a,i;let l,u;return e.parentIndex===o.node.index&&!!e.rect&&(t=e,r=o.rect,n=s,!("button"!==(l=tt(t.type??""))&&"cell"!==l&&"other"!==l||1>=aH(t,n))&&!(t.rect.width<16)&&!(t.rect.height<16)&&!!aq(r,t.rect)&&(a=r,i=t.rect,u=Math.max(a.y,i.y),Math.max(0,Math.min(a.y+a.height,i.y+i.height)-u)/Math.max(1,Math.min(a.height,i.height))>=.5))}).sort((e,t)=>e.rect.x-t.rect.x));if(0===D.length)return null;let k=(S=Math.floor((b=[...D.map(e=>e.rect.width)].sort((e,t)=>e-t)).length/2),b[S]??0),O=function(e,t){let r=[],n=e.x,a=e.x+e.width;for(let i of t){let t=Math.max(e.x,i.x),o=Math.min(a,i.x+i.width);t>n&&r.push({x:n,width:t-n}),n=Math.max(n,o)}return a>n&&r.push({x:n,width:a-n}),r}(t.rect,D.map(e=>e.rect)),R=(l=t,u=r,c=O,d=k,N=c.filter(e=>{var t,r;return t=e.width,r=d,!(t<24)&&!(r<24)&&t>=.4*r&&t<=1.6*r}),M=(p=l,f=u,I=c.find(e=>1>Math.abs(e.x-p.rect.x)),_=Math.max(48,Math.min(220,8*f.length+24)),(m=p,h=f,g=I,w=_,g&&"scrollview"===tt(m.node.type??"")&&1>=aH(m.node,h)&&m.rect.width>=240&&m.rect.height>=32&&m.rect.height<=80&&g.width<=.55*m.rect.width&&g.width>=.6*w)?{x:p.rect.x,width:Math.min(_,I.width)}:null),x=N.some(e=>{var t;return t=l.rect,1>Math.abs(e.x-t.x)}),M&&!x?M:1===N.length?N[0]??null:M);return R?(y=t,v=R,{...y,rect:{x:v.x,y:y.rect.y,width:v.width,height:y.rect.height}}):null}(e,f,n)??f:f}(e,L,r,n,o,s);return y=e,v=$,A=R,b=o,S=a,v?b?(I=y,_=v,N=A,M=S,(aj(_.node)?null:e2(I,_.node,N,e=>{if(!aj(e))return null;let t=aF(I,e,N);return t&&function(e,t,r){if(!aq(t,e))return!1;let n=aT(t),a=aT(e);if(a>0&&n>30*a)return!1;if(r){let e=r.referenceWidth*r.referenceHeight;if(e>0&&n>.5*e)return!1}return!0}(_.rect,t.rect,M)?{node:e,rect:t.rect}:null}))??{node:v.node,rect:v.rect}):{node:v.node,rect:v.rect}:null}function aE(e,t,r,n){return(function(e,t,r,n){var a;let i,o,s;if(!r||t.length<2)return t;let l=t.filter(e=>0===aH(e.node,r));if(l.length<2)return t;let u=e7(e),c=l.map(t=>({candidate:t,container:aU(e,t.node,u)})).filter(e=>!!e.container);if(c.length<2||c.length!==l.length)return t;let d=c.filter(e=>{var t;return t=e,c.some(e=>e!==t&&t.container.index!==e.container.index&&aK(t.container.rect,e.container.rect)>=.6)});if(d.length<2)return t;let p=(o=Math.max(...i=(a=d).map(e=>aT(e.container.rect))),(s=Math.min(...i))<=0||o<1.2*s?[]:a.filter(e=>aT(e.container.rect)===o).map(e=>e.candidate));if(p.length>0)return p;let f=function(e,t,r,n){if(!r)return[];let a=aU(e,r.node,n),i=a&&aq(a.rect,r.rect)?a:null,o=t.map(e=>({entry:e,score:function(e,t,r){if(r)return e.index===r.index?0:.6>aK(e.rect,r.rect)?1/0:Math.abs(e.index-r.index);if(aK(e.rect,t.rect)>=.6)return 0;let n=e.index-t.node.index;return n>=0?n:1e5+Math.abs(n)}(e.container,r,i)})),s=Math.min(...o.map(e=>e.score));return Number.isFinite(s)?o.filter(e=>e.score===s).map(e=>e.entry.candidate):[]}(e,d,n,u);if(f.length>0)return f;let m=Math.max(...d.map(e=>e.container.index)),h=d.filter(e=>e.container.index===m).map(e=>e.candidate);return h.length>0?h:t})(e,t,r,n).sort((e,t)=>(function(e,t,r){var n,a;let i=function(e,t,r){if(r){let n=aH(e.node,r)-aH(t.node,r);if(0!==n)return n}let n=aG(e.node)-aG(t.node);if(0!==n)return n;let a=Number(e.inheritedRect)-Number(t.inheritedRect);if(0!==a)return a;let i=r&&aG(e.node)===aG(t.node)?aT(t.rect)-aT(e.rect):aT(e.rect)-aT(t.rect);return 0!==i?i:0}(e,t,r);if(0!==i)return i;if(n=e.rect,a=t.rect,Math.round(n.x)!==Math.round(a.x)||Math.round(n.y)!==Math.round(a.y)||Math.round(n.width)!==Math.round(a.width)||Math.round(n.height)!==Math.round(a.height))return e.node.index-t.node.index;let o=(t.node.depth??0)-(e.node.depth??0);return 0!==o?o:t.node.index-e.node.index})(e,t,r))[0]??null}function aV(e,t,r,n){let a=e7(e),i=t.filter(r=>{var n;return(n=r).rect.width>=16&&n.rect.width<=260&&n.rect.height>=24&&n.rect.height<=80&&t.some(t=>{var n,i,o,s;return n=e,i=t,o=r,s=a,!(i.node.index===o.node.index||!aq(i.rect,o.rect)||aT(i.rect)<2*aT(o.rect))&&e3(n,o.node,i.node,s)})});return aE(e,i,r,n)}function aU(e,t,r){return e2(e,t,r,e=>{let t;return!e.rect||"scrollview"!==(t=tt(e.type??""))&&"scroll-area"!==t&&"list"!==t||e.rect.width<240||e.rect.height<320?null:e})}function aT(e){return e.width*e.height}function aG(e){return aD.get(tt(e.type??""))??3}function aj(e){let t=tt(e.type??"");return!0===e.hittable||"button"===t||"link"===t||"cell"===t||"textfield"===t||"searchfield"===t||"switch"===t||"slider"===t}function aq(e,t){return t.x>=e.x&&t.y>=e.y&&t.x+t.width<=e.x+e.width&&t.y+t.height<=e.y+e.height}function aK(e,t){let r=Math.max(e.x,t.x),n=Math.min(e.x+e.width,t.x+t.width),a=Math.max(e.y,t.y);return Math.max(0,n-r)*Math.max(0,Math.min(e.y+e.height,t.y+t.height)-a)/Math.max(1,Math.min(aT(e),aT(t)))}function aH(e,t){let r=[e.label,e1(e),e.identifier,e.value].filter(e=>!!e);return r.some(e=>e===t)?0:r.some(e=>tr(e)===tr(t))?1:r.some(e=>aP(e,t))?2:3}async function aB(e){let t,r=aW(e.positionals,{command:"assertVisible",defaultTimeoutMs:5e3});if(!r.ok)return r.response;let n=Date.now(),a=r.timeoutMs+1e3,i=!1;for(;;){var o,s,l,u,c,d,p;let f=Date.now(),m=await az(e,r.selector,"assertVisible");if(m.visible){return o=m.response,s=r.selector,l=n,o.ok?{ok:!0,data:{selector:s,...o.data,waitedMs:Date.now()-l}}:o}if(t=m.response,Date.now()-n>=a){if(u=i,c=f,d=n,p=a,!u&&c-d<p){i=!0;continue}break}await td(250)}return t??aN("COMMAND_FAILED",`Expected visible but did not match: ${r.selector}`,{selector:r.selector,timeoutMs:r.timeoutMs})}function aW(e,t){let[r,n=String(t.defaultTimeoutMs)]=e;if(!r)return{ok:!1,response:aN("INVALID_ARGS",`${t.command} requires a selector.`)};let a=Number(n);return!Number.isFinite(a)||a<0?{ok:!1,response:aN("INVALID_ARGS",`${t.command} timeout must be a non-negative number.`)}:{ok:!0,selector:r,timeoutMs:a}}async function az(e,t,r){var n;let a=await aM(e);if(!a.ok)return{visible:!1,response:a,infrastructureFailure:!0};let i=ax(a.data);if(!i)return{visible:!1,response:aN("COMMAND_FAILED",`Unable to read snapshot data for ${r}.`),infrastructureFailure:!0};let o=ak(i,t,aR(e.baseReq.flags),q(i));return o.ok?(n=e.scope,n&&a_.set(n,{selector:t}),{visible:!0,response:{ok:!0,data:{selector:t,matches:o.matches,nodeIndex:o.node.index,nodeType:o.node.type,nodeLabel:o.node.label,nodeIdentifier:o.node.identifier,rect:o.rect}}}):{visible:!1,response:aN("COMMAND_FAILED",o.message,{selector:t}),infrastructureFailure:!1}}async function aJ(e){let t,r=aW(e.positionals,{command:"assertNotVisible",defaultTimeoutMs:3e3});if(!r.ok)return r.response;let n=Date.now(),a=0;for(;Date.now()-n<=r.timeoutMs;){let i=await az(e,r.selector,"assertNotVisible");if(!i.visible&&i.infrastructureFailure)return i.response;if(i.visible)a=0,t=i.response;else{a+=1;let e=Date.now()-n;if(a>=2||e>=r.timeoutMs)return{ok:!0,data:{pass:!0,selector:r.selector,stableSamples:a,waitedMs:e,timeoutMs:r.timeoutMs}}}await td(250)}return a>0?{ok:!0,data:{pass:!0,selector:r.selector,stableSamples:a,waitedMs:Date.now()-n,timeoutMs:r.timeoutMs}}:aN("COMMAND_FAILED",`Expected not visible but matched: ${r.selector}`,{selector:r.selector,timeoutMs:r.timeoutMs,lastResponse:t})}async function aX(e){let t,r,n=Number(e.positionals[0]??15e3);if(!Number.isFinite(n)||n<0)return aN("INVALID_ARGS","waitForAnimationToEnd timeout must be a number.");let a=Date.now();for(;Date.now()-a<n;){let a=await aM(e),i=function(e,t,r){let n=function(e){if(!e.ok)return null;let t=ax(e.data);return t?JSON.stringify(t.nodes.map(e=>({index:e.index,parentIndex:e.parentIndex,type:e.type,identifier:e.identifier,label:e.label,value:e.value,rect:e.rect?{x:Math.round(e.rect.x),y:Math.round(e.rect.y),width:Math.round(e.rect.width),height:Math.round(e.rect.height)}:void 0}))):null}(e);return e.ok?n?t===n?{done:!0,response:{ok:!0,data:{stable:!0,timeoutMs:r}}}:{done:!1,signature:n}:{done:!0,response:e}:{done:!1}}(a,t,n);if(i.done)return i.response;t=i.signature??t,r=a,await td(250)}return r?.ok===!1?r:{ok:!0,data:{stable:!1,timeoutMs:n}}}let aY=.35,aZ=120,aQ=360,a0=8,a1=120,a2=70,a3=200,a5=168,a6=48;function a8(e,t){return Math.round(Math.min(aQ,Math.max(aZ,"number"==typeof e?e*aY:0,1.5*t)))}async function a9(e){var t,r,n;let[a,i="5000",o="down"]=e.positionals;if(!a)return aN("INVALID_ARGS","scrollUntilVisible requires a selector.");let s=Number(i);if(!Number.isFinite(s)||s<=0)return aN("INVALID_ARGS","scrollUntilVisible timeout must be a positive number.");let l=aL(a),u=Math.max(1,Math.ceil(s/500)),c=null;for(let t=0;t<u;t+=1){let r=await is(e,a,l,Math.min(500,Math.max(1,s-500*t)));if(r.ok)return r;if(c=r,t===u-1)break;let n=await e.invoke({...e.baseReq,command:"scroll",positionals:[o]});if(!n.ok)return n}return t=c,r=a,n=s,t?{ok:!1,error:{...t.error,message:`scrollUntilVisible timed out after ${n}ms for selector: ${r}. Last wait: ${t.error.message}`}}:aN("COMMAND_FAILED",`scrollUntilVisible timed out after ${n}ms for selector: ${r}`)}async function a4(e){let[t,r]=e.positionals,n=Number(t),a=Number(r);if(!Number.isFinite(n)||!Number.isFinite(a))return aN("INVALID_ARGS","tapOn percentage point requires numeric x/y values.");let i=await aM(e);if(!i.ok)return i;let o=ax(i.data);if(!o)return aN("COMMAND_FAILED","Unable to read snapshot data for Maestro percentage point tap.");let s=q(o);if(!s)return aN("COMMAND_FAILED","Unable to resolve screen size for Maestro percentage point tap.");let l=tn(s,n,a);return await e.invoke({...e.baseReq,command:"click",positionals:[String(l.x),String(l.y)]})}async function a7(e){let t=await ie(e);if(t)return t;let r=await ii(e);return r.ok?await ia(e,r,r.durationMs):r.response}async function ie(e){let[t,r,n]=e.positionals;if("direction"===t&&("left"===r||"right"===r))return await e.invoke({...e.baseReq,command:"gesture",positionals:["swipe",r,...n?[n]:[]]})}async function it(e){var t,r,n,a;let i,[o,s]=e.positionals;if(!o)return aN("INVALID_ARGS","tapOn requires a selector.");let l=function(e){if(!e)return{ok:!0,value:null};try{let t=JSON.parse(e);return{ok:!0,value:t}}catch{return{ok:!1,response:aN("INVALID_ARGS","tapOn runtime options must be valid JSON.")}}}(s);if(!l.ok)return l.response;let u=Date.now(),c=(t=e,t.baseReq.flags?.maestro?.optional===!0?3e3:3e4);for(;Date.now()-u<c;){let t=await il(e,o,l.value??{});if(!t.retry)return t.response;i=t.response,await td(250)}return r=e,n=o,a=i,r.baseReq.flags?.maestro?.optional===!0?{ok:!0,data:{skipped:!0,optional:!0,selector:n}}:a??aN("COMMAND_FAILED",`tapOn timed out for selector: ${n}`)}async function ir(e){let[t,r="up",n]=e.positionals;if(!t)return aN("INVALID_ARGS","swipe.label requires a label selector.");let a=await id(e,t,{},"swipe.label",{promoteTapTarget:!1});if(!a.ok)return a.response;let i=function(e,t){let r=tl(e.rect),n=e.frame,a=a8(n?.referenceWidth,e.rect.width),i=a8(n?.referenceHeight,e.rect.height),o=a0,s=n?n.referenceWidth-o:r.x+a,l=n?n.referenceHeight-o:r.y+i;switch(t.toLowerCase()){case"up":return{ok:!0,start:r,end:{x:r.x,y:ta(r.y-i,o,l)}};case"down":return{ok:!0,start:r,end:{x:r.x,y:ta(r.y+i,o,l)}};case"left":return{ok:!0,start:r,end:{x:ta(r.x-a,o,s),y:r.y}};case"right":return{ok:!0,start:r,end:{x:ta(r.x+a,o,s),y:r.y}};default:return{ok:!1,message:"swipe.label direction must be up, down, left, or right."}}}(a.target,r);return i.ok?await ia(e,i,n):aN("INVALID_ARGS",i.message)}async function ia(e,t,r){return await e.invoke({...e.baseReq,command:"swipe",positionals:[String(t.start.x),String(t.start.y),String(t.end.x),String(t.end.y),...r?[r]:[]]})}async function ii(e){var t;let r=((t=e.scope)?aI.get(t):void 0)??await io(e);if(!r)return{ok:!1,response:aN("COMMAND_FAILED","Unable to resolve screen size for Maestro swipe.")};let[n,...a]=e.positionals;return"direction"===n?function(e,t){let[r,n]=e;if(!r)return{ok:!1,response:aN("INVALID_ARGS","Maestro direction swipe requires a direction.")};switch(r){case"up":case"down":var a,i,o;let s;return a=r,i=t,o=n,{ok:!0,start:tc({x:(s=ti({direction:a,amount:.6,referenceWidth:i.referenceWidth,referenceHeight:i.referenceHeight})).x1,y:s.y1},i,8),end:tc({x:s.x2,y:s.y2},i,8),durationMs:o};default:return{ok:!1,response:aN("INVALID_ARGS","Maestro swipe direction must be UP, DOWN, LEFT, or RIGHT.")}}}(a,r):"percent"===n?function(e,t,r){var n,a,i,o,s;let[l,u,c,d,p]=e,f=[l,u,c,d].map(Number);if(f.some(e=>!Number.isFinite(e)))return{ok:!1,response:aN("INVALID_ARGS","Maestro percentage swipe requires numeric points.")};let[m,h,g,w]=f,y=(n=r,a=m,i=h,o=g,s=w,"android"!==n||i!==s||50!==i||30>Math.abs(o-a)?{startY:i,endY:s}:{startY:65,endY:65});return{ok:!0,start:tn(t,m,y.startY,{marginPx:1}),end:tn(t,g,y.endY,{marginPx:1}),durationMs:p}}(a,r,aR(e.baseReq.flags)):{ok:!1,response:aN("INVALID_ARGS","Maestro screen swipe requires direction or percent.")}}async function io(e){let t=await aM(e);if(t.ok)return q(ax(t.data))}async function is(e,t,r,n){let a=await e.invoke({...e.baseReq,command:"wait",positionals:[t,String(n)]});return a.ok||!r?a:await e.invoke({...e.baseReq,command:"find",positionals:[r,"wait",String(n)]})}async function il(e,t,r){let n=aL(t),a=await iu(e,t,r);return a.response.ok?{retry:!1,response:a.response}:a.targetResolved&&n?await ic(e,n):{retry:!0,response:a.response}}async function iu(e,t,r){var n,a,i;let o=await id(e,t,r,"tapOn",{promoteTapTarget:!0});if(!o.ok)return{response:o.response,targetResolved:!1};let s=(n=o.target,a=null!==aL(t),!function(e,t,r){if(!t||r.width<a1)return!1;let n=tt(e.type??"");return!(r.height<a2)&&!(r.height>a3)&&("cell"===n||"other"===n||"scrollview"===n||"scroll-area"===n)}(n.node,a,n.rect)?tl(n.rect):{x:to(n.rect.x,Math.min(n.rect.width,a5)),y:to(n.rect.y,Math.min(n.rect.height,a6))});eZ({level:"debug",phase:"maestro_tap_target",data:{selector:t,node:{index:o.target.node.index,type:o.target.node.type,label:o.target.node.label,value:o.target.node.value,identifier:o.target.node.identifier,visibleToUser:o.target.node.visibleToUser},rect:o.target.rect,point:s}});let l=await e.invoke({...e.baseReq,command:"click",positionals:[String(s.x),String(s.y)]});return l.ok&&(i=e.scope)&&a_.delete(i),{response:l,targetResolved:!0}}async function ic(e,t){let r=await e.invoke({...e.baseReq,command:"find",positionals:[t,"click"],flags:{...e.baseReq.flags,findFirst:!0}});return r.ok?{retry:!1,response:r}:{retry:!0,response:r}}async function id(e,t,r,n,a){let i=await aM(e);if(!i.ok)return{ok:!1,response:i};let o=ax(i.data);if(!o)return{ok:!1,response:aN("COMMAND_FAILED",`Unable to read snapshot data for ${n}.`)};let s=q(o),l=aR(e.baseReq.flags),u=function(e,t,r,n){var a;let i=(a=e.scope)?a_.get(a):void 0;if(!i)return;let o=ak(t,i.selector,r,n);if(o.ok)return eZ({level:"debug",phase:"maestro_preferred_context",data:{selector:i.selector,node:{index:o.node.index,type:o.node.type,label:o.node.label,value:o.node.value,identifier:o.node.identifier},rect:o.rect}}),{node:o.node,rect:o.rect}}(e,o,l,s),c=function(e,t,r,n,a,i={}){let o=a$(e,t,n);if(r.childOf){let t=a$(e,r.childOf,n);if(0===t.length)return{ok:!1,message:`Maestro childOf parent did not match: ${r.childOf}`};let a=e7(e.nodes);o=o.filter(r=>t.some(t=>e3(e.nodes,r,t,a)))}let s=aO({nodes:e.nodes,matches:o,platform:n}),l=aC(e.nodes,s.matches,r.index,aL(t),a,!1,i.promoteTapTarget,i.preferredContext);if(!l){let e=r.index??0;return{ok:!1,message:s.blockedByReactNativeOverlay?`Maestro selector matched ${o.length} element(s), but React Native overlay is covering app content: ${t}`:o.length>0&&0===s.matches.length?`Maestro selector matched ${o.length} element(s), but none were visible: ${t}`:`Maestro selector did not match index ${e}: ${t}`}}return{ok:!0,node:l.node,rect:l.rect}}(o,t,r,l,s,{...a,preferredContext:u});if(!c.ok){let e=aL(t);if(e){let t=function(e,t,r,n,a={}){let i=function(e,t){let r=tr(t);if(!r)return[];let n=[],a=[];for(let t of e.nodes){let e=[t.label,e1(t),t.identifier,t.value].filter(e=>!!e).map(e=>tr(e));e.some(e=>e===r)?n.push(t):e.some(e=>e.includes(r))&&a.push(t)}return n.length>0?n:a}(e,t),o=aO({nodes:e.nodes,matches:i,platform:r}),s=aC(e.nodes,o.matches,void 0,t,n,!1,a.promoteTapTarget,a.preferredContext);return s?{ok:!0,node:s.node,rect:s.rect}:{ok:!1,message:`Maestro fuzzy text did not match: ${t}`}}(o,e,l,s,{...a,preferredContext:u});if(t.ok)return{ok:!0,target:{node:t.node,rect:t.rect,frame:s}}}}return c.ok?{ok:!0,target:{node:c.node,rect:c.rect,frame:s}}:{ok:!1,response:aN("ELEMENT_NOT_FOUND",c.message,{selector:t,options:r,command:n})}}async function ip(e){switch(e.command){case nX:return await aB(e);case nY:return await aJ(e);case nZ:return await im(e);case nQ:return await aX(e);case n0:return await a9(e);case n1:return await a7(e);case n2:return await ir(e);case n3:return await it(e);case n5:return await a4(e);case nJ:return function(e){let[r]=e.positionals;if(!r)return aN("INVALID_ARGS","runScript requires a file path.");try{let n=function(e){let{scriptPath:r,env:n}=e,a=t.readFileSync(r,"utf8"),i=Object.create(null);try{var o,s;l.runInNewContext(a,(o=n,s=i,{...o,output:s,json:ac,http:{post:(e,t)=>(function(e,t,r){let n=eQ(process.execPath,["-e",au],{stdin:JSON.stringify({method:e,url:t,headers:r?.headers??{},body:r?.body??""}),timeoutMs:3e4,allowFailure:!0});if(0!==n.exitCode){let r;throw new d("COMMAND_FAILED",`Maestro runScript http.${e.toLowerCase()} failed for ${t}: ${(r=n.stderr.trim()).length>0?r.slice(0,1e3):"request process exited without stderr"}`,{exitCode:n.exitCode,stderr:n.stderr})}try{return JSON.parse(n.stdout)}catch(r){throw new d("COMMAND_FAILED",`Maestro runScript http.${e.toLowerCase()} returned invalid JSON for ${t}`,{stdout:n.stdout.slice(0,1e3),stderr:n.stderr.slice(0,1e3)},r instanceof Error?r:void 0)}})("POST",e,t)}}),{filename:r,timeout:3e4})}catch(e){throw new d("COMMAND_FAILED",`Maestro runScript failed for ${r}: ${e instanceof Error?e.message:String(e)}`,{scriptPath:r},e instanceof Error?e:void 0)}return function(e,t){for(let r of Object.keys(e))if(r.includes("."))throw new d("INVALID_ARGS",`Maestro runScript output key cannot contain ".": ${r}`,{scriptPath:t,key:r})}(i,r),Object.fromEntries(Object.entries(i).map(([e,t])=>{var r;return[`output.${e}`,(r=t,"string"==typeof r?r:"number"==typeof r||"boolean"==typeof r?String(r):JSON.stringify(r))]}))}({scriptPath:r,env:{...e.scope.values,...e.baseReq.flags?.maestro?.runScriptEnv??{}}});return{ok:!0,data:{outputEnv:n}}}catch(t){let e=u(t);return aN(e.code,e.message,e.details)}}(e);default:return}}async function im(e){let t=await e.invoke({...e.baseReq,command:"keyboard",positionals:["enter"]});return t.ok?t:await e.invoke({...e.baseReq,command:"type",positionals:["\n"]})}async function ih(e){for(let[t,r]of e.actions.entries()){let n=await e.invokeReplayAction({action:r,line:e.line,step:e.step+t/1e3});if(!n.ok)return n}return{ok:!0,data:{ran:e.actions.length}}}async function ig(e){let t;for(let r=0;r<=e.maxRetries;r+=1){let n=await ih({actions:e.actions,line:e.line,step:e.step+r,invokeReplayAction:e.invokeReplayAction});if(n.ok)return{ok:!0,data:{attempts:r+1,retried:r>0}};t=n}return t??{ok:!1,error:{code:"COMMAND_FAILED",message:"retry commands failed."}}}async function iw(e){let t=await iy(e,e.control);return t.ok?t.matched?await ib(e):{ok:!0,data:{skipped:!0,condition:e.control.mode,selector:e.control.selector}}:t.response}async function iy(e,t){if("visible"===t.mode)return await iv(e,t);let r=await aM(e);if(!r.ok)return{ok:!1,response:r};let n=iA(e,t.selector,r);return n.ok?{ok:!0,matched:!n.matched}:{ok:!1,response:n.response}}async function iv(e,t){let r=Date.now();for(;;){let n=await aM(e);if(!n.ok)return{ok:!1,response:n};let a=iA(e,t.selector,n);if(!a.ok)return{ok:!1,response:a.response};if(a.matched)return{ok:!0,matched:!0};if(Date.now()-r>=3e3)return{ok:!0,matched:!1};await td(250)}}function iA(e,t,r){let n=ax(r.data);return n?{ok:!0,matched:ak(n,t,aR(e.baseReq.flags),q(n)).ok}:{ok:!1,response:aN("COMMAND_FAILED","Unable to read snapshot data for runFlow.when.")}}async function ib(e){let t=await ih({actions:e.control.actions,line:e.line,step:e.step,invokeReplayAction:e.invokeReplayAction});return t.ok?{ok:!0,data:{ran:t.data?.ran,condition:e.control.mode,selector:e.control.selector}}:t}async function iS(e){var t;let{req:r,sessionName:n,action:a,scope:i,filePath:o,line:s,step:l,tracePath:u,invoke:c}=e,d=(t={file:o,line:s},{...a,positionals:(a.positionals??[]).map(e=>nf(e,i,t)),flags:nm(a.flags,i,t)??{},runtime:nm(a.runtime,i,t),replayControl:function(e,t,r){if(!e)return e;if(e.kind==="maestroRunFlowWhen"){return{...e,selector:nf(e.selector,t,r)}}return e}(a.replayControl,i,t)}),p=Date.now();iN(u,{type:"replay_action_start",ts:new Date(p).toISOString(),replayPath:o,line:s,step:l,command:d.command,positionals:d.positionals??[]});let f=await iI({req:r,sessionName:n,resolved:d,scope:i,line:s,step:l,invoke:c,invokeReplayAction:e=>iS({req:r,sessionName:n,action:e.action,scope:i,filePath:o,line:e.line,step:e.step,tracePath:u,invoke:c})}),m=Date.now();return iN(u,{type:"replay_action_stop",ts:new Date(m).toISOString(),replayPath:o,line:s,step:l,command:d.command,ok:f.ok,durationMs:m-p,resultTiming:f.ok?function(e){if(!e||"object"!=typeof e||Array.isArray(e))return;let t=e.timing;if(!(!t||"object"!=typeof t||Array.isArray(t)))return Object.fromEntries(Object.entries(t).filter(([,e])=>{let t=typeof e;return"number"===t||"string"===t||"boolean"===t}))}(f.data):void 0,errorCode:f.ok?void 0:f.error.code}),f}async function iI(e){var t;let{req:r,sessionName:n,resolved:a,scope:i,line:o,step:s,invoke:l,invokeReplayAction:u}=e,c=(t=r.flags,eW(t,{...a.flags??{}})),d={token:r.token,session:n,flags:c,runtime:a.runtime,meta:r.meta},p=await i_({control:a.replayControl,baseReq:d,line:o,step:s,invoke:l,invokeReplayAction:u})??await ip({command:a.command,baseReq:d,positionals:a.positionals??[],scope:i,line:o,step:s,invoke:l,invokeReplayAction:u})??await l({...d,command:a.command,positionals:a.positionals??[]});if(p.ok){let e=function(e){if(!e||"object"!=typeof e)return null;let t=e.outputEnv;if(!t||"object"!=typeof t||Array.isArray(t))return null;let r=Object.entries(t).filter(e=>"string"==typeof e[1]);return r.length>0?Object.fromEntries(r):null}(p.data);e&&Object.assign(i.values,e)}return p}async function i_(e){let{control:t,baseReq:r,line:n,step:a,invoke:i,invokeReplayAction:o}=e;if(t){switch(t.kind){case"retry":return await ig({actions:t.actions,maxRetries:t.maxRetries,line:n,step:a,invokeReplayAction:o});case"maestroRunFlowWhen":return await iw({baseReq:r,control:t,line:n,step:a,invoke:i,invokeReplayAction:o})}return t}}function iN(e,r){e&&t.appendFileSync(e,`${JSON.stringify(r)}
28
+ `)}async function iM(e){let{req:r,sessionName:n,logPath:i,sessionStore:o,tracePath:s,invoke:l}=e,c=r.positionals?.[0];if(!c)return R("INVALID_ARGS","replay requires a path");let p="",f=new Set;try{var m,h;p=Q.expandHome(c,r.meta?.cwd);let e=t.readFileSync(p,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return R("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let g=function(e,t,r={}){var n;let a=function(e){let t=e?.replayBackend;if("string"!=typeof t)return;let r=ay[t];if(!r)throw new d("INVALID_ARGS",`Unsupported replay backend "${t}".`);return r}(t);return a?{...a.parse(e,{...r,platform:t?.platform,env:(n=t,{...nu(np(n?.replayShellEnv)),...nc(nd(n?.replayEnv))})}),updateUnsupportedMessage:"replay -u is not supported for compat flow input. Convert to .ad first, then update that replay file."}:{...function(e){let t=[],r=[],n=e.split(/\r?\n/),a=!1;for(let[e,i]of n.entries()){let n=i.trim();if(0===n.length||n.startsWith("#"))continue;if(ny(n)){if(a)throw new d("INVALID_ARGS",`env directives must precede all actions (line ${e+1}).`);continue}let o=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let[r,...n]=function(e){let t=[],r=0;for(;r<e.length&&!((r=function(e,t){let r=t;for(;r<e.length&&/\s/.test(e.charAt(r));)r+=1;return r}(e,r))>=e.length);){let n='"'===e[r]?function(e,t){let r=!1,n=t+1;for(;n<e.length;n+=1){let t=e.charAt(n);if('"'===t&&!r)break;if(r){r=!1;continue}r="\\"===t}if(n>=e.length)throw new d("INVALID_ARGS",`Invalid replay script line: ${e}`);return{value:JSON.parse(e.slice(t,n+1)),nextCursor:n+1}}(e,r):function(e,t){let r=t;for(;r<e.length&&!/\s/.test(e.charAt(r));)r+=1;return{value:e.slice(t,r),nextCursor:r}}(e,r);t.push(n.value),r=n.nextCursor}return t}(t);if(void 0===r||"context"===r)return null;let a={ts:Date.now(),command:r,positionals:[],flags:{}};if("snapshot"===r){a.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("-i"===t){a.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){a.flags.snapshotCompact=!0;continue}if("--raw"===t){a.flags.snapshotRaw=!0;continue}if("--force-full"===t){a.flags.snapshotForceFull=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<n.length){let t=Number(n[e+1]);Number.isFinite(t)&&t>=0&&(a.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<n.length){a.flags.snapshotScope=n[e+1],e+=1;continue}if("--backend"===t&&e+1<n.length){e+=1;continue}}return a}if("open"===r){let e=$(n);return a.positionals=e.positionals,Object.assign(a.flags,e.flags),a.runtime=e.runtime,a}if("runtime"===r){let e=G(n);return a.positionals=e.positionals,Object.assign(a.flags,e.flags),a}if(M(r)){let e=eh(r,n);Object.assign(a.flags,e.flags);let t=e.positionals[0];if(void 0===t)return a;if(t.startsWith("@"))return a.positionals=[t],e.positionals[1]&&(a.result={refLabel:e.positionals[1]}),a;let i=e.positionals[0],o=e.positionals[1];return nA(i)&&nA(o)&&e.positionals.length>=2?a.positionals=[i,o]:a.positionals=[e.positionals.join(" ")],a}if("fill"===r){let e=eh(r,n);if(Object.assign(a.flags,e.flags),!(e.positionals.length>=2))return a.positionals=e.positionals,a;let[t,i,...o]=e.positionals;return t.startsWith("@")?(o.length>0?(a.positionals=[t,o.join(" ")],a.result={refLabel:i}):a.positionals=[t,i],a):(a.positionals=[t,[i,...o].join(" ")],a)}if("get"===r){let e=n[0],t=n[1];return void 0===e||void 0===t?a.positionals=n:t.startsWith("@")?(a.positionals=[e,t],n[2]&&(a.result={refLabel:n[2]})):a.positionals=[e,n.slice(1).join(" ")],a}if("swipe"===r||"type"===r){let e=eh(r,n);return Object.assign(a.flags,e.flags),a.positionals=e.positionals,a}if("record"===r){let e=[];for(let t=0;t<n.length;t+=1){let r=n[t];if("--hide-touches"===r){a.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<n.length){let e=Number(n[t+1]);Number.isFinite(e)&&(a.flags.fps=Math.floor(e)),t+=1;continue}if("--quality"===r&&t+1<n.length){let e=Number(n[t+1]);Number.isFinite(e)&&(a.flags.quality=Math.floor(e)),t+=1;continue}e.push(r)}return a.positionals=e,a}if("screenshot"===r){let e=[];for(let t=0;t<n.length;t+=1){let r=n[t],i=eY({args:n,index:t,flags:a.flags});if(i.handled){t=i.nextIndex;continue}e.push(r)}return a.positionals=e,a}return a.positionals=n,a}(i);o&&(t.push(o),r.push(e+1),a=!0)}return{actions:t,actionLines:r}}(e),metadata:nw(e)}}(e,r.flags,{sourcePath:p}),w=g.metadata,y=w.platform||w.target?{...r,flags:(m=r.flags,h=w,{...m??{},...void 0!==h.platform&&m?.platform===void 0?{platform:h.platform}:{},...void 0!==h.target&&m?.target===void 0?{target:h.target}:{}})}:r,v=g.actions,A=g.actionLines;if(r.flags?.replayUpdate===!0&&g.updateUnsupportedMessage)return R("INVALID_ARGS",g.updateUnsupportedMessage);if(r.flags?.replayUpdate===!0&&w.env&&Object.keys(w.env).length>0)return R("INVALID_ARGS","replay -u does not yet preserve env directives. Temporarily remove the env lines, run replay -u, then restore them.");if(r.flags?.replayUpdate===!0&&function(e){for(let t of e){for(let e of t.positionals??[])if("string"==typeof e&&e.includes("${"))return!0;if(ik(t.flags)||ik(t.runtime))return!0}return!1}(v))return R("INVALID_ARGS","replay -u does not yet preserve ${VAR} substitutions. Resolve or inline the variables before running with -u.");let S=function(e){let t={};if(e.builtins)for(let[r,n]of Object.entries(e.builtins))t[r]=n;for(let r of[e.fileEnv,e.shellEnv,e.cliEnv])if(r)for(let[e,n]of Object.entries(r)){if(ns(e))throw nl(e);t[e]=n}return{values:t}}({builtins:function(e){let{req:t,sessionName:r,metadata:n,resolvedPath:i}=e,o=t.flags??{},s=t.meta?.cwd??process.cwd(),l={AD_SESSION:r,AD_FILENAME:a.relative(s,i)||i},u=o.platform??n.platform;u&&(l.AD_PLATFORM=u);let c=o.target??n.target;c&&(l.AD_TARGET=c);let d=o.device;"string"==typeof d&&d.length>0&&(l.AD_DEVICE=d);let p=o.artifactsDir;return"string"==typeof p&&p.length>0&&(l.AD_ARTIFACTS=p),l}({req:y,sessionName:n,metadata:w,resolvedPath:p}),fileEnv:w.env,shellEnv:nu(np(r.flags?.replayShellEnv)),cliEnv:nc(nd(r.flags?.replayEnv))}),I=r.flags?.replayUpdate===!0,_=s??o.get(n)?.trace?.outPath,N=0;for(let e=0;e<v.length;e+=1){let t=v[e];if(!t||"replay"===t.command)continue;let r=await iS({req:y,sessionName:n,action:t,scope:S,filePath:p,line:A[e]??0,step:e+1,tracePath:_,invoke:l});if(r.ok){iD(r).forEach(e=>f.add(e));continue}if(!I)return ix(r,t,e,p,[...f]);let a=await aA({action:t,sessionName:n,logPath:i,sessionStore:o});if(!a)return ix(r,t,e,p,[...f]);if(v[e]=a,!(r=await iS({req:y,sessionName:n,action:a,scope:S,filePath:p,line:A[e]??0,step:e+1,tracePath:_,invoke:l})).ok)return ix(r,a,e,p,[...f]);iD(r).forEach(e=>f.add(e)),N+=1}return I&&N>0&&function(e,r,n){let a=[];if(n){let e=n.device.kind?` kind=${n.device.kind}`:"",t=n.device.target?` target=${n.device.target}`:"";a.push(`context platform=${n.device.platform}${t} device=${ee(n.device.name)}${e} theme=unknown`)}for(let e of r){var i;a.push((i=e,b(i,{runtimeIncludeAllPositionals:!0})))}let o=`${a.join("\n")}
29
+ `,s=`${e}.tmp-${process.pid}-${Date.now()}`;t.writeFileSync(s,o),t.renameSync(s,e)}(p,v,o.get(n)),{ok:!0,data:{replayed:v.length,healed:N,session:n,artifactPaths:[...f]}}}catch(t){let e=u(t);return R(e.code,e.message,f.size>0?{artifactPaths:[...f]}:void 0)}}function ix(e,t,r,n,a=[]){if(e.ok)return e;let i=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${i} (${et(t)}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:n,step:i,action:t.command,positionals:t.positionals??[],artifactPaths:a}}}}function iD(e){if(!e.ok||!e.data)return[];let r=[];if("string"==typeof e.data.path&&r.push(e.data.path),"string"==typeof e.data.outPath&&r.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let t of e.data.artifacts){if(!t||"object"!=typeof t)continue;let e="string"==typeof t.localPath?t.localPath:void 0,n="string"==typeof t.path?t.path:void 0;e?r.push(e):n&&r.push(n)}return[...new Set(r.filter(e=>(function(e){try{return t.statSync(e).isFile()}catch{return!1}})(e)))]}function ik(e){return"string"==typeof e?e.includes("${"):Array.isArray(e)?e.some(ik):!!e&&"object"==typeof e&&Object.values(e).some(ik)}async function iO(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e;return"replay"===t.command?await iM({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}):"test"===t.command?await nk({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,target:s,requestId:l,artifactsDir:u,artifactPaths:c,tracePath:d})=>{let p=function(e){let{parentFlags:t,platform:r,target:n,artifactsDir:a}=e;return void 0===r&&void 0===n&&void 0===a?t:{...t??{},...void 0!==r?{platform:r}:{},...void 0!==n?{target:n}:{},...void 0!==a?{artifactsDir:a}:{}}}({parentFlags:t.flags,platform:o,target:s,artifactsDir:u});return await iM({req:{...t,command:"replay",session:r,positionals:[e],flags:p,meta:l?{...t.meta??{},requestId:l}:t.meta},sessionName:r,logPath:n,sessionStore:a,tracePath:d,invoke:async e=>{var t;return t=await i(e),c&&iD(t).forEach(e=>c.add(e)),t}})},cleanupSession:async e=>{a.get(e)&&await H({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:n,sessionStore:a})}}):null}let iR=tf.inventory,iL=tf.state,i$=tf.observability,iP=tf.replay,iF={...Object.fromEntries([...iR].map(e=>[e,!0])),...Object.fromEntries([...iL].map(e=>[e,!0])),...Object.fromEntries([...i$].map(e=>[e,!0])),...Object.fromEntries([...iP].map(e=>[e,!0])),[tp.runtime]:!0,[tm.clipboard]:!0,[tm.keyboard]:!0,[tm.install]:!0,[tm.reinstall]:!0,[tp.installSource]:!0,[tp.releaseMaterializedPaths]:!0,[tm.push]:!0,[tm.triggerAppEvent]:!0,[tm.open]:!0,[tm.batch]:!0,[tm.close]:!0};async function iC(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,command:i,positionals:o,recordPositionals:s,deriveNextSession:l}=e,u=a.get(r),c=t.flags??{},d=I(i,u,c);if(d)return d;let p=await w({session:u,flags:c,ensureReady:!0});if(!eA(i,p))return R("UNSUPPORTED_OPERATION",`${i} is not supported on this device`);let f=await m(p,i,o,t.flags?.out,{...Y(n,t.flags,u?.appBundleId,u?.trace?.outPath)});if(u){let e=l?await l(u,f,p):u;a.recordAction(e,{command:i,positionals:s??o,flags:t.flags??{},result:f??{}}),e!==u&&a.set(r,e)}return{ok:!0,data:f??{}}}async function iE(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,i=a.get(r),o=t.flags??{},s=I(tm.clipboard,i,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return R("INVALID_ARGS","clipboard requires a subcommand: read or write");let u=await w({session:i,flags:o,ensureReady:!0});if(!eA(tm.clipboard,u))return R("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let c=await m(u,tm.clipboard,t.positionals??[],t.flags?.out,{...Y(n,t.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:c??{}}),{ok:!0,data:{platform:u.platform,...c??{}}}}async function iV(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i,invokeReplayAction:o,androidAdbExecutor:s}=e;if(iR.has(t.command))return await ri({req:t,sessionName:r,sessionStore:a});if("runtime"===t.command)return await tD({req:t,sessionName:r,sessionStore:a});if(iL.has(t.command))return await rc({req:t,sessionName:r,sessionStore:a});if(t.command===tm.clipboard)return await iE({req:t,sessionName:r,logPath:n,sessionStore:a});if(t.command===tm.keyboard){let e=a.get(r),i=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==i&&"enter"!==i&&"return"!==i||"ios"!==eI((t.flags??{}).platform)?await iC({req:t,sessionName:r,logPath:n,sessionStore:a,command:tm.keyboard,positionals:t.positionals??[]}):R("SESSION_NOT_FOUND","iOS keyboard action requires an active session so the target app stays foregrounded. Run open first.")}if(i$.has(t.command))return await r8({req:t,sessionName:r,sessionStore:a,androidAdbExecutor:s});if(t.command===tm.install||t.command===tm.reinstall)return await rn({req:t,command:t.command,sessionName:r,sessionStore:a,deployOps:t.command===tm.install?rr:rt});if(t.command===tp.installSource)return await tA({req:t,sessionName:r,sessionStore:a});if(t.command===tp.releaseMaterializedPaths)return await tb({req:t});if(t.command===tm.push){let e,i=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return i&&o?await iC({req:t,sessionName:r,logPath:n,sessionStore:a,command:tm.push,positionals:[i,"file"===(e=eo(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>Q.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[i,o]}):R("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return t.command===tm.triggerAppEvent?await iC({req:t,sessionName:r,logPath:n,sessionStore:a,command:tm.triggerAppEvent,positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,n=r?await t0(e.device,r,e.appBundleId,tZ)??e.appBundleId:e.appBundleId;return{...e,appBundleId:n}}}):t.command===tm.open?await re({req:t,sessionName:r,logPath:n,sessionStore:a}):iP.has(t.command)?await iO({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:o??i}):t.command===tm.batch?await ra(t,r,i):t.command===tm.close?await H({req:t,sessionName:r,logPath:n,sessionStore:a}):null}export{tg as session_namespaceObject};
@@ -0,0 +1,2 @@
1
+ import{__webpack_require__ as e}from"./rslib-runtime.js";import{promises as t}from"node:fs";import n from"node:os";import a from"node:path";import{centerOfRect as s}from"./4057.js";import{normalizeError as o,AppError as r}from"./9152.js";import{withDiagnosticTimer as i,emitDiagnostic as l}from"./7599.js";import{pressAndroid as d,backAndroid as p}from"./input-actions.js";import{createDaemonRuntimeSessionStore as u,captureSnapshot as c,dispatchCommand as f,resolveSnapshotScope as m,runMacOsAlertAction as h,errorResponse as w,runIosRunnerCommand as _,isCommandSupportedOnDevice as g,snapshotAndroid as y,annotateScreenshotWithRefs as v,context_contextFromFlags as S}from"./2415.js";import{successText as b}from"./1998.js";import{sleep as I}from"./4829.js";import{buildSnapshotSession as A,dispatchWaitViaRuntime as C,createDaemonRuntimePolicy as R,recordIfSession as N,resolveSessionDevice as M,withSessionlessRunnerCleanup as P}from"./selector-runtime.js";import{parseTimeout as D}from"./6085.js";import{SETTINGS_INVALID_ARGS_MESSAGE as k,isMacOsSettingSupported as E,getUnsupportedMacOsSettingMessage as K}from"./1352.js";import{createAgentDevice as O}from"./9533.js";import{DAEMON_COMMAND_GROUPS as U}from"./5792.js";var x={};e.r(x),e.d(x,{SNAPSHOT_COMMAND_HANDLERS:()=>eh,handleSnapshotCommands:()=>ew});let H=new Set(["com.android.permissioncontroller","com.google.android.permissioncontroller","com.google.android.packageinstaller","com.android.packageinstaller"]),L=new Set(["android","com.android.systemui"]),$=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,T=/^android:id\/button[123]$/i,B=/(?:^|:)id\/permission_/i,q=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,F=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,j=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function z(e,t){let n=t[0];if(!n)return;let a=W(e,n.index);for(let n of t.slice(1)){let t=new Set(W(e,n.index));for(let e=a.length-1;e>=0;e-=1)t.has(a[e])||a.splice(e,1)}return a[a.length-1]}function W(e,t){let n=new Map(e.map(e=>[e.index,e])),a=[],s=n.get(t);for(;s;)a.push(s.index),s=void 0===s.parentIndex?void 0:n.get(s.parentIndex);return a.reverse()}function G(e,t){let n=new Map;for(let t of e){if(void 0===t.parentIndex)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let a=new Set([t]),s=[t];for(let e of s)for(let t of n.get(e)??[])a.has(t.index)||(a.add(t.index),s.push(t.index));return e.filter(e=>a.has(e.index))}function V(e){let t=e.type??"",n=e.identifier??"";return!!(e.hittable||/\bbutton\b/i.test(t)||T.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function J(e){if(!e)return"";let t=[e.label,e.value].filter(e=>"string"==typeof e&&e.trim().length>0);return t[0]?.trim()??""}async function Q(e,t,n={}){if("wait"===t)return await X(e,n.timeoutMs??1e4);if("get"===t){var a;let t=await ee(e);return{kind:"alertStatus",platform:"android",action:"get",alert:a=t?.alert??null,...a?b("Alert visible"):b("No alert visible")}}return await Y(e,t)}async function X(e,t){let n=Date.now(),a=await Z(e,t);if(!a)throw new r("COMMAND_FAILED","alert wait timed out");return{kind:"alertWait",platform:"android",action:"wait",alert:a.alert,waitedMs:Date.now()-n,...b("Alert visible")}}async function Y(e,t){var n;let a,s,o=await Z(e,2e3);if(!o)throw new r("COMMAND_FAILED","alert not found",{hint:"If a sheet is visible in snapshot but alert reports no alert, it is likely app-owned UI. Use snapshot -i and press the visible label/ref."});let i=(n=o.buttons,a="accept"===t?"accept":"dismiss",(s=n.find(e=>e.role===a))||("dismiss"===t?n.find(e=>"neutral"===e.role)??null:1===n.length?n[0]??null:null));if(i)return await d(e,i.x,i.y),et(t,o.alert,i.label);if("dismiss"===t)return await p(e),et(t,o.alert,"Back");throw new r("COMMAND_FAILED","alert accept found an alert but no accept button",{alert:o.alert,hint:"Inspect alert get --json for visible buttons, then use press by visible label/ref if needed."})}async function Z(e,t){let n=Date.now();for(;Date.now()-n<t;){let t=await ee(e);if(t)return t;await I(300)}return null}async function ee(e){return function(e){var t,n,a,o;let r,i=function(e){let t=e.filter(e=>{var t;let n;return n=(t=e).bundleId??"",H.has(n)||B.test(t.identifier??"")});if(t.length)return{nodes:t,source:"permission"};let n=function(e){let t=e.filter(e=>{var t;let n;return n=(t=e).bundleId??"",L.has(n)&&q.test(J(t))});if(0===t.length)return[];let n=z(e,t);return void 0===n?t:G(e,n).filter(e=>e.bundleId&&L.has(e.bundleId))}(e);return n.length?{nodes:n,source:"system-dialog"}:{nodes:function(e){var t;let n,a,s=e.filter(e=>{var t;return t=e.type??"",/(?:^|[.$])[^.]*Dialog$/i.test(t)}),o=e.filter(e=>$.test(e.identifier??"")),r=s.length?[...s,...o]:(n=(t=o).some(e=>T.test(e.identifier??"")),a=t.some(e=>!T.test(e.identifier??"")),n&&a?t:[]);if(0===r.length)return[];let i=z(e,r);return void 0===i?r:G(e,i)}(e),source:"native-dialog"}}(e),l=i.nodes;if(0===l.length)return null;let d=function(e){let t=new Set,n=[];for(let a of e){let e=J(a);if(!e||!a.rect||!V(a))continue;let o=e.trim().toLowerCase();if(!o||t.has(o))continue;t.add(o);let r=s(a.rect);n.push({label:e,x:r.x,y:r.y,role:function(e,t){var n;let a=(n=e.identifier??"",/(?:^|:)id\/button1$/i.test(n)?"accept":/(?:^|:)id\/button2$/i.test(n)?"dismiss":/(?:^|:)id\/button3$/i.test(n)?"neutral":/(?:^|:)id\/permission_allow/i.test(n)?"accept":/(?:^|:)id\/permission_deny/i.test(n)?"dismiss":null);return a||(F.test(t.trim())?"accept":j.test(t.trim())?"dismiss":"neutral")}(a,e)})}return n}(l),p=l.filter(e=>J(e)&&!V(e)),u=J((t=p).find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??"")))||J(t[0]),c=(n=p,a=u,(r=n.map(e=>J(e)).filter(e=>e&&e!==a)).length?[...new Set(r)].join("\n"):void 0),f=(o=l,o.find(e=>e.bundleId)?.bundleId);return{alert:{...u?{title:u}:{},...c?{message:c}:{},buttons:d.map(e=>e.label),platform:"android",source:i.source,...f?{packageName:f}:{}},buttons:d}}((await i("snapshot_capture",async()=>await y(e,{helperWaitForIdleTimeoutMs:0,includeHiddenContentHints:!1}),{backend:"android",purpose:"alert"})).nodes)}function et(e,t,n){return{kind:"alertHandled",platform:"android",action:e,handled:!0,alert:t,button:n,...b(`Alert ${e}ed`)}}async function en(e){var t;let{req:n,logPath:a,session:s,device:o}=e,r="accept"===(t=n.positionals?.[0])||"dismiss"===t||"wait"===t?t:"get",i=s?"frontmost-app"===s.surface?{surface:"frontmost-app"}:{bundleId:s.appBundleId,surface:s.surface}:{};if(!g("alert",o))return w("UNSUPPORTED_OPERATION","alert is not supported on this device");if("android"===o.platform){let t=D(n.positionals?.[1])??1e4;return er(e,await Q(o,r,{timeoutMs:t}))}if("macos"===o.platform){let t=async e=>await h(e,i);return await ea(e,r,t)}let l={verbose:n.flags?.verbose,logPath:a,traceLogPath:s?.trace?.outPath,requestId:n.meta?.requestId},d=async e=>await _(o,{command:"alert",action:e,appBundleId:s?.appBundleId},l);return await ea(e,r,d)}async function ea(e,t,n){if("wait"===t)return await es(e,n);let a="accept"===t||"dismiss"===t?t:"get";return"accept"===a||"dismiss"===a?await eo(e,a,n):er(e,await n("get"))}async function es(e,t){let n=D(e.req.positionals?.[1])??1e4,a=Date.now();for(;Date.now()-a<n;){try{return er(e,await t("get"))}catch{}await I(300)}return w("COMMAND_FAILED","alert wait timed out")}async function eo(e,t,n){var a,s;let o,i,l=Date.now();for(;Date.now()-l<2e3;){try{return er(e,await n(t))}catch(t){i=t;let e=String(t?.message??"").toLowerCase();if(!e.includes("alert not found")&&!e.includes("no alert"))break}await I(300)}throw(a=i)instanceof r&&(s=a,(o=String(s?.message??"").toLowerCase()).includes("alert not found")||o.includes("no alert"))?new r(a.code,a.message,{...a.details??{},hint:"If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref."}):a}function er(e,t){return N(e.sessionStore,e.session,e.req,t),{ok:!0,data:t}}async function ei(e){let{req:t,logPath:n,sessionStore:a,session:s,device:o,parsed:r}=e,{setting:i,state:l,permissionTarget:d,latitude:p,longitude:u}=r;if(!g("settings",o))return w("UNSUPPORTED_OPERATION","settings is not supported on this device");if("macos"===o.platform&&!E(i))return w("INVALID_ARGS",K(i));let c=s?.appBundleId,m="permission"===i?[i,l,d??"",t.positionals?.[3]??"",c??""]:"location"===i&&"set"===l?[i,l,p??"",u??"",c??""]:[i,l,c??""],h=await f(o,"settings",m,t.flags?.out,{...S(n,t.flags,c,s?.trace?.outPath)});return N(a,s,t,h??{setting:i,state:l}),{ok:!0,data:h??{setting:i,state:l}}}async function el(e){var t,n;let a;if("snapshot"!==e.command||"android"!==e.device.platform)return;let s=o(e.error);if("COMMAND_FAILED"===(t=s).code&&(n=t,a=`${n.message}
2
+ ${n.hint??""}`,/Android UI hierarchy dump timed out/i.test(a)||/Stock UIAutomator fallback was skipped/i.test(a)||/Android accessibility snapshots can be blocked/i.test(a)||function(e){if(!e||"object"!=typeof e)return!1;let t=String(e.errorType??""),n=String(e.message??"");return/TimeoutException/i.test(t)||/timed out/i.test(n)}(t.details?.helper)||function(e){var t;if(!e)return!1;let n=e?.timeoutMs,a=e?.cmd,s=Array.isArray(t=e?.args)?t.map(String):"string"==typeof t?t.split(/\s+/):[];return"number"==typeof n&&"adb"===a&&s.includes("uiautomator")&&s.includes("dump")}(t.details)))return{ok:!1,error:{...s,details:{...s.details??{},androidSnapshotTimeoutScreenshot:await ed(e)}}}}async function ed(e){try{var s,r,i;let o=await t.mkdtemp(a.join(n.tmpdir(),"agent-device-android-snapshot-timeout-")),d=a.join(o,"snapshot-timeout-overlay-refs.png"),p=(s=await f(e.device,"screenshot",[d],void 0,{...S(e.logPath,{screenshotNoStabilize:!0},e.session?.appBundleId,e.session?.trace?.outPath),surface:e.session?.surface}),r=d,(i=s,"object"==typeof i&&null!==i&&"path"in i&&"string"==typeof i.path)?s.path:r);await t.access(p);let u=await ep(p,e.session);return l({level:"warn",phase:"android_snapshot_timeout_screenshot_captured",data:{path:p,overlayRefCount:"overlayRefCount"in u?u.overlayRefCount:void 0,overlayRefsAnnotated:"overlayRefsAnnotated"in u?u.overlayRefsAnnotated:void 0}}),u}catch(t){let e=o(t);return l({level:"warn",phase:"android_snapshot_timeout_screenshot_failed",data:{error:e.message}}),{captureFailed:!0,error:e.message}}}async function ep(e,t){if(!t?.snapshot)return{path:e,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:"unavailable",overlayRefCount:0};try{let n=await v({screenshotPath:e,snapshot:t.snapshot});return{path:e,overlayRefsRequested:!0,overlayRefsAnnotated:n.length>0,overlayRefCount:n.length,overlayRefSource:"session-snapshot",overlayRefs:n}}catch(n){let t=o(n);return l({level:"warn",phase:"android_snapshot_timeout_screenshot_overlay_failed",data:{path:e,error:t.message}}),{path:e,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:"session-snapshot",overlayRefCount:0,overlayAnnotationError:t.message}}}async function eu(e){return await ef({...e,command:"snapshot",unsupportedMessage:"snapshot is not supported on this device",execute:async({runtime:e,sessionName:t,req:n,snapshotScope:a})=>{let s=await e.capture.snapshot({session:t,interactiveOnly:n.flags?.snapshotInteractiveOnly,compact:n.flags?.snapshotCompact,depth:n.flags?.snapshotDepth,scope:a,raw:n.flags?.snapshotRaw,forceFull:n.flags?.snapshotForceFull});return{data:s,record:{kind:"snapshot",nodes:s.nodes.length,truncated:s.truncated}}}})}async function ec(e){return await ef({...e,command:"diff",unsupportedMessage:"diff is not supported on this device",execute:async({runtime:e,sessionName:t,req:n,snapshotScope:a})=>{let s=await e.capture.diffSnapshot({session:t,interactiveOnly:n.flags?.snapshotInteractiveOnly,compact:n.flags?.snapshotCompact,depth:n.flags?.snapshotDepth,scope:a,raw:n.flags?.snapshotRaw});return{data:s,record:{kind:"diff",mode:"snapshot",baselineInitialized:s.baselineInitialized,summary:s.summary}}}})}async function ef(e){let{req:t,sessionName:n,logPath:a,sessionStore:s}=e,{session:o,device:i}=await M(s,n,t.flags);if(!g(e.command,i))return w("UNSUPPORTED_OPERATION",e.unsupportedMessage);let l=m(t.flags?.snapshotScope,o);return l.ok?await P(o,i,async()=>{var d,p;let f,m,h=function(e){let{req:t,sessionName:n,logPath:a,sessionStore:s,session:o,device:i,snapshotScope:l}=e;return O({backend:function(e){let{req:t,logPath:n,session:a,device:s,snapshotScope:o}=e;return{platform:s.platform,captureSnapshot:async(e,r)=>{let i=await c({device:s,session:a,flags:t.flags,outPath:r?.outPath??t.flags?.out,logPath:n,snapshotScope:o});return{snapshot:i.snapshot,analysis:i.analysis,androidSnapshot:i.androidSnapshot,freshness:i.freshness,appName:a?.appBundleId?a.appName??a.appBundleId:void 0,appBundleId:a?.appBundleId}}}}({req:t,logPath:a,session:o,device:i,snapshotScope:l}),...R("snapshot"),sessions:u({sessionName:n,getSession:()=>s.get(n),recordOptions:{includeSnapshot:!0},setRecord:e=>{var a;let o=function(e){if(!e.snapshot)throw new r("UNKNOWN","snapshot runtime did not produce session state");return e}(e),l=s.get(n);s.set(n,function(e){var t,n;let{current:a,sessionName:s,device:o,record:r,refScopedSnapshot:i}=e,l=(t=a,n=r,i&&n.snapshot?.nodes.length===0&&t?.snapshot!==void 0),d=l?a.snapshot:r.snapshot,p=A({session:a,sessionName:s,device:o,snapshot:d,appBundleId:r.appBundleId});return p.snapshotScopeSource=function(e){let{current:t,keepCurrentSnapshot:n,refScopedSnapshot:a}=e;if(a)return n?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}({current:a,keepCurrentSnapshot:l,refScopedSnapshot:i}),r.appName&&(p.appName=r.appName),p}({current:l,sessionName:n,device:i,record:o,refScopedSnapshot:(a=t,a.flags?.snapshotScope?.trim().startsWith("@")===!0)}))}})})}({req:t,sessionName:n,logPath:a,sessionStore:s,session:o,device:i,snapshotScope:l.scope});try{m=await e.execute({runtime:h,sessionName:n,req:t,snapshotScope:l.scope})}catch(n){let t=await el({error:n,command:e.command,logPath:a,session:o,device:i});if(!t)throw n;return t}return(f=(d={req:t,sessionName:n,sessionStore:s,result:m.record}).sessionStore.get(d.sessionName))&&d.sessionStore.recordAction(f,{command:d.req.command,positionals:d.req.positionals??[],flags:d.req.flags??{},result:"snapshot"===(p=d.result).kind?{nodes:p.nodes,truncated:p.truncated}:{mode:p.mode,baselineInitialized:p.baselineInitialized,summary:p.summary}}),{ok:!0,data:m.data}}):l}let em=U.snapshot,eh={snapshot:async({req:e,sessionName:t,logPath:n,sessionStore:a})=>await eu({req:e,sessionName:t,logPath:n,sessionStore:a}),diff:async({req:e,sessionName:t,logPath:n,sessionStore:a})=>e.positionals?.[0]!=="snapshot"?w("INVALID_ARGS","diff currently supports only: diff snapshot"):await ec({req:e,sessionName:t,logPath:n,sessionStore:a}),wait:async({req:e,sessionName:t,logPath:n,sessionStore:a})=>await C({req:e,sessionName:t,logPath:n,sessionStore:a}),alert:async({req:e,sessionName:t,logPath:n,sessionStore:a})=>{let{session:s,device:o}=await M(a,t,e.flags);return await P(s,o,async()=>await en({req:e,logPath:n,sessionStore:a,session:s,device:o}))},settings:async({req:e,sessionName:t,logPath:n,sessionStore:a})=>{let s,o,r,i=(s=e.positionals?.[0]?.toLowerCase(),o=e.positionals?.[1]?.toLowerCase(),r=e.positionals?.[2]?.toLowerCase(),s&&o&&("permission"!==s||r)&&("location"!==s||"set"!==o||e.positionals?.[2]&&e.positionals?.[3])?{ok:!0,parsed:{setting:s,state:o,permissionTarget:r,latitude:e.positionals?.[2],longitude:e.positionals?.[3]}}:w("INVALID_ARGS",k));if(!i.ok)return i;let{session:l,device:d}=await M(a,t,e.flags);return await P(l,d,async()=>await ei({req:e,logPath:n,sessionStore:a,session:l,device:d,parsed:i.parsed}))}};async function ew(e){let t=e.req.command;if(!em.has(t))return null;let n=eh[t];return n?await n(e):w("COMMAND_FAILED",`Snapshot command has no handler: ${t}`)}export{x as snapshot_namespaceObject};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-device",
3
- "version": "0.16.4",
3
+ "version": "0.16.6",
4
4
  "description": "Agent-native CLI for AI mobile testing and app automation across iOS, Android, tvOS, Android TV, macOS, and Linux.",
5
5
  "mcpName": "io.github.callstackincubator/agent-device",
6
6
  "license": "MIT",
@@ -96,6 +96,8 @@
96
96
  "build:macos-helper": "swift build -c release --package-path macos-helper",
97
97
  "build:all": "pnpm build:node && pnpm build:xcuitest",
98
98
  "ad": "node bin/agent-device.mjs",
99
+ "size": "node scripts/size-report.mjs",
100
+ "size:markdown": "node scripts/size-report.mjs --json .tmp/size-report.json --markdown .tmp/size-report.md",
99
101
  "lint": "oxlint . --deny-warnings",
100
102
  "format": "oxfmt --write src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
101
103
  "fallow": "fallow --summary",
@@ -104,6 +106,7 @@
104
106
  "check:quick": "pnpm lint && pnpm typecheck",
105
107
  "sync:mcp-metadata": "node scripts/sync-mcp-metadata.mjs",
106
108
  "check:mcp-metadata": "node scripts/sync-mcp-metadata.mjs --check",
109
+ "version": "node scripts/sync-mcp-metadata.mjs && git add server.json",
107
110
  "check:tooling": "pnpm lint && pnpm typecheck && pnpm check:mcp-metadata && pnpm build",
108
111
  "check:unit": "pnpm test:unit && pnpm test:smoke",
109
112
  "check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/callstackincubator/agent-device",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.16.4",
10
+ "version": "0.16.6",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "agent-device",
15
- "version": "0.16.4",
15
+ "version": "0.16.6",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }
@@ -1 +0,0 @@
1
- f390055d51600b183b9b9cb07cbee02dd2966c03682ee389f10823622e9ff714 agent-device-android-multitouch-helper-0.16.4.apk
@@ -1 +0,0 @@
1
- 94f014115f4797937f21786b542dcbf9d310be1e8d90520a33ec6dbe4b88ff0b agent-device-android-snapshot-helper-0.16.4.apk
package/dist/src/1769.js DELETED
@@ -1,7 +0,0 @@
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"./7599.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:"],b=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,v=/([^{}]*\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){let t=e.trim().split(":")[0]?.toLowerCase();return"http"===t||"https"===t}function T(e,t){let a=e?.trim();return a||(k(t)?"com.apple.mobilesafari":void 0)}function E(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=S(e,t),r=n.get(i);if(r)return r.expiresAtMs<=a()?void n.delete(i):r.value},set:(e,i,r)=>(n.set(S(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 S(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 R(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()}),U({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),U(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),U(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),U(o),n)throw n;throw new i("COMMAND_FAILED","retry failed")}async function P(e,t={}){return R(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function U(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 B(e){return F(e)}function V(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function W(e,t=process.env){let a=F(e)??F(t.AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST);if(a)return V(a)}let $=new Set(["IOS_BOOT_TIMEOUT","IOS_RUNNER_CONNECT_TIMEOUT","IOS_TOOL_MISSING","ANDROID_BOOT_TIMEOUT","ADB_TRANSPORT_UNAVAILABLE","CI_RESOURCE_STARVATION_SUSPECTED"]);function G(e){return $.has(e.toUpperCase())}function j(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 K(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 H=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];async function z(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 q(e){return`${e.stdout}
2
- ${e.stderr}`}function Z(e,t){return["-s",e,...t]}function J(e){return e.startsWith("emulator-")}function X(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function Q(e,t=1e4){return o("adb",Z(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function Y(e,t){let a=t.replace(/_/g," ").trim();if(!J(e))return a||e;let n=await et(e);return n?n.replace(/_/g," "):a||e}async function ee(e,t,a){try{return await a("adb",Z(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 et(e,t=o){for(let a of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let n=await ee(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 ee(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 ea(e,t){let a=q(await o("adb",Z(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:1e4})).toLowerCase();return!!a.includes("true")||!a.includes("false")&&null}async function en(e){return(await z(H,2,async t=>await ea(e,t))).some(e=>!0===e)}async function ei(e){var t;let a;return"tv"===((a=q(await o("adb",Z(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:1e4})).toLowerCase()).includes("tv")||a.includes("leanback")?"tv":null)||await en(e)?"tv":(t=q(await o("adb",Z(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 er(e={}){if(await u(),!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??W(void 0),a=(await eo()).filter(e=>!t||t.has(e.serial));return await z(a,3,async({serial:e,rawModel:t})=>{let[a,n,i]=await Promise.all([Y(e,t),eu(e),ei(e)]);return{platform:"android",id:e,name:a,kind:J(e)?"emulator":"device",target:i,booted:n}})}async function eo(){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 es(){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 el(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await ed(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 ed(e,t){let a=X(e);for(let e of(await eo()).filter(e=>(!t||e.serial===t)&&J(e.serial)))if(X(e.rawModel)===a||X(await Y(e.serial,e.rawModel))===a)return e.serial}async function eu(e){try{let t=await Q(e);return"1"===t.stdout.trim()}catch{return!1}}async function ec(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 es(),c=function(e,t){let a=e.find(e=>e===t);if(a)return a;let n=X(t);return e.find(e=>X(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 er(),a=e.serial,n=X(c),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!a||e.id===a)&&X(e.name)===n));if(!f){let t=["-avd",c];e.headless&&t.push("-no-window","-no-audio"),d("emulator",t)}let m=f??await el({avdName:c,serial:e.serial,timeoutMs:o}),w=Math.max(1e3,o-(Date.now()-p));await ep(m.id,w);let h=(await er()).find(e=>e.id===m.id);return h?{...h,name:c,booted:!0}:{...m,name:c,booted:!0}}async function ep(e,t=6e4){let a,r=x.fromTimeoutMs(t),o=Math.max(1,Math.ceil(t/1e3)),s=!1;try{await R(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 Q(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=j({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=>j({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=j({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:K(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 ef(e,t,a){return await h(e)(t,a)}function em(e){return{platform:"android",id:e,name:e,kind:e.startsWith("emulator-")?"emulator":"device",booted:!0}}async function ew(){if(await u(),!await l("adb"))throw new i("TOOL_MISSING","adb not found in PATH")}let eh=/\.(?:apk|aab)$/i,eA=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function ey(e){var t,a;let n=e.trim();return 0===n.length?"other":eh.test(n)?n.includes("/")||n.includes("\\")||n.startsWith(".")||n.startsWith("~")||(t=n,!eA.test(t))?"binary":"package":(a=n,eA.test(a))?"package":"other"}function eg(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}async function eb(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 eM={settings:{type:"intent",value:"android.settings.SETTINGS"}},e_="android.intent.category.LAUNCHER",eI="android.intent.category.LEANBACK_LAUNCHER",eO="android.intent.category.DEFAULT",eN="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.",eC=new Set(["localhost","127.0.0.1","::1","[::1]"]),eD=E();function ek(e){return{platform:"android",deviceId:e.id,variant:e.target??""}}async function eT(e,t){let a=t.trim();if("package"===ey(a))return{type:"package",value:a};let n=eM[a.toLowerCase()];if(n)return n;let r=ek(e),o=eD.get(r,a);if(o)return o;let s=(await ef(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 eD.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:eN})}async function eE(e,t){let a=await eS(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:eR(e)}))}async function eS(e){let t=new Set;for(let a of eL(e,{includeFallbackWhenUnknown:!0})){let n=await ef(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?[eI]:"mobile"===e.target?[e_]:t.includeFallbackWhenUnknown?[e_,eI]:[e_]}async function ex(e){return I((await ef(e,["shell","pm","list","packages","-3"])).stdout)}function eR(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 eP(e){let t=await eF(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let a=await eF(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return a||{}}async function eU(e){return await eB(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]])}async function eF(e,t){for(let a of t){let t=O((await ef(e,a,{allowFailure:!0})).stdout??"");if(t)return t}return null}async function eB(e,t){for(let a of t){let t=N((await ef(e,a,{allowFailure:!0})).stdout??"",(e,t)=>(function(e,t){let a=e.split("}")[0]?.trim()??e.trim(),n=b.exec(a);if(n){let e=n[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=v.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 eV(e,t){let a=function(e){let t;try{t=new URL(e)}catch{return null}let a=t.hostname.toLowerCase();if(!eC.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 eW(e,t,a){var n;e.booted||await ep(e.id);let i="string"==typeof(n=a)?{activity:n}:n??{},r=i.activity,o=t.trim();if(D(o))return void await e$(e,o,i);if(void 0!==i.url)return void await eG(e,t,i);let s=await eT(e,t),l=eL(e)[0]??e_;"intent"===s.type?await ej(e,s.value,r):r?await eK(e,s.value,r,l):await eH(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 eV(e,t),await ef(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",t,...(n=a.appBundleId,(r=n?.trim())?["-p",r]:[])])}async function eG(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 eq(e,t,"app-bound open");await ef(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",n,"-p",r])}async function ej(e,t,a){if(a)throw new i("INVALID_ARGS","Activity override requires a package name, not an intent");await ef(e,["shell","am","start","-W","-a",t])}async function eK(e,t,a,n){let i=a.includes("/")?a:`${t}/${a.startsWith(".")?a:`.${a}`}`;try{await ef(e,ez(i,n))}catch(a){throw await eX(e,t,a),a}}async function eH(e,t,a){let n=await ef(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eO,"-c",a,"-p",t],{allowFailure:!0});if(0===n.exitCode&&!e0(n.stdout,n.stderr))return;let r=await eY(e,t);if(!r){if(!await eJ(e,t))throw eZ(t);throw new i("COMMAND_FAILED",`Failed to launch ${t}`,{stdout:n.stdout,stderr:n.stderr})}await ef(e,ez(r,a))}function ez(e,t){return["shell","am","start","-W","-a","android.intent.action.MAIN","-c",eO,"-c",t,"-n",e]}async function eq(e,t,a){let n=await eT(e,t);if("intent"===n.type)throw new i("INVALID_ARGS",`Android ${a} requires a package name, not an intent`);return n.value}function eZ(e){return new i("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:eN})}async function eJ(e,t){let a=await ef(e,["shell","pm","path",t],{allowFailure:!0}),n=`${a.stdout}
3
- ${a.stderr}`;return!!(0===a.exitCode&&/\bpackage:/i.test(n))||(eQ(n),!1)}async function eX(e,t,a){if(eQ(a instanceof i?`${String(a.details?.stdout??"")}
4
- ${String(a.details?.stderr??"")}`:"")||!await eJ(e,t))throw eZ(t)}function eQ(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 eY(e,t){for(let a of Array.from(new Set(eL(e,{includeFallbackWhenUnknown:!0})))){let n=await ef(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",a,t],{allowFailure:!0});if(0!==n.exitCode)continue;let i=e1(n.stdout);if(i)return i}return null}function e0(e,t){let a=`${e}
5
- ${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(a)}function e1(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 e2(e){e.booted||await ep(e.id)}async function e9(e,t){if("settings"===t.trim().toLowerCase())return void await ef(e,["shell","am","force-stop","com.android.settings"]);let a=await eT(e,t);if("intent"===a.type)throw new i("INVALID_ARGS","Close requires a package name, not an intent");await ef(e,["shell","am","force-stop",a.value])}async function e4(e,t){let a=await eT(e,t);if("intent"===a.type)throw new i("INVALID_ARGS","App uninstall requires a package name, not an intent");let n=await ef(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 e3=null;async function e8(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(e3?.key===e)return e3.invocation;if(await l("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return e3={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 e3={key:e,invocation:a},a}async function e5(e){let t=await e8();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 e5(["build-apks","--bundle",i,"--output",l,"--mode",o]),await e5(["install-apks","--apks",l,"--device-id",n.id])}finally{await e.rm(s,{recursive:!0,force:!0})}}async function e7(e,t){".aab"===a.extname(t).toLowerCase()?await e6(e,t):await w(t,{device:e,replace:!0})}async function te(e){return new Set((await ef(e,["shell","pm","list","packages"])).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function tt(e,t){let a=Array.from(await te(e)).filter(e=>!t.has(e));if(1===a.length)return a[0]}async function ta(e,t){await eD.invalidateWhile(ek(e),async()=>{e.booted||await ep(e.id),await e7(e,t)})}async function tn(e,t,a){let n=a?void 0:await te(e);return await ta(e,t),a??(n?await tt(e,n):void 0)}async function ti(e,t){e.booted||await ep(e.id);let a=await eb({kind:"path",path:t});try{let t=await tn(e,a.installablePath,a.packageName),n=t?eR(t):void 0;return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:t,appName:n,launchTarget:t}}finally{await a.cleanup()}}async function tr(e,t,a){return await eD.invalidateWhile(ek(e),async()=>{e.booted||await ep(e.id);let{package:n}=await e4(e,t),i=await eb({kind:"path",path:a},{resolveIdentity:!1});try{await ta(e,i.installablePath)}finally{await i.cleanup()}return{package:n}})}async function to(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 ts(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 tl=new Set(["com.google.android.inputmethod.latin","com.samsung.android.honeyboard","com.touchtype.swiftkey","com.microsoft.swiftkey"]);function td(e){let t=tc(e.packageName),a=(e.resourceId??"").toLowerCase(),n=tc(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&&tl.has(t))return{inputMethodOwned:!0,source:"known-ime-package"};for(let e of tl)if(a.startsWith(`${e}:id/`))return{inputMethodOwned:!0,source:"known-ime-resource"};return{inputMethodOwned:!1,source:"app"}}function tu(e){return td(e).inputMethodOwned}function tc(e){return(e??"").trim().toLowerCase()||void 0}let tp=["mInputShown","mIsInputViewShown","isInputViewShown","mDecorViewVisible","mWindowVisible","mInShowWindow"],tf=new Map([[2,"number"],[3,"phone"],[4,"datetime"]]),tm=new Set([32,208]),tw=new Set([128,224,144]);async function th(e){return await tA(h(e))}async function tA(e){var t,a,n;let o,s,l,d,u,c,p,f,m=await e(["shell","dumpsys","input_method"],{allowFailure:!0});if(0!==m.exitCode)throw new i("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:m.stdout,stderr:m.stderr,exitCode:m.exitCode});return s=function(e){var t=function(e,t){let a=new Map,n=RegExp(`\\b(${t.join("|")})=([a-zA-Z]+)\\b`,"g");for(let t of e.matchAll(n)){let e=t[1],n=t[2]?.toLowerCase();e&&("true"===n||"false"===n)&&a.set(e,"true"===n)}return a}(e,tp);if(0===t.size)return null;let a=tv(t,["mWindowVisible","mDecorViewVisible","mInShowWindow"]);if(void 0!==a)return a;let n=t.get("mInputShown");return void 0!==n?n:tv(t,["mIsInputViewShown","isInputViewShown"])??null}(t=m.stdout)??function(e){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/),a=t?.[1];if(!a)return null;let n=Number.parseInt(a,16);return Number.isNaN(n)?null:(1&n)!=0}(t),l=(o=tb(t,/\binputType=0x([0-9a-fA-F]+)\b/gi))?`0x${o.toLowerCase()}`:void 0,d=tb(t,/\bpackageName=([A-Za-z0-9_.]+)\b/g),u=tb(t,/\b(?:resourceId|resource-id)=([^\s,}]+)/g),p=function(e,t,a){return e||t?td({packageName:e,resourceId:t,activeInputMethodPackage:a}).inputMethodOwned?"ime":"app":"unknown"}(d,u,c=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 tc(a?.[0])}(a?.[1]);if(n)return n}}(t)),a=d,n=u,!c&&((f=tc(a))&&tl.has(f)||function(e){let t=(e??"").toLowerCase();for(let e of tl)if(t.startsWith(`${e}:id/`))return!0;return!1}(n))&&r({level:"warn",phase:"android_input_ownership_fallback",data:{focusedPackage:a,focusedResourceId:n}}),{visible:s??!1,inputType:l,type:l?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let a=15&t,n=tf.get(a);if(n)return n;if(1!==a)return"unknown";let i=4080&t;return tm.has(i)?"email":tw.has(i)?"password":"text"}(l):void 0,inputMethodPackage:c,focusedPackage:d,focusedResourceId:u,inputOwner:p}}async function ty(e){return await tg(h(e))}async function tg(e){let t=await tA(e),a=t,n=0;for(;a.visible&&n<2;)await e(["shell","input","keyevent","111"]),n+=1,await p(120),a=await tA(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 tb(e,t){let a;for(let n of e.matchAll(t))a=n[1];return a}function tv(e,t){for(let a of t){let t=e.get(a);if(void 0!==t)return t}}async function tM(e){return await t_(h(e))}async function t_(e){let t,a;return(a=(t=(await tN(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 tI(e,t){await tO(h(e),t)}async function tO(e,t){await tN(e,["shell","cmd","clipboard","set","text",t],"write")}async function tN(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,em as androidDeviceForSerial,K as bootFailureHint,to as captureAndroidLogcatWithAdb,ey as classifyAndroidAppTarget,j as classifyBootFailure,e9 as closeAndroidApp,E as createAppResolutionCache,ty as dismissAndroidKeyboard,tg as dismissAndroidKeyboardWithAdb,ew as ensureAdb,ec as ensureAndroidEmulatorBooted,eg as formatAndroidInstalledPackageRequiredMessage,eP as getAndroidAppState,eU as getAndroidBlockingDialogFocus,th as getAndroidKeyboardState,tA as getAndroidKeyboardStatusWithAdb,eR as inferAndroidAppName,ti as installAndroidApp,tn as installAndroidInstallablePathAndResolvePackageName,e0 as isAmStartError,tu as isAndroidInputMethodOwnedNode,D as isDeepLinkTarget,L as isEnvTruthy,G as isInfrastructureBootFailureReason,k as isWebUrl,eE as listAndroidApps,er as listAndroidDevices,eW as openAndroidApp,e2 as openAndroidDevice,O as parseAndroidForegroundApp,e1 as parseAndroidLaunchComponent,_ as parseAndroidLaunchablePackages,I as parseAndroidUserInstalledPackages,V as parseSerialAllowlist,eb as prepareAndroidInstallArtifact,tM as readAndroidClipboardText,t_ as readAndroidClipboardWithAdb,tr as reinstallAndroidApp,eT as resolveAndroidApp,W as resolveAndroidSerialAllowlist,T as resolveIosDeviceDeepLinkBundleId,B as resolveIosSimulatorDeviceSetPath,R as retryWithPolicy,ef as runAndroidAdb,ts as streamAndroidLogcatWithAdb,ep as waitForAndroidBoot,P as withRetry,tI as writeAndroidClipboardText,tO as writeAndroidClipboardWithAdb};