agent-device 0.14.9 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.9.apk → agent-device-android-snapshot-helper-0.15.1.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.15.1.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.9.manifest.json → agent-device-android-snapshot-helper-0.15.1.manifest.json} +6 -6
- package/dist/src/1393.js +1 -0
- package/dist/src/1769.js +7 -0
- package/dist/src/1974.js +2 -2
- package/dist/src/208.js +1 -1
- package/dist/src/2151.js +434 -0
- package/dist/src/221.js +4 -4
- package/dist/src/2842.js +1 -0
- package/dist/src/3572.js +1 -0
- package/dist/src/4057.js +1 -1
- package/dist/src/4829.js +1 -1
- package/dist/src/9542.js +2 -2
- package/dist/src/9639.js +2 -2
- package/dist/src/989.js +1 -1
- package/dist/src/android-adb.d.ts +38 -9
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-snapshot-helper.d.ts +23 -0
- package/dist/src/cli.js +60 -57
- package/dist/src/contracts.d.ts +1 -0
- package/dist/src/finders.d.ts +1 -0
- package/dist/src/index.d.ts +56 -27
- package/dist/src/internal/companion-tunnel.js +1 -1
- package/dist/src/internal/daemon.js +51 -23
- package/dist/src/remote-config.d.ts +17 -14
- package/dist/src/selectors.d.ts +2 -0
- package/dist/src/server.js +2 -20
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/xcshareddata/xcschemes/AgentDeviceRunner.xcscheme +7 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +155 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +131 -72
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +734 -10
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +89 -16
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +5 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +9 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +4 -3
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +1 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests.xctestplan +26 -0
- package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +7 -1
- package/package.json +30 -11
- package/server.json +3 -3
- package/skills/agent-device/SKILL.md +2 -7
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.9.apk.sha256 +0 -1
- package/dist/src/180.js +0 -1
- package/dist/src/6108.js +0 -26
- package/dist/src/6642.js +0 -1
- package/dist/src/7462.js +0 -1
- package/dist/src/8809.js +0 -8
- package/dist/src/command-schema.js +0 -382
|
@@ -1,16 +1,34 @@
|
|
|
1
|
-
let e,t,r;import a from"node:crypto";import i,{promises as n}from"node:fs";import s from"node:path";import o from"node:http";import{fileURLToPath as l,pathToFileURL as d}from"node:url";import"node:https";import u from"node:os";import{once as c}from"node:events";import{Transform as f}from"node:stream";import{pipeline as p}from"node:stream/promises";import m from"node:fs/promises";import{setTimeout as h}from"node:timers/promises";import{PNG as g}from"pngjs";import w from"node:net";import{resolveUserPath as y}from"../3267.js";import{withDiagnosticsScope as v,flushDiagnosticsToSessionFile as S,getDiagnosticsMeta as I,emitDiagnostic as A}from"../7599.js";import{trimRuntimeValue as b,readProcessCommand as _,resolveRuntimeTransportHints as N,isAgentDeviceDaemonProcess as M,readProcessStartTime as x}from"../8656.js";import{withAndroidAdbProvider as D,pullAndroidAdbFile as k,resolveAndroidAdbProvider as P,resolveAndroidAdbExecutor as R}from"../9639.js";import{androidDeviceForSerial as L,runAndroidAdb as O,resolveIosSimulatorDeviceSetPath as E,classifyAndroidAppTarget as C,resolveIosDeviceDeepLinkBundleId as $,parseSerialAllowlist as T,getAndroidAppState as F,resolveAndroidSerialAllowlist as U,isDeepLinkTarget as V,openAndroidApp as G,formatAndroidInstalledPackageRequiredMessage as j}from"../8809.js";import{streamAndroidLogcatWithAdb as q,captureAndroidLogcatWithAdb as H}from"../6642.js";import{toAppErrorCode as B,asAppError as K,normalizeError as z,AppError as W}from"../9152.js";import{sleep as J,resolveTimeoutMs as Z}from"../4829.js";import{runCmdBackground as X,runCmd as Y}from"../9818.js";import{IOS_RUNNER_CONTAINER_BUNDLE_IDS as Q,resolveAppleSimulatorSetPathForSelector as ee,buildSimctlArgs as et,dispatchCommand as er,refSnapshotFlagGuardResponse as ea,buttonTag as ei,handleSnapshotCommands as en,withTargetDeviceResolutionScope as es,shutdownSimulator as eo,stopIosRunnerSession as el,localCommandPolicy as ed,getClickButtonValidationError as eu,createRequestCanceledError as ec,isNavigationSensitiveAction as ef,registerRequestAbort as ep,errorResponse as em,resolveIosDevicectlHint as eh,snapshotAndroid as eg,resolveTargetDevice as ew,withKeyedLock as ey,setSessionSnapshot as ev,dispatchGetViaRuntime as eS,assertAndroidPressStayedInApp as eI,stopAllIosRunnerSessions as eA,runMacOsAlertAction as eb,createAgentDevice as e_,getAndroidScreenSize as eN,readTextForNode as eM,captureSnapshot as ex,dispatchIsViaRuntime as eD,resolveClickButton as ek,IOS_DEVICECTL_DEFAULT_HINT as eP,buildSnapshotState as eR,context_contextFromFlags as eL,captureSnapshotData as eO,resolveRequestTrackingId as eE,isRequestCanceled as eC,resolvePayloadInput as e$,abortAllIosRunnerSessions as eT,getRunnerSessionSnapshot as eF,createUnsupportedArtifactAdapter as eU,isAndroidEscapeError as eV,markRequestCanceled as eG,dispatchFindReadOnlyViaRuntime as ej,runIosRunnerCommand as eq,ensureDeviceReady as eH,readInfoPlistString as eB,clearRequestCanceled as eK,buildSimctlArgsForDevice as ez,getActiveAndroidSnapshotFreshness as eW,parseXmlDocumentSync as eJ,resolveFrontmostMacOsApp as eZ,IOS_SIMCTL_LIST_TIMEOUT_MS as eX,matchesPlatformSelector as eY,isCommandSupportedOnDevice as eQ,listIosDeviceApps as e0,isApplePlatform as e1,listIosDeviceProcesses as e2,normalizePlatformSelector as e8,getRequestSignal as e3,decodePng as e5,buildScrollGesturePlan as e4,markAndroidSnapshotFreshness as e6}from"../6108.js";import{normalizeTenantId as e9,withSuccessText as e7,resolveDaemonPaths as te,resolveSessionIsolationMode as tt,resolveDaemonServerMode as tr,successText as ta,resolveInstallFromSourceResultTarget as ti,resolveDeployResultTarget as tn,resolveDaemonCodeSignature as ts}from"../180.js";import{parseSessionSurface as to}from"../7462.js";import{runBatch as tl,mergeParentFlags as td}from"../1231.js";import{splitSelectorFromArgs as tu,findNearestHittableAncestor as tc,extractNodeText as tf,splitIsSelectorArgs as tp,tryParseSelectorChain as tm,resolveSelectorChain as th,resolveRefLabel as tg,buildSelectorChainForNode as tw,normalizeType as ty,pruneGroupNodes as tv}from"../940.js";import{attachRefs as tS,centerOfRect as tI}from"../4057.js";import{findBestMatchesByLocator as tA,parseFindArgs as tb}from"../7556.js";import{readVersion as t_}from"../9671.js";function tN(e){let t=e.result?.text;if("string"==typeof t&&t.trim().length>0)return t;let r=e.positionals??[];return 0===r.length?"":r[0].startsWith("@")?r.length>=3?r.slice(2).join(" ").trim():r.slice(1).join(" ").trim():!(r.length>=3)||Number.isNaN(Number(r[0]))||Number.isNaN(Number(r[1]))?r.slice(1).join(" ").trim():r.slice(2).join(" ").trim()}function tM(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tx=/^-?\d+(\.\d+)?$/,tD=/^[^\s"\\]+$/,tk=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tP=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tR=new Map([["--delay-ms","delayMs"]]);function tL(e){return"click"===e||"press"===e}function tO(e){return"type"===e||"fill"===e}function tE(e){return t$(e,tT)}function tC(e){return JSON.stringify(e)}function t$(e,t){return t(e)?e:tC(e)}function tT(e){return tF(e)&&e.startsWith("@")||tx.test(e)}function tF(e){return tD.test(e)}function tU(e,t){let r=t.flags??{};if(tL(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}if("swipe"===t.command){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern);return}tO(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tV(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",t$(t.metroHost,tF)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",t$(t.bundleUrl,tF)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",t$(t.launchUrl,tF)))}function tG(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(t$(r,tF)),a))e.push(tE(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),"number"==typeof t.flags?.quality&&e.push("--quality",String(t.flags.quality)),t.flags?.hideTouches&&e.push("--hide-touches")}function tj(e,t){let r=[],a={},i=tL(e)?tk:"swipe"===e?tP:tO(e)?tR:void 0;for(let n=0;n<t.length;n+=1){let s=t[n];if(tL(e)&&"--double-tap"===s){a.doubleTap=!0;continue}if(tL(e)&&"--button"===s&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let o=i?.get(s);if(o&&n+1<t.length){let e=tH(t[n+1]);if(null!==e){a[o]=e,n+=1;continue}}if("swipe"===e&&"--pattern"===s&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(s)}return{positionals:r,flags:a}}function tq(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let i=e[a];if("--platform"===i&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===i&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===i&&a+1<e.length){let t=tH(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function tH(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tB(e,t){for(let r of t.positionals??[])e.push(tE(r));t.flags?.relaunch&&e.push("--relaunch"),tV(e,t.runtime)}class tK{sessions=new Map;runtimeHints=new Map;sessionsDir;constructor(e){this.sessionsDir=e}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=tK.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let t={};for(let r of tz)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),A({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=s.dirname(t);i.existsSync(r)||i.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.kind?` kind=${e.device.kind}`:"";for(let i of(r.push(`context platform=${e.device.platform} device=${tC(e.device.name)}${a} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(tL(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tE(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tE(a)),tU(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tE(r)),tU(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tE(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tE(a)),e.positionals.length>1&&t.push(tE(i)),tU(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tE(r)),t.push(tE(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tE(r))}return t.join(" ")}}if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tE(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tE(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),"number"==typeof e.flags?.screenshotMaxSize&&t.push("--max-size",String(e.flags.screenshotMaxSize)),t.join(" ")}if("open"===e.command)return tB(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(t$(r,tF)),tV(t,e.flags),t.join(" ")}if("record"===e.command)return tG(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tE(r));return tU(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
2
|
-
|
|
3
|
-
`)}function
|
|
4
|
-
`)},flush:()=>{a&&(i(a),a="")}}}function t0(e,t,r){let a=e.stdout,i=e.stderr;return a&&i?(a.setEncoding("utf8"),i.setEncoding("utf8"),a.on("data",r.writer.onChunk),i.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(a=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),a({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}function t1(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new W("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function t2(e,t){let r=(await R(L(e))(["shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function t8(e,t){var r,a;let i;t1(t);let n=await t2(e,t),s=R(L(e)),o=await H(s,{lines:4e3,timeoutMs:3e3}).catch(()=>"");if(0===o.trim().length)return null;let l=function(e,t,r){let a=new Set;for(let i of(r&&a.add(r),e.split("\n")))if(i.includes(t))for(let e of function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=[RegExp(`\\bStart proc\\s+(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`\\b(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`${r}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,"i"),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${r}`,"i")],i=[];for(let t of a){let r=t.exec(e),a=r?.[1];a&&/^\d+$/.test(a)&&i.push(a)}return i}(i,t))a.add(e);return[...a]}(o,t,n);if(0===l.length)return null;let d=(r=o,a=t,i=new Set(l),r.split("\n").filter(e=>{var t;let r;if(!e.trim())return!1;if(e.includes(a))return!0;let n=(t=e,r=/\(\s*(\d+)\)\s*:/.exec(t),r?.[1]??null);return!!n&&i.has(n)}).join("\n"));return 0===d.trim().length?null:{pid:n,text:d,recoveredPids:l}}async function t3(e,t,r,a,i){let n,s,o="recovering",l=!1,d=(async()=>{try{for(;!l;){let d=await t2(e,t);if(!d){o="recovering",await J(1e3);continue}let u=P(L(e)),c=q(u,{pid:d});n=c;let f=tQ(r,{redactionPatterns:a});if(s=t0(c,r,{endStreamOnClose:!1,writer:f}),"number"==typeof c.pid&&tZ(i,c.pid),o="active",await s,tX(i),n=void 0,s=void 0,l)break;o="recovering",await J(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tX(i)}})();return{backend:"android",getState:()=>o,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),s&&await tY(s),n&&!n.killed&&n.kill("SIGKILL"),await tY(d),tX(i)}}}function t5(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}"`}async function t4(e){let{deviceId:t,appBundleId:r,startedAt:a,simulatorSetPath:i}=e,n=et(["spawn",t,"log","show","--style","compact","--info","--predicate",t5(r)],{simulatorSetPath:i});"number"==typeof a&&Number.isFinite(a)&&a>0?n.push("--start",`@${Math.floor(a/1e3)}`):n.push("--last","5m");let s=await Y("xcrun",n,{allowFailure:!0,timeoutMs:4e3});if(0!==s.exitCode||0===s.stdout.trim().length)return null;let o=s.stdout.split("\n").map(e=>e.trimEnd()).filter(e=>{let t=e.trim();return t.length>0&&!t.startsWith("Timestamp Ty Process[PID:TID]")});return 0===o.length?null:{text:`${o.join("\n")}
|
|
5
|
-
`,recoveredLineCount:o.length}}async function t6(e,t,r,a,i,n){return re({backend:"ios-simulator",cmd:"xcrun",args:function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return et(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",t5(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:i}),stream:r,redactionPatterns:a,pidPath:n})}async function t9(e,t,r,a){return re({backend:"macos",cmd:"log",args:["stream","--style","compact","--predicate",t5(e)],stream:t,redactionPatterns:r,pidPath:a})}async function t7(e,t,r,a){return re({backend:"ios-device",cmd:"xcrun",args:["devicectl","device","log","stream","--device",e],stream:t,redactionPatterns:r,pidPath:a})}function re(e){let t="active",r=X(e.cmd,e.args,{allowFailure:!0,captureOutput:!1});r.wait.catch(()=>{});let a=r.child,i=tQ(e.stream,{redactionPatterns:e.redactionPatterns});"number"==typeof a.pid&&tZ(e.pidPath,a.pid);let n=t0(a,e.stream,{endStreamOnClose:!0,writer:i}).then(r=>(0!==r.exitCode&&(t="failed"),tX(e.pidPath),r),r=>{throw t="failed",tX(e.pidPath),r});return{backend:e.backend,getState:()=>t,startedAt:Date.now(),wait:n,stop:async()=>{a.killed||a.kill("SIGINT"),await tY(n),a.killed||a.kill("SIGKILL"),await tY(n),tX(e.pidPath)}}}let rt=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),rr=/https?:\/\/[^\s"'<>\])]+/i,ra=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function ri(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>rs(e)));for(let e of t.entries){let t=rs(e);if(!i.has(t)&&(i.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function rn(e,t){let r=rg(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=rg(t?.maxPayloadChars,2048,64,16384),s=rg(t?.maxScanLines,4e3,100,2e4),o=e.split("\n"),l=Math.max(0,o.length-s),d=o.slice(l),u=[];for(let e=d.length-1;e>=0&&u.length<r;e-=1){let t=d[e];if(!t?.trim())continue;let r=function(e,t,r,a,i,n){let s=e[t]?.trim();if(!s)return null;let o=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(s),l=rf(o,["method","httpMethod"]),d=rf(o,["url","requestUrl"]),u=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(o,["status","statusCode","responseCode"]),c=rt.exec(s),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(s),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=rr.exec(s),h=d??m?.[0];if(!h)return null;let g=u??rl(s)??void 0;if(!(l||f?.[1]||c?.[1]||void 0!==g||/\bURL["'=: ]+https?:\/\//i.test(s)||/\bheaders?["'=: ]+/i.test(s)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(s)))return null;let w={method:p,url:h,status:g,timestamp:rd(s),packetId:ru(s)??void 0,durationMs:rc(s)??void 0,raw:rh(s,n),line:r};if("android"===a&&function(e,t,r){let a=ro(t,r,5),i=e.packetId??a.map(e=>ru(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?ro(t,r,12).filter(e=>ru(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>rd(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>rl(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>rc(e)).find(e=>"number"==typeof e))}(w,e,t),"headers"===i||"all"===i){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return rm(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(s,o);e&&(w.headers=rh(e,n))}if("body"===i||"all"===i){let e=rp(s,o,["requestBody","body","payload","request"]),t=rp(s,o,["responseBody","response"]);e&&(w.requestBody=rh(e,n)),t&&(w.responseBody=rh(t,n))}return w}(d,e,l+e+1,a,i,n);r&&u.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:d.length,matchedLines:u.length,entries:u,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:s}}}function rs(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function ro(e,t,r){let a=[],i=Math.max(0,t-r),n=Math.min(e.length-1,t+r);for(let t=i;t<=n;t+=1){let r=e[t]?.trim();r&&a.push(r)}return a}function rl(e){for(let t of ra){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function rd(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function ru(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function rc(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function rf(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function rp(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return rm(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function rm(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function rh(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function rg(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function rw(e,t){let r=process.env[e];if(!r)return t;let a=Number.parseInt(r,10);return Number.isInteger(a)&&a>0?a:t}function ry(e){let t=s.dirname(e);i.existsSync(t)||i.mkdirSync(t,{recursive:!0}),function(e,t){if(i.existsSync(e)&&!(i.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,a=`${e}.${r}`;i.existsSync(t)&&(i.existsSync(a)&&i.unlinkSync(a),i.renameSync(t,a))}}(e,{maxBytes:rw("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rw("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rv(e){var t,r,a,n;let s,o,l,d,{device:u,appBundleId:c,appLogState:f,appLogStartedAt:p,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y}=e,v="macos"===u.platform?"macos":"ios"===u.platform?"device"===u.kind?"ios-device":"ios-simulator":"android",S=(t={backend:v,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y},s=rg(t?.maxEntries,25,1,200),o=t?.include??"summary",l=rg(t?.maxPayloadChars,2048,64,16384),d=rg(t?.maxScanLines,4e3,100,2e4),i.existsSync(m)?rn(i.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:o,limits:{maxEntries:s,maxPayloadChars:l,maxScanLines:d}}),I=[],A=await rS({device:u,appBundleId:c,appLogPath:m,appLogState:f});if(A){let e=await t8(u.id,c);if(e){let t=rn(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y});t.entries.length>0&&(S=ri(t,S,h),I.push((r=A,a=e.recoveredPids,"stale-active"===r.reason?`Session app log stream was still bound to prior Android PID ${r.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${a.join(", ")}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${a.join(", ")}.`)))}}if("ios"===u.platform&&"simulator"===u.kind&&c&&0===S.entries.length){let e=await rA({deviceId:u.id,appBundleId:c,startedAt:p,simulatorSetPath:u.simulatorSetPath,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y});e&&(e.dump.entries.length>0?(S=ri(e.dump,S,h),I.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&I.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===f?I.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==f&&0===I.length&&("ios"===u.platform&&"simulator"===u.kind?I.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):I.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===S.entries.length&&I.push("ios"===(n=u).platform&&"simulator"===n.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===n.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:v,dump:S,notes:I}}async function rS(e){let{device:t,appBundleId:r,appLogPath:a,appLogState:n}=e;if("android"!==t.platform||!r)return null;if(void 0!==n&&"active"!==n)return{reason:"inactive"};if("active"!==n)return null;let o=function(e){let t=function(e){if(!e||!i.existsSync(e))return null;try{return tJ(i.readFileSync(e,"utf8"))}catch{return null}}(e)?.command;if(!t)return null;let r=/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(t);return r?.[1]??null}(s.join(s.dirname(a),tW));if(!o)return null;let l=await t2(t.id,r);return l&&l!==o?{reason:"stale-active",trackedPid:o}:null}async function rI(e,t,r,a){ry(r);let n=i.createWriteStream(r,{flags:"a"}),s=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await t7(e.id,n,s,a):await t6(e.id,t,n,s,e.simulatorSetPath,a);if("android"===e.platform)return t1(t),await t3(e.id,t,n,s,a);if("macos"===e.platform)return await t9(t,n,s,a);throw n.end(),new W("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rA(e){let t=await t4({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:rn(t.text,{path:`${e.appLogPath} (simctl log show recovery)`,backend:"ios-simulator",maxEntries:e.maxEntries,include:e.include,maxPayloadChars:e.maxPayloadChars,maxScanLines:e.maxScanLines}),recoveredLineCount:t.recoveredLineCount}:null}async function rb(e){await e.stop(),await tY(e.wait)}async function r_(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let t=await O(e,["shell","echo","ok"],{allowFailure:!0,timeoutMs:1e3});r.adbAvailable=0===t.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await O(e,["shell","pidof",t],{allowFailure:!0,timeoutMs:1e3})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await Y("xcrun",["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await Y("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await Y("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function rN(e){let t=s.dirname(e),r=s.basename(e);i.existsSync(t)||i.mkdirSync(t,{recursive:!0}),i.existsSync(e)?i.truncateSync(e,0):i.writeFileSync(e,"","utf8");let a=0;for(let e of i.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let n=e.slice(r.length+1);if(/^\d+$/.test(n))try{i.unlinkSync(s.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let rM=new Map;function rx(e){let t=rM.get(e);if(t&&(clearTimeout(t.timer),rM.delete(e),t.deleteAfterDownload))try{i.rmSync(t.artifactPath,{force:!0})}catch{}}let rD=new Map;function rk(e,t){let r=rD.get(e);if(!r)throw new W("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new W("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function rP(e){let t=rD.get(e);t&&(clearTimeout(t.timer),rD.delete(e),i.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rR(e){let t=await rL(e);await Y("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=s.join(e.tempDir,t);if(!i.existsSync(r))throw new W("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rL(e){let t=await Y("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new W("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new W("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rO),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new W("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new W("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===a.length)return a[0];throw new W("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===i||e.startsWith(`${i}/`)))throw new W("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,s=i;if(n!==s&&!n.startsWith(`${s}/`))throw new W("INVALID_ARGS",`Archive entry must stay inside top-level "${s}" bundle: ${n}`)}for(let t of(await Y("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new W("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rO(e){if(e.includes("\0"))throw new W("INVALID_ARGS",`Invalid archive entry: ${e}`);if(s.posix.isAbsolute(e))throw new W("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=s.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new W("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rE=Z(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rC(e,t){return new Promise((r,a)=>{let n,s=!1,o=0,l=i.createWriteStream(t),d=e=>{if(!s){if(s=!0,n&&clearTimeout(n),e)return void r$(l,t).finally(()=>a(e));r()}},u=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let t=new W("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rE});"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t),c.destroy(t),d(t)},rE)},c=new f({transform(e,t,r){u();let a=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e,t);(o+=a)>0x80000000?r(new W("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")):r(null,e)}});e.on("aborted",()=>{d(new W("COMMAND_FAILED","Artifact transfer was interrupted"))}),u(),p(e,c,l).then(()=>d(),e=>d(e))})}async function r$(e,t){if(e.destroy(),!e.closed)try{await c(e,"close")}catch{}await i.promises.rm(t,{force:!0}).catch(()=>{})}async function rT(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new W("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new W("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new W("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let n=function(e){let t=e.trim(),r=s.basename(t);if(!r||"."===r||".."===r)throw new W("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),o=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),i.mkdtempSync(s.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=s.join(o,n);return await rC(e,t),{artifactPath:t,tempDir:o}}let t=s.join(o,"artifact.tar");await rC(e,t);let a=await rR({archivePath:t,tempDir:o,platform:"ios",expectedRootName:n});return i.rmSync(t,{force:!0}),{artifactPath:a,tempDir:o}}catch(e){throw i.rmSync(o,{recursive:!0,force:!0}),e}}let rF=new Set(["agent_device.command","agent-device.command"]),rU=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rV=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rG={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},rj=new Set([...rF,...rU,...rV,...Object.keys(rG)]);function rq(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rH(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rB(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rK(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,i="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??i??a??""}function rz(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rW(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}function rJ(e,t){let r="string"==typeof e[t]?e[t].trim():"";if(!r)throw new W("INVALID_ARGS",`Invalid params: source.${t} is required for github-actions-artifact sources`);return r}function rZ(e,t){let r=e[t],a="number"==typeof r?r:"string"==typeof r?Number(r):NaN;if(!Number.isInteger(a))throw new W("INVALID_ARGS",`Invalid params: source.${t} must be an integer`);return a}async function rX(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=z(new W("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:rq(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=z(new W(B(r.code,"UNAUTHORIZED"),r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:rq(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=e9(r.tenantId);if(!e){let e=z(new W("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:rq(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rY(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",a=s.isAbsolute(t)?t:s.resolve(t);try{e=await import(d(a).href)}catch(e){throw new W("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let i=e[r];if("function"!=typeof i)throw new W("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rQ(e){let t=await rY(),{handleRequest:r,token:a}=e;return o.createServer((e,i)=>{if("GET"===e.method&&"/health"===e.url){i.statusCode=200,i.setHeader("content-type","application/json"),i.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void r0(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/artifacts/"))return void r1(e,i,t,a);if("POST"!==e.method||"/rpc"!==e.url){i.statusCode=404,i.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{i.headersSent||rH(i,rq(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,s;try{a=JSON.parse(n)}catch{rH(i,rq(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rH(i,rq(a.id??null,-32600,"Invalid Request"),400);if(!rj.has(a.method))return void rH(i,rq(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rH(i,rq(a.id??null,-32602,"Invalid params"),400);try{var o;let n=a.params,l=function(e,t,r){if(rF.has(e))return{token:rK(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(rU.has(e)){let e,a=rz(t,"platform");if("ios"!==a&&"android"!==a)throw new W("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rK(t,r),session:rz(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rz(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new W("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new W("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,a={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new W("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new W("INVALID_ARGS","Invalid params: source.headers values must be strings");a[e]=t}}return Object.keys(a).length>0?{kind:"url",url:e,headers:a}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new W("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}if("github-actions-artifact"===t.kind)return function(e){let t,r=rJ(e,"owner"),a=rJ(e,"repo"),i=void 0!==e.artifactId,n=void 0!==e.runId,s=void 0!==e.artifactName;if(i&&(n||s))throw new W("INVALID_ARGS","Invalid params: source must specify either artifactId or artifactName, not both");if(!i&&n&&!s)throw new W("INVALID_ARGS","Invalid params: source.artifactName is required when source.runId is specified");if(!i&&!s)throw new W("INVALID_ARGS","Invalid params: source must specify artifactId or artifactName");return i?{kind:"github-actions-artifact",owner:r,repo:a,artifactId:rZ(e,"artifactId")}:(n&&(t=rZ(e,"runId")),{kind:"github-actions-artifact",owner:r,repo:a,...n?{runId:t}:{},artifactName:rJ(e,"artifactName")})}(t);throw new W("INVALID_ARGS",'Invalid params: source.kind must be "url", "path", or "github-actions-artifact"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rW(t,"retentionMs")}}}if(rV.has(e)){let e=rz(t,"materializationId")?.trim();if(!e)throw new W("INVALID_ARGS","Invalid params: materializationId is required");return{token:rK(t,r),session:rz(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rz(t,"requestId"),materializationId:e}}}let a=rG[e];if(a)return{token:rK(t,r),session:rz(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rz(t,"tenantId")??rz(t,"tenant"),runId:rz(t,"runId"),leaseId:rz(t,"leaseId"),leaseTtlMs:rW(t,"ttlMs"),leaseBackend:rz(t,"backend")}};throw new W("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(o=a.method,rF.has(o)&&("string"!=typeof l.command||0===l.command.length))return void rH(i,rq(a.id??null,-32602,"Invalid params: command is required"),400);s=eE(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:s},ep(s);let d=()=>{i.writableFinished||eG(s)};e.on("aborted",d),i.on("close",d);let u=await rX(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rH(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rH(i,{jsonrpc:"2.0",id:a.id??null,result:c});rH(i,rq(a.id??null,-32e3,c.error.message,c.error),rB(c.error.code))}catch(t){let e=z(t);rH(i,rq(a.id??null,-32e3,e.message,e),rB(e.code))}finally{eK(s)}})})}async function r0(e,t,r,i){try{var n;let s,o,l=rK({},e.headers),d=r2(l,i);if(d){t.statusCode=rB(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await rX(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await rT(e),f=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},s=a.randomUUID(),(o=setTimeout(()=>{rP(s)},3e5)).unref(),rD.set(s,{artifactPath:n.artifactPath,tempDir:n.tempDir,tenantId:n.tenantId,timer:o}),s);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:f}))}catch(r){let e=z(r);t.statusCode=rB(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function r1(e,t,r,a){let n=e.url?.slice("/artifacts/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let s=rK({},e.headers),o=r2(s,a);if(o){t.statusCode=rB(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let l=await rX(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:s,session:"default",command:"download_artifact",positionals:[n]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let d=function(e,t){let r=rM.get(e);if(!r)throw new W("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new W("UNAUTHORIZED","Artifact belongs to a different tenant");if(!i.existsSync(r.artifactPath))throw rx(e),new W("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),u=i.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=z(e);t.statusCode=rB(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rx(n)}),u.pipe(t)}catch(r){let e=z(r);t.statusCode=rB(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function r2(e,t){return t&&e!==t?z(new W("UNAUTHORIZED","Invalid token")):null}function r8(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function r3(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function r5(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";if("ios-instance"===t||"android-instance"===t)return t;throw new W("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class r4{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=r5(e.backend),r=e9(e.tenantId);if(!r)throw new W("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=r8(e.runId);if(!i)throw new W("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),s=this.bindingKey(r,i,t),o=this.runBindings.get(s);if(o){let e=this.leases.get(o);if(e)return this.refreshLease(e,n);this.runBindings.delete(s)}this.enforceCapacity(t);let l=this.now(),d={leaseId:a.randomBytes(16).toString("hex"),tenantId:r,runId:i,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+n};return this.leases.set(d.leaseId,d),this.runBindings.set(s,d.leaseId),{...d}}heartbeatLease(e){let t=r3(e.leaseId);if(!t)throw new W("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new W("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=r3(e.leaseId);if(!t)throw new W("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=r5(e.backend),r=e9(e.tenantId);if(!r)throw new W("INVALID_ARGS","tenant isolation requires tenant id.");let a=r8(e.runId);if(!a)throw new W("INVALID_ARGS","tenant isolation requires run id.");let i=r3(e.leaseId);if(!i)throw new W("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new W("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new W("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}cleanupExpiredLeases(){let e=this.now();for(let t of this.leases.values())t.expiresAt>e||(this.leases.delete(t.leaseId),this.runBindings.delete(this.bindingKey(t.tenantId,t.runId,t.backend)))}enforceCapacity(e){if("ios-simulator"!==e||this.maxActiveSimulatorLeases<=0)return;let t=Array.from(this.leases.values()).filter(e=>"ios-simulator"===e.backend).length;if(!(t<this.maxActiveSimulatorLeases))throw new W("COMMAND_FAILED","No simulator lease capacity available",{reason:"LEASE_CAPACITY_EXCEEDED",activeLeases:t,maxActiveLeases:this.maxActiveSimulatorLeases,backend:e,hint:"Retry after releasing another simulator lease."})}resolveLeaseTtlMs(e){if(!Number.isInteger(e))return this.defaultLeaseTtlMs;let t=Number(e);if(t<this.minLeaseTtlMs||t>this.maxLeaseTtlMs)throw new W("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),a={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(a.leaseId,a),this.runBindings.set(this.bindingKey(a.tenantId,a.runId,a.backend),a.leaseId),{...a}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let a=e9(t),i=r8(r);if(t&&!a)throw new W("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new W("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||i&&e.runId!==i)throw new W("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let r6=Z(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),r9=new Map;async function r7(e){let t=await m.mkdtemp(s.join(u.tmpdir(),"agent-device-materialized-"));try{let r=await ar(e.installablePath,s.join(t,"installable")),i=e.archivePath?await ar(e.archivePath,s.join(t,"archive")):void 0,n=a.randomUUID(),o=e.ttlMs??r6,l=Date.now()+o,d=setTimeout(()=>{ae(n)},o);return r9.set(n,{rootPath:t,installablePath:r,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:l,timer:d}),{materializationId:n,installablePath:r,...i?{archivePath:i}:{},expiresAt:new Date(l).toISOString()}}catch(e){throw await m.rm(t,{recursive:!0,force:!0}),e}}async function ae(e,t){let r=r9.get(e);if(!r)throw new W("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new W("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),r9.delete(e),await m.rm(r.rootPath,{recursive:!0,force:!0})}async function at(e){let t=Array.from(r9.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await ae(e)}))}async function ar(e,t){let r=await m.stat(e);await m.mkdir(t,{recursive:!0});let a=s.join(t,s.basename(e));return r.isDirectory()?await m.cp(e,a,{recursive:!0}):await m.copyFile(e,a),a}async function aa(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 W("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await eH(e.session.device),e.session.device}if(!r)throw new W("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await ew(e.flags??{});return await eH(a),a}async function ai(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);try{let e,n,s,o=(n=function(e){let t=e.meta?.installSource;if(!t)throw new W("INVALID_ARGS","install_from_source requires a source payload");switch(t.kind){case"url":if(!t.url||0===t.url.trim().length)throw new W("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 W("INVALID_ARGS","install_from_source path source requires a non-empty path");return t;case"github-actions-artifact":throw new W("UNSUPPORTED_OPERATION","install_from_source github-actions-artifact sources require a compatible remote daemon");default:throw new W("UNSUPPORTED_OPERATION",`install_from_source ${String(t.kind)} sources require a compatible remote daemon`)}}(t),(s=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:rk(s,t.meta?.tenantId)},cleanup:()=>{rP(s)}}:{source:n,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new W("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await aa({session:i,flags:t.flags});if(!eQ("install",d))return em("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let u=e3(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await import("../6108.js"),{prepareIosInstallArtifact:s}=await import("../6108.js"),c=await s(o.source,{signal:u});try{if(l.enabled&&(e=await r7({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(d,c.installablePath),!c.bundleId)throw new W("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let s={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},o=e7(s,an(s));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:o}),{ok:!0,data:o}}catch(r){throw e&&await ae(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),o.cleanup()}}let{prepareAndroidInstallArtifact:c}=await import("../8809.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("../6108.js"),p=await c(o.source,{signal:u});try{l.enabled&&(e=await r7({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await f(d,p.installablePath,p.packageName);if(!n)throw new W("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:s}=await import("../6108.js"),o=s(n),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...o?{appName:o}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=e7(u,an(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await ae(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),o.cleanup()}}catch(e){return{ok:!1,error:z(e)}}}function an(e){return`Installed: ${ti(e)}`}async function as(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new W("INVALID_ARGS","release_materialized_paths requires a materializationId");return await ae(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:z(e)}}}let ao=Z(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),al=Z(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function ad(e,t,r){return t||au(r)?null:em("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function au(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function ac(e){return"ios"===e.platform&&"simulator"===e.kind}async function af(e,t){ac(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function ap(e){let t=au(e.flags)||!e.session?await ew(e.flags??{}):await am(e.session.device);return!1!==e.ensureReady&&await eH(t),t}async function am(e){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let t={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await ew(t)}catch(e){if(!(e instanceof W)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await ew({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function ah(e){let t=e.flags?.device?.trim();return t||(e.resolvedDevice?.platform==="android"&&"emulator"===e.resolvedDevice.kind?e.resolvedDevice.name:e.sessionDevice?.platform==="android"&&"emulator"===e.sessionDevice.kind?e.sessionDevice.name:void 0)}let ag="shared_prefs/ReactNativeDevPrefs.xml",aw="debug_http_host",ay="dev_server_https",av="RCT_jsLocation",aS="RCT_packager_scheme",aI="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",aA='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function ab(e){return void 0!==N(e)}async function a_(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=N(a);if(i){if("android"===t.platform)return void await aM(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await aP(t,r,i)}}async function aN(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await ax(t,r);"ios"===t.platform&&"simulator"===t.kind&&await aR(t,r)}}async function aM(e,t,r){var a,i,n,s,o,l;let d,u;aC(t);let c=(a=await aD(e,t),i=aw,n=`${r.host}:${r.port}`,d=` <string name="${a$(i)}">${a$(n)}</string>`,aO(aE(a,i),d));s=c,o=ay,l="https"===r.scheme,u=` <boolean name="${a$(o)}" value="${l?"true":"false"}" />`,c=aO(aE(s,o),u),await ak(e,t,c)}async function ax(e,t){aC(t);let r=await aD(e,t),a=aE(r,aw),i=aE(a,ay);i!==r&&await ak(e,t,i)}async function aD(e,t){let r=await O(e,["shell","run-as",t,"cat",ag],{allowFailure:!0});return 0!==r.exitCode?aA:aL(r.stdout)}async function ak(e,t,r){let a=["shell","run-as",t,"id"],i=await O(e,a,{allowFailure:!0});if(0!==i.exitCode){let e=aT(i.stdout,i.stderr);throw new W("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?aI:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await O(e,["shell","run-as",t,"mkdir","-p","shared_prefs"]),await O(e,["shell","run-as",t,"tee",ag],{stdin:r.trimEnd()})}catch(a){let e=K(a);if("TOOL_MISSING"===e.code)throw e;let r=aT("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new W("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?aI:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function aP(e,t,r){await Y("xcrun",ez(e,["spawn",e.id,"defaults","write",t,av,"-string",`${r.host}:${r.port}`])),await Y("xcrun",ez(e,["spawn",e.id,"defaults","write",t,aS,"-string",r.scheme]))}async function aR(e,t){await Y("xcrun",ez(e,["spawn",e.id,"defaults","delete",t,av]),{allowFailure:!0}),await Y("xcrun",ez(e,["spawn",e.id,"defaults","delete",t,aS]),{allowFailure:!0})}function aL(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
6
|
-
|
|
7
|
-
</map>`)}function aE(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return aL(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function aC(e){if("binary"!==C(e))return;let t=j(e);throw new W("INVALID_ARGS",t,{package:e,hint:t})}function a$(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function aT(e,t){let r=`${e}
|
|
8
|
-
${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}let aF=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function aU(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function aV(e,t){if(void 0!==e){if("string"!=typeof e)throw new W("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return b(e)}}function aG(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new W("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function aj(e){if("ios"===e||"android"===e)return e}async function aq(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!ab(r)||ab(a)||await aN({device:i.device,appId:i.appBundleId})}async function aH(e){var t,r;let{req:a,sessionName:i,sessionStore:n}=e,s=(a.positionals?.[0]??"show").toLowerCase(),o=n.get(i),l=n.getRuntimeHints(i);if(!["set","show","clear"].includes(s))return em("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===s){ab(l)&&o?.appBundleId&&await aN({device:o.device,appId:o.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===s)return{ok:!0,data:{session:i,configured:!!l,runtime:l}};let d=aj(e8(a.flags?.platform)??l?.platform??o?.device.platform);if(!d)return em("INVALID_ARGS","runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first.");if(o&&o.device.platform!==d)return em("INVALID_ARGS",`runtime set targets ${d}, but session "${i}" is already bound to ${o.device.platform}.`);let u={platform:(t=a.flags,r={platform:d,metroHost:b(t?.metroHost),metroPort:aG(t?.metroPort),bundleUrl:b(t?.bundleUrl),launchUrl:b(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===aU(u)?em("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(n.setRuntimeHints(i,u),{ok:!0,data:{session:i,configured:!0,runtime:u}})}let aB="open-command-roundtrip",aK="Not implemented for this platform in this release.",az=new Set(["app","desktop","frontmost-app"]);async function aW(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await eZ();return{appBundleId:t.bundleId,appName:t.appName}}function aJ(e){return Math.round(10*e)/10}function aZ(e){return Math.round(10*e)/10}let aX="adb-shell-dumpsys-gfxinfo-framestats";function aY(e,t,r){let a=t.get(r);if(void 0===a)return null;let i=Number(e[a]);return Number.isFinite(i)?i:null}function aQ(e){return 0===e.length?{}:{firstFrameNs:Math.min(...e.map(e=>e.intendedVsyncNs)),lastFrameNs:Math.max(...e.map(e=>e.frameCompletedNs))}}function a0(e,t){if(void 0!==e&&void 0!==t)return Math.max(0,Math.round((t-e)/1e6))}function a1(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`^\\s*${r}:\\s*([0-9][0-9,]*)`,"im"));if(a)return a2(a[1])??void 0}function a2(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}async function a8(e,t,r={}){var a,i,n,s,o,l,d,u;let c=R(e,r.adb);try{let d,u,f,p,m,h,g,w,y,v,S,I=(a=(await c(["shell","dumpsys","gfxinfo",t,"framestats"],{timeoutMs:15e3})).stdout,i=new Date().toISOString(),function(e,t){if(/no process found for:/i.test(e))throw new W("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."})}(a,t),f=function(e){let t=e.split(/\nProfile data in ms:\n/i)[0]??"",r=a1(t,"Total frames rendered"),a=t.match(/^\s*Janky frames:\s*([0-9][0-9,]*)\s*\(([0-9.]+)%\)/im);if(void 0===r||!a)return;let i=a2(a[1])??void 0,n=Number(a[2]);if(void 0===i||!Number.isFinite(n)||r<0)return;let s=a1(t,"Uptime"),o=a1(t,"Stats since");return{droppedFramePercent:aJ(n),droppedFrameCount:i,totalFrameCount:r,sampleWindowMs:function(e){let{uptimeMs:t,statsSinceNs:r}=e;if(void 0===t||void 0===r)return;let a=t-Math.round(r/1e6);return a>=0?a:void 0}({uptimeMs:s,statsSinceNs:o}),uptimeMs:s,statsSinceNs:o}}(a),p=function(e){let t=[],r=null;for(let i of e.split("\n")){var a;let e=i.trim();if(0===e.length||"---PROFILEDATA---"===e)continue;let n=e.split(",").map(e=>e.trim());if((a=n).includes("IntendedVsync")&&a.includes("FrameCompleted")){r=new Map(n.map((e,t)=>[e,t]));continue}let s=function(e,t){if(!t||e.length<t.size)return;let r=aY(e,t,"Flags"),a=aY(e,t,"IntendedVsync"),i=aY(e,t,"FrameCompleted");if(0===r&&null!==a&&null!==i&&!(a<=0)&&!(i<=a))return{intendedVsyncNs:a,frameCompletedNs:i,durationNs:i-a}}(n,r);s&&t.push(s)}return t.sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs)}(a),m=function(e,t,r){let a=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)),a=[];for(let e=1;e<r.length;e+=1){let t=r[e]-r[e-1];t>=4e6&&t<=5e7&&a.push(t)}if(0!==a.length){let e,t;return e=[...a].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 W("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!==a)return a;throw new W("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."})}(p,f,t),h=Date.parse(i),g=function(e){let{frames:t,measuredAtMs:r,summary:a}=e,i=aQ(t),n=a?.statsSinceNs,s=n??i.firstFrameNs,o=a0(s,i.lastFrameNs),l=a?.sampleWindowMs??o;if(!Number.isFinite(r)||a?.uptimeMs===void 0||void 0===s)return{sampleWindowMs:l,windowStartNs:s};let d=r-a.uptimeMs;return{sampleWindowMs:l,windowStartNs:s,windowStartedAt:new Date(d+s/1e6).toISOString(),windowEndedAt:function(e){let{deviceBootWallClockMs:t,measuredAtMs:r,summaryStartNs:a,lastFrameNs:i}=e;return void 0!==a?new Date(r).toISOString():void 0===i?void 0:new Date(t+i/1e6).toISOString()}({deviceBootWallClockMs:d,measuredAtMs:r,summaryStartNs:n,lastFrameNs:i.lastFrameNs}),timestampSource:"estimated-from-device-uptime"}}({frames:p,measuredAtMs:h,summary:f}),w=function(e){let{frames:t,frameDeadlineNs:r,summaryDroppedFrameCount:a}=e;return void 0!==a?a<=0?[]:[...t].sort((e,t)=>t.durationNs-e.durationNs).slice(0,a).sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs):void 0===r?[]:t.filter(e=>e.durationNs>r)}({frames:p,frameDeadlineNs:m,summaryDroppedFrameCount:f?.droppedFrameCount}),y=f?.sampleWindowMs??g.sampleWindowMs??function(e){if(0===e.length)return;let t=aQ(e);return a0(t.firstFrameNs,t.lastFrameNs)}(p),n=f,s=p,o=w,d=n?.totalFrameCount??s.length,u=n?.droppedFrameCount??o.length,v={totalFrameCount:d,droppedFrameCount:u,droppedFramePercent:n?.droppedFramePercent??(d>0?aJ(u/d*100):0)},S=function(e){let{droppedFrames:t,timing:r,measuredAtMs:a,summary:i}=e;if(0===t.length)return;let n=function(e){let{frames:t,windowStartNs:r,measuredAtMs:a,uptimeMs:i}=e;if(0===t.length||void 0===r)return[];let n=[],s=[];for(let e of t){let t=s.at(-1);if(!t||e.intendedVsyncNs-t.frameCompletedNs<=5e8){s.push(e);continue}n.push(s),s=[e]}return s.length>0&&n.push(s),n.map(e=>(function(e){let{frames:t,windowStartNs:r,measuredAtMs:a,uptimeMs:i}=e,n=Math.min(...t.map(e=>e.intendedVsyncNs)),s=Math.max(...t.map(e=>e.frameCompletedNs)),o=Math.max(0,Math.round((n-r)/1e6)),l=Math.max(o,Math.round((s-r)/1e6)),d=void 0!==i&&Number.isFinite(a)?a-i:void 0;return{startOffsetMs:o,endOffsetMs:l,startAt:void 0===d?void 0:new Date(d+n/1e6).toISOString(),endAt:void 0===d?void 0:new Date(d+s/1e6).toISOString(),missedDeadlineFrameCount:t.length,worstFrameMs:aZ(Math.max(...t.map(e=>e.durationNs))/1e6)}})({frames:e,windowStartNs:r,measuredAtMs:a,uptimeMs:i})).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:a,uptimeMs:i?.uptimeMs});return n.length>0?n:void 0}({droppedFrames:w,timing:g,measuredAtMs:h,summary:f}),{...v,sampleWindowMs:y,...(l=m,{frameDeadlineMs:void 0===l?void 0:aZ(l/1e6),refreshRateHz:void 0===l?void 0:aZ(1e9/l)}),windowStartedAt:g.windowStartedAt,windowEndedAt:g.windowEndedAt,timestampSource:g.timestampSource,measuredAt:i,method:aX,source:f?"android-gfxinfo-summary":"framestats-rows",worstWindows:S&&S.length>0?S:void 0});return await a3(e,t,r),I}catch(e){throw d=t,(u=e)instanceof W?new W(u.code,u.message,{...u.details??{},metric:"fps",package:d},u):new W("COMMAND_FAILED",`Failed to sample Android fps for ${d}`,{metric:"fps",package:d},u)}}async function a3(e,t,r={}){let a=R(e,r.adb);try{await a(["shell","dumpsys","gfxinfo",t,"reset"],{allowFailure:!0,timeoutMs:3e3})}catch{}}let a5="adb-shell-dumpsys-cpuinfo",a4="adb-shell-dumpsys-meminfo";async function a6(e,t,r={}){let a=R(e,r.adb);try{let e=await a(["shell","dumpsys","cpuinfo"],{timeoutMs:15e3});return function(e,t,r){let a=new Set,i=0;for(let r of e.split("\n")){var n,s;let e=r.trim();if(0===e.length)continue;let o=e.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!o)continue;let l=Number(o[1]),d=o[2];Number.isFinite(l)&&(n=d,s=t,n===s||n.startsWith(`${s}:`))&&(i+=l,a.add(d))}return{usagePercent:aJ(i),measuredAt:r,method:a5,matchedProcesses:[...a]}}(e.stdout,t,new Date().toISOString())}catch(e){throw a7("cpu",t,e)}}async function a9(e,t,r={}){let a=R(e,r.adb);try{let e=await a(["shell","dumpsys","meminfo",t],{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new W("COMMAND_FAILED",`Android meminfo did not find a running process for ${t}`,{metric:"memory",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf."});let a=ie(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!==it(e));if(!r)break;return it(r)??void 0}}(e);if(void 0===a)throw new W("COMMAND_FAILED",`Failed to parse Android meminfo output for ${t}`,{metric:"memory",package:t,hint:"Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging."});return{totalPssKb:a,totalRssKb:ie(e,"TOTAL RSS"),measuredAt:r,method:a4}}(e.stdout,t,new Date().toISOString())}catch(e){throw a7("memory",t,e)}}function a7(e,t,r){return r instanceof W?new W(r.code,r.message,{...r.details??{},metric:e,package:t},r):new W("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function ie(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return it(a[1])??void 0}function it(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}async function ir(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return V(t)?"macos"===e.platform?void 0:"device"===e.kind?$(r,t):void 0:await ia(e,t)}async function ia(e,t){try{let{resolveIosApp:r}=await import("../6108.js");return await r(e,t)}catch{return}}async function ii(e,t){if(!("android"!==e.platform||!t||V(t)))try{let{resolveAndroidApp:r}=await import("../6108.js"),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function is(e,t,r){if(r||"android"!==e.platform||!t||!V(t))return r;try{let{getAndroidAppState:t}=await import("../6108.js"),a=await t(e);return a.package?.trim()||r}catch{return r}}async function io(e,t,r,a){return await ir(e,t,r)??await a(e,t)??("android"===e.platform&&t&&V(t)?r:void 0)}function il(e){return em("INVALID_ARGS",e)}function id(e,t,r,a){try{return function(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:i}=e;if(("macos"===t.platform||"linux"===t.platform)&&!r)return i??"app";if("linux"===t.platform){if(!r)return"app";let e=to(r);if(!az.has(e))throw new W("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new W("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new W("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let n=r?to(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new W("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return em(e instanceof W?e.code:"INVALID_ARGS",String(e.message))}}function iu(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&V(r)?il("open --relaunch does not support URL targets."):"app"!==a?il("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===C(r)?il(j(r)):null:null}async function ic(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:s,existingSession:o}=e;await eH(i);let{appBundleId:l,appName:d}=await ip({device:i,surface:n,openTarget:s,existingAppBundleId:o?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),s=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new W("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!aF.includes(e));if(i)throw new W("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${aF.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new W("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new W("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:aV(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new W("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return aG(e)}}(t.metroPort),bundleUrl:aV(t.bundleUrl,"bundleUrl"),launchUrl:aV(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:aj(i.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let i=r?.platform,n=aj(i);if(a.platform&&r&&!n)throw new W("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new W("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:s&&aU(s)>0?s:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=K(t);return em(e.code,e.message,e.details)}}({req:t,sessionStore:a,sessionName:r,device:i});if(!u.ok)return{type:"response",response:u};if(o){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await aq({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:o})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function ip(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await aW(r);return{appBundleId:n.appBundleId??await io(t,a,i,ii),appName:n.appName??a}}let im=new Map;async function ih(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await el(t.id),await er(t,"close",[r],a,i),await af(t,ao)}async function ig(e){let{runtime:t,device:r,req:a,logPath:i,appBundleId:n,traceLogPath:s,openPositionals:o}=e,l=t?.launchUrl;if(!l||0===o.length||o.length>1)return;let d=o[0]?.trim();!d||V(d)||await er(r,"open",[l],a.flags?.out,{...eL(i,a.flags,n,s)})}async function iw(e){var t,r,a,i;let{req:n,sessionName:s,sessionStore:o,logPath:l,device:d,openTarget:u,openPositionals:c,appName:f,surface:p,appBundleId:m,runtime:h,existingSession:g}=e,w=n.flags?.relaunch===!0,y=g?.trace?.outPath,v=m;if(w&&u){let e=v??u;await ih({device:d,closeTarget:e,outFlag:n.flags?.out,context:{...eL(l,n.flags,v??g?.appBundleId,y)}})}await a_({device:d,appId:v,runtime:h});let S=Date.now();await er(d,"open",c,n.flags?.out,{...eL(l,n.flags,v)}),await ig({runtime:h,device:d,req:n,logPath:l,appBundleId:v,traceLogPath:y,openPositionals:c}),v=await is(d,u,v),"android"===d.platform&&v&&await a3(d,v);let I=u?(t=v,{durationMs:Math.max(0,Date.now()-S),measuredAt:new Date().toISOString(),method:aB,appTarget:u,appBundleId:t}):void 0;if(await af(d,al),eC(n.meta?.requestId)){let e=ec();return em(e.code,e.message,e.details)}g&&e6(g,"open",g.snapshot);let A=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:s,saveScript:o}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:s,recordSession:t.recordSession||o,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:s,recordSession:o,actions:[]}}({existingSession:g,sessionName:s,device:d,surface:p,appBundleId:v,appName:f,saveScript:!!n.flags?.saveScript});void 0!==n.runtime&&(r=o,a=s,(i=h)&&(0===aU(i)?r.clearRuntimeHints(a):r.setRuntimeHints(a,i)));let b=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:i,startup:n,device:s,runtime:o,runtimeHintCount:l}=e,d={session:t,surface:i};return r&&(d.appName=r),a&&(d.appBundleId=a),n&&(d.startup=n),o&&l(o)>0&&(d.runtime=o),s&&(d.platform=s.platform,d.target=s.target??"mobile",d.device=s.name,d.id=s.id,d.kind=s.kind,"android"===s.platform&&(d.serial=s.id)),s?.platform==="ios"&&(d.device_udid=s.id,d.ios_simulator_device_set=s.simulatorSetPath??null),{...d,...ta(`Opened: ${r??a??t}`)}}({sessionName:s,appName:f,appBundleId:v,surface:p,startup:I,device:d,runtime:h,runtimeHintCount:aU});return o.recordAction(A,{command:"open",positionals:c,flags:n.flags??{},runtime:void 0!==n.runtime?h:void 0,result:b}),o.set(s,A),{ok:!0,data:b}}async function iy(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return em("SESSION_NOT_FOUND",`Session "${r}" not found.`);let n=t.flags?.relaunch===!0,s=t.positionals?.[0],o=s??(n?e.appName:void 0),l=id(e.device,t.flags?.surface,o,e.surface);if("string"!=typeof l)return l;if(!o&&"app"===l)return n?il("open --relaunch requires an app name or an active session app."):il("Session already active. Close it first or pass a new --session name.");let d=iu({shouldRelaunch:n,openTarget:o,surface:l,device:e.device});if(d)return d;let u=await am(e.device),c=await ic({req:t,sessionName:r,sessionStore:i,device:u,surface:l,openTarget:o,existingSession:e});return"response"===c.type?c.response:await iw({req:t,sessionName:r,sessionStore:i,logPath:a,device:u,openTarget:o,openPositionals:s?t.positionals??[]:o?[o]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,s=t.positionals?.[0];if(n&&!s)return il("open --relaunch requires an app argument.");let o=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&V(r)?il("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===C(r)?il(j(r)):null:null}({shouldRelaunch:n,openTarget:s,platform:t.flags?.platform==="android"?"android":void 0});if(o)return o;let l=await ew(t.flags??{}),d=id(l,t.flags?.surface,s);if("string"!=typeof d)return d;let u=iu({shouldRelaunch:n,openTarget:s,surface:d,device:l});return u||await ey(im,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return em("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name});let n=await ic({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:s});return"response"===n.type?n.response:await iw({req:t,sessionName:r,sessionStore:i,logPath:a,device:l,openTarget:s,openPositionals:t.positionals??[],appBundleId:n.details.appBundleId,appName:n.details.appName,runtime:n.details.runtime,surface:d})})}async function iv(e){let t=await O(e,["emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function iS(e){let{device:t,shutdownRequested:r}=e;if(r&&(ac(t)||"android"===t.platform&&"emulator"===t.kind))try{return ac(t)?await eo(t):await iv(t)}catch(t){let e=z(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function iI(e){if(await el(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await eb("dismiss",t).catch(t=>{A({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function iA(e,t){e.appLog&&await rb(e.appLog),e1(e.device.platform)&&await iI(e),await at(t).catch(()=>{})}async function ib(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return em("SESSION_NOT_FOUND","No active session");n.appLog&&await rb(n.appLog),t.positionals&&t.positionals.length>0&&(e1(n.device.platform)&&await iI(n),await er(n.device,"close",t.positionals,t.flags?.out,{...eL(a,t.flags,n.appBundleId,n.trace?.outPath)}),await af(n.device,ao)),e1(n.device.platform)&&await iI(n),ab(i.getRuntimeHints(r))&&n.appBundleId&&await aN({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...ta(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await at(r).catch(()=>{}),i.delete(r);let s=await iS({device:n.device,shutdownRequested:t.flags?.shutdown});return s?{ok:!0,data:e7({session:r,shutdown:s},`Closed: ${r}`)}:{ok:!0,data:{session:r,...ta(`Closed: ${r}`)}}}let i_={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await import("../6108.js");return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await import("../6108.js");return await a(e,t,r)}},iN={ios:async(e,t,r)=>{let{installIosApp:a}=await import("../6108.js"),i=await a(e,r,{appIdentifierHint:t});return{bundleId:i.bundleId,appName:i.appName,launchTarget:i.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await import("../6108.js"),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function iM(e){let{req:t,command:r,sessionName:a,sessionStore:n,deployOps:s}=e,o=n.get(a),l=t.flags??{},d=ad(r,o,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return em("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let f=t.meta?.uploadedArtifactId;try{var p;let e,a=f?rk(f,t.meta?.tenantId):tK.expandHome(c);if(!i.existsSync(a))return em("INVALID_ARGS",`App binary not found: ${a}`);let d=await ap({session:o,flags:l,ensureReady:!1});if(!eQ(r,d))return em("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await s.ios(d,u,a),r=t.bundleId;e=r?{app:u,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await s.android(d,u,a),r=t.package;e=r?{app:u,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=e7(e,(p=e,`Installed: ${p.appName??tn(p)}`));return o&&n.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&rP(f)}}async function ix(e,t,r){return await tl(e,t,r)}async function iD(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:s,reuseExisting:o,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new W("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:s??void 0};if(o){let e=await ik({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await iP({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await iR(t,u),a=!0)}else t=(await iP({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await iR(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...s?{simulatorSetPath:s}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function ik(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await Y("xcrun",et(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:eX});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||iL(a).includes(iL(r))){for(let e of i)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function iP(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await Y("xcrun",et(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new W("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let s=String(n.stdout??"").trim();if(!s)throw new W("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:s}}async function iR(e,t){let r=await Y("xcrun",et(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:eX});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function iL(e){return e.toLowerCase().replace(/[._-]/g,"")}async function iO(e){let{req:t,sessionName:r,sessionStore:a}=e;if("session_list"===t.command)return{ok:!0,data:{sessions:a.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",surface:e.surface??"app",device:e.device.name,id:e.device.id,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("ensure-simulator"===t.command)try{let e=t.flags??{},r=e.device,a=e.runtime,i=E(e.iosSimulatorDeviceSet);if(!r)return em("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await iD({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:eH});return{ok:!0,data:{udid:n.udid,device:n.device,runtime:n.runtime,ios_simulator_device_set:i??null,created:n.created,booted:n.booted}}}catch(t){let e=K(t);return em(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=U(t.flags?.androidDeviceAllowlist),a=e8(t.flags?.platform),i=ee({simulatorSetPath:E(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("../8809.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("../6108.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("../8809.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("../6108.js");try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,s=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:s}}}catch(t){let e=K(t);return em(e.code,e.message,e.details)}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=ad(t.command,e,i);if(n)return n;let s=await ap({session:e,flags:i,ensureReady:!0});if(!eQ("apps",s))return em("UNSUPPORTED_OPERATION","apps is not supported on this device");let o=t.flags?.appsFilter??"all";if(e1(s.platform)){let{listIosApps:e}=await import("../6108.js");return{ok:!0,data:{apps:(await e(s,o)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await import("../6108.js");return{ok:!0,data:{apps:(await l(s,o)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function iE(e){let{ensureAndroidEmulatorBooted:t}=await import("../8809.js");return await t(e)}let iC='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',i$='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function iT(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},s=e8(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return em("SESSION_NOT_FOUND","ios"===s?`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 o=ad("appstate",i,n);if(o)return o;let l=e1(i?.device.platform)&&function(e,t){if(!t)return!1;if(!au(e))return!0;let r=e8(e?.platform);return!(r&&!eY(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(n,i);if("ios"===s&&!l)return em("SESSION_NOT_FOUND",iC);if("macos"===s&&!l)return em("SESSION_NOT_FOUND",i$);if(l&&i){let e=i.appName??i.appBundleId;if(!i.appName&&!i.appBundleId){if("macos"===i.device.platform&&i.surface&&"app"!==i.surface&&"frontmost-app"!==i.surface)return{ok:!0,data:{platform:i.device.platform,appName:i.surface,appBundleId:i.appBundleId,source:"session",surface:i.surface}};let e="macos"===i.device.platform?"macOS":"iOS";return em("COMMAND_FAILED",`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`)}return{ok:!0,data:{platform:i.device.platform,appName:e??"unknown",appBundleId:i.appBundleId,source:"session",surface:i.surface??"app",..."ios"===i.device.platform?{device_udid:i.device.id,ios_simulator_device_set:i.device.simulatorSetPath??null}:{}}}}let d=await ap({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return em("SESSION_NOT_FOUND",iC);if("macos"===d.platform)return em("SESSION_NOT_FOUND",i$);let{getAndroidAppState:u}=await import("../6108.js"),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function iF(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},s=ad(t.command,i,n);if(s)return s;let o="android"===(e8(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!o)return em("INVALID_ARGS","boot --headless is supported only for Android emulators.");let d=ah({flags:n,sessionDevice:i?.device}),u=o&&!!d,c=!1;try{e=await ap({session:i,flags:n,ensureReady:!1})}catch(r){let t=K(r);if(o&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return em("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await iE({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return em("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(o&&l){if("android"!==e.platform||"emulator"!==e.kind)return em("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=ah({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return em("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await iE({avdName:t,serial:n.serial,headless:!0})}await eH(e)}else("android"!==e.platform||!0!==e.booted)&&await eH(e);return eQ("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:em("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await iT({req:t,sessionName:r,sessionStore:a}):null}function iU(e,t){for(let r of e){if(t(r))return r;let e=iU(r.children,t);if(e)return e}}function iV(e,t){let r=[];for(let a of e)t(a)&&r.push(a),r.push(...iV(a.children,t));return r}function iG(e,t){let r=iU(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 ij(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 iq(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:ij(e):null}let iH="xctrace-animation-hitches";function iB(e,t){let r=eJ(e),a=iG(r,t);return{rows:0===a.length?[]:iV(r,e=>"row"===e.name),schema:a}}function iK(e,t){for(let r of e)iK(r.children,t),r.attributes.id&&t.set(r.attributes.id,{numberValue:ij(r),process:iz(r)})}function iz(e){if(!e||e.children.some(e=>"sentinel"===e.name))return null;let t=ij(iU(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 iW="ps-process-snapshot",iJ="ps-process-snapshot",iZ="xctrace-activity-monitor",iX="xctrace-activity-monitor";async function iY(e,t){if("ios"===e.platform&&"device"===e.kind)return await i9(e,t);let r=await i6(e,t),a=await ni(e,r);if(0===a.length)throw new W("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,hint:"Run open <app> for this session again to ensure the Apple app is active, then retry perf."});let i=new Date().toISOString();return nn({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:[r.executableName],cpuMethod:iW,memoryMethod:iJ})}async function iQ(e,t){var r;let a,i,n,o,d,u;if("ios"!==e.platform||"device"!==e.kind)throw new W("COMMAND_FAILED","Apple frame-health sampling is currently available only on connected iOS devices.",{metric:"fps",platform:e.platform,deviceKind:e.kind});let c=await i7(e,t),f=await i0(e,t,c);return a=iB((r={hitchesXml:f.hitchesXml,frameLifetimesXml:f.frameLifetimesXml,displayInfoXml:f.displayInfoXml,processIds:c.map(e=>e.pid),processNames:tM(c.map(e=>s.basename(l(e.executable)))),windowStartedAt:f.windowStartedAt,windowEndedAt:f.windowEndedAt,measuredAt:f.windowEndedAt}).frameLifetimesXml,"hitches-frame-lifetimes").rows.length,i=function(e){if(!e)return;let{rows:t,schema:r}=iB(e,"device-display-info"),a=r.indexOf("max-refresh-rate");if(a<0)return;let i=new Map;for(let e of t){iK(e.children,i);let t=iq(e.children[a],i);if(null!==t&&t>0)return t}}(r.displayInfoXml),o=(n=(function(e){let t,r,a=eJ(e),i=Object.values(r={start:(t=iG(a,"hitches")).indexOf("start"),duration:t.indexOf("duration"),process:t.indexOf("process"),isSystem:t.indexOf("is-system")}).every(e=>e>=0)?r:null;if(!i)return[];let n=new Map;return iV(a,e=>"row"===e.name).map(e=>(function(e,t,r){var a,i,n;let s;if(iK(e.children,r),!0===(a=e.children[t.isSystem],null===(s=iq(a,r))?null:0!==s))return null;let o=iq(e.children[t.start],r),l=iq(e.children[t.duration],r);if(null===o||null===l)return null;let d=(i=e.children[t.process],n=r,i?i.attributes.ref?n.get(i.attributes.ref)?.process??null:iz(i):null);return{startNs:o,durationNs:l,pid:d?.pid,processName:d?.name}})(e,i,n)).filter(e=>!!e)})(r.hitchesXml).filter(e=>{var t,a,i;return t=e,a=r.processIds,i=r.processNames,!!(void 0!==t.pid&&a.includes(t.pid))||!!t.processName&&i.includes(t.processName)})).length,d=Math.max(0,Math.round(Date.parse(r.windowEndedAt)-Date.parse(r.windowStartedAt))),u=function(e,t){if(0===e.length)return[];let r=[...e].sort((e,t)=>e.startNs-t.startNs),a=[],i=[];for(let e of r){let t=i.at(-1);if(!t||e.startNs-(t.startNs+t.durationNs)<=5e8){i.push(e);continue}a.push(i),i=[e]}return i.length>0&&a.push(i),a.map(e=>{var r,a;let i,n,s,o;return r=e,a=t,i=Math.min(...r.map(e=>e.startNs)),n=Math.max(...r.map(e=>e.startNs+e.durationNs)),o=Math.max(s=Math.max(0,Math.round(i/1e6)),Math.round(n/1e6)),{startOffsetMs:s,endOffsetMs:o,startAt:new Date(a+s).toISOString(),endAt:new Date(a+o).toISOString(),missedDeadlineFrameCount:r.length,worstFrameMs:aJ(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)}(n,Date.parse(r.windowStartedAt)),{droppedFramePercent:a>0?aJ(o/a*100):0,droppedFrameCount:o,totalFrameCount:a,sampleWindowMs:d,windowStartedAt:r.windowStartedAt,windowEndedAt:r.windowEndedAt,measuredAt:r.measuredAt,method:iH,matchedProcesses:[...new Set(n.map(e=>e.processName).filter(e=>"string"==typeof e&&e.length>0))],frameDeadlineMs:void 0===i?void 0:aJ(1e3/i),refreshRateHz:i,worstWindows:u.length>0?u:void 0}}async function i0(e,t,r){let a=await n.mkdtemp(s.join(u.tmpdir(),"agent-device-ios-frame-perf-")),i=s.join(a,"animation-hitches.trace"),o=s.join(a,"hitches.xml"),l=s.join(a,"frame-lifetimes.xml"),d=s.join(a,"display-info.xml");try{let a=await i1({device:e,appBundleId:t,tracePath:i,template:"Animation Hitches",duration:"2s",targetPids:r.map(e=>e.pid),validateTraceOutput:!0,failureMessage:`Failed to record iOS frame-health sample for ${t}`});await i3(e,t,i,"hitches",o),await i3(e,t,i,"hitches-frame-lifetimes",l);let s=await i5(e,t,i,"device-display-info",d);return{windowStartedAt:a.startedAt,windowEndedAt:a.endedAt,hitchesXml:await n.readFile(o,"utf8"),frameLifetimesXml:await n.readFile(l,"utf8"),displayInfoXml:s?await n.readFile(d,"utf8"):void 0}}finally{await n.rm(a,{recursive:!0,force:!0}).catch(()=>{})}}async function i1(e){let{device:t,appBundleId:r,tracePath:a,template:i,duration:n}=e,s=e.allProcesses?["--all-processes"]:(e.targetPids??[]).flatMap(e=>["--attach",String(e)]),o=["xctrace","record","--template",i,"--device",t.id,...s,"--time-limit",n,"--output",a,"--quiet","--no-prompt"],l=await i2(o,e.tracePath);if(0===l.result.exitCode)return e.validateTraceOutput&&await i8(e,l.result.stdout,l.result.stderr),{startedAt:l.startedAt,endedAt:l.endedAt,capturedAtMs:l.capturedAtMs};throw new W("COMMAND_FAILED",e.failureMessage,{cmd:"xcrun",args:o,exitCode:l.result.exitCode,stdout:l.result.stdout,stderr:l.result.stderr,appBundleId:r,deviceId:t.id,hint:no(l.result.stdout,l.result.stderr)})}async function i2(e,t){let r;for(let a=1;a<=3;a+=1){a>1&&(await n.rm(t,{recursive:!0,force:!0}).catch(()=>{}),await new Promise(e=>setTimeout(e,1500)));let i=new Date().toISOString(),s=await Y("xcrun",e,{allowFailure:!0,timeoutMs:6e4});if(r={result:s,startedAt:i,endedAt:new Date().toISOString(),capturedAtMs:Date.now()},0===s.exitCode||!function(e){let t=`${e.stdout}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
`,i.appendFileSync(s,a,"utf8"),{ok:!0,data:{path:s,marked:!0}}}(t,r,a):"clear"===s?nD(n,r,a,o):"start"===s?nk(n,r,a):"stop"===s?nP(n,r,a):em("INVALID_ARGS",nv):em("INVALID_ARGS",nv)}async function nx(e,t,r){let a=r.resolveAppLogPath(t),i=await r_(e.device,e.appBundleId);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}async function nD(e,t,r,a){if(e.appLog&&!a)return em("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return em("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let i=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:rN(i)};e.appLog&&await rb(e.appLog);let n=rN(i),s=r.resolveAppLogPidPath(t);try{let a=await rI(e.device,e.appBundleId,i,s);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:i,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}}),{ok:!0,data:{...n,restarted:!0}}}catch(a){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:z(a)}}}async function nk(e,t,r){if(e.appLog)return em("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return em("INVALID_ARGS","logs start requires an app session; run open <app> first");let a=r.resolveAppLogPath(t),i=r.resolveAppLogPidPath(t);try{let n=await rI(e.device,e.appBundleId,a,i);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:a,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{path:a,started:!0}}}catch(e){return{ok:!1,error:z(e)}}}async function nP(e,t,r){if(!e.appLog)return em("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await rb(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function nR(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return em("SESSION_NOT_FOUND","network requires an active session");if(!eQ("network",i.device))return em("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!nS.includes(n))return em("INVALID_ARGS",nI);let s=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(s)||s<1||s>200)return em("INVALID_ARGS","network dump limit must be an integer in range 1..200");let o=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return em("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return nA.includes(a)?{ok:!0,include:a}:em("INVALID_ARGS",nb)}(t);if(!o.ok)return o;let{include:l}=o,d=await rv({device:i.device,appBundleId:i.appBundleId,appLogState:i.appLog?.getState(),appLogStartedAt:i.appLog?.startedAt,appLogPath:a.resolveAppLogPath(r),maxEntries:s,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...d.dump,active:!!i.appLog,state:i.appLog?.getState()??"inactive",backend:d.backend,notes:d.notes}}}let nL=/^[A-Z_][A-Z0-9_]*$/,nO=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-((?:[^}\\]|\\.)*))?\}/g,nE="AD_VAR_";function nC(e){return e.startsWith("AD_")}function n$(e){return new W("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function nT(e,t,r){return e.replace(nO,(e,a,i,n)=>{if(a)return"${";if(!i)return e;if(Object.prototype.hasOwnProperty.call(t.values,i))return t.values[i];if(void 0!==n)return n.replace(/\\(.)/g,"$1");throw new W("INVALID_ARGS",`Unresolved variable \${${i}} at ${r.file}:${r.line}.`)})}function nF(e,t,r){if(!e)return e;let a={...e};for(let[e,i]of Object.entries(a))"string"==typeof i&&(a[e]=nT(i,t,r));return a}let nU=new Set(["ios","android","macos","linux"]);function nV(e){let t=e.split(/\r?\n/),r={};for(let e=0;e<t.length;e+=1){let a=t[e].trim();if(0===a.length||a.startsWith("#"))continue;if(nG(a)){!function(e,t,r){let{key:a,value:i}=function(e,t){let r=e.slice(3).replace(/^[\s]+/,""),a=r.indexOf("=");if(a<=0)throw new W("INVALID_ARGS",`Invalid env directive on line ${t}: expected "env KEY=VALUE".`);let i=r.slice(0,a);if(!nL.test(i))throw new W("INVALID_ARGS",`Invalid env key "${i}" on line ${t}: keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(i.startsWith("AD_"))throw new W("INVALID_ARGS",`Invalid env key "${i}" on line ${t}: the AD_* namespace is reserved for built-in variables. Rename ${i} to avoid the AD_ prefix.`);return{key:i,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 W("INVALID_ARGS",`Invalid quoted env value on line ${t}.`)}return e}(r.slice(a+1),t)}}(t,r),n=e.env??{};if(Object.prototype.hasOwnProperty.call(n,a))throw new W("INVALID_ARGS",`Duplicate env directive "${a}" on line ${r}.`);n[a]=i,e.env=n}(r,a,e+1);continue}if(!a.startsWith("context "))break;let i=a.match(/(?:^|\s)platform=([^\s]+)/);if(i){let e=i[1];e&&nU.has(e)&&nj(r,"platform",e)}let n=a.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&nj(r,"timeoutMs",Math.floor(e))}let s=a.match(/(?:^|\s)retries=(\d+)/);if(s){let e=Number(s[1]);Number.isFinite(e)&&e>=0&&nj(r,"retries",Math.floor(e))}}return r}function nG(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function nj(e,t,r){let a=e[t];if(void 0!==a)throw new W("INVALID_ARGS",a===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(a)} vs ${String(r)}.`);e[t]=r}function nq(e){return!!e&&!Number.isNaN(Number(e))}let nH=/[*?[\]{}]/;async function nB(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:s,artifactsDir:o,runReplay:l,cleanupSession:d}=e;ep(i);let u=new Set,c=!1,f=l({filePath:r,sessionName:a,platform:s,requestId:i,artifactsDir:o,artifactPaths:u}).catch(e=>{let t=K(e);return em(t.code,t.message)}).finally(()=>{eK(i)});try{return"number"==typeof n?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{c=!0,eG(i),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(n,[...u]))},n)})]):await f}finally{t&&clearTimeout(t),c&&(await nK(f)||A({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await d(a)}catch(e){A({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:K(e).message}})}}}async function nK(e){return await Promise.race([e.then(()=>!0),h(2e3).then(()=>!1)])}async function nz(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:n}=e;if((t.positionals?.length??0)===0)return em("INVALID_ARGS","test requires at least one path or glob");try{var o,l,d,u,c,f;let e,p,m,h,g,w=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,n=r??process.cwd(),o=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let n=tK.expandHome(e,t);if(i.existsSync(n)){let t=i.statSync(n);if(t.isDirectory())return i.globSync("**/*.ad",{cwd:n}).map(e=>s.join(n,e));if(t.isFile()){if(".ad"!==s.extname(n))throw new W("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[n]}return[]}if(r=e,!nH.test(r)&&(a=n,!nH.test(a)))throw new W("INVALID_ARGS",`test input not found: ${e}`);let o=s.isAbsolute(n)?n:e;return i.globSync(o,{cwd:s.isAbsolute(n)?void 0:t}).map(e=>s.isAbsolute(e)?e:s.resolve(t,e)).filter(e=>".ad"===s.extname(e)&&function(e){try{return i.statSync(e).isFile()}catch{return!1}}(e))})(e,n)))].map(e=>s.normalize(e)).sort((e,t)=>e.localeCompare(t)),l=[];for(let e of o){var d,u;let t=nV(i.readFileSync(e,"utf8"));if(!a){l.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){l.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${a}`});continue}d=a,u=t.platform,("apple"===d?"apple"===u||"ios"===u||"macos"===u:u===d)&&l.push({kind:"run",path:e,metadata:t})}if(0===l.filter(e=>"run"===e.kind).length){let e=a?` for --platform ${a}`:"";throw new W("INVALID_ARGS",`No .ad tests matched${e}.`)}return l}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),y=(o=t.meta?.requestId,(o?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),v=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:a}=e,i=tK.expandHome(t??".agent-device/test-artifacts",r);return s.join(i,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),S=[],I=Date.now(),A=0;for(let e of w){if("skip"===e.kind){S.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}A+=1;let i=await nW({entry:e,sessionName:r,suiteInvocationId:y,caseIndex:A-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(l=t.flags?.timeoutMs,d=e.metadata.timeoutMs,"number"==typeof l?l:d),suiteArtifactsDir:v,runReplay:a,cleanupSession:n});if(S.push(i),t.flags?.failFast===!0)break}let b=(u=w.length,c=S,f=Date.now()-I,e=c.filter(e=>"passed"===e.status).length,m=(p=c.filter(e=>"failed"===e.status)).length,h=c.filter(e=>"skipped"===e.status).length,g=e+m,{total:u,executed:g,passed:e,failed:m,skipped:h,notRun:Math.max(0,u-g-h),durationMs:f,failures:p,tests:c});return{ok:!0,data:b}}catch(t){let e=K(t);return em(e.code,e.message)}}async function nW(e){var t,r;let a,n,{entry:o,sessionName:l,suiteInvocationId:d,caseIndex:u,cwd:c,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:g,cleanupSession:w}=e,y=Date.now(),v=s.join(h,(t=o.path,(0===(n=c?s.relative(c,t):s.basename(t)).length||n.startsWith("..")?s.basename(t):n).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),S="",I=0;for(let e=0;e<=p;e+=1){I=e+1;let t=function(e,t,r,a,i=0){let n=s.basename(r,s.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${n?`-${n}`:""}:attempt-${i+1}`}(l,d,o.path,u,e),n=s.join(v,`attempt-${I}`);r=o.path,i.mkdirSync(n,{recursive:!0}),i.copyFileSync(r,s.join(n,"replay.ad"));let c=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:n}=e;return eE(`${t??r}:test:${i+1}:${s.basename(a)}:attempt:${n+1}`,r)}({requestId:f,suiteInvocationId:d,filePath:o.path,caseIndex:u,attemptIndex:e}),h=await nB({filePath:o.path,sessionName:t,requestId:c,timeoutMs:m,platform:o.metadata.platform,artifactsDir:n,runReplay:g,cleanupSession:w});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:n,maxAttempts:o,attemptArtifactsDir:l}=e,d=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||d.push(t.error.logPath);let u=function(e,t){let r=[],a=new Map;for(let n of e){if(!function(e){try{return i.statSync(e).isFile()}catch{return!1}}(n))continue;let e=function(e,t){let r=s.extname(e),a=r?e.slice(0,-r.length):e,i=t.get(e)??0;return(t.set(e,i+1),0===i)?e:`${a}-${i+1}${r}`}(s.basename(n),a),o=s.join(t,e);s.resolve(n)!==s.resolve(o)&&i.copyFileSync(n,o),r.push(o)}return r}(d,l),c=[`file: ${r}`,`session: ${a}`,`attempt: ${n}/${o}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;c.push(`replayed: ${e}`,`healed: ${r}`)}else c.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&c.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&c.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&c.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&c.push("timeoutMode: cooperative");u.length>0&&c.push(`copiedArtifacts: ${u.map(e=>s.basename(e)).join(", ")}`);let f=s.join(l,"result.txt"),p=`${c.join("\n")}
|
|
12
|
-
`;i.writeFileSync(f,p),t.ok||i.writeFileSync(s.join(l,"failure.txt"),p)}({response:h,filePath:o.path,sessionName:t,attempts:I,maxAttempts:p+1,attemptArtifactsDir:n}),a=h,S=t,h.ok)break}let A=Date.now()-y;if(a?.ok)return{file:o.path,session:S,status:"passed",durationMs:A,attempts:I,artifactsDir:v,replayed:"number"==typeof a.data?.replayed?a.data.replayed:0,healed:"number"==typeof a.data?.healed?a.data.healed:0};let b=a?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:a?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:o.path,session:S,status:"failed",durationMs:A,attempts:I,artifactsDir:v,error:b}}function nJ(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=tu(r?e.slice(0,-1):e.slice());return!a||a.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:a.selectorExpression,selectorTimeout:r?t:null}}async function nZ(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(tL(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let n=i.get(r);if(!n)return null;let s=(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),tL(e.command)){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&t.push(e.positionals.join(" "))}if("fill"===e.command){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&Number.isNaN(Number(r))&&t.push(r)}if("get"===e.command){let r=e.positionals?.[1]??"";r&&!r.startsWith("@")&&t.push(e.positionals.slice(1).join(" "))}if("is"===e.command){let{split:r}=tp(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=nJ(e.positionals??[]);r&&t.push(r)}return tM(t).filter(e=>e.trim().length>0)})(t).map(e=>tm(e)).filter(e=>null!==e);if(0===s.length)return null;let o=tL(t.command)||"fill"===t.command,l=tL(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await nX(n,t,a,o,i);for(let e of s){let r=th(d.nodes,e,{platform:n.device.platform,requireRect:o,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=tw(r.node,n.device.platform,{action:tL(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tL(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=tN(t);if(!e)continue;return{...t,positionals:[a,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,a]}}if("is"===t.command){let{predicate:e,split:r}=tp(t.positionals);if(!e)continue;let i=r?.rest.join(" ").trim()??"",n=[e,a];return"text"===e&&i.length>0&&n.push(i),{...t,positionals:n}}if("wait"===t.command){let{selectorTimeout:e}=nJ(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function nX(e,t,r,a,i){let n=await er(e.device,"snapshot",[],t.flags?.out,{...eL(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),s=n?.nodes??[],o={nodes:tS(t.flags?.snapshotRaw?s:tv(s)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return ev(e,o),i.set(e.name,e),o}async function nY(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:o}=e,l=t.positionals?.[0];if(!l)return em("INVALID_ARGS","replay requires a path");let d="",u=new Set;try{var c;let e;d=tK.expandHome(l,t.meta?.cwd);let f=i.readFileSync(d,"utf8"),p=f.trimStart()[0];if("{"===p||"["===p)return em("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let m=nV(f),h=function(e){let t=[],r=[],a=e.split(/\r?\n/),i=!1;for(let e=0;e<a.length;e+=1){let n=a[e],s=n.trim();if(0===s.length||s.startsWith("#"))continue;if(nG(s)){if(i)throw new W("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=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,i=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!i)break;i="\\"===t&&!i,"\\"!==t&&(i=!1),a+=1}if(a>=e.length)throw new W("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=tq(r);return{positionals:i.positionals,flags:a,runtime:(t=i.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?i.flags:void 0}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n.runtime=e.runtime,n}if("runtime"===a){let e=tq(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tL(a)){let e=tj(a,i);if(Object.assign(n.flags,e.flags),0===e.positionals.length)return n;let t=e.positionals[0];if(t.startsWith("@"))return n.positionals=[t],e.positionals[1]&&(n.result={refLabel:e.positionals[1]}),n;let r=e.positionals[0],s=e.positionals[1];return nq(r)&&nq(s)&&e.positionals.length>=2?n.positionals=[r,s]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=tj(a,i);if(Object.assign(n.flags,e.flags),e.positionals.length<2)return n.positionals=e.positionals,n;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(n.positionals=[t,e.positionals.slice(2).join(" ")],n.result={refLabel:e.positionals[1]}):n.positionals=[t,e.positionals[1]],n):(n.positionals=[t,e.positionals.slice(1).join(" ")],n)}if("get"===a){if(i.length<2)return n.positionals=i,n;let e=i[0],t=i[1];return t.startsWith("@")?(n.positionals=[e,t],i[2]&&(n.result={refLabel:i[2]})):n.positionals=[e,i.slice(1).join(" ")],n}if("swipe"===a||"type"===a){let e=tj(a,i);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}if("record"===a){let e=[];for(let t=0;t<i.length;t+=1){let r=i[t];if("--hide-touches"===r){n.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(n.flags.fps=Math.floor(e)),t+=1;continue}if("--quality"===r&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(n.flags.quality=Math.floor(e)),t+=1;continue}e.push(r)}return n.positionals=e,n}if("screenshot"===a){let e=[];for(let t=0;t<i.length;t+=1){let r=i[t];if("--fullscreen"===r){n.flags.screenshotFullscreen=!0;continue}if("--max-size"===r){let e=i[t+1],r=void 0===e?NaN:Number(e);if(!Number.isInteger(r)||r<1)throw new W("INVALID_ARGS","screenshot --max-size requires a positive integer");n.flags.screenshotMaxSize=r,t+=1;continue}e.push(r)}return n.positionals=e,n}return n.positionals=i,n}(n);o&&(t.push(o),r.push(e+1),i=!0)}return{actions:t,actionLines:r}}(f),g=h.actions,w=h.actionLines;if(t.flags?.replayUpdate===!0&&m.env&&Object.keys(m.env).length>0)return em("INVALID_ARGS","replay -u does not yet preserve env directives. Temporarily remove the env lines, run replay -u, then restore them.");if(t.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(t.flags){for(let e of Object.values(t.flags))if("string"==typeof e&&e.includes("${"))return!0}if(t.runtime){for(let e of Object.values(t.runtime))if("string"==typeof e&&e.includes("${"))return!0}}return!1}(g))return em("INVALID_ARGS","replay -u does not yet preserve ${VAR} substitutions. Resolve or inline the variables before running with -u.");let y=function(e){let t={};if(e.builtins)for(let[r,a]of Object.entries(e.builtins))t[r]=a;for(let r of[e.fileEnv,e.shellEnv,e.cliEnv])if(r)for(let[e,a]of Object.entries(r)){if(nC(e))throw n$(e);t[e]=a}return{values:t}}({builtins:function(e){let{req:t,sessionName:r,metadata:a,resolvedPath:i}=e,n=t.flags??{},o=t.meta?.cwd??process.cwd(),l={AD_SESSION:r,AD_FILENAME:s.relative(o,i)||i},d=n.platform??a.platform;d&&(l.AD_PLATFORM=d);let u=n.device;"string"==typeof u&&u.length>0&&(l.AD_DEVICE=u);let c=n.artifactsDir;return"string"==typeof c&&c.length>0&&(l.AD_ARTIFACTS=c),l}({req:t,sessionName:r,metadata:m,resolvedPath:d}),fileEnv:m.env,shellEnv:function(e){let t={};for(let[r,a]of Object.entries(e)){if("string"!=typeof a||!r.startsWith(nE))continue;let e=r.slice(nE.length);0!==e.length&&nL.test(e)&&(nC(e)||(t[e]=a))}return t}(function(e){let t=e.flags?.replayShellEnv;if(t&&"object"==typeof t&&!Array.isArray(t)){let e={};for(let[r,a]of Object.entries(t))"string"==typeof a&&(e[r]=a);return e}return process.env}(t)),cliEnv:function(e){let t={};for(let r of e){let e=r.indexOf("=");if(e<=0)throw new W("INVALID_ARGS",`Invalid -e entry "${r}": expected KEY=VALUE.`);let a=r.slice(0,e);if(!nL.test(a))throw new W("INVALID_ARGS",`Invalid -e key "${a}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(nC(a))throw n$(a);t[a]=r.slice(e+1)}return t}((c=t,e=c.flags?.replayEnv,Array.isArray(e)?e.filter(e=>"string"==typeof e):[]))}),v=t.flags?.replayUpdate===!0,S=0;for(let e=0;e<g.length;e+=1){let i=g[e];if(!i||"replay"===i.command)continue;let s=await nQ({req:t,sessionName:r,action:i,scope:y,filePath:d,line:w[e]??0,invoke:o});if(s.ok){n1(s).forEach(e=>u.add(e));continue}if(!v)return n0(s,i,e,d,[...u]);let l=await nZ({action:i,sessionName:r,logPath:a,sessionStore:n});if(!l)return n0(s,i,e,d,[...u]);if(g[e]=l,!(s=await nQ({req:t,sessionName:r,action:l,scope:y,filePath:d,line:w[e]??0,invoke:o})).ok)return n0(s,l,e,d,[...u]);n1(s).forEach(e=>u.add(e)),S+=1}return v&&S>0&&function(e,t,r){let a=[];if(r){let e=r.device.kind?` kind=${r.device.kind}`:"",t=r.device.target?` target=${r.device.target}`:"";a.push(`context platform=${r.device.platform}${t} device=${tC(r.device.name)}${e} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tE(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tB(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(t$(r,tF));return tV(t,e.flags),t.join(" ")}if("record"===e.command)return tG(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tE(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),"number"==typeof e.flags?.screenshotMaxSize&&t.push("--max-size",String(e.flags.screenshotMaxSize)),t.join(" ")}for(let r of e.positionals??[])t.push(tE(r));return tU(t,e),t.join(" ")}(e));let n=`${a.join("\n")}
|
|
13
|
-
`,s=`${e}.tmp-${process.pid}-${Date.now()}`;i.writeFileSync(s,n),i.renameSync(s,e)}(d,g,n.get(r)),{ok:!0,data:{replayed:g.length,healed:S,session:r,artifactPaths:[...u]}}}catch(t){let e=K(t);return em(e.code,e.message,u.size>0?{artifactPaths:[...u]}:void 0)}}async function nQ(e){var t,r;let{req:a,sessionName:i,action:n,scope:s,filePath:o,line:l,invoke:d}=e,u=(t={file:o,line:l},{...n,positionals:(n.positionals??[]).map(e=>nT(e,s,t)),flags:nF(n.flags,s,t)??{},runtime:nF(n.runtime,s,t)});return await d({token:a.token,session:i,command:u.command,positionals:u.positionals??[],flags:(r=a.flags,td(r,{...u.flags??{}})),runtime:u.runtime,meta:a.meta})}function n0(e,t,r,a,i=[]){let n;if(e.ok)return e;let s=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${s} (${n=(t.positionals??[]).map(e=>tE(e)),[t.command,...n].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:a,step:s,action:t.command,positionals:t.positionals??[],artifactPaths:i}}}}function n1(e){if(!e.ok||!e.data)return[];let t=[];if("string"==typeof e.data.path&&t.push(e.data.path),"string"==typeof e.data.outPath&&t.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let r of e.data.artifacts){if(!r||"object"!=typeof r)continue;let e="string"==typeof r.localPath?r.localPath:void 0,a="string"==typeof r.path?r.path:void 0;e?t.push(e):a&&t.push(a)}return[...new Set(t.filter(e=>(function(e){try{return i.statSync(e).isFile()}catch{return!1}})(e)))]}async function n2(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await nY({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await nz({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:s,requestId:o,artifactsDir:l,artifactPaths:d})=>{let u=function(e){let{parentFlags:t,platform:r,artifactsDir:a}=e;return void 0===r&&void 0===a?t:{...t??{},...void 0!==r?{platform:r}:{},...void 0!==a?{artifactsDir:a}:{}}}({parentFlags:t.flags,platform:s,artifactsDir:l});return await nY({req:{...t,command:"replay",session:r,positionals:[e],flags:u,meta:o?{...t.meta??{},requestId:o}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),d&&n1(t).forEach(e=>d.add(e)),t}})},cleanupSession:async e=>{i.get(e)&&await ib({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let n8=new Set(["session_list","ensure-simulator","devices","apps"]),n3=new Set(["boot","appstate"]),n5=new Set(["perf","logs","network"]),n4=new Set(["replay","test"]);async function n6(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:s,recordPositionals:o,deriveNextSession:l}=e,d=i.get(r),u=t.flags??{},c=ad(n,d,u);if(c)return c;let f=await ap({session:d,flags:u,ensureReady:!0});if(!eQ(n,f))return em("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await er(f,n,s,t.flags?.out,{...eL(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,p,f):d;i.recordAction(e,{command:n,positionals:o??s,flags:t.flags??{},result:p??{}}),e!==d&&i.set(r,e)}return{ok:!0,data:p??{}}}async function n9(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),s=t.flags??{},o=ad("clipboard",n,s);if(o)return o;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return em("INVALID_ARGS","clipboard requires a subcommand: read or write");let d=await ap({session:n,flags:s,ensureReady:!0});if(!eQ("clipboard",d))return em("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let u=await er(d,"clipboard",t.positionals??[],t.flags?.out,{...eL(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function n7(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,androidAdbExecutor:s}=e;if(n8.has(t.command))return await iO({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await aH({req:t,sessionName:r,sessionStore:i});if(n3.has(t.command))return await iF({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await n9({req:t,sessionName:r,logPath:a,sessionStore:i});if("keyboard"===t.command){let e=i.get(r),n=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==n||"ios"!==e8((t.flags??{}).platform)?await n6({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):em("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(n5.has(t.command))return await n_({req:t,sessionName:r,sessionStore:i,androidAdbExecutor:s});if("install"===t.command||"reinstall"===t.command)return await iM({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?iN:i_});if("install_source"===t.command)return await ai({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await as({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),s=t.positionals?.[1]?.trim();return n&&s?await n6({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=e$(s,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tK.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,s]}):em("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await n6({req:t,sessionName:r,logPath:a,sessionStore:i,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await io(e.device,r,e.appBundleId,ii)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await iy({req:t,sessionName:r,logPath:a,sessionStore:i}):n4.has(t.command)?await n2({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await ix(t,r,n):"close"===t.command?await ib({req:t,sessionName:r,logPath:a,sessionStore:i}):null}async function se(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,s=t.command;if("find"!==s)return null;let o=t.positionals??[];if(0===o.length)return em("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:u,value:c,timeoutMs:f}=tb(o);if(!d)return em("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return em("INVALID_ARGS","find accepts only one of --first or --last");let p=await ej({req:t,sessionName:r,logPath:a,sessionStore:i});if(p)return p;let m=i.get(r);if(!m&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return em("SESSION_NOT_FOUND","No active session. Run open first.");let h=m?.device??await ew(t.flags??{});m||await eH(h);let g="role"!==l?d:void 0,w="click"===u||"focus"===u||"fill"===u||"type"===u,y=0,v=null,S=async()=>{let e=Date.now();if(v&&e-y<750&&!eW(m))return{nodes:v};let{snapshot:n}=await ex({device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:g}),s=n.nodes;return y=e,v=s,m&&(ev(m,n),i.set(r,m)),{nodes:s,truncated:n.truncated,backend:n.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:m,device:h,command:s,locator:l,query:d};if("wait"===u)return st(I,S,l,d,f);let{nodes:A}=await S(),b=tA(A,l,d,{requireRect:w});if(w&&b.matches.length>1)if(t.flags?.findFirst)b.matches=[b.matches[0]];else{if(!t.flags?.findLast){var _,N,M;let e;return _=b.matches,N=l,M=d,e=_.slice(0,8).map(e=>{let t=tf(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),em("AMBIGUOUS_MATCH",`find matched ${_.length} elements for ${N} "${M}". Use a more specific locator or selector.`,{locator:N,query:M,matches:_.length,candidates:e})}b.matches=[b.matches[b.matches.length-1]]}let x=b.matches[0]??null;if(!x)return em("COMMAND_FAILED","find did not match any element");let D="click"===u||"focus"===u||"fill"===u||"type"===u?tc(A,x)??x:x,k=`@${D.ref}`,P={node:x,resolvedNode:D,ref:k,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},R={exists:()=>sr(I),get_text:()=>sa(I,P),get_attrs:()=>si(I,P),click:()=>sn(I,P),fill:()=>ss(I,P,c),focus:()=>so(I,P),type:()=>sl(I,P,c)}[u];return R?R():null}async function st(e,t,r,a,i){let{req:n,sessionStore:s,session:o,command:l}=e,d=i??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(tA(e,r,a,{requireRect:!1}).matches[0])return o&&s.recordAction(o,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{found:!0,waitedMs:Date.now()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await J(300)}return em("COMMAND_FAILED","find wait timed out")}async function sr(e){let{req:t,sessionStore:r,session:a,command:i}=e;return a&&r.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function sa(e,t){let{req:r,sessionStore:a,session:i,command:n,device:s,logPath:o}=e,l=await eM({device:s,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eL(o,e,t,r)});return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function si(e,t){let{req:r,sessionStore:a,session:i,command:n}=e;return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function sn(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:s,command:o,locator:l,query:d}=e,u=await s({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?tI(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:d};return c&&(f.x=c.x,f.y=c.y),n&&i.recordAction(n,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:f}}async function ss(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:s,invoke:o,command:l}=e;if(!r)return em("INVALID_ARGS","find fill requires text");let d=await o({token:a.token,session:i,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return d.ok&&s&&n.recordAction(s,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),d}async function so(e,t){let{req:r,sessionStore:a,session:i,device:n,command:s,logPath:o}=e,l=t.node.rect?tI(t.node.rect):null;if(!l)return em("COMMAND_FAILED","matched element has no bounds");let d=await er(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eL(o,r.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:d??{ref:t.ref}}}async function sl(e,t,r){let{req:a,sessionStore:i,session:n,device:s,command:o,logPath:l}=e;if(!r)return em("INVALID_ARGS","find type requires text");let d=t.node.rect?tI(t.node.rect):null;if(!d)return em("COMMAND_FAILED","matched element has no bounds");await er(s,"focus",[String(d.x),String(d.y)],a.flags?.out,{...eL(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let u=await er(s,"type",[r],a.flags?.out,{...eL(l,a.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:o,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:u??{ref:t.ref}}}let sd=`
|
|
1
|
+
let e,t,r,n,a;import{__webpack_require__ as i}from"../rslib-runtime.js";import o,{createHash as s}from"node:crypto";import l,{existsSync as u,promises as d}from"node:fs";import c,{hostname as p}from"node:os";import f from"node:path";import m from"node:net";import{AsyncLocalStorage as h}from"node:async_hooks";import{XMLParser as w}from"fast-xml-parser";import g from"node:http";import{fileURLToPath as y,pathToFileURL as v}from"node:url";import"node:https";import{once as I}from"node:events";import{Transform as A}from"node:stream";import{pipeline as S}from"node:stream/promises";import b from"node:fs/promises";import{PNG as _}from"pngjs";import{setTimeout as N}from"node:timers/promises";import{parseAllDocuments as x}from"yaml";import{toAppErrorCode as M,asAppError as D,normalizeError as k,AppError as P}from"../9152.js";import{runCmdBackground as O,runCmdStreaming as E,runCmd as C,whichCmd as L,resolveExecutableOverridePath as R}from"../9818.js";import{withRetry as T,listAndroidDevices as $,classifyBootFailure as F,isEnvTruthy as U,streamAndroidLogcatWithAdb as G,writeAndroidClipboardText as V,openAndroidApp as j,closeAndroidApp as B,listAndroidApps as q,openAndroidDevice as H,androidDeviceForSerial as W,captureAndroidLogcatWithAdb as z,readAndroidClipboardText as K,formatAndroidInstalledPackageRequiredMessage as J,runAndroidAdb as X,resolveIosSimulatorDeviceSetPath as Z,dismissAndroidKeyboard as Y,resolveIosDeviceDeepLinkBundleId as Q,Deadline as ee,ensureAdb as et,bootFailureHint as er,getAndroidKeyboardState as en,parseSerialAllowlist as ea,retryWithPolicy as ei,getAndroidAppState as eo,classifyAndroidAppTarget as es,isAndroidInputMethodOwnedNode as el,resolveAndroidSerialAllowlist as eu,createAppResolutionCache as ed,isDeepLinkTarget as ec}from"../1769.js";import{readProcessStartTime as ep,trimRuntimeValue as ef,readProcessCommand as em,resolveRuntimeTransportHints as eh,isProcessGroupAlive as ew,isAgentDeviceDaemonProcess as eg,isProcessAlive as ey}from"../8656.js";import{withDiagnosticsScope as ev,getDiagnosticsMeta as eI,flushDiagnosticsToSessionFile as eA,withDiagnosticTimer as eS,emitDiagnostic as eb}from"../7599.js";import{readVersion as e_,findProjectRoot as eN}from"../9671.js";import{sleep as ex}from"../4829.js";import{resolveUserPath as eM}from"../3267.js";import{resolveDaemonCodeSignature as eD,DAEMON_COMMAND_GROUPS as ek,readLocationCoordinate as eP,PUBLIC_COMMANDS as eO,normalizeTenantId as eE,INTERACTION_COMMAND_CAPABILITIES as eC,resolveSessionIsolationMode as eL,parseTimeout as eR,appendScreenshotScriptFlags as eT,successText as e$,readScreenshotScriptFlag as eF,screenshotOptionsFromFlags as eU,requireLocationCoordinates as eG,parseWaitPositionals as eV,resolveDeployResultTarget as ej,screenshotFlagsFromOptions as eB,withSuccessText as eq,resolveDaemonPaths as eH,typeCommandDefinition as eW,INTERNAL_COMMANDS as ez,resolveDaemonServerMode as eK,resolveInstallFromSourceResultTarget as eJ,fillCommandCodec as eX,splitNonEmptyTrimmedLines as eZ,interactionTargetCodec as eY,SCREENSHOT_ACTION_FLAG_KEYS as eQ}from"../3572.js";import{withAndroidAdbProvider as e0,pullAndroidAdbFile as e1,resolveAndroidTextInjector as e2,resolveAndroidAdbProvider as e3,resolveAndroidAdbExecutor as e4}from"../9639.js";import{isScrollableType as e5}from"../2842.js";import{parseUiHierarchy as e8,ensureAndroidSnapshotHelper as e6,parseUiHierarchyTree as e9,captureAndroidSnapshotWithHelper as e7,parseAndroidSnapshotHelperManifest as te,androidUiNodes as tt,forgetAndroidSnapshotHelperInstall as tr,buildUiHierarchySnapshot as tn}from"../221.js";import{decodePng as ta,isSupportedPredicate as ti,evaluateIsPredicate as to,CAPTURE_COMMAND_CAPABILITIES as ts,isMacOsSettingSupported as tl,resolveRectCenter as tu,detectReactNativeOverlay as td,formatScrollEdgeMessage as tc,deriveMobileSnapshotHiddenContentHints as tp,SETTINGS_INVALID_ARGS_MESSAGE as tf,resolveReactNativeOverlayDismissTarget as tm,captureScrollEdgeState as th,normalizeSnapshotTree as tw,parseSessionSurface as tg,REACT_NATIVE_COMMAND_CAPABILITIES as ty,applyCommandDefaults as tv,createAgentDevice as tI,runScrollEdgePasses as tA,SELECTOR_COMMAND_CAPABILITIES as tS,getUnsupportedMacOsSettingMessage as tb,requireIntInRange as t_,SESSION_LIFECYCLE_COMMAND_CAPABILITIES as tN,parseDeviceRotation as tx,localCommandPolicy as tM,findMistargetedTypeRefToken as tD}from"../2151.js";import{snapshotPresentationOptionsFromFlags as tk,normalizeRef as tP,findNodeByRef as tO,buildSnapshotPresentationKey as tE,centerOfRect as tC,attachRefs as tL}from"../4057.js";import{materializeInstallablePath as tR,isTrustedInstallSourceUrl as tT}from"../989.js";import{splitSelectorFromArgs as t$,findNearestHittableAncestor as tF,extractNodeText as tU,extractNodeReadText as tG,tryParseSelectorChain as tV,findNodeByLabel as tj,resolveRefLabel as tB,splitIsSelectorArgs as tq,resolveSelectorChain as tH,buildSelectorChainForNode as tW,normalizeType as tz,pruneGroupNodes as tK}from"../940.js";import{findBestMatchesByLocator as tJ,parseFindArgs as tX}from"../7556.js";import{runBatch as tZ,mergeParentFlags as tY}from"../1231.js";import{assertResolvedAppsFilter as tQ}from"../1393.js";var t0={};i.r(t0),i.d(t0,{TM:()=>l6,installIosApp:()=>l7,installIosInstallablePath:()=>ut,YO:()=>uo,L5:()=>l5,IJ:()=>l8,TJ:()=>ua,J7:()=>ur,reinstallIosApp:()=>ue,resolveIosApp:()=>l4,kc:()=>lj,Cm:()=>ui,ap:()=>un});var t1={};i.r(t1),i.d(t1,{prepareIosInstallArtifact:()=>sQ});var t2={};i.r(t2),i.d(t2,{ensureBootedSimulator:()=>sJ,SA:()=>sZ,EB:()=>sz,N3:()=>sX});let t3=new Set,t4=new Map,t5="request_canceled",t8="request canceled";function t6(e,t){if("string"==typeof e&&e.length>0)return e;let r=("string"==typeof t?t:"number"==typeof t&&Number.isFinite(t)?String(t):"generated").trim().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,32)||"generated",n=Math.random().toString(36).slice(2,10);return`req:${r}:${process.pid}:${Date.now()}:${n}`}function t9(e){if(!e)return;!function(e){if(e.size<=5e4)return;let t=0;for(let r of e.keys()){if(t>=1e4)break;e.delete(r),t++}}(t4);let t=new AbortController;t4.set(e,t),t3.has(e)&&t.abort()}function t7(e){e&&(!function(e){if(e.size<=5e4)return;let t=0;for(let r of e){if(t>=1e4)break;e.delete(r),t++}}(t3),t3.add(e),t4.get(e)?.abort())}function re(e){e&&(t3.delete(e),t4.delete(e))}function rt(e){return!!e&&t3.has(e)}function rr(e){if(e)return t4.get(e)?.signal}function rn(){return new P("COMMAND_FAILED",t8,{reason:t5})}function ra(e){if(rt(e))throw rn()}function ri(e){return e instanceof P&&"COMMAND_FAILED"===e.code&&(e.details?.reason===t5||e.message===t8)}function ro(e,t=e=>e){let r=new h;return{resolve:n=>n?t(n):r.getStore()??e,run:async(e,n)=>e?await r.run(t(e),n):await n(),hasScope:()=>!!r.getStore()}}function rs(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}function rl(e,t){return{openBundle:async(t,r)=>{var n,a;let i;await e("open",(n=t,a=r,i=["-b",n],a&&i.push(a),i))},openTarget:async t=>{await e("open",[t])},readClipboard:async()=>{let t=await e("pbpaste",[],{allowFailure:!0});if(0!==t.exitCode)throw new P("COMMAND_FAILED","Failed to read macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return t.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")},writeClipboard:async t=>{let r=await e("pbcopy",[],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new P("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})},readDarkMode:async()=>{let t=await e("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==t.exitCode)throw new P("COMMAND_FAILED","Failed to read macOS appearance",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.trim().toLowerCase();if("true"===r)return!0;if("false"===r)return!1;throw new P("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${t.stdout.trim()}`)},setDarkMode:async t=>{let r=`tell application "System Events" to tell appearance preferences to set dark mode to ${t?"true":"false"}`,n=await e("osascript",["-e",r],{allowFailure:!0});if(0!==n.exitCode)throw new P("COMMAND_FAILED","Failed to set macOS appearance",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},listApps:async r=>await ru(e,t,r)}}async function ru(e,t,r){let n=["/Applications","/System/Applications",f.join(c.homedir(),"Applications")],a=new Set;for(let t of n){let r=await d.stat(t).catch(()=>null);if(!r?.isDirectory())continue;let n=await e("find",[t,"-maxdepth","4","-type","d","-name","*.app"],{allowFailure:!0});if(0===n.exitCode)for(let e of n.stdout.split("\n")){let t=e.trim();t&&a.add(t)}}return rs((await Promise.all(Array.from(a).map(async e=>{let r=await rd(e,t).catch(()=>({})),n=r.bundleId;return n?{bundleId:n,name:r.appName??f.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),r)}async function rd(e,t){for(let r of[f.join(e,"Contents","Info.plist"),f.join(e,"Info.plist")]){let e=await t(r),n=rc(e,"CFBundleIdentifier"),a=rc(e,"CFBundleDisplayName"),i=rc(e,"CFBundleName");if(n||a||i)return{bundleId:n,appName:a??i}}return{}}function rc(e,t){let r=e?.[t];return"string"==typeof r&&r.trim()?r.trim():void 0}let rp={runCommand:C,simctl:{run:async(e,t)=>await C("xcrun",["simctl",...e],t)},devicectl:{run:async(e,t)=>await C("xcrun",["devicectl",...e],t)},plist:{readJson:async e=>await rI(C,e)},macosHost:rl(C,async e=>await rI(C,e)),whichCommand:L},rf=ro(rp,function(e){return"function"==typeof e?rm({runCommand:e}):rm(e)});function rm(e={}){let t={...rp,...e},r=e.plist??{readJson:async e=>await rI(t.runCommand,e)};return{...t,simctl:e.simctl??{run:async(e,r)=>await t.runCommand("xcrun",["simctl",...e],r)},devicectl:e.devicectl??{run:async(e,r)=>await t.runCommand("xcrun",["devicectl",...e],r)},plist:r,macosHost:e.macosHost??rl(t.runCommand,async e=>await r.readJson(e))}}function rh(e){return rf.resolve(e)}async function rw(e,t){return await rf.run(e,t)}async function rg(e,t,r){return await rh().runCommand(e,t,r)}async function ry(e,t){let r=rh(),[n,...a]=e;return"simctl"===n?await (r.simctl?.run(a,t)??r.runCommand("xcrun",e,t)):"devicectl"===n?await (r.devicectl?.run(a,t)??r.runCommand("xcrun",e,t)):await rg("xcrun",e,t)}async function rv(e){return await rh().plist?.readJson(e)??null}async function rI(e,t){try{let r=await e("plutil",["-convert","json","-o","-",t],{allowFailure:!0});if(0!==r.exitCode||!r.stdout.trim())return null;return JSON.parse(r.stdout)}catch{return null}}function rA(e,t={}){let r=Z(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function rS(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:rA(t,{simulatorSetPath:e.simulatorSetPath})}let rb="If runner build products look stale or corrupted, run `pnpm clean:xcuitest` in a local checkout, or remove ~/.agent-device/ios-runner/derived, then retry.";function r_(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.message??""}`.toLowerCase();return!(t.includes("xcodebuild exited early")||t.includes("device is busy")&&t.includes("connecting"))&&!!(t.includes("runner did not accept connection")||t.includes("fetch failed")||t.includes("econnrefused")||t.includes("socket hang up"))}function rN(e){return!(e instanceof P)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function rx(e){let{port:t,endpoints:r,logPath:n,lastError:a}=e,i="Runner did not accept connection";return new P("COMMAND_FAILED",i,{port:t,endpoints:r,logPath:n,lastError:a?String(a):void 0,reason:F({error:a,message:i,context:{platform:"ios",phase:"connect"}}),hint:er("IOS_RUNNER_CONNECT_TIMEOUT")})}async function rM(e){var t,r;let n,{session:a,port:i,logPath:o}=e,s=await a.testPromise,l="Runner did not accept connection (xcodebuild exited early)",u=F({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new P("COMMAND_FAILED",l,{port:i,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:u,hint:(t=s.stdout,r=s.stderr,(n=`${l}
|
|
2
|
+
${t}
|
|
3
|
+
${r}`.toLowerCase()).includes("device is busy")&&n.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":`${er("IOS_RUNNER_CONNECT_TIMEOUT")} ${rb}`)})}function rD(e){return"interactionFrame"===e||"snapshot"===e||"screenshot"===e||"findText"===e||"querySelector"===e||"readText"===e||"alert"===e||"uptime"===e}function rk(e){if(rt(e))throw rn()}let rP=new Map;async function rO(e,t,r,n,a=45e3,i,o){let s=ee.fromTimeoutMs(a),{getEndpoints:l}=rC(e,t),{endpoints:u}=await l(s.remainingMs()),d=null,c=Math.max(1,Math.ceil(a/250));try{return await ei(async({deadline:s})=>{if(s?.isExpired())throw new P("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:a});if(i&&null!==i.child.exitCode&&void 0!==i.child.exitCode)throw await rM({session:i,port:t,logPath:n});let c=!1;if("device"===e.kind){let e=await l(s?.remainingMs());u=e.endpoints,c=e.cached}let p=c?u[0]:null,f=await rL(u,{command:r,port:t,timeoutMs:a,signal:o,attemptDeadline:s,onError:(t,r)=>{var n;d=r,"device"===e.kind&&t===p&&(n=e.id,rP.delete(n))}});if(f)return f;if("device"===e.kind&&c){var m;m=e.id,rP.delete(m),u=(await l(s?.remainingMs(),!0)).endpoints;let n=await rL(u,{command:r,port:t,timeoutMs:a,signal:o,attemptDeadline:s,onError:(e,t)=>{d=t}});if(n)return n}if(o?.aborted)throw rn();throw new P("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:u,lastError:d?String(d):void 0})},{maxAttempts:c,baseDelayMs:300,maxDelayMs:2e3,jitter:.2,shouldRetry:rN},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||ri(e))throw rn();d||(d=e)}if(o?.aborted)throw rn();if("simulator"===e.kind){let a=s.remainingMs();if(a<=0)throw rx({port:t,endpoints:u,logPath:n,lastError:d});let i=await rF(e,t,r,a,o);return new Response(i.body,{status:i.status})}throw rx({port:t,endpoints:u,logPath:n,lastError:d})}async function rE(e,t,r,n=45e3,a){if(a?.aborted)throw rn();let i=ee.fromTimeoutMs(n),{getEndpoints:o}=rC(e,t),{endpoints:s}=await o(i.remainingMs()),l=s[0];if(!l)throw new P("COMMAND_FAILED","Runner command endpoint not available",{port:t,endpoints:s});let u=i.remainingMs();if(u<=0)throw new P("COMMAND_FAILED","Runner command deadline exceeded",{timeoutMs:n});return await rT(l,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},u,a)}function rC(e,t){let r;return{getEndpoints:async(n,a=!1)=>{var i,o,s;let l,u=await rR({device:e,timeoutBudgetMs:n,forceRefresh:a,requestTunnelIp:r,setRequestTunnelIp:e=>{r=e}});return{endpoints:(i=e,o=t,s=u.ip,l=[`http://127.0.0.1:${o}/command`],"device"!==i.kind||s&&l.unshift(`http://[${s}]:${o}/command`),l),cached:u.sharedCacheHit}}}}async function rL(e,t){let{command:r,port:n,timeoutMs:a,signal:i,attemptDeadline:o,onError:s}=t;for(let t of e)try{let e=o?.remainingMs()??a;if(e<=0)throw new P("COMMAND_FAILED","Runner connection deadline exceeded",{port:n,timeoutMs:a});return await rT(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(2e4,e),i)}catch(e){if(i?.aborted||ri(e))throw rn();s(t,e)}return null}async function rR(e){var t,r,n;let{device:a,timeoutBudgetMs:i,forceRefresh:o,requestTunnelIp:s,setRequestTunnelIp:l}=e;if("device"!==a.kind)return{ip:null,sharedCacheHit:!1};if(!o){let e,r=(t=a.id,(e=rP.get(t))?e.expiresAt<=Date.now()?(rP.delete(t),null):e.ip:null);if(r)return{ip:r,sharedCacheHit:!0};if(void 0!==s)return{ip:s,sharedCacheHit:!1}}let u=await r$(a.id,i);return l(u),u&&(r=a.id,n=u,rP.set(r,{ip:n,expiresAt:Date.now()+3e4})),{ip:u,sharedCacheHit:!1}}async function rT(e,t,r,n){let a=AbortSignal.timeout(r),i=n?AbortSignal.any([n,a]):a;return await fetch(e,{...t,signal:i})}async function r$(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(1e4,t)):1e4,n=f.join(c.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),a=await ry(["devicectl","device","info","details","--device",e,"--json-output",n,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==a.exitCode||!l.existsSync(n))return null;let i=JSON.parse(l.readFileSync(n,"utf8"));if(i.info?.outcome&&"success"!==i.info.outcome)return null;let o=(i.result?.connectionProperties?.tunnelIPAddress??i.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{rB(n)}}async function rF(e,t,r,n,a){let i=JSON.stringify(r),o=rS(e,["spawn",e.id,"/usr/bin/curl","-s","-X","POST","-H","Content-Type: application/json","--data",i,`http://127.0.0.1:${t}/command`]),s=await ry(o,{allowFailure:!0,timeoutMs:n,signal:a}),l=s.stdout;if(0!==s.exitCode){let e=F({message:"Runner did not accept connection (simctl spawn)",stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});throw new P("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode,reason:e,hint:er(e)})}return{status:200,body:l}}async function rU(){return await new Promise((e,t)=>{let r=m.createServer();r.listen(0,"127.0.0.1",()=>{let n=r.address();if("object"==typeof n&&n?.port){let t=n.port;r.close(()=>e(t))}else r.close(()=>t(new P("COMMAND_FAILED","Failed to allocate port")))}),r.on("error",t)})}function rG(e,t,r,n){t&&rj(t,e),r&&rj(r,e),n&&process.stderr.write(e)}let rV=new Map;function rj(e,t){let r=(rV.get(e)??Promise.resolve()).catch(()=>{}).then(()=>l.promises.appendFile(e,t)).catch(()=>{}).finally(()=>{rV.get(e)===r&&rV.delete(e)});rV.set(e,r)}function rB(e){try{l.existsSync(e)&&l.unlinkSync(e)}catch{}}let rq=new h;async function rH(e,t,r){let n=rq.getStore()??[];if(n.some(r=>r.locks===e&&r.key===t))return await r();let a=(e.get(t)??Promise.resolve()).catch(()=>{}).then(()=>rq.run([...n,{locks:e,key:t}],r));return e.set(t,a),a.finally(()=>{e.get(t)===a&&e.delete(t)})}function rW(e){return"apple"===e||"ios"===e||"macos"===e}function rz(e,t){return!t||("apple"===t?rW(e):e===t)}function rK(e){let{simulatorSetPath:t,platform:r,target:n}=e;if(t&&"macos"!==r&&"desktop"!==n)return t}async function rJ(e,t,r={}){let n=e,a=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(n=n.filter(e=>rz(e.platform,t.platform))),t.target&&(n=n.filter(e=>(e.target??"mobile")===t.target)),t.udid){let e=n.find(e=>e.id===t.udid&&rW(e.platform));if(!e)throw new P("DEVICE_NOT_FOUND",`No Apple device with UDID ${t.udid}`);return e}if(t.serial){let e=n.find(e=>e.id===t.serial&&"android"===e.platform);if(!e)throw new P("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=a(t.deviceName),r=n.find(t=>a(t.name)===e);if(!r)throw new P("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===n.length)return n[0];if(0===n.length){var i;let e=r.simulatorSetPath;if(e&&(!(i=t.platform)||"apple"===i||"ios"===i))throw new P("DEVICE_NOT_FOUND","No devices found in the scoped simulator set",{simulatorSetPath:e,hint:`The simulator set at "${e}" appears to be empty. Create a simulator first:
|
|
4
|
+
xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new P("DEVICE_NOT_FOUND","No devices found",{selector:t})}let o=n.filter(e=>"device"!==e.kind);o.length>0&&(n=o);let s=n.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??n[0]}let rX=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function rZ(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new P("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:r});let n=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of n)if(!l.existsSync(e))throw new P("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of n)if(!await rY(e)){await rg("codesign",["--remove-signature",e],{allowFailure:!0});try{await rg("codesign",["--force","--sign","-",e])}catch(n){let t=n instanceof P?n:new P("COMMAND_FAILED",String(n));throw new P("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}async function rY(e){return 0===(await rg("codesign",["--verify","--deep","--strict",e],{allowFailure:!0})).exitCode}let rQ=null;function r0(e){return function e(t){if(!Array.isArray(t))return[];let r=[];for(let n of t)if(!(!n||"object"!=typeof n||Array.isArray(n)))for(let[t,a]of Object.entries(n))":@"!==t&&"#text"!==t&&r.push({name:t,attributes:function(e){if(!e||"object"!=typeof e||Array.isArray(e))return{};let t={};for(let[r,n]of Object.entries(e))"string"==typeof n&&(t[r]=n);return t}(n[":@"]),text:r2(a)??r2(n["#text"]),children:e(a)});return r}((rQ??=new w({ignoreAttributes:!1,attributeNamePrefix:"",preserveOrder:!0,trimValues:!0,parseTagValue:!1})).parse(e))}function r1(e,t){for(let r of e){if("dict"===r.name)for(let e=0;e<r.children.length-1;e+=1){let n=r.children[e],a=r.children[e+1];n?.name==="key"&&n.text&&a&&t(n.text,a)}r1(r.children,t)}}function r2(e){if("string"==typeof e){let t=e.trim();return t.length>0?t:null}if(!Array.isArray(e))return null;let t=e.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return null;let t=e["#text"];return"string"==typeof t?t.trim():null}).filter(e=>null!==e&&e.length>0).join("").trim();return t.length>0?t:null}let r3=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]);async function r4(e){var t;let r=await r5(e);if(!r||0===r.length)return null;let n=f.dirname(e),a=new Set,i=function(e,t){let r=[],n=new Set,a=[];for(let i of e){if(i.startsWith("__TESTHOST__/")){a.push(i.slice(13));continue}if(!i.startsWith("__TESTROOT__/"))continue;let e=i.slice(13);r.push(f.join(t,e));let o=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(e);o&&n.add(f.join(t,o))}return{testRootPaths:r,hostRoots:Array.from(n),hostRelativePaths:a}}(r,n);for(let e of i.testRootPaths){if(!l.existsSync(e))return null;a.add(e)}for(let e of(t=i).hostRelativePaths.map(e=>{let r=t.hostRoots.find(t=>l.existsSync(f.join(t,e)));return r?f.join(r,e):null})){if(!e)return null;a.add(e)}return Array.from(a)}async function r5(e){let t=await rv(e);if(t){var r,n,a,i=t;let e=new Set;for(let t of[a=i,...function(e){let t=e.TestConfigurations;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!r8(e))continue;let t=e.TestTargets;Array.isArray(t)&&r.push(...t.filter(r8))}return r}(a),...Object.values(a).filter(e=>r8(e)&&"TestBundlePath"in e)])for(let r of function(e){let t=new Set;for(let[r,n]of Object.entries(e))if(r3.has(r)){if("string"==typeof n){t.add(n);continue}if(Array.isArray(n))for(let e of n)"string"==typeof e&&t.add(e)}return Array.from(t)}(t))e.add(r);return Array.from(e)}if("darwin"===process.platform)return null;try{let t;return r=l.readFileSync(e,"utf8"),n=r0(r),t=new Set,r1(n,(e,r)=>{if(r3.has(e)){if("string"===r.name&&r.text)return void t.add(r.text);if("array"===r.name)for(let e of r.children)"string"===e.name&&e.text&&t.add(e.text)}}),Array.from(t)}catch{return null}}function r8(e){return!!e&&"object"==typeof e}let r6="XCTestDevices",r9=".agent-device-backup",r7=".agent-device-xctestdevices-backup-",ne=f.join(c.homedir(),".agent-device","ios-runner"),nt=".agent-device-runner-cache.json",nr={PreferredScreenCaptureFormat:"screenshots",SystemAttachmentLifetime:"keepNever",UserAttachmentLifetime:"keepNever"},nn=new Map,na=new Set;function ni(e){return e?.trim()??""}function no(e=process.env){return ni(e.AGENT_DEVICE_IOS_BUNDLE_ID)||ni(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function ns(e=process.env){let t=ni(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${no(e)}.uitests`}let nl=function(e=process.env){let t=no(e),r=ns(e);return Array.from(new Set([ni(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);function nu(e=c.homedir()){return f.join(e,"Library","Developer","XCTestDevices")}async function nd(e,t={}){if("ios"!==e.platform||"simulator"!==e.kind)return null;let r=Z(e.simulatorSetPath);if(!r)return null;let n=f.resolve(r),a=f.resolve(t.xctestDeviceSetPath??nu()),i=f.resolve(t.backupPath??function(e=nu()){return`${e}${r9}`}(a)),o=f.resolve(t.lockDirPath??function(e=c.homedir()){return f.join(e,".agent-device","xctest-device-set.lock")}()),s=t.ownerStartTime??ep(process.pid),u=await nf({lockDirPath:o,owner:{pid:t.ownerPid??process.pid,startTime:s,acquiredAtMs:t.nowMs??Date.now()}});try{if(nc({xctestDeviceSetPath:a,backupPath:i}),function(e,t){if(f.resolve(e)===f.resolve(t))return!0;try{return l.realpathSync.native(e)===l.realpathSync.native(t)}catch{return!1}}(n,a))return await u(),null;l.mkdirSync(n,{recursive:!0}),l.existsSync(a)&&l.renameSync(a,i),function(e){let{requestedSetPath:t,xctestDeviceSetPath:r}=e,n=f.dirname(r),a=f.join(n,`${r6}.agent-device-link-${process.pid}-${Date.now()}`);l.mkdirSync(n,{recursive:!0});try{l.symlinkSync(t,a,"dir"),l.renameSync(a,r)}catch(e){throw l.existsSync(a)&&np(a),e}}({requestedSetPath:n,xctestDeviceSetPath:a})}catch(e){throw nc({xctestDeviceSetPath:a,backupPath:i}),await u(),new P("COMMAND_FAILED","Failed to redirect XCTest device set path",{requestedSetPath:n,xctestDeviceSetPath:a,backupPath:i,error:String(e)})}let d=!1;return{release:async()=>{if(!d){d=!0;try{nc({xctestDeviceSetPath:a,backupPath:i})}finally{await u()}}}}}function nc(e){let{xctestDeviceSetPath:t,backupPath:r}=e,n=[r,...function(e){let t=f.dirname(e),r=f.basename(e).replace(r9,""),n=r===r6?r7:`${r}${r7}`;try{return l.readdirSync(t).filter(e=>e.startsWith(n)).sort().map(e=>f.join(t,e))}catch{return[]}}(r)],a=n.find(e=>l.existsSync(e)),i=l.existsSync(t)&&l.lstatSync(t).isSymbolicLink();if(a){if(i&&np(t),l.existsSync(t))if(!i)return void eb({level:"warn",phase:"ios_runner_xctest_device_set_restore_collision",data:{xctestDeviceSetPath:t,activeBackupPath:a}});else a!==r?l.rmSync(a,{recursive:!0,force:!0}):l.rmSync(r,{recursive:!0,force:!0});else l.mkdirSync(f.dirname(t),{recursive:!0}),l.renameSync(a,t);for(let e of n)e!==a&&l.existsSync(e)&&l.rmSync(e,{recursive:!0,force:!0});return}i&&(eb({level:"warn",phase:"ios_runner_xctest_device_set_orphaned_symlink",data:{xctestDeviceSetPath:t}}),np(t))}function np(e){!l.existsSync(e)||l.lstatSync(e).isSymbolicLink()&&l.unlinkSync(e)}async function nf(e){let{lockDirPath:t,owner:r}=e,n=f.join(t,"owner.json"),a=Date.now()+3e4;for(l.mkdirSync(f.dirname(t),{recursive:!0});Date.now()<a;)try{l.mkdirSync(t),function(e,t){let r=`${e}.${process.pid}.${Date.now()}.tmp`;l.writeFileSync(r,JSON.stringify(t),"utf8"),l.renameSync(r,e)}(n,r);let e=!1;return async()=>{e||(e=!0,l.rmSync(t,{recursive:!0,force:!0}))}}catch(e){if("EEXIST"!==e.code)throw e;if(function(e,t){let r=null;try{r=l.statSync(e)}catch{return!0}let n=function(e){try{return JSON.parse(l.readFileSync(e,"utf8"))}catch{return null}}(t);if(n){var a;return!(Number.isInteger((a=n).pid)&&!(a.pid<=0)&&ey(a.pid)&&(!a.startTime||ep(a.pid)===a.startTime))&&(l.rmSync(e,{recursive:!0,force:!0}),!0)}return!(Date.now()-r.mtimeMs<5e3)&&(l.rmSync(e,{recursive:!0,force:!0}),!0)}(t,n))continue;await ex(100)}throw new P("COMMAND_FAILED","Timed out waiting for XCTest device set lock",{lockDirPath:t})}async function nm(e,t){var r;let n,a=(r=e,(n=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?f.resolve(n):"macos"===r.platform?f.join(ne,"derived","macos"):"simulator"===r.kind?f.join(ne,"derived"):f.join(ne,"derived",r.kind)),i=eN();return await rH(nn,a,async()=>{let r=function(e,t=eN()){var r;let n;return{schemaVersion:1,packageVersion:e_(),runnerSourceFingerprint:function(e){let t=f.join(e,"ios-runner","AgentDeviceRunner"),r=function(e){if(!l.existsSync(e))return[];let t=[],r=[e];for(;r.length>0;){let e=r.pop();for(let i of l.readdirSync(e,{withFileTypes:!0})){var n,a;let o=f.join(e,i.name);if(i.isDirectory()){if("xcuserdata"===i.name)continue;r.push(o);continue}i.isFile()&&(n=i.name,a=o,"project.pbxproj"===n?a.includes(`${f.sep}.xcodeproj${f.sep}`):[".swift",".plist",".entitlements",".xctestplan",".xcconfig",".storyboard",".xib"].includes(f.extname(n)))&&t.push(o)}}return t.sort((e,t)=>e.localeCompare(t))}(t),n=function(e,t){let r=o.createHash("sha256");for(let n of t){let t=f.relative(e,n),a=l.statSync(n);r.update(t),r.update("\0"),r.update(String(a.size)),r.update("\0"),r.update(String(Math.trunc(a.mtimeMs))),r.update("\0")}return r.digest("hex")}(t,r),a=nS.get(t);if(a?.fileStatsFingerprint===n)return a.sourceFingerprint;let i=o.createHash("sha256");for(let e of r){let r=f.relative(t,e);i.update(r),i.update("\0"),i.update(l.readFileSync(e)),i.update("\0")}let s=i.digest("hex");return nS.set(t,{fileStatsFingerprint:n,sourceFingerprint:s}),s}(t),platformName:nE(e),deviceKind:e.kind,target:e.target??"phone",buildDestinationFamily:"macOS"===(n=nE(r=e))?`platform=macOS,arch=${nC()}`:"simulator"===r.kind?`generic/platform=${n} Simulator`:`generic/platform=${n}`,runnerBundleBuildSettings:nT(process.env),runnerSigningBuildSettings:nR(process.env,"device"===e.kind,e.platform),runnerPerformanceBuildSettings:n$()}}(e,i);U(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(nG("clean","forced_clean",{derived:a}),nF(a),nh(a));let n=await nU({derived:a,projectRoot:i,expectedCacheMetadata:r,findXctestrun:t=>nb(t,e),xctestrunReferencesProjectRoot:nN,resolveExistingXctestrunProductPaths:r4});if("reuse_ready"!==n.reason&&nG("rebuild",n.reason,{derived:a,xctestrunPath:n.xctestrunPath}),"reuse_ready"===n.reason)try{return await rZ(e,n.productPaths,n.xctestrunPath),nG("reuse","reuse_ready",{derived:a,xctestrunPath:n.xctestrunPath}),ng(a,nv(r,n.xctestrunPath,n.productPaths)),n.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof P))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&rX.has(t)}(e))throw e;nG("rebuild","repair_failed",{derived:a,xctestrunPath:n.xctestrunPath})}n.xctestrunPath&&(nF(a),nh(a));let s=f.join(i,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!l.existsSync(s))throw new P("COMMAND_FAILED","iOS runner project not found",{projectPath:s});await nO(e,s,a,t);let u=nb(a,e);if(!u)throw new P("COMMAND_FAILED","Failed to locate .xctestrun after build");let d=await r4(u);if(!d)throw new P("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:u});return await rZ(e,d,u),ng(a,nv(r,u,d)),nG("build","built_new",{derived:a,xctestrunPath:u}),u})}function nh(e){try{if(!l.existsSync(e))return;if("derived"!==f.basename(e))return void l.rmSync(e,{recursive:!0,force:!0});for(let r of l.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,nw.has(t)&&l.rmSync(f.join(e,r.name),{recursive:!0,force:!0})}}catch{}}let nw=new Set([nt,"Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function ng(e,t){l.mkdirSync(e,{recursive:!0}),l.writeFileSync(f.join(e,nt),`${JSON.stringify(t,null,2)}
|
|
5
|
+
`)}function ny(e){let{artifacts:t,...r}=e;return r}function nv(e,t,r){let n=function(e,t){let r=nA(e);if(null===r||0===t.length)return null;let n=[];for(let e of t){let t=nA(e);if(null===t)return null;n.push({path:e,mtimeMs:t})}return{xctestrunPath:e,xctestrunMtimeMs:r,productPaths:n}}(t,r);return n?{...e,artifacts:n}:e}function nI(e){return!(!e||"object"!=typeof e||Array.isArray(e))&&"string"==typeof e.path&&Number.isInteger(e.mtimeMs)}function nA(e){try{return Math.trunc(l.statSync(e).mtimeMs)}catch{return null}}let nS=new Map;function nb(e,t){if(!l.existsSync(e))return null;let r=[],n=[e];for(;n.length>0;){let e=n.pop();for(let t of l.readdirSync(e,{withFileTypes:!0})){let a=f.join(e,t.name);if(t.isDirectory()){n.push(a);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=l.statSync(a);r.push({path:a,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let n=n_(r.path,t)-n_(e.path,t);if(0!==n)return n}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)}function n_(e,t){var r;let n=0,a=e.toLowerCase();f.basename(a).startsWith("agentdevicerunner.env.")&&(n-=1e3),a.includes(`${f.sep}macos${f.sep}`)&&(n-=5e3);let i="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return i.preferred.length>0&&(i.preferred.some(e=>a.includes(e))?n+=2e3:n-=500),i.disallowed.some(e=>a.includes(e))&&(n-=2500),n}function nN(e,t){try{let r=l.readFileSync(e,"utf8"),n=new Set([t]);try{n.add(l.realpathSync(t))}catch{}for(let e of n)if(r.includes(e))return!0;return!1}catch{return!1}}async function nx(e,t,r){let n=f.dirname(e),a=r.replace(/[^a-zA-Z0-9._-]/g,"_"),i=f.join(n,`AgentDeviceRunner.env.${a}.json`),o=f.join(n,`AgentDeviceRunner.env.${a}.xctestrun`),s=await nM(e);return nk(s,e=>{var r,n;return r=e,n=t,void(r.EnvironmentVariables={...r.EnvironmentVariables??{},...n},r.UITestEnvironmentVariables={...r.UITestEnvironmentVariables??{},...n},r.UITargetAppEnvironmentVariables={...r.UITargetAppEnvironmentVariables??{},...n},r.TestingEnvironmentVariables={...r.TestingEnvironmentVariables??{},...n})}),nk(s,e=>Object.assign(e,nr),{requireTestBundlePath:!0}),await nD(s,i,o),{xctestrunPath:o,jsonPath:i}}async function nM(e){let t=await rg("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())throw new P("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:t.stderr});try{let e=JSON.parse(t.stdout);if(!e||"object"!=typeof e||Array.isArray(e))throw Error("Root must be an object");return e}catch(t){throw new P("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}}async function nD(e,t,r){l.writeFileSync(t,JSON.stringify(e,null,2));let n=await rg("plutil",["-convert","xml1","-o",r,t],{allowFailure:!0});if(0!==n.exitCode)throw new P("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:r,stderr:n.stderr})}function nk(e,t,r={}){let n=e.TestConfigurations;if(Array.isArray(n))for(let e of n)e&&"object"==typeof e&&function(e,t,r){if(Array.isArray(e))for(let n of e){let e=nP(n,r);e&&t(e)}}(e.TestTargets,t,r);for(let r of Object.values(e)){let e=nP(r,{requireTestBundlePath:!0});e&&t(e)}}function nP(e,t){return!e||"object"!=typeof e||Array.isArray(e)||t.requireTestBundlePath&&!e.TestBundlePath?null:e}async function nO(e,t,r,n){let a=nT(process.env),i=nR(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[],s=n$(),l=await nd(e);try{var u;let l;await E("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",nL(e),"1","-destination",(u=e,l=nE(u),"macOS"===l?`platform=macOS,arch=${nC()}`:"simulator"===u.kind?`platform=${l} Simulator,id=${u.id}`:`generic/platform=${l}`),"-derivedDataPath",r,...s,...a,...o,...i],{detached:!0,onSpawn:e=>{na.add(e),e.on("close",()=>{na.delete(e)})},onStdoutChunk:e=>{rG(e,n.logPath,n.traceLogPath,n.verbose)},onStderrChunk:e=>{rG(e,n.logPath,n.traceLogPath,n.verbose)}})}catch(i){let e,t,r=i instanceof P?i:new P("COMMAND_FAILED",String(i)),a=(e=r.details?JSON.stringify(r.details):"",((t=`${r.message}
|
|
6
|
+
${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0)??rb);throw new P("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:r.message,details:r.details,logPath:n.logPath,hint:a})}finally{await l?.release()}}function nE(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new P("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"macos"===e.platform?"macOS":"macos"===(t=e.target)||"desktop"===t?"macOS":"tv"===t?"tvOS":"iOS"}function nC(){return"arm64"===process.arch?"arm64":"x86_64"}function nL(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function nR(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let n=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",a=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",i=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return n&&o.push(`DEVELOPMENT_TEAM=${n}`),a&&o.push(`CODE_SIGN_IDENTITY=${a}`),i&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${i}`),o}function nT(e=process.env){let t=no(e),r=ns(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}function n$(){return["COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO"]}function nF(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()){var r;let t,n;if(r=e,t=f.resolve(eN(),".tmp"),""===(n=f.relative(t,f.resolve(r)))||n.startsWith("..")||f.isAbsolute(n))throw new P("COMMAND_FAILED","Refusing to clean AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH automatically",{derivedPath:e,hint:`Unset AGENT_DEVICE_IOS_CLEAN_DERIVED, or move AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH under a subdirectory of ${f.join(eN(),".tmp")}.`})}}async function nU(e){var t,r;let n,a=(t=e.derived,r=e.expectedCacheMetadata,(n=function(e){try{let t=JSON.parse(l.readFileSync(f.join(e,nt),"utf8"));if(!t||"object"!=typeof t||Array.isArray(t))return null;return t}catch{return null}}(t))?JSON.stringify(ny(n))!==JSON.stringify(ny(r))?{ok:!1,reason:"cache_metadata_mismatch"}:{ok:!0,metadata:n}:{ok:!1,reason:"cache_metadata_missing"}),i=a.ok?function(e){var t;let r=e?.artifacts;if(!(!(!(t=r)||"object"!=typeof t||Array.isArray(t))&&"string"==typeof t.xctestrunPath&&Number.isInteger(t.xctestrunMtimeMs)&&Array.isArray(t.productPaths)&&t.productPaths.length>0&&t.productPaths.every(nI))||nA(r.xctestrunPath)!==r.xctestrunMtimeMs)return null;let n=[];for(let e of r.productPaths){if(nA(e.path)!==e.mtimeMs)return null;n.push(e.path)}return{xctestrunPath:r.xctestrunPath,productPaths:n}}(a.metadata):null,o=i?.xctestrunPath??e.findXctestrun(e.derived);if(!o)return{reason:"missing_xctestrun",xctestrunPath:null};let s=i?.xctestrunPath===o?i.productPaths:await e.resolveExistingXctestrunProductPaths(o);return s?e.xctestrunReferencesProjectRoot(o,e.projectRoot)?a.ok?{reason:"reuse_ready",xctestrunPath:o,productPaths:s}:{reason:a.reason,xctestrunPath:o,productPaths:s}:{reason:"project_root_mismatch",xctestrunPath:o,productPaths:s}:{reason:"missing_products",xctestrunPath:o,productPaths:[]}}function nG(e,t,r){eb({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}let nV=new Map,nj=new Map;async function nB(e,t){return await rH(nj,e.id,async()=>{let r,n,a=nV.get(e.id);if(a){if(nX(a.child.pid))return eb({level:"debug",phase:"ios_runner_session_reuse",data:{deviceId:e.id,sessionId:a.sessionId,ready:a.ready}}),a;await n1({},"stop_stale_session",async()=>{await nW(e.id,a)})}let i={};await n1(i,"ensure_booted",async()=>{var t;await ("simulator"!==(t=e).kind?Promise.resolve():t.booted?(eb({level:"debug",phase:"ios_runner_startup_ensure_booted_skipped",data:{deviceId:t.id}}),Promise.resolve()):nY(t))}),t.cleanStaleBundles?await n1(i,"cleanup_stale_bundles",async()=>{await nq(e)}):(i.cleanup_stale_bundles=0,eb({level:"debug",phase:"ios_runner_startup_cleanup_stale_bundles_skipped"}));let o=await n1(i,"ensure_xctestrun",async()=>await nm(e,t)),s=await n1(i,"allocate_port",async()=>await rU()),{xctestrunPath:l,jsonPath:u}=await n1(i,"prepare_xctestrun_env",async()=>await nx(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`)),d=await n1(i,"simulator_set_redirect",async()=>await nd(e));try{({child:r,wait:n}=await n1(i,"launch_xcodebuild",()=>{let t;return O("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",nL(e),"1","-destination-timeout",String(20),"-xctestrun",l,"-destination",(t=nE(e),"macOS"===t?`platform=macOS,arch=${nC()}`:"simulator"===e.kind?`platform=${t} Simulator,id=${e.id}`:`platform=${t},id=${e.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(s)},detached:!0})}))}catch(e){throw await d?.release(),e}r.stdout?.on("data",e=>{rG(e,t.logPath,t.traceLogPath,t.verbose)}),r.stderr?.on("data",e=>{rG(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${s}:${Date.now()}`,device:e,deviceId:e.id,port:s,xctestrunPath:l,jsonPath:u,testPromise:n,child:r,ready:!1,startupTimings:i,simulatorSetRedirect:d??void 0};return nV.set(e.id,c),c})}async function nq(e){if("simulator"===e.kind)for(let t of nl){let r=await ry(rS(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==r.exitCode){let e=`${r.stdout}
|
|
7
|
+
${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found nothing")&&!e.includes("no such file")&&!e.includes("invalid device")&&!e.includes("could not find"))continue}}}async function nH(e,t){await rH(nj,e.deviceId,async()=>{nV.get(e.deviceId)===e&&(eb({level:"warn",phase:"ios_runner_session_invalidated",data:{deviceId:e.deviceId,sessionId:e.sessionId,reason:t}}),await nW(e.deviceId,e,{graceful:!1,waitTimeoutMs:1e3}))})}async function nW(e,t,r={}){let n=t??nV.get(e);if(n){var a;if(!1!==r.graceful)try{await rO(n.device,n.port,{command:"shutdown"},void 0,15e3)}catch{await nZ(n.child.pid,"SIGTERM")}else await nZ(n.child.pid,"SIGTERM");try{await Promise.race([n.testPromise,new Promise(e=>setTimeout(e,r.waitTimeoutMs??1e4))])}catch{}(a=n.child.pid)&&(nX(a)||ew(a))&&await nZ(n.child.pid,"SIGKILL"),rB(n.xctestrunPath),rB(n.jsonPath),await n.simulatorSetRedirect?.release(),nV.get(e)===n&&nV.delete(e)}}async function nz(e){await rH(nj,e,async()=>{await nW(e)})}async function nK(){let e=Array.from(nV.values()),t=Array.from(na);await Promise.allSettled(e.map(async e=>{await nZ(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await nZ(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await nZ(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await nZ(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await nZ(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await nZ(e.pid,"SIGKILL"),na.delete(e)})),await Promise.allSettled(e.map(async e=>{await e.simulatorSetRedirect?.release()}))}async function nJ(){await nK();let e=Array.from(nV.keys());await Promise.allSettled(e.map(async e=>{await nz(e)}));let t=Array.from(na);await Promise.allSettled(t.map(async e=>{try{await nZ(e.pid,"SIGTERM"),await nZ(e.pid,"SIGKILL")}finally{na.delete(e)}}))}function nX(e){return!!e&&ey(e)}async function nZ(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let r="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await rg("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function nY(e){await ry(rS(e,["bootstatus",e.id,"-b"]),{timeoutMs:45e3})}async function nQ(e,t,r,n,a,i){var o,s;if(o=t,s=r.command,o.startupTimingsReported||!o.startupTimings||(o.startupTimingsReported=!0,eb({level:"info",phase:"ios_runner_session_startup_timings",durationMs:Object.values(o.startupTimings).reduce((e,t)=>e+t,0),data:{command:s,sessionId:o.sessionId,ready:o.ready,timings:o.startupTimings}})),rD(r.command)){let o=await eS("ios_runner_command_send",async()=>await rO(e,t.port,r,n,a,t,i),{command:r.command,readOnly:!0,sessionReady:t.ready,timeoutMs:a});return await n0(o,t,n)}let l=ee.fromTimeoutMs(a),u=t.ready?Math.min(5e3,l.remainingMs()):Math.min(45e3,l.remainingMs()),d=await eS("ios_runner_readiness_preflight",async()=>await rO(e,t.port,{command:"uptime"},n,u,t,i),{command:r.command,sessionReady:t.ready,timeoutMs:u});await n0(d,t,n);let c=l.remainingMs();if(c<=0)throw new P("COMMAND_FAILED","Runner command deadline exceeded",{timeoutMs:a});let p=await eS("ios_runner_command_send",async()=>await rE(e,t.port,r,c,i),{command:r.command});return await n0(p,t,n)}async function n0(e,t,r){let n,a=await e.text();try{let e=JSON.parse(a);n=e&&"object"==typeof e?e:{}}catch{throw new P("COMMAND_FAILED","Invalid runner response",{text:a})}if(!n.ok){let e=n.error?.code;throw new P("string"==typeof e&&e.trim().length>0?M(e):"COMMAND_FAILED",("string"==typeof n.error?.message?n.error.message:void 0)??"Runner error",{runner:n,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r})}return(t.ready=!0,n.data&&"object"==typeof n.data&&!Array.isArray(n.data))?n.data:{}}async function n1(e,t,r){let n=Date.now();try{return await r()}finally{let r=Date.now()-n;e[t]=r,eb({level:"debug",phase:`ios_runner_startup_${t}`,durationMs:r})}}let n2=new h;function n3(e,t={}){return void 0!==n4(e,t)}function n4(e,t={}){let r=n2.getStore();return r&&r.deviceId===e.id&&(r.requestId?r.requestId===t.requestId:!t.requestId)?r:void 0}async function n5(e,t,r){if(!e)return await r();let n={provider:n8(e),deviceId:t.deviceId,requestId:t.requestId};return await n2.run(n,r)}function n8(e){return"function"==typeof e?{runCommand:e}:e}async function n6(e,t,r={}){if("ios"!==e.platform&&"macos"!==e.platform)throw new P("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new P("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);rk(r.requestId);let n=function(e,t,r,n={}){if(r)return n8(r);let a=n4(e,n);return a?n8(a.provider):n8(t)}(e,{runCommand:n9},void 0,{requestId:r.requestId});return rD(t.command)?T(()=>(rk(r.requestId),n.runCommand(e,t,r)),{shouldRetry:e=>(rk(r.requestId),r_(e))}):n.runCommand(e,t,r)}async function n9(e,t,r){let n;rk(r.requestId);let a=rr(r.requestId);try{let i=((n=await nB(e,r)).ready,45e3);return await nQ(e,n,t,r.logPath,i,a)}catch(o){let i=o instanceof P?o:new P("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===i.code&&"string"==typeof i.message&&i.message.includes("Runner did not accept connection")&&rN(i)&&n){rk(r.requestId),await nH(n,"runner_connect_failed_before_command_send"),n=await nB(e,{...r,cleanStaleBundles:!0});try{return await nQ(e,n,t,r.logPath,45e3,a)}catch(e){throw r_(e instanceof P?e:new P("COMMAND_FAILED",String(e)))&&await nH(n,"transport_error_after_retry_command_send"),e}}throw!n&&i.message.includes("Runner did not accept connection")&&await nz(e.id),n&&r_(i)&&await nH(n,"transport_error_after_command_send"),o}}function n7(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}let ae=["platform","device","udid","serial","out","verbose","metroHost","metroPort","bundleUrl","launchUrl","snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw",...eQ,"relaunch","saveScript","noRecord","fps","quality","hideTouches","count","intervalMs","delayMs","holdMs","jitterPx","doubleTap","clickButton","pauseMs","pattern"];function at(e){let t=e.result?.text;if("string"==typeof t&&t.trim().length>0)return t;let r=e.positionals??[];return 0===r.length?"":r[0].startsWith("@")?r.length>=3?r.slice(2).join(" ").trim():r.slice(1).join(" ").trim():!(r.length>=3)||Number.isNaN(Number(r[0]))||Number.isNaN(Number(r[1]))?r.slice(1).join(" ").trim():r.slice(2).join(" ").trim()}function ar(e){let t=new Set,r=[];for(let n of e)t.has(n)||(t.add(n),r.push(n));return r}let an=/^-?\d+(\.\d+)?$/,aa=/^[^\s"\\]+$/,ai=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),ao=new Map([["--count","count"],["--pause-ms","pauseMs"]]),as=new Map([["--delay-ms","delayMs"]]);function al(e){return"click"===e||"press"===e}function au(e){return al(e)||"longpress"===e}function ad(e){return"type"===e||"fill"===e}function ac(e){return af(e,am)}function ap(e){return JSON.stringify(e)}function af(e,t){return t(e)?e:ap(e)}function am(e){return ah(e)&&e.startsWith("@")||an.test(e)}function ah(e){return aa.test(e)}function aw(e,t){let r=t.flags??{};if(al(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}if("swipe"===t.command){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern);return}ad(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function ag(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",af(t.metroHost,ah)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",af(t.bundleUrl,ah)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",af(t.launchUrl,ah)))}function ay(e,t){let r=[],n={},a=al(e)?ai:"swipe"===e?ao:ad(e)?as:void 0;for(let i=0;i<t.length;i+=1){let o=t[i];if(al(e)&&"--double-tap"===o){n.doubleTap=!0;continue}if(al(e)&&"--button"===o&&i+1<t.length){let e=t[i+1];("primary"===e||"secondary"===e||"middle"===e)&&(n.clickButton=e),i+=1;continue}let s=a?.get(o);if(s&&i+1<t.length){let e=aI(t[i+1]);if(null!==e){n[s]=e,i+=1;continue}}if("swipe"===e&&"--pattern"===o&&i+1<t.length){let e=t[i+1];("one-way"===e||"ping-pong"===e)&&(n.pattern=e),i+=1;continue}r.push(o)}return{positionals:r,flags:n}}function av(e){let t=[],r={};for(let n=0;n<e.length;n+=1){let a=e[n];if("--platform"===a&&n+1<e.length){let t=e[n+1];("ios"===t||"android"===t)&&(r.platform=t),n+=1;continue}if("--metro-host"===a&&n+1<e.length){r.metroHost=e[n+1],n+=1;continue}if("--metro-port"===a&&n+1<e.length){let t=aI(e[n+1]);null!==t&&(r.metroPort=t),n+=1;continue}if("--bundle-url"===a&&n+1<e.length){r.bundleUrl=e[n+1],n+=1;continue}if("--launch-url"===a&&n+1<e.length){r.launchUrl=e[n+1],n+=1;continue}t.push(a)}return{positionals:t,flags:r}}function aI(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function aA(e,t={}){let r=[e.command];if("snapshot"===e.command)e.flags?.snapshotInteractiveOnly&&r.push("-i"),e.flags?.snapshotCompact&&r.push("-c"),"number"==typeof e.flags?.snapshotDepth&&r.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&r.push("-s",ac(e.flags.snapshotScope)),e.flags?.snapshotRaw&&r.push("--raw");else if("open"===e.command){for(let t of e.positionals??[])r.push(ac(t));e.flags?.relaunch&&r.push("--relaunch"),ag(r,e.runtime)}else if("runtime"===e.command)!function(e,t,r={}){let n=t.positionals??[];for(let t of r.includeAllPositionals?n:n.slice(0,1))e.push(af(t,ah));ag(e,t.flags)}(r,e,{includeAllPositionals:t.runtimeIncludeAllPositionals});else if("record"===e.command)!function(e,t){let[r,...n]=t.positionals??[];for(let t of(r&&e.push(af(r,ah)),n))e.push(ac(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),"number"==typeof t.flags?.quality&&e.push("--quality",String(t.flags.quality)),t.flags?.hideTouches&&e.push("--hide-touches")}(r,e);else if("screenshot"===e.command){for(let t of e.positionals??[])r.push(ac(t));eT(r,e.flags)}else{for(let t of e.positionals??[])r.push(ac(t));aw(r,e)}return r.join(" ")}class aS{sessionsDir;constructor(e){this.sessionsDir=e}write(e){let t;try{if(!e.recordSession)return{written:!1};t=this.resolveScriptPath(e);let r=f.dirname(t);l.existsSync(r)||l.mkdirSync(r,{recursive:!0});let n=function(e){var t=e,r=function(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let n=function(e){let t=function(e){let t=Array.isArray(e.result?.selectorChain)&&e.result.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];return t.length>0?t.join(" || "):void 0}(e);if(t&&ab(e.command))return al(e.command)?{...e,positionals:[t]}:"longpress"===e.command?function(e,t){let r="number"==typeof e.result?.durationMs?String(e.result.durationMs):function(e){let t=e.at(-1);if(!(e.length<=1)&&void 0!==t&&""!==t.trim())return Number.isFinite(Number(t))?t:void 0}(e.positionals??[]);return{...e,positionals:r?[t,r]:[t]}}(e,t):"fill"===e.command?function(e,t){let r=at(e);return r.length>0?{...e,positionals:[t,r]}:void 0}(e,t):function(e,t){let r=e.positionals?.[0];return"text"===r||"attrs"===r?{...e,positionals:[r,t]}:void 0}(e,t)}(r);if(n){t.push(n);continue}let a=function(e,t){if(!ab(t.command))return;let r=t.result?.refLabel;if("string"!=typeof r||0===r.trim().length)return;let n=r.trim();return{ts:t.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:n},result:{scope:n}}}(e,r);a&&t.push(a),t.push(r)}return t}(e);let n=[],a=t.device.kind?` kind=${t.device.kind}`:"";for(let e of(n.push(`context platform=${t.device.platform} device=${ap(t.device.name)}${a} theme=unknown`),r))e.flags?.noRecord||n.push(function(e){var t,r;let n=(t=[e.command],r=e,al(r.command)?function(e,t){let r=t.positionals?.[0];if(r){if(r.startsWith("@"))return e.push(ac(r)),a_(e,t),aw(e,t),e.join(" ");if(1===t.positionals.length)return e.push(ac(r)),aw(e,t),e.join(" ")}}(t,r):"fill"===r.command?function(e,t){let r=t.positionals?.[0];if(!r?.startsWith("@"))return;e.push(ac(r)),a_(e,t);let n=t.positionals.slice(1).join(" ");return t.positionals.length>1&&e.push(ac(n)),aw(e,t),e.join(" ")}(t,r):"get"===r.command?function(e,t){let r=t.positionals?.[0],n=t.positionals?.[1];if(r&&n)return e.push(ac(r)),e.push(ac(n)),n.startsWith("@")&&a_(e,t),e.join(" ")}(t,r):void 0);return n||aA(e)}(e));return`${n.join("\n")}
|
|
8
|
+
`}(e);return l.writeFileSync(t,n),{written:!0,path:t}}catch(r){return eb({level:"warn",phase:"session_script_write_failed",data:{session:e.name,path:t,error:r instanceof Error?r.message:String(r)}}),{written:!1}}}resolveScriptPath(e){if(e.saveScriptPath)return eM(e.saveScriptPath,{cwd:void 0});l.existsSync(this.sessionsDir)||l.mkdirSync(this.sessionsDir,{recursive:!0});let t=n7(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return f.join(this.sessionsDir,`${t}-${r}.ad`)}}function ab(e){return au(e)||"fill"===e||"get"===e}function a_(e,t){let r=t.result?.refLabel;"string"==typeof r&&r.trim().length>0&&e.push(ac(r))}class aN{sessions=new Map;runtimeHints=new Map;sessionsDir;scriptWriter;constructor(e){this.sessionsDir=e,this.scriptWriter=new aS(e)}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=eM(t.flags.saveScript,{cwd:void 0}))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let t={};for(let r of ae)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),eb({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){let t=this.scriptWriter.write(e);t.written&&eb({level:"info",phase:"session_script_written",data:{session:e.name,path:t.path}})}defaultTracePath(e){let t=n7(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return f.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return f.join(this.sessionsDir,n7(e),"app.log")}resolveAppLogPidPath(e){return f.join(this.sessionsDir,n7(e),"app-log.pid")}static expandHome(e,t){return eM(e,{cwd:t})}}let ax="app-log.pid";function aM(e){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t))return{pid:Number.parseInt(t,10)};try{let e=JSON.parse(t);if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}function aD(e,t){if(!e)return;let r=f.dirname(e);l.existsSync(r)||l.mkdirSync(r,{recursive:!0});let n={pid:t,startTime:ep(t)??void 0,command:em(t)??void 0};l.writeFileSync(e,`${JSON.stringify(n)}
|
|
9
|
+
`)}function ak(e){if(e&&l.existsSync(e))try{l.unlinkSync(e)}catch{}}async function aP(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}function aO(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],n="",a=n=>{(!(r.length>0)||r.some(e=>n.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(n,t.redactionPatterns))};return{onChunk:e=>{let t=`${n}${e}`.split("\n");for(let e of(n=t.pop()??"",t))a(`${e}
|
|
10
|
+
`)},flush:()=>{n&&(a(n),n="")}}}function aE(e,t,r){let n=e.stdout,a=e.stderr;return n&&a?(n.setEncoding("utf8"),a.setEncoding("utf8"),n.on("data",r.writer.onChunk),a.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(n=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),n({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}function aC(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new P("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function aL(e,t){let r=(await e4(W(e))(["shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function aR(e,t){var r,n;let a;aC(t);let i=await aL(e,t),o=e4(W(e)),s=await z(o,{lines:4e3,timeoutMs:3e3}).catch(()=>"");if(0===s.trim().length)return null;let l=function(e,t,r){let n=new Set;for(let a of(r&&n.add(r),e.split("\n")))if(a.includes(t))for(let e of function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=[RegExp(`\\bStart proc\\s+(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`\\b(\\d+):${r}(?:\\b|/)`,"i"),RegExp(`${r}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,"i"),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${r}`,"i")],a=[];for(let t of n){let r=t.exec(e),n=r?.[1];n&&/^\d+$/.test(n)&&a.push(n)}return a}(a,t))n.add(e);return[...n]}(s,t,i);if(0===l.length)return null;let u=(r=s,n=t,a=new Set(l),r.split("\n").filter(e=>{var t;let r;if(!e.trim())return!1;if(e.includes(n))return!0;let i=(t=e,r=/\(\s*(\d+)\)\s*:/.exec(t),r?.[1]??null);return!!i&&a.has(i)}).join("\n"));return 0===u.trim().length?null:{pid:i,text:u,recoveredPids:l}}async function aT(e,t,r,n,a){let i,o,s="recovering",l=!1,u=(async()=>{try{for(;!l;){let u=await aL(e,t);if(!u){s="recovering",await ex(1e3);continue}let d=e3(W(e)),c=G(d,{pid:u});i=c;let p=aO(r,{redactionPatterns:n});if(o=aE(c,r,{endStreamOnClose:!1,writer:p}),"number"==typeof c.pid&&aD(a,c.pid),s="active",await o,ak(a),i=void 0,o=void 0,l)break;s="recovering",await ex(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),ak(a)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:u,stop:async()=>{l=!0,i&&!i.killed&&i.kill("SIGINT"),o&&await aP(o),i&&!i.killed&&i.kill("SIGKILL"),await aP(u),ak(a)}}}function a$(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}"`}async function aF(e){let{deviceId:t,appBundleId:r,startedAt:n,simulatorSetPath:a}=e,i=rA(["spawn",t,"log","show","--style","compact","--info","--predicate",a$(r)],{simulatorSetPath:a});"number"==typeof n&&Number.isFinite(n)&&n>0?i.push("--start",`@${Math.floor(n/1e3)}`):i.push("--last","5m");let o=await ry(i,{allowFailure:!0,timeoutMs:4e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=o.stdout.split("\n").map(e=>e.trimEnd()).filter(e=>{let t=e.trim();return t.length>0&&!t.startsWith("Timestamp Ty Process[PID:TID]")});return 0===s.length?null:{text:`${s.join("\n")}
|
|
11
|
+
`,recoveredLineCount:s.length}}async function aU(e,t,r,n,a,i){return aj({backend:"ios-simulator",cmd:"xcrun",args:function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:n}=e;return rA(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",a$(r)],{simulatorSetPath:n})}({deviceId:e,appBundleId:t,simulatorSetPath:a}),stream:r,redactionPatterns:n,pidPath:i})}async function aG(e,t,r,n){return aj({backend:"macos",cmd:"log",args:["stream","--style","compact","--predicate",a$(e)],stream:t,redactionPatterns:r,pidPath:n})}async function aV(e,t,r,n){return aj({backend:"ios-device",cmd:"xcrun",args:["devicectl","device","log","stream","--device",e],stream:t,redactionPatterns:r,pidPath:n})}function aj(e){let t="active",r=O(e.cmd,e.args,{allowFailure:!0,captureOutput:!1});r.wait.catch(()=>{});let n=r.child,a=aO(e.stream,{redactionPatterns:e.redactionPatterns});"number"==typeof n.pid&&aD(e.pidPath,n.pid);let i=aE(n,e.stream,{endStreamOnClose:!0,writer:a}).then(r=>(0!==r.exitCode&&(t="failed"),ak(e.pidPath),r),r=>{throw t="failed",ak(e.pidPath),r});return{backend:e.backend,getState:()=>t,startedAt:Date.now(),wait:i,stop:async()=>{n.killed||n.kill("SIGINT"),await aP(i),n.killed||n.kill("SIGKILL"),await aP(i),ak(e.pidPath)}}}let aB=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),aq=/https?:\/\/[^\s"'<>\])]+/i,aH=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function aW(e,t,r=e.limits.maxEntries){let n=[...e.entries],a=new Set(n.map(e=>aK(e)));for(let e of t.entries){let t=aK(e);if(!a.has(t)&&(a.add(t),n.push(e),n.length>=r))break}return{...e,matchedLines:n.length,entries:n}}function az(e,t){let r=a4(t?.maxEntries,25,1,200),n=t?.backend,a=t?.include??"summary",i=a4(t?.maxPayloadChars,2048,64,16384),o=a4(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),u=s.slice(l),d=[];for(let e=u.length-1;e>=0&&d.length<r;e-=1){let t=u[e];if(!t?.trim())continue;let r=function(e,t,r,n,a,i){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let n=e.slice(t,r+1);try{let e=JSON.parse(n);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=a0(s,["method","httpMethod"]),u=a0(s,["url","requestUrl"]),d=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=aB.exec(o),p=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),f=(l??p?.[1]??c?.[1])?.toUpperCase(),m=aq.exec(o),h=u??m?.[0];if(!h)return null;let w=d??aX(o)??void 0;if(!(l||p?.[1]||c?.[1]||void 0!==w||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let g={method:f,url:h,status:w,timestamp:aZ(o),packetId:aY(o)??void 0,durationMs:aQ(o)??void 0,raw:a3(o,i),line:r};if("android"===n&&function(e,t,r){let n=aJ(t,r,5),a=e.packetId??n.map(e=>aY(e)).find(e=>"string"==typeof e&&e.length>0);a&&(e.packetId=a);let i=a?aJ(t,r,12).filter(e=>aY(e)===a):n;e.timestamp||(e.timestamp=i.map(e=>aZ(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=i.map(e=>aX(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=i.map(e=>aQ(e)).find(e=>"number"==typeof e))}(g,e,t),"headers"===a||"all"===a){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return a2(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(g.headers=a3(e,i))}if("body"===a||"all"===a){let e=a1(o,s,["requestBody","body","payload","request"]),t=a1(o,s,["responseBody","response"]);e&&(g.requestBody=a3(e,i)),t&&(g.responseBody=a3(t,i))}return g}(u,e,l+e+1,n,a,i);r&&d.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:u.length,matchedLines:d.length,entries:d,include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:o}}}function aK(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function aJ(e,t,r){let n=[],a=Math.max(0,t-r),i=Math.min(e.length-1,t+r);for(let t=a;t<=i;t+=1){let r=e[t]?.trim();r&&n.push(r)}return n}function aX(e){for(let t of aH){let r=t.exec(e);if(!r)continue;let n=Number.parseInt(r[1]??"",10);if(Number.isInteger(n))return n}return null}function aZ(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function aY(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function aQ(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function a0(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function a1(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return a2(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(n?.[1])return n[1].trim()}}function a2(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function a3(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function a4(e,t,r,n){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(n,e)):t}let a5={start:async e=>await ia(e)},a8=ro(a5,function(e={}){return{...a5,...e}});async function a6(e,t){return await a8.run(e,t)}function a9(e,t){let r=process.env[e];if(!r)return t;let n=Number.parseInt(r,10);return Number.isInteger(n)&&n>0?n:t}function a7(e){let t=f.dirname(e);l.existsSync(t)||l.mkdirSync(t,{recursive:!0}),function(e,t){if(l.existsSync(e)&&!(l.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,n=`${e}.${r}`;l.existsSync(t)&&(l.existsSync(n)&&l.unlinkSync(n),l.renameSync(t,n))}}(e,{maxBytes:a9("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:a9("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function ie(e){var t,r,n,a;let i,o,s,u,{device:d,appBundleId:c,appLogState:p,appLogStartedAt:f,appLogPath:m,maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y}=e,v="macos"===d.platform?"macos":"ios"===d.platform?"device"===d.kind?"ios-device":"ios-simulator":"android",I=(t={backend:v,maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y},i=a4(t?.maxEntries,25,1,200),o=t?.include??"summary",s=a4(t?.maxPayloadChars,2048,64,16384),u=a4(t?.maxScanLines,4e3,100,2e4),l.existsSync(m)?az(l.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:o,limits:{maxEntries:i,maxPayloadChars:s,maxScanLines:u}}),A=[],S=await it({device:d,appBundleId:c,appLogPath:m,appLogState:p});if(S){let e=await aR(d.id,c);if(e){let t=az(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y});t.entries.length>0&&(I=aW(t,I,h),A.push((r=S,n=e.recoveredPids,"stale-active"===r.reason?`Session app log stream was still bound to prior Android PID ${r.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${n.join(", ")}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${n.join(", ")}.`)))}}if("ios"===d.platform&&"simulator"===d.kind&&c&&0===I.entries.length){let e=await ii({deviceId:d.id,appBundleId:c,startedAt:f,simulatorSetPath:d.simulatorSetPath,appLogPath:m,maxEntries:h,include:w,maxPayloadChars:g,maxScanLines:y});e&&(e.dump.entries.length>0?(I=aW(e.dump,I,h),A.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&A.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===p?A.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==p&&0===A.length&&("ios"===d.platform&&"simulator"===d.kind?A.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):A.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===I.entries.length&&A.push("ios"===(a=d).platform&&"simulator"===a.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===a.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:v,dump:I,notes:A}}async function it(e){let{device:t,appBundleId:r,appLogPath:n,appLogState:a}=e;if("android"!==t.platform||!r)return null;if(void 0!==a&&"active"!==a)return{reason:"inactive"};if("active"!==a)return null;let i=function(e){let t=function(e){if(!e||!l.existsSync(e))return null;try{return aM(l.readFileSync(e,"utf8"))}catch{return null}}(e)?.command;if(!t)return null;let r=/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(t);return r?.[1]??null}(f.join(f.dirname(n),ax));if(!i)return null;let o=await aL(t.id,r);return o&&o!==i?{reason:"stale-active",trackedPid:i}:null}async function ir(e,t,r,n){return await a8.resolve(void 0).start({device:e,appBundleId:t,outPath:r,pidPath:n})}async function ia({device:e,appBundleId:t,outPath:r,pidPath:n}){a7(r);let a=l.createWriteStream(r,{flags:"a"}),i=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await aV(e.id,a,i,n):await aU(e.id,t,a,i,e.simulatorSetPath,n);if("android"===e.platform)return aC(t),await aT(e.id,t,a,i,n);if("macos"===e.platform)return await aG(t,a,i,n);throw a.end(),new P("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function ii(e){let t=await aF({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:az(t.text,{path:`${e.appLogPath} (simctl log show recovery)`,backend:"ios-simulator",maxEntries:e.maxEntries,include:e.include,maxPayloadChars:e.maxPayloadChars,maxScanLines:e.maxScanLines}),recoveredLineCount:t.recoveredLineCount}:null}async function io(e){await e.stop(),await aP(e.wait)}async function is(e,t){let r={},n=[];if(t||n.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let t=await X(e,["shell","echo","ok"],{allowFailure:!0,timeoutMs:1e3});r.adbAvailable=0===t.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await X(e,["shell","pidof",t],{allowFailure:!0,timeoutMs:1e3})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await ry(["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await ry(["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await C("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:n}}function il(e){let t=f.dirname(e),r=f.basename(e);l.existsSync(t)||l.mkdirSync(t,{recursive:!0}),l.existsSync(e)?l.truncateSync(e,0):l.writeFileSync(e,"","utf8");let n=0;for(let e of l.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let a=e.slice(r.length+1);if(/^\d+$/.test(a))try{l.unlinkSync(f.join(t,e)),n+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:n}}let iu=new Map;function id(e){let t=o.randomUUID(),r=setTimeout(()=>{ic(t)},9e5);return r.unref(),iu.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}function ic(e){let t=iu.get(e);if(t&&(clearTimeout(t.timer),iu.delete(e),t.deleteAfterDownload))try{l.rmSync(t.artifactPath,{force:!0})}catch{}}let ip=new Map;function im(e,t){let r=ip.get(e);if(!r)throw new P("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new P("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function ih(e){let t=ip.get(e);t&&(clearTimeout(t.timer),ip.delete(e),l.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function iw(e){let t=await ig(e);await C("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=f.join(e.tempDir,t);if(!l.existsSync(r))throw new P("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function ig(e){let t=await C("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new P("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new P("INVALID_ARGS","Uploaded app bundle archive is empty");let n=r.map(iy),a=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let n=[...r];if("ios"===t){let e=n.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new P("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new P("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===n.length)return n[0];throw new P("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${n.join(", ")}`)}(n,e.platform);if(!n.some(e=>e===a||e.startsWith(`${a}/`)))throw new P("INVALID_ARGS",`Uploaded archive must contain a top-level "${a}" bundle`);for(let e of n){var i=e,o=a;if(i!==o&&!i.startsWith(`${o}/`))throw new P("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${i}`)}for(let t of(await C("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new P("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return a}function iy(e){if(e.includes("\0"))throw new P("INVALID_ARGS",`Invalid archive entry: ${e}`);if(f.posix.isAbsolute(e))throw new P("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=f.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new P("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}function iv(e,t){return new Promise((r,n)=>{let a,i=!1,o=0,s=l.createWriteStream(t),u=e=>{if(!i){if(i=!0,a&&clearTimeout(a),e)return void iI(s,t).finally(()=>n(e));r()}},d=()=>{a&&clearTimeout(a),a=setTimeout(()=>{let t=new P("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:6e4});"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t),c.destroy(t),u(t)},6e4)},c=new A({transform(e,t,r){d();let n=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e,t);(o+=n)>0x80000000?r(new P("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")):r(null,e)}});e.on("aborted",()=>{u(new P("COMMAND_FAILED","Artifact transfer was interrupted"))}),d(),S(e,c,s).then(()=>u(),e=>u(e))})}async function iI(e,t){if(e.destroy(),!e.closed)try{await I(e,"close")}catch{}await l.promises.rm(t,{force:!0}).catch(()=>{})}async function iA(e){let t,r=e.headers["x-artifact-type"],n=e.headers["x-artifact-filename"];if(!r||!n)throw new P("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new P("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new P("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let a=function(e){let t=e.trim(),r=f.basename(t);if(!r||"."===r||".."===r)throw new P("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(n),i=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),l.mkdtempSync(f.join(c.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=f.join(i,a);return await iv(e,t),{artifactPath:t,tempDir:i}}let t=f.join(i,"artifact.tar");await iv(e,t);let n=await iw({archivePath:t,tempDir:i,platform:"ios",expectedRootName:a});return l.rmSync(t,{force:!0}),{artifactPath:n,tempDir:i}}catch(e){throw l.rmSync(i,{recursive:!0,force:!0}),e}}let iS=new Set(["agent_device.command","agent-device.command"]),ib=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),i_=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),iN={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},ix=new Set([...iS,...ib,...i_,...Object.keys(iN)]);function iM(e,t,r,n){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:n}}}function iD(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function ik(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function iP(e,t){let r="string"==typeof t.authorization?t.authorization:"",n=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,a="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??a??n??""}function iO(e,t){let r=e[t];return"string"==typeof r?r:void 0}function iE(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}function iC(e,t){let r="string"==typeof e[t]?e[t].trim():"";if(!r)throw new P("INVALID_ARGS",`Invalid params: source.${t} is required for github-actions-artifact sources`);return r}function iL(e,t){let r=e[t],n="number"==typeof r?r:"string"==typeof r?Number(r):NaN;if(!Number.isInteger(n))throw new P("INVALID_ARGS",`Invalid params: source.${t} must be an integer`);return n}async function iR(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=k(new P("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:iM(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=k(new P(M(r.code,"UNAUTHORIZED"),r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:iM(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=eE(r.tenantId);if(!e){let e=k(new P("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:iM(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function iT(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",n=f.isAbsolute(t)?t:f.resolve(t);try{e=await import(v(n).href)}catch(e){throw new P("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:n,error:e instanceof Error?e.message:String(e)})}let a=e[r];if("function"!=typeof a)throw new P("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:n,exportName:r});return a}async function i$(e){let t=await iT(),{handleRequest:r,token:n}=e;return g.createServer((e,a)=>{if("GET"===e.method&&"/health"===e.url){a.statusCode=200,a.setHeader("content-type","application/json"),a.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void iF(e,a,t,n);if("GET"===e.method&&e.url?.startsWith("/artifacts/"))return void iU(e,a,t,n);if("POST"!==e.method||"/rpc"!==e.url){a.statusCode=404,a.end("Not found");return}let i="";e.setEncoding("utf8"),e.on("data",t=>{(i+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{a.headersSent||iD(a,iM(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let n,o;try{n=JSON.parse(i)}catch{iD(a,iM(null,-32700,"Parse error"),400);return}if("2.0"!==n.jsonrpc||"string"!=typeof n.method)return void iD(a,iM(n.id??null,-32600,"Invalid Request"),400);if(!ix.has(n.method))return void iD(a,iM(n.id??null,-32601,`Method not found: ${n.method}`),404);if(!n.params||"object"!=typeof n.params)return void iD(a,iM(n.id??null,-32602,"Invalid params"),400);try{var s;let i=n.params,l=function(e,t,r){if(iS.has(e))return{token:iP(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(ib.has(e)){let e,n=iO(t,"platform");if("ios"!==n&&"android"!==n)throw new P("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:iP(t,r),session:iO(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:n},meta:{requestId:iO(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new P("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new P("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,n={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new P("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new P("INVALID_ARGS","Invalid params: source.headers values must be strings");n[e]=t}}return Object.keys(n).length>0?{kind:"url",url:e,headers:n}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new P("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}if("github-actions-artifact"===t.kind)return function(e){let t,r=iC(e,"owner"),n=iC(e,"repo"),a=void 0!==e.artifactId,i=void 0!==e.runId,o=void 0!==e.artifactName;if(a&&(i||o))throw new P("INVALID_ARGS","Invalid params: source must specify either artifactId or artifactName, not both");if(!a&&i&&!o)throw new P("INVALID_ARGS","Invalid params: source.artifactName is required when source.runId is specified");if(!a&&!o)throw new P("INVALID_ARGS","Invalid params: source must specify artifactId or artifactName");return a?{kind:"github-actions-artifact",owner:r,repo:n,artifactId:iL(e,"artifactId")}:(i&&(t=iL(e,"runId")),{kind:"github-actions-artifact",owner:r,repo:n,...i?{runId:t}:{},artifactName:iC(e,"artifactName")})}(t);throw new P("INVALID_ARGS",'Invalid params: source.kind must be "url", "path", or "github-actions-artifact"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:iE(t,"retentionMs")}}}if(i_.has(e)){let e=iO(t,"materializationId")?.trim();if(!e)throw new P("INVALID_ARGS","Invalid params: materializationId is required");return{token:iP(t,r),session:iO(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:iO(t,"requestId"),materializationId:e}}}let n=iN[e];if(n)return{token:iP(t,r),session:iO(t,"session")??"default",command:n,positionals:[],meta:{tenantId:iO(t,"tenantId")??iO(t,"tenant"),runId:iO(t,"runId"),leaseId:iO(t,"leaseId"),leaseTtlMs:iE(t,"ttlMs"),leaseBackend:iO(t,"backend")}};throw new P("INVALID_ARGS",`Method not found: ${e}`)}(n.method,i,e.headers);if(s=n.method,iS.has(s)&&("string"!=typeof l.command||0===l.command.length))return void iD(a,iM(n.id??null,-32602,"Invalid params: command is required"),400);o=t6(l.meta?.requestId,n.id),l.meta={...l.meta,requestId:o},t9(o);let u=()=>{a.writableFinished||t7(o)};e.on("aborted",u),a.on("close",u);let d=await iR(t,{headers:e.headers,rpcRequest:n,daemonRequest:l});if(!d.ok)return void iD(a,d.response,d.statusCode);d.tenantId&&(l.meta={...l.meta,tenantId:d.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void iD(a,{jsonrpc:"2.0",id:n.id??null,result:c});iD(a,iM(n.id??null,-32e3,c.error.message,c.error),ik(c.error.code))}catch(t){let e=k(t);iD(a,iM(n.id??null,-32e3,e.message,e),ik(e.code))}finally{re(o)}})})}async function iF(e,t,r,n){try{var a;let i,s,l=iP({},e.headers),u=iG(l,n);if(u){t.statusCode=ik(u.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.message,code:u.code}));return}let d=await iR(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let c=await iA(e),p=(a={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:d.tenantId},i=o.randomUUID(),(s=setTimeout(()=>{ih(i)},3e5)).unref(),ip.set(i,{artifactPath:a.artifactPath,tempDir:a.tempDir,tenantId:a.tenantId,timer:s}),i);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:p}))}catch(r){let e=k(r);t.statusCode=ik(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function iU(e,t,r,n){let a=e.url?.slice("/artifacts/".length)??"";if(!a){t.statusCode=400,t.end("Missing artifact id");return}try{let i=iP({},e.headers),o=iG(i,n);if(o){t.statusCode=ik(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let s=await iR(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:i,session:"default",command:"download_artifact",positionals:[a]}});if(!s.ok){t.statusCode=s.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.response.error?.data?.message??s.response.error?.message??"Unauthorized"}));return}let u=function(e,t){let r=iu.get(e);if(!r)throw new P("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new P("UNAUTHORIZED","Artifact belongs to a different tenant");if(!l.existsSync(r.artifactPath))throw ic(e),new P("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(a,s.tenantId),d=l.createReadStream(u.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),u.fileName&&t.setHeader("content-disposition",`attachment; filename="${u.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=k(e);t.statusCode=ik(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&ic(a)}),d.pipe(t)}catch(r){let e=k(r);t.statusCode=ik(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function iG(e,t){return t&&e!==t?k(new P("UNAUTHORIZED","Invalid token")):null}function iV(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function ij(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function iB(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";if("ios-instance"===t||"android-instance"===t)return t;throw new P("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class iq{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=iB(e.backend),r=eE(e.tenantId);if(!r)throw new P("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let n=iV(e.runId);if(!n)throw new P("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let a=this.resolveLeaseTtlMs(e.ttlMs),i=this.bindingKey(r,n,t),s=this.runBindings.get(i);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,a);this.runBindings.delete(i)}this.enforceCapacity(t);let l=this.now(),u={leaseId:o.randomBytes(16).toString("hex"),tenantId:r,runId:n,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+a};return this.leases.set(u.leaseId,u),this.runBindings.set(i,u.leaseId),{...u}}heartbeatLease(e){let t=ij(e.leaseId);if(!t)throw new P("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new P("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let n=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,n)}releaseLease(e){let t=ij(e.leaseId);if(!t)throw new P("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=iB(e.backend),r=eE(e.tenantId);if(!r)throw new P("INVALID_ARGS","tenant isolation requires tenant id.");let n=iV(e.runId);if(!n)throw new P("INVALID_ARGS","tenant isolation requires run id.");let a=ij(e.leaseId);if(!a)throw new P("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let i=this.leases.get(a);if(!i)throw new P("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(i.backend!==t||i.tenantId!==r||i.runId!==n)throw new P("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}cleanupExpiredLeases(){let e=this.now();for(let t of this.leases.values())t.expiresAt>e||(this.leases.delete(t.leaseId),this.runBindings.delete(this.bindingKey(t.tenantId,t.runId,t.backend)))}enforceCapacity(e){if("ios-simulator"!==e||this.maxActiveSimulatorLeases<=0)return;let t=Array.from(this.leases.values()).filter(e=>"ios-simulator"===e.backend).length;if(!(t<this.maxActiveSimulatorLeases))throw new P("COMMAND_FAILED","No simulator lease capacity available",{reason:"LEASE_CAPACITY_EXCEEDED",activeLeases:t,maxActiveLeases:this.maxActiveSimulatorLeases,backend:e,hint:"Retry after releasing another simulator lease."})}resolveLeaseTtlMs(e){if(!Number.isInteger(e))return this.defaultLeaseTtlMs;let t=Number(e);if(t<this.minLeaseTtlMs||t>this.maxLeaseTtlMs)throw new P("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),n={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(n.leaseId,n),this.runBindings.set(this.bindingKey(n.tenantId,n.runId,n.backend),n.leaseId),{...n}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let n=eE(t),a=iV(r);if(t&&!n)throw new P("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!a)throw new P("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(n&&e.tenantId!==n||a&&e.runId!==a)throw new P("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}function iH(){return{platform:"macos",id:"host-macos-local",name:c.hostname(),kind:"device",target:"desktop",booted:!0}}async function iW(){return[iH()]}let iz=/^(iphone|ipad|ipod|appletv)/i,iK=/\b(iphone|ipad|ipod)\b/i,iJ=/^appletv/i,iX=["apple tv","appletv","tvos"],iZ=/^==\s*(.+?)\s*==$/,iY=/^(?<name>.+?)\s+\[(?<id>[^[\]]+)\]\s*$/;function iQ(e){return(e??"").trim().toLowerCase()}function i0(e){return iQ(e.hardwareProperties?.platform)}function i1(e){return e.includes("tvos")}function i2(e){let t=iQ(e);return iX.some(e=>t.includes(e))}function i3(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function i4(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function i5(e={}){let t,r,n=Z(e.simulatorSetPath),a=e.target;try{t=await ry(rA(["list","devices","-j"],{simulatorSetPath:n}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let i=i8(r,n),o=null,s=null,l=null;for(let e of i)a&&e.target!==a||(e.booted&&(o=o??e),"mobile"===e.target&&(s=s??e),l=l??e);return o??s??l}function i8(e,t){let r=[];for(let[n,a]of Object.entries(e.devices))if(function(e){let t=iQ(e);return t.includes("ios")||t.includes("tvos")}(n))for(let e of a)e.isAvailable&&r.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:i1(iQ(n))?"tv":"mobile",booted:"Booted"===e.state,...t?{simulatorSetPath:t}:{}});return r}function i6(e,t){let r=new Set(e.map(e=>e.id)),n=[...e];for(let e of t)r.has(e.id)||(r.add(e.id),n.push(e));return n}async function i9(){let e=null;try{e=f.join(c.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let t=await ry(["devicectl","list","devices","--json-output",e],{allowFailure:!0,timeoutMs:8e3});if(0!==t.exitCode)return[];let r=await d.readFile(e,"utf8");return function(e){let t=[];for(let r of e.result?.devices??[]){if(!function(e){var t;let r=i0(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=i4(e),!!iz.test(t.trim())||i3(e).some(i2))}(r))continue;let e=r.hardwareProperties?.udid??r.identifier??"",n=r.name??r.deviceProperties?.name??e;e&&t.push({platform:"ios",id:e,name:n,kind:"device",target:function(e){var t;return i1(i0(e))?"tv":(t=i4(e),iJ.test(t.trim())||i3(e).some(i2))?"tv":"mobile"}(r),booted:!0})}return t}(JSON.parse(r))}catch{return[]}finally{e&&await d.rm(e,{force:!0}).catch(()=>{})}}async function i7(){try{let e=await ry(["xctrace","list","devices"],{allowFailure:!0});if(0!==e.exitCode)return[];return function(e){let t=[],r=null;for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e)continue;let a=iZ.exec(e);if(a){r=a[1]?.trim()??null;continue}if("Devices"!==r)continue;let i=iY.exec(e),o=i?.groups?.id?.trim()??"",s=i?.groups?.name?.trim()??"";if(!o||!s)continue;let l=function(e){return i2(e)?"tv":iK.test(e.trim())?"mobile":null}(s);l&&t.push({platform:"ios",id:o,name:s,kind:"device",target:l,booted:!0})}return t}(e.stdout)}catch{return[]}}async function oe(e={}){if("darwin"!==process.platform)throw new P("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await rh().whichCommand("xcrun"))throw new P("TOOL_MISSING","xcrun not found in PATH");let t=Z(e.simulatorSetPath),r=await ry(rA(["list","devices","-j"],{simulatorSetPath:t})),n=[];try{let e=JSON.parse(r.stdout);n=i8(e,t)}catch(e){throw new P("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(n.push(iH()),e.udid&&n.some(t=>"ios"===t.platform&&t.id===e.udid)||t)return n;let[a,i]=await Promise.all([i9(),i7()]);return n=i6(n,a),i6(n,i)}async function ot(){return"linux"!==process.platform?[]:[{platform:"linux",id:"local",name:p(),kind:"device",target:"desktop",booted:!0}]}let or=new h,on=new h;async function oa(e,t,r){var n,a;let i=await oi(e,t,r);if(n=t,a=i,!oo(n)&&(!n.platform||"apple"===n.platform||"ios"===n.platform)&&"desktop"!==n.target&&(!a||"device"===a.kind)){let e=await i5({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(i)return i;throw new P("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function oi(e,t,r){try{return await rJ(e,t,r)}catch(e){var n;if(n=e,!oo(t)&&n instanceof P&&"DEVICE_NOT_FOUND"===n.code)return;throw e}}function oo(e){return!!(e.udid||e.serial||e.deviceName)}async function os(e){let t=e.platform,r=rK({simulatorSetPath:Z(e.iosSimulatorDeviceSet),platform:t,target:e.target}),n=eu(e.androidDeviceAllowlist),a=function(e){let{flags:t,normalizedPlatform:r,iosSimulatorSetPath:n,androidSerialAllowlist:a}=e;return JSON.stringify({platform:r,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorSetPath:n,androidSerialAllowlist:a?Array.from(a).sort():void 0})}({flags:e,normalizedPlatform:t,iosSimulatorSetPath:r,androidSerialAllowlist:n}),i={platform:t,target:e.target,cacheHit:!1};return await eS("resolve_target_device",async()=>{let o=function(e){let t=or.getStore(),r=t?.get(e);if(r)return{...r}}(a);if(o)return i.cacheHit=!0,o;let s={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(s.target&&!s.platform)throw new P("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|linux|apple with --target mobile|tv|desktop.");let l=await op({...s,iosSimulatorSetPath:r,androidSerialAllowlist:n?Array.from(n).sort():void 0});if(l)return om(s)?oh(a,await oa(l,s,{simulatorSetPath:r})):oh(a,await rJ(l,s,{simulatorSetPath:r}));"android"===s.platform&&await et();let u=await of({...s,iosSimulatorSetPath:r,androidSerialAllowlist:n?Array.from(n).sort():void 0});return om(s)?oh(a,await oa(u,s,{simulatorSetPath:r})):oh(a,await rJ(u,s,{simulatorSetPath:r}))},i)}async function ol(e){return or.getStore()?await e():await or.run(new Map,e)}async function ou(e,t){return e?await on.run(e,t):await t()}async function od(e,t){return await ou(e,async()=>await ol(t))}async function oc(e){return await op(e)??await of(e)}async function op(e){let t=on.getStore();if(!t)return null;let r=await t(e);return null==r?null:r.map(e=>({...e}))}async function of(e){if("macos"===e.platform||"apple"===e.platform&&"desktop"===e.target)return await iW();if("linux"===e.platform)return await ot();if("android"===e.platform)return await $({serialAllowlist:e.androidSerialAllowlist?new Set(e.androidSerialAllowlist):void 0});if(e.platform)return await oe({simulatorSetPath:e.iosSimulatorSetPath,udid:e.udid});let t=[];try{t.push(...await $({serialAllowlist:e.androidSerialAllowlist?new Set(e.androidSerialAllowlist):void 0}))}catch{}try{t.push(...await oe({simulatorSetPath:e.iosSimulatorSetPath,udid:e.udid}))}catch{}try{t.push(...await ot())}catch{}return t}function om(e){return!!e.platform&&"android"!==e.platform&&"linux"!==e.platform}function oh(e,t){return or.getStore()?.set(e,{...t}),t}let ow={runCommand:C,whichCommand:L,desktop:oA(C,L),clipboard:oS(C,L),screenshot:ob(C,L)},og=ro(ow,function(e={}){let t={...ow,...e};return{...t,desktop:e.desktop??oA(t.runCommand,t.whichCommand),clipboard:e.clipboard??oS(t.runCommand,t.whichCommand),screenshot:e.screenshot??ob(t.runCommand,t.whichCommand)}});function oy(e){return og.resolve(e)}async function ov(e,t){return await og.run(e,t)}async function oI(e,t,r){return await oy().runCommand(e,t,r)}function oA(e,t){return{async openTarget(r){if(r.includes("://")||r.startsWith("/"))return void await e("xdg-open",[r]);if(await t(r)){e(r,[],{allowFailure:!0}).catch(e=>{eb({level:"warn",phase:"linux_app_launch",data:{app:r,error:String(e)}})}),await ex(500);return}await e("xdg-open",[r],{allowFailure:!0})},async closeApp(r){await t("wmctrl")?await e("wmctrl",["-c",r],{allowFailure:!0}):await e("pkill",["-x",r],{allowFailure:!0})}}}function oS(e,t){return{async readText(){let r=ox[await ok(t,o_)];return(await e(r.cmd,r.args,r.options)).stdout},async writeText(r){let n=oM[await ok(t,o_)](r);await e(n.cmd,n.args,n.options)}}}function ob(e,t){return{async capture(r){let n=oD[await ok(t,oN)](r);await e(n.cmd,n.args,n.options)}}}let o_={wayland:[{tool:"wl-clipboard",command:"wl-paste"}],x11:[{tool:"xclip",command:"xclip"},{tool:"xsel",command:"xsel"}],waylandError:"wl-paste (wl-clipboard) is required for clipboard access on Wayland. Install via your package manager.",x11Error:"xclip or xsel is required for clipboard access on X11. Install via your package manager."},oN={wayland:[{tool:"grim",command:"grim"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],x11:[{tool:"scrot",command:"scrot"},{tool:"import",command:"import"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],waylandError:"grim or gnome-screenshot is required for screenshots on Wayland. Install via your package manager.",x11Error:"scrot, import (ImageMagick), or gnome-screenshot is required for screenshots on X11. Install via your package manager."},ox={"wl-clipboard":{cmd:"wl-paste",args:["--no-newline"],options:{allowFailure:!0,timeoutMs:5e3}},xclip:{cmd:"xclip",args:["-selection","clipboard","-o"],options:{allowFailure:!0,timeoutMs:5e3}},xsel:{cmd:"xsel",args:["--clipboard","--output"],options:{allowFailure:!0,timeoutMs:5e3}}},oM={"wl-clipboard":e=>({cmd:"wl-copy",args:["--",e],options:{allowFailure:!1,timeoutMs:5e3}}),xclip:e=>({cmd:"xclip",args:["-selection","clipboard"],options:{allowFailure:!1,timeoutMs:5e3,stdin:e}}),xsel:e=>({cmd:"xsel",args:["--clipboard","--input"],options:{allowFailure:!1,timeoutMs:5e3,stdin:e}})},oD={grim:e=>({cmd:"grim",args:[e]}),scrot:e=>({cmd:"scrot",args:[e]}),import:e=>({cmd:"import",args:["-window","root",e]}),"gnome-screenshot":e=>({cmd:"gnome-screenshot",args:["-f",e]})};async function ok(e,t){let r=process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11";for(let n of t[r])if(await e(n.command))return n.tool;throw new P("TOOL_MISSING","wayland"===r?t.waylandError:t.x11Error)}async function oP(e,t){let r=["devicectl",...e],n=await ry(r,{allowFailure:!0,timeoutMs:2e4});if(0===n.exitCode)return;let a=String(n.stdout??""),i=String(n.stderr??"");throw new P("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:n.exitCode,stdout:a,stderr:i,deviceId:t.deviceId,hint:oR(a,i)??oL})}async function oO(e,t){var r;return r=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let n="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t,a="string"==typeof e.url&&e.url.trim().length>0?e.url.trim():void 0;r.push({bundleId:t,name:n,url:a})}return r}(await oC(e,{jsonPrefix:"agent-device-ios-apps",args:["devicectl","device","info","apps","--device",e.id,"--include-all-apps"],failureMessage:"Failed to list iOS apps",parseFailureMessage:"Failed to parse iOS apps list"})),"user-installed"===t?r.filter(e=>!e.bundleId.startsWith("com.apple.")):r}async function oE(e){return function(e){let t=e?.result?.runningProcesses;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.executable?e.executable.trim():"",n="number"==typeof e.processIdentifier&&Number.isFinite(e.processIdentifier)?e.processIdentifier:NaN;t&&Number.isFinite(n)&&r.push({executable:t,pid:n})}return r}(await oC(e,{jsonPrefix:"agent-device-ios-processes",args:["devicectl","device","info","processes","--device",e.id],failureMessage:"Failed to list iOS processes",parseFailureMessage:"Failed to parse iOS process list"}))}async function oC(e,t){let r=f.join(c.tmpdir(),`${t.jsonPrefix}-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),n=[...t.args,"--json-output",r],a=await ry(n,{allowFailure:!0,timeoutMs:2e4});try{if(0!==a.exitCode){let r=String(a.stdout??""),i=String(a.stderr??"");throw new P("COMMAND_FAILED",t.failureMessage,{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:r,stderr:i,deviceId:e.id,hint:oR(r,i)??oL})}return JSON.parse(await d.readFile(r,"utf8"))}catch(r){if(r instanceof P)throw r;throw new P("COMMAND_FAILED",t.parseFailureMessage,{deviceId:e.id,cause:String(r)})}finally{await d.unlink(r).catch(()=>{})}}let oL="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function oR(e,t){let r=`${e}
|
|
12
|
+
${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}let oT=new Map;async function o$(e){var t;let r,n=(r="simulator"===(t=e).kind?t.simulatorSetPath??"":"",JSON.stringify([t.platform,t.kind,t.id,t.target??"",r])),a=oT.get(n);if(void 0!==a){if(a>Date.now())return;oT.delete(n)}if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(t2);await t(e),oF(n);return}if("device"===e.kind){await oU(e.id),oF(n);return}}if("android"===e.platform){let{waitForAndroidBoot:t}=await import("../1769.js");await t(e.id),oF(n)}}function oF(e){oT.set(e,Date.now()+5e3)}async function oU(e){let t=f.join(c.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(15));try{let n=await ry(["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:18e3}),a=String(n.stdout??""),i=String(n.stderr??""),o=await oG(t);if(0===n.exitCode){if(!o.parsed)throw new P("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:a,stderr:i,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new P("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,tunnelState:t,hint:"Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry."});return}throw new P("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:a,stderr:i,exitCode:n.exitCode,tunnelState:o?.tunnelState,hint:oV(a,i)})}catch(t){if(t instanceof P&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},n=String(r.stdout??""),a=String(r.stderr??""),i=Number(r.timeoutMs??15e3),o=`CoreDevice did not respond within ${i}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new P("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:i,stdout:n,stderr:a,hint:n||a?oV(n,a):o},t)}throw new P("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,hint:"Reconnect the device, keep it unlocked, and retry."},t instanceof Error?t:void 0)}finally{await d.rm(t,{force:!0}).catch(()=>{})}}async function oG(e){try{let t=await d.readFile(e,"utf8"),r=JSON.parse(t),n=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,n=t.device?.connectionProperties?.tunnelState,a="string"==typeof r?r:"string"==typeof n?n:void 0;return a?{tunnelState:a}:{}}(r);return{parsed:!0,tunnelState:n.tunnelState}}catch{return{parsed:!1}}}function oV(e,t){let r=oR(e,t);return r||(`${e}
|
|
13
|
+
${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":oL)}async function oj(e,t,r){let n="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,a=["shell","am","broadcast","-a",n,"-p",t],i="string"==typeof r.receiver?r.receiver.trim():"";i&&a.push("-n",i);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new P("INVALID_ARGS","Android push payload extras must be an object");let s=0;for(let[e,t]of Object.entries(o??{}))e&&(function(e,t,r){if("string"==typeof r)return e.push("--es",t,r);if("boolean"==typeof r)return e.push("--ez",t,r?"true":"false");if("number"==typeof r&&Number.isFinite(r))return Number.isInteger(r)?e.push("--ei",t,String(r)):e.push("--ef",t,String(r));throw new P("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(a,e,t),s+=1);return await X(e,a),{action:n,extrasCount:s}}function oB(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,n=function(e){if(void 0===e)return .6;if(!Number.isFinite(e)||e<=0)throw new P("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),a=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new P("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*n),i=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(a,Math.max(1,r-2*i))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),u=Math.round(e.referenceHeight/2),d=(r,n,a,i)=>({direction:t,x1:r,y1:n,x2:a,y2:i,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return d(l,u-s,l,u+s);case"down":return d(l,u+s,l,u-s);case"left":return d(l-s,u,l+s,u);case"right":return d(l+s,u,l-s,u)}}function oq(e){var t;return!!e&&(!!e.password||!!(t=e.text)&&Array.from(t).every(oW))}function oH(e){if(!e)return null;let t=oq(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function oW(e){return"•"===e||"*"===e||"●"===e}function oz(e){if(0===e.length)return null;let t=[...e].sort((e,t)=>e-t);return t[Math.floor(t.length/2)]??null}function oK(e,t){let r=Math.max(24,Math.round(.2*Math.min(e.size,t.size))),n=Math.max(48,Math.round(.15*Math.min(e.crossSize,t.crossSize)));return Math.abs(e.size-t.size)<=r&&Math.abs(e.crossSize-t.crossSize)<=n}function oJ(e,t){return{start:e.y-t.y,size:e.height,crossSize:e.width}}async function oX(e,t={}){let r=e4(e,t.helperAdb),n=await oZ(e,t,r),a=n.xml,i=!1!==t.includeHiddenContentHints;if(!t.interactiveOnly){let o=e8(a,800,t);return i&&function(e,t){for(let[r,n]of e){let e=t[r];e&&(n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0))}}(await o2(e,o.nodes,r),o.nodes),{...o,androidSnapshot:n.metadata}}let o=e9(a),s=tn(o,800,{...t,interactiveOnly:!1}),l=tn(o,800,t);if(i){let t=await o2(e,s.nodes,r);o9(t,s,l),0===t.size&&o9(tp(tL(s.nodes)),s,l)}let{sourceNodes:u,...d}=l;return{...d,androidSnapshot:n.metadata}}async function oZ(e,t,r){let n=await eS("android_snapshot_helper_artifact_resolution",async()=>await o0(t.helperArtifact));if(n.artifact){var a;let i=(a=e,`${a.platform}:${a.id}`);try{let a=e3(e,t.helperAdb),o=await eS("android_snapshot_helper_install",async()=>await e6({adb:r,adbProvider:a,artifact:n.artifact,deviceKey:i,installPolicy:t.helperInstallPolicy,timeoutMs:3e4}),{packageName:n.artifact.manifest.packageName,versionCode:n.artifact.manifest.versionCode,installPolicy:t.helperInstallPolicy??"missing-or-outdated"});eb({phase:"android_snapshot_helper_install_decision",data:{packageName:o.packageName,versionCode:o.versionCode,installedVersionCode:o.installedVersionCode,installed:o.installed,reason:o.reason}});let s=await eS("android_snapshot_helper_capture",async()=>await e7({adb:r,packageName:n.artifact.manifest.packageName,instrumentationRunner:n.artifact.manifest.instrumentationRunner,waitForIdleTimeoutMs:t.helperWaitForIdleTimeoutMs??500,timeoutMs:5e3,commandTimeoutMs:8e3}),{packageName:n.artifact.manifest.packageName,version:n.artifact.manifest.version,timeoutMs:5e3,commandTimeoutMs:8e3});return{xml:s.xml,metadata:{backend:"android-helper",helperVersion:n.artifact.manifest.version,helperApiVersion:s.metadata.helperApiVersion,installReason:o.reason,waitForIdleTimeoutMs:s.metadata.waitForIdleTimeoutMs,timeoutMs:s.metadata.timeoutMs,maxDepth:s.metadata.maxDepth,maxNodes:s.metadata.maxNodes,rootPresent:s.metadata.rootPresent,captureMode:s.metadata.captureMode,windowCount:s.metadata.windowCount,nodeCount:s.metadata.nodeCount,helperTruncated:s.metadata.truncated,elapsedMs:s.metadata.elapsedMs}}}catch(o){let t=function(e){let t=k(e);if(!function(e,t){if(!e||"object"!=typeof e)return!1;let r="errorType"in e?String(e.errorType):"",n=oQ(e)??t;return/TimeoutException/.test(r)||/timed out/i.test(n)}(t.details?.helper,t.message))return;let r=oY(e);return new P(M(t.code),`${r}. Stock UIAutomator fallback was skipped because this usually means the Android accessibility tree is busy or stalled.`,{...t.details,hint:"Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists."},e)}(o);if(t)throw t;let a=oY(o);return eb({level:"warn",phase:"android_snapshot_helper_fallback",data:{reason:a}}),tr({deviceKey:i,packageName:n.artifact.manifest.packageName,versionCode:n.artifact.manifest.versionCode}),await o1(e,a,r)}}return eb({level:n.fallbackReason?"warn":"info",phase:"android_snapshot_helper_unavailable",data:{reason:n.fallbackReason??"artifact_not_found"}}),await o1(e,n.fallbackReason,r)}function oY(e){let t=k(e),r=oQ(t.details?.helper);if(r&&r!==t.message)return`${t.message}: ${r}`;if(r)return r;let n=("string"==typeof t.details?.stderr?t.details.stderr.trim():"").split(/\r?\n/).find(e=>e.trim());return n?`${t.message}: ${n}`:t.message}function oQ(e){if(!e||"object"!=typeof e||!("message"in e))return;let t=String(e.message).trim();return t&&"null"!==t?t:void 0}async function o0(e){if(e)return{artifact:e};let t=e_(),r=f.join(eN(),"android-snapshot-helper","dist"),n=f.join(r,`agent-device-android-snapshot-helper-${t}.manifest.json`);try{await b.access(n)}catch{return{}}try{let e=te(JSON.parse(await b.readFile(n,"utf8"))),t=f.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await b.access(t),{artifact:{apkPath:t,manifest:e}}}catch(e){return{fallbackReason:k(e).message}}}async function o1(e,t,r){let n;try{n=await eS("android_snapshot_stock_capture",async()=>await o3(e,r),{fallbackReason:t,timeoutMs:8e3})}catch(e){if(t){var a,i;let r;throw a=e,i=t,new P(M((r=k(a)).code),`${r.message} Android snapshot helper failed before stock fallback: ${i}`,{...r.details,androidSnapshotHelperFallbackReason:i,...r.hint?{hint:r.hint}:{}},a)}throw e}return{xml:n,metadata:{backend:"uiautomator-dump",...t?{fallbackReason:t}:{}}}}async function o2(e,t,r){if(!t.some(e=>e5(e.type)))return new Map;let n=await o6(e,r);return n?function(e,t){let r=function(e){let t={className:"root",rect:{x:0,y:0,width:0,height:0},children:[]},r=[{indent:-1,node:t}],n=/^(\s*)([\w.$]+)\{[^}]* (-?\d+),(-?\d+)-(-?\d+),(-?\d+) #/;for(let t of e.split("\n")){let e=n.exec(t);if(!e)continue;let a=e[1].length,i=Number(e[3]),o=Number(e[4]),s=Number(e[5]),l=Number(e[6]),u={className:e[2],rect:{x:i,y:o,width:Math.max(0,s-i),height:Math.max(0,l-o)},children:[]};for(;r.length>1&&a<=r[r.length-1].indent;)r.pop();r[r.length-1].node.children.push(u),r.push({indent:a,node:u})}return t.children.length>0?t:null}(t);if(!r)return new Map;let n=function(e){let t=[],r=[e];for(;r.length>0;){let e=r.pop();if(e5(e.className)){let r=function(e){let t=e.children[0];if(!t)return null;let r=Math.max(t.rect.height,...t.children.map(e=>e.rect.y+e.rect.height)),n=t.children.filter(e=>e.rect.height>0).map(t=>oJ(t.rect,e.rect)).sort((e,t)=>e.start-t.start);return 0===n.length?null:{rect:e.rect,contentExtent:r,contentBlocks:n}}(e);r&&t.push(r)}r.push(...e.children)}return t}(r);if(0===n.length)return new Map;let a=new Map;for(let t of e){if(!t.rect||!e5(t.type))continue;let r=function(e,t){let r=null,n=1/0;for(let a of t){let t=Math.abs(a.rect.width-e.width)+Math.abs(a.rect.height-e.height);if(t>32)continue;let i=4*t+(Math.abs(a.rect.x-e.x)+Math.abs(a.rect.y-e.y));i<n&&(r=a,n=i)}return r}(t.rect,n);if(!r)continue;let i=function(e,t){let r=function(e,t){let r=t,n=new Set;for(;!n.has(r.index);){var a,i;n.add(r.index);let o=e.filter(e=>e.parentIndex===r.index&&e.rect);if(1!==o.length)return r;let s=o[0];if(a=s.rect,i=t.rect,a.x!==i.x||a.y!==i.y||a.width!==i.width||a.height!==i.height)return r;r=s}return t}(e,t);return e.filter(e=>e.parentIndex===r.index&&e.rect).map(e=>e.rect).filter(e=>e.height>0).sort((e,t)=>e.y-t.y).map(e=>oJ(e,t.rect))}(e,t),o=function(e){let{viewportRect:t,visibleBlocks:r,nativeScrollView:n}=e;if(0===r.length||0===n.contentBlocks.length)return null;let a=function(e){if(0===e.contentBlocks.length)return null;let t=e.contentBlocks[0],r=e.contentBlocks[e.contentBlocks.length-1];if(!t||!r)return null;let n=oz(e.contentBlocks.map(e=>e.size))??e.rect.height,a=Math.max(48,Math.round(.5*n)),i=Math.max(24,Math.round(.25*n)),o=t.start>=a,s=e.contentExtent-(r.start+r.size)>=i;return o||s?{above:o,below:s}:null}(n),i=function(e,t){let r=new Map;for(let n of e)for(let e of t){if(!oK(n,e))continue;let t=n.start-e.start,a=8*Math.round(t/8),i=r.get(a)??[];i.push(t),r.set(a,i)}let n=null;for(let e of r.values())(!n||e.length>n.length)&&(n=e);if(!n||n.length<2)return null;let a=[...n].sort((e,t)=>e-t);return a[Math.floor(a.length/2)]??null}(n.contentBlocks,r)??function(e){let{nativeBlocks:t,visibleBlocks:r,viewportExtent:n,contentExtent:a}=e,i=[],o=[];for(let e of t)for(let t of r){if(!oK(e,t))continue;let r=e.start-t.start;16>=Math.abs(r)&&i.push(r),16>=Math.abs(r+n-a)&&o.push(r)}return o.length>0?oz(o):i.length>0?oz(i):null}({nativeBlocks:n.contentBlocks,visibleBlocks:r,viewportExtent:t.height,contentExtent:n.contentExtent});if(null===i)return a;let o=t.height;return{above:(a?.above??!1)||i>16,below:(a?.below??!1)||i+o<n.contentExtent-16}}({viewportRect:t.rect,visibleBlocks:i,nativeScrollView:r});if(!o)continue;let s={};o.above&&(s.hiddenContentAbove=!0),o.below&&(s.hiddenContentBelow=!0),(s.hiddenContentAbove||s.hiddenContentBelow)&&a.set(t.index,s)}return a}(t,n):new Map}async function o3(e,t=e4(e)){try{return await T(()=>o4(t),{shouldRetry:o8})}catch(e){if(function(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code||"number"!=typeof e.details?.timeoutMs)return!1;let t=e.details?.cmd,r=e.details?.args,n=Array.isArray(r)?r.map(String):"string"==typeof r?r.split(/\s+/):[];return"adb"===t&&n.includes("uiautomator")&&n.includes("dump")}(e)){let t="Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout. Stock Android UIAutomator may still time out on app-owned infinite animations.";throw new P("COMMAND_FAILED",`Android UI hierarchy dump timed out while waiting for the UI to become idle. ${t}`,{...e.details??{},hint:t},e)}throw e}}async function o4(e){var t,r,n;let a,i,o=await e(["exec-out","uiautomator","dump","/dev/tty"],{allowFailure:!0,timeoutMs:8e3}),s=o5(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",u=await e(["shell","uiautomator","dump",l],{allowFailure:!0,timeoutMs:8e3}),d=(t=l,r=u.stdout,n=u.stderr,a=`${r}
|
|
14
|
+
${n}`,i=/dumped to:\s*(\S+)/i.exec(a),i?.[1]??t),c=await e(["shell","cat",d]),p=o5(c.stdout,c.stderr);if(!p)throw new P("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return p}function o5(e,t){let r=`${e}
|
|
15
|
+
${t}`,n=r.indexOf("<?xml"),a=n>=0?n:r.indexOf("<hierarchy");if(a<0)return null;let i=r.lastIndexOf("</hierarchy>");if(i<0||i<a)return null;let o=r.slice(a,i+12).trim();return o.length>0?o:null}function o8(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details?.stderr,r=("string"==typeof t?t:"").toLowerCase();return!!(r.includes("device offline")||r.includes("device not found")||r.includes("transport error")||r.includes("connection reset")||r.includes("broken pipe")||r.includes("timed out")||r.includes("no such file or directory"))}async function o6(e,t=e4(e)){try{let e=await t(["shell","dumpsys","activity","top"],{allowFailure:!0,timeoutMs:8e3}),r=`${e.stdout}
|
|
16
|
+
${e.stderr}`.trim();return r.length>0?r:null}catch{return null}}function o9(e,t,r){if(0===e.size)return;let n=new Map;for(let[e,t]of r.sourceNodes.entries()){let a=r.nodes[e];a&&n.set(t,a)}for(let[r,a]of e){let e=t.sourceNodes[r];if(!e)continue;let i=n.get(e);i&&(a.hiddenContentAbove&&(i.hiddenContentAbove=!0),a.hiddenContentBelow&&(i.hiddenContentBelow=!0))}}async function o7(e,t,r,n){let a=null,i=null,o=await sa(e);for(let s of[0,150,350]){s>0&&await ex(s);let l=await st(e,t,r,n,o);if(a=l,"ime_capture"===l.reason)return l;i=l.ok?l:null}return i??a??{ok:!1,actual:null,reason:"text_mismatch",targetInput:null,actualInput:null}}async function se(e,t,r){var n,a,i;return n=await o3(e),a=t,i=r,sr(n,a,i).actualInput?.text??null}async function st(e,t,r,n,a){return function(e,t,r,n,a={}){var i,o;let s,l=sr(e,t,r,a);return!function(e){let{targetInput:t,actualInput:r}=e;return!!t&&!!r&&r!==t&&r.inputMethodOwned&&!t.inputMethodOwned}(l)?function(e,t){let r=e.actualInput;if(!r||!oq(r))return null;let n=r.text??null,a=Array.from(n??"").length,i=Array.from(t).length,o=null!==n&&a>0&&i>0&&a===i;return{ok:o,actual:n,reason:o?void 0:"masked_unverified",masked:!0,targetInput:e.targetInput,actualInput:r}}(l,n)??(i=l,o=n,{ok:function(e,t){if(e===t)return!0;let r=sn(e),n=sn(t);return!!r&&!!n&&!!(r===n||function(e,t){if(e.length!==t.length||0===e.length||e.slice(1)!==t.slice(1))return!1;let r=e[0],n=t[0];return!!r&&!!n&&n.toLowerCase()===n&&r===n.toUpperCase()}(r,n))}(s=i.actualInput?.text??null,o),actual:s,reason:"text_mismatch",targetInput:i.targetInput,actualInput:i.actualInput}):{ok:!1,actual:l.actualInput?.text??null,reason:"ime_capture",targetInput:l.targetInput,actualInput:l.actualInput}}(await o3(e),t,r,n,a)}function sr(e,t,r,n={}){var a;let i,o={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of tt(e)){let e=function(e,t){if(!e.rect)return null;let r=e.text??"",n=Math.max(1,e.rect.width*e.rect.height);return{text:r||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:!0===e.password,inputMethodOwned:el({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:n,editText:function(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}(e.className??"")}}(a,n);e&&function(e,t,r,n){var a,i,o;let s=(a=t.rect,i=r,o=n,i>=a.x&&i<=a.x+a.width&&o>=a.y&&o<=a.y+a.height);if(s&&t.editText&&(e.editAtPoint=si(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=si(e.focusedEdit,t);return}s&&t.text&&(e.anyAtPoint=si(e.anyAtPoint,t))}(o,e,t,r)}return{targetInput:i=(a=o).editAtPoint??a.anyAtPoint,actualInput:(a.focusedEdit?.text?a.focusedEdit:null)??i}}function sn(e){return(e??"").replace(/\s+/g," ").trim()}async function sa(e){try{return{activeInputMethodPackage:(await en(e)).inputMethodPackage}}catch(e){return eb({level:"warn",phase:"android_fill_verification_input_method_probe_failed",data:{error:e instanceof Error?e.message:String(e)}}),{}}}function si(e,t){return e&&e.area<t.area?e:t}async function so(e,t,r){await X(e,["shell","input","tap",String(t),String(r)])}async function ss(e,t,r,n,a,i=250){await X(e,["shell","input","swipe",String(t),String(r),String(n),String(a),String(i)])}async function sl(e){await X(e,["shell","input","keyevent","4"])}async function su(e){await X(e,["shell","input","keyevent","3"])}async function sd(e,t){let r=function(e){switch(e){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new P("INVALID_ARGS",`Unsupported Android rotation: ${e}`)}}(t);await X(e,["shell","settings","put","system","accelerometer_rotation","0"]),await X(e,["shell","settings","put","system","user_rotation",r])}async function sc(e){await X(e,["shell","input","keyevent","187"])}async function sp(e,t,r,n=800){await X(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(n)])}async function sf(e,t,r=0){let n=e2(e);if(n){await n({action:"type",text:t,delayMs:r}),sN("type","provider-native",t);return}(sb(t),await sy(e,"type"),r>0&&Array.from(t).length>1)?await sA(e,{action:"type",text:t,chunkSize:1,delayMs:r}):await sA(e,{action:"type",text:t,chunkSize:sI,delayMs:0})}async function sm(e,t,r){await so(e,t,r)}async function sh(e,t,r,n,a=0){let i=e2(e);if(i){await i({action:"fill",target:{x:t,y:r},text:n,delayMs:a}),sN("fill","provider-native",n);let o=await o7(e,t,r,n);if(o.ok)return;sw(n,o)}sb(n);let o=Array.from(n).length,s=null;for(let i of[{clearPadding:12,minClear:8,maxClear:48,chunkSize:a>0?1:sI,inputDelayMs:a},{clearPadding:24,minClear:16,maxClear:96,chunkSize:a>0?1:4,inputDelayMs:a>0?a:15}]){var l,u;await sm(e,t,r),await sy(e,"fill");let a=(l=o+i.clearPadding,u=i.minClear,Math.max(u,Math.min(i.maxClear,l)));await sx(e,a),await sA(e,{action:"fill",text:n,chunkSize:i.chunkSize,delayMs:i.inputDelayMs});let d=await o7(e,t,r,n);if(s=d,d.ok)return;"ime_capture"===d.reason&&sw(n,d)}sw(n,s)}function sw(e,t){let r;throw new P("COMMAND_FAILED",t?.reason==="ime_capture"?"Android fill input was captured by the active keyboard instead of the app field":t?.reason==="masked_unverified"?"Android fill verification could not confirm masked text value":"Android fill verification failed",(r=function(e,t){var r;if(!t)return{expected:e,actual:null,failureReason:"text_mismatch",targetInput:null,actualInput:null};let n=!0===(r=t).masked||oq(r.targetInput)||oq(r.actualInput),a={failureReason:t.reason??"text_mismatch",targetInput:oH(t.targetInput),actualInput:oH(t.actualInput)};return n?{...a,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??"").length}:{...a,expected:e,actual:t.actual}}(e,t),t?.reason==="ime_capture"&&(r.hint="The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill."),r))}async function sg(e,t,r){let n=await sv(e),a=oB({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:n.width,referenceHeight:n.height});return await X(e,["shell","input","swipe",String(a.x1),String(a.y1),String(a.x2),String(a.y2),"300"]),a}async function sy(e,t){let r;try{r=await en(e)}catch(e){eb({level:"warn",phase:"android_input_ownership_probe_failed",data:{action:t,error:e instanceof Error?e.message:String(e)}});return}if("ime"===r.inputOwner)throw new P("COMMAND_FAILED","KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.",{failureReason:"ime_capture",action:t,inputOwner:r.inputOwner,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,nextAction:"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry."})}async function sv(e){let t=(await X(e,["shell","wm","size"])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new P("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}let sI=8;async function sA(e,t){let r=t.text.split("\n");for(let[n,a]of r.entries()){let i=function(e,t){let r=Math.max(1,Math.floor(t)),n=[],a=Array.from(e);for(let e=0;e<a.length;e+=r)n.push(a.slice(e,e+r).join(""));return n.length>0?n:[""]}(a,t.chunkSize);for(let[a,o]of i.entries())await sS(e,o),t.delayMs>0&&(a+1<i.length||n+1<r.length)&&await ex(t.delayMs);n+1<r.length&&await X(e,["shell","input","keyevent","ENTER"])}sN(t.action,"adb-shell",t.text)}async function sS(e,t){if(t)try{await X(e,["shell","input","text",t.replace(/ /g,"%s")])}catch(e){if(function(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details?.stderr,r=("string"==typeof t?t:"").toLowerCase();return!!(r.includes("exception occurred while executing 'text'")||r.includes("nullpointerexception")&&r.includes("inputshellcommand.sendtext"))}(e))throw s_(t,e);throw e}}function sb(e){if(!function(e){for(let t of e){let e=t.codePointAt(0);if(void 0!==e&&"\n"!==t&&(e<32||e>126))return!1}return!0}(e))throw s_(e)}function s_(e,t){return new P("COMMAND_FAILED","Android text input requires provider-native text injection for non-ASCII/control characters; the current adb-shell fallback supports ASCII text only.",{backend:"adb-shell",textLength:Array.from(e).length,textPreview:e.slice(0,32)},t instanceof Error?t:void 0)}function sN(e,t,r){eb({phase:"android_text_injection",data:{action:e,backend:t,textLength:Array.from(r).length}})}async function sx(e,t){let r=Math.max(0,t);await X(e,["shell","input","keyevent","KEYCODE_MOVE_END"],{allowFailure:!0});for(let t=0;t<r;t+=24){let n=Math.min(24,r-t);await X(e,["shell","input","keyevent",...Array(n).fill("KEYCODE_DEL")],{allowFailure:!0})}}function sM(e){return e.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}))}let sD=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function sk(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new P("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function sP(e){let t=e?.trim().toLowerCase();if("camera"===t||"microphone"===t||"photos"===t||"contacts"===t||"contacts-limited"===t||"notifications"===t||"calendar"===t||"location"===t||"location-always"===t||"media-library"===t||"motion"===t||"reminders"===t||"siri"===t)return t;throw new P("INVALID_ARGS",`permission setting requires a target: ${sD.join("|")}`)}function sO(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new P("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}function sE(e){let t=e.toLowerCase();if("on"===t||"true"===t||"1"===t)return!0;if("off"===t||"false"===t||"0"===t)return!1;throw new P("INVALID_ARGS",`Invalid setting state: ${e}`)}let sC=["window_animation_scale","transition_animation_scale","animator_duration_scale"];async function sL(e,t,r,n,a){switch(t.toLowerCase()){case"wifi":{let t=sE(r);await X(e,["shell","svc","wifi",t?"enable":"disable"]);return}case"airplane":{let t=sE(r);await X(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"]),await X(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]);return}case"location":{if("set"===r.toLowerCase()){if("emulator"!==e.kind)throw new P("UNSUPPORTED_OPERATION","Android precise location coordinates are supported only on emulators.",{deviceId:e.id,hint:"Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling."});let{latitude:t,longitude:r}=eG(a);return await X(e,["emu","geo","fix",String(r),String(t)]),{latitude:t,longitude:r}}let t=sE(r);await X(e,["shell","settings","put","secure","location_mode",t?"3":"0"]);return}case"animations":{let t=sE(r)?"1":"0";for(let r of sC)await X(e,["shell","settings","put","global",r,t]);return{scale:t,keys:[...sC]}}case"appearance":{let t=await sT(e,r);await X(e,["shell","cmd","uimode","night","dark"===t?"yes":"no"]);return}case"fingerprint":{let t=function(e){let t=e.trim().toLowerCase();if("match"===t)return"match";if("nonmatch"===t)return"nonmatch";throw new P("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await sR(e,t);return}case"permission":{if(!n)throw new P("INVALID_ARGS","permission setting requires an active app in session");let t=sk(r),i=function(e,t){let r=sP(e);if(t?.trim())throw new P("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===r)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===r)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===r)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===r)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new P("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(a?.permissionTarget,a?.permissionMode);if("notifications"===i.kind)return void await sF(e,n,t,i);let o="grant"===t?"grant":"revoke";if("photos"===i.type)return void await s$(e,n,o);await X(e,["shell","pm",o,n,i.value]);return}default:throw new P("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function sR(e,t){var r;let n,a,i=(r=e,a=[["shell","cmd","fingerprint","touch",n="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",n]],"emulator"===r.kind&&a.push(["emu","finger","touch",n]),a),o=[];for(let t of i){let r=await X(e,t,{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=sM(o);if(o.length>0&&o.every(e=>{var t,r;let n;return t=e.stdout,r=e.stderr,(n=`${t}
|
|
17
|
+
${r}`.toLowerCase()).includes("unknown command")||n.includes("can't find service: fingerprint")||n.includes("service fingerprint was not found")||n.includes("fingerprint cmd unavailable")||n.includes("emu command is not supported")||n.includes("emulator console is not running")||n.includes("fingerprint")&&n.includes("not found")}))throw new P("UNSUPPORTED_OPERATION","Android fingerprint simulation is not supported on this target/runtime.",{deviceId:e.id,action:t,hint:"Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.",attempts:s});throw new P("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}async function sT(e,t){let r=sO(t);if("toggle"!==r)return r;let n=await X(e,["shell","cmd","uimode","night"],{allowFailure:!0});if(0!==n.exitCode)throw new P("COMMAND_FAILED","Failed to read current Android appearance",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});let a=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
|
|
18
|
+
${t}`);if(!r)return null;let n=r[1].toLowerCase();return"yes"===n?"dark":"no"===n?"light":"auto"===n?"auto":null}(n.stdout,n.stderr);if(!a)throw new P("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:n.stdout,stderr:n.stderr});return"auto"===a?"dark":"dark"===a?"light":"dark"}async function s$(e,t,r){let n=await sU(e),a=[];for(let i of null!==n&&n>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let n=await X(e,["shell","pm",r,t,i],{allowFailure:!0});if(0===n.exitCode)return;a.push({permission:i,stderr:n.stderr,exitCode:n.exitCode})}throw new P("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:n,attempts:a})}async function sF(e,t,r,n){"grant"===r?await X(e,["shell","pm","grant",t,n.permission],{allowFailure:!0}):(await X(e,["shell","pm","revoke",t,n.permission],{allowFailure:!0}),"reset"===r&&(await X(e,["shell","pm","clear-permission-flags",t,n.permission,"user-set"],{allowFailure:!0}),await X(e,["shell","pm","clear-permission-flags",t,n.permission,"user-fixed"],{allowFailure:!0}))),await X(e,["shell","appops","set",t,n.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"])}async function sU(e){let t=await X(e,["shell","getprop","ro.build.version.sdk"],{allowFailure:!0});if(0!==t.exitCode)return null;let r=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(r)||r<=0?null:r}let sG=Buffer.from([137,80,78,71,13,10,26,10]);async function sV(e,t,r={}){if(!1===r.stabilize)return void await sq(e,t);await sj(e);try{await ex(1e3),await sq(e,t)}finally{await sB(e).catch(()=>{})}}async function sj(e){let t=t=>X(e,["shell",t],{allowFailure:!0});await t("settings put global sysui_demo_allowed 1");let r=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await r("clock -e hhmm 0941"),await r("notifications -e visible false")}async function sB(e){await X(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"],{allowFailure:!0})}async function sq(e,t){let r=await X(e,["exec-out","screencap","-p"],{binaryStdout:!0});if(!r.stdoutBuffer)throw new P("COMMAND_FAILED","Failed to capture screenshot");let n=r.stdoutBuffer.indexOf(sG);if(n<0)throw new P("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let a=function(e,t){let r=t+sG.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),n=r+4,a=e.toString("ascii",n,n+4),i=r+12+t;if(i>e.length)break;if("IEND"===a)return i;r=i}return null}(r.stdoutBuffer,n);if(!a)throw new P("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await d.writeFile(t,r.stdoutBuffer.subarray(n,a))}function sH(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{};if(4!==t.exitCode)return!1;let r=String(t.stderr??"").toLowerCase();return r.includes("fbsopenapplicationserviceerrordomain")&&r.includes("the request to open")}async function sW(e,t){let r=await ry(rS(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let n=r.stdout.trim();if(!n)return{installed:!1};let a=await rg("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${n}/Info.plist`],{allowFailure:!0});if(0!==a.exitCode||!a.stdout.trim())return{installed:!0};let i=a.stdout.trim(),o=`${n}/${i}`,s=await rg("otool",["-l",o],{allowFailure:!0});if(0!==s.exitCode)return{installed:!0};let l=s.stdout.toLowerCase();return{installed:!0,simulatorCompatible:l.includes("iossimulator")||l.includes("platform 7")}}function sz(e,t){if("simulator"!==e.kind)throw new P("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function sK(){await rg("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:1e4})}async function sJ(e){let t,r;if("simulator"!==e.kind||"Booted"===await sZ(e))return;let n=ee.fromTimeoutMs(18e4);try{await ei(async({deadline:n})=>{if(n?.isExpired())throw new P("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:18e4});let a=Math.max(1e3,n?.remainingMs()??18e4),i=await ry(rS(e,["boot",e.id]),{allowFailure:!0,timeoutMs:a});t={stdout:String(i.stdout??""),stderr:String(i.stderr??""),exitCode:i.exitCode};let o=`${t.stdout}
|
|
19
|
+
${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new P("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await ry(rS(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:a});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new P("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let u=await sZ(e);if("Booted"!==u)throw new P("COMMAND_FAILED","Simulator is still booting",{state:u})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let n=F({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==n&&"CI_RESOURCE_STARVATION_SUSPECTED"!==n}},{deadline:n,phase:"boot",classifyReason:e=>F({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(i){let a=F({error:i,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new P("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:18e4,elapsedMs:n.elapsedMs(),reason:a,hint:er(a),boot:t,bootstatus:r})}await sK()}async function sX(e){let t=rS(e,["shutdown",e.id]),r=await ry(t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function sZ(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?rA(["list","devices","-j"]):rS(e,["list","devices","-j"]),n=await ry(r,{allowFailure:!0,timeoutMs:6e4});if(0!==n.exitCode)return null;try{let e=JSON.parse(String(n.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function sY(e,t){try{let r=await rv(e),n=r?.[t];if("string"==typeof n&&n.length>0)return n}catch{}try{let r=await rg("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{var r,n;let a;return r=await d.readFile(e,"utf8"),n=t,r1(r0(r),(e,t)=>{void 0===a&&e===n&&"string"===t.name&&(a=t.text??void 0)}),a}catch{return}}async function sQ(e,t){let r;if("url"===e.kind&&!tT(e.url))throw new P("INVALID_ARGS","iOS install_from_source URL sources are only supported for trusted artifact services such as GitHub Actions and EAS. Use a path source for other hosts.");let n=await tR({source:e,isInstallablePath:(e,t)=>t.isDirectory()&&e.toLowerCase().endsWith(".app")||t.isFile()&&e.toLowerCase().endsWith(".ipa"),installableLabel:"iOS installable (.app or .ipa)",allowArchiveExtraction:"url"!==e.kind||tT(e.url),signal:t?.signal});try{let e=r=await s1(n.installablePath,t),a=await s0(e.installPath);return{archivePath:n.archivePath??(n.installablePath.toLowerCase().endsWith(".ipa")?n.installablePath:void 0),installablePath:e.installPath,bundleId:a.bundleId,appName:a.appName,cleanup:async()=>{await e.cleanup(),await n.cleanup()}}}catch(e){try{await r?.cleanup()}finally{await n.cleanup()}throw e}}async function s0(e){let t=f.join(e,"Info.plist"),[r,n,a]=await Promise.all([sY(t,"CFBundleIdentifier"),sY(t,"CFBundleDisplayName"),sY(t,"CFBundleName")]);return{bundleId:r,appName:n??a}}async function s1(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await d.mkdtemp(f.join(c.tmpdir(),"agent-device-ios-ipa-")),n=async()=>{await d.rm(r,{recursive:!0,force:!0})};try{await C("unzip",["-q",e,"-d",r]);let a=f.join(r,"Payload"),i=(await d.readdir(a,{withFileTypes:!0}).catch(()=>{throw new P("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:f.join(a,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===i.length)return{installPath:i[0].installPath,cleanup:n};if(0===i.length)throw new P("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await s2(i);let o=t?.appIdentifierHint?.trim();if(o){let e=function(e,t){let r=t.toLowerCase(),n=e.filter(e=>e.bundleName.toLowerCase()===r);if(1===n.length)return n[0];if(n.length>1)throw new P("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${t}" by name. Use a bundle id hint instead.`);if(t.includes(".")){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(1===t.length)return t[0]}}(i,o);if(e)return{installPath:e.installPath,cleanup:n};throw new P("INVALID_ARGS",`Invalid IPA: found ${i.length} .app bundles under Payload and none matched "${o}". Available bundles: ${i.map(s3).join(", ")}`)}throw new P("INVALID_ARGS",`Invalid IPA: found ${i.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${i.map(s3).join(", ")}`)}catch(e){throw await n(),e}}async function s2(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await s0(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function s3(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}let s4="agent-device-macos-helper",s5="AGENT_DEVICE_MACOS_HELPER_BIN",s8=f.join(c.homedir(),".agent-device","macos-helper","current"),s6=f.join(s8,"manifest.json"),s9=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function s7(e){let t=e.trim();if(!s9.test(t))throw new P("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function le(e,t){t.bundleId&&e.push("--bundle-id",s7(t.bundleId)),t.surface&&e.push("--surface",t.surface)}function lt(){return function(e){let t=f.dirname(e);for(;;){let e=f.join(t,"macos-helper");if(u(f.join(e,"Package.swift")))return e;let r=f.dirname(t);if(r===t)break;t=r}throw new P("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(y(import.meta.url))}async function lr(e){let t=await d.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let r=f.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await lr(r):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[r]:[]}))).flat().sort()}async function ln(e){let t=await lr(e),r=s("sha256");for(let n of t)r.update(f.relative(e,n)),r.update("\0"),r.update(await d.readFile(n)),r.update("\0");let n=await rg("swift",["--version"],{allowFailure:!0,cwd:e,timeoutMs:1e4});return r.update("swift-version"),r.update("\0"),r.update(n.stdout||n.stderr||`exit:${n.exitCode}`),r.update("\0"),r.digest("hex")}async function la(){try{let e=JSON.parse(await d.readFile(s6,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function li(){let e=await R(process.env[s5],s5);if(e)return e;let t=lt(),r=await ln(t),n=f.join(s8,s4);try{if(await la()===r)return await d.access(n),n}catch{}let a=f.join(lt(),".build","release",s4);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await rg("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await d.mkdir(s8,{recursive:!0});let i=`${n}.tmp`;return await d.copyFile(a,i),await d.rename(i,n),await d.chmod(n,493),await d.writeFile(s6,`${JSON.stringify({fingerprint:r},null,2)}
|
|
20
|
+
`,"utf8"),n}async function lo(){let e=process.env[s5]?.trim();if(e){let t=await R(e,s5);if(t)return t}if(rf.hasScope())return s4;if("darwin"!==process.platform)throw new P("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");return await li()}async function ls(e){let t={allowFailure:!0,timeoutMs:3e4},r=rh().macosHelper,n=r?s4:await lo(),a=r?await r.run(e,t):await rg(n,e,t),i=a.stdout.trim(),o=null;if(i)try{o=JSON.parse(i)}catch{o=null}if(0===a.exitCode&&o?.ok)return o.data;throw new P("COMMAND_FAILED",o&&!o.ok?o.error?.message??`macOS helper exited with code ${a.exitCode}`:i||a.stderr.trim()||`macOS helper exited with code ${a.exitCode}`,{helperPath:n,args:e,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,...o&&!o.ok?o.error?.details:{}})}async function ll(){return await ls(["app","frontmost"])}async function lu(e){return await ls(["app","quit","--bundle-id",s7(e)])}async function ld(e,t){return await ls(["permission",e,t])}async function lc(e,t={}){let r=["alert",e];return le(r,t),await ls(r)}async function lp(e,t={}){let r=["snapshot","--surface",e];return le(r,t),await ls(r)}async function lf(e,t,r={}){let n=["read","--x",String(e),"--y",String(t)];return le(n,r),await ls(n)}async function lm(e,t,r={}){let n=["press","--x",String(e),"--y",String(t)];return le(n,r),await ls(n)}async function lh(e,t={}){let r=["screenshot","--out",e];return le(r,t),t.fullscreen&&r.push("--fullscreen"),await ls(r)}let lw={settings:"com.apple.systempreferences"},lg=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/,ly={platform:"macos",deviceId:"host",variant:"all"},lv=ed();async function lI(e){let t=e.trim(),r=lw[t.toLowerCase()];if(r)return r;if(lg.test(t))return t;let n=lv.get(ly,t);if(n)return n;let a=(await lM("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return lv.set(ly,t,a[0].bundleId);if(a.length>1)throw new P("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});throw new P("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function lA(e,t,r){let n=r?.url?.trim();if(n){if(!ec(n))throw new P("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await lI(t);await lD().openBundle(e,n);return}let a=t.trim();if(ec(a))return void await lD().openTarget(a);let i=r?.appBundleId??await lI(a);await lD().openBundle(i)}async function lS(e,t){let r=await lI(t),n=await lu(r);if(n.running&&!n.terminated&&!n.forceTerminated)throw new P("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:r,running:n.running,terminated:n.terminated,forceTerminated:n.forceTerminated})}async function lb(){return await lD().readClipboard()}async function l_(e){await lD().writeClipboard(e)}async function lN(){return await lD().readDarkMode()}async function lx(e){let t=sO(e),r="toggle"===t?!await lN():"dark"===t;await lD().setDarkMode(r)}async function lM(e){return await lD().listApps(e)}function lD(){let e=rh().macosHost;if(!e)throw new P("UNSUPPORTED_OPERATION","macOS host provider is not available");return e}function lk(e){if(!(e instanceof P))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}let lP=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],lO={0:"hide",1:"wifi",6:"3g",7:"4g",8:"lte",9:"lte-a",10:"lte+",11:"5g",12:"5g+",13:"5g-uwb",14:"5g-uc"},lE={1:"searching",2:"failed",3:"active"},lC={0:"notSupported",1:"searching",2:"failed",3:"active"};function lL(e,t,r){return ry(rS(e,t),r)}async function lR(e,t){var r,n;let a;await l$(e),t&&await lF(e,(a=[],(r=t).dataNetwork&&a.push("--dataNetwork",r.dataNetwork),r.wifiMode&&a.push("--wifiMode",r.wifiMode),void 0!==r.wifiBars&&("wifi"===r.dataNetwork||r.wifiMode)&&a.push("--wifiBars",r.wifiBars),r.cellularMode&&a.push("--cellularMode",r.cellularMode),void 0!==r.cellularBars&&(r.cellularMode||(n=r.dataNetwork)&&"hide"!==n&&"wifi"!==n||void 0!==r.operatorName)&&a.push("--cellularBars",r.cellularBars),void 0!==r.operatorName&&a.push("--operatorName",r.operatorName),a))}async function lT(e){let t=await lL(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new P("COMMAND_FAILED","Failed to read simulator status bar overrides",{exitCode:t.exitCode,stdout:t.stdout,stderr:t.stderr});return function(e){let t={};for(let r of e.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&"Current Status Bar Overrides:"!==e&&!/^=+$/.test(e))){let e=/^DataNetworkType:\s+(\d+)$/.exec(r);if(e){let r=Number(e[1]),n=lO[r];if(!n)throw new P("COMMAND_FAILED",`Unsupported simulator data network type: ${r}`);t.dataNetwork=n;continue}let n=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(r);if(n){let e=lE[Number(n[1])];e&&(t.wifiMode=e),t.wifiBars=n[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(r);if(a){let e=Number(a[1]),r=lC[e];if(!r)throw new P("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=r,t.cellularBars=a[2];continue}let i=/^Operator Name:\s*(.*)$/.exec(r);if(i){t.operatorName=i[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function l$(e){await lL(e,["status_bar",e.id,"clear"])}async function lF(e,t){0!==t.length&&await lL(e,["status_bar",e.id,"override",...t])}function lU(e,t,r){eb({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...lk(r)}})}function lG(e,t,r){return ry(rS(e,t),r)}let lV={ensureBooted:sJ,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await lT(e),r=!0}catch(t){lU(e,"snapshot_failed",t)}try{await l$(e),await lF(e,lP)}catch(t){lU(e,"prepare_failed",t)}return async()=>{await lR(e,r?t:null)}},captureWithRetry:lq,captureWithRunner:lH,shouldFallbackToRunner:lZ};async function lj(e,t,r,n,a){if("macos"===e.platform)return void await lH(e,t,r,n,a);if("simulator"===e.kind)return void await lB(e,t,r,n,void 0,a);try{await oP(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",n="string"==typeof t.stderr?t.stderr:"",a=`${e.message}
|
|
21
|
+
${r}
|
|
22
|
+
${n}`.toLowerCase();return a.includes("unknown option '--device'")||a.includes("unknown subcommand")&&a.includes("screenshot")||a.includes("unrecognized subcommand")&&a.includes("screenshot")}(t))throw t;lJ(e,"devicectl_screenshot",t)}await lH(e,t,r,n,a)}async function lB(e,t,r,n,a=lV,i){if("simulator"!==e.kind)throw new P("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let o="object"==typeof n&&null!==n?n:a;await o.ensureBooted(e);let s=async()=>{};try{s=await o.prepareStatusBarForScreenshot(e)}catch(t){lX(e,"prepare_failed",t)}try{try{await o.captureWithRetry(e,t);return}catch(t){if(!o.shouldFallbackToRunner(t))throw t;lJ(e,"simctl_screenshot",t)}await o.captureWithRunner(e,t,r,"boolean"==typeof n?n:void 0,i)}finally{await s().catch(t=>lX(e,"restore_failed",t))}}async function lq(e,t){let r=ee.fromTimeoutMs(2e4);await ei(async({deadline:r})=>{await lG(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,r?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>lZ(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function lH(e,t,r,n,a){let i=(await n6(e,{command:"screenshot",appBundleId:r,fullscreen:n},a)).message;if(!i)throw new P("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await d.copyFile(i,t):"simulator"===e.kind?await lz(e,i,t):await lW(e,i,t)}async function lW(e,t,r){let n=ee.fromTimeoutMs(2e4),a={exitCode:1,stdout:"",stderr:""};for(let i of nl)if(0===(a=await ry(["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",i],{allowFailure:!0,timeoutMs:lK(n,2e4,"runner screenshot copy")})).exitCode)return;let i=a.stderr.trim()||a.stdout.trim()||`devicectl exited with code ${a.exitCode}`;throw new P("COMMAND_FAILED",`Failed to capture iOS screenshot: ${i}`)}async function lz(e,t,r){let n=ee.fromTimeoutMs(2e4),a="Unable to locate runner container for simulator screenshot";for(let i of nl){let o=await lG(e,["get_app_container",e.id,i,"data"],{allowFailure:!0,timeoutMs:lK(n,2e4,"runner screenshot container lookup")});if(0!==o.exitCode){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=f.resolve(e),n=t.trim();if(!n)return[];let a=[],i=new Set,o=e=>{let t=f.normalize(e);i.has(t)||(i.add(t),a.push(t))},s=n.replace(/^\/+/,""),l=s.replace(/\\/g,"/");if(s&&o(f.join(r,s)),f.isAbsolute(n)&&o(f.normalize(n)),l.startsWith("tmp/"))o(f.join(r,l));else{let e=l.lastIndexOf("/tmp/");if(e>=0){let t=l.slice(e+1);o(f.join(r,t))}}let u=f.basename(n);return u&&o(f.join(r,"tmp",u)),a}(s,t))try{await d.copyFile(e,r);return}catch(e){a=e instanceof Error?e.message:String(e)}}throw new P("COMMAND_FAILED",`Failed to capture iOS screenshot: ${a}`)}function lK(e,t,r){let n=e.remainingMs();if(n>0)return n;throw new P("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function lJ(e,t,r){let n=lk(r);eb({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...n}})}function lX(e,t,r){eb({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...lk(r)}})}function lZ(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",n="string"==typeof t.stderr?t.stderr:"",a=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",i=`${e.message}
|
|
23
|
+
${r}
|
|
24
|
+
${n}
|
|
25
|
+
${a}`.toLowerCase();return i.includes("timeout waiting for screen surfaces")||i.includes("nsposixerrordomain")&&i.includes("code=60")&&i.includes("screenshot")||i.includes("timed out")&&i.includes("screenshot")}let lY={settings:"com.apple.Preferences"},lQ=ed(),l0=null;function l1(e){return{platform:"ios",deviceId:e.id,variant:e.kind}}function l2(e,t,r){return ry(rS(e,t),r)}function l3(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function l4(e,t){if("macos"===e.platform)return await lI(t);let r=t.trim();if(r.includes("."))return r;let n=lY[r.toLowerCase()];if(n)return n;let a=l1(e),i=lQ.get(a,r);if(i)return i;let o=("simulator"===e.kind?await us(e):await oO(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===o.length)return lQ.set(a,r,o[0].bundleId);if(o.length>1)throw new P("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:o});throw new P("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function l5(e,t,r){if("macos"===e.platform)return void await lA(e,t,r);let n=r?.url?.trim();if(n){if(!ec(n))throw new P("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await sJ(e),await l2(e,["openurl",e.id,n]);return}let a=Q(r?.appBundleId??await l4(e,t),n);if(!a)throw new P("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await uh(e,a,{payloadUrl:n});return}let a=t.trim();if(ec(a)){if("simulator"===e.kind){await sJ(e),await l2(e,["openurl",e.id,a]);return}let t=Q(r?.appBundleId,a);if(!t)throw new P("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await uh(e,t,{payloadUrl:a});return}let i=r?.appBundleId??await l4(e,t);"simulator"===e.kind?await um(e,i):await uh(e,i)}async function l8(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await sZ(e)&&await sJ(e)}async function l6(e,t){if("macos"===e.platform)return void await lS(e,t);let r=await l4(e,t);if("simulator"===e.kind){await sJ(e);let t=rS(e,["terminate",e.id,r]),n=await ry(t,{allowFailure:!0});if(0!==n.exitCode){if(n.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new P("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}return}await oP(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function l9(e,t){return await lQ.invalidateWhile(l1(e),async()=>{let r=await l4(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],n=await ry(t,{allowFailure:!0,timeoutMs:2e4});if(0!==n.exitCode){let a=String(n.stdout??""),i=String(n.stderr??"");if(!l3(`${a}
|
|
26
|
+
${i}`.toLowerCase()))throw new P("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:n.exitCode,stdout:a,stderr:i,deviceId:e.id,hint:oR(a,i)??oL})}return{bundleId:r}}await sJ(e);let n=await l2(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==n.exitCode&&!l3(`${n.stdout}
|
|
27
|
+
${n.stderr}`.toLowerCase()))throw new P("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});return{bundleId:r}})}async function l7(e,t,r){let n=await sQ({kind:"path",path:t},r);try{return await ut(e,n.installablePath),{archivePath:n.archivePath,installablePath:n.installablePath,bundleId:n.bundleId,appName:n.appName,launchTarget:n.bundleId}}finally{await n.cleanup()}}async function ue(e,t,r){return await lQ.invalidateWhile(l1(e),async()=>{let{bundleId:n}=await l9(e,t);return await l7(e,r,{appIdentifierHint:t}),{bundleId:n}})}async function ut(e,t){await lQ.invalidateWhile(l1(e),async()=>{"simulator"!==e.kind?await oP(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await sJ(e),await l2(e,["install",e.id,t]))})}async function ur(e){if("macos"===e.platform)return await lb();sz(e,"clipboard"),await sJ(e);let t=await l2(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new P("COMMAND_FAILED","Failed to read iOS simulator clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return t.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function un(e,t){if("macos"===e.platform)return void await l_(t);sz(e,"clipboard"),await sJ(e);let r=await l2(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new P("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function ua(e,t,r){sz(e,"push"),await sJ(e);let n=await d.mkdtemp(f.join(c.tmpdir(),"agent-device-ios-push-")),a=f.join(n,"payload.apns");try{await d.writeFile(a,`${JSON.stringify(r)}
|
|
28
|
+
`,"utf8"),await l2(e,["push",e.id,t,a])}finally{await d.rm(n,{recursive:!0,force:!0})}}async function ui(e,t,r,n,a){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await lx(r);if("permission"===e){let e=sk(r);if("deny"===e)throw new P("INVALID_ARGS",tb("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new P("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(a?.permissionTarget);return await ld(e,t)}throw new P("INVALID_ARGS",tb(t))}sz(e,"settings"),await sJ(e);let i=t.toLowerCase();switch(i){case"wifi":{let t=sE(r);await l2(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(sE(r)?await l2(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await l2(e,["status_bar",e.id,"clear"]));case"location":{if("set"===r.toLowerCase()){let{latitude:t,longitude:r}=eG(a);return await l2(e,["location",e.id,"set",`${t},${r}`]),{latitude:t,longitude:r}}let t=sE(r);if(!n)throw new P("INVALID_ARGS","location setting requires an active app in session");await l2(e,["privacy",e.id,t?"grant":"revoke","location",n]);return}case"faceid":case"touchid":{let t=uu[i],n=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new P("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,i);await uf(e,n,{settingName:i,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await ul(e,r);await l2(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!n)throw new P("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=sk(r))?"revoke":o,i=function(e,t){let r=sP(e);if("photos"!==r&&t?.trim())throw new P("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return"camera";if("microphone"===r)return"microphone";if("contacts"===r)return"contacts";if("contacts-limited"===r)return"contacts-limited";if("notifications"===r)return"notifications";if("calendar"===r)return"calendar";if("location"===r)return"location";if("location-always"===r)return"location-always";if("media-library"===r)return"media-library";if("motion"===r)return"motion";if("reminders"===r)return"reminders";if("siri"===r)return"siri";if("photos"===r){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new P("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new P("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(a?.permissionTarget,a?.permissionMode);await ud(e,t,i,n);return}default:throw new P("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function uo(e,t){return"macos"===e.platform?await lM(t):"simulator"===e.kind?rs(await us(e),t):await oO(e,t)}async function us(e){let t=(await l2(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let r=null;if(t.startsWith("{"))try{r=JSON.parse(t)}catch{r=null}if(!r&&t.startsWith("{"))try{let e=await rg("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}async function ul(e,t){let r=sO(t);if("toggle"!==r)return r;let n=await l2(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==n.exitCode)throw new P("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});let a=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
|
|
29
|
+
${t}`);if(!r)return null;let n=r[1].toLowerCase();return"dark"===n?"dark":"light"===n?"light":null}(n.stdout,n.stderr);if(!a)throw new P("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:n.stdout,stderr:n.stderr});return"dark"===a?"light":"dark"}let uu={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function ud(e,t,r,n){let a=await up(e);if(!a.has(r))throw new P("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:n,hint:`Supported services: ${Array.from(a).sort().join(", ")}`});let i=["privacy",e.id,t,r,n],o="notifications"===r;if(!("reset"===t&&o))try{await l2(e,i);return}catch(t){if(!(o&&uc(t)))throw t;throw new P("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:n,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await l2(e,i);return}catch(e){if(!uc(e))throw e}try{await l2(e,["privacy",e.id,"reset","all",n])}catch(t){throw new P("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:n,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function uc(e){if(!(e instanceof P)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return(t.includes("failed to grant access")||t.includes("failed to revoke access")||t.includes("failed to reset access"))&&t.includes("operation not permitted")}async function up(t){let r=Z(t.simulatorSetPath),n=`${process.env.PATH??""}::${r??""}`;if(l0&&e===n)return l0;let a=await l2(t,["privacy","help"],{allowFailure:!0}),i=function(e){let t=new Set,r=!1;for(let n of e.split("\n")){let e=n.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let a=/^([a-z-]+)\s+-\s+/.exec(e);a&&t.add(a[1])}return t}(`${a.stdout}
|
|
30
|
+
${a.stderr}`);if(0===i.size)throw new P("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return l0=i,e=n,i}async function uf(e,t,r){let n=function(e,t,r){let n=r.length>0?r:["face"];switch(t){case"match":return n.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return n.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),a=[];for(let t of n){let r=rS(e,t),n=await ry(r,{allowFailure:!0});if(0===n.exitCode)return;a.push({args:r,stderr:n.stderr,stdout:n.stdout,exitCode:n.exitCode})}let i=sM(a);if(a.length>0&&a.every(e=>{var t,r;let n;return t=e.stdout,r=e.stderr,(n=`${t}
|
|
31
|
+
${r}`.toLowerCase()).includes("unrecognized subcommand")||n.includes("unknown subcommand")||n.includes("not supported")||n.includes("unavailable")||n.includes("biometric")&&n.includes("invalid")}))throw new P("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:i});throw new P("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:i})}async function um(e,t){await sJ(e);let r=0,n=ee.fromTimeoutMs(6e4);try{await ei(async({deadline:r})=>{var n;if(r?.isExpired())throw new P("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:6e4});let a=(n=["launch",e.id,t],rS(e,n)),i=await ry(a,{allowFailure:!0});if(0!==i.exitCode)throw new P("COMMAND_FAILED",`xcrun exited with code ${i.exitCode}`,{cmd:"xcrun",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!sH(e)&&(r+=1)<3},{deadline:n})}catch(r){if(sH(r)){var a;let n=(a=await sW(e,t)).installed?!1===a.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(n)}}throw r}}async function uh(e,t,r){let n=["device","process","launch","--device",e.id,t];r?.payloadUrl&&n.push("--payload-url",r.payloadUrl),await oP(n,{action:"launch iOS app",deviceId:e.id})}function uw(e,t,r){return{command:"remotePress",remoteButton:e,...void 0!==r?{durationMs:r}:{},...void 0!==t?{appBundleId:t}:{}}}async function ug(e,t,r,n,a,i,o){if("tv"===t.target)return uI(await e(t,uw(a,r.appBundleId),n),i);let s=o??await uy(e,t,r,n),l=oB({direction:a,amount:i?.amount,pixels:i?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return uI(await e(t,{command:"drag",x:s.originX+l.x1,y:s.originY+l.y1,x2:s.originX+l.x2,y2:s.originY+l.y2,appBundleId:r.appBundleId},n),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function uy(e,t,r,n){let a=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},n),i=uv(a.x),o=uv(a.y),s=uv(a.referenceWidth),l=uv(a.referenceHeight);if(void 0===i||void 0===o||void 0===s||void 0===l)throw new P("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:i,originY:o,referenceWidth:s,referenceHeight:l}}function uv(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function uI(e,t){var r;let{x1:n,y1:a,x2:i,y2:o}={x1:uv((r=e).x),y1:uv(r.y),x2:uv(r.x2),y2:uv(r.y2)},s=uv(e.referenceWidth),l=uv(e.referenceHeight),u=void 0!==n&&void 0!==i?Math.round(Math.abs(i-n)):void 0,d=void 0!==a&&void 0!==o?Math.round(Math.abs(o-a)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:u&&u>0?u:d&&d>0?d:void 0;return{...void 0!==n?{x1:n}:{},...void 0!==a?{y1:a}:{},...void 0!==i?{x2:i}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}let uA=null;async function uS(){let e=oy();if(uA?.provider===e)return uA;let t=process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11";if("wayland"===t){if(await e.whichCommand("ydotool"))return uA={tool:"ydotool",display:t,provider:e};throw new P("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await e.whichCommand("xdotool"))return uA={tool:"xdotool",display:t,provider:e};throw new P("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function ub(...e){await oy().runCommand("xdotool",e,{allowFailure:!1,timeoutMs:1e4})}async function u_(...e){await oy().runCommand("ydotool",e,{allowFailure:!1,timeoutMs:1e4})}function uN(){return oy().input}async function ux(e,t){let{tool:r}=await uS();"xdotool"===r?await ub("mousemove","--sync",String(e),String(t)):await u_("mousemove","--absolute","-x",String(e),"-y",String(t))}async function uM(e,t){let r=uN();if(r)return void await r.key(e,t);let{tool:n}=await uS();"xdotool"===n?await ub("key","--clearmodifiers",e):await u_("key",...t)}async function uD(e,t,r,n){await ux(e,t);let{tool:a}=await uS();"xdotool"===a?await ub("click",r):await u_("click",n)}async function uk(e,t,r,n,a){let i=uN();i?await i.click(e,t,r):await uD(e,t,n,a)}async function uP(e,t){await uk(e,t,"primary","1","0xC0")}async function uO(e,t){await uk(e,t,"secondary","3","0xC1")}async function uE(e,t){await uk(e,t,"middle","2","0xC2")}async function uC(e,t){let r=uN();if(r)return void await r.doubleClick(e,t);let{tool:n}=await uS();await ux(e,t),"xdotool"===n?await ub("click","--repeat","2","1"):(await u_("click","0xC0"),await u_("click","0xC0"))}async function uL(e,t,r=800){let n=uN();if(n)return void await n.longPress(e,t,r);let{tool:a}=await uS();await ux(e,t),"xdotool"===a?(await ub("mousedown","1"),await ex(r),await ub("mouseup","1")):(await u_("click","--down","0xC0"),await ex(r),await u_("click","--up","0xC0"))}async function uR(e,t){await uP(e,t)}async function uT(e,t,r,n,a=300){let i=uN();if(i)return void await i.drag(e,t,r,n,a);let{tool:o}=await uS();await ux(e,t),"xdotool"===o?(await ub("mousedown","1"),await ub("mousemove","--sync",String(r),String(n)),await ex(a),await ub("mouseup","1")):(await u_("click","--down","0xC0"),await u_("mousemove","--absolute","-x",String(r),"-y",String(n)),await ex(a),await u_("click","--up","0xC0"))}async function u$(e,t){let r=uN();if(r)return void await r.scroll(e,t);let{tool:n}=await uS(),a=5;if(t?.pixels!=null?a="xdotool"===n?Math.max(1,Math.round(t.pixels/15)):Math.max(1,Math.round(t.pixels/40)):t?.amount!=null&&(a=Math.max(1,Math.round(5*(t.amount/.6)))),"xdotool"===n)await ub("click","--repeat",String(a),"up"===e?"4":"down"===e?"5":"left"===e?"6":"7");else if("up"===e||"down"===e){let t="up"===e?String(-a):String(a);await u_("mousemove","--wheel","-y",t)}else{let t="left"===e?String(-a):String(a);await u_("mousemove","--wheel","-x",t)}}async function uF(e,t=0){let r=uN();if(r)return void await r.typeText(e,{delayMs:t});let{tool:n}=await uS();if("xdotool"===n){let r=["type"];t>0&&r.push("--delay",String(t)),r.push("--clearmodifiers","--",e),await ub(...r)}else await u_("type","--",e)}async function uU(e,t,r,n=0){await uP(e,t),await ex(100),await uM("ctrl+a",["29:1","30:1","30:0","29:0"]),await ex(50),await uF(r,n)}async function uG(e){await oy().desktop.openTarget(e)}async function uV(e){await oy().desktop.closeApp(e)}async function uj(){await uM("alt+Left",["56:1","105:1","105:0","56:0"])}async function uB(){await uM("super+d",["125:1","32:1","32:0","125:0"])}async function uq(){return await oy().clipboard.readText()}async function uH(e){await oy().clipboard.writeText(e)}async function uW(e,t){await oy().screenshot.capture(e,t)}let uz={"push button":"Button","toggle button":"Button","push button menu":"Button",label:"StaticText",static:"StaticText",caption:"StaticText",text:"TextField",entry:"TextField","password text":"TextField","spin button":"TextField",terminal:"TextArea","document text":"TextArea",paragraph:"TextArea",frame:"Window",window:"Window",dialog:"Dialog",alert:"Alert","file chooser":"Dialog","color chooser":"Dialog","font chooser":"Dialog",panel:"Group",filler:"Group",section:"Group",form:"Group",grouping:"Group","layered pane":"Group","glass pane":"Group","root pane":"Group","option pane":"Group","internal frame":"Group","desktop frame":"Group","block quote":"Group",article:"Group",comment:"Group",landmark:"Group",log:"Group",marquee:"Group",math:"Group",notification:"Group","content deletion":"Group","content insertion":"Group",mark:"Group",suggestion:"Group","scroll pane":"ScrollArea","scroll bar":"ScrollBar","menu bar":"MenuBar",menu:"Menu","popup menu":"Menu","menu item":"MenuItem","check menu item":"MenuItem","radio menu item":"MenuItem","tearoff menu item":"MenuItem","check box":"CheckBox","radio button":"RadioButton",switch:"Switch","combo box":"ComboBox","page tab":"Tab","page tab list":"TabList",table:"Table","tree table":"Table","table cell":"Cell","table row":"Row","table column header":"Cell","table row header":"Cell","column header":"Cell","row header":"Cell",list:"List","list item":"ListItem","list box":"List",tree:"Tree","tree item":"TreeItem","description list":"List","description term":"ListItem","description value":"ListItem","tool bar":"Toolbar","status bar":"StatusBar","info bar":"StatusBar",slider:"Slider","progress bar":"ProgressBar","level bar":"ProgressBar",image:"Image",icon:"Image",animation:"Image",canvas:"Image","drawing area":"Image",video:"Video",audio:"Audio",link:"Link",hyperlink:"Link",separator:"Separator",application:"Application","tool tip":"Tooltip",timer:"Timer",heading:"Heading",footnote:"Footnote","title bar":"TitleBar","date editor":"DateEditor",rating:"Slider"},uK="atspi-dump.py",uJ=null;async function uX(e,t={}){let r,n=oy().accessibility;if(n)return await n.captureTree(e,t);if("linux"!==process.platform)throw new P("UNSUPPORTED_PLATFORM","AT-SPI2 bridge is only available on Linux");if(!await oy().whichCommand("python3"))throw new P("TOOL_MISSING","python3 is required for AT-SPI2 accessibility snapshots on Linux.");let a=t.maxNodes??1500,i=t.maxDepth??12,o=t.maxApps??24,s=[function(){if(uJ)return uJ;let e=f.dirname(y(import.meta.url));for(let t=0;t<5;t++){let r=f.join(e,"src","platforms","linux",uK);if(l.existsSync(r))return uJ=r,r;if(0===t){let t=f.join(e,uK);if(l.existsSync(t))return uJ=t,t}e=f.dirname(e)}throw new P("TOOL_MISSING",`Cannot find ${uK}. Ensure the agent-device package is installed correctly.`)}(),"--surface",e,"--max-nodes",String(a),"--max-depth",String(i),"--max-apps",String(o)],u=await oI("python3",s,{allowFailure:!0,timeoutMs:3e4});if(0!==u.exitCode){let e=u.stderr.trim();if(e.includes("No module named")||e.includes("gi.require_version"))throw new P("TOOL_MISSING","AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.",{cause:e});throw new P("COMMAND_FAILED",`AT-SPI2 snapshot failed (exit ${u.exitCode}): ${e||u.stdout}`)}try{r=JSON.parse(u.stdout)}catch{throw new P("COMMAND_FAILED",`AT-SPI2 snapshot returned invalid JSON: ${u.stdout.slice(0,200)}`)}if(r.error)throw new P("COMMAND_FAILED",`AT-SPI2: ${r.error}`);return{nodes:(r.nodes??[]).map(e=>{let t,r;return{index:e.index,type:(r=uz[t=e.role.toLowerCase().trim()])||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0}}),truncated:r.truncated,surface:e}}async function uZ(e){let t="desktop"===e?"desktop":"frontmost-app"===e||"app"===e?"frontmost-app":("menubar"===e&&eb({level:"warn",phase:"linux_snapshot",data:{message:"menubar surface is not supported on Linux, falling back to desktop"}}),"desktop"),r=await uX(t);return{nodes:r.nodes,truncated:r.truncated}}async function uY(e,t,r){let{nodes:n}=await uZ(r);for(let r of n.filter(r=>{let n=r.rect;return!!n&&e>=n.x&&t>=n.y&&e<=n.x+n.width&&t<=n.y+n.height}).sort((e,t)=>{let r=e.depth??0,n=t.depth??0;return r!==n?n-r:uQ(e.rect)-uQ(t.rect)})){let e=function(e){for(let t of[e.value,e.label,e.identifier])if("string"==typeof t&&t.length>0)return t;return""}(r);if(e.trim())return e}return""}function uQ(e){return(e?.width??0)*(e?.height??0)}let u0=/^[A-Za-z0-9_.:-]{1,64}$/;function u1(e){return e?.clickButton??"primary"}function u2(e){return"primary"===e.button?null:"click"!==e.commandLabel?new P("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform&&"linux"!==e.platform?new P("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS and Linux`):"macos"===e.platform&&"middle"===e.button?new P("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new P("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let u3=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];async function u4(e,t,r){for(let n=0;n<e;n+=1)await r(n),n<e-1&&t>0&&await ex(t)}async function u5(e,t){let r=Number(t[0]),n=Number(t[1]),a=t[2]?Number(t[2]):void 0;if(Number.isNaN(r)||Number.isNaN(n))throw new P("INVALID_ARGS","longpress requires x y [durationMs]",{hint:"Direct platform longpress requires coordinates. In an open daemon session, use agent-device longpress @ref|selector [durationMs]; otherwise run snapshot -i -c, use the target rect center as x y, then retry longpress x y durationMs."});return await e.longPress(r,n,a),{x:r,y:n,durationMs:a,...e$(`Long pressed (${r}, ${n})`)}}async function u8(e,t){let[r,n]=t.map(Number);if(Number.isNaN(r)||Number.isNaN(n))throw new P("INVALID_ARGS","focus requires x y");return await e.focus(r,n),{x:r,y:n,...e$(`Focused (${r}, ${n})`)}}async function u6(e,t,r){let n=tD(t[0]);if(n)throw new P("INVALID_ARGS",`type does not accept a target ref like "${n}"`,{hint:`Use fill ${n} "text" to target that field, or press ${n} then type "text" to append.`});let a=t.join(" ");if(!a)throw new P("INVALID_ARGS","type requires text");let i=t_(r?.delayMs??0,"delay-ms",0,1e4);return await e.type(a,i),{text:a,delayMs:i,...e$(dw("Typed",a))}}async function u9(e,t,r){let n=Number(t[0]),a=Number(t[1]),i=t.slice(2).join(" ");if(Number.isNaN(n)||Number.isNaN(a)||!i)throw new P("INVALID_ARGS","fill requires x y text");let o=t_(r?.delayMs??0,"delay-ms",0,1e4);return await e.fill(n,a,i,o),{x:n,y:a,text:i,delayMs:o,...e$(dw("Filled",i))}}async function u7(e,t,r,n){var a,i,o,s;if(n?.directElementSelector&&"ios"===e.platform)return await de(t,n.directElementSelector);let{x:l,y:u}=function(e,t){let[r,n]=e.map(Number);if(Number.isNaN(r)||Number.isNaN(n))throw new P("INVALID_ARGS",t);return{x:r,y:n}}(r,"press requires x y");if("macos"===e.platform&&n?.surface&&"app"!==n.surface)return await dt(l,u,n);let d=u1(n);if("primary"!==d)return await dr(e,l,u,d,n);let c=(s=n,{count:da(s?.count,1,"count",1,200),intervalMs:da(s?.intervalMs,0,"interval-ms",0,1e4),holdMs:da(s?.holdMs,0,"hold-ms",0,1e4),jitterPx:da(s?.jitterPx,0,"jitter-px",0,100),doubleTap:!!s?.doubleTap});return(function({doubleTap:e,holdMs:t,jitterPx:r}){if(e&&t>0)throw new P("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(e&&r>0)throw new P("INVALID_ARGS","double-tap cannot be combined with jitter-px")}(c),a=c.count,i=c.holdMs,o=c.jitterPx,rW(e.platform)&&a>1&&0===i&&0===o)?await di(e,l,u,c,n):await ds(t,l,u,c)}async function de(e,t){if(!e.tapElementSelector)throw new P("UNSUPPORTED_OPERATION","direct element selector tap is not supported");let r=await e.tapElementSelector(t);return{selector:t.raw,...r??{},...e$(`Tapped ${t.raw}`)}}async function dt(e,t,r){let n=u1(r);if("primary"!==n)throw new P("UNSUPPORTED_OPERATION",`${n} click is not supported on macOS ${r.surface} sessions.`);return await lm(e,t,{bundleId:r.appBundleId,surface:r.surface}),{x:e,y:t,...e$(dm({x:e,y:t}))}}async function dr(e,t,r,n,a){return(function(e,t,r){let n=u2({commandLabel:"click",platform:e.platform,button:t,count:r?.count,intervalMs:r?.intervalMs,holdMs:r?.holdMs,jitterPx:r?.jitterPx,doubleTap:r?.doubleTap});if(n)throw n}(e,n,a),"linux"===e.platform)?await dn(t,r,n):(await n6(e,{command:"mouseClick",x:t,y:r,button:n,appBundleId:a?.appBundleId},dl(a)),{x:t,y:r,button:n,...e$(dm({x:t,y:r,button:n}))})}async function dn(e,t,r){return"secondary"===r?await uO(e,t):await uE(e,t),{x:e,y:t,button:r,...e$(dm({x:e,y:t,button:r}))}}function da(e,t,r,n,a){return t_(void 0===e?t:e,r,n,a)}async function di(e,t,r,n,a){let i=await n6(e,{command:"tapSeries",x:t,y:r,count:n.count,intervalMs:n.intervalMs,doubleTap:n.doubleTap,appBundleId:a?.appBundleId},dl(a));return{x:t,y:r,count:n.count,intervalMs:n.intervalMs,holdMs:n.holdMs,jitterPx:n.jitterPx,doubleTap:n.doubleTap,timingMode:"runner-series",...i,...e$(dm({x:t,y:r}))}}async function ds(e,t,r,n){let a;return await u4(n.count,n.intervalMs,async i=>{let[o,s]=function(e,t){if(t<=0)return[0,0];let[r,n]=u3[e%u3.length];return[r*t,n*t]}(i,n.jitterPx),l=t+o,u=r+s;if(n.doubleTap){a??=await e.doubleTap(l,u)??void 0;return}n.holdMs>0?a??=await e.longPress(l,u,n.holdMs)??void 0:a??=await e.tap(l,u)??void 0}),eq({x:t,y:r,count:n.count,intervalMs:n.intervalMs,holdMs:n.holdMs,jitterPx:n.jitterPx,doubleTap:n.doubleTap,...a},dm({x:t,y:r}))}function dl(e){return{verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,requestId:e?.requestId}}async function du(e,t,r,n){let a=Number(r[0]),i=Number(r[1]),o=Number(r[2]),s=Number(r[3]);if([a,i,o,s].some(Number.isNaN))throw new P("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=t_(r[4]?Number(r[4]):250,"durationMs",16,1e4),u="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,d=t_(n?.count??1,"count",1,200),c=t_(n?.pauseMs??0,"pause-ms",0,1e4),p=n?.pattern??"one-way";if("one-way"!==p&&"ping-pong"!==p)throw new P("INVALID_ARGS",`Invalid pattern: ${p}`);if(rW(e.platform)&&d>1){let t=await n6(e,{command:"dragSeries",x:a,y:i,x2:o,y2:s,durationMs:u,count:d,pauseMs:c,pattern:p,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId});return{x1:a,y1:i,x2:o,y2:s,durationMs:l,effectiveDurationMs:u,timingMode:"runner-series",count:d,pauseMs:c,pattern:p,...t,...e$(dh(d,p))}}return await u4(d,c,async e=>{"ping-pong"===p&&e%2==1?await t.swipe(o,s,a,i,u):await t.swipe(a,i,o,s,u)}),eq({x1:a,y1:i,x2:o,y2:s,durationMs:l,effectiveDurationMs:u,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:d,pauseMs:c,pattern:p},dh(d,p))}async function dd(e,t,r){var n;let a=t[0],i=t[1]?Number(t[1]):void 0,o=r?.pixels;if(!a)throw new P("INVALID_ARGS","scroll requires direction");if(void 0!==i&&!Number.isFinite(i))throw new P("INVALID_ARGS","scroll amount must be a number");if(void 0!==i&&void 0!==o)throw new P("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let s="bottom"===(n=a)?{direction:"down",edge:"bottom"}:"top"===n?{direction:"up",edge:"top"}:{direction:function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new P("INVALID_ARGS",`Unknown direction: ${e}`)}}(n)},l={},u=0;if(s.edge){let t=s.edge,n=await tA({edge:t,captureState:async n=>await dc(e,r,t,n),scroll:async()=>await e.scroll(s.direction,{amount:i,pixels:o})});l=n.result??{},u=n.passes}else l=await e.scroll(s.direction,{amount:i,pixels:o}),u=1;return eq({direction:s.direction,...s.edge?{edge:s.edge,passes:u}:{},...void 0!==i?{amount:i}:{},...void 0!==o?{pixels:o}:{},...l},tc(s.direction,s.edge,u,i,o))}async function dc(e,t,r,n){if("function"!=typeof e.snapshot)throw new P("UNSUPPORTED_OPERATION",`scroll ${r} requires snapshot support to verify hidden content before scrolling`);let a=e.snapshot;return await th({edge:r,scope:n,captureNodes:async e=>(await a({appBundleId:t?.appBundleId,compact:!0,scope:e})).nodes??[]})}async function dp(e,t,r){if("android"===e.platform)throw new P("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("tv"===e.target)throw new P("UNSUPPORTED_OPERATION","pinch is not supported on tvOS");if("macos"===e.platform&&r?.surface&&"app"!==r.surface)throw new P("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let n=Number(t[0]),a=t[1]?Number(t[1]):void 0,i=t[2]?Number(t[2]):void 0;if(Number.isNaN(n)||n<=0)throw new P("INVALID_ARGS","pinch requires scale > 0");return await n6(e,{command:"pinch",scale:n,x:a,y:i,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId}),{scale:n,x:a,y:i,...e$(`Pinched to scale ${n}`)}}async function df(e,t,r){let[n,a]=t.map(Number);if(Number.isNaN(n)||Number.isNaN(a))throw new P("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await se(e,n,a)??""};if("linux"===e.platform)return{action:"read",text:await uY(n,a,r?.surface)};if("macos"===e.platform&&r?.surface&&"app"!==r.surface)return{action:"read",text:(await lf(n,a,{bundleId:r.appBundleId,surface:r.surface})).text};let i=await n6(e,{command:"readText",x:n,y:a,appBundleId:r?.appBundleId},{verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath,requestId:r?.requestId});return{action:"read",text:"string"==typeof i.text?i.text:"string"==typeof i.message?i.message:""}}function dm(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function dh(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function dw(e,t){return`${e} ${Array.from(t).length} chars`}function dg(e,t){let r,n=t?.subject??"Payload",a=e.trim();if(!a)throw new P("INVALID_ARGS",`${n} cannot be empty`);let i=t?.expandPath?t.expandPath(a,t.cwd):a;try{if(!l.statSync(i).isFile())throw new P("INVALID_ARGS",`${n} path is not a file: ${i}`);return{kind:"file",path:i}}catch(t){if(t instanceof P)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new P("INVALID_ARGS",`${n} file is not readable: ${i}`);if(e&&"ENOENT"!==e)throw new P("COMMAND_FAILED",`Unable to read ${n} file: ${i}`,{cause:String(t)})}if((r=a.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:a};throw new P("INVALID_ARGS",`${n} file not found: ${i}`)}async function dy(e){let t=dg(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await dv(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new P("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof P)throw t;throw new P("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function dv(e){try{return await d.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new P("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new P("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new P("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new P("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}async function dI(e,t,r,n,a){let i={requestId:a?.requestId,appBundleId:a?.appBundleId,verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>j(e,t,r?.activity),openDevice:()=>H(e),close:t=>B(e,t),tap:(t,r)=>so(e,t,r),doubleTap:async(t,r)=>{await so(e,t,r),await so(e,t,r)},swipe:(t,r,n,a,i)=>ss(e,t,r,n,a,i),longPress:(t,r,n)=>sp(e,t,r,n),focus:(t,r)=>sm(e,t,r),type:(t,r)=>sf(e,t,r),fill:(t,r,n,a)=>sh(e,t,r,n,a),scroll:(t,r)=>sg(e,t,r),screenshot:(t,r)=>sV(e,t,r),snapshot:async t=>{let r=await eS("snapshot_capture",async()=>await oX(e,{interactiveOnly:t?.interactiveOnly,compact:t?.compact,depth:t?.depth,scope:t?.scope,raw:t?.raw}),{backend:"android"});return{nodes:r.nodes??[],truncated:r.truncated??!1,backend:"android",analysis:r.analysis,androidSnapshot:r.androidSnapshot}},back:t=>sl(e),home:()=>su(e),rotate:t=>sd(e,t),appSwitcher:()=>sc(e),readClipboard:()=>K(e),writeClipboard:t=>V(e,t),setSetting:(t,r,n,a)=>sL(e,t,r,n,a)};case"linux":return{open:e=>uG(e),openDevice:()=>Promise.resolve(),close:e=>uV(e),tap:(e,t)=>uP(e,t),doubleTap:(e,t)=>uC(e,t),swipe:(e,t,r,n,a)=>uT(e,t,r,n,a),longPress:(e,t,r)=>uL(e,t,r),focus:(e,t)=>uR(e,t),type:(e,t)=>uF(e,t),fill:(e,t,r,n)=>uU(e,t,r,n),scroll:(e,t)=>u$(e,t),screenshot:(e,t)=>uW(e,t),snapshot:async e=>{let t=await eS("snapshot_capture",async()=>await uZ(e?.surface),{backend:"linux-atspi"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"linux-atspi"}},back:()=>uj(),home:()=>uB(),rotate:()=>{throw new P("UNSUPPORTED_OPERATION","rotate not supported on Linux")},appSwitcher:()=>{throw new P("UNSUPPORTED_OPERATION","appSwitcher not yet supported on Linux")},readClipboard:()=>uq(),writeClipboard:e=>uH(e),setSetting:()=>{throw new P("UNSUPPORTED_OPERATION","setSetting not supported on Linux")}};case"ios":case"macos":return function(e,t){let r,{overrides:n,runnerOpts:a}={runnerOpts:r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},overrides:{tap:async(n,a)=>await n6(e,{command:"tap",x:n,y:a,appBundleId:t.appBundleId},r),tapElementSelector:async n=>await n6(e,{command:"tap",selectorKey:n.key,selectorValue:n.value,appBundleId:t.appBundleId},r),doubleTap:async(n,a)=>await n6(e,{command:"tapSeries",x:n,y:a,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(n,a,i,o,s)=>await n6(e,{command:"drag",x:n,y:a,x2:i,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(n,a,i)=>await n6(e,{command:"longPress",x:n,y:a,durationMs:i,appBundleId:t.appBundleId},r),focus:async(n,a)=>await n6(e,{command:"tap",x:n,y:a,appBundleId:t.appBundleId},r),type:async(n,a)=>{await n6(e,{command:"type",text:n,delayMs:a,textEntryMode:"append",appBundleId:t.appBundleId},r)},fill:async(n,a,i,o)=>await n6(e,{command:"type",x:n,y:a,text:i,delayMs:o,textEntryMode:"replace",appBundleId:t.appBundleId},r),scroll:async(n,a)=>await ug(n6,e,t,r,n,a)}};return{open:(t,r)=>l5(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>l8(e),close:t=>l6(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await lh(t,{surface:r.surface,fullscreen:r.fullscreen}):await lj(e,t,r?.appBundleId,r?.fullscreen,a)},snapshot:async t=>{var r;let n={nodes:Array.isArray((r=await eS("snapshot_capture",async()=>await n6(e,{command:"snapshot",appBundleId:t?.appBundleId,interactiveOnly:t?.interactiveOnly,compact:t?.compact,depth:t?.depth,scope:t?.scope,raw:t?.raw},a),{backend:"xctest"})).nodes)?r.nodes:void 0,truncated:"boolean"==typeof r.truncated?r.truncated:void 0},i=n.nodes??[];if(0===i.length&&"simulator"===e.kind)throw new P("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:i,truncated:n.truncated??!1,backend:"xctest"}},back:async r=>{"tv"===e.target?await n6(e,uw("menu",t.appBundleId),a):await n6(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},a)},home:async()=>{"tv"===e.target?await n6(e,uw("home",t.appBundleId),a):await n6(e,{command:"home",appBundleId:t.appBundleId},a)},rotate:async r=>{await n6(e,{command:"rotate",orientation:r,appBundleId:t.appBundleId},a)},appSwitcher:async()=>{await n6(e,{command:"appSwitcher",appBundleId:t.appBundleId},a)},readClipboard:()=>ur(e),writeClipboard:t=>un(e,t),setSetting:(t,r,n,a)=>ui(e,t,r,n,a),...n}}(e,t);default:throw new P("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,i);return eb({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await eS("platform_command",async()=>{switch(t){case"open":return dA(e,o,r,a);case"close":{let e=r[0];if(!e)return{closed:"session",...e$("Closed session")};return await o.close(e),{app:e,...e$(`Closed: ${e}`)}}case"press":return u7(e,o,r,a);case"swipe":return du(e,o,r,a);case"longpress":return u5(o,r);case"focus":return u8(o,r);case"type":return u6(o,r,a);case"fill":return u9(o,r,a);case"scroll":return dd(o,r,a);case"pinch":return dp(e,r,a);case"trigger-app-event":{let{eventName:t,payload:n}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new P("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!u0.test(t))throw new P("INVALID_ARGS",`Invalid trigger-app-event event name: ${t}`,{hint:"Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash."});if(e.length>2)throw new P("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let n=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new P("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let n=JSON.stringify(r);if(Buffer.byteLength(n,"utf8")>8192)throw new P("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof P)throw t;throw new P("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:n}}(r),i=function(e,t,r){var n;let a,i=(a=("ios"===(n=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===n?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,a?.trim()||void 0);if(!i)throw new P("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=i.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new P("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,n);return await o.open(i,{appBundleId:a?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link",...e$(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??n??`./screenshot-${Date.now()}.png`;await d.mkdir(f.dirname(e),{recursive:!0});let t=eU(a);return await o.screenshot(e,{appBundleId:a?.appBundleId,fullscreen:t.fullscreen,stabilize:t.stabilize,surface:a?.surface}),{path:e,...e$(`Saved screenshot: ${e}`)}}case"back":return await o.back(a?.backMode),{action:"back",mode:a?.backMode??"in-app",...e$("Back")};case"home":return await o.home(),{action:"home",...e$("Home")};case"rotate":{let e=tx(r[0]);return await o.rotate(e),{action:"rotate",orientation:e,...e$(`Rotated to ${e}`)}}case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...e$("Opened app switcher")};case"clipboard":return dS(o,r);case"keyboard":return db(e,r,a,i);case"settings":return d_(e,o,r,a);case"push":return dN(e,r,a);case"snapshot":return await dx(o,a);case"read":return df(e,r,a);default:throw new P("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}async function dA(e,t,r,n){let a=r[0],i=r[1];if(r.length>2)throw new P("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!a)return await t.openDevice(),{app:null,...e$("Opened device")};if(void 0!==i){if("android"===e.platform)throw new P("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(ec(a))throw new P("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!ec(i))throw new P("INVALID_ARGS","open <app> <url> requires a valid URL target");return await t.open(a,{activity:n?.activity,appBundleId:n?.appBundleId,url:i}),{app:a,url:i,...e$(`Opened: ${a}`)}}return await t.open(a,{activity:n?.activity,appBundleId:n?.appBundleId}),{app:a,...e$(`Opened: ${a}`)}}async function dS(e,t){let r=(t[0]??"").toLowerCase();if("read"!==r&&"write"!==r)throw new P("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===r){if(1!==t.length)throw new P("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:r,text:await e.readClipboard()}}if(t.length<2)throw new P("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let n=t.slice(1).join(" ");return await e.writeClipboard(n),{action:r,textLength:Array.from(n).length,...e$("Clipboard updated")}}async function db(e,t,r,n){let a=(t[0]??"status").toLowerCase();if("status"!==a&&"get"!==a&&"dismiss"!==a)throw new P("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(t.length>1)throw new P("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===a){let t=await Y(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type,inputMethodPackage:t.inputMethodPackage,focusedPackage:t.focusedPackage,focusedResourceId:t.focusedResourceId,inputOwner:t.inputOwner}}let t=await en(e);return{platform:"android",action:"status",visible:t.visible,inputType:t.inputType,type:t.type,inputMethodPackage:t.inputMethodPackage,focusedPackage:t.focusedPackage,focusedResourceId:t.focusedResourceId,inputOwner:t.inputOwner}}if("ios"===e.platform){if("dismiss"!==a)throw new P("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let t=await n6(e,{command:"keyboardDismiss",appBundleId:r?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,...e$(t.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new P("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}async function d_(e,t,r,n){var a;let[i,o,s,l]=r,u="location"===i&&"set"===o,d=("permission"===i||u?r[4]:r[2])??n?.appBundleId,c="permission"===i?{permissionTarget:s,permissionMode:l}:u?{latitude:eP(s,"latitude"),longitude:eP(l,"longitude")}:void 0;eb({level:"debug",phase:"settings_apply",data:u?{setting:i,state:o,latitude:s,longitude:l,platform:e.platform}:"permission"===i?{setting:i,state:o,permissionTarget:s,permissionMode:l,platform:e.platform}:{setting:i,state:o,appBundleId:d,platform:e.platform}});let p=await t.setSetting(i,o,d,c);return p&&"object"==typeof p?eq({setting:i,state:o,...p},("string"==typeof(a=p).message&&a.message.length>0?a.message:void 0)??`Updated setting: ${i}`):{setting:i,state:o,...e$(`Updated setting: ${i}`)}}async function dN(e,t,r){let n=t[0]?.trim(),a=t[1]?.trim();if(!n||!a)throw new P("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await dy(a);if("ios"===e.platform)return await ua(e,n,i),{platform:"ios",bundleId:n,...e$(`Pushed notification to ${n}`)};let o=await oj(e,n,i);return{platform:"android",package:n,action:o.action,extrasCount:o.extrasCount,...e$(`Pushed notification to ${n}`)}}async function dx(e,t){return await e.snapshot({appBundleId:t?.appBundleId,interactiveOnly:t?.snapshotInteractiveOnly,compact:t?.snapshotCompact,depth:t?.snapshotDepth,scope:t?.snapshotScope,raw:t?.snapshotRaw,surface:t?.surface})}function dM(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}function dD(e,t,r){return t||dk(r)?null:dM("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function dk(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function dP(e){return"ios"===e.platform&&"simulator"===e.kind}async function dO(e,t){dP(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function dE(e){let t=dk(e.flags)||!e.session?await os(e.flags??{}):await dC(e.session.device);return!1!==e.ensureReady&&await o$(t),t}async function dC(e){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let t={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await os(t)}catch(e){if(!(e instanceof P)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await os({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function dL(e){let t=e.flags?.device?.trim();return t||(e.resolvedDevice?.platform==="android"&&"emulator"===e.resolvedDevice.kind?e.resolvedDevice.name:e.sessionDevice?.platform==="android"&&"emulator"===e.sessionDevice.kind?e.sessionDevice.name:void 0)}let dR={startIosSimulatorRecording:({device:e,outPath:t})=>O("xcrun",rS(e,["io",e.id,"recordVideo",t]),{allowFailure:!0})},dT=ro(dR,function(e={}){return{...dR,...e}});async function d$(e,t){return await dT.run(e,t)}let dF=[{resolverKey:"androidAdbProvider",resolve(e,t){let r=e.androidAdbProvider;if(!r||"android"!==t.device.platform)return{};let n=r(t),a="function"==typeof n?n:n?.exec;return{androidAdb:{provider:n,executor:a,serial:t.device.id}}},appendWrapper(e,t){dj(t,e.androidAdb,(t,r)=>e0(t,{serial:e.androidAdb?.serial??""},r))}},{resolverKey:"appleRunnerProvider",resolve(e,t){let r=e.appleRunnerProvider;return r&&rW(t.device.platform)?{appleRunner:{provider:r(t),deviceId:t.device.id,requestId:t.req.meta?.requestId}}:{}},appendWrapper(e,t){dj(t,e.appleRunner,(t,r)=>n5(t,{deviceId:e.appleRunner?.deviceId??"",requestId:e.appleRunner?.requestId},r))}},{resolverKey:"appleToolProvider",resolve(e,t){let r=e.appleToolProvider;return r&&rW(t.device.platform)?{appleTool:{provider:r(t)}}:{}},appendWrapper(e,t){dj(t,e.appleTool,rw)}},{resolverKey:"linuxToolProvider",resolve(e,t){let r=e.linuxToolProvider;return r&&"linux"===t.device.platform?{linuxTool:{provider:r(t)}}:{}},appendWrapper(e,t){dj(t,e.linuxTool,ov)}},{resolverKey:"appLogProvider",resolve(e,t){let r=e.appLogProvider;return r?{appLog:{provider:r(t)}}:{}},appendWrapper(e,t){dj(t,e.appLog,a6)}},{resolverKey:"recordingProvider",resolve(e,t){let r=e.recordingProvider;return r?{recording:{provider:r(t)}}:{}},appendWrapper(e,t){dj(t,e.recording,d$)}}];async function dU(e,t){let r=await dG(e),n={androidAdbExecutor:r.androidAdb?.executor},a=function(e){let t=[];for(let r of dF)r.appendWrapper(e,t);return t}(r);return await dB(a,async()=>await t(n))}async function dG(e){var t,r,n;if(t=e.providers,!dF.some(e=>!!t[e.resolverKey]))return{};let a=await dV(e.req,e.existingSession);if(!a)return{};let i=(r=e,n=a,{req:r.req,device:n,session:r.existingSession});return dF.reduce((t,r)=>({...t,...r.resolve(e.providers,i)}),{})}async function dV(e,t){var r;return t?t.device:e.command===eO.open||dk(e.flags)||(r=e).command===eO.record&&"start"===(r.positionals?.[0]??"").toLowerCase()?await os(e.flags??{}):void 0}function dj(e,t,r){let n=t?.provider;n&&e.push(async e=>await r(n,e))}async function dB(e,t){let r=t;for(let t of[...e].reverse()){let e=r;r=async()=>await t(e)}return await r()}let dq=e=>"macos"!==e.platform,dH={device:!0},dW={},dz={alert:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW,supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},pinch:{apple:{simulator:!0,device:!0},android:{},linux:dW,supports:e=>"macos"===e.platform||"simulator"===e.kind&&"tv"!==e.target},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW,supports:dq},...tN,back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW,supports:dq},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH,supports:e=>"android"===e.platform||"linux"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},...ts,...tS,focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH,supports:dq},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW,supports:dq},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW},...ty,rotate:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dH},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW,supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:dW},...eC};function dK(e,t){let r=dz[e];if(!r)return!0;let n=rW(t.platform)?r.apple:"linux"===t.platform?r.linux:r.android;return!!n&&(!r.supports||!!r.supports(t))&&!0===n[t.kind??"unknown"]}let dJ=[250,400,600];function dX(e,t,r=e.snapshot){if("android"!==e.device.platform)return;let n=r?.comparisonSafe===!0;e.androidSnapshotFreshness={action:t,markedAt:Date.now(),baselineCount:r?.nodes.length??0,baselineSignatures:n?d0(r?.nodes??[]):void 0,routeComparable:n}}function dZ(e){if(!e||"android"!==e.device.platform)return;let t=e.androidSnapshotFreshness;if(t)return Date.now()-t.markedAt>2500?void delete e.androidSnapshotFreshness:t}function dY(e){e&&"android"===e.device.platform&&delete e.androidSnapshotFreshness}function dQ(e){return"press"===e||"click"===e||"back"===e||"open"===e}function d0(e){return e.map(e=>[e.depth??0,e.type??"",e.role??"",e.label??"",e.value??"",e.identifier??"",!1===e.enabled?"disabled":"enabled",!0===e.selected?"selected":"unselected",!0===e.hittable?"hittable":"not-hittable"].join("|"))}function d1(e,t,r,n,a){return{requestId:a??eI().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:n,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,...eB(t),count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:u1(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}function d2(e){e?.postGestureStabilization&&(e.postGestureStabilization=void 0)}async function d3(e){let{session:t,capture:r}=e,n=t?.postGestureStabilization;if(!t||"ios"!==t.device.platform||!n)return await r();let a=Date.now(),i=1,o=await r(),s=d4(o.nodes);for(;Date.now()-a<1500;){await ex(200),i+=1;let e=await r(),l=d4(e.nodes);if(function(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r+=1){let n=e[r],a=t[r];if(!n||!a||n.key!==a.key||Math.abs(n.x-a.x)>1||Math.abs(n.y-a.y)>1||Math.abs(n.width-a.width)>1||Math.abs(n.height-a.height)>1)return!1}return!0}(s,l))return d2(t),eb({level:i>2?"info":"debug",phase:"post_gesture_snapshot_stabilized",data:{action:n.action,attempts:i,durationMs:Date.now()-a}}),e;o=e,s=l}return d2(t),eb({level:"warn",phase:"post_gesture_snapshot_stabilization_timeout",data:{action:n.action,attempts:i,durationMs:Date.now()-a}}),o}function d4(e){let t=new Map,r=[];for(let i of e){var n,a;if(!i.rect||!([(n=i.rect).x,n.y,n.width,n.height].every(e=>Number.isFinite(e))&&n.width>0&&n.height>0)||(a=i,`${a.label??""} ${a.identifier??""}`.toLowerCase().includes("scroll bar")))continue;let e=[i.identifier,i.label,i.value,i.type].map(e=>"string"==typeof e?e.trim():"").join("|");if(!e.replaceAll("|",""))continue;let o=t.get(e)??0;t.set(e,o+1),r.push({key:`${e}|#${o}`,x:i.rect.x,y:i.rect.y,width:i.rect.width,height:i.rect.height})}return r}async function d5(e){if("ios"===e.device.platform&&e.session?.postGestureStabilization)return{snapshot:await d3({session:e.session,capture:async()=>(await d9(e)).snapshot})};let t=dZ(e.session);if(t&&"android"===e.device.platform)return await d6(e,t);let r=await d8(e);return dY(e.session),{snapshot:ct(r,d7(e)),analysis:r.analysis,androidSnapshot:r.androidSnapshot}}async function d8(e){let{device:t,session:r,flags:n,outPath:a,logPath:i,snapshotScope:o}=e;if("linux"===t.platform){let e=await uZ(r?.surface);return cr({nodes:e.nodes,truncated:e.truncated,backend:"linux-atspi"},{snapshotDepth:n?.snapshotDepth,snapshotInteractiveOnly:n?.snapshotInteractiveOnly,snapshotScope:o})}return"macos"===t.platform&&r?.surface&&"app"!==r.surface?cr(await lp(r.surface,{bundleId:"menubar"===r.surface?r.appBundleId:void 0}),{snapshotDepth:n?.snapshotDepth,snapshotInteractiveOnly:n?.snapshotInteractiveOnly,snapshotScope:o}):await dI(t,"snapshot",[],a,{...d1(i,{...n,snapshotScope:o},r?.appBundleId,r?.trace?.outPath)})}async function d6(e,t){let r=await d9(e),n=ce(r,t,e),a=0,i=t.markedAt+1500;for(let o of dJ){if(!n)break;let s=i-Date.now();if(s<=0)break;await ex(Math.min(o,s)),r=await d9(e),a+=1,n=ce(r,t,e)}return n||dY(e.session),{snapshot:r.snapshot,analysis:r.data.analysis,androidSnapshot:r.data.androidSnapshot,freshness:a>0||n?{action:t.action,retryCount:a,staleAfterRetries:!!n,reason:n??void 0}:void 0}}async function d9(e){let t=await d8(e);return{data:t,snapshot:ct(t,d7(e))}}function d7(e){return void 0===e.snapshotScope?e.flags:{...e.flags,snapshotScope:e.snapshotScope}}function ce(e,t,r){var n,a;let i=r.flags?.snapshotInteractiveOnly===!0,o=e.data.analysis;if(i&&0===e.snapshot.nodes.length&&o&&o.rawNodeCount>=12)return"empty-interactive";if("ref-refresh"===r.androidFreshnessMode)return null;return(n=t.baselineCount,a=e.snapshot.nodes.length,!(n<12)&&a<=Math.floor(.2*n))?e.snapshot.nodes.some(e=>!0===e.hittable||!!e.label?.trim()||!!e.value?.trim()||!!e.identifier?.trim())?null:"sharp-drop":t.routeComparable&&dQ(t.action)&&function(e,t){if(!e||0===e.length)return!1;let r=Math.max(e.length,t.length);if(r<12)return!1;let n=d0(t),a=Math.min(e.length,n.length),i=0;for(let t=0;t<a;t+=1)e[t]===n[t]&&(i+=1);let o=Math.max(0,n.length-e.length),s=Math.max(0,e.length-n.length),l=Math.max(3,Math.floor(.15*r));return i>=Math.floor(.9*r)&&o<=l&&s<=l}(t.baselineSignatures,e.snapshot.nodes)?"stuck-route":null}function ct(e,t){let r=e?.nodes??[],n=tw(t?.snapshotRaw?r:tK(r));return{nodes:tL(t?.snapshotScope&&e?.backend!=="macos-helper"?cn(n,t.snapshotScope):n),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend,presentationKey:tE(tk(t)),comparisonSafe:e?.backend==="android"&&t?.snapshotInteractiveOnly!==!0&&t?.snapshotCompact!==!0&&"number"!=typeof t?.snapshotDepth&&!t?.snapshotScope}}function cr(e,t){var r,n;let a=e.nodes??[];return t.snapshotScope&&(a=cn(a,t.snapshotScope)),t.snapshotInteractiveOnly&&(a=function(e){if(0===e.length)return e;let t=new Map;for(let r of e)t.set(r.index,r);let r=new Set;for(let n of e){if(!function(e){if(e.focused||e.hittable||e.rect)return!0;let t=`${e.type??""} ${e.role??""} ${e.subrole??""}`.toLowerCase();return t.includes("button")||t.includes("menu")||t.includes("textfield")||t.includes("searchfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")}(n))continue;let e=n;for(;e&&!r.has(e.index);)r.add(e.index),e="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0}return 0===r.size?e:ca(e.filter(e=>r.has(e.index)))}(a)),"number"==typeof t.snapshotDepth&&(r=a,n=t.snapshotDepth,a=ca(r.filter(e=>(e.depth??0)<=n))),{...e,nodes:a}}function cn(e,t){let r=tj(tL(e),t);if(!r)return[];let n=e.findIndex(e=>e.index===r.index);if(-1===n)return[];let a=e[n]?.depth??0,i=[];for(let t=n;t<e.length;t+=1){let r=e[t];if(!r)continue;let o=r.depth??0;if(t>n&&o<=a)break;i.push(r)}return ca(i,a)}function ca(e,t=0){let r=new Map;for(let[t,n]of e.entries())r.set(n.index,t);return e.map((e,n)=>({...e,index:n,depth:Math.max(0,(e.depth??0)-t),parentIndex:"number"==typeof e.parentIndex?r.get(e.parentIndex):void 0}))}function ci(e,t){e.snapshot=t,e.snapshotScopeSource=void 0}function co(e){return{get:t=>t===e.sessionName?function(e,t,r={}){if(e)return{name:t,appBundleId:e.appBundleId,appName:e.appName,...!0===r.includeSnapshot?{snapshot:e.snapshot}:{},metadata:{surface:e.surface,...r.metadata??{}}}}(e.getSession(),e.sessionName,e.recordOptions):void 0,set:t=>{t.name!==e.sessionName?eb({level:"warn",phase:"runtime_session_write_skipped",data:{expected:e.sessionName,received:t.name}}):e.setRecord(t)}}}async function cs(e){let{session:t,sessionName:r,outPath:n,outputPlacement:a,dispatchContext:i}=e,o=tI({backend:function(e){let{session:t,outputPlacement:r,dispatchContext:n}=e;return{platform:t.device.platform,captureScreenshot:async(e,a,i)=>{let o={...n,...eB(i),surface:i?.surface};return"out"===r?cl(await dI(t.device,"screenshot",[],a,o)):cl(await dI(t.device,"screenshot",[a],void 0,o))}}}({session:t,outputPlacement:a,dispatchContext:i}),artifacts:{resolveInput:async()=>{throw new P("UNSUPPORTED_OPERATION","screenshot does not resolve input artifacts")},reserveOutput:async e=>{let t,r;return e?.kind==="path"?r=e.path:(t=await d.mkdtemp(f.join(c.tmpdir(),"agent-device-screenshot-")),r=f.join(t,"screenshot.png")),await d.mkdir(f.dirname(r),{recursive:!0}),{path:r,visibility:"client-visible",publish:async()=>void 0,...t?{cleanup:async()=>{await d.rm(t,{recursive:!0,force:!0})}}:{}}},createTempFile:async e=>{let t=await d.mkdtemp(f.join(c.tmpdir(),`${e.prefix}-`));return{path:f.join(t,`file${e.ext}`),visibility:"internal",cleanup:async()=>{await d.rm(t,{recursive:!0,force:!0})}}}},sessions:co({sessionName:r,getSession:()=>t,recordOptions:{includeSnapshot:!1},setRecord:()=>{}}),policy:tM()});return await o.capture.screenshot({session:r,requestId:i.requestId,appBundleId:t.appBundleId,...eU(i),surface:t.surface,...n?{out:{kind:"path",path:n}}:{}})}function cl(e){if("object"==typeof e&&null!==e)return{..."string"==typeof e.path?{path:e.path}:{},...Array.isArray(e.overlayRefs)?{overlayRefs:e.overlayRefs}:{}}}let cu=/\bis(?:n't| not)\s+responding\b/i,cd=/^close app$/i;async function cc(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await cp(t),r=function(e){if(cw(e))return e.find(e=>{let t=ch(e);return t.length>0&&cd.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:n,y:a}=tC(r.rect),i=await X(t.device,["shell","input","tap",String(Math.round(n)),String(Math.round(a))],{allowFailure:!0});if(0!==i.exitCode)return eb({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:i.exitCode,stdout:i.stdout.trim(),stderr:i.stderr.trim()}}),"failed";if(!await cf(t))return eb({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await j(t.device,t.appBundleId),!await cm(t,t.appBundleId)))return eb({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return eb({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:n,y:a}}),"recovered"}catch(e){return eb({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function cp(e){return tL(tK((await oX(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function cf(e){for(let t=0;t<12;t+=1){if(!cw(await cp(e)))return!0;await ex(500)}return!cw(await cp(e))}async function cm(e,t){for(let r=0;r<12;r+=1){if((await eo(e.device)).package===t)return!0;await ex(500)}return(await eo(e.device)).package===t}function ch(e){let t=[e.label,e.identifier];return"string"==typeof e.value&&e.value.trim().length>0&&t.push(e.value),t.filter(e=>"string"==typeof e&&e.trim().length>0).join(" ").trim()}function cw(e){return e.some(e=>{let t=ch(e);return t.length>0&&cu.test(t)})}let cg=[255,59,48,255],cy=[255,214,10,255],cv=[0,0,0,255],cI={e:["01110","10000","11110","10000","10000","10001","01110"],0:["01110","10001","10011","10101","11001","10001","01110"],1:["00100","01100","00100","00100","00100","00100","01110"],2:["01110","10001","00001","00010","00100","01000","11111"],3:["11110","00001","00001","01110","00001","00001","11110"],4:["00010","00110","01010","10010","11111","00010","00010"],5:["11111","10000","10000","11110","00001","00001","11110"],6:["01110","10000","10000","11110","10001","10001","01110"],7:["11111","00001","00010","00100","01000","01000","01000"],8:["01110","10001","10001","01110","10001","10001","01110"],9:["01110","10001","10001","01111","00001","00001","01110"]};async function cA(e){let t=ta(await d.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,n={}){let a=function(e){let t=null;for(let r of e)cb(r)&&cD(r.rect)&&(!t||ck(r.rect)>ck(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,n=-1/0,a=-1/0;for(let i of e)i.rect&&cD(i.rect)&&(t=Math.min(t,i.rect.x),r=Math.min(r,i.rect.y),n=Math.max(n,i.rect.x+i.rect.width),a=Math.max(a,i.rect.y+i.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||n<=t||a<=r?null:{x:t,y:r,width:n-t,height:a-r}}(e.filter(e=>{var t;return cD(e.rect)&&!("image"===tz((t=e).type??"")&&!c_(t.label))}))}(e.nodes),i=new Map;for(let n of e.nodes){if(!function(e){let t=[e.label,e.value].some(cN)||cx(e.identifier);return cS(e)?t:t&&function(e){let t=tz(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(n))continue;let o=function(e,t){if(function(e){return cS(e)&&!cb(e)}(t)&&cD(t.rect))return t;let r=function(e,t){let r=t,n=new Set;for(;void 0!==r.parentIndex&&!n.has(r.ref);){;n.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(cS(t)&&!cb(t)&&cD(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&cD(r.rect))return r;if(t.hittable&&cD(t.rect)&&!cb(t))return t;let n=tF(e,t);return n?.rect&&cD(n.rect)&&!cb(n)?n:null}(e.nodes,n);if(!o?.rect||!cD(o.rect))continue;let s=function(e,t,r){let n=cM(e);if(e.ref!==t.ref&&n)return n;let a=function(e,t){let r=null;for(let n of t){if(n.ref===e.ref||!function(e,t,r){let n=e;for(;void 0!==n.parentIndex;){let e=r[n.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;n=e}return!1}(n,e,t))continue;let a=cM(n);if(!a)continue;let i=function(e){let t=0;return tz(e.type??"").includes("text")&&(t+=2),cN(e.label)&&(t+=2),cN(e.value)&&(t+=1),t}(n);(!r||i>r.score)&&(r={label:a,score:i})}return r?.label}(t,r);return a||(cM(t)??tB(t,r))}(n,o,e.nodes),l=function(e,t,r){let n=0;return e.ref===t.ref&&(n+=4),t.hittable&&(n+=3),cS(t)&&(n+=3),cS(e)&&(n+=2),r&&(n+=2),cx(t.identifier)&&(n+=1),c_(t.value)&&(n+=1),n}(n,o,s),u=function(e,t,r,n){if(!e)return cE({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,n);let a=r/e.width,i=n/e.height;return cE({x:Math.round((t.x-e.x)*a),y:Math.round((t.y-e.y)*i),width:Math.max(1,Math.round(t.width*a)),height:Math.max(1,Math.round(t.height*i))},r,n)}(a,o.rect,t,r);if(!cD(u))continue;let d=i.get(o.ref);(!d||l>d.score)&&i.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:u,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>ck(e.overlayRect)-ck(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(cP(e.overlayRect,r.overlayRect)||cP(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}ck(r.overlayRect)<ck(t[e].overlayRect)&&(t[e]=r)}return t})([...i.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let n=e.overlayRect.x-t.overlayRect.x;return 0!==n?n:cO(e.ref,t.ref)}).slice(0,n.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let n=e.overlayRect.x-t.overlayRect.x;return 0!==n?n:cO(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:tC(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var n,a;(function(e,t,r){for(let n=0;n<2;n+=1)cL(e,t.x,t.x+t.width-1,t.y+n,r),cL(e,t.x,t.x+t.width-1,t.y+t.height-1-n,r),cR(e,t.x+n,t.y,t.y+t.height-1,r),cR(e,t.x+t.width-1-n,t.y,t.y+t.height-1,r)})(n=t,(a=e).overlayRect,cg),function(e,t,r){let n=6+5*r.length+ +Math.max(0,r.length-1),a=cC(t.x,0,Math.max(0,e.width-n)),i=t.y-11-2,o=i>=0?i:cC(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,n,a){for(let i=0;i<11;i+=1)for(let o=0;o<n;o+=1)cT(e,t+o,r+i,a)})(e,a,o,n,cy),function(e,t,r,n,a){let i=t;for(let t of n.toLowerCase()){let n=cI[t];if(n)for(let t=0;t<n.length;t+=1)for(let o=0;o<n[t].length;o+=1)"1"===n[t][o]&&cT(e,i+o,r+t,a);i+=6}}(e,a+3,o+2,r,cv)}(n,a.overlayRect,a.ref)}return await d.writeFile(e.screenshotPath,_.sync.write(t)),r}function cS(e){let t=[e.type,e.role,e.subrole].map(e=>tz(e??"")).join(" ");return t.includes("button")||t.includes("link")||t.includes("menu")||t.includes("tab")||t.includes("textfield")||t.includes("searchfield")||t.includes("securetextfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")||t.includes("cell")}function cb(e){let t=[e.type,e.role,e.subrole].map(e=>tz(e??"")).join(" ");return t.includes("application")||t.includes("window")}function c_(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function cN(e){var t;let r;return!!c_(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function cx(e){var t;return"string"==typeof e&&!!cN(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function cM(e){let t=[e.label,e.value].find(cN);return t?t.trim():cx(e.identifier)?e.identifier.trim():void 0}function cD(e){return!!(e&&e.width>0&&e.height>0)}function ck(e){return e.width*e.height}function cP(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 cO(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function cE(e,t,r){let n=cC(e.x,0,Math.max(0,t-1)),a=cC(e.y,0,Math.max(0,r-1)),i=Math.max(1,t-n),o=Math.max(1,r-a);return{x:n,y:a,width:cC(e.width,1,i),height:cC(e.height,1,o)}}function cC(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function cL(e,t,r,n,a){for(let i=t;i<=r;i+=1)cT(e,i,n,a)}function cR(e,t,r,n,a){for(let i=r;i<=n;i+=1)cT(e,t,i,a)}function cT(e,t,r,n){if(t<0||r<0||t>=e.width||r>=e.height)return;let a=(e.width*r+t)*4;e.data[a]=n[0],e.data[a+1]=n[1],e.data[a+2]=n[2],e.data[a+3]=n[3]}function c$(e){return"number"==typeof e.gestureClockOriginAtMs&&"number"==typeof e.gestureClockOriginUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureClockOriginAtMs+(e.gestureStartUptimeMs-e.gestureClockOriginUptimeMs)-e.recordingStartedAt):"number"==typeof e.runnerStartedAtUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureStartUptimeMs-e.runnerStartedAtUptimeMs):"number"==typeof e.gestureStartUptimeMs&&"number"==typeof e.gestureEndUptimeMs?Math.max(0,e.fallbackFinishedAtMs-(e.gestureEndUptimeMs-e.gestureStartUptimeMs)-e.recordingStartedAt):Math.max(0,e.fallbackStartedAtMs-e.recordingStartedAt)}let cF=new WeakMap;function cU(e){if(!e)return;let t=cF.get(e);if(t)return t;let r=function(e){let t=function(e){let t=e.filter(e=>(function(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("application")||t.includes("window")})(e.type)&&cG(e.rect)).map(e=>e.rect).sort((e,t)=>(t?.width??0)*(t?.height??0)-(e?.width??0)*(e?.height??0))[0];if(t)return t;let r=e.map(e=>e.rect).filter(cG);if(0===r.length)return;let n=Math.max(...r.map(e=>e.x+e.width)),a=Math.max(...r.map(e=>e.y+e.height));if(!(n<=0)&&!(a<=0))return{x:0,y:0,width:n,height:a}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return cF.set(e,r),r}function cG(e){return!!e&&e.width>0&&e.height>0}let cV={referenceWidth:1e3,referenceHeight:1e3};function cj(e,t,r,n,a={},i=Date.now(),o=Date.now()){var s,l,u;let d,c,p=e.recording;if(!p)return;let f={...a,...n??{}},m=cz(f.effectiveDurationMs)??cz(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:cz(f.gestureStartUptimeMs),gestureEndUptimeMs:cz(f.gestureEndUptimeMs),fallbackStartedAtMs:i,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:cz(f.gestureStartUptimeMs),gestureEndUptimeMs:cz(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:i,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===cz(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=cK(cz(t.count),1)??1,r=!0===t.doubleTap,n=cK(cz(t.holdMs),1);return 1===e&&!r&&void 0===n}case"react-native":return"dismiss-overlay"===t.action;default:return!1}}(t,f)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return c$(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):c$(h),y=(l=e.snapshot,d=cz((u=f).referenceWidth),c=cz(u.referenceHeight),void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:cU(l)),v=function(e,t,r,n,a,i){switch(e){case"click":case"press":return cB(t,r,n,i);case"react-native":return"dismiss-overlay"===t[0]?cB(t,r,n,i):[];case"fill":case"focus":return function(e,t,r,n){let a=cJ(t,e);if(!a)return[];let{x:i,y:o}=a;return[cq(r,i,o,n)]}(t,r,n,i);case"longpress":return function(e,t,r,n,a){let i=cJ(t,e);if(!i)return[];let{x:o,y:s}=i;return[cH(r,o,s,cZ(n,[cz(t.durationMs),cz(e[2])],800),a)]}(t,r,n,a,i);case"scroll":return function(e,t,r,n,a){let i=cX(t,e),o=cW(t.contentDirection)??cW(t.direction);if(!i||!o)return[];let{x1:s,y1:l,x2:u,y2:d}=i,c=cZ(n,[],250),p=cz(t.amount)??cz(e[1]),f=cz(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:u,y2:d,...a,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{},...void 0!==f?{pixels:f}:{}}]}(t,r,n,a,i);case"swipe":return function(e,t,r,n,a){let i=cX(t,e);if(!i)return[];let{x1:o,y1:s,x2:l,y2:u}=i,d=cZ(n,[cz(t.effectiveDurationMs),cz(t.durationMs),cz(e[4])],250),c=cK(cz(t.count),1)??1,p=cK(cz(t.pauseMs),0)??0,f="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===f&&e%2==1,n=t?l:o,i=t?u:s,c=t?o:l,h=t?s:u,w=r+e*(d+p);if("back-swipe"===function(e,t,r,n,a){if(!a||Math.abs(r-e)<=1.25*Math.abs(n-t))return"swipe";let i=.08*a.referenceWidth;return e<=i&&r>e||e>=a.referenceWidth-i&&r<e?"back-swipe":"swipe"}(n,i,c,h,a)){m.push({kind:"back-swipe",tMs:w,x:n,y:i,x2:c,y2:h,...a,durationMs:d,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(n,c,a)});continue}m.push({kind:"swipe",tMs:w,x:n,y:i,x2:c,y2:h,...a,durationMs:d})}return m}(t,r,n,a,i);case"pinch":return function(e,t,r,n,a){let i=cJ(t,e,1),o=cz(t.scale)??cz(e[0]);if(!i||void 0===o||o<=0)return[];let{x:s,y:l}=i;return[{kind:"pinch",tMs:r,x:s,y:l,...a,scale:o,durationMs:cZ(n,[],280)}]}(t,r,n,a,i);default:return[]}}(t,r,f,g,w,y);0!==v.length&&(p.gestureEvents.push(...v),eb({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:v.length,tMs:g,gestureDurationMs:w,kinds:v.map(e=>e.kind)}}))}function cB(e,t,r,n){let a=cJ(t,e);if(!a)return[];let{x:i,y:o}=a,s=cK(cz(t.count),1)??1,l=cK(cz(t.intervalMs),0)??0,u=!0===t.doubleTap,d=cK(cz(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==d&&d>0){c.push(cH(t,i,o,d,n));continue}c.push(cq(t,i,o,n)),u&&c.push(cq(t+90,i,o,n))}return c}function cq(e,t,r,n){return{kind:"tap",tMs:e,x:t,y:r,...n}}function cH(e,t,r,n,a){return{kind:"longpress",tMs:e,x:t,y:r,...a,durationMs:n}}function cW(e){if("string"!=typeof e)return;let t=e.trim().toLowerCase();switch(t){case"up":case"down":case"left":case"right":return t;default:return}}function cz(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e||0===e.trim().length)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function cK(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function cJ(e,t,r=0){let n=cz(e.x)??cz(t[r]),a=cz(e.y)??cz(t[r+1]);if(void 0!==n&&void 0!==a)return{x:n,y:a}}function cX(e,t){let r=cz(e.x1)??cz(t[0]),n=cz(e.y1)??cz(t[1]),a=cz(e.x2)??cz(t[2]),i=cz(e.y2)??cz(t[3]);if(void 0!==r&&void 0!==n&&void 0!==a&&void 0!==i)return{x1:r,y1:n,x2:a,y2:i}}function cZ(e,t,r){return cK(e,1)??t.map(e=>cK(e,1)).find(e=>void 0!==e)??r}async function cY(e){var t,r,n,a,i,o,s,l,u;let d,c,p,f,m,{req:h,session:w,logPath:g,sessionStore:y,contextFromFlags:v}=e,I=h.command;if(!dK(I,w.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${I} is not supported on this device`}};if("android"===w.device.platform&&w.recording&&"record"!==I&&"failed"===await cc({session:w}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:A,resolvedOut:S,recordedPositionals:b,recordedFlags:_}="screenshot"===(t=h).command?(c=(n=(r=t).positionals??[],a=r.meta?.cwd,(d=n[0])?[aN.expandHome(d,a),...n.slice(1)]:n),f=(p=(i=r.flags?.out,o=r.meta?.cwd,i?aN.expandHome(i,o):i))?{...r.flags??{},out:p}:r.flags??{},{resolvedPositionals:c,resolvedOut:p,recordedPositionals:c,recordedFlags:f}):{resolvedPositionals:m=(s=t).positionals??[],resolvedOut:s.flags?.out,recordedPositionals:m,recordedFlags:s.flags??{}},N=Date.now(),x={...v(h.flags,w.appBundleId,w.trace?.outPath),surface:w.surface},M="screenshot"===I?await cs({session:w,sessionName:e.sessionName,outPath:A[0]??S,outputPlacement:"screenshot"!==(l=h).command?"default":(l.positionals??[])[0]?"positional":l.flags?.out?"out":"default",dispatchContext:x}):await dI(w.device,I,A,S,{...x});return"screenshot"===I&&h.flags?.overlayRefs&&"string"==typeof M?.path&&await cQ(w,M,g),function(e){let{session:t,sessionStore:r,command:n,resolvedPositionals:a,recordedPositionals:i,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:u,flags:d}=e,c=function(e,t,r,n){if("scroll"!==t)return n;let a=cU(e.snapshot),i={...n??{}},o=cW(i.direction)??cW(r[0]);if(!o)return n;let s=cz(i.amount)??cz(r[1]),l=cz(i.pixels),u=cX(i,[]),d=cz(i.referenceWidth),c=cz(i.referenceHeight),p=void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:a??cV;if(u&&(u.x1!==u.x2||u.y1!==u.y2))return{...i,x1:u.x1,y1:u.y1,x2:u.x2,y2:u.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250};let f=oB({direction:o,amount:s,pixels:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return{...i,x1:f.x1,y1:f.y1,x2:f.x2,y2:f.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==f.pixels?{pixels:f.pixels}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250}}(t,n,a,s);cj(t,n,a,c,d,l,u),r.recordAction(t,{command:n,positionals:i,flags:o,result:s??{}})}({session:w,sessionStore:y,command:I,resolvedPositionals:A,recordedPositionals:b,recordedFlags:_,data:M,actionStartedAt:N,actionFinishedAt:Date.now(),flags:h.flags??{}}),dQ(I)&&dX(w,I),"ios"!==w.device.platform||("swipe"===(u=I)||"scroll"===u)&&(w.postGestureStabilization={action:I,markedAt:Date.now()}),{ok:!0,data:M??{}}}async function cQ(e,t,r){let n=ct(await d8({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);ci(e,n);let a=await cA({screenshotPath:t.path,snapshot:n});t.overlayRefs=a}async function c0(e){let{device:t,node:r,flags:n,appBundleId:a,traceOutPath:i,surface:o,contextFromFlags:s}=e,l=tG(r),u=tu(r.rect);if(!u)return l;try{let e=await dI(t,"read",[String(u.x),String(u.y)],void 0,{...s(n,a,i),surface:o}),d=e&&"object"==typeof e?e:void 0,c="string"==typeof d?.text?d.text:"";if(c.trim())return c;return eb({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return eb({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}async function c1(e,t,r){let n=e.get(t),a=n?.device??await os(r??{});return n||await o$(a),{session:n,device:a}}async function c2(e,t,r){let n=!e&&"ios"===t.platform;try{return await r()}finally{n&&await nz(t.id)}}function c3(e,t,r,n){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}let c4=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function c5(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,n]of c4)void 0!==e[r]&&t.push(n);return t}(t);return 0===r.length?null:dM("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function c8(e,t){let r=await c6(e);if(r)throw new P("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${r.foregroundPackage}. The tap likely escaped the app.`,r)}async function c6(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let r=await eo(e.device),n=r.package?.trim();return n&&n!==e.appBundleId&&("com.android.settings"===(t=n)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:n,activity:r.activity,hint:"com.google.android.permissioncontroller"===n?"Dismiss or allow the permission prompt, then retry the smoke assertion.":"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."}:null}function c9(e,t){let r=Array.isArray(e.selectorChain)?e.selectorChain:void 0,n=pr(e),a=n?.kind==="ref"?pn(n.ref):void 0,i=n?.kind==="selector"?n.selector:void 0,o={...a?{ref:a}:{},...i?{selector:i}:{},...r?{selectorChain:r}:{}};if("attrs"===t)return o;let s="string"==typeof e.text?e.text:"";return{...o,text:s,refLabel:function(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}(s)}}function c7(e){let t=pr(e);return{...t?.kind==="ref"?{ref:pn(t.ref)}:{},...t?.kind==="selector"?{selector:t.selector}:{},..."string"==typeof e.text?{text:e.text}:{},...e.node&&"object"==typeof e.node?{node:e.node}:{}}}function pe(e){let{selectorChain:t,...r}=e;return r}function pt(e,t,r,n){let a=e.get(t);a&&e.recordAction(a,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function pr(e){let t=e.target;return t&&"object"==typeof t?"ref"===t.kind&&"string"==typeof t.ref?{kind:"ref",ref:t.ref}:"selector"===t.kind&&"string"==typeof t.selector?{kind:"selector",selector:t.selector}:void 0:void 0}function pn(e){return e.startsWith("@")?e.slice(1):e}function pa(e,t={}){return{artifacts:function(e,t={}){let r=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new P("UNSUPPORTED_OPERATION",`${e} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new P("UNSUPPORTED_OPERATION",`${e} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new P("UNSUPPORTED_OPERATION",`${e} ${r} not create temporary files`)}}}(e,t),policy:tM()}}let pi=["application","window","tabbar","scrollbar","image"],po=new Set(["tab bar"]);async function ps(e,t){var r;if(t.ok||(r=t.error.message,!/^wait timed out for (?:selector|text): /i.test(r)))return t;let n=await pl(e).catch(()=>null);return n?dM(t.error.code,`${t.error.message}. Current surface: ${n.summary}.`,{...t.error.details??{},currentSurface:n.details}):t}async function pl(e){let t=[...(await d5({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!0,snapshotCompact:!0},logPath:e.logPath??""})).snapshot.nodes].sort(pd),r=pu(t,6,{includeIdentifiers:!0});if(0===r.length)return null;let n=pu(t.filter(e=>!pf(e)),4,{includeIdentifiers:!1}),a=pu(t.filter(pm),4,{includeIdentifiers:!0});return{summary:(n.length>0?n:r.slice(0,4)).join(", "),details:{labels:r,...a.length>0?{buttons:a}:{}}}}function pu(e,t,r){let n=new Set,a=[];for(let i of e){let e=pp(i,r);if(!(!e||n.has(e))&&(n.add(e),a.push(e),a.length>=t))break}return a}function pd(e,t){var r,n;return pc(e)-pc(t)||(r=e,n=t,r.rect&&n.rect?r.rect.y-n.rect.y||r.rect.x-n.rect.x:r.rect?-1:n.rect?1:(r.depth??0)-(n.depth??0)||r.index-n.index)}function pc(e){let t=!!pp(e,{includeIdentifiers:!1});return 2*!!pf(e)+ +!t}function pp(e,t){let r=(t.includeIdentifiers?[e.label,e.value,e.identifier]:[e.label,e.value]).map(e=>"string"==typeof e?e.trim():"").find(e=>e.length>0);return r?r.replace(/\s+/g," ").slice(0,80):""}function pf(e){let t=tz(`${e.type??""} ${e.role??""} ${e.subrole??""}`),r=`${e.label??""} ${e.value??""}`.trim().toLowerCase();return pi.some(e=>t.includes(e))||po.has(r)||r.endsWith(".fill")}function pm(e){return tz(`${e.type??""} ${e.role??""} ${e.subrole??""}`).includes("button")}function ph(e){var t;let{session:r,selectorExpression:n}=e;if(!r||"ios"!==r.device.platform||r.postGestureStabilization)return null;let a=tV(n);if(!a||1!==a.selectors.length)return null;let i=a.selectors[0];if(!i||1!==i.terms.length)return null;let o=i.terms[0];return o&&"string"==typeof o.value&&("id"===(t=o.key)||"label"===t||"text"===t||"value"===t)?{key:o.key,value:o.value,raw:i.raw}:null}function pw(e){let t=D(e);if("COMMAND_FAILED"!==t.code)return!1;let r=t.message.toLowerCase();return r.includes("fetch failed")||r.includes("timed out")||r.includes("timeout")||r.includes("runner did not accept connection")||r.includes("invalid runner response")}async function pg(e){var t;let{req:r}=e;if("find"!==r.command)return null;let n=r.positionals??[];if(0===n.length)return dM("INVALID_ARGS","find requires a locator or text");let a=tX(n);if(!a.query)return dM("INVALID_ARGS","find requires a value");if(r.flags?.findFirst&&r.flags?.findLast)return dM("INVALID_ARGS","find accepts only one of --first or --last");let i=a.action;if("exists"!==(t=i)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let o=await pk(e,{requireSession:!1,capability:"find"});return o.ok?await pE(async()=>{let t=await o.runtime.selectors.find({session:e.sessionName,requestId:r.meta?.requestId,locator:a.locator,query:a.query,action:i,timeoutMs:a.timeoutMs});return pt(e.sessionStore,e.sessionName,r,function(e,t){if("exists"===t)return{found:!0};if("wait"===t)return{found:!0,waitedMs:e.waitedMs};let r="string"==typeof e.ref?e.ref:void 0;return"get_attrs"===t?{ref:r,action:"get attrs"}:{ref:r,action:"get text",text:"string"==typeof e.text?e.text:""}}(t,i)),"found"===t.kind?{found:!0,..."number"==typeof t.waitedMs?{waitedMs:t.waitedMs}:{}}:{..."string"==typeof t.ref?{ref:t.ref}:{},..."string"==typeof t.text?{text:t.text}:{},...t.node&&"object"==typeof t.node?{node:t.node}:{}}}):o.response}async function py(e){let{req:t}=e;if("get"!==t.command)return null;let r=t.positionals?.[0];if("text"!==r&&"attrs"!==r)return dM("INVALID_ARGS","get only supports text or attrs");let n=function(e){let t=e.positionals?.[1]??"";if(t.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:e.positionals.length>2?e.positionals.slice(2).join(" ").trim():""}};let r=e.positionals?.slice(1).join(" ").trim()??"";return r?{ok:!0,target:{kind:"selector",selector:r}}:{ok:!1,response:dM("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!n.ok)return n.response;if("ref"===n.target.kind){let e=c5("get",t.flags);if(e)return e}if("selector"===n.target.kind){let t=await pA(e,r,n.target.selector);if(t)return t}let a=await pk(e,{requireSession:!0,capability:"get"});return a.ok?await pE(async()=>{let i=await a.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:r,target:n.target});return pt(e.sessionStore,e.sessionName,t,c9(i,r)),c7(i)}):a.response}async function pv(e){let{req:t}=e;if("is"!==t.command)return null;let r=(t.positionals?.[0]??"").toLowerCase();if(!ti(r))return dM("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:n}=tq(t.positionals??[]);if(!n)return dM("INVALID_ARGS","is requires a selector expression");let a=n.rest.join(" ").trim();if("text"===r&&!a)return dM("INVALID_ARGS","is text requires expected text value");if("text"!==r&&n.rest.length>0)return dM("INVALID_ARGS",`is ${r} does not accept trailing values`);let i=await pS(e,r,n.selectorExpression,a);if(i)return i;let o=await pk(e,{requireSession:!0,capability:"is"});if(!o.ok)return o.response;let s=await pE(async()=>{let i=await o.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:r,selector:n.selectorExpression,expectedText:a});return pt(e.sessionStore,e.sessionName,t,i),pe(i)});return await pC(e,s,`is ${r}`)}async function pI(e){let{req:t,sessionName:r,sessionStore:n}=e,a=eV(t.positionals??[]);if(!a)return dM("INVALID_ARGS","wait requires a duration or text");let{session:i,device:o}=await c1(n,r,t.flags);if("sleep"!==a.kind&&!dK("wait",o))return dM("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===a.kind){let t=await pb({...e,session:i,device:o,selectorExpression:a.selectorExpression,timeoutMs:a.timeoutMs});if(t)return t}let s=async()=>{let s=pD({...e,session:i,device:o}),l=await pE(async()=>{let e=await s.selectors.wait({session:r,requestId:t.meta?.requestId,target:function(e,t){if("sleep"===e.kind)return{kind:"sleep",durationMs:e.durationMs};if("selector"===e.kind)return{kind:"selector",selector:e.selectorExpression,timeoutMs:e.timeoutMs};if("ref"===e.kind){if(!t?.snapshot)throw new P("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new P("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(a,i)});return pt(n,r,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}}),u=await ps({req:t,logPath:e.logPath,session:i,device:o},l);return await pC(e,u,"wait")};return"sleep"===a.kind?await s():await c2(i,o,s)}async function pA(e,t,r){let n=await p_(e,r);if(pM(n))return n.response;if(!n)return null;let a=function(e,t,r){if(!r.found||!r.node)return null;let n={target:{kind:"selector",selector:t},node:r.node,selectorChain:[t]};return"attrs"===e?{kind:"attrs",...n}:"string"!=typeof r.text?null:{kind:"text",...n,text:r.text}}(t,n.selector.raw,n.result);return a?(pt(e.sessionStore,e.sessionName,e.req,c9(a,t)),{ok:!0,data:c7(a)}):null}async function pS(e,t,r,n){var a,i,o,s,l;let u;if("hidden"===t)return null;let d=await p_(e,r);if(pM(d))return d.response;if(!d?.result.found||!d.result.node)return null;let c="exists"===t?{predicate:t,pass:!0,selector:d.selector.raw,matches:1,selectorChain:[d.selector.raw]}:(a=t,i=n,o=d.selector.raw,s=d.session,u=to({predicate:a,node:l=d.result.node,nodes:[l],expectedText:i,platform:s.device.platform}),{predicate:a,pass:u.pass,selector:o,..."text"===a?{text:u.actualText}:{},selectorChain:[o]});return c?(pt(e.sessionStore,e.sessionName,e.req,c),{ok:!0,data:pe(c)}):null}async function pb(e){let t=ph({session:e.session,selectorExpression:e.selectorExpression});if(!e.session||!t)return null;let r=Date.now(),n=await px(e,e.session,t);if(pM(n))return n.response;if(!n?.found)return null;let a={kind:"selector",selector:t.raw,waitedMs:Date.now()-r,selectorChain:[t.raw]};return pt(e.sessionStore,e.sessionName,e.req,a),await ps({req:e.req,logPath:e.logPath,session:e.session,device:e.device},{ok:!0,data:a})}async function p_(e,t){let r=e.sessionStore.get(e.sessionName),n=ph({session:r,selectorExpression:t});if(!r||!n)return null;let a=await px(e,r,n);return pM(a)?a:a?{session:r,selector:n,result:a}:null}async function pN(e,t,r){let n=await n6(t.device,{command:"querySelector",selectorKey:r.key,selectorValue:r.value,appBundleId:t.appBundleId},{verbose:!!e.req.flags?.verbose,logPath:e.logPath,traceLogPath:t.trace?.outPath,requestId:e.req.meta?.requestId}),a=!0===n.found,i=function(e){let t=e.nodes;if(!Array.isArray(t))return;let r=t[0];if(r&&"object"==typeof r)return r}(n);return{found:a,..."string"==typeof n.text?{text:n.text}:{},...i?{node:i}:{}}}async function px(e,t,r){try{return await pN(e,t,r)}catch(e){if(pw(e))return null;return{kind:"error",response:{ok:!1,error:k(e)}}}}function pM(e){return null!==e&&"kind"in e&&"error"===e.kind}function pD(e){return tI({backend:function(e){let t,{req:r,session:n,device:a,logPath:i,sessionName:o,sessionStore:s}=e,l=0;return{platform:a.platform,captureSnapshot:async(e,u)=>{var d;let c,p={...r.flags,...(d=u,c={},d?.interactiveOnly!==void 0&&(c.snapshotInteractiveOnly=d.interactiveOnly),d?.compact!==void 0&&(c.snapshotCompact=d.compact),d?.scope!==void 0&&(c.snapshotScope=d.scope),d?.depth!==void 0&&(c.snapshotDepth=d.depth),d?.raw!==void 0&&(c.snapshotRaw=d.raw),c)},f=u?.scope??r.flags?.snapshotScope,m=Date.now(),h=tE(tk(p)),w="wait"===r.command||"find"===r.command;if(!w&&t&&m-l<750&&!dZ(n)&&!n?.postGestureStabilization)return t;if(!w&&n?.snapshot&&m-n.snapshot.createdAt<750&&n.snapshot.presentationKey===h&&!dZ(n)&&!n.postGestureStabilization)return l=n.snapshot.createdAt,t={snapshot:n.snapshot};let g=await d5({device:a,session:n,flags:p,outPath:r.flags?.out,logPath:i??"",snapshotScope:f});return n&&(ci(n,g.snapshot),s.set(o,n)),l=m,t={snapshot:g.snapshot}},readText:async(t,o)=>({text:await c0({device:a,node:o,flags:r.flags,appBundleId:n?.appBundleId,traceOutPath:n?.trace?.outPath,surface:n?.surface,contextFromFlags:e.contextFromFlags??((e,t,r)=>d1(i??"",e,t,r))})}),findText:async(t,r)=>({found:await pP(e,r)})}}(e),...pa("selector commands",{plural:!0}),sessions:co({sessionName:e.sessionName,getSession:()=>e.session,recordOptions:{includeSnapshot:!0},setRecord:t=>{e.session&&t.snapshot&&(ci(e.session,t.snapshot),e.sessionStore.set(e.sessionName,e.session))}})})}async function pk(e,t){let r=e.sessionStore.get(e.sessionName);if(!r&&t.requireSession)return{ok:!1,response:dM("SESSION_NOT_FOUND","No active session. Run open first.")};let n=r?.device??await os(e.req.flags??{});return(r||await o$(n),dK(t.capability,n))?{ok:!0,runtime:pD({...e,session:r,device:n})}:{ok:!1,response:dM("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function pP(e,t){let{device:r,session:n,req:a,logPath:i}=e;if("macos"===r.platform&&n?.surface&&"app"!==n.surface)return!!tj((await pO(e)).nodes,t);if(rW(r.platform)&&n?.appBundleId){let e=await n6(r,{command:"findText",text:t,appBundleId:n?.appBundleId},{verbose:a.flags?.verbose,logPath:i,traceLogPath:n?.trace?.outPath,requestId:a.meta?.requestId});return e?.found===!0}return!!tj((await pO(e)).nodes,t)}async function pO(e){let t=await d5({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&(ci(e.session,t.snapshot),e.sessionStore.set(e.sessionName,e.session)),t.snapshot}async function pE(e){try{return{ok:!0,data:await e()}}catch(t){let e=D(t);return dM(e.code,e.message,e.details)}}async function pC(e,t,r){var n;let a;if(t.ok)return t;let i=e.sessionStore.get(e.sessionName);if(!i)return t;try{a=await c6(i)}catch{return t}return a?dM(t.error.code,`${r} failed because ${"com.google.android.permissioncontroller"===(n=a).foregroundPackage?`Android permission dialog is blocking ${n.expectedPackage}`:`${n.foregroundPackage} is foreground instead of ${n.expectedPackage}`}.`,{...t.error.details??{},...a,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}async function pL(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return dM("INVALID_ARGS","find requires a locator or text");let{locator:l,query:u,action:d,value:c,timeoutMs:p}=tX(s);if(!u)return dM("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return dM("INVALID_ARGS","find accepts only one of --first or --last");let f=await pg({req:t,sessionName:r,logPath:n,sessionStore:a});if(f)return f;let m=a.get(r);if(!m&&"exists"!==d&&"wait"!==d&&"get_text"!==d&&"get_attrs"!==d)return dM("SESSION_NOT_FOUND","No active session. Run open first.");let h=m?.device??await os(t.flags??{});m||await o$(h);let w="role"!==l?u:void 0,g="click"===d||"focus"===d||"fill"===d||"type"===d,y=0,v=null,I=async()=>{let e=Date.now();if(v&&e-y<750&&!dZ(m))return{nodes:v};let{snapshot:i}=await d5({device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:g,snapshotCompact:g},outPath:t.flags?.out,logPath:n,snapshotScope:w}),o=i.nodes;return y=e,v=o,m&&(ci(m,i),a.set(r,m)),{nodes:o,truncated:i.truncated,backend:i.backend}},A={req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i,session:m,device:h,command:o,locator:l,query:u};if("wait"===d)return pR(A,I,l,u,p);let{nodes:S}=await I(),b=tJ(S,l,u,{requireRect:g});if(g&&b.matches.length>1)if(t.flags?.findFirst)b.matches=[b.matches[0]];else{if(!t.flags?.findLast){var _,N,x;let e;return _=b.matches,N=l,x=u,e=_.slice(0,8).map(e=>{let t=tU(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),dM("AMBIGUOUS_MATCH",`find matched ${_.length} elements for ${N} "${x}". Use a more specific locator or selector.`,{locator:N,query:x,matches:_.length,candidates:e})}b.matches=[b.matches[b.matches.length-1]]}let M=b.matches[0]??null;if(!M)return dM("COMMAND_FAILED","find did not match any element");let D="click"===d||"focus"===d||"fill"===d||"type"===d?tF(S,M)??M:M,k=`@${D.ref}`,P={node:M,resolvedNode:D,ref:k,nodes:S,actionFlags:{...t.flags??{},noRecord:!0}},O={exists:()=>pT(A),get_text:()=>p$(A,P),get_attrs:()=>pF(A,P),click:()=>pU(A,P),fill:()=>pG(A,P,c),focus:()=>pV(A,P),type:()=>pj(A,P,c)}[d];return O?O():null}async function pR(e,t,r,n,a){let{req:i,sessionStore:o,session:s,command:l}=e,u=a??1e4,d=Date.now();for(;Date.now()-d<u;){let{nodes:e}=await t();if(tJ(e,r,n,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:i.positionals??[],flags:i.flags??{},result:{found:!0,waitedMs:Date.now()-d}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-d}};await ex(300)}return dM("COMMAND_FAILED","find wait timed out")}async function pT(e){let{req:t,sessionStore:r,session:n,command:a}=e;return n&&r.recordAction(n,{command:a,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function p$(e,t){let{req:r,sessionStore:n,session:a,command:i,device:o,logPath:s}=e,l=await c0({device:o,node:t.node,flags:r.flags,appBundleId:a?.appBundleId,traceOutPath:a?.trace?.outPath,surface:a?.surface,contextFromFlags:(e,t,r)=>d1(s,e,t,r)});return a&&n.recordAction(a,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function pF(e,t){let{req:r,sessionStore:n,session:a,command:i}=e;return a&&n.recordAction(a,{command:i,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function pU(e,t){let{req:r,sessionName:n,sessionStore:a,session:i,invoke:o,command:s,locator:l,query:u}=e,d=await o({token:r.token,session:n,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!d.ok)return d;let c=t.resolvedNode.rect?tC(t.resolvedNode.rect):null,p={ref:t.ref,locator:l,query:u};return c&&(p.x=c.x,p.y=c.y),i&&a.recordAction(i,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:u}}),{ok:!0,data:p}}async function pG(e,t,r){let{req:n,sessionName:a,sessionStore:i,session:o,invoke:s,command:l}=e;if(!r)return dM("INVALID_ARGS","find fill requires text");let u=await s({token:n.token,session:a,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return u.ok&&o&&i.recordAction(o,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{ref:t.ref,action:"fill"}}),u}async function pV(e,t){let{req:r,sessionStore:n,session:a,device:i,command:o,logPath:s}=e,l=t.node.rect?tC(t.node.rect):null;if(!l)return dM("COMMAND_FAILED","matched element has no bounds");let u=await dI(i,"focus",[String(l.x),String(l.y)],r.flags?.out,{...d1(s,r.flags,a?.appBundleId,a?.trace?.outPath)});return a&&n.recordAction(a,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:u??{ref:t.ref}}}async function pj(e,t,r){let{req:n,sessionStore:a,session:i,device:o,command:s,logPath:l}=e;if(!r)return dM("INVALID_ARGS","find type requires text");let u=t.node.rect?tC(t.node.rect):null;if(!u)return dM("COMMAND_FAILED","matched element has no bounds");await dI(o,"focus",[String(u.x),String(u.y)],n.flags?.out,{...d1(l,n.flags,i?.appBundleId,i?.trace?.outPath)});let d=await dI(o,"type",[r],n.flags?.out,{...d1(l,n.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:s,positionals:n.positionals??[],flags:n.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:d??{ref:t.ref}}}function pB(e){var t,r,n;let a,i,o,{data:s,fallbackX:l,fallbackY:u,referenceFrame:d,extra:c}=e,p=(t=c,r=l,n=u,a="string"==typeof t?.ref?t.ref:void 0,i="string"==typeof t?.button?t.button:void 0,o="string"==typeof t?.gesture?t.gesture:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:a?"longpress"===o?`Long pressed @${a} (${r}, ${n})`:i&&"primary"!==i?`Clicked ${i} @${a} (${r}, ${n})`:`Tapped @${a} (${r}, ${n})`:void 0)??("string"==typeof s?.message?s.message:void 0));return{x:l,y:u,...d??{},...c??{},...s??{},...e$(p)}}function pq(e){let{session:t,sessionStore:r,command:n,positionals:a,flags:i,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:u,androidFreshnessBaseline:d}=e;return r.recordAction(t,{command:n,positionals:a,flags:i??{},result:o}),dQ(n)&&dX(t,n,d??t.snapshot),cj(t,n,a,o,i??{},l,u),{ok:!0,data:s}}async function pH(e){let{session:t,flags:r,sessionStore:n,contextFromFlags:a,captureSnapshotForSession:i}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await sv(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=cU(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=cU(await i(t,r,n,a,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function pW(e){try{return await pH(e)}catch(t){eb({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function pz(e){return cU({nodes:e,createdAt:0})}function pK(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:dM("UNSUPPORTED_OPERATION",`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function pJ(e){let t=e.sessionStore.get(e.sessionName);if(!t)throw new P("SESSION_NOT_FOUND","No active session. Run open first.");return tI({backend:function(e){let{req:t,session:r}=e;return{platform:r.device.platform,captureSnapshot:async(n,a)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:a?.interactiveOnly===!0})}),tap:async(n,a)=>pX(await dI(r.device,"press",[String(a.x),String(a.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fill:async(n,a,i)=>pX(await dI(r.device,"fill",[String(a.x),String(a.y),i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),longPress:async(n,a,i)=>pX(await dI(r.device,"longpress",[String(a.x),String(a.y),...i?.durationMs===void 0?[]:[String(i.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(n,a)=>pX(await dI(r.device,"type",[a],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),...pa("interaction commands",{plural:!0}),sessions:co({sessionName:e.sessionName,getSession:()=>t,recordOptions:{includeSnapshot:!0},setRecord:r=>{r.snapshot&&(ci(t,r.snapshot),e.sessionStore.set(e.sessionName,t))}})})}function pX(e){return e&&"object"==typeof e?e:void 0}function pZ(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}function pY(e,t){let r=pZ(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let n=e[0]??"";if(n.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:n,fallbackLabel:eY.decode(e).label??""}};let a=e.join(" ").trim();return a?{ok:!0,target:{kind:"selector",selector:a}}:{ok:!1,response:dM("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}function pQ(e){return"ref"===e.kind?{ref:p0(e.target?.kind==="ref"?e.target.ref:void 0),refLabel:e.refLabel,selectorChain:e.selectorChain}:"selector"===e.kind?{selector:e.target?.kind==="selector"?e.target.selector:void 0,selectorChain:e.selectorChain,refLabel:e.refLabel}:{}}function p0(e){return e?.startsWith("@")?e.slice(1):e}async function p1(e){switch(e.req.command){case"press":return await p2(e,"press");case"click":return await p2(e,"click");case"longpress":return await p2(e,"longpress");case"fill":return await p8(e);default:return null}}async function p2(e,t){let r,{req:n,sessionName:a,sessionStore:i}=e,o=i.get(a);if(!o)return dM("SESSION_NOT_FOUND","No active session. Run open first.");let s="click"===t?"click":t,l="longpress"===t?"longpress":"press",u=pK(o,s);if(u)return u;if(!dK(l,o.device))return dM("UNSUPPORTED_OPERATION",`${l} is not supported on this device`);let d=u1(n.flags),c="primary"===d?{}:{button:d};if("longpress"!==t&&"primary"!==d){let e=u2({commandLabel:s,platform:o.device.platform,button:d,count:n.flags?.count,intervalMs:n.flags?.intervalMs,holdMs:n.flags?.holdMs,jitterPx:n.flags?.jitterPx,doubleTap:n.flags?.doubleTap});if(e)return dM(e.code,e.message,e.details)}let p="longpress"===t?function(e){var t,r,n;let a,i=pZ(e);if(i){return{ok:!0,target:{kind:"point",x:i.x,y:i.y},...void 0===(t=e[2])?{}:{durationMs:Number(t)}}}let o=(a=(r=e).at(-1),r.length>1&&void 0!==(n=a)&&""!==n.trim()&&Number.isFinite(Number(n))?{targetPositionals:r.slice(0,-1),duration:{durationMs:Number(a)}}:{targetPositionals:r,duration:{}}),s=pY(o.targetPositionals,"longpress");return s.ok?{ok:!0,target:s.target,...o.duration}:s}(n.positionals??[]):pY(n.positionals??[],s);if(!p.ok)return p.response;if("ref"===p.target.kind){let a=e.refSnapshotFlagGuardResponse("longpress"===t?"longpress":"press",n.flags);if(a)return a;r=await p9(e,o)}let f=function(e){var t;let{session:r,commandLabel:n,target:a,flags:i}=e;return"click"!==n||"selector"!==a.kind||(t=i,t?.count!==void 0||t?.intervalMs!==void 0||t?.holdMs!==void 0||t?.jitterPx!==void 0||t?.doubleTap!==void 0||t?.clickButton!==void 0&&"primary"!==t.clickButton)?null:ph({session:r,selectorExpression:a.selector})}({session:o,commandLabel:s,target:p.target,flags:n.flags});if(f){let t=await p5(e,o,f);if(t)return t}let m="longpress"===t?p.durationMs:void 0;return await p6(e,{androidFreshnessBaseline:r,run:async e=>await p3({runtime:e,command:t,target:p.target,sessionName:a,requestId:n.meta?.requestId,clickButton:d,flags:n.flags,durationMs:m}),afterRun:async e=>{var t;await c8(o,(t=p.target,"point"===t.kind?"coordinate tap":"ref"===e.kind&&e.target?.kind==="ref"?e.target.ref:"selector"===e.kind&&e.target?.kind==="selector"?e.target.selector:"target"))},buildPayloads:async r=>{var n;let a="durationMs"in(n=r)?n.durationMs:void 0,i=await p4({params:e,session:o,result:r,extra:"longpress"===t?{...void 0!==a?{durationMs:a}:{},gesture:"longpress"}:c});return{result:i,responseData:i}}})}async function p3(e){let{runtime:t,command:r,target:n,sessionName:a,requestId:i,flags:o}=e;if("longpress"===r)return await t.interactions.longPress(n,{session:a,requestId:i,durationMs:e.durationMs});let s={session:a,requestId:i,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap};return"click"===r?await t.interactions.click(n,s):await t.interactions.press(n,s)}async function p4(e){let{params:t,session:r,result:n,extra:a}=e,i="point"===n.kind?await pW({session:r,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):pz(r.snapshot?.nodes??[]);return pB({data:n.backendResult,fallbackX:n.point.x,fallbackY:n.point.y,referenceFrame:i,extra:{...pQ(n),...a}})}async function p5(e,t,r){let n=Date.now();try{var a,i;let o,s,l=await dI(t.device,"press",[],e.req.flags?.out,{...e.contextFromFlags(e.req.flags,t.appBundleId,t.trace?.outPath),directElementSelector:r,surface:t.surface})??{},u=Date.now(),d=(a=l,o="number"==typeof a.x?a.x:void 0,s="number"==typeof a.y?a.y:void 0,void 0!==o&&void 0!==s?{x:o,y:s}:{x:0,y:0}),c=pB({data:l,fallbackX:d.x,fallbackY:d.y,referenceFrame:(i=l,"number"==typeof i.referenceWidth&&"number"==typeof i.referenceHeight?{referenceWidth:i.referenceWidth,referenceHeight:i.referenceHeight}:void 0),extra:{selector:r.raw}});return pq({session:t,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags,result:c,responseData:c,actionStartedAt:n,actionFinishedAt:u})}catch(e){if(!pw(e))return{ok:!1,error:k(e)};return eb({level:"debug",phase:"ios_direct_selector_tap_fallback",data:{selector:r.raw,error:e instanceof Error?e.message:String(e)}}),null}}async function p8(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(a){let e=pK(a,"fill");if(e)return e}if(a&&!dK("fill",a.device))return dM("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!a)return dM("SESSION_NOT_FOUND","No active session. Run open first.");let i=function(e){let t=e[0]??"";if(t.startsWith("@")){var r;let n=eX.decode(e).text;return n?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:(r=e).length>=3&&r[1]?.trim()||""},text:n}:{ok:!1,response:dM("INVALID_ARGS","fill requires text after ref")}}let n=pZ(e);if(n){let t=e.slice(2).join(" ");return t?{ok:!0,target:{kind:"point",x:n.x,y:n.y},text:t}:{ok:!1,response:dM("INVALID_ARGS","fill requires text after coordinates")}}let a=eX.decode(e);if("selector"!==a.kind)return{ok:!1,response:dM("INVALID_ARGS","fill requires x y text, @ref text, or selector text")};let i=a.text.trim();return i?{ok:!0,target:{kind:"selector",selector:a.target.selector},text:i}:{ok:!1,response:dM("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!i.ok)return i.response;if("ref"===i.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await p9(e,a)}return await p6(e,{run:async e=>await e.interactions.fill(i.target,i.text,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),buildPayloads:e=>{let t="point"===e.kind?void 0:pz(a.snapshot?.nodes??[]),r=pB({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...pQ(e),text:i.text}});e.warning&&(r.warning=e.warning);let n="ref"===e.kind?{...e.backendResult??{ref:p0(e.target?.kind==="ref"?e.target.ref:void 0),x:e.point.x,y:e.point.y}}:r;return e.warning&&(n.warning=e.warning),{result:r,responseData:n}}})}async function p6(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return dM("SESSION_NOT_FOUND","No active session. Run open first.");let n=pJ(e),a=Date.now();try{let i=await t.run(n);await t.afterRun?.(i);let o=Date.now(),{result:s,responseData:l}=await t.buildPayloads(i);return pq({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags,result:s,responseData:l,actionStartedAt:a,actionFinishedAt:o,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=D(t);if("COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage)throw e;return{ok:!1,error:k(t)}}}async function p9(e,t){if(!dZ(t))return;let r=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:"ref-refresh"})}catch(t){eb({level:"warn",phase:"android_ref_snapshot_refresh_failed",data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return r}async function p7(e,t,r,n,a){let i={...t??{},snapshotInteractiveOnly:a.interactiveOnly,snapshotCompact:a.interactiveOnly},o=n(i,e.appBundleId,e.trace?.outPath),{snapshot:s}=await d5({device:e.device,session:e,flags:i,outPath:i.out,logPath:o.logPath??"",androidFreshnessMode:a.androidFreshnessMode});return ci(e,s),r.set(e.name,e),s}async function fe(e){let t=await p1({...e,captureSnapshotForSession:p7,refSnapshotFlagGuardResponse:c5});if(t)return t;switch(e.req.command){case eW.name:return await ft({...e,captureSnapshotForSession:p7});case"get":return await py(e);case"is":return await pv(e);default:return null}}async function ft(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(!a)return dM("SESSION_NOT_FOUND","No active session. Run open first.");if(!dK(eW.name,a.device))return dM("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===a.device.platform&&a.recording&&"failed"===await cc({session:a}))return dM("COMMAND_FAILED","Android system dialog blocked the recording session");let i=(t.positionals??[]).join(" "),o=pJ(e),s=Date.now();try{let e=await o.interactions.typeText(i,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),l=Date.now(),u={...e.backendResult??{},text:e.text,delayMs:e.delayMs,...e$(e.message??`Typed ${Array.from(e.text).length} chars`)};return pq({session:a,sessionStore:n,command:t.command,positionals:t.positionals??[],flags:t.flags,result:u,responseData:u,actionStartedAt:s,actionFinishedAt:l})}catch(e){return{ok:!1,error:k(e)}}}function fr(e){return{tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend}}async function fn(e){let{req:t,leaseRegistry:r}=e,n=fr(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:n.tenantId??"",runId:n.runId??"",backend:n.leaseBackend,ttlMs:n.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:n.leaseId??"",tenantId:n.tenantId,runId:n.runId,ttlMs:n.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:n.leaseId??"",tenantId:n.tenantId,runId:n.runId})};default:return null}}async function fa(e){var t,r;let{req:n,sessionName:a,sessionStore:i}=e;if(n.command!==eO.reactNative)return null;let o=1===(t=n.positionals??[]).length&&"dismiss-overlay"===t[0]?{ok:!0}:{ok:!1,response:dM("INVALID_ARGS","react-native supports only: dismiss-overlay")};if(!o.ok)return o.response;let s=i.get(a);if(!s)return dM("SESSION_NOT_FOUND","No active session. Run open first.");if(!dK(eO.reactNative,s.device))return dM("UNSUPPORTED_OPERATION","react-native dismiss-overlay is not supported on this device");try{let t=await p7(s,n.flags,i,e.contextFromFlags,{interactiveOnly:!0}),a=tm(t.nodes);if(!a){return r=t,td(r.nodes).detected?dM("COMMAND_FAILED","React Native overlay detected, but no safe dismiss target was found",{hint:"Use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing the warning body."}):{ok:!0,data:{action:"dismiss-overlay",detected:!1,dismissed:!1,...e$("No React Native overlay detected")}}}return await fi(e,s,t,a)}catch(e){return{ok:!1,error:k(e)}}}async function fi(e,t,r,n){let{req:a,sessionStore:i}=e,o=Date.now(),s=await dI(t.device,"press",[String(n.point.x),String(n.point.y)],a.flags?.out,e.contextFromFlags(a.flags,t.appBundleId,t.trace?.outPath))??{},l=Date.now(),u={...pz(r.nodes),...s,action:"dismiss-overlay",overlayAction:n.action,x:n.point.x,y:n.point.y,...n.ref?{ref:n.ref}:{},...n.label?{label:n.label}:{},...n.warning?{warning:n.warning}:{},dismissed:!0,verified:!1,verificationRequired:!0,nextCommand:"agent-device snapshot -i -c",...e$("minimize"===n.action?"React Native RedBox minimize action sent; run snapshot -i before continuing":"React Native overlay dismiss action sent; run snapshot -i before continuing")};return pq({session:t,sessionStore:i,command:a.command,positionals:a.positionals??[],flags:a.flags,result:u,responseData:u,actionStartedAt:o,actionFinishedAt:l})}function fo(e=process.env){let t=fu(),r=f.join(t,"home"),n=f.join(t,"module-cache");return l.mkdirSync(r,{recursive:!0}),l.mkdirSync(n,{recursive:!0}),{...e,HOME:r,CLANG_MODULE_CACHE_PATH:n}}async function fs(e){let t=l.statSync(e.sourcePath),r=l.readFileSync(e.sourcePath),n=fp(e.cacheName??f.basename(e.sourcePath,f.extname(e.sourcePath))),a=ff(["1",process.platform,process.arch,f.resolve(e.sourcePath),t.size,r]),i=f.join(fu(),"bin",`${n}-${a}`);return await fd({sourcePath:e.sourcePath,executablePath:i,timeoutMs:e.timeoutMs}),i}async function fl(e){let t=fp(e.cacheName),r=ff(["1",process.platform,process.arch,e.source]),n=f.join(fu(),"sources",`${t}-${r}.swift`),a=f.join(fu(),"bin",`${t}-${r}`);return l.mkdirSync(f.dirname(n),{recursive:!0}),l.existsSync(n)||l.writeFileSync(n,e.source),await fd({sourcePath:n,executablePath:a,timeoutMs:e.timeoutMs}),a}function fu(){let e=process.env.AGENT_DEVICE_SWIFT_CACHE_DIR?.trim();return e?f.resolve(e):f.join(c.tmpdir(),"agent-device-swift-cache")}async function fd(e){if(fc(e.executablePath))return;l.mkdirSync(f.dirname(e.executablePath),{recursive:!0});let t=`${e.executablePath}.${process.pid}.${Date.now()}.tmp`;try{await C("xcrun",["swiftc",e.sourcePath,"-o",t],{timeoutMs:e.timeoutMs??12e4,env:fo()}),fc(e.executablePath)||l.renameSync(t,e.executablePath)}finally{l.rmSync(t,{force:!0})}}function fc(e){try{return l.accessSync(e,l.constants.X_OK),l.statSync(e).isFile()}catch{return!1}}function fp(e){return e.replaceAll(/[^A-Za-z0-9._-]/g,"-").replaceAll(/^-+|-+$/g,"")||"swift-helper"}function ff(e){let t=s("sha256");for(let r of e)t.update(Buffer.isBuffer(r)?r:String(r)),t.update("\0");return t.digest("hex").slice(0,16)}let fm=`
|
|
14
32
|
import Foundation
|
|
15
33
|
import AVFoundation
|
|
16
34
|
|
|
@@ -34,13 +52,23 @@ Task {
|
|
|
34
52
|
|
|
35
53
|
semaphore.wait()
|
|
36
54
|
exit(exitCode)
|
|
37
|
-
`.trim();async function
|
|
38
|
-
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return sp(e);return!1}catch(t){if(t instanceof W&&"TOOL_MISSING"===t.code)return sp(e);throw t}}async function sf(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await sc(e))return;await J(r)}}function sp(e){try{let t=i.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=i.openSync(e,"r");try{let e=i.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>i.readSync(t,e,0,8,r))break;let n=e.readUInt32BE(0),s=e.toString("latin1",4,8);if(a.push(s),1===n){let e=Buffer.alloc(8);if(8>i.readSync(t,e,0,8,r+8))break;n=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(n)||n<=0)break;r+=n}return a}finally{i.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function sm(e){let t=s.parse(e);return s.join(t.dir,`${t.name}.gesture-telemetry.json`)}function sh(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function sg(e){let t=s.dirname(l(import.meta.url)),r=[l(new URL(`./${e}`,import.meta.url)),s.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),s.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),s.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(i.existsSync(e))return e;throw new W("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}async function sw(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await su(t),await sf(t);let o=i.mkdtempSync(s.join(u.tmpdir(),"agent-device-record-overlay-")),l=s.join(o,`input${s.extname(t)||".mp4"}`),d=s.join(o,s.basename(t)),c=s.join(o,"home"),f=s.join(o,"module-cache");i.copyFileSync(t,l),i.mkdirSync(c,{recursive:!0}),i.mkdirSync(f,{recursive:!0});try{await Y("xcrun",["swift",r,"--input",l,"--output",d,...a],{timeoutMs:12e4,env:{...process.env,HOME:c,CLANG_MODULE_CACHE_PATH:f}}),await sf(d),i.copyFileSync(d,t)}catch(a){let e=a instanceof W?a:new W("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new W("COMMAND_FAILED",n,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{i.rmSync(o,{recursive:!0,force:!0})}}async function sy(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await sw({videoPath:r,scriptPath:t??=sg("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function sv(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await sw({videoPath:r,scriptPath:e??=sg("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function sS(e){let{videoPath:t,quality:a,targetLabel:i="recording"}=e;await sw({videoPath:t,scriptPath:r??=sg("recording-resize.swift"),scriptArgs:["--quality",String(a)],commandDescription:`Failed to resize the ${i}`})}function sI(e){return e instanceof Error?e.message:String(e)}function sA(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function sb(e){let{recording:t,deps:r,trimStartMs:a,targetLabel:n}=e,s=function(e){var t,r,a;let n,s,{recording:o,trimStartMs:l}=e,d=(n=sm((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:l}).videoPath),s={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?sh(r.flatMap(e=>{let t=e.tMs-a,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):sh(r))},i.writeFileSync(n,JSON.stringify(s,null,2)),n);return o.telemetryPath=d,d}({recording:t,trimStartMs:a});if(t.showTouches){let e=function(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}();if(e)t.overlayWarning??=e;else try{await r.overlayRecordingTouches({videoPath:t.outPath,telemetryPath:s,targetLabel:n})}catch(e){t.overlayWarning??=`failed to overlay recording touches: ${sI(e)}`}}}async function s_(e,t,r){return await O(L(e),t,r)}async function sN(e,t){let r=await s_(e,["shell","ps","-o","pid=","-p",t],{allowFailure:!0});return 0===r.exitCode&&r.stdout.split(/\s+/).map(e=>e.trim()).includes(t)}async function sM(e,t){for(let r=0;r<40;r+=1){if(!await sN(e,t))return!0;await J(250)}return!await sN(e,t)}async function sx(e,t){let r,a=0;for(let i=0;i<20;i+=1){let i=await s_(e,["shell","stat","-c","%s",t],{allowFailure:!0}),n=0===i.exitCode?i.stdout.trim():"";if(n.length>0&&n===r){if((a+=1)>=4)return}else a=0;r=n,await J(250)}}async function sD(e,t,r){for(let a=0;a<8;a+=1){let i=await s_(e,["shell","stat","-c","%s",t],{allowFailure:!0}),n=0===i.exitCode?Number(i.stdout.trim()):NaN;if(Number.isFinite(n)&&n>0)return!0;if(!await sN(e,r))break;if(a+1>=2)return!0;await J(250)}return!1}async function sk(e){let t,{deps:r,deviceId:a,remotePath:n,outPath:s}=e;for(let e=0;e<2;e+=1){try{i.rmSync(s,{force:!0})}catch{}let o=L(a),l=await k(n,s,{allowFailure:!0,device:o});if(0!==l.exitCode)t=sA(l,"adb pull");else{await r.waitForStableFile(s,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(s);if(A({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:n,outPath:s,attempt:e+1,fileSize:(()=>{try{return i.statSync(s).size}catch{return 0}})(),playable:t}}),t)return;A({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:n,outPath:s,attempt:e+1}})}e<1&&await J(750)}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function sP(e){let{deviceId:t,quality:r}=e;if(void 0===r||r>=10)return;let a=await s_(t,["shell","wm","size"],{allowFailure:!0}),i=a.stdout.match(/Override size:\s*(\d+)x(\d+)/)??a.stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(0!==a.exitCode||!i)throw Error(`failed to resolve Android screen size for recording quality: ${sA(a,"adb shell wm size")}`);return{width:sR(Number(i[1]),r),height:sR(Number(i[2]),r)}}function sR(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function sL(e,t){await s_(e,["shell","rm","-f",t],{allowFailure:!0})}async function sO(e,t){let r=await s_(e,["shell","kill","-9",t],{allowFailure:!0});return A({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:e,remotePid:t,exitCode:r.exitCode,stdout:r.stdout.trim(),stderr:r.stderr.trim()}}),!(0!==r.exitCode&&await sN(e,t))&&await sM(e,t)}async function sE(e){var t;let r,a,{device:i,recordingBase:n}=e,s="failed to start recording: Android screenrecord did not begin producing frames";try{r=await sP({deviceId:i.id,quality:n.quality})}catch(e){return em("COMMAND_FAILED",e instanceof Error?e.message:String(e))}for(let e of(t=Date.now(),a=`agent-device-recording-${t}.mp4`,[`/sdcard/${a}`,`/data/local/tmp/${a}`])){let t=await s_(i.id,["shell",function(e,t){let r=["screenrecord"];return t&&r.push("--size",`${t.width}x${t.height}`),r.push(e),`${r.join(" ")} >/dev/null 2>&1 & echo $!`}(e,r)],{allowFailure:!0});if(0!==t.exitCode){s=`failed to start recording: ${sA(t,"adb shell screenrecord")}`;continue}let a=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!a){s="failed to start recording: adb did not return a valid Android screenrecord pid",await sL(i.id,e);continue}if(A({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:a}}),await sD(i.id,e,a))return{platform:"android",remotePath:e,remotePid:a,...n,startedAt:Date.now()};s="failed to start recording: Android screenrecord did not begin producing frames",await sO(i.id,a),await sL(i.id,e)}return em("COMMAND_FAILED",s)}async function sC(e){let t,r,{deps:a,device:i,recording:n}=e;A({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let s=await s_(i.id,["shell","kill","-2",n.remotePid],{allowFailure:!0});if(A({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:s.exitCode,stdout:s.stdout.trim(),stderr:s.stderr.trim()}}),0!==s.exitCode?await sN(i.id,n.remotePid)&&!await sO(i.id,n.remotePid)&&(t=`failed to stop recording: ${sA(s,"adb shell kill")}`):await sM(i.id,n.remotePid)||await sO(i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await sx(i.id,n.remotePath);let e=await sk({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await o(),em("COMMAND_FAILED",e);await sb({recording:n,deps:a,targetLabel:"Android recording"})}if(await o(),t)return em("COMMAND_FAILED",t);if(r)return em("COMMAND_FAILED",r);return null;async function o(){let e=await s_(i.id,["shell","rm","-f",n.remotePath],{allowFailure:!0});A({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:i.id,remotePath:n.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${sA(e,"adb shell rm")}`)}}function s$(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function sT(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function sF(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,s=s$(r);if(s)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:s,interactiveOnly:!0,compact:!0,depth:1},sT(t,i,r))}catch(e){A({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:s,error:sI(e)}})}}async function sU(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:s,logPath:o,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=sT(a,o,i),h=async()=>l.runIosRunnerCommand(s,{command:"recordStart",outPath:f,fps:d,quality:u.quality,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var g,w;if(!sI(a).toLowerCase().includes("recording already in progress"))return em("COMMAND_FAILED",`failed to start recording: ${sI(a)}`);A({level:"warn",phase:"record_start_runner_desynced",data:{platform:s.platform,kind:s.kind,deviceId:s.id,session:i.name,error:sI(a)}});let e=(g=s.id,w=i.name,n.toArray().find(e=>e.name!==w&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===g&&e.recording?.platform==="ios-device-runner"));if(e)return em("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await l.runIosRunnerCommand(s,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return em("COMMAND_FAILED",`failed to start recording: ${sI(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function sV(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:s,recordingBase:o,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:o.outPath,fps:s,quality:o.quality,appBundleId:l},sT(t,i,r))}catch(e){return em("COMMAND_FAILED",`failed to start recording: ${sI(e)}`)}return{platform:"macos-runner",...o}}async function sG(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:s}=e,o=s$(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:o},sT(t,i,r))}catch(e){A({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:sI(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of Q)if(0===(l=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",s.remotePath,"--destination",s.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return em("COMMAND_FAILED",`failed to copy recording from device: ${e}`)}let d="number"!=typeof s.runnerStartedAtUptimeMs||"number"!=typeof s.targetAppReadyUptimeMs?0:Math.max(0,s.targetAppReadyUptimeMs-s.runnerStartedAtUptimeMs);return d>0&&await n.trimRecordingStart({videoPath:s.outPath,trimStartMs:d}),await sb({recording:s,deps:n,trimStartMs:d,targetLabel:"iOS recording"}),null}async function sj(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:s}=e,o=s$(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:o},sT(t,i,r))}catch(e){A({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:sI(e)}})}return await sb({recording:s,deps:n,targetLabel:"macOS recording"}),null}async function sq(e){for(let t=0;t<2;t+=1){try{if(i.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await J(250)}return Date.now()}async function sH(e){let t,r,{req:a,activeSession:i,device:n,logPath:s,deps:o,recordingBase:l,resolvedOut:d}=e;await sF({req:a,activeSession:i,device:n,logPath:s,deps:o});let{child:u,wait:c}=o.runCmdBackground("xcrun",ez(n,["io",n.id,"recordVideo",d]),{allowFailure:!0}),f=await sq(d);try{let e=Date.now(),l=await o.runIosRunnerCommand(n,{command:"uptime",appBundleId:s$(i)},{verbose:a.flags?.verbose,logPath:s,traceLogPath:i.trace?.outPath}),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:u,wait:c,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function sB(e){let t,{req:r,sessionName:a,sessionStore:n,activeSession:o,device:l,logPath:d,deps:u}=e;if(o.recording)return em("INVALID_ARGS","recording already in progress");let c=r.flags?.fps,f=r.flags?.quality;if(void 0!==c&&(!Number.isInteger(c)||c<1||c>120))return em("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==f&&(!Number.isInteger(f)||f<5||f>10))return em("INVALID_ARGS","quality must be an integer between 5 and 10");if(!eQ("record",l))return em("UNSUPPORTED_OPERATION","record is not supported on this device");let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,m=tK.expandHome(p,r.meta?.cwd),h={outPath:m,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),quality:r.flags?.quality,showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(i.mkdirSync(s.dirname(m),{recursive:!0}),i.rmSync(m,{force:!0}),"ios"===l.platform&&"device"===l.kind){let e=s$(o);if(!e)return em("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await sU({req:r,activeSession:o,sessionStore:n,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:h,appBundleId:e})}else if("macos"===l.platform){let e=s$(o);if(!e)return em("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await sV({req:r,activeSession:o,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:h,appBundleId:e})}else t="ios"===l.platform?await sH({req:r,activeSession:o,device:l,logPath:d,deps:u,recordingBase:h,resolvedOut:m}):await sE({device:l,recordingBase:h});return"ok"in t?t:(o.recording=t,n.set(a,o),n.recordAction(o,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??p,showTouches:t.showTouches}})}async function sK(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await sC({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return em("COMMAND_FAILED",`failed to stop recording: ${sA(i,"simctl recordVideo")}`);if(void 0!==a.quality&&a.quality<10)try{await t.resizeRecording({videoPath:a.outPath,quality:a.quality,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to resize recording: ${sI(e)}`}return await sb({recording:a,deps:t,targetLabel:"iOS recording"}),null}async function sz(e){var t;let r,{req:a,activeSession:i,device:n,logPath:o,deps:l}=e;if(!i.recording)return em("INVALID_ARGS","no active recording");let d=i.recording,u=d.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===d.platform?await sG({req:a,activeSession:i,device:n,logPath:o,deps:l,recording:d}):"macos-runner"===d.platform?await sj({req:a,activeSession:i,device:n,logPath:o,deps:l,recording:d}):await sK({deps:l,device:n,recording:d});return c||(u?em("COMMAND_FAILED",u):(r=[{field:"outPath",path:(t=d).outPath,localPath:t.clientOutPath,fileName:s.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return sm(e.clientOutPath)}(t),fileName:s.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function sW(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:Y,runCmdBackground:X,runIosRunnerCommand:eq,waitForStableFile:su,isPlayableVideo:sc,trimRecordingStart:sy,resizeRecording:sS,overlayRecordingTouches:sv},s=a.get(r),o=s?.device??await ew(t.flags??{});s||await eH(o);let l=s??{name:r,device:o,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return em("INVALID_ARGS","record requires start|stop");if("start"===d)return sB({req:t,sessionName:r,sessionStore:a,activeSession:l,device:o,logPath:i,deps:n});let u=await sz({req:t,activeSession:l,device:o,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function sJ(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,o=t.command;if("record"===o)return sW({req:t,sessionName:r,sessionStore:a,logPath:n});if("trace"===o){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return em("INVALID_ARGS","trace requires start|stop");let n=a.get(r);if(!n)return em("SESSION_NOT_FOUND","No active session");if("start"===e){if(n.trace)return em("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(n),r=tK.expandHome(e);return i.mkdirSync(s.dirname(r),{recursive:!0}),i.appendFileSync(r,""),n.trace={outPath:r,startedAt:Date.now()},a.recordAction(n,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!n.trace)return em("INVALID_ARGS","no active trace");let l=n.trace.outPath;if(t.positionals?.[1]){let e=tK.expandHome(t.positionals[1]);i.mkdirSync(s.dirname(e),{recursive:!0}),i.existsSync(l)?i.renameSync(l,e):i.appendFileSync(e,""),l=e}return n.trace=void 0,a.recordAction(n,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l}}),{ok:!0,data:{trace:"stopped",outPath:l}}}return null}function sZ(e){return"number"==typeof e.gestureClockOriginAtMs&&"number"==typeof e.gestureClockOriginUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureClockOriginAtMs+(e.gestureStartUptimeMs-e.gestureClockOriginUptimeMs)-e.recordingStartedAt):"number"==typeof e.runnerStartedAtUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureStartUptimeMs-e.runnerStartedAtUptimeMs):"number"==typeof e.gestureStartUptimeMs&&"number"==typeof e.gestureEndUptimeMs?Math.max(0,e.fallbackFinishedAtMs-(e.gestureEndUptimeMs-e.gestureStartUptimeMs)-e.recordingStartedAt):Math.max(0,e.fallbackStartedAtMs-e.recordingStartedAt)}let sX=new WeakMap;function sY(e){if(!e)return;let t=sX.get(e);if(t)return t;let r=function(e){let t=function(e){let t=e.filter(e=>(function(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("application")||t.includes("window")})(e.type)&&sQ(e.rect)).map(e=>e.rect).sort((e,t)=>(t?.width??0)*(t?.height??0)-(e?.width??0)*(e?.height??0))[0];if(t)return t;let r=e.map(e=>e.rect).filter(sQ);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),i=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(i<=0))return{x:0,y:0,width:a,height:i}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return sX.set(e,r),r}function sQ(e){return!!e&&e.width>0&&e.height>0}let s0={referenceWidth:1e3,referenceHeight:1e3};function s1(e,t,r,a,i={},n=Date.now(),s=Date.now()){var o,l,d;let u,c,f=e.recording;if(!f)return;let p={...i,...a??{}},m=s5(p.effectiveDurationMs)??s5(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:s5(p.gestureStartUptimeMs),gestureEndUptimeMs:s5(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:s},g="number"==typeof(o={gestureStartUptimeMs:s5(p.gestureStartUptimeMs),gestureEndUptimeMs:s5(p.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:s}).gestureStartUptimeMs&&"number"==typeof o.gestureEndUptimeMs?Math.max(0,o.gestureEndUptimeMs-o.gestureStartUptimeMs):"number"==typeof o.reportedDurationMs?Math.max(0,o.reportedDurationMs):Math.max(0,o.fallbackFinishedAtMs-o.fallbackStartedAtMs),w="ios"===e.device.platform&&void 0===s5(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=s4(s5(t.count),1)??1,r=!0===t.doubleTap,a=s4(s5(t.holdMs),1);return 1===e&&!r&&void 0===a}default:return!1}}(t,p)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return sZ(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):sZ(h),y=(l=e.snapshot,u=s5((d=p).referenceWidth),c=s5(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:sY(l)),v=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=s6(t,e);if(!i)return[];let{x:n,y:s}=i,o=s4(s5(t.count),1)??1,l=s4(s5(t.intervalMs),0)??0,d=!0===t.doubleTap,u=s4(s5(t.holdMs),1),c=[];for(let e=0;e<o;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(s8(t,n,s,u,a));continue}c.push(s2(t,n,s,a)),d&&c.push(s2(t+90,n,s,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=s6(t,e);if(!i)return[];let{x:n,y:s}=i;return[s2(r,n,s,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=s6(t,e);if(!n)return[];let{x:s,y:o}=n;return[s8(r,s,o,s7(a,[s5(t.durationMs),s5(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=s9(t,e),s=s3(t.contentDirection)??s3(t.direction);if(!n||!s)return[];let{x1:o,y1:l,x2:d,y2:u}=n,c=s7(a,[],250),f=s5(t.amount)??s5(e[1]),p=s5(t.pixels);return[{kind:"scroll",tMs:r,x:o,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:s,...void 0!==f?{amount:f}:{},...void 0!==p?{pixels:p}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=s9(t,e);if(!n)return[];let{x1:s,y1:o,x2:l,y2:d}=n,u=s7(a,[s5(t.effectiveDurationMs),s5(t.durationMs),s5(e[4])],250),c=s4(s5(t.count),1)??1,f=s4(s5(t.pauseMs),0)??0,p="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===p&&e%2==1,a=t?l:s,n=t?d:o,c=t?s:l,h=t?o:d,g=r+e*(u+f);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=s6(t,e,1),s=s5(t.scale)??s5(e[0]);if(!n||void 0===s||s<=0)return[];let{x:o,y:l}=n;return[{kind:"pinch",tMs:r,x:o,y:l,...i,scale:s,durationMs:s7(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,w,g,y);0!==v.length&&(f.gestureEvents.push(...v),A({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:v.length,tMs:w,gestureDurationMs:g,kinds:v.map(e=>e.kind)}}))}function s2(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function s8(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function s3(e){if("string"!=typeof e)return;let t=e.trim().toLowerCase();switch(t){case"up":case"down":case"left":case"right":return t;default:return}}function s5(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e||0===e.trim().length)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function s4(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function s6(e,t,r=0){let a=s5(e.x)??s5(t[r]),i=s5(e.y)??s5(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function s9(e,t){let r=s5(e.x1)??s5(t[0]),a=s5(e.y1)??s5(t[1]),i=s5(e.x2)??s5(t[2]),n=s5(e.y2)??s5(t[3]);if(void 0!==r&&void 0!==a&&void 0!==i&&void 0!==n)return{x1:r,y1:a,x2:i,y2:n}}function s7(e,t,r){return s4(e,1)??t.map(e=>s4(e,1)).find(e=>void 0!==e)??r}function oe(e){var t,r,a;let i,n,{data:s,fallbackX:o,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,r=o,a=l,i="string"==typeof t?.ref?t.ref:void 0,n="string"==typeof t?.button?t.button:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:i?n&&"primary"!==n?`Clicked ${n} @${i} (${r}, ${a})`:`Tapped @${i} (${r}, ${a})`:void 0)??("string"==typeof s?.message?s.message:void 0));return{x:o,y:l,...d??{},...u??{},...s??{},...ta(c)}}function ot(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:s,responseData:o,actionStartedAt:l,actionFinishedAt:d,androidFreshnessBaseline:u}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:s}),ef(a)&&e6(t,a,u??t.snapshot),s1(t,a,i,s,n??{},l,d),{ok:!0,data:o}}async function or(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await eN(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let s=sY(t.snapshot);if(s)return t.recording&&(t.recording.touchReferenceFrame=s),s;if(!t.recording)return;let o=sY(await n(t,r,a,i,{interactiveOnly:!0}));return o&&t.recording&&(t.recording.touchReferenceFrame=o),o}async function oa(e){try{return await or(e)}catch(t){A({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function oi(e){return sY({nodes:e,createdAt:0})}function on(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:em("UNSUPPORTED_OPERATION",`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function os(e){let t=e.sessionStore.get(e.sessionName);if(!t)throw new W("SESSION_NOT_FOUND","No active session. Run open first.");return e_({backend:function(e){let{req:t,session:r}=e;return{platform:r.device.platform,captureSnapshot:async(a,i)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:i?.interactiveOnly===!0})}),tap:async(a,i)=>oo(await er(r.device,"press",[String(i.x),String(i.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fill:async(a,i,n)=>oo(await er(r.device,"fill",[String(i.x),String(i.y),n],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(a,i)=>oo(await er(r.device,"type",[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),artifacts:eU("interaction commands",{plural:!0}),sessions:{get:r=>r===e.sessionName?{name:e.sessionName,appBundleId:t.appBundleId,appName:t.appName,snapshot:t.snapshot,metadata:{surface:t.surface}}:void 0,set:r=>{r.snapshot&&(ev(t,r.snapshot),e.sessionStore.set(e.sessionName,t))}},policy:ed()})}function oo(e){return e&&"object"==typeof e?e:void 0}function ol(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}function od(e){return"ref"===e.kind?{ref:ou(e.target?.kind==="ref"?e.target.ref:void 0),refLabel:e.refLabel,selectorChain:e.selectorChain}:"selector"===e.kind?{selector:e.target?.kind==="selector"?e.target.selector:void 0,selectorChain:e.selectorChain,refLabel:e.refLabel}:{}}function ou(e){return e?.startsWith("@")?e.slice(1):e}async function oc(e){switch(e.req.command){case"press":case"click":return await of(e);case"fill":return await op(e);default:return null}}async function of(e){let t,{req:r,sessionName:a,sessionStore:i}=e,n=i.get(a),s="click"===r.command?"click":"press";if(!n)return em("SESSION_NOT_FOUND","No active session. Run open first.");let o=on(n,s);if(o)return o;if(!eQ("press",n.device))return em("UNSUPPORTED_OPERATION","press is not supported on this device");let l=ek(r.flags),d=ei(l);if("primary"!==l){let e=eu({commandLabel:s,platform:n.device.platform,button:l,count:r.flags?.count,intervalMs:r.flags?.intervalMs,holdMs:r.flags?.holdMs,jitterPx:r.flags?.jitterPx,doubleTap:r.flags?.doubleTap});if(e)return em(e.code,e.message,e.details)}let u=function(e,t){let r=ol(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let a=e[0]??"";if(a.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:a,fallbackLabel:e.length>1?e.slice(1).join(" ").trim():""}};let i=e.join(" ").trim();return i?{ok:!0,target:{kind:"selector",selector:i}}:{ok:!1,response:em("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}(r.positionals??[],s);if(!u.ok)return u.response;if("ref"===u.target.kind){let a=e.refSnapshotFlagGuardResponse("press",r.flags);if(a)return a;t=await oh(e,n)}return await om(e,{androidFreshnessBaseline:t,run:async e=>{let t={session:a,requestId:r.meta?.requestId,button:l,count:r.flags?.count,intervalMs:r.flags?.intervalMs,holdMs:r.flags?.holdMs,jitterPx:r.flags?.jitterPx,doubleTap:r.flags?.doubleTap};return"click"===s?await e.interactions.click(u.target,t):await e.interactions.press(u.target,t)},afterRun:async e=>{var t;await eI(n,(t=u.target,"point"===t.kind?"coordinate tap":"ref"===e.kind&&e.target?.kind==="ref"?e.target.ref:"selector"===e.kind&&e.target?.kind==="selector"?e.target.selector:"target"))},buildPayloads:async t=>{let a="point"===t.kind?await oa({session:n,flags:r.flags,sessionStore:i,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:e.captureSnapshotForSession}):oi(n.snapshot?.nodes??[]),s=oe({data:t.backendResult,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:a,extra:{...od(t),...d}});return{result:s,responseData:s}}})}async function op(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(i){let e=on(i,"fill");if(e)return e}if(i&&!eQ("fill",i.device))return em("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!i)return em("SESSION_NOT_FOUND","No active session. Run open first.");let n=function(e){let t=e[0]??"";if(t.startsWith("@")){let r=e.length>=3?e[1]:"",a=e.length>=3?e.slice(2).join(" "):e.slice(1).join(" ");return a?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:r},text:a}:{ok:!1,response:em("INVALID_ARGS","fill requires text after ref")}}let r=ol(e);if(r){let t=e.slice(2).join(" ");return t?{ok:!0,target:{kind:"point",x:r.x,y:r.y},text:t}:{ok:!1,response:em("INVALID_ARGS","fill requires text after coordinates")}}let a=tu(e,{preferTrailingValue:!0});if(!a)return{ok:!1,response:em("INVALID_ARGS","fill requires x y text, @ref text, or selector text")};let i=a.rest.join(" ").trim();return i?{ok:!0,target:{kind:"selector",selector:a.selectorExpression},text:i}:{ok:!1,response:em("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!n.ok)return n.response;if("ref"===n.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await oh(e,i)}return await om(e,{run:async e=>await e.interactions.fill(n.target,n.text,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),buildPayloads:e=>{let t="point"===e.kind?void 0:oi(i.snapshot?.nodes??[]),r=oe({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...od(e),text:n.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:ou(e.target?.kind==="ref"?e.target.ref:void 0),x:e.point.x,y:e.point.y}}:r;return e.warning&&(a.warning=e.warning),{result:r,responseData:a}}})}async function om(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return em("SESSION_NOT_FOUND","No active session. Run open first.");let a=os(e),i=Date.now();try{let n=await t.run(a);await t.afterRun?.(n);let s=Date.now(),{result:o,responseData:l}=await t.buildPayloads(n);return ot({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags,result:o,responseData:l,actionStartedAt:i,actionFinishedAt:s,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=K(t);if(eV(e))throw e;return{ok:!1,error:z(t)}}}async function oh(e,t){if(!eW(t))return;let r=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:"ref-refresh"})}catch(t){A({level:"warn",phase:"android_ref_snapshot_refresh_failed",data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return r}async function og(e,t,r,a,i){let n={...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},s=a(n,e.appBundleId,e.trace?.outPath),{snapshot:o}=await ex({device:e.device,session:e,flags:n,outPath:n.out,logPath:s.logPath??"",androidFreshnessMode:i.androidFreshnessMode});return ev(e,o),r.set(e.name,e),o}let ow=/\bis(?:n't| not)\s+responding\b/i,oy=/^close app$/i;async function ov(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oS(t),r=function(e){if(o_(e))return e.find(e=>{let t=ob(e);return t.length>0&&oy.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=tI(r.rect),n=await O(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))],{allowFailure:!0});if(0!==n.exitCode)return A({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:n.exitCode,stdout:n.stdout.trim(),stderr:n.stderr.trim()}}),"failed";if(!await oI(t))return A({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await G(t.device,t.appBundleId),!await oA(t,t.appBundleId)))return A({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return A({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:a,y:i}}),"recovered"}catch(e){return A({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function oS(e){return tS(tv((await eg(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function oI(e){for(let t=0;t<12;t+=1){if(!o_(await oS(e)))return!0;await J(500)}return!o_(await oS(e))}async function oA(e,t){for(let r=0;r<12;r+=1){if((await F(e.device)).package===t)return!0;await J(500)}return(await F(e.device)).package===t}function ob(e){let t=[e.label,e.identifier];return"string"==typeof e.value&&e.value.trim().length>0&&t.push(e.value),t.filter(e=>"string"==typeof e&&e.trim().length>0).join(" ").trim()}function o_(e){return e.some(e=>{let t=ob(e);return t.length>0&&ow.test(t)})}async function oN(e){let t=await oc({...e,captureSnapshotForSession:og,refSnapshotFlagGuardResponse:ea});if(t)return t;switch(e.req.command){case"type":return await oM({...e,captureSnapshotForSession:og});case"get":return await eS(e);case"is":return await eD(e);default:return null}}async function oM(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return em("SESSION_NOT_FOUND","No active session. Run open first.");if(!eQ("type",i.device))return em("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===i.device.platform&&i.recording&&"failed"===await ov({session:i}))return em("COMMAND_FAILED","Android system dialog blocked the recording session");let n=(t.positionals??[]).join(" "),s=os(e),o=Date.now();try{let e=await s.interactions.typeText(n,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),l=Date.now(),d={...e.backendResult??{},text:e.text,delayMs:e.delayMs,...ta(e.message??`Typed ${Array.from(e.text).length} chars`)};return ot({session:i,sessionStore:a,command:t.command,positionals:t.positionals??[],flags:t.flags,result:d,responseData:d,actionStartedAt:o,actionFinishedAt:l})}catch(e){return{ok:!1,error:z(e)}}}function ox(e){return{tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend}}async function oD(e){let{req:t,leaseRegistry:r}=e,a=ox(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:a.tenantId??"",runId:a.runId??"",backend:a.leaseBackend,ttlMs:a.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId,ttlMs:a.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId})};default:return null}}function ok(e,t){if(!t)return[];let r=[],a=e.device,i=e8(t.platform);if(i&&!eY(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=T(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function oP(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let oR=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"];async function oL(e){let{session:t,sessionName:r,outPath:a,outputPlacement:i,dispatchContext:o}=e,l=e_({backend:function(e){let{session:t,outputPlacement:r,dispatchContext:a}=e;return{platform:t.device.platform,captureScreenshot:async(e,i,n)=>{let s={...a,screenshotFullscreen:n?.fullscreen,overlayRefs:n?.overlayRefs,surface:n?.surface};return"out"===r?oO(await er(t.device,"screenshot",[],i,s)):oO(await er(t.device,"screenshot",[i],void 0,s))}}}({session:t,outputPlacement:i,dispatchContext:o}),artifacts:{resolveInput:async()=>{throw new W("UNSUPPORTED_OPERATION","screenshot does not resolve input artifacts")},reserveOutput:async e=>{let t,r;return e?.kind==="path"?r=e.path:(t=await n.mkdtemp(s.join(u.tmpdir(),"agent-device-screenshot-")),r=s.join(t,"screenshot.png")),await n.mkdir(s.dirname(r),{recursive:!0}),{path:r,visibility:"client-visible",publish:async()=>void 0,...t?{cleanup:async()=>{await n.rm(t,{recursive:!0,force:!0})}}:{}}},createTempFile:async e=>{let t=await n.mkdtemp(s.join(u.tmpdir(),`${e.prefix}-`));return{path:s.join(t,`file${e.ext}`),visibility:"internal",cleanup:async()=>{await n.rm(t,{recursive:!0,force:!0})}}}},sessions:{get:e=>e===r?{name:r,appBundleId:t.appBundleId,metadata:{surface:t.surface}}:void 0,set:()=>{}},policy:ed()});return await l.capture.screenshot({session:r,requestId:o.requestId,appBundleId:t.appBundleId,fullscreen:o.screenshotFullscreen,maxSize:o.screenshotMaxSize,surface:t.surface,...a?{out:{kind:"path",path:a}}:{}})}function oO(e){if("object"==typeof e&&null!==e)return{..."string"==typeof e.path?{path:e.path}:{},...Array.isArray(e.overlayRefs)?{overlayRefs:e.overlayRefs}:{}}}let oE=[255,59,48,255],oC=[255,214,10,255],o$=[0,0,0,255],oT={e:["01110","10000","11110","10000","10000","10001","01110"],0:["01110","10001","10011","10101","11001","10001","01110"],1:["00100","01100","00100","00100","00100","00100","01110"],2:["01110","10001","00001","00010","00100","01000","11111"],3:["11110","00001","00001","01110","00001","00001","11110"],4:["00010","00110","01010","10010","11111","00010","00010"],5:["11111","10000","10000","11110","00001","00001","11110"],6:["01110","10000","10000","11110","10001","10001","01110"],7:["11111","00001","00010","00100","01000","01000","01000"],8:["01110","10001","10001","01110","10001","10001","01110"],9:["01110","10001","10001","01111","00001","00001","01110"]};async function oF(e){let t=e5(await n.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)oV(r)&&oB(r.rect)&&(!t||oK(r.rect)>oK(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,a=-1/0,i=-1/0;for(let n of e)n.rect&&oB(n.rect)&&(t=Math.min(t,n.rect.x),r=Math.min(r,n.rect.y),a=Math.max(a,n.rect.x+n.rect.width),i=Math.max(i,n.rect.y+n.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||a<=t||i<=r?null:{x:t,y:r,width:a-t,height:i-r}}(e.filter(e=>{var t;return oB(e.rect)&&!("image"===ty((t=e).type??"")&&!oG(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(oj)||oq(e.identifier);return oU(e)?t:t&&function(e){let t=ty(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(a))continue;let s=function(e,t){if(function(e){return oU(e)&&!oV(e)}(t)&&oB(t.rect))return t;let r=function(e,t){let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){;a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(oU(t)&&!oV(t)&&oB(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&oB(r.rect))return r;if(t.hittable&&oB(t.rect)&&!oV(t))return t;let a=tc(e,t);return a?.rect&&oB(a.rect)&&!oV(a)?a:null}(e.nodes,a);if(!s?.rect||!oB(s.rect))continue;let o=function(e,t,r){let a=oH(e);if(e.ref!==t.ref&&a)return a;let i=function(e,t){let r=null;for(let a of t){if(a.ref===e.ref||!function(e,t,r){let a=e;for(;void 0!==a.parentIndex;){let e=r[a.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;a=e}return!1}(a,e,t))continue;let i=oH(a);if(!i)continue;let n=function(e){let t=0;return ty(e.type??"").includes("text")&&(t+=2),oj(e.label)&&(t+=2),oj(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(oH(t)??tg(t,r))}(a,s,e.nodes),l=function(e,t,r){let a=0;return e.ref===t.ref&&(a+=4),t.hittable&&(a+=3),oU(t)&&(a+=3),oU(e)&&(a+=2),r&&(a+=2),oq(t.identifier)&&(a+=1),oG(t.value)&&(a+=1),a}(a,s,o),d=function(e,t,r,a){if(!e)return oJ({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,a);let i=r/e.width,n=a/e.height;return oJ({x:Math.round((t.x-e.x)*i),y:Math.round((t.y-e.y)*n),width:Math.max(1,Math.round(t.width*i)),height:Math.max(1,Math.round(t.height*n))},r,a)}(i,s.rect,t,r);if(!oB(d))continue;let u=n.get(s.ref);(!u||l>u.score)&&n.set(s.ref,{ref:s.ref,label:o,rect:s.rect,overlayRect:d,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>oK(e.overlayRect)-oK(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(oz(e.overlayRect,r.overlayRect)||oz(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}oK(r.overlayRect)<oK(t[e].overlayRect)&&(t[e]=r)}return t})([...n.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:oW(e.ref,t.ref)}).slice(0,a.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:oW(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:tI(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,i;(function(e,t,r){for(let a=0;a<2;a+=1)oX(e,t.x,t.x+t.width-1,t.y+a,r),oX(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),oY(e,t.x+a,t.y,t.y+t.height-1,r),oY(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,oE),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=oZ(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,s=n>=0?n:oZ(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,i){for(let n=0;n<11;n+=1)for(let s=0;s<a;s+=1)oQ(e,t+s,r+n,i)})(e,i,s,a,oC),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=oT[t];if(a)for(let t=0;t<a.length;t+=1)for(let s=0;s<a[t].length;s+=1)"1"===a[t][s]&&oQ(e,n+s,r+t,i);n+=6}}(e,i+3,s+2,r,o$)}(a,i.overlayRect,i.ref)}return await n.writeFile(e.screenshotPath,g.sync.write(t)),r}function oU(e){let t=[e.type,e.role,e.subrole].map(e=>ty(e??"")).join(" ");return t.includes("button")||t.includes("link")||t.includes("menu")||t.includes("tab")||t.includes("textfield")||t.includes("searchfield")||t.includes("securetextfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")||t.includes("cell")}function oV(e){let t=[e.type,e.role,e.subrole].map(e=>ty(e??"")).join(" ");return t.includes("application")||t.includes("window")}function oG(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function oj(e){var t;let r;return!!oG(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function oq(e){var t;return"string"==typeof e&&!!oj(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function oH(e){let t=[e.label,e.value].find(oj);return t?t.trim():oq(e.identifier)?e.identifier.trim():void 0}function oB(e){return!!(e&&e.width>0&&e.height>0)}function oK(e){return e.width*e.height}function oz(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 oW(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function oJ(e,t,r){let a=oZ(e.x,0,Math.max(0,t-1)),i=oZ(e.y,0,Math.max(0,r-1)),n=Math.max(1,t-a),s=Math.max(1,r-i);return{x:a,y:i,width:oZ(e.width,1,n),height:oZ(e.height,1,s)}}function oZ(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function oX(e,t,r,a,i){for(let n=t;n<=r;n+=1)oQ(e,n,a,i)}function oY(e,t,r,a,i){for(let n=r;n<=a;n+=1)oQ(e,t,n,i)}function oQ(e,t,r,a){if(t<0||r<0||t>=e.width||r>=e.height)return;let i=(e.width*r+t)*4;e.data[i]=a[0],e.data[i+1]=a[1],e.data[i+2]=a[2],e.data[i+3]=a[3]}let o0=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),o1=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),o2=new Set(o1),o8=new Map;function o3(e){if(eC(e.meta?.requestId))throw ec()}function o5(e,t,r,a){let i=I().requestId;return{...eL(e,t,r,a,i),requestId:i}}async function o4(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||au(e.flags))try{let t=await ew(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function o6(e,t){if(t)return"android"===t.device.platform?t.device:void 0;if("open"!==e.command&&!au(e.flags))return;let r=await ew(e.flags??{});return"android"===r.platform?r:void 0}async function o9(e){let{req:t,existingSession:r,androidAdbProvider:a}=e;if(!a)return{};let i=await o6(t,r);if(!i)return{};let n=a({req:t,device:i,session:r}),s="function"==typeof n?n:n?.exec;return{provider:n,executor:s,serial:i.id}}async function o7(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:s,androidAdbExecutor:o,contextFromFlags:l}=e,d=await oD({req:t,leaseRegistry:n});if(d)return d;let u=await n7({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:s,androidAdbExecutor:o});if(u)return u;let c=await en({req:t,sessionName:r,logPath:a,sessionStore:i});if(c)return c;let f=await sJ({req:t,sessionName:r,sessionStore:i,logPath:a});if(f)return f;let p=await se({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:s});if(p)return p;let m=await oN({req:t,sessionName:r,logPath:a,sessionStore:i,contextFromFlags:l});return m||null}async function le(e){var t,r;let a,i,n,s,o,l,d,{req:u,session:c,logPath:f,sessionStore:p}=e,m=u.command;if(!eQ(m,c.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${m} is not supported on this device`}};if("android"===c.device.platform&&c.recording&&"record"!==m&&"failed"===await ov({session:c}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:h,resolvedOut:g,recordedPositionals:w,recordedFlags:y}=(a=(t=u).command,i=t.positionals??[],n=t.flags?.out,s="screenshot"===a&&i[0]?[tK.expandHome(i[0],t.meta?.cwd),...i.slice(1)]:i,o="screenshot"===a&&n?tK.expandHome(n,t.meta?.cwd):n,l="screenshot"===a?s:i,d="screenshot"===a&&o?{...t.flags??{},out:o}:t.flags??{},{resolvedPositionals:s,resolvedOut:o,recordedPositionals:l,recordedFlags:d}),v=Date.now(),S={...o5(f,u.flags,c.appBundleId,c.trace?.outPath),surface:c.surface},I="screenshot"===m?await oL({session:c,sessionName:e.sessionName,outPath:h[0]??g,outputPlacement:"screenshot"!==(r=u).command?"default":(r.positionals??[])[0]?"positional":r.flags?.out?"out":"default",dispatchContext:S}):await er(c.device,m,h,g,{...S});return"screenshot"===m&&u.flags?.overlayRefs&&"string"==typeof I?.path&&await lt(c,I,f),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:i,recordedPositionals:n,recordedFlags:s,data:o,actionStartedAt:l,actionFinishedAt:d,flags:u}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let i=sY(e.snapshot),n={...a??{}},s=s3(n.direction)??s3(r[0]);if(!s)return a;let o=s5(n.amount)??s5(r[1]),l=s5(n.pixels),d=s9(n,[]),u=s5(n.referenceWidth),c=s5(n.referenceHeight),f=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:i??s0;if(d&&(d.x1!==d.x2||d.y1!==d.y2))return{...n,x1:d.x1,y1:d.y1,x2:d.x2,y2:d.y2,contentDirection:s,...void 0!==o?{amount:o}:{},...void 0!==l?{pixels:l}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250};let p=e4({direction:s,amount:o,pixels:l,referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight});return{...n,x1:p.x1,y1:p.y1,x2:p.x2,y2:p.y2,contentDirection:s,...void 0!==o?{amount:o}:{},...void 0!==p.pixels?{pixels:p.pixels}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250}}(t,a,i,o);s1(t,a,i,c,u,l,d),r.recordAction(t,{command:a,positionals:n,flags:s,result:o??{}})}({session:c,sessionStore:p,command:m,resolvedPositionals:h,recordedPositionals:w,recordedFlags:y,data:I,actionStartedAt:v,actionFinishedAt:Date.now(),flags:u.flags??{}}),ef(m)&&e6(c,m),{ok:!0,data:I??{}}}async function lt(e,t,r){let a=eR(await eO({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);ev(e,a);let i=await oF({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}async function lr(e,t=5e3){await Promise.all(e.map(async e=>{let r;await new Promise(a=>{r=setTimeout(()=>{!function(e){e.destroyConnections?.();let t="closeAllConnections"in e?e.closeAllConnections:void 0;if("function"==typeof t)return t.call(e);let r="closeIdleConnections"in e?e.closeIdleConnections:void 0;"function"==typeof r&&r.call(e)}(e),a()},t);try{e.close(()=>a())}catch{a()}}),r&&clearTimeout(r)}))}function la(e){i.existsSync(e)&&i.unlinkSync(e)}function li(e){if(!i.existsSync(e))return null;try{let t=JSON.parse(i.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function ln(e){let t=li(e);if(!t||t.pid===process.pid)try{i.existsSync(e)&&i.unlinkSync(e)}catch{}}function ls(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:lo,infoPath:ll,lockPath:ld,logPath:lu,sessionsDir:lc}=te(process.env.AGENT_DEVICE_STATE_DIR),lf=tr(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var lp=lc;if(i.existsSync(lp))for(let e of i.readdirSync(lp,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=s.join(lp,e.name,tW);if(i.existsSync(t))try{let e=tJ(i.readFileSync(t,"utf8"));if(e&&function(e){let t,r=x(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=_(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{tX(t)}}let lm=new tK(lc),lh=new r4({maxActiveSimulatorLeases:ls(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:ls(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:ls(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:ls(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),lg=t_(),lw=a.randomBytes(24).toString("hex"),ly=x(process.pid)??void 0,lv=ts(),lS=function(e){let{logPath:t,token:r,androidAdbProvider:a,deviceInventoryProvider:i,trackDownloadableArtifact:n}=e,{sessionStore:o,leaseRegistry:l}=e;async function d(e){let u=!!(e.meta?.debug||e.flags?.verbose);return await v({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:u,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:z(new W("UNAUTHORIZED","Invalid token"))};try{return await es(i,async()=>{let r=function(e){let t=tt(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=e9(r);if(r&&!a)throw new W("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new W("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);A({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let i=r.command,u=ox(r);o1.has(i)||r.meta?.sessionIsolation!=="tenant"||l.assertLeaseAdmission({tenantId:u.tenantId,runId:u.runId,leaseId:u.leaseId,backend:u.leaseBackend});let c=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,o),f=o2.has(i)?null:await o4(r,c,o),p=async()=>{o3(r);let e=o.get(c);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=eF(e.device.id);if(!t.runnerSessionId){r?.alive&&(t.runnerSessionId=r.sessionId);return}if(!r?.alive){t.invalidatedReason??="iOS runner session exited during recording";return}r.sessionId!==t.runnerSessionId&&(t.invalidatedReason??="iOS runner session restarted during recording")}(e),o.set(c,e));let u=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?ok(t,a):function(e,t,r){var a,i;let n=[],s=e8(t);if(void 0!==e.platform&&s&&(a=e8(e.platform),i=s,a&&i&&a!==i&&("apple"===a?!e1(i):"apple"!==i||!e1(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of oR){let r=e[t];"string"==typeof r&&r.trim().length>0&&n.push({key:t,value:r})}return n}(a,e.meta?.lockPlatform,e.command);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of oR)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new W("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(oP).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),f=e=>(function(e,t,r){let a=I();if(!t.ok){A({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=S({force:!0})??void 0;return{ok:!1,error:z(new W(B(t.error.code),t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:a.diagnosticId,logPath:e})}}return A({level:"info",phase:"request_success"}),S(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let o=(a=e,i=t,n=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||n.some(e=>e?.field==="path")||"string"!=typeof i.path||n.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:s.basename(a.meta?.clientArtifactPaths?.path??i.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===o.length?t:{...t,artifacts:o.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(u,e,n);if(e?.recording?.invalidatedReason&&"record"!==i&&"close"!==i)return f({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||u.meta?.lockPolicy||o0.has(i)||function(e,t){let r=ok(e,t);if(0!==r.length){var a;let t,i,n;throw new W("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(oP).join(", ")}. Use a different --session name or close this session first.`)}}(e,u.flags);let p=await o9({req:u,existingSession:e,androidAdbProvider:a});return await D(p.provider,{serial:p.serial??""},async()=>{let e=await o7({req:u,sessionName:c,logPath:t,sessionStore:o,leaseRegistry:l,invoke:d,androidAdbExecutor:p.executor,contextFromFlags:(e,r,a)=>({...o5(t,e,r,a),surface:o.get(c)?.surface})});if(e)return f(e);let r=o.get(c);if(!r)return f({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let a=await le({req:u,session:r,sessionName:c,logPath:t,sessionStore:o});return f(a)})};return f?(o3(r),await ey(o8,f,p)):(o3(r),await p())})}catch(r){A({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=I(),t=S({force:!0})??void 0;return{ok:!1,error:z(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return d}({logPath:lu,token:lw,sessionStore:lm,leaseRegistry:lh,trackDownloadableArtifact:function(e){let t=a.randomUUID(),r=setTimeout(()=>{rx(t)},9e5);return r.unref(),rM.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});async function lI(e){await v({command:"daemon",session:"daemon",logPath:lu,debug:!0},async()=>{A({level:"error",phase:"daemon_fatal",data:{error:e instanceof Error?e.message:String(e)}}),S({force:!0})})}async function lA(){let e=lm.toArray();await Promise.all(e.map(lb))}async function lb(e){let t=iA(e,e.name).catch(t=>{process.stderr.write(`Daemon session teardown error (${e.name}): ${t instanceof Error?t.message:String(t)}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
`),n=r.indexOf("\n")}})})).destroyConnections=()=>{for(let e of t)e.destroy();t.clear()},a);r.push(i),e=await new Promise((e,t)=>{i.once("error",t),i.listen(0,"127.0.0.1",()=>{i.off("error",t);let r=i.address();"object"==typeof r&&r?.port?e(r.port):t(new W("COMMAND_FAILED","Failed to bind socket server"))})})}if("socket"!==lf){let e=await rQ({handleRequest:lS,token:lw});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let a=e.address();"object"==typeof a&&a?.port?t(a.port):r(new W("COMMAND_FAILED","Failed to bind HTTP server"))})})}return{servers:r,socketPort:e,httpPort:t}}!async function(){if(!function(e,t,r){i.existsSync(e)||i.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),n=()=>{try{return i.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(n())return!0;let s=li(t);if(s?.pid&&s.pid!==process.pid&&M(s.pid,s.processStartTime))return!1;try{i.unlinkSync(t)}catch{}return n()}(lo,ld,{pid:process.pid,version:lg,startedAt:Date.now(),processStartTime:ly})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let e=[];try{var t,r,a;let n,s=await l_();e=s.servers,t=s.socketPort,r=s.httpPort,a={socketPort:t,httpPort:r,token:lw,version:lg,codeSignature:lv,processStartTime:ly},i.existsSync(lo)||i.mkdirSync(lo,{recursive:!0}),i.writeFileSync(lu,""),n=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",i.writeFileSync(ll,JSON.stringify({port:a.socketPort,httpPort:a.httpPort,transport:n,token:a.token,pid:process.pid,version:a.version,codeSignature:a.codeSignature,processStartTime:a.processStartTime,stateDir:lo},null,2),{mode:384}),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${t}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
`),e))try{r.close(()=>{})}catch{}la(ll),ln(ld),process.exit(1);return}let n=!1,s=async(t={})=>{n||(n=!0,t.cause&&await lI(t.cause),await lr(e),await lA(),await eA(),la(ll),ln(ld),process.exit(t.exitCode??0))};process.on("SIGINT",()=>{s()}),process.on("SIGTERM",()=>{s()}),process.on("SIGHUP",()=>{s()}),process.on("uncaughtException",e=>{let t=e instanceof W?e:K(e);process.stderr.write(`Daemon error: ${t.message}
|
|
45
|
-
`),s({exitCode:1,cause:e})}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof W?t:K(t);process.stderr.write(`Daemon error: ${r.message}
|
|
46
|
-
|
|
55
|
+
`.trim();async function fh(e,t={}){let r,n=t.pollMs??150,a=t.attempts??12,i=0;for(let t=0;t<a;t+=1){let t=0;try{t=l.statSync(e).size}catch{t=0}if(t>0&&t===r){if((i+=1)>=2)return}else i=0;r=t,await ex(n)}}async function fw(e){try{let t=await fg(),r=await C(t,[e],{allowFailure:!0,timeoutMs:1e4,env:fo()});if(0===r.exitCode)return!0;if(fv(r.stderr,r.stdout))return fI(e);return!1}catch(r){var t;if((t=r)instanceof P&&("TOOL_MISSING"===t.code||fv(String(t.details?.stderr??""),String(t.details?.stdout??""))))return fI(e);throw r}}async function fg(){t??=fl({source:fm,cacheName:"video-validator",timeoutMs:3e4});try{return await t}catch(e){throw t=void 0,e}}async function fy(e,t={}){let r=t.pollMs??150,n=t.attempts??12;for(let t=0;t<n;t+=1){if(await fw(e))return;await ex(r)}}function fv(e,t){let r=`${e}
|
|
56
|
+
${t}`;return/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swiftc?["']|xcrun: error: unable to find utility ["']swiftc?["'])\b/i.test(r)}function fI(e){try{let t=l.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=l.openSync(e,"r");try{let e=l.fstatSync(t).size,r=0,n=[];for(;r+8<=e&&n.length<16;){let e=Buffer.alloc(8);if(8>l.readSync(t,e,0,8,r))break;let a=e.readUInt32BE(0),i=e.toString("latin1",4,8);if(n.push(i),1===a){let e=Buffer.alloc(8);if(8>l.readSync(t,e,0,8,r+8))break;a=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(a)||a<=0)break;r+=a}return n}finally{l.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function fA(e){let t=f.parse(e);return f.join(t.dir,`${t.name}.gesture-telemetry.json`)}function fS(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function fb(e){let t=f.dirname(y(import.meta.url)),r=[y(new URL(`./${e}`,import.meta.url)),f.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),f.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),f.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(l.existsSync(e))return e;throw new P("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}async function f_(e){var t;let r,n,{videoPath:a,scriptPath:i,scriptArgs:o,commandDescription:s}=e;await fh(a),await fy(a);let u=(t=a,r=f.parse(t),n=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,f.join(r.dir,`.${r.name}.agent-device-${n}${r.ext||".mp4"}`));try{let e=await fs({sourcePath:i});await C(e,["--input",a,"--output",u,...o],{timeoutMs:12e4,env:fo()}),await fy(u),l.renameSync(u,a)}catch(t){let e=t instanceof P?t:new P("COMMAND_FAILED",String(t),void 0,t instanceof Error?t:void 0);throw new P("COMMAND_FAILED",s,{videoPath:a,script:i,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{l.rmSync(u,{force:!0})}}async function fN(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await f_({videoPath:t,scriptPath:n??=fb("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function fx(e){let{videoPath:t,telemetryPath:n,targetLabel:a="recording"}=e;await f_({videoPath:t,scriptPath:r??=fb("recording-overlay.swift"),scriptArgs:["--events",n],commandDescription:`Failed to add touch overlays to the ${a}`})}async function fM(e){let{videoPath:t,quality:r,targetLabel:n="recording"}=e;await f_({videoPath:t,scriptPath:a??=fb("recording-resize.swift"),scriptArgs:["--quality",String(r)],commandDescription:`Failed to resize the ${n}`})}function fD(e){return e instanceof Error?e.message:String(e)}function fk(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function fP(e){let{recording:t,deps:r,trimStartMs:n,targetLabel:a}=e,i=function(e){var t,r,n;let a,i,{recording:o,trimStartMs:s}=e,u=(a=fA((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:s}).videoPath),i={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(n=t.trimStartMs??0)>0?fS(r.flatMap(e=>{let t=e.tMs-n,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):fS(r))},l.writeFileSync(a,JSON.stringify(i,null,2)),a);return o.telemetryPath=u,u}({recording:t,trimStartMs:n});if(!t.showTouches)return void eb({level:"debug",phase:"record_stop_overlay_skipped",data:{reason:"hide_touches"}});if(0===t.gestureEvents.length)return void eb({level:"debug",phase:"record_stop_overlay_skipped",data:{reason:"no_gesture_events"}});let o=function(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}();if(o){t.overlayWarning??=o;return}try{await eS("record_stop_overlay_export",()=>r.overlayRecordingTouches({videoPath:t.outPath,telemetryPath:i,targetLabel:a}),{targetLabel:a,gestureEventCount:t.gestureEvents.length})}catch(e){t.overlayWarning??=`failed to overlay recording touches: ${fD(e)}`}}async function fO(e,t,r){return await X(W(e),t,r)}async function fE(e,t){let r=await fO(e,["shell","ps","-o","pid=","-p",t],{allowFailure:!0});return 0===r.exitCode&&r.stdout.split(/\s+/).map(e=>e.trim()).includes(t)}async function fC(e,t){for(let r=0;r<40;r+=1){if(!await fE(e,t))return!0;await ex(250)}return!await fE(e,t)}async function fL(e,t){let r,n=0;for(let a=0;a<20;a+=1){let a=await fO(e,["shell","stat","-c","%s",t],{allowFailure:!0}),i=0===a.exitCode?a.stdout.trim():"";if(i.length>0&&i===r){if((n+=1)>=4)return}else n=0;r=i,await ex(250)}}async function fR(e,t,r){for(let n=0;n<8;n+=1){let a=await fO(e,["shell","stat","-c","%s",t],{allowFailure:!0}),i=0===a.exitCode?Number(a.stdout.trim()):NaN;if(Number.isFinite(i)&&i>0)return!0;if(!await fE(e,r))break;if(n+1>=2)return!0;await ex(250)}return!1}async function fT(e){let t,{deps:r,deviceId:n,remotePath:a,outPath:i}=e;for(let e=0;e<2;e+=1){try{l.rmSync(i,{force:!0})}catch{}let o=W(n),s=await e1(a,i,{allowFailure:!0,device:o});if(0!==s.exitCode)t=fk(s,"adb pull");else{await r.waitForStableFile(i,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(i);if(eb({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:n,remotePath:a,outPath:i,attempt:e+1,fileSize:(()=>{try{return l.statSync(i).size}catch{return 0}})(),playable:t}}),t)return;eb({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:n,remotePath:a,outPath:i,attempt:e+1}})}e<1&&await ex(750)}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function f$(e){let{deviceId:t,quality:r}=e;if(void 0===r||r>=10)return;let n=await fO(t,["shell","wm","size"],{allowFailure:!0}),a=n.stdout.match(/Override size:\s*(\d+)x(\d+)/)??n.stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(0!==n.exitCode||!a)throw Error(`failed to resolve Android screen size for recording quality: ${fk(n,"adb shell wm size")}`);return{width:fF(Number(a[1]),r),height:fF(Number(a[2]),r)}}function fF(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function fU(e,t){await fO(e,["shell","rm","-f",t],{allowFailure:!0})}async function fG(e,t){let r=await fO(e,["shell","kill","-9",t],{allowFailure:!0});return eb({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:e,remotePid:t,exitCode:r.exitCode,stdout:r.stdout.trim(),stderr:r.stderr.trim()}}),!(0!==r.exitCode&&await fE(e,t))&&await fC(e,t)}async function fV(e){var t;let r,n,{device:a,recordingBase:i}=e,o="failed to start recording: Android screenrecord did not begin producing frames";try{r=await f$({deviceId:a.id,quality:i.quality})}catch(e){return dM("COMMAND_FAILED",e instanceof Error?e.message:String(e))}for(let e of(t=Date.now(),n=`agent-device-recording-${t}.mp4`,[`/sdcard/${n}`,`/data/local/tmp/${n}`])){let t=await fO(a.id,["shell",function(e,t){let r=["screenrecord"];return t&&r.push("--size",`${t.width}x${t.height}`),r.push(e),`${r.join(" ")} >/dev/null 2>&1 & echo $!`}(e,r)],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${fk(t,"adb shell screenrecord")}`;continue}let n=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!n){o="failed to start recording: adb did not return a valid Android screenrecord pid",await fU(a.id,e);continue}if(eb({level:"debug",phase:"record_start_android_started",data:{deviceId:a.id,remotePath:e,remotePid:n}}),await fR(a.id,e,n))return{platform:"android",remotePath:e,remotePid:n,...i,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await fG(a.id,n),await fU(a.id,e)}return dM("COMMAND_FAILED",o)}async function fj(e){let t,r,{deps:n,device:a,recording:i}=e;eb({level:"debug",phase:"record_stop_android_enter",data:{deviceId:a.id,remotePath:i.remotePath,remotePid:i.remotePid}});let o=await fO(a.id,["shell","kill","-2",i.remotePid],{allowFailure:!0});if(eb({level:"debug",phase:"record_stop_android_signal",data:{deviceId:a.id,remotePath:i.remotePath,remotePid:i.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await fE(a.id,i.remotePid)&&!await fG(a.id,i.remotePid)&&(t=`failed to stop recording: ${fk(o,"adb shell kill")}`):await fC(a.id,i.remotePid)||await fG(a.id,i.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${i.remotePid} did not exit`),!t){await fL(a.id,i.remotePath);let e=await fT({deps:n,deviceId:a.id,remotePath:i.remotePath,outPath:i.outPath});if(e)return await s(),dM("COMMAND_FAILED",e);await fP({recording:i,deps:n,targetLabel:"Android recording"})}if(await s(),t)return dM("COMMAND_FAILED",t);if(r)return dM("COMMAND_FAILED",r);return null;async function s(){let e=await fO(a.id,["shell","rm","-f",i.remotePath],{allowFailure:!0});eb({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:a.id,remotePath:i.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${fk(e,"adb shell rm")}`)}}function fB(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function fq(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath,requestId:e.meta?.requestId}}async function fH(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i}=e,o=fB(r);try{await i.runIosRunnerCommand(n,{command:"recordStop",appBundleId:o},fq(t,a,r))}catch(e){eb({level:"warn",phase:"record_stop_runner_failed",data:{platform:n.platform,kind:n.kind,deviceId:n.id,session:r.name,error:fD(e)}})}}async function fW(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i}=e,o=fB(r);if(o)try{await i.runIosRunnerCommand(n,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},fq(t,a,r))}catch(e){eb({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:n.id,session:r.name,appBundleId:o,error:fD(e)}})}}async function fz(e){let t,r,{req:n,activeSession:a,sessionStore:i,device:o,logPath:s,deps:l,fpsFlag:u,recordingBase:d,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=fq(n,s,a),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:u,quality:d.quality,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(n){var w,g;if(!fD(n).toLowerCase().includes("recording already in progress"))return dM("COMMAND_FAILED",`failed to start recording: ${fD(n)}`);eb({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:a.name,error:fD(n)}});let e=(w=o.id,g=a.name,i.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return dM("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return dM("COMMAND_FAILED",`failed to start recording: ${fD(e)}`)}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...d}}async function fK(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await i.runIosRunnerCommand(n,{command:"recordStart",outPath:s.outPath,fps:o,quality:s.quality,appBundleId:l},fq(t,a,r))}catch(e){return dM("COMMAND_FAILED",`failed to start recording: ${fD(e)}`)}return{platform:"macos-runner",...s}}async function fJ(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i,recording:o}=e;await fH({req:t,activeSession:r,device:n,logPath:a,deps:i});let s={stdout:"",stderr:"",exitCode:1};for(let e of nl)if(0===(s=await i.runCmd("xcrun",["devicectl","device","copy","from","--device",n.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==s.exitCode){let e=s.stderr.trim()||s.stdout.trim()||`devicectl exited with code ${s.exitCode}`;return dM("COMMAND_FAILED",`failed to copy recording from device: ${e}`)}let l="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);return l>0&&await i.trimRecordingStart({videoPath:o.outPath,trimStartMs:l}),await fP({recording:o,deps:i,trimStartMs:l,targetLabel:"iOS recording"}),null}async function fX(e){let{req:t,activeSession:r,device:n,logPath:a,deps:i,recording:o}=e;return await fH({req:t,activeSession:r,device:n,logPath:a,deps:i}),await fP({recording:o,deps:i,targetLabel:"macOS recording"}),null}async function fZ(e){"ios"!==e.platform||0!==e.gestureEvents.length&&await ex(350)}async function fY(e){for(let t=0;t<2;t+=1){try{if(l.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await ex(250)}return Date.now()}async function fQ(e){let t,r,{req:n,activeSession:a,device:i,logPath:o,deps:s,recordingBase:l,resolvedOut:u}=e;l.showTouches&&await fW({req:n,activeSession:a,device:i,logPath:o,deps:s});let{child:d,wait:c}=s.startIosSimulatorRecording({device:i,outPath:u}),p=await fY(u);if(l.showTouches)try{let e=Date.now(),l=await s.runIosRunnerCommand(i,{command:"uptime",appBundleId:fB(a)},fq(n,o,a)),u=Date.now();t=Math.round((e+u)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:d,wait:c,...l,startedAt:p,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function f0(e){let t,{req:r,sessionName:n,sessionStore:a,activeSession:i,device:o,logPath:s,deps:u}=e;if(i.recording)return dM("INVALID_ARGS","recording already in progress");let d=r.flags?.fps,c=r.flags?.quality;if(void 0!==d&&(!Number.isInteger(d)||d<1||d>120))return dM("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==c&&(!Number.isInteger(c)||c<5||c>10))return dM("INVALID_ARGS","quality must be an integer between 5 and 10");if(!dK("record",o))return dM("UNSUPPORTED_OPERATION","record is not supported on this device");let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,m=aN.expandHome(p,r.meta?.cwd),h={outPath:m,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),quality:r.flags?.quality,showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(l.mkdirSync(f.dirname(m),{recursive:!0}),l.rmSync(m,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=fB(i);if(!e)return dM("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await fz({req:r,activeSession:i,sessionStore:a,device:o,logPath:s,deps:u,fpsFlag:d,recordingBase:h,appBundleId:e})}else if("macos"===o.platform){let e=fB(i);if(!e)return dM("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await fK({req:r,activeSession:i,device:o,logPath:s,deps:u,fpsFlag:d,recordingBase:h,appBundleId:e})}else t="ios"===o.platform?await fQ({req:r,activeSession:i,device:o,logPath:s,deps:u,recordingBase:h,resolvedOut:m}):await fV({device:o,recordingBase:h});return"ok"in t?t:(i.recording=t,a.set(n,i),a.recordAction(i,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??p,showTouches:t.showTouches}})}async function f1(e){let{deps:t,device:r,recording:n}=e;if("android"===n.platform)return await fj({deps:t,device:r,recording:n});await eS("record_stop_tail_settle",()=>t.waitForRecordingTail(n),{platform:n.platform,gestureEventCount:n.gestureEvents.length});let a=await eS("record_stop_ios_simulator_process",()=>f2({deps:t,recording:n}),{outPath:n.outPath});if(!a)return dM("COMMAND_FAILED","failed to stop recording: simctl recordVideo did not exit after 5000ms and forced cleanup");if(0!==a.exitCode)return dM("COMMAND_FAILED",`failed to stop recording: ${fk(a,"simctl recordVideo")}`);if(await eS("record_stop_video_stable",()=>t.waitForStableFile(n.outPath,{pollMs:150,attempts:12}),{outPath:n.outPath}),!await eS("record_stop_video_playable_check",()=>t.isPlayableVideo(n.outPath),{outPath:n.outPath}))return dM("COMMAND_FAILED",`failed to stop recording: ${n.outPath} was not finalized into a playable video`);if(void 0!==n.quality&&n.quality<10){let e=n.quality;try{await eS("record_stop_resize",()=>t.resizeRecording({videoPath:n.outPath,quality:e,targetLabel:"iOS recording"}),{outPath:n.outPath,quality:e})}catch(e){n.overlayWarning=`failed to resize recording: ${fD(e)}`}}return await eS("record_stop_finalize_overlay",()=>fP({recording:n,deps:t,targetLabel:"iOS recording"}),{outPath:n.outPath,showTouches:n.showTouches,gestureEventCount:n.gestureEvents.length}),null}async function f2(e){let{deps:t,recording:r}=e;r.child.kill("SIGINT");let n=await f3(r.wait,5e3);return n||(await f4(t,r.outPath,"SIGINT"),(n=await f3(r.wait,2e3))||(r.child.kill("SIGTERM"),await f4(t,r.outPath,"SIGTERM"),n=await f3(r.wait,2e3)))?n:(r.child.kill("SIGKILL"),await f4(t,r.outPath,"SIGKILL"),await f3(r.wait,2e3))}async function f3(e,t){return await Promise.race([e,ex(t).then(()=>null)])}async function f4(e,t,r){let n,a=`simctl.*recordVideo.*${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}`;try{n=await e.runCmd("pgrep",["-f",a],{allowFailure:!0})}catch(e){eb({level:"warn",phase:"record_stop_ios_simulator_pgrep_failed",data:{outPath:t,signal:r,error:fD(e)}});return}let i=n.stdout.split(/\s+/).map(e=>Number(e)).filter(e=>Number.isInteger(e)&&e>0&&e!==process.pid),o=0;for(let e of i)try{process.kill(e,r),o+=1}catch{}eb({level:o>0?"warn":"debug",phase:"record_stop_ios_simulator_signal_recorders",data:{outPath:t,signal:r,matchedPidCount:i.length,signaled:o,pgrepExitCode:n.exitCode}})}async function f5(e){var t;let r,{req:n,activeSession:a,device:i,logPath:o,deps:s}=e;if(!a.recording)return dM("INVALID_ARGS","no active recording");let l=a.recording,u=l.invalidatedReason;a.recording=void 0;let d="ios-device-runner"===l.platform?await fJ({req:n,activeSession:a,device:i,logPath:o,deps:s,recording:l}):"macos-runner"===l.platform?await fX({req:n,activeSession:a,device:i,logPath:o,deps:s,recording:l}):await f1({deps:s,device:i,recording:l});return d||(u?dM("COMMAND_FAILED",u):(r=[{field:"outPath",path:(t=l).outPath,localPath:t.clientOutPath,fileName:f.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return fA(e.clientOutPath)}(t),fileName:f.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function f8(e){let{req:t,sessionName:r,sessionStore:n,logPath:a}=e,i={runCmd:async(e,t,r)=>"xcrun"===e?await ry(t,r):await C(e,t,r),startIosSimulatorRecording:e=>dT.resolve(void 0).startIosSimulatorRecording(e),runIosRunnerCommand:n6,waitForRecordingTail:fZ,waitForStableFile:fh,isPlayableVideo:fw,trimRecordingStart:fN,resizeRecording:fM,overlayRecordingTouches:fx},o=n.get(r),s=o?.device??await os(t.flags??{});o||await o$(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},u=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(u))return dM("INVALID_ARGS","record requires start|stop");if("start"===u)return f0({req:t,sessionName:r,sessionStore:n,activeSession:l,device:s,logPath:a,deps:i});let d=await f5({req:t,activeSession:l,device:s,logPath:a,deps:i});return d.ok&&n.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:d.data?.outPath,showTouches:d.data?.showTouches}}),d}async function f6(e){let{req:t,sessionName:r,sessionStore:n,logPath:a}=e,i=t.command;if("record"===i)return f8({req:t,sessionName:r,sessionStore:n,logPath:a});if("trace"===i){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return dM("INVALID_ARGS","trace requires start|stop");let a=n.get(r);if(!a)return dM("SESSION_NOT_FOUND","No active session");if("start"===e){if(a.trace)return dM("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??n.defaultTracePath(a),r=aN.expandHome(e);return l.mkdirSync(f.dirname(r),{recursive:!0}),l.appendFileSync(r,""),a.trace={outPath:r,startedAt:Date.now()},n.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!a.trace)return dM("INVALID_ARGS","no active trace");let o=a.trace.outPath;if(t.positionals?.[1]){let e=aN.expandHome(t.positionals[1]);l.mkdirSync(f.dirname(e),{recursive:!0}),l.existsSync(o)?l.renameSync(o,e):l.appendFileSync(e,""),o=e}return a.trace=void 0,n.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}let f9=new Map;async function f7(e){let t=await b.mkdtemp(f.join(c.tmpdir(),"agent-device-materialized-"));try{let r=await mr(e.installablePath,f.join(t,"installable")),n=e.archivePath?await mr(e.archivePath,f.join(t,"archive")):void 0,a=o.randomUUID(),i=e.ttlMs??9e5,s=Date.now()+i,l=setTimeout(()=>{me(a)},i);return f9.set(a,{rootPath:t,installablePath:r,archivePath:n,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:a,installablePath:r,...n?{archivePath:n}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await b.rm(t,{recursive:!0,force:!0}),e}}async function me(e,t){let r=f9.get(e);if(!r)throw new P("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new P("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),f9.delete(e),await b.rm(r.rootPath,{recursive:!0,force:!0})}async function mt(e){let t=Array.from(f9.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await me(e)}))}async function mr(e,t){let r=await b.stat(e);await b.mkdir(t,{recursive:!0});let n=f.join(t,f.basename(e));return r.isDirectory()?await b.cp(e,n,{recursive:!0}):await b.copyFile(e,n),n}async function mn(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 P("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await o$(e.session.device),e.session.device}if(!r)throw new P("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let n=await os(e.flags??{});return await o$(n),n}async function ma(e){let{prepared:t,retention:r,req:n,session:a,sessionName:i}=e;if(r.enabled)return await f7({archivePath:t.archivePath,installablePath:t.installablePath,tenantId:n.meta?.tenantId,sessionName:a?i:void 0,ttlMs:r.ttlMs})}function mi(e){return e?{...e.archivePath?{archivePath:e.archivePath}:{},installablePath:e.installablePath,materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}}async function mo(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 P("INVALID_ARGS","install_from_source requires a source payload");switch(t.kind){case"url":if(!t.url||0===t.url.trim().length)throw new P("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 P("INVALID_ARGS","install_from_source path source requires a non-empty path");return t;case"github-actions-artifact":throw new P("UNSUPPORTED_OPERATION","install_from_source github-actions-artifact sources require a compatible remote daemon");default:throw new P("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:im(i,t.meta?.tenantId)},cleanup:()=>{ih(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 P("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),l=await mn({session:a,flags:t.flags});if(!dK("install",l))return dM("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let u=rr(t.meta?.requestId),d=async(e,i)=>{let l;try{var u;l=await ma({prepared:e,retention:s,req:t,session:a,sessionName:r});let o=await i(l),d=eq(o,(u=o,`Installed: ${eJ(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:d}),{ok:!0,data:d}}catch(e){throw l&&await me(l.materializationId,t.meta?.tenantId).catch(()=>{}),e}finally{await e.cleanup(),o.cleanup()}};if("ios"===l.platform){let{installIosInstallablePath:e}=await Promise.resolve(t0),{prepareIosInstallArtifact:t}=await Promise.resolve(t1),r=await t(o.source,{signal:u});return await d(r,async t=>{if(await e(l,r.installablePath),!r.bundleId)throw new P("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");return{...mi(t),bundleId:r.bundleId,...r.appName?{appName:r.appName}:{},launchTarget:r.bundleId}})}let{prepareAndroidInstallArtifact:c}=await import("../1769.js"),{installAndroidInstallablePathAndResolvePackageName:p}=await import("../1769.js"),f=await c(o.source,{signal:u});return await d(f,async e=>{let t=await p(l,f.installablePath,f.packageName);if(!t)throw new P("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:r}=await import("../1769.js"),n=r(t);return{...mi(e),packageName:t,...n?{appName:n}:{},launchTarget:t}})}catch(e){return{ok:!1,error:k(e)}}}async function ms(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new P("INVALID_ARGS","release_materialized_paths requires a materializationId");return await me(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:k(e)}}}let ml="shared_prefs/ReactNativeDevPrefs.xml",mu="debug_http_host",md="dev_server_https",mc="RCT_jsLocation",mp="RCT_packager_scheme",mf="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",mm='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function mh(e){return void 0!==eh(e)}async function mw(e){let{device:t,appId:r,runtime:n}=e;if(!r)return;let a=eh(n);if(a){if("android"===t.platform)return void await my(t,r,a);"ios"===t.platform&&"simulator"===t.kind&&await mS(t,r,a)}}async function mg(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await mv(t,r);"ios"===t.platform&&"simulator"===t.kind&&await mb(t,r)}}async function my(e,t,r){var n,a,i,o,s,l;let u,d;mM(t);let c=(n=await mI(e,t),a=mu,i=`${r.host}:${r.port}`,u=` <string name="${mD(a)}">${mD(i)}</string>`,mN(mx(n,a),u));o=c,s=md,l="https"===r.scheme,d=` <boolean name="${mD(s)}" value="${l?"true":"false"}" />`,c=mN(mx(o,s),d),await mA(e,t,c)}async function mv(e,t){mM(t);let r=await mI(e,t),n=mx(r,mu),a=mx(n,md);a!==r&&await mA(e,t,a)}async function mI(e,t){let r=await X(e,["shell","run-as",t,"cat",ml],{allowFailure:!0});return 0!==r.exitCode?mm:m_(r.stdout)}async function mA(e,t,r){let n=["shell","run-as",t,"id"],a=await X(e,n,{allowFailure:!0});if(0!==a.exitCode){let e=mk(a.stdout,a.stderr);throw new P("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:n,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:e?mf:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await X(e,["shell","run-as",t,"mkdir","-p","shared_prefs"]),await X(e,["shell","run-as",t,"tee",ml],{stdin:r.trimEnd()})}catch(n){let e=D(n);if("TOOL_MISSING"===e.code)throw e;let r=mk("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new P("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?mf:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function mS(e,t,r){await ry(rS(e,["spawn",e.id,"defaults","write",t,mc,"-string",`${r.host}:${r.port}`])),await ry(rS(e,["spawn",e.id,"defaults","write",t,mp,"-string",r.scheme]))}async function mb(e,t){await ry(rS(e,["spawn",e.id,"defaults","delete",t,mc]),{allowFailure:!0}),await ry(rS(e,["spawn",e.id,"defaults","delete",t,mp]),{allowFailure:!0})}function m_(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
57
|
+
`:mm}function mN(e,t){return m_(e).replace("</map>",`${t}
|
|
58
|
+
</map>`)}function mx(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return m_(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function mM(e){if("binary"!==es(e))return;let t=J(e);throw new P("INVALID_ARGS",t,{package:e,hint:t})}function mD(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function mk(e,t){let r=`${e}
|
|
59
|
+
${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}let mP=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function mO(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function mE(e,t){if(void 0!==e){if("string"!=typeof e)throw new P("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return ef(e)}}function mC(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new P("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function mL(e){if("ios"===e||"android"===e)return e}async function mR(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:n,session:a}=e;!t||!a?.appBundleId||!mh(r)||mh(n)||await mg({device:a.device,appId:a.appBundleId})}async function mT(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 dM("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){mh(l)&&s?.appBundleId&&await mg({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=mL(n.flags?.platform??l?.platform??s?.device.platform);if(!u)return dM("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 dM("INVALID_ARGS",`runtime set targets ${u}, but session "${a}" is already bound to ${s.device.platform}.`);let d={platform:(t=n.flags,r={platform:u,metroHost:ef(t?.metroHost),metroPort:mC(t?.metroPort),bundleUrl:ef(t?.bundleUrl),launchUrl:ef(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===mO(d)?dM("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(i.setRuntimeHints(a,d),{ok:!0,data:{session:a,configured:!0,runtime:d}})}let m$="open-command-roundtrip",mF="Not implemented for this platform in this release.",mU=new Set(["app","desktop","frontmost-app"]);async function mG(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await ll();return{appBundleId:t.bundleId,appName:t.appName}}function mV(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}function mj(e){return Math.round(10*e)/10}function mB(e){return Math.round(10*e)/10}let mq="adb-shell-dumpsys-gfxinfo-framestats";function mH(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 mW(e){return 0===e.length?{}:{firstFrameNs:Math.min(...e.map(e=>e.intendedVsyncNs)),lastFrameNs:Math.max(...e.map(e=>e.frameCompletedNs))}}function mz(e,t){if(void 0!==e&&void 0!==t)return Math.max(0,Math.round((t-e)/1e6))}function mK(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=e.match(RegExp(`^\\s*${r}:\\s*([0-9][0-9,]*)`,"im"));if(n)return mV(n[1])??void 0}async function mJ(e,t,r={}){var n,a,i,o,s,l,u,d;let c=e4(e,r.adb);try{let u,d,p,f,m,h,w,g,y,v,I,A=(n=(await c(["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 P("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),p=function(e){let t=e.split(/\nProfile data in ms:\n/i)[0]??"",r=mK(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=mV(n[1])??void 0,i=Number(n[2]);if(void 0===a||!Number.isFinite(i)||r<0)return;let o=mK(t,"Uptime"),s=mK(t,"Stats since");return{droppedFramePercent:mj(i),droppedFrameCount:a,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:o,statsSinceNs:s}),uptimeMs:o,statsSinceNs:s}}(n),f=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=mH(e,t,"Flags"),n=mH(e,t,"IntendedVsync"),a=mH(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),m=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 P("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 P("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."})}(f,p,t),h=Date.parse(a),w=function(e){let{frames:t,measuredAtMs:r,summary:n}=e,a=mW(t),i=n?.statsSinceNs,o=i??a.firstFrameNs,s=mz(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:f,measuredAtMs:h,summary:p}),g=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:f,frameDeadlineNs:m,summaryDroppedFrameCount:p?.droppedFrameCount}),y=p?.sampleWindowMs??w.sampleWindowMs??function(e){if(0===e.length)return;let t=mW(e);return mz(t.firstFrameNs,t.lastFrameNs)}(f),i=p,o=f,s=g,u=i?.totalFrameCount??o.length,d=i?.droppedFrameCount??s.length,v={totalFrameCount:u,droppedFrameCount:d,droppedFramePercent:i?.droppedFramePercent??(u>0?mj(d/u*100):0)},I=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:mB(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:g,timing:w,measuredAtMs:h,summary:p}),{...v,sampleWindowMs:y,...(l=m,{frameDeadlineMs:void 0===l?void 0:mB(l/1e6),refreshRateHz:void 0===l?void 0:mB(1e9/l)}),windowStartedAt:w.windowStartedAt,windowEndedAt:w.windowEndedAt,timestampSource:w.timestampSource,measuredAt:a,method:mq,source:p?"android-gfxinfo-summary":"framestats-rows",worstWindows:I&&I.length>0?I:void 0});return await mX(e,t,r),A}catch(e){throw u=t,(d=e)instanceof P?new P(d.code,d.message,{...d.details??{},metric:"fps",package:u},d):new P("COMMAND_FAILED",`Failed to sample Android fps for ${u}`,{metric:"fps",package:u},d)}}async function mX(e,t,r={}){let n=e4(e,r.adb);try{await n(["shell","dumpsys","gfxinfo",t,"reset"],{allowFailure:!0,timeoutMs:3e3})}catch{}}let mZ="adb-shell-dumpsys-cpuinfo",mY="adb-shell-dumpsys-meminfo";async function mQ(e,t,r={}){let n=e4(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 eZ(e)){var i,o;let e=r.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!e)continue;let s=Number(e[1]),l=e[2];Number.isFinite(s)&&(i=l,o=t,i===o||i.startsWith(`${o}:`))&&(a+=s,n.add(l))}return{usagePercent:mj(a),measuredAt:r,method:mZ,matchedProcesses:[...n]}}(e.stdout,t,new Date().toISOString())}catch(e){throw m1("cpu",t,e)}}async function m0(e,t,r={}){let n=e4(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 P("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=m2(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!==mV(e));if(!r)break;return mV(r)??void 0}}(e);if(void 0===n)throw new P("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:m2(e,"TOTAL RSS"),measuredAt:r,method:mY}}(e.stdout,t,new Date().toISOString())}catch(e){throw m1("memory",t,e)}}function m1(e,t,r){return r instanceof P?new P(r.code,r.message,{...r.details??{},metric:e,package:t},r):new P("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function m2(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(n)return mV(n[1])??void 0}async function m3(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return ec(t)?"macos"===e.platform?void 0:"device"===e.kind?Q(r,t):void 0:await m4(e,t)}async function m4(e,t){try{let{resolveIosApp:r}=await Promise.resolve(t0);return await r(e,t)}catch{return}}async function m5(e,t){if(!("android"!==e.platform||!t||ec(t)))try{let{resolveAndroidApp:r}=await import("../1769.js"),n=await r(e,t);return"package"===n.type?n.value:void 0}catch{return}}async function m8(e,t,r){if(r||"android"!==e.platform||!t||!ec(t))return r;try{let{getAndroidAppState:t}=await import("../1769.js"),n=await t(e);return n.package?.trim()||r}catch{return r}}async function m6(e,t,r,n){return await m3(e,t,r)??await n(e,t)??("android"===e.platform&&t&&ec(t)?r:void 0)}function m9(e){return dM("INVALID_ARGS",e)}function m7(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=tg(r);if(!mU.has(e))throw new P("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&n)throw new P("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new P("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let i=r?tg(r):"app";if("app"!==i&&"menubar"!==i&&n)throw new P("INVALID_ARGS",`open --surface ${i} does not accept an app target`);return i}({device:e,surfaceFlag:t,openTarget:r,existingSurface:n})}catch(e){return dM(e instanceof P?e.code:"INVALID_ARGS",String(e.message))}}function he(e){let{shouldRelaunch:t,openTarget:r,surface:n,device:a}=e;return t?r&&ec(r)?m9("open --relaunch does not support URL targets."):"app"!==n?m9("open --relaunch is supported only for app surfaces."):"android"===a.platform&&r&&"binary"===es(r)?m9(J(r)):null:null}async function ht(e){let{req:t,sessionName:r,sessionStore:n,device:a,surface:i,openTarget:o,existingSession:s}=e;await o$(a);let{appBundleId:l,appName:u}=await hr({device:a,surface:i,openTarget:o,existingAppBundleId:s?.appBundleId}),d=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:n,device:a}=e,i=r.getRuntimeHints(n),o=function(e){let{runtime:t,sessionName:r,platform:n}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new P("INVALID_ARGS","open runtime must be an object.");let a=Object.keys(t).find(e=>!mP.includes(e));if(a)throw new P("INVALID_ARGS",`Invalid open runtime field: ${a}. Supported fields are ${mP.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new P("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new P("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,n),metroHost:mE(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new P("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return mC(e)}}(t.metroPort),bundleUrl:mE(t.bundleUrl,"bundleUrl"),launchUrl:mE(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:n,platform:mL(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=mL(a);if(n.platform&&r&&!i)throw new P("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 P("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&&mO(o)>0?o:void 0,previousRuntime:i,replacedStoredRuntime:!0}}(e)}}catch(t){let e=D(t);return dM(e.code,e.message,e.details)}}({req:t,sessionStore:n,sessionName:r,device:a});if(!d.ok)return{type:"response",response:d};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=d.data;await mR({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:u,runtime:d.data.runtime}}}async function hr(e){let{device:t,surface:r,openTarget:n,existingAppBundleId:a}=e,i=await mG(r);return{appBundleId:i.appBundleId??await m6(t,n,a,m5),appName:i.appName??n}}let hn=new Map;async function ha(e){let{device:t,closeTarget:r,outFlag:n,context:a}=e;"android"!==t.platform&&await nz(t.id),await dI(t,"close",[r],n,a),await dO(t,300)}async function hi(e){let{runtime:t,device:r,req:n,logPath:a,appBundleId:i,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let u=s[0]?.trim();!u||ec(u)||await dI(r,"open",[l],n.flags?.out,{...d1(a,n.flags,i,o)})}async function ho(e){var t,r,n,a;let i,{req:o,sessionName:s,sessionStore:l,logPath:u,device:d,openTarget:c,openPositionals:p,appName:f,surface:m,appBundleId:h,runtime:w,existingSession:g}=e,y=o.flags?.relaunch===!0,v=g?.trace?.outPath,I=h,A=Date.now(),S={};if(y&&c){let e=I??c,t=Date.now();await ha({device:d,closeTarget:e,outFlag:o.flags?.out,context:{...d1(u,o.flags,I??g?.appBundleId,v)}}),S.relaunchCloseDurationMs=Math.max(0,Date.now()-t)}let b=Date.now();await mw({device:d,appId:I,runtime:w}),S.runtimeHintsDurationMs=Math.max(0,Date.now()-b);let _="ios"===d.platform&&"app"===m&&p.length>0,N={verbose:o.flags?.verbose,logPath:u,traceLogPath:v,requestId:o.meta?.requestId};_&&I?(S.runnerPrewarmKind="session",S.runnerPrewarmScheduled=!0,i=function(e,t={}){return"ios"!==e.platform?void 0:n3(e,{requestId:t.requestId})?void eb({level:"debug",phase:"ios_runner_session_prewarm_skipped_scoped_provider",data:{deviceId:e.id}}):nB(e,t).then(()=>{}).catch(t=>{eb({level:"warn",phase:"ios_runner_session_prewarm_failed",data:{deviceId:e.id,error:t instanceof Error?t.message:String(t)}})})}(d,N)):_&&(S.runnerPrewarmKind="xctestrun",S.runnerPrewarmScheduled=!0,i=function(e,t={}){return"ios"!==e.platform?void 0:n3(e,{requestId:t.requestId})?void eb({level:"debug",phase:"ios_runner_xctestrun_prewarm_skipped_scoped_provider",data:{deviceId:e.id}}):nm(e,t).then(()=>{}).catch(t=>{eb({level:"warn",phase:"ios_runner_xctestrun_prewarm_failed",data:{deviceId:e.id,error:t instanceof Error?t.message:String(t)}})})}(d,N));let x=Date.now();await dI(d,"open",p,o.flags?.out,{...d1(u,o.flags,I)}),S.openDispatchDurationMs=Math.max(0,Date.now()-x);let M=Date.now();if(await hi({runtime:w,device:d,req:o,logPath:u,appBundleId:I,traceLogPath:v,openPositionals:p}),S.launchUrlDurationMs=Math.max(0,Date.now()-M),y&&i){let e=Date.now();await i,S.runnerPrewarmWaited=!0,S.runnerPrewarmDurationMs=Math.max(0,Date.now()-e)}else i&&(S.runnerPrewarmWaited=!1);I=await m8(d,c,I),"android"===d.platform&&I&&await mX(d,I);let D=c?(t=I,{durationMs:Math.max(0,Date.now()-x),measuredAt:new Date().toISOString(),method:m$,appTarget:c,appBundleId:t}):void 0,k=Date.now();if(await dO(d,300),S.postOpenSettleDurationMs=Math.max(0,Date.now()-k),rt(o.meta?.requestId)){let e=rn();return dM(e.code,e.message,e.details)}g&&dX(g,"open",g.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:g,sessionName:s,device:d,surface:m,appBundleId:I,appName:f,saveScript:!!o.flags?.saveScript});void 0!==o.runtime&&(r=l,n=s,(a=w)&&(0===mO(a)?r.clearRuntimeHints(n):r.setRuntimeHints(n,a))),S.totalDurationMs=Math.max(0,Date.now()-A);let O=function(e){let{sessionName:t,appName:r,appBundleId:n,surface:a,startup:i,timing:o,device:s,runtime:l,runtimeHintCount:u}=e,d={session:t,surface:a};return r&&(d.appName=r),n&&(d.appBundleId=n),i&&(d.startup=i),o&&(d.timing=o),l&&u(l)>0&&(d.runtime=l),s&&(d.platform=s.platform,d.target=s.target??"mobile",d.device=s.name,d.id=s.id,d.kind=s.kind,"android"===s.platform&&(d.serial=s.id)),s?.platform==="ios"&&(d.device_udid=s.id,d.ios_simulator_device_set=s.simulatorSetPath??null),{...d,...e$(`Opened: ${r??n??t}`)}}({sessionName:s,appName:f,appBundleId:I,surface:m,startup:D,timing:S,device:d,runtime:w,runtimeHintCount:mO});return l.recordAction(P,{command:"open",positionals:p,flags:o.flags??{},runtime:void 0!==o.runtime?w:void 0,result:O}),l.set(s,P),{ok:!0,data:O}}async function hs(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e;if(a.has(r)){let e=a.get(r);if(!e)return dM("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=m7(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return i?m9("open --relaunch requires an app name or an active session app."):m9("Session already active. Close it first or pass a new --session name.");let u=he({shouldRelaunch:i,openTarget:s,surface:l,device:e.device});if(u)return u;let d=await dC(e.device),c=await ht({req:t,sessionName:r,sessionStore:a,device:d,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await ho({req:t,sessionName:r,sessionStore:a,logPath:n,device:d,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let i=t.flags?.relaunch===!0,o=t.positionals?.[0];if(i&&!o)return m9("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:n}=e;return t?r&&ec(r)?m9("open --relaunch does not support URL targets."):"android"===n&&r&&"binary"===es(r)?m9(J(r)):null:null}({shouldRelaunch:i,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await os(t.flags??{}),u=m7(l,t.flags?.surface,o);if("string"!=typeof u)return u;let d=he({shouldRelaunch:i,openTarget:o,surface:u,device:l});return d||await rH(hn,l.id,async()=>{let e=a.toArray().find(e=>e.device.id===l.id);if(e)return dM("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 ht({req:t,sessionName:r,sessionStore:a,device:l,surface:u,openTarget:o});return"response"===i.type?i.response:await ho({req:t,sessionName:r,sessionStore:a,logPath:n,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:i.details.appBundleId,appName:i.details.appName,runtime:i.details.runtime,surface:u})})}async function hl(e){let t=await X(e,["emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function hu(e){let{device:t,shutdownRequested:r}=e;if(r&&(dP(t)||"android"===t.platform&&"emulator"===t.kind))try{return dP(t)?await sX(t):await hl(t)}catch(t){let e=k(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function hd(e){if(await nz(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await lc("dismiss",t).catch(t=>{eb({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function hc(e,t){e.appLog&&await io(e.appLog),rW(e.device.platform)&&await hd(e),await mt(t).catch(()=>{})}async function hp(e){let t,{req:r,sessionName:n,logPath:a,sessionStore:i}=e,o=i.get(n);if(!o)return dM("SESSION_NOT_FOUND","No active session");o.appLog&&await io(o.appLog),r.positionals&&r.positionals.length>0&&(rW(o.device.platform)&&await hd(o),await dI(o.device,"close",r.positionals,r.flags?.out,{...d1(a,r.flags,o.appBundleId,o.trace?.outPath)}),await dO(o.device,300)),rW(o.device.platform)&&(t=(r.positionals?.length??0)>0,!dP(o.device)||t||r.flags?.shutdown||o.recording)?await hd(o):rW(o.device.platform)&&eb({level:"debug",phase:"ios_runner_retained_after_close",data:{session:o.name,deviceId:o.device.id}}),mh(i.getRuntimeHints(n))&&o.appBundleId&&await mg({device:o.device,appId:o.appBundleId}).catch(()=>{}),i.recordAction(o,{command:"close",positionals:r.positionals??[],flags:r.flags??{},result:{session:n,...e$(`Closed: ${n}`)}}),r.flags?.saveScript&&(o.recordSession=!0),i.writeSessionLog(o),await mt(n).catch(()=>{}),i.delete(n);let s=await hu({device:o.device,shutdownRequested:r.flags?.shutdown});return s?{ok:!0,data:eq({session:n,shutdown:s},`Closed: ${n}`)}:{ok:!0,data:{session:n,...e$(`Closed: ${n}`)}}}let hf={ios:async(e,t,r)=>{let{reinstallIosApp:n}=await Promise.resolve(t0);return await n(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:n}=await import("../1769.js");return await n(e,t,r)}},hm={ios:async(e,t,r)=>{let{installIosApp:n}=await Promise.resolve(t0),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("../1769.js"),a=await n(e,r);return{package:a.packageName,appName:a.appName,launchTarget:a.launchTarget}}};async function hh(e){let{req:t,command:r,sessionName:n,sessionStore:a,deployOps:i}=e,o=a.get(n),s=t.flags??{},u=dD(r,o,s);if(u)return u;let d=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!d||!c)return dM("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let p=t.meta?.uploadedArtifactId;try{var f;let e,n=p?im(p,t.meta?.tenantId):aN.expandHome(c);if(!l.existsSync(n))return dM("INVALID_ARGS",`App binary not found: ${n}`);let u=await dE({session:o,flags:s,ensureReady:!1});if(!dK(r,u))return dM("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===u.platform){let t=await i.ios(u,d,n),r=t.bundleId;e=r?{app:d,appPath:n,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:n,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await i.android(u,d,n),r=t.package;e=r?{app:d,appPath:n,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:n,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=eq(e,(f=e,`Installed: ${f.appName??ej(f)}`));return o&&a.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{p&&ih(p)}}async function hw(e,t,r){return await tZ(e,t,r)}async function hg(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=eu(t.flags?.androidDeviceAllowlist),r=t.flags?.platform,n=rK({simulatorSetPath:Z(t.flags?.iosSimulatorDeviceSet),platform:r,target:t.flags?.target}),a=await oc({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?rW(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=D(t);return dM(e.code,e.message,e.details)}if("apps"===t.command){let e=n.get(r),a=t.flags??{},i=dD(t.command,e,a);if(i)return i;let o=await dE({session:e,flags:a,ensureReady:!0});if(!dK("apps",o))return dM("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=tQ(t.flags?.appsFilter);return rW(o.platform)?{ok:!0,data:{apps:(await uo(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}:{ok:!0,data:{apps:(await q(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function hy(e){let{ensureAndroidEmulatorBooted:t}=await import("../1769.js");return await t(e)}let hv='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',hI='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function hA(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r),i=t.flags??{},o=i.platform;if(!a&&"string"==typeof i?.session&&i.session.trim().length>0)return dM("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=dD("appstate",a,i);if(s)return s;let l=rW(a?.device.platform)&&function(e,t){if(!t)return!1;if(!dk(e))return!0;let r=e?.platform;return!(r&&!rz(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(i,a);if("ios"===o&&!l)return dM("SESSION_NOT_FOUND",hv);if("macos"===o&&!l)return dM("SESSION_NOT_FOUND",hI);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 dM("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 dE({session:a,flags:i,ensureReady:!0});if("ios"===u.platform)return dM("SESSION_NOT_FOUND",hv);if("macos"===u.platform)return dM("SESSION_NOT_FOUND",hI);let{getAndroidAppState:d}=await import("../1769.js"),c=await d(u);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function hS(e){let{req:t,sessionName:r,sessionStore:n}=e;if("boot"===t.command){let e,a=n.get(r),i=t.flags??{},o=dD(t.command,a,i);if(o)return o;let s="android"===(i.platform??a?.device.platform),l=!0===i.headless;if(l&&!s)return dM("INVALID_ARGS","boot --headless is supported only for Android emulators.");let u=dL({flags:i,sessionDevice:a?.device}),d=s&&!!u,c=!1;try{e=await dE({session:a,flags:i,ensureReady:!1})}catch(r){let t=D(r);if(s&&l&&!u&&"DEVICE_NOT_FOUND"===t.code)return dM("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!d||"DEVICE_NOT_FOUND"!==t.code||!u)throw r;e=await hy({avdName:u,serial:i.serial,headless:l}),c=!0}if(i.target&&(e.target??"mobile")!==i.target)return dM("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${i.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return dM("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=dL({flags:i,sessionDevice:a?.device,resolvedDevice:e});if(!t)return dM("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await hy({avdName:t,serial:i.serial,headless:!0})}await o$(e)}else("android"!==e.platform||!0!==e.booted)&&await o$(e);return dK("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:dM("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await hA({req:t,sessionName:r,sessionStore:n}):null}function hb(e,t){for(let r of e){if(t(r))return r;let e=hb(r.children,t);if(e)return e}}function h_(e,t){let r=[];for(let n of e)t(n)&&r.push(n),r.push(...h_(n.children,t));return r}function hN(e,t){let r=hb(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 hx(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 hM(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:hx(e):null}let hD="xctrace-animation-hitches";function hk(e,t){let r=r0(e),n=hN(r,t);return{rows:0===n.length?[]:h_(r,e=>"row"===e.name),schema:n}}function hP(e,t){for(let r of e)hP(r.children,t),r.attributes.id&&t.set(r.attributes.id,{numberValue:hx(r),process:hO(r)})}function hO(e){if(!e||e.children.some(e=>"sentinel"===e.name))return null;let t=hx(hb(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 hE="ps-process-snapshot",hC="ps-process-snapshot",hL="xctrace-activity-monitor",hR="xctrace-activity-monitor";async function hT(e,t){if("ios"===e.platform&&"device"===e.kind)return await hW(e,t);let r=await hH(e,t),n=await hY(e,r);if(0===n.length)throw new P("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 hQ({usagePercent:n.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:n.reduce((e,t)=>e+t.rssKb,0),measuredAt:a,matchedProcesses:[r.executableName],cpuMethod:hE,memoryMethod:hC})}async function h$(e,t){var r;let n,a,i,o,s,l;if("ios"!==e.platform||"device"!==e.kind)throw new P("COMMAND_FAILED","Apple frame-health sampling is currently available only on connected iOS devices.",{metric:"fps",platform:e.platform,deviceKind:e.kind});let u=await hz(e,t),d=await hF(e,t,u);return n=hk((r={hitchesXml:d.hitchesXml,frameLifetimesXml:d.frameLifetimesXml,displayInfoXml:d.displayInfoXml,processIds:u.map(e=>e.pid),processNames:ar(u.map(e=>f.basename(y(e.executable)))),windowStartedAt:d.windowStartedAt,windowEndedAt:d.windowEndedAt,measuredAt:d.windowEndedAt}).frameLifetimesXml,"hitches-frame-lifetimes").rows.length,a=function(e){if(!e)return;let{rows:t,schema:r}=hk(e,"device-display-info"),n=r.indexOf("max-refresh-rate");if(n<0)return;let a=new Map;for(let e of t){hP(e.children,a);let t=hM(e.children[n],a);if(null!==t&&t>0)return t}}(r.displayInfoXml),o=(i=(function(e){let t,r,n=r0(e),a=Object.values(r={start:(t=hN(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 h_(n,e=>"row"===e.name).map(e=>(function(e,t,r){var n,a,i;let o;if(hP(e.children,r),!0===(n=e.children[t.isSystem],null===(o=hM(n,r))?null:0!==o))return null;let s=hM(e.children[t.start],r),l=hM(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:hO(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,s=Math.max(0,Math.round(Date.parse(r.windowEndedAt)-Date.parse(r.windowStartedAt))),l=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:mj(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)}(i,Date.parse(r.windowStartedAt)),{droppedFramePercent:n>0?mj(o/n*100):0,droppedFrameCount:o,totalFrameCount:n,sampleWindowMs:s,windowStartedAt:r.windowStartedAt,windowEndedAt:r.windowEndedAt,measuredAt:r.measuredAt,method:hD,matchedProcesses:[...new Set(i.map(e=>e.processName).filter(e=>"string"==typeof e&&e.length>0))],frameDeadlineMs:void 0===a?void 0:mj(1e3/a),refreshRateHz:a,worstWindows:l.length>0?l:void 0}}async function hF(e,t,r){let n=await d.mkdtemp(f.join(c.tmpdir(),"agent-device-ios-frame-perf-")),a=f.join(n,"animation-hitches.trace"),i=f.join(n,"hitches.xml"),o=f.join(n,"frame-lifetimes.xml"),s=f.join(n,"display-info.xml");try{let n=await hU({device:e,appBundleId:t,tracePath:a,template:"Animation Hitches",duration:"2s",targetPids:r.map(e=>e.pid),validateTraceOutput:!0,failureMessage:`Failed to record iOS frame-health sample for ${t}`});await hj(e,t,a,"hitches",i),await hj(e,t,a,"hitches-frame-lifetimes",o);let l=await hB(e,t,a,"device-display-info",s);return{windowStartedAt:n.startedAt,windowEndedAt:n.endedAt,hitchesXml:await d.readFile(i,"utf8"),frameLifetimesXml:await d.readFile(o,"utf8"),displayInfoXml:l?await d.readFile(s,"utf8"):void 0}}finally{await d.rm(n,{recursive:!0,force:!0}).catch(()=>{})}}async function hU(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 hG(s,e.tracePath);if(0===l.result.exitCode)return e.validateTraceOutput&&await hV(e,l.result.stdout,l.result.stderr),{startedAt:l.startedAt,endedAt:l.endedAt,capturedAtMs:l.capturedAtMs};throw new P("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:h1(l.result.stdout,l.result.stderr)})}async function hG(e,t){let r;for(let n=1;n<=3;n+=1){n>1&&(await d.rm(t,{recursive:!0,force:!0}).catch(()=>{}),await new Promise(e=>setTimeout(e,1500)));let a=new Date().toISOString(),i=await ry(e,{allowFailure:!0,timeoutMs:6e4});if(r={result:i,startedAt:a,endedAt:new Date().toISOString(),capturedAtMs:Date.now()},0===i.exitCode||!function(e){let t=`${e.stdout}
|
|
60
|
+
${e.stderr}`.toLowerCase();return t.includes("_lockkperf")||t.includes("could not lock kperf")||t.includes("likely another session just started")}(i))break}return r}async function hV(e,t,r){let n=await d.stat(e.tracePath).catch(()=>null);if(!(n?.isDirectory()===!0?(await d.readdir(e.tracePath).catch(()=>[])).length>0:(n?.size??0)>0))throw new P("COMMAND_FAILED",`${e.failureMessage}: xctrace produced no trace data`,{tracePath:e.tracePath,appBundleId:e.appBundleId,deviceId:e.device.id,stdout:t,stderr:r,hint:"Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf."})}async function hj(e,t,r,n,a){let i=["xctrace","export","--input",r,"--xpath",`/trace-toc/run/data/table[@schema="${n}"]`,"--output",a],o=await ry(i,{allowFailure:!0,timeoutMs:15e3});if(0!==o.exitCode)throw new P("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:h1(o.stdout,o.stderr)})}async function hB(e,t,r,n,a){try{return await hj(e,t,r,n,a),!0}catch{return!1}}async function hq(e){let t=r0(e),r=hN(t,"activity-monitor-process-live");if(0===r.length)throw new P("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 P("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let s=h_(t,e=>"row"===e.name),l=[],u=new Map;for(let e of s){var d,c;let t=e.children;if(0===t.length)continue;for(let e of t){let t=hb(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:hx(e),processName:h0(e)})}let r=hM(t[n],u),s=(d=t[a],c=u,d?d.attributes.ref?c.get(d.attributes.ref)?.processName??null:h0(d):null);null!==r&&Number.isFinite(r)&&s&&l.push({pid:r,processName:s,cpuTimeNs:hM(t[i],u),residentMemoryBytes:hM(t[o],u)})}return l}async function hH(e,t){let r="macos"===e.platform?await hX(t):await hZ(e,t),n="macos"===e.platform?f.join(r,"Contents","Info.plist"):f.join(r,"Info.plist"),a=await sY(n,"CFBundleExecutable");if(!a)throw new P("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:a,executablePath:"macos"===e.platform?f.join(r,"Contents","MacOS",a):f.join(r,a)}}async function hW(e,t){let r=await hz(e,t),n=await hK(e,t),a=await hK(e,t),i=hJ(await hq(n.xml),r,t,e),o=hJ(await hq(a.xml),r,t,e),s=a.capturedAtMs-n.capturedAtMs;if(s<=0)throw new P("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 P("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 hQ({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:hL,memoryMethod:hR})}async function hz(e,t){let r=(await oO(e,"all")).find(e=>e.bundleId===t);if(!r)throw new P("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new P("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let n=r.url.replace(/\/$/,""),a=y(n),i=(await oE(e)).filter(e=>e.executable.startsWith(`${n}/`));if(0===i.length)throw new P("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,deviceId:e.id,appBundlePath:a,hint:"Run open <app> for this session again to ensure the iOS app is active, then retry perf."});return i}async function hK(e,t){let r=await d.mkdtemp(f.join(c.tmpdir(),"agent-device-ios-perf-")),n=f.join(r,"sample.trace"),a=f.join(r,"activity-monitor-process-live.xml");try{let r=await hU({device:e,appBundleId:t,tracePath:n,template:"Activity Monitor",duration:"1s",allProcesses:!0,failureMessage:`Failed to record iOS device Activity Monitor sample for ${t}`});return await hj(e,t,n,"activity-monitor-process-live",a),{capturedAtMs:r.capturedAtMs,xml:await d.readFile(a,"utf8")}}finally{await d.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function hJ(e,t,r,n){let a=new Set(t.map(e=>e.pid)),i=new Set(t.map(e=>f.basename(y(e.executable)))),o=e.filter(e=>a.has(e.pid)||i.has(e.processName));if(0===o.length)throw new P("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:n.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let s=new Map;for(let e of o){let t=s.get(e.pid);if(!t){s.set(e.pid,e);continue}s.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:h2(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:h2(t.residentMemoryBytes,e.residentMemoryBytes)})}let l=[...s.values()],u=l.map(e=>e.cpuTimeNs).filter(e=>null!==e),d=l.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:u.length>0?u.reduce((e,t)=>e+t,0):null,residentMemoryBytes:d.length>0?d.reduce((e,t)=>e+t,0):null,matchedProcesses:ar(l.map(e=>e.processName))}}async function hX(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await rg("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new P("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 P("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return n}async function hZ(e,t){let r=rS(e,["get_app_container",e.id,t,"app"]),n=await ry(r,{allowFailure:!0,timeoutMs:15e3});if(0!==n.exitCode)throw new P("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 P("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return a}async function hY(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:rS(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of eZ(e)){let e=r.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!e)continue;let n=Number(e[1]),a=Number(e[2]),i=Number(e[3]),o=e[4].trim();Number.isFinite(n)&&Number.isFinite(a)&&Number.isFinite(i)&&t.push({pid:n,cpuPercent:a,rssKb:i,command:o})}return t})(("macos"===e.platform?await rg("ps",r,{timeoutMs:15e3}):await ry(r,{timeoutMs:15e3})).stdout).filter(e=>{var r,n;let a;return r=e.command,n=t,a=function(e){let[t=""]=e.trim().split(/\s+/,1);return t}(r),!!(n.executablePath&&(r===n.executablePath||a===n.executablePath||r.startsWith(`${n.executablePath} `)))||f.basename(a)===n.executableName})}function hQ(e){return{cpu:{usagePercent:mj(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 h0(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function h1(e,t){let r=oR(e,t);if(r)return r;let n=`${e}
|
|
61
|
+
${t}`.toLowerCase();return n.includes("no device matched")||n.includes("failed to find device")?oL: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 h2(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function h3(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===m$&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:m$,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:m$,sampleCount:i.length,samples:i}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:m$},{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:mF},cpu:{available:!1,reason:mF}},sampling:{startup:{method:m$,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:mY,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:mZ,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"},fps:{method:mq,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:hD,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:hD,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:hR,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:hL,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:hC,description:`Resident memory snapshot from ${n}`,unit:"kB"},cpu:{method:hE,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 h4(u,e,t):await h5(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 h4(e,t,r){let n=await h8(t,r);e.metrics.memory=h7(n.memory),e.metrics.cpu=h7(n.cpu),e.metrics.fps=we(h7(n.fps),t)}async function h5(e,t){let r=await h6(t);e.metrics.memory=h7(r.memory),e.metrics.cpu=h7(r.cpu),e.metrics.fps=we(h7(r.fps),t)}async function h8(e,t){let r=e.appBundleId,n={adb:t.androidAdb},[a,i,o]=await Promise.allSettled([m0(e.device,r,n),mQ(e.device,r,n),mJ(e.device,r,n)]);return{memory:a,cpu:i,fps:o}}async function h6(e){let t=e.appBundleId,r=await h9(h$(e.device,t)),n=await h9(hT(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 h9(e){try{return{status:"fulfilled",value:await e}}catch(e){return{status:"rejected",reason:e}}}function h7(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=k(e.reason);return{available:!1,reason:t.message,error:t}}function we(e,t){var r,n;let a,i;if(!0!==e.available)return e;let o=(r=t.actions,a=wt((n=e).windowStartedAt),i=wt(n.windowEndedAt)??wt(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 wt(e){if("string"!=typeof e)return;let t=Date.parse(e);return Number.isFinite(t)?t:void 0}let wr=["path","start","stop","doctor","mark","clear"],wn=`logs requires ${wr.slice(0,-1).join(", ")}, or ${wr.at(-1)}`,wa=["dump","log"],wi=`network requires ${wa.join(" or ")}`,wo=["summary","headers","body","all"],ws=`network include mode must be one of: ${wo.join(", ")}`;async function wl(e){let{req:t}=e;return"perf"===t.command?wu(e):"logs"===t.command?wd(e):"network"===t.command?wh(e):null}async function wu(e){let{sessionName:t,sessionStore:r,androidAdbExecutor:n}=e,a=r.get(t);if(!a)return dM("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await h3(a,{androidAdb:n})}}catch(e){return{ok:!1,error:k(e)}}}async function wd(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(!a)return dM("SESSION_NOT_FOUND","logs requires an active session");if(!dK("logs",a.device))return dM("UNSUPPORTED_OPERATION","logs is not supported on this device");let i=(t.positionals?.[0]??"path").toLowerCase(),o=!!t.flags?.restart;return wr.includes(i)?o&&"clear"!==i?dM("INVALID_ARGS","logs --restart is only supported with logs clear"):"path"===i?function(e,t,r){let n=r.resolveAppLogPath(t),a=function(e){if(!l.existsSync(e))return{exists:!1,sizeBytes:0};let t=l.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(n);return{ok:!0,data:{path:n,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android",sizeBytes:a.sizeBytes,modifiedAt:a.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}(a,r,n):"doctor"===i?wc(a,r,n):"mark"===i?function(e,t,r){let n,a=e.positionals?.slice(1).join(" ")??"",i=r.resolveAppLogPath(t);return a7(i),n=`[agent-device][mark][${new Date().toISOString()}] ${a.trim()||"marker"}
|
|
62
|
+
`,l.appendFileSync(i,n,"utf8"),{ok:!0,data:{path:i,marked:!0}}}(t,r,n):"clear"===i?wp(a,r,n,o):"start"===i?wf(a,r,n):"stop"===i?wm(a,r,n):dM("INVALID_ARGS",wn):dM("INVALID_ARGS",wn)}async function wc(e,t,r){let n=r.resolveAppLogPath(t),a=await is(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 wp(e,t,r,n){if(e.appLog&&!n)return dM("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(n&&!e.appBundleId)return dM("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let a=r.resolveAppLogPath(t);if(!n)return{ok:!0,data:il(a)};e.appLog&&await io(e.appLog);let i=il(a),o=r.resolveAppLogPidPath(t);try{let n=await ir(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:k(n)}}}async function wf(e,t,r){if(e.appLog)return dM("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return dM("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 ir(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:k(e)}}}async function wm(e,t,r){if(!e.appLog)return dM("INVALID_ARGS","no app log stream active");let n=e.appLog.outPath;return await io(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:n,stopped:!0}}}async function wh(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(!a)return dM("SESSION_NOT_FOUND","network requires an active session");if(!dK("network",a.device))return dM("UNSUPPORTED_OPERATION","network is not supported on this device");let i=(t.positionals?.[0]??"dump").toLowerCase();if(!wa.includes(i))return dM("INVALID_ARGS",wi);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return dM("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 dM("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let n=(r??t??"summary").toLowerCase();return wo.includes(n)?{ok:!0,include:n}:dM("INVALID_ARGS",ws)}(t);if(!s.ok)return s;let{include:l}=s,u=await ie({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 ww=/^[A-Z_][A-Z0-9_]*$/,wg=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-((?:[^}\\]|\\.)*))?\}/g,wy="AD_VAR_";function wv(e){return e.startsWith("AD_")}function wI(e){return new P("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function wA(e){let t={};for(let[r,n]of Object.entries(e)){if("string"!=typeof n||!r.startsWith(wy))continue;let e=r.slice(wy.length);0!==e.length&&ww.test(e)&&(wv(e)||(t[e]=n))}return t}function wS(e){let t={};for(let r of e){let e=r.indexOf("=");if(e<=0)throw new P("INVALID_ARGS",`Invalid -e entry "${r}": expected KEY=VALUE.`);let n=r.slice(0,e);if(!ww.test(n))throw new P("INVALID_ARGS",`Invalid -e key "${n}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(wv(n))throw wI(n);t[n]=r.slice(e+1)}return t}function wb(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):[]}function w_(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 wN(e,t,r){return e.replace(wg,(e,n,a,i)=>{if(n)return"${";if(!a)return e;if(Object.prototype.hasOwnProperty.call(t.values,a))return t.values[a];if(void 0!==i)return i.replace(/\\(.)/g,"$1");throw new P("INVALID_ARGS",`Unresolved variable \${${a}} at ${r.file}:${r.line}.`)})}function wx(e,t,r){if(!e)return e;let n={...e};for(let[e,a]of Object.entries(n))"string"==typeof a&&(n[e]=wN(a,t,r));return n}let wM=new Set(["ios","android","macos","linux"]),wD=new Set(["mobile","tv","desktop"]);function wk(e){let t=e.split(/\r?\n/),r={};for(let e=0;e<t.length;e+=1){let n=t[e].trim();if(0===n.length||n.startsWith("#"))continue;if(wP(n)){!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 P("INVALID_ARGS",`Invalid env directive on line ${t}: expected "env KEY=VALUE".`);let a=r.slice(0,n);if(!ww.test(a))throw new P("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 P("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 P("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 P("INVALID_ARGS",`Duplicate env directive "${n}" on line ${r}.`);i[n]=a,e.env=i}(r,n,e+1);continue}if(!n.startsWith("context "))break;let a=n.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&wM.has(e)&&wO(r,"platform",e)}let i=n.match(/(?:^|\s)target=([^\s]+)/);if(i){let e=i[1];e&&wD.has(e)&&wO(r,"target",e)}let o=n.match(/(?:^|\s)timeout=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=1&&wO(r,"timeoutMs",Math.floor(e))}let s=n.match(/(?:^|\s)retries=(\d+)/);if(s){let e=Number(s[1]);Number.isFinite(e)&&e>=0&&wO(r,"retries",Math.floor(e))}}return r}function wP(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function wO(e,t,r){let n=e[t];if(void 0!==n)throw new P("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 wE(e){return!!e&&!Number.isNaN(Number(e))}let wC=/[*?[\]{}]/;async function wL(e){let t,{filePath:r,sessionName:n,requestId:a,timeoutMs:i,platform:o,target:s,artifactsDir:l,runReplay:u,cleanupSession:d}=e;t9(a);let c=new Set,p=!1,f=u({filePath:r,sessionName:n,platform:o,target:s,requestId:a,artifactsDir:l,artifactPaths:c}).catch(e=>{let t=D(e);return dM(t.code,t.message)}).finally(()=>{re(a)});try{return"number"==typeof i?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{p=!0,t7(a),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(i,[...c]))},i)})]):await f}finally{t&&clearTimeout(t),p&&(await wR(f)||eb({level:"warn",phase:"test_timeout_cleanup_race",data:{session:n,requestId:a,graceMs:2e3}}));try{await d(n)}catch(e){eb({level:"warn",phase:"test_cleanup_failed",data:{session:n,error:D(e).message}})}}}async function wR(e){return await Promise.race([e.then(()=>!0),N(2e3).then(()=>!1)])}async function wT(e){let{req:t,sessionName:r,runReplay:n,cleanupSession:a}=e;if((t.positionals?.length??0)===0)return dM("INVALID_ARGS","test requires at least one path or glob");try{var i,o,s,u,d,c;let e,p,m,h,w,g=function(e){let{inputs:t,cwd:r,platformFilter:n}=e,a=r??process.cwd(),i=[...new Set(t.flatMap(e=>(function(e,t){var r,n;let a=aN.expandHome(e,t);if(l.existsSync(a)){let t=l.statSync(a);if(t.isDirectory())return l.globSync("**/*.ad",{cwd:a}).map(e=>f.join(a,e));if(t.isFile()){if(".ad"!==f.extname(a))throw new P("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[a]}return[]}if(r=e,!wC.test(r)&&(n=a,!wC.test(n)))throw new P("INVALID_ARGS",`test input not found: ${e}`);let i=f.isAbsolute(a)?a:e;return l.globSync(i,{cwd:f.isAbsolute(a)?void 0:t}).map(e=>f.isAbsolute(e)?e:f.resolve(t,e)).filter(e=>".ad"===f.extname(e)&&function(e){try{return l.statSync(e).isFile()}catch{return!1}}(e))})(e,a)))].map(e=>f.normalize(e)).sort((e,t)=>e.localeCompare(t)),o=[];for(let e of i){var s,u;let t=wk(l.readFileSync(e,"utf8"));if(!n){o.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){o.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${n}`});continue}s=n,u=t.platform,("apple"===s?"apple"===u||"ios"===u||"macos"===u:u===s)&&o.push({kind:"run",path:e,metadata:t})}if(0===o.filter(e=>"run"===e.kind).length){let e=n?` for --platform ${n}`:"";throw new P("INVALID_ARGS",`No .ad tests matched${e}.`)}return o}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),y=(i=t.meta?.requestId,(i?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),v=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:n}=e,a=aN.expandHome(t??".agent-device/test-artifacts",r);return f.join(a,n)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),I=[],A=Date.now(),S=0;for(let e of g){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}S+=1;let i=await w$({entry:e,sessionName:r,suiteInvocationId:y,caseIndex:S-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(o=t.flags?.timeoutMs,s=e.metadata.timeoutMs,"number"==typeof o?o:s),suiteArtifactsDir:v,runReplay:n,cleanupSession:a});if(I.push(i),t.flags?.failFast===!0)break}let b=(u=g.length,d=I,c=Date.now()-A,e=d.filter(e=>"passed"===e.status).length,m=(p=d.filter(e=>"failed"===e.status)).length,h=d.filter(e=>"skipped"===e.status).length,w=e+m,{total:u,executed:w,passed:e,failed:m,skipped:h,notRun:Math.max(0,u-w-h),durationMs:c,failures:p,tests:d});return{ok:!0,data:b}}catch(t){let e=D(t);return dM(e.code,e.message)}}async function w$(e){var t,r;let n,a,{entry:i,sessionName:o,suiteInvocationId:s,caseIndex:u,cwd:d,requestId:c,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:w,cleanupSession:g}=e,y=Date.now(),v=f.join(h,(t=i.path,(0===(a=d?f.relative(d,t):f.basename(t)).length||a.startsWith("..")?f.basename(t):a).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",A=0;for(let e=0;e<=p;e+=1){A=e+1;let t=function(e,t,r,n,a=0){let i=f.basename(r,f.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${n+1}${i?`-${i}`:""}:attempt-${a+1}`}(o,s,i.path,u,e),a=f.join(v,`attempt-${A}`);r=i.path,l.mkdirSync(a,{recursive:!0}),l.copyFileSync(r,f.join(a,"replay.ad"));let d=function(e){let{requestId:t,suiteInvocationId:r,filePath:n,caseIndex:a,attemptIndex:i}=e;return t6(`${t??r}:test:${a+1}:${f.basename(n)}:attempt:${i+1}`,r)}({requestId:c,suiteInvocationId:s,filePath:i.path,caseIndex:u,attemptIndex:e}),h=await wL({filePath:i.path,sessionName:t,requestId:d,timeoutMs:m,platform:i.metadata.platform,target:i.metadata.target,artifactsDir:a,runReplay:w,cleanupSession:g});if(!function(e){let{response:t,filePath:r,sessionName:n,attempts:a,maxAttempts:i,attemptArtifactsDir:o}=e,s=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||s.push(t.error.logPath);let u=function(e,t){let r=[],n=new Map;for(let a of e){if(!function(e){try{return l.statSync(e).isFile()}catch{return!1}}(a))continue;let e=function(e,t){let r=f.extname(e),n=r?e.slice(0,-r.length):e,a=t.get(e)??0;return(t.set(e,a+1),0===a)?e:`${n}-${a+1}${r}`}(f.basename(a),n),i=f.join(t,e);f.resolve(a)!==f.resolve(i)&&l.copyFileSync(a,i),r.push(i)}return r}(s,o),d=[`file: ${r}`,`session: ${n}`,`attempt: ${a}/${i}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;d.push(`replayed: ${e}`,`healed: ${r}`)}else d.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&d.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&d.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&d.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&d.push("timeoutMode: cooperative");u.length>0&&d.push(`copiedArtifacts: ${u.map(e=>f.basename(e)).join(", ")}`);let c=f.join(o,"result.txt"),p=`${d.join("\n")}
|
|
63
|
+
`;l.writeFileSync(c,p),t.ok||l.writeFileSync(f.join(o,"failure.txt"),p)}({response:h,filePath:i.path,sessionName:t,attempts:A,maxAttempts:p+1,attemptArtifactsDir:a}),n=h,I=t,h.ok)break}let S=Date.now()-y;if(n?.ok)return{file:i.path,session:I,status:"passed",durationMs:S,attempts:A,artifactsDir:v,replayed:"number"==typeof n.data?.replayed?n.data.replayed:0,healed:"number"==typeof n.data?.healed?n.data.healed:0};let b=n?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:n?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:i.path,session:I,status:"failed",durationMs:S,attempts:A,artifactsDir:v,error:b}}function wF(e,t=[],r){return{ts:Date.now(),command:e,positionals:t,flags:r??{}}}function wU(e,t,r){let n=new Set(r),a=Object.keys(e).filter(e=>!n.has(e));if(a.length>0)throw wX(`Maestro ${t} field "${a[0]}" is not supported yet.`)}function wG(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function wV(e){return e.map((e,t)=>{if("string"==typeof e||wG(e))return e;throw new P("INVALID_ARGS",`Unsupported Maestro command at index ${t+1}: expected a scalar or one-key map.`)})}function wj(e){return e.trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}function wB(e,t){if(null==e)return{};if(!wG(e))throw new P("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 wq(e,t){return wG(e)&&"number"==typeof e.timeout&&Number.isFinite(e.timeout)?Math.max(0,Math.floor(e.timeout)):t}function wH(e,t){if(e.appId)return e.appId;throw new P("INVALID_ARGS",`${t} requires appId in the Maestro flow config.`)}function wW(e,t){if("string"==typeof t)return t;throw new P("INVALID_ARGS",`${e} expects a string value.`)}function wz(e,t){return e.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g,(e,r)=>Object.prototype.hasOwnProperty.call(t.env,r)?t.env[r]:e)}function wK(e,t){return"string"==typeof e?wz(e,t):e}function wJ(e){throw wX(`Maestro command "${e}" is not supported yet.`)}function wX(e){throw new P("INVALID_ARGS",`${e} See supported/unsupported Maestro compatibility at https://github.com/callstackincubator/agent-device/issues/558. If this syntax matters for your flows, comment there or open a focused issue at https://github.com/callstackincubator/agent-device/issues/new.`)}function wZ(e){let t=e.trim().toLowerCase();return"android"===t?"android":"ios"===t?"ios":void 0}let wY=new Set(["accessibility","calendar","camera","contacts","contacts-limited","input-monitoring","location","location-always","media-library","microphone","motion","notifications","photos","reminders","screen-recording","siri"]),wQ={allow:"grant",grant:"grant",granted:"grant",deny:"deny",denied:"deny",reset:"reset",unset:"reset",revoke:"reset",revoked:"reset"},w0={limited:{command:"grant",mode:"limited"},full:{command:"grant",mode:"full"}};function w1(e,t,r){if(null==e)return wF("open",[wz(wH(t,"launchApp"),r)]);if("string"==typeof e)return wF("open",[wz(e,r)]);if(!wG(e))throw new P("INVALID_ARGS","launchApp expects a string or map.");return wU(e,"launchApp",["appId","stopApp","clearState","clearKeychain","arguments","permissions","launchArguments"]),w5(e,"clearState"),w5(e,"clearKeychain"),w8(e,"arguments"),w8(e,"permissions"),w8(e,"launchArguments"),wF("open",[wz("string"==typeof e.appId?e.appId:wH(t,"launchApp"),r)],{relaunch:!0===e.stopApp})}function w2(e,t,r){if(null==e)return wF("close",[wz(wH(t,"stopApp"),r)]);if("string"==typeof e)return wF("close",[wz(e,r)]);throw new P("INVALID_ARGS","stopApp expects a string appId or no value.")}function w3(e,t,r){if(null==e)return wF("close",[wz(wH(t,"killApp"),r)]);if("string"==typeof e)return wF("close",[wz(e,r)]);throw new P("INVALID_ARGS","killApp expects a string appId or no value.")}function w4(e,t,r){let n=wK(e,r),a="number"==typeof n?n:"string"==typeof n&&n.trim().length>0?Number(n):NaN;if(!Number.isFinite(a))throw new P("INVALID_ARGS",`${t} must be a finite number.`);return String(a)}function w5(e,t){if(!0===e[t])throw wX(`Maestro launchApp ${t}: true is not supported yet.`)}function w8(e,t){if(void 0!==e[t])throw wX(`Maestro launchApp field "${t}" is not supported yet.`)}function w6(e,t,r=[],n){if("string"==typeof e){var a;return[w9("label",a=wz(e,n)),w9("text",a),w9("id",a)].join(" || ")}if(!wG(e))throw new P("INVALID_ARGS",`${t} expects a string or selector map.`);wU(e,t,["id","text","enabled","selected",...r]);let i=[];if("string"==typeof e.id&&i.push(w9("id",wz(e.id,n))),"string"==typeof e.text&&i.push(w9("label",wz(e.text,n))),"boolean"==typeof e.enabled&&i.push(w9("enabled",String(e.enabled))),"boolean"==typeof e.selected&&i.push(w9("selected",String(e.selected))),0===i.length)throw new P("INVALID_ARGS",`${t} selector map must include one of id, text, enabled, or selected.`);return i.join(" ")}function w9(e,t){return`${e}=${JSON.stringify(t)}`}function w7(e){if(!wG(e))return;let t={};return"number"==typeof e.repeat&&Number.isInteger(e.repeat)&&e.repeat>1&&(t.count=e.repeat),"number"==typeof e.delay&&Number.isInteger(e.delay)&&e.delay>=0&&(t.intervalMs=e.delay),Object.keys(t).length>0?t:void 0}function ge(e){let t={doubleTap:!0};return wG(e)&&"number"==typeof e.delay&&Number.isInteger(e.delay)&&(t.intervalMs=Math.max(0,e.delay)),t}function gt(e){let t=e.match(/^(\d+),(\d+)$/);if(!t)throw wX('Only absolute Maestro point selectors like "100,200" are supported.');return{x:Number(t[1]),y:Number(t[2])}}function gr(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 wX('Only Maestro swipe coordinates like "100,200" or "50%,75%" are supported.')}let gn={launchApp:({value:e,config:t,context:r})=>[w1(e,t,r)],tapOn:({value:e,context:t})=>[function(e,t){if(wG(e)&&"string"==typeof e.point){wU(e,"tapOn",["point","repeat","delay"]);let t=gt(e.point);return wF("click",[String(t.x),String(t.y)],w7(e))}return wG(e)&&wU(e,"tapOn",["id","text","enabled","selected","repeat","delay","optional","label"]),wF("click",[w6(e,"tapOn",["repeat","delay","optional","label"],t)],w7(e))}(e,t)],doubleTapOn:({value:e,context:t})=>[function(e,t){if(wG(e)&&"string"==typeof e.point){wU(e,"doubleTapOn",["point","delay"]);let t=gt(e.point);return wF("click",[String(t.x),String(t.y)],ge(e))}return wG(e)&&wU(e,"doubleTapOn",["id","text","enabled","selected","delay"]),wF("click",[w6(e,"doubleTapOn",["delay"],t)],ge(e))}(e,t)],longPressOn:({value:e,context:t})=>[function(e,t){if(wG(e)&&"string"==typeof e.point){wU(e,"longPressOn",["point"]);let t=gt(e.point);return wF("longpress",[String(t.x),String(t.y),"3000"])}return wG(e)&&wU(e,"longPressOn",["id","text","enabled","selected"]),wF("click",[w6(e,"longPressOn",[],t)],{holdMs:3e3})}(e,t)],inputText:({value:e,context:t})=>[wF("type",[wz(function(e){if("string"==typeof e)return e;if(!wG(e))throw new P("INVALID_ARGS","inputText expects a string or map.");if(wU(e,"inputText",["text","label"]),"string"!=typeof e.text)throw new P("INVALID_ARGS","inputText map requires a string text field.");return e.text}(e),t)])],pasteText:({value:e,context:t,name:r})=>[wF("type",[wz(wW(r,e),t)])],openLink:({value:e,context:t,name:r})=>[wF("open",[wz(wW(r,e),t)])],assertVisible:({value:e,context:t,name:r})=>[wF("wait",[w6(e,r,[],t),"5000"])],assertNotVisible:({value:e,context:t,name:r})=>[wF("is",["hidden",w6(e,r,[],t)])],assertTrue:({value:e,context:t})=>(function(e,t){let r=wK(e,t);if(!0===r||"string"==typeof r&&"true"===wj(r))return[];if(!1===r||"string"==typeof r&&"false"===wj(r))throw new P("INVALID_ARGS","Maestro assertTrue literal evaluated to false.");throw wX("Only literal Maestro assertTrue true/false is supported.")})(e,t),extendedWaitUntil:({value:e,context:t})=>(function(e,t){if(!wG(e))throw new P("INVALID_ARGS","extendedWaitUntil expects a map.");wU(e,"extendedWaitUntil",["visible","notVisible","timeout"]);let r=e.visible??e.notVisible;if(void 0===r)throw wX("Only Maestro extendedWaitUntil.visible/notVisible is supported.");let n=w6(r,"extendedWaitUntil",[],t),a=String(wq(e,3e4));return void 0!==e.notVisible?[wF("wait",[a]),wF("is",["hidden",n])]:[wF("wait",[n,a])]})(e,t),takeScreenshot:({value:e,context:t,name:r})=>[wF("screenshot",[wz(wW(r,e),t)])],scroll:({value:e})=>[function(e){if(null!=e)throw wX("Maestro scroll options are not supported yet.");return wF("scroll",["down"])}(e)],swipe:({value:e})=>[function(e){if(!wG(e))throw new P("INVALID_ARGS","swipe expects a map.");if(wU(e,"swipe",["start","end","duration"]),"string"!=typeof e.start||"string"!=typeof e.end)throw wX("Only Maestro swipe start/end coordinates are supported.");let t=gr(e.start),r=gr(e.end),n="number"==typeof e.duration&&Number.isFinite(e.duration)?String(Math.max(16,Math.floor(e.duration))):void 0;if("absolute"===t.kind&&"absolute"===r.kind)return wF("swipe",[String(t.x),String(t.y),String(r.x),String(r.y),...n?[n]:[]]);if("percent"===t.kind&&"percent"===r.kind)return wF("scroll",function(e,t){let r=t.x-e.x,n=t.y-e.y;if(0===Math.abs(r)&&0===Math.abs(n))throw new P("INVALID_ARGS","swipe start and end cannot be the same point.");let a=Math.abs(n)>=Math.abs(r);return[a?n<0?"down":"up":r<0?"right":"left",Math.min(1,Math.max(.01,Math.abs(a?n:r)/100)).toFixed(2).replace(/0+$/,"").replace(/\.$/,"")]}(t,r));throw wX("Maestro swipe start/end must both be absolute pixels or both be percentages.")}(e)],hideKeyboard:()=>[wF("keyboard",["dismiss"])],pressKey:({value:e})=>[function(e){let t=wW("pressKey",e).toLowerCase();if("back"===t)return wF("back");if("enter"===t||"return"===t)return wF("press",["return"]);if("home"===t)return wF("home");throw wX(`Maestro pressKey "${t}" is not supported yet.`)}(e)],back:()=>[wF("back")],waitForAnimationToEnd:({value:e})=>[wF("wait",[String(wq(e,250))])],stopApp:({value:e,config:t,context:r})=>[w2(e,t,r)],killApp:({value:e,config:t,context:r})=>[w3(e,t,r)],setAirplaneMode:({value:e,context:t})=>[wF("settings",["airplane",!function(e,t){if("boolean"==typeof e)return e;if("string"==typeof e){let t=wj(e);if("true"===t)return!0;if("false"===t)return!1}throw new P("INVALID_ARGS",`${t} expects a boolean value.`)}(wK(e,t),"setAirplaneMode")?"off":"on"])],setLocation:({value:e,context:t})=>[function(e,t){if(!wG(e))throw new P("INVALID_ARGS","setLocation expects a map.");return wU(e,"setLocation",["latitude","longitude","lat","lon","lng"]),wF("settings",["location","set",w4(e.latitude??e.lat,"setLocation.latitude",t),w4(e.longitude??e.lon??e.lng,"setLocation.longitude",t)])}(e,t)],setOrientation:({value:e,context:t})=>[function(e,t){let r=wK(e,t);if("string"!=typeof r)throw new P("INVALID_ARGS","setOrientation expects a string value.");let n=wj(r);switch(n){case"portrait":case"landscape-left":case"landscape-right":return wF("rotate",[n]);case"portrait-upside-down":case"upside-down":return wF("rotate",["portrait-upside-down"]);default:throw wX(`Maestro setOrientation "${r}" cannot be mapped to a supported rotate orientation.`)}}(e,t)],setPermissions:({value:e,context:t})=>(function(e,t){if(!wG(e))throw new P("INVALID_ARGS","setPermissions expects a map.");return Object.entries(e).map(([e,r])=>{let{target:n,command:a,mode:i}=function(e,t,r){let n=wj(e),a=wK(t,r);if("string"!=typeof a)throw new P("INVALID_ARGS",`setPermissions.${e} expects a string state.`);let i=wj(a);if("location"===n&&"always"===i&&(n="location-always"),!wY.has(n))throw wX(`Maestro setPermissions target "${e}" cannot be mapped to a supported settings permission target.`);let o=wQ[i];if(o)return{target:n,command:o};let s=w0[i];if(s)return{target:n,...s};let l=function(e,t){if("location-always"===e&&"always"===t||"location"===e&&("while-in-use"===t||"when-in-use"===t))return"grant"}(n,i);if(l)return{target:n,command:l};throw wX(`Maestro setPermissions state "${a}" cannot be mapped to grant, deny, or reset.`)}(e,r,t);return wF("settings",["permission",a,n,...i?[i]:[]])})})(e,t),startRecording:({value:e,context:t})=>[function(e,t){if(null==e)return wF("record",["start"]);if("string"==typeof e)return wF("record",["start",wz(e,t)]);if(!wG(e))throw new P("INVALID_ARGS","startRecording expects a string path, map, or no value.");wU(e,"startRecording",["path","file"]);let r=e.path??e.file;if(void 0===r)return wF("record",["start"]);if("string"!=typeof r)throw new P("INVALID_ARGS","startRecording path must be a string.");return wF("record",["start",wz(r,t)])}(e,t)],stopRecording:({value:e})=>[function(e){if(null!=e)throw new P("INVALID_ARGS","stopRecording expects no value.");return wF("record",["stop"])}(e)],runFlow:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n){if("string"==typeof e)return n.parseRunFlowFile(wz(e,r),r).actions;if(!wG(e))throw new P("INVALID_ARGS","runFlow expects a file path string or map.");if(wU(e,"runFlow",["file","commands","env","when","label"]),!function(e,t){if(null==e)return!0;if(!wG(e))throw new P("INVALID_ARGS","runFlow.when expects a map.");if(wU(e,"runFlow.when",["platform","visible","notVisible","true"]),gs(e,"visible","when.visible"),gs(e,"notVisible","when.notVisible"),gs(e,"true","when.true"),void 0===e.platform)return!0;let r=function(e,t){if("string"!=typeof e)throw new P("INVALID_ARGS",`${t} expects Android or iOS.`);let r=wZ(e);if(!r)throw new P("INVALID_ARGS",`${t} expects Android or iOS.`);return r}(e.platform,"runFlow.when.platform");if(!t.platform)throw new P("INVALID_ARGS","Maestro runFlow.when.platform requires replay to be run with --platform ios|android.");return r===t.platform}(e.when,r))return[];let a={...r,env:{...r.env,...wB(e.env,"runFlow.env"),...r.envOverrides}};if("string"==typeof e.file)return n.parseRunFlowFile(wz(e.file,a),a).actions;if(Array.isArray(e.commands))return go(wV(e.commands),t,a,n);throw new P("INVALID_ARGS","runFlow map requires either file or commands.")})(e,t,r,n),repeat:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n){if(!wG(e))throw new P("INVALID_ARGS","repeat expects a map.");if(wU(e,"repeat",["times","commands","while"]),void 0!==e.while)throw wX("Maestro repeat.while is not supported yet. Only deterministic repeat.times is supported.");let a=function(e,t){let r="string"==typeof e?wz(e,t):e,n="number"==typeof r?r:"string"==typeof r&&/^\d+$/.test(r)?Number(r):void 0;if(void 0===n||!Number.isInteger(n)||n<0)throw new P("INVALID_ARGS","repeat.times must be a non-negative integer or ${VAR} resolving to one.");return n}(e.times,r);if(!Array.isArray(e.commands))throw new P("INVALID_ARGS","repeat requires a commands list.");if(a>100)throw new P("INVALID_ARGS","repeat.times must be <= 100 for deterministic replay expansion.");let i=wV(e.commands);return Array.from({length:a}).flatMap(()=>go(i,t,r,n))})(e,t,r,n)},ga={launchApp:(e,t)=>[w1(void 0,e,t)],scroll:()=>[wF("scroll",["down"])],hideKeyboard:()=>[wF("keyboard",["dismiss"])],back:()=>[wF("back")],waitForAnimationToEnd:()=>[wF("wait",["250"])],stopApp:(e,t)=>[w2(void 0,e,t)],killApp:(e,t)=>[w3(void 0,e,t)],startRecording:()=>[wF("record",["start"])],stopRecording:()=>[wF("record",["stop"])]};function gi(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=ga[a])?n(i,o):wJ(a)}let s=Object.entries(e);if(1!==s.length)throw new P("INVALID_ARGS","Maestro command maps must contain exactly one command.");let[l,u]=s[0],d=gn[l];return d?d({value:u,config:t,context:r,deps:n,name:l}):wJ(l)}(e,t,n,a)}catch(e){if(e instanceof P&&!/\bline \d+\b/.test(e.message))throw new P(e.code,`${e.message} (line ${r})`,e.details);throw e}}function go(e,t,r,n){return e.flatMap((e,a)=>gi(e,t,a+1,r,n))}function gs(e,t,r){if(void 0!==e[t])throw wX(`Maestro ${r} is not supported yet.`)}function gl(e,t){let{config:r,commands:n}=function(e){if(0===e.length)throw new P("INVALID_ARGS","Maestro flow is empty.");if(Array.isArray(e[0]))return{config:{},commands:wV(e[0])};let t=function(e){if(!wG(e))throw new P("INVALID_ARGS","Maestro flow config must be a YAML map.");return{..."string"==typeof e.appId&&e.appId.length>0?{appId:e.appId}:{},...wG(e.env)?{env:wB(e.env,"env")}:{},...Array.isArray(e.onFlowStart)?{onFlowStart:wV(e.onFlowStart)}:{},...Array.isArray(e.onFlowComplete)?{onFlowComplete:wV(e.onFlowComplete)}:{}}}(e[0]),r=e[1];if(!Array.isArray(r))throw new P("INVALID_ARGS","Maestro flow must contain a command list after the YAML document separator.");return{config:t,commands:wV(r)}}(function(e){let t=x(e);for(let e of t)if(e.errors.length>0){let t=e.errors[0]?.message??"Invalid Maestro YAML flow.";throw new P("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=gi(r,t,n,a,{parseRunFlowFile:gu});s.push(...i),i.forEach(()=>l.push(n))}return{actions:s,actionLines: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 gu(e,t){let r=function(e,t){if(f.isAbsolute(e))return e;if(!t.baseDir)throw new P("INVALID_ARGS","runFlow file paths require replay input to have a source path.");return f.resolve(t.baseDir,e)}(e,t);if(t.visitedPaths.has(r))throw new P("INVALID_ARGS",`Maestro runFlow cycle detected at ${r}.`);let n=l.readFileSync(r,"utf8"),a=new Set(t.visitedPaths);return a.add(r),gl(n,{...t,baseDir:f.dirname(r),visitedPaths:a})}let gd={maestro:{parse:function(e,t={}){var r;let n;return gl(e,(n=(r=t).visitedPaths??new Set,r.sourcePath&&n.add(f.resolve(r.sourcePath)),{baseDir:r.sourcePath?f.dirname(r.sourcePath):void 0,platform:function(e){if(e)return wZ(e)}(r.platform),env:{},envOverrides:r.env??{},visitedPaths:n}))}}};function gc(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),n=t$(r?e.slice(0,-1):e.slice());return!n||n.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:n.selectorExpression,selectorTimeout:r?t:null}}async function gp(e){let{action:t,sessionName:r,logPath:n,sessionStore:a}=e;if(!(au(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),au(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&&gf(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}=tq(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=gc(e.positionals??[]);r&&t.push(r)}return ar(t).filter(e=>e.trim().length>0)})(t).map(e=>tV(e)).filter(e=>null!==e);if(0===o.length)return null;let s=au(t.command)||"fill"===t.command,l=au(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await gm(i,t,n,s,a);for(let e of o){let r=tH(u.nodes,e,{platform:i.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let n=tW(r.node,i.device.platform,{action:"fill"===t.command?"fill":au(t.command)?"click":"get"}).join(" || ");if(au(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&&gf(t)?t:void 0}(e.positionals??[]);return r?[t,r]:[t]}(t,n):[n]};if("fill"===t.command){let e=at(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}=tq(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}=gc(t.positionals??[]),r=[n];return e&&r.push(e),{...t,positionals:r}}}return null}function gf(e){return void 0!==e&&""!==e.trim()&&Number.isFinite(Number(e))}async function gm(e,t,r,n,a){let i=await dI(e.device,"snapshot",[],t.flags?.out,{...d1(r,{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n},e.appBundleId,e.trace?.outPath)}),o=i?.nodes??[],s={nodes:tL(t.flags?.snapshotRaw?o:tK(o)),truncated:i?.truncated,createdAt:Date.now(),backend:i?.backend};return ci(e,s),a.set(e.name,e),s}async function gh(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e,o=t.positionals?.[0];if(!o)return dM("INVALID_ARGS","replay requires a path");let s="",u=new Set;try{var d,c;s=aN.expandHome(o,t.meta?.cwd);let e=l.readFileSync(s,"utf8"),p=e.trimStart()[0];if("{"===p||"["===p)return dM("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let m=function(e,t,r={}){var n;let a=function(e){let t=e?.replayBackend;if("string"!=typeof t)return;let r=gd[t];if(!r)throw new P("INVALID_ARGS",`Unsupported replay backend "${t}".`);return r}(t);return a?{...a.parse(e,{...r,platform:t?.platform,env:(n=t,{...wA(w_(n?.replayShellEnv)),...wS(wb(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=0;e<n.length;e+=1){let i=n[e],o=i.trim();if(0===o.length||o.startsWith("#"))continue;if(wP(o)){if(a)throw new P("INVALID_ARGS",`env directives must precede all actions (line ${e+1}).`);continue}let s=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length&&!((r=function(e,t){let r=t;for(;r<e.length&&/\s/.test(e[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[n];if('"'===t&&!r)break;if(r){r=!1;continue}r="\\"===t}if(n>=e.length)throw new P("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[r]);)r+=1;return{value:e.slice(t,r),nextCursor:r}}(e,r);t.push(n.value),r=n.nextCursor}return t}(t);if(0===r.length)return null;let[n,...a]=r;if("context"===n)return null;let i={ts:Date.now(),command:n,positionals:[],flags:{}};if("snapshot"===n){i.positionals=[];for(let e=0;e<a.length;e+=1){let t=a[e];if("-i"===t){i.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){i.flags.snapshotCompact=!0;continue}if("--raw"===t){i.flags.snapshotRaw=!0;continue}if("--force-full"===t){i.flags.snapshotForceFull=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<a.length){let t=Number(a[e+1]);Number.isFinite(t)&&t>=0&&(i.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<a.length){i.flags.snapshotScope=a[e+1],e+=1;continue}if("--backend"===t&&e+1<a.length){e+=1;continue}}return i}if("open"===n){let e=function(e){var t;let r=[],n={};for(let t of e){if("--relaunch"===t){n.relaunch=!0;continue}r.push(t)}let a=av(r);return{positionals:a.positionals,flags:n,runtime:(t=a.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?a.flags:void 0}}(a);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i.runtime=e.runtime,i}if("runtime"===n){let e=av(a);return i.positionals=e.positionals,Object.assign(i.flags,e.flags),i}if(al(n)){let e=ay(n,a);if(Object.assign(i.flags,e.flags),0===e.positionals.length)return i;let t=e.positionals[0];if(t.startsWith("@"))return i.positionals=[t],e.positionals[1]&&(i.result={refLabel:e.positionals[1]}),i;let r=e.positionals[0],o=e.positionals[1];return wE(r)&&wE(o)&&e.positionals.length>=2?i.positionals=[r,o]:i.positionals=[e.positionals.join(" ")],i}if("fill"===n){let e=ay(n,a);if(Object.assign(i.flags,e.flags),e.positionals.length<2)return i.positionals=e.positionals,i;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(i.positionals=[t,e.positionals.slice(2).join(" ")],i.result={refLabel:e.positionals[1]}):i.positionals=[t,e.positionals[1]],i):(i.positionals=[t,e.positionals.slice(1).join(" ")],i)}if("get"===n){if(a.length<2)return i.positionals=a,i;let e=a[0],t=a[1];return t.startsWith("@")?(i.positionals=[e,t],a[2]&&(i.result={refLabel:a[2]})):i.positionals=[e,a.slice(1).join(" ")],i}if("swipe"===n||"type"===n){let e=ay(n,a);return Object.assign(i.flags,e.flags),i.positionals=e.positionals,i}if("record"===n){let e=[];for(let t=0;t<a.length;t+=1){let r=a[t];if("--hide-touches"===r){i.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<a.length){let e=Number(a[t+1]);Number.isFinite(e)&&(i.flags.fps=Math.floor(e)),t+=1;continue}if("--quality"===r&&t+1<a.length){let e=Number(a[t+1]);Number.isFinite(e)&&(i.flags.quality=Math.floor(e)),t+=1;continue}e.push(r)}return i.positionals=e,i}if("screenshot"===n){let e=[];for(let t=0;t<a.length;t+=1){let r=a[t],n=eF({args:a,index:t,flags:i.flags});if(n.handled){t=n.nextIndex;continue}e.push(r)}return i.positionals=e,i}return i.positionals=a,i}(i);s&&(t.push(s),r.push(e+1),a=!0)}return{actions:t,actionLines:r}}(e),metadata:wk(e)}}(e,t.flags,{sourcePath:s}),h=m.metadata,w=h.platform||h.target?{...t,flags:(d=t.flags,c=h,{...d??{},...void 0!==c.platform&&d?.platform===void 0?{platform:c.platform}:{},...void 0!==c.target&&d?.target===void 0?{target:c.target}:{}})}:t,g=m.actions,y=m.actionLines;if(t.flags?.replayUpdate===!0&&m.updateUnsupportedMessage)return dM("INVALID_ARGS",m.updateUnsupportedMessage);if(t.flags?.replayUpdate===!0&&h.env&&Object.keys(h.env).length>0)return dM("INVALID_ARGS","replay -u does not yet preserve env directives. Temporarily remove the env lines, run replay -u, then restore them.");if(t.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(t.flags){for(let e of Object.values(t.flags))if("string"==typeof e&&e.includes("${"))return!0}if(t.runtime){for(let e of Object.values(t.runtime))if("string"==typeof e&&e.includes("${"))return!0}}return!1}(g))return dM("INVALID_ARGS","replay -u does not yet preserve ${VAR} substitutions. Resolve or inline the variables before running with -u.");let v=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(wv(e))throw wI(e);t[e]=n}return{values:t}}({builtins:function(e){let{req:t,sessionName:r,metadata:n,resolvedPath:a}=e,i=t.flags??{},o=t.meta?.cwd??process.cwd(),s={AD_SESSION:r,AD_FILENAME:f.relative(o,a)||a},l=i.platform??n.platform;l&&(s.AD_PLATFORM=l);let u=i.target??n.target;u&&(s.AD_TARGET=u);let d=i.device;"string"==typeof d&&d.length>0&&(s.AD_DEVICE=d);let c=i.artifactsDir;return"string"==typeof c&&c.length>0&&(s.AD_ARTIFACTS=c),s}({req:w,sessionName:r,metadata:h,resolvedPath:s}),fileEnv:h.env,shellEnv:wA(w_(t.flags?.replayShellEnv)),cliEnv:wS(wb(t.flags?.replayEnv))}),I=t.flags?.replayUpdate===!0,A=0;for(let e=0;e<g.length;e+=1){let t=g[e];if(!t||"replay"===t.command)continue;let o=await gw({req:w,sessionName:r,action:t,scope:v,filePath:s,line:y[e]??0,step:e+1,tracePath:a.get(r)?.trace?.outPath,invoke:i});if(o.ok){gv(o).forEach(e=>u.add(e));continue}if(!I)return gy(o,t,e,s,[...u]);let l=await gp({action:t,sessionName:r,logPath:n,sessionStore:a});if(!l)return gy(o,t,e,s,[...u]);if(g[e]=l,!(o=await gw({req:w,sessionName:r,action:l,scope:v,filePath:s,line:y[e]??0,step:e+1,tracePath:a.get(r)?.trace?.outPath,invoke:i})).ok)return gy(o,l,e,s,[...u]);gv(o).forEach(e=>u.add(e)),A+=1}return I&&A>0&&function(e,t,r){let n=[];if(r){let e=r.device.kind?` kind=${r.device.kind}`:"",t=r.device.target?` target=${r.device.target}`:"";n.push(`context platform=${r.device.platform}${t} device=${ap(r.device.name)}${e} theme=unknown`)}for(let e of t){var a;n.push((a=e,aA(a,{runtimeIncludeAllPositionals:!0})))}let i=`${n.join("\n")}
|
|
64
|
+
`,o=`${e}.tmp-${process.pid}-${Date.now()}`;l.writeFileSync(o,i),l.renameSync(o,e)}(s,g,a.get(r)),{ok:!0,data:{replayed:g.length,healed:A,session:r,artifactPaths:[...u]}}}catch(t){let e=D(t);return dM(e.code,e.message,u.size>0?{artifactPaths:[...u]}:void 0)}}async function gw(e){var t,r;let{req:n,sessionName:a,action:i,scope:o,filePath:s,line:l,step:u,tracePath:d,invoke:c}=e,p=(t={file:s,line:l},{...i,positionals:(i.positionals??[]).map(e=>wN(e,o,t)),flags:wx(i.flags,o,t)??{},runtime:wx(i.runtime,o,t)}),f=Date.now();gg(d,{type:"replay_action_start",ts:new Date(f).toISOString(),replayPath:s,line:l,step:u,command:p.command,positionals:p.positionals??[]});let m=await c({token:n.token,session:a,command:p.command,positionals:p.positionals??[],flags:(r=n.flags,tY(r,{...p.flags??{}})),runtime:p.runtime,meta:n.meta}),h=Date.now();return gg(d,{type:"replay_action_stop",ts:new Date(h).toISOString(),replayPath:s,line:l,step:u,command:p.command,ok:m.ok,durationMs:h-f,errorCode:m.ok?void 0:m.error.code}),m}function gg(e,t){e&&l.appendFileSync(e,`${JSON.stringify(t)}
|
|
65
|
+
`)}function gy(e,t,r,n,a=[]){let i;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${i=(t.positionals??[]).map(e=>ac(e)),[t.command,...i].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:n,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:a}}}}function gv(e){if(!e.ok||!e.data)return[];let t=[];if("string"==typeof e.data.path&&t.push(e.data.path),"string"==typeof e.data.outPath&&t.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let r of e.data.artifacts){if(!r||"object"!=typeof r)continue;let e="string"==typeof r.localPath?r.localPath:void 0,n="string"==typeof r.path?r.path:void 0;e?t.push(e):n&&t.push(n)}return[...new Set(t.filter(e=>(function(e){try{return l.statSync(e).isFile()}catch{return!1}})(e)))]}async function gI(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e;return"replay"===t.command?await gh({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}):"test"===t.command?await wT({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,target:s,requestId:l,artifactsDir:u,artifactPaths:d})=>{let c=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 gh({req:{...t,command:"replay",session:r,positionals:[e],flags:c,meta:l?{...t.meta??{},requestId:l}:t.meta},sessionName:r,logPath:n,sessionStore:a,invoke:async e=>{var t;return t=await i(e),d&&gv(t).forEach(e=>d.add(e)),t}})},cleanupSession:async e=>{a.get(e)&&await hp({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:n,sessionStore:a})}}):null}let gA=ek.inventory,gS=ek.state,gb=ek.observability,g_=ek.replay;async function gN(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,command:i,positionals:o,recordPositionals:s,deriveNextSession:l}=e,u=a.get(r),d=t.flags??{},c=dD(i,u,d);if(c)return c;let p=await dE({session:u,flags:d,ensureReady:!0});if(!dK(i,p))return dM("UNSUPPORTED_OPERATION",`${i} is not supported on this device`);let f=await dI(p,i,o,t.flags?.out,{...d1(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 gx(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,i=a.get(r),o=t.flags??{},s=dD(eO.clipboard,i,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return dM("INVALID_ARGS","clipboard requires a subcommand: read or write");let u=await dE({session:i,flags:o,ensureReady:!0});if(!dK(eO.clipboard,u))return dM("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let d=await dI(u,eO.clipboard,t.positionals??[],t.flags?.out,{...d1(n,t.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:d??{}}),{ok:!0,data:{platform:u.platform,...d??{}}}}async function gM(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i,invokeReplayAction:o,androidAdbExecutor:s}=e;if(gA.has(t.command))return await hg({req:t,sessionName:r,sessionStore:a});if("runtime"===t.command)return await mT({req:t,sessionName:r,sessionStore:a});if(gS.has(t.command))return await hS({req:t,sessionName:r,sessionStore:a});if(t.command===eO.clipboard)return await gx({req:t,sessionName:r,logPath:n,sessionStore:a});if(t.command===eO.keyboard){let e=a.get(r),i=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==i||"ios"!==(t.flags??{}).platform?await gN({req:t,sessionName:r,logPath:n,sessionStore:a,command:eO.keyboard,positionals:t.positionals??[]}):dM("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(gb.has(t.command))return await wl({req:t,sessionName:r,sessionStore:a,androidAdbExecutor:s});if(t.command===eO.install||t.command===eO.reinstall)return await hh({req:t,command:t.command,sessionName:r,sessionStore:a,deployOps:t.command===eO.install?hm:hf});if(t.command===ez.installSource)return await mo({req:t,sessionName:r,sessionStore:a});if(t.command===ez.releaseMaterializedPaths)return await ms({req:t});if(t.command===eO.push){let e,i=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return i&&o?await gN({req:t,sessionName:r,logPath:n,sessionStore:a,command:eO.push,positionals:[i,"file"===(e=dg(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>aN.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[i,o]}):dM("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return t.command===eO.triggerAppEvent?await gN({req:t,sessionName:r,logPath:n,sessionStore:a,command:eO.triggerAppEvent,positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,n=r?await m6(e.device,r,e.appBundleId,m5)??e.appBundleId:e.appBundleId;return{...e,appBundleId:n}}}):t.command===eO.open?await hs({req:t,sessionName:r,logPath:n,sessionStore:a}):g_.has(t.command)?await gI({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:o??i}):t.command===eO.batch?await hw(t,r,i):t.command===eO.close?await hp({req:t,sessionName:r,logPath:n,sessionStore:a}):null}let gD=new Set(["com.android.permissioncontroller","com.google.android.permissioncontroller","com.google.android.packageinstaller","com.android.packageinstaller"]),gk=new Set(["android","com.android.systemui"]),gP=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,gO=/^android:id\/button[123]$/i,gE=/(?:^|:)id\/permission_/i,gC=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,gL=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,gR=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function gT(e,t){let r=t[0];if(!r)return;let n=g$(e,r.index);for(let r of t.slice(1)){let t=new Set(g$(e,r.index));for(let e=n.length-1;e>=0;e-=1)t.has(n[e])||n.splice(e,1)}return n[n.length-1]}function g$(e,t){let r=new Map(e.map(e=>[e.index,e])),n=[],a=r.get(t);for(;a;)n.push(a.index),a=void 0===a.parentIndex?void 0:r.get(a.parentIndex);return n.reverse()}function gF(e,t){let r=new Map;for(let t of e){if(void 0===t.parentIndex)continue;let e=r.get(t.parentIndex)??[];e.push(t),r.set(t.parentIndex,e)}let n=new Set([t]),a=[t];for(let e of a)for(let t of r.get(e)??[])n.has(t.index)||(n.add(t.index),a.push(t.index));return e.filter(e=>n.has(e.index))}function gU(e){let t=e.type??"",r=e.identifier??"";return!!(e.hittable||/\bbutton\b/i.test(t)||gO.test(r)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(r))}function gG(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 gV(e,t,r={}){if("wait"===t)return await gj(e,r.timeoutMs??1e4);if("get"===t){var n;let t=await gH(e);return{kind:"alertStatus",platform:"android",action:"get",alert:n=t?.alert??null,...n?e$("Alert visible"):e$("No alert visible")}}return await gB(e,t)}async function gj(e,t){let r=Date.now(),n=await gq(e,t);if(!n)throw new P("COMMAND_FAILED","alert wait timed out");return{kind:"alertWait",platform:"android",action:"wait",alert:n.alert,waitedMs:Date.now()-r,...e$("Alert visible")}}async function gB(e,t){var r;let n,a,i=await gq(e,2e3);if(!i)throw new P("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 o=(r=i.buttons,n="accept"===t?"accept":"dismiss",(a=r.find(e=>e.role===n))||("dismiss"===t?r.find(e=>"neutral"===e.role)??null:1===r.length?r[0]??null:null));if(o)return await so(e,o.x,o.y),gW(t,i.alert,o.label);if("dismiss"===t)return await sl(e),gW(t,i.alert,"Back");throw new P("COMMAND_FAILED","alert accept found an alert but no accept button",{alert:i.alert,hint:"Inspect alert get --json for visible buttons, then use press by visible label/ref if needed."})}async function gq(e,t){let r=Date.now();for(;Date.now()-r<t;){let t=await gH(e);if(t)return t;await ex(300)}return null}async function gH(e){return function(e){var t,r,n,a;let i,o=function(e){let t=e.filter(e=>{var t;let r;return r=(t=e).bundleId??"",gD.has(r)||gE.test(t.identifier??"")});if(t.length)return{nodes:t,source:"permission"};let r=function(e){let t=e.filter(e=>{var t;let r;return r=(t=e).bundleId??"",gk.has(r)&&gC.test(gG(t))});if(0===t.length)return[];let r=gT(e,t);return void 0===r?t:gF(e,r).filter(e=>e.bundleId&&gk.has(e.bundleId))}(e);return r.length?{nodes:r,source:"system-dialog"}:{nodes:function(e){var t;let r,n,a=e.filter(e=>{var t;return t=e.type??"",/(?:^|[.$])[^.]*Dialog$/i.test(t)}),i=e.filter(e=>gP.test(e.identifier??"")),o=a.length?[...a,...i]:(r=(t=i).some(e=>gO.test(e.identifier??"")),n=t.some(e=>!gO.test(e.identifier??"")),r&&n?t:[]);if(0===o.length)return[];let s=gT(e,o);return void 0===s?o:gF(e,s)}(e),source:"native-dialog"}}(e),s=o.nodes;if(0===s.length)return null;let l=function(e){let t=new Set,r=[];for(let n of e){let e=gG(n);if(!e||!n.rect||!gU(n))continue;let a=e.trim().toLowerCase();if(!a||t.has(a))continue;t.add(a);let i=tC(n.rect);r.push({label:e,x:i.x,y:i.y,role:function(e,t){var r;let n=(r=e.identifier??"",/(?:^|:)id\/button1$/i.test(r)?"accept":/(?:^|:)id\/button2$/i.test(r)?"dismiss":/(?:^|:)id\/button3$/i.test(r)?"neutral":/(?:^|:)id\/permission_allow/i.test(r)?"accept":/(?:^|:)id\/permission_deny/i.test(r)?"dismiss":null);return n||(gL.test(t.trim())?"accept":gR.test(t.trim())?"dismiss":"neutral")}(n,e)})}return r}(s),u=s.filter(e=>gG(e)&&!gU(e)),d=gG((t=u).find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??"")))||gG(t[0]),c=(r=u,n=d,(i=r.map(e=>gG(e)).filter(e=>e&&e!==n)).length?[...new Set(i)].join("\n"):void 0),p=(a=s,a.find(e=>e.bundleId)?.bundleId);return{alert:{...d?{title:d}:{},...c?{message:c}:{},buttons:l.map(e=>e.label),platform:"android",source:o.source,...p?{packageName:p}:{}},buttons:l}}((await eS("snapshot_capture",async()=>await oX(e,{helperWaitForIdleTimeoutMs:0,includeHiddenContentHints:!1}),{backend:"android",purpose:"alert"})).nodes)}function gW(e,t,r){return{kind:"alertHandled",platform:"android",action:e,handled:!0,alert:t,button:r,...e$(`Alert ${e}ed`)}}async function gz(e){var t;let{req:r,logPath:n,session:a,device:i}=e,o="accept"===(t=r.positionals?.[0])||"dismiss"===t||"wait"===t?t:"get",s=a?"frontmost-app"===a.surface?{surface:"frontmost-app"}:{bundleId:a.appBundleId,surface:a.surface}:{};if(!dK("alert",i))return dM("UNSUPPORTED_OPERATION","alert is not supported on this device");if("android"===i.platform){let t=eR(r.positionals?.[1])??1e4;return gZ(e,await gV(i,o,{timeoutMs:t}))}if("macos"===i.platform){let t=async e=>await lc(e,s);return await gK(e,o,t)}let l={verbose:r.flags?.verbose,logPath:n,traceLogPath:a?.trace?.outPath,requestId:r.meta?.requestId},u=async e=>await n6(i,{command:"alert",action:e,appBundleId:a?.appBundleId},l);return await gK(e,o,u)}async function gK(e,t,r){if("wait"===t)return await gJ(e,r);let n="accept"===t||"dismiss"===t?t:"get";return"accept"===n||"dismiss"===n?await gX(e,n,r):gZ(e,await r("get"))}async function gJ(e,t){let r=eR(e.req.positionals?.[1])??1e4,n=Date.now();for(;Date.now()-n<r;){try{return gZ(e,await t("get"))}catch{}await ex(300)}return dM("COMMAND_FAILED","alert wait timed out")}async function gX(e,t,r){var n,a;let i,o,s=Date.now();for(;Date.now()-s<2e3;){try{return gZ(e,await r(t))}catch(t){o=t;let e=String(t?.message??"").toLowerCase();if(!e.includes("alert not found")&&!e.includes("no alert"))break}await ex(300)}throw(n=o)instanceof P&&(a=n,(i=String(a?.message??"").toLowerCase()).includes("alert not found")||i.includes("no alert"))?new P(n.code,n.message,{...n.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."}):n}function gZ(e,t){return c3(e.sessionStore,e.session,e.req,t),{ok:!0,data:t}}async function gY(e){let{req:t,logPath:r,sessionStore:n,session:a,device:i,parsed:o}=e,{setting:s,state:l,permissionTarget:u,latitude:d,longitude:c}=o;if(!dK("settings",i))return dM("UNSUPPORTED_OPERATION","settings is not supported on this device");if("macos"===i.platform&&!tl(s))return dM("INVALID_ARGS",tb(s));let p=a?.appBundleId,f="permission"===s?[s,l,u??"",t.positionals?.[3]??"",p??""]:"location"===s&&"set"===l?[s,l,d??"",c??"",p??""]:[s,l,p??""],m=await dI(i,"settings",f,t.flags?.out,{...d1(r,t.flags,p,a?.trace?.outPath)});return c3(n,a,t,m??{setting:s,state:l}),{ok:!0,data:m??{setting:s,state:l}}}async function gQ(e){return await g1({...e,command:"snapshot",unsupportedMessage:"snapshot is not supported on this device",execute:async({runtime:e,sessionName:t,req:r,snapshotScope:n})=>{let a=await e.capture.snapshot({session:t,interactiveOnly:r.flags?.snapshotInteractiveOnly,compact:r.flags?.snapshotCompact,depth:r.flags?.snapshotDepth,scope:n,raw:r.flags?.snapshotRaw,forceFull:r.flags?.snapshotForceFull});return{data:a,record:{kind:"snapshot",nodes:a.nodes.length,truncated:a.truncated}}}})}async function g0(e){return await g1({...e,command:"diff",unsupportedMessage:"diff is not supported on this device",execute:async({runtime:e,sessionName:t,req:r,snapshotScope:n})=>{let a=await e.capture.diffSnapshot({session:t,interactiveOnly:r.flags?.snapshotInteractiveOnly,compact:r.flags?.snapshotCompact,depth:r.flags?.snapshotDepth,scope:n,raw:r.flags?.snapshotRaw});return{data:a,record:{kind:"diff",mode:"snapshot",baselineInitialized:a.baselineInitialized,summary:a.summary}}}})}async function g1(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,{session:i,device:o}=await c1(a,r,t.flags);if(!dK(e.command,o))return dM("UNSUPPORTED_OPERATION",e.unsupportedMessage);let s=function(e,t){let r;if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return dM("INVALID_ARGS","Ref scope requires an existing snapshot in session.");let n=tP(e.trim());if(!n)return dM("INVALID_ARGS",`Invalid ref scope: ${e}`);for(let e of[t.snapshot,...t.snapshotScopeSource?[t.snapshotScopeSource]:[]]){let t=tO(e.nodes,n);if(r=t?tB(t,e.nodes):void 0)break}return r?{ok:!0,scope:r}:dM("COMMAND_FAILED",`Ref ${e} not found or has no label`)}(t.flags?.snapshotScope,i);return s.ok?await c2(i,o,async()=>{var l,u;let d,c=function(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,session:i,device:o,snapshotScope:s}=e;return tI({backend:function(e){let{req:t,logPath:r,session:n,device:a,snapshotScope:i}=e;return{platform:a.platform,captureSnapshot:async(e,o)=>{let s=await d5({device:a,session:n,flags:t.flags,outPath:o?.outPath??t.flags?.out,logPath:r,snapshotScope:i});return{snapshot:s.snapshot,analysis:s.analysis,androidSnapshot:s.androidSnapshot,freshness:s.freshness,appName:n?.appBundleId?n.appName??n.appBundleId:void 0,appBundleId:n?.appBundleId}}}}({req:t,logPath:n,session:i,device:o,snapshotScope:s}),...pa("snapshot"),sessions:co({sessionName:r,getSession:()=>a.get(r),recordOptions:{includeSnapshot:!0},setRecord:e=>{var n;let i=function(e){if(!e.snapshot)throw new P("UNKNOWN","snapshot runtime did not produce session state");return e}(e),s=a.get(r);a.set(r,function(e){var t,r;let{current:n,sessionName:a,device:i,record:o,refScopedSnapshot:s}=e,l=(t=n,r=o,s&&r.snapshot?.nodes.length===0&&t?.snapshot!==void 0),u=l?n.snapshot:o.snapshot,d=function(e){let{session:t,sessionName:r,device:n,snapshot:a,appBundleId:i}=e;return t?{...t,snapshot:a}:{name:r,device:n,createdAt:Date.now(),appBundleId:i,snapshot:a,actions:[]}}({session:n,sessionName:a,device:i,snapshot:u,appBundleId:o.appBundleId});return d.snapshotScopeSource=function(e){let{current:t,keepCurrentSnapshot:r,refScopedSnapshot:n}=e;if(n)return r?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}({current:n,keepCurrentSnapshot:l,refScopedSnapshot:s}),o.appName&&(d.appName=o.appName),d}({current:s,sessionName:r,device:o,record:i,refScopedSnapshot:(n=t,n.flags?.snapshotScope?.trim().startsWith("@")===!0)}))}})})}({req:t,sessionName:r,logPath:n,sessionStore:a,session:i,device:o,snapshotScope:s.scope}),p=await e.execute({runtime:c,sessionName:r,req:t,snapshotScope:s.scope});return(d=(l={req:t,sessionName:r,sessionStore:a,result:p.record}).sessionStore.get(l.sessionName))&&l.sessionStore.recordAction(d,{command:l.req.command,positionals:l.req.positionals??[],flags:l.req.flags??{},result:"snapshot"===(u=l.result).kind?{nodes:u.nodes,truncated:u.truncated}:{mode:u.mode,baselineInitialized:u.baselineInitialized,summary:u.summary}}),{ok:!0,data:p.data}}):s}let g2=ek.snapshot,g3={snapshot:async({req:e,sessionName:t,logPath:r,sessionStore:n})=>await gQ({req:e,sessionName:t,logPath:r,sessionStore:n}),diff:async({req:e,sessionName:t,logPath:r,sessionStore:n})=>e.positionals?.[0]!=="snapshot"?dM("INVALID_ARGS","diff currently supports only: diff snapshot"):await g0({req:e,sessionName:t,logPath:r,sessionStore:n}),wait:async({req:e,sessionName:t,logPath:r,sessionStore:n})=>await pI({req:e,sessionName:t,logPath:r,sessionStore:n}),alert:async({req:e,sessionName:t,logPath:r,sessionStore:n})=>{let{session:a,device:i}=await c1(n,t,e.flags);return await c2(a,i,async()=>await gz({req:e,logPath:r,sessionStore:n,session:a,device:i}))},settings:async({req:e,sessionName:t,logPath:r,sessionStore:n})=>{let a,i,o,s=(a=e.positionals?.[0]?.toLowerCase(),i=e.positionals?.[1]?.toLowerCase(),o=e.positionals?.[2]?.toLowerCase(),a&&i&&("permission"!==a||o)&&("location"!==a||"set"!==i||e.positionals?.[2]&&e.positionals?.[3])?{ok:!0,parsed:{setting:a,state:i,permissionTarget:o,latitude:e.positionals?.[2],longitude:e.positionals?.[3]}}:dM("INVALID_ARGS",tf));if(!s.ok)return s;let{session:l,device:u}=await c1(n,t,e.flags);return await c2(l,u,async()=>await gY({req:e,logPath:r,sessionStore:n,session:l,device:u,parsed:s.parsed}))}};async function g4(e){let t=e.req.command;if(!g2.has(t))return null;let r=g3[t];return r?await r(e):dM("COMMAND_FAILED",`Snapshot command has no handler: ${t}`)}async function g5(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,leaseRegistry:i,invoke:o,invokeReplayAction:s,androidAdbExecutor:l,contextFromFlags:u}=e,d=await fn({req:t,leaseRegistry:i});if(d)return d;let c=await gM({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:o,invokeReplayAction:s,androidAdbExecutor:l});if(c)return c;let p=await g4({req:t,sessionName:r,logPath:n,sessionStore:a});if(p)return p;let f=await fa({req:t,sessionName:r,logPath:n,sessionStore:a,contextFromFlags:u});if(f)return f;let m=await f6({req:t,sessionName:r,sessionStore:a,logPath:n});if(m)return m;let h=await pL({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:o});if(h)return h;let w=await fe({req:t,sessionName:r,logPath:n,sessionStore:a,contextFromFlags:u});return w||null}function g8(e,t){if(!t)return[];let r=[],n=e.device,a=t.platform;if(a&&!rz(n.platform,a)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(n.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==n.platform||t.udid!==n.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==n.platform||t.serial!==n.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==n.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),a=n.simulatorSetPath?.trim();("ios"!==n.platform||"simulator"!==n.kind||e!==a)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=ea(t.androidDeviceAllowlist);"android"===n.platform&&e.has(n.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function g6(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let g9=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],g7=ek.selectorValidationExempt,ye=ek.leaseAdmissionExempt,yt=new Set(ye);async function yr(e){let{req:t,sessionName:r,sessionStore:n}=e,a=n.get(r);if(a)return`device:${a.device.id}`;if("open"===t.command||dk(t.flags))try{let e=await os(t.flags??{});return`device:${e.id}`}catch{}return`session:${r}`}let yn=new WeakMap;async function ya(e){var t,r;let n,a,i,{sessionStore:o,leaseRegistry:s}=e,l=(n={...(t=function(e){let t=eL(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,n=eE(r);if(r&&!n)throw new P("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!n)throw new P("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let a=e.session||"default";return a.startsWith(`${n}:`)?{...e,meta:{...e.meta,tenantId:n,sessionIsolation:t}}:{...e,session:`${n}:${a}`,meta:{...e.meta,tenantId:n,sessionIsolation:t}}}(e.req)).flags??{}},((a=tv(t.command,n))||!t.flags)&&a?{...t,flags:n}:t);eb({level:"info",phase:"request_start",data:{session:l.session,command:l.command,tenant:l.meta?.tenantId,isolation:l.meta?.sessionIsolation}});let u=l.command;!function(e,t){if(ye.has(e.command)||e.meta?.sessionIsolation!=="tenant")return;let r=fr(e);t.assertLeaseAdmission({tenantId:r.tenantId,runId:r.runId,leaseId:r.leaseId,backend:r.leaseBackend})}(l,s);let d=function(e,t){var r;let n,a=e.session||"default";if(r=e,"string"==typeof(n=r.flags?.session)&&n.trim().length>0||"default"!==a||t.has(a))return a;let i=t.toArray();return 1===i.length?i[0].name:a}(l,o),c=yt.has(u)?null:await yr({req:l,sessionName:d,sessionStore:o}),p=(r=s,(i=yn.get(r))||(i=new Map,yn.set(r,i)),i);return{req:l,command:u,sessionName:d,throwIfCanceled:()=>ra(l.meta?.requestId),runLocked:async e=>(ra(l.meta?.requestId),c)?await rH(p,c,async()=>(ra(l.meta?.requestId),await e())):await e()}}function yi(e){var t,r;let{scope:n,logPath:a,sessionStore:i,trackDownloadableArtifact:o}=e;n.throwIfCanceled();let s=i.get(n.sessionName);s&&(!function(e){var t,r;let n,a;if(!((a=(r=e).recording)&&"ios"===r.device.platform&&!1!==a.showTouches))return;let i=e.recording,o=(t=e.device.id,(n=nV.get(t))?{sessionId:n.sessionId,alive:nX(n.child.pid)}:null);if(!i.runnerSessionId){o?.alive&&(i.runnerSessionId=o.sessionId);return}if(!o?.alive){i.invalidatedReason??="iOS runner session exited during recording";return}o.sessionId!==i.runnerSessionId&&(i.invalidatedReason??="iOS runner session restarted during recording")}(s),i.set(n.sessionName,s));let l=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let n={...e.flags??{}},a=t?g8(t,n):function(e,t,r){var n,a;let i=[];if(void 0!==e.platform&&t&&(n=e.platform,a=t,n&&a&&n!==a&&("apple"===n?!rW(a):"apple"!==a||!rW(n)))&&i.push({key:"platform",value:e.platform}),"open"===r)return i;for(let t of g9){let r=e[t];"string"==typeof r&&r.trim().length>0&&i.push({key:t,value:r})}return i}(n,e.meta?.lockPlatform,e.command);if(0===a.length)return!t&&e.meta?.lockPlatform&&void 0===n.platform&&(n.platform=e.meta.lockPlatform),{...e,flags:n};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(n,a),n.platform=t.device.platform):function(e,t){for(let t of g9)delete e[t];t&&(e.platform=t)}(n,e.meta?.lockPlatform),{...e,flags:n};throw new P("INVALID_ARGS",`${e.command} cannot override session lock policy with ${a.map(g6).join(", ")}. Unset those selectors or remove the request lock policy.`)}(n.req,s),u=e=>(function(e,t,r){let n=eI();if(!t.ok){eb({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=eA({force:!0})??void 0;return{ok:!1,error:k(new P(M(t.error.code),t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:n.diagnosticId,logPath:e})}}return eb({level:"info",phase:"request_success"}),eA(),{ok:!0,data:function(e,t,r){var n,a;let i;if(!t)return t;let o=(n=e,i=Array.isArray((a=t).artifacts)?[...a.artifacts]:[],"screenshot"!==n.command||i.some(e=>e?.field==="path")||"string"!=typeof a.path||i.push({field:"path",path:a.path,localPath:n.meta?.clientArtifactPaths?.path,fileName:f.basename(n.meta?.clientArtifactPaths?.path??a.path)}),i.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===o.length?t:{...t,artifacts:o.map(t=>{let n=t.path;return{field:t.field,artifactId:r({artifactPath:n,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(l,e,o);if(s?.recording?.invalidatedReason&&"record"!==(t=n.command)&&"close"!==t)return{type:"response",response:u({ok:!1,error:{code:"COMMAND_FAILED",message:s.recording.invalidatedReason}})};!s||l.meta?.lockPolicy||(r=n.command,g7.has(r))||function(e,t){let r=g8(e,t);if(0!==r.length){var n;let t,a,i;throw new P("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(n=e).device.platform,a=n.device.name.trim(),i=n.device.id,`${t} device "${a}" (${i})`)} and cannot be used with ${r.map(g6).join(", ")}. Use a different --session name or close this session first.`)}}(s,l.flags);let d=(e,t,r)=>{let n;return{...d1(a,e,t,r,n=eI().requestId),requestId:n}};return{type:"scope",scope:{req:l,sessionName:n.sessionName,existingSession:s,finalize:u,contextFromFlags:d,handlerContextFromFlags:(e,t,r)=>({...d(e,t,r),surface:i.get(n.sessionName)?.surface})}}}async function yo(e){let{lockedScope:t,logPath:r,sessionStore:n}=e,a=n.get(t.sessionName);if(!a)return t.finalize({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let i=await cY({req:t.req,session:a,sessionName:t.sessionName,logPath:r,sessionStore:n,contextFromFlags:t.contextFromFlags});return t.finalize(i)}function ys(e){eb({level:"error",phase:"request_failed",data:{error:e instanceof Error?e.message:String(e)}});let t=eI(),r=eA({force:!0})??void 0;return{ok:!1,error:k(e,{diagnosticId:t.diagnosticId,logPath:r})}}async function yl(e,t=5e3){await Promise.all(e.map(async e=>{let r;await new Promise(n=>{r=setTimeout(()=>{!function(e){e.destroyConnections?.();let t="closeAllConnections"in e?e.closeAllConnections:void 0;if("function"==typeof t)return t.call(e);let r="closeIdleConnections"in e?e.closeIdleConnections:void 0;"function"==typeof r&&r.call(e)}(e),n()},t);try{e.close(()=>n())}catch{n()}}),r&&clearTimeout(r)}))}function yu(e){l.existsSync(e)&&l.unlinkSync(e)}function yd(e){if(!l.existsSync(e))return null;try{let t=JSON.parse(l.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function yc(e){let t=yd(e);if(!t||t.pid===process.pid)try{l.existsSync(e)&&l.unlinkSync(e)}catch{}}function yp(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}(async function(e={}){let t,r,n=e.env??process.env,a=e.stdout??process.stdout,i=e.stderr??process.stderr,s=e.exit??(e=>process.exit(e)),{baseDir:u,infoPath:d,lockPath:c,logPath:p,sessionsDir:h}=eH(n.AGENT_DEVICE_STATE_DIR),w=eK(n.AGENT_DEVICE_DAEMON_SERVER_MODE);var g,y,v,I=h;if(l.existsSync(I))for(let e of l.readdirSync(I,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=f.join(I,e.name,ax);if(l.existsSync(t))try{let e=aM(l.readFileSync(t,"utf8"));if(e&&function(e){let t,r=ep(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let n=em(e.pid);return!!n&&!!((t=n.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||n===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{ak(t)}}let A=new aN(h),S=new iq({maxActiveSimulatorLeases:yp(n.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:yp(n.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:yp(n.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:yp(n.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),b=e_(),_=o.randomBytes(24).toString("hex"),N=ep(process.pid)??void 0,x=eD(),M=function(e){let{logPath:t,token:r,androidAdbProvider:n,appleRunnerProvider:a,appleToolProvider:i,linuxToolProvider:o,appLogProvider:s,recordingProvider:l,deviceInventoryProvider:u,trackDownloadableArtifact:d}=e,{sessionStore:c,leaseRegistry:p}=e;async function f(e){let m=!!(e.meta?.debug||e.flags?.verbose);return await ev({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:m,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:k(new P("UNAUTHORIZED","Invalid token"))};try{return await od(u,async()=>{let u=await ya({req:e,sessionStore:c,leaseRegistry:p});return await u.runLocked(async()=>{let e=yi({scope:u,logPath:t,sessionStore:c,trackDownloadableArtifact:d});if("response"===e.type)return e.response;let m=e.scope;return await dU({req:m.req,existingSession:m.existingSession,providers:{androidAdbProvider:n,appleRunnerProvider:a,appleToolProvider:i,linuxToolProvider:o,appLogProvider:s,recordingProvider:l}},async e=>{let n=await g5({req:m.req,sessionName:m.sessionName,logPath:t,sessionStore:c,leaseRegistry:p,invoke:f,invokeReplayAction:function(e){let{parentScope:t,providerScope:r,handleRequest:n,deps:a}=e;return async e=>{var i,o;if(i=e,o=t,!(i.session===o.sessionName&&ek.replayScopedAction.has(i.command)))return await n(e);if(e.token!==a.token)return{ok:!1,error:k(new P("UNAUTHORIZED","Invalid token"))};try{let i=await ya({req:e,sessionStore:a.sessionStore,leaseRegistry:a.leaseRegistry});if(i.sessionName!==t.sessionName)return await n(e);let o=yi({scope:i,logPath:a.logPath,sessionStore:a.sessionStore,trackDownloadableArtifact:a.trackDownloadableArtifact});if("response"===o.type)return o.response;let s=o.scope,l=await g5({req:s.req,sessionName:s.sessionName,logPath:a.logPath,sessionStore:a.sessionStore,leaseRegistry:a.leaseRegistry,invoke:n,androidAdbExecutor:r.androidAdbExecutor,contextFromFlags:s.handlerContextFromFlags});if(l)return s.finalize(l);return await yo({lockedScope:s,logPath:a.logPath,sessionStore:a.sessionStore})}catch(e){return ys(e)}}}({parentScope:m,providerScope:e,handleRequest:f,deps:{logPath:t,token:r,sessionStore:c,leaseRegistry:p,trackDownloadableArtifact:d}}),androidAdbExecutor:e.androidAdbExecutor,contextFromFlags:m.handlerContextFromFlags});return n?m.finalize(n):await yo({lockedScope:m,logPath:t,sessionStore:c})})})})}catch(e){return ys(e)}})}return f}({logPath:p,token:_,sessionStore:A,leaseRegistry:S,trackDownloadableArtifact:id}),O=async e=>{await ev({command:"daemon",session:"daemon",logPath:p,debug:!0},async()=>{eb({level:"error",phase:"daemon_fatal",data:{error:e instanceof Error?e.message:String(e)}}),eA({force:!0})})},E=async e=>{let t=hc(e,e.name).catch(t=>{i.write(`Daemon session teardown error (${e.name}): ${t instanceof Error?t.message:String(t)}
|
|
66
|
+
`)});await Promise.race([t,ex(5e3).then(()=>{i.write(`Daemon session teardown timed out (${e.name}).
|
|
67
|
+
`)})]),A.writeSessionLog(e),A.delete(e.name)},C=async()=>{let e=A.toArray();await Promise.all(e.map(E))},L=async()=>{let e,t,r=[];if("http"!==w){let t,n,a=(t=new Set,(n=m.createServer(e=>{t.add(e),e.on("close",()=>t.delete(e));let r="",n=0,a=new Set,i=!1,o=()=>{if(!i&&0!==n){for(let e of(i=!0,a))t7(e);eb({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:n}}),(async()=>{try{let e=Date.now()+15e3;for(;n>0&&Date.now()<e&&(await nK(),!(n<=0));)await ex(200)}catch(e){eb({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:n}})}})()}};e.setEncoding("utf8"),e.on("close",o),e.on("error",o),e.on("data",async t=>{let i=(r+=t).indexOf("\n");for(;-1!==i;){let t,o,s=r.slice(0,i).trim();if(r=r.slice(i+1),0===s.length){i=r.indexOf("\n");continue}n+=1;try{let e=JSON.parse(s);if(o=t6(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),t9(o),rt(o))throw rn();t=await M(e)}catch(e){t={ok:!1,error:k(e)}}finally{n-=1,o&&(a.delete(o),re(o))}e.destroyed||e.write(`${JSON.stringify(t)}
|
|
68
|
+
`),i=r.indexOf("\n")}})})).destroyConnections=()=>{for(let e of t)e.destroy();t.clear()},n);r.push(a),e=await new Promise((e,t)=>{a.once("error",t),a.listen(0,"127.0.0.1",()=>{a.off("error",t);let r=a.address();"object"==typeof r&&r?.port?e(r.port):t(new P("COMMAND_FAILED","Failed to bind socket server"))})})}if("socket"!==w){let e=await i$({handleRequest:M,token:_});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let n=e.address();"object"==typeof n&&n?.port?t(n.port):r(new P("COMMAND_FAILED","Failed to bind HTTP server"))})})}return{servers:r,socketPort:e,httpPort:t}};if(!function(e,t,r){l.existsSync(e)||l.mkdirSync(e,{recursive:!0});let n=JSON.stringify(r,null,2),a=()=>{try{return l.writeFileSync(t,n,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(a())return!0;let i=yd(t);if(i?.pid&&i.pid!==process.pid&&eg(i.pid,i.processStartTime))return!1;try{l.unlinkSync(t)}catch{}return a()}(u,c,{pid:process.pid,version:b,startedAt:Date.now(),processStartTime:N}))return i.write("Daemon lock is held by another process; exiting.\n"),s(0),null;let R=[];try{let e,n=await L();R=n.servers,t=n.socketPort,r=n.httpPort,g=t,y=r,v={socketPort:g,httpPort:y,token:_,version:b,codeSignature:x,processStartTime:N},l.existsSync(u)||l.mkdirSync(u,{recursive:!0}),l.writeFileSync(p,""),e=v.socketPort&&v.httpPort?"dual":v.httpPort?"http":"socket",l.writeFileSync(d,JSON.stringify({port:v.socketPort,httpPort:v.httpPort,transport:e,token:v.token,pid:process.pid,version:v.version,codeSignature:v.codeSignature,processStartTime:v.processStartTime,stateDir:u},null,2),{mode:384}),g&&a.write(`AGENT_DEVICE_DAEMON_PORT=${g}
|
|
69
|
+
`),y&&a.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${y}
|
|
70
|
+
`)}catch(t){let e=D(t);for(let t of(i.write(`Daemon error: ${e.message}
|
|
71
|
+
`),R))try{t.close(()=>{})}catch{}return yu(d),yc(c),s(1),null}let T=!1,$=async(e={})=>{T||(T=!0,e.cause&&await O(e.cause),await yl(R),await C(),await nJ(),yu(d),yc(c),s(e.exitCode??0))};return!1!==e.registerProcessHandlers&&(process.on("SIGINT",()=>{$()}),process.on("SIGTERM",()=>{$()}),process.on("SIGHUP",()=>{$()}),process.on("uncaughtException",e=>{let t=e instanceof P?e:D(e);i.write(`Daemon error: ${t.message}
|
|
72
|
+
`),$({exitCode:1,cause:e})}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof P?t:D(t);i.write(`Daemon error: ${r.message}
|
|
73
|
+
`),$({exitCode:1,cause:t})})),{httpPort:r,shutdown:$,socketPort:t,token:_}})().catch(e=>{let t=D(e);process.stderr.write(`Daemon error: ${t.message}
|
|
74
|
+
`),process.exit(1)});
|