agent-device 0.14.8 → 0.14.9
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 +1 -2
- package/android-snapshot-helper/README.md +4 -2
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.8.apk → agent-device-android-snapshot-helper-0.14.9.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.9.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.8.manifest.json → agent-device-android-snapshot-helper-0.14.9.manifest.json} +6 -6
- package/dist/src/6108.js +17 -17
- package/dist/src/7462.js +1 -1
- package/dist/src/9542.js +1 -1
- package/dist/src/9639.js +2 -2
- package/dist/src/9818.js +1 -1
- package/dist/src/android-adb.d.ts +11 -2
- package/dist/src/android-snapshot-helper.d.ts +12 -2
- package/dist/src/cli.js +46 -46
- package/dist/src/command-schema.js +1 -0
- package/dist/src/contracts.d.ts +1 -0
- package/dist/src/finders.d.ts +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/internal/daemon.js +20 -20
- package/dist/src/selectors.d.ts +1 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +86 -13
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +160 -93
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +1 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +3 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +15 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +1 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +185 -0
- package/package.json +1 -1
- package/server.json +3 -3
- package/skills/agent-device/SKILL.md +11 -1
- package/skills/dogfood/SKILL.md +3 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.8.apk.sha256 +0 -1
- package/skills/react-devtools/SKILL.md +0 -48
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
let e,t,r;import a from"node:crypto";import i,{promises as n}from"node:fs";import s from"node:path";import{spawn as o}from"node:child_process";import l from"node:http";import{fileURLToPath as d,pathToFileURL as u}from"node:url";import"node:https";import c from"node:os";import{once as f}from"node:events";import{Transform as p}from"node:stream";import{pipeline as m}from"node:stream/promises";import h from"node:fs/promises";import{setTimeout as g}from"node:timers/promises";import{PNG as w}from"pngjs";import y from"node:net";import{resolveUserPath as v}from"../3267.js";import{withDiagnosticsScope as S,flushDiagnosticsToSessionFile as I,getDiagnosticsMeta as A,emitDiagnostic as b}from"../7599.js";import{trimRuntimeValue as _,readProcessCommand as N,resolveRuntimeTransportHints as M,isAgentDeviceDaemonProcess as x,readProcessStartTime as D}from"../8656.js";import{withAndroidAdbProvider as k,pullAndroidAdbFile as P,resolveAndroidAdbProvider as R,resolveAndroidAdbExecutor as L}from"../9639.js";import{androidDeviceForSerial as O,runAndroidAdb as E,resolveIosSimulatorDeviceSetPath as C,classifyAndroidAppTarget as $,resolveIosDeviceDeepLinkBundleId as T,parseSerialAllowlist as F,getAndroidAppState as U,resolveAndroidSerialAllowlist as V,isDeepLinkTarget as G,openAndroidApp as j,formatAndroidInstalledPackageRequiredMessage as q}from"../8809.js";import{streamAndroidLogcatWithAdb as H,captureAndroidLogcatWithAdb as B}from"../6642.js";import{toAppErrorCode as K,asAppError as z,normalizeError as W,AppError as J}from"../9152.js";import{sleep as Z,resolveTimeoutMs as X}from"../4829.js";import{runCmdBackground as Y,runCmd as Q}from"../9818.js";import{IOS_RUNNER_CONTAINER_BUNDLE_IDS as ee,resolveAppleSimulatorSetPathForSelector as et,buildSimctlArgs as er,dispatchCommand as ea,refSnapshotFlagGuardResponse as ei,buttonTag as en,handleSnapshotCommands as es,withTargetDeviceResolutionScope as eo,shutdownSimulator as el,stopIosRunnerSession as ed,localCommandPolicy as eu,getClickButtonValidationError as ec,createRequestCanceledError as ef,isNavigationSensitiveAction as ep,registerRequestAbort as em,errorResponse as eh,resolveIosDevicectlHint as eg,snapshotAndroid as ew,resolveTargetDevice as ey,withKeyedLock as ev,setSessionSnapshot as eS,dispatchGetViaRuntime as eI,assertAndroidPressStayedInApp as eA,stopAllIosRunnerSessions as eb,runMacOsAlertAction as e_,createAgentDevice as eN,getAndroidScreenSize as eM,readTextForNode as ex,captureSnapshot as eD,dispatchIsViaRuntime as ek,resolveClickButton as eP,IOS_DEVICECTL_DEFAULT_HINT as eR,buildSnapshotState as eL,context_contextFromFlags as eO,captureSnapshotData as eE,resolveRequestTrackingId as eC,isRequestCanceled as e$,resolvePayloadInput as eT,abortAllIosRunnerSessions as eF,getRunnerSessionSnapshot as eU,createUnsupportedArtifactAdapter as eV,isAndroidEscapeError as eG,markRequestCanceled as ej,dispatchFindReadOnlyViaRuntime as eq,runIosRunnerCommand as eH,ensureDeviceReady as eB,readInfoPlistString as eK,clearRequestCanceled as ez,buildSimctlArgsForDevice as eW,getActiveAndroidSnapshotFreshness as eJ,parseXmlDocumentSync as eZ,resolveFrontmostMacOsApp as eX,IOS_SIMCTL_LIST_TIMEOUT_MS as eY,matchesPlatformSelector as eQ,isCommandSupportedOnDevice as e0,listIosDeviceApps as e1,isApplePlatform as e2,listIosDeviceProcesses as e8,normalizePlatformSelector as e3,getRequestSignal as e5,decodePng as e4,buildScrollGesturePlan as e6,markAndroidSnapshotFreshness as e9}from"../6108.js";import{normalizeTenantId as e7,withSuccessText as te,resolveDaemonPaths as tt,resolveSessionIsolationMode as tr,resolveDaemonServerMode as ta,successText as ti,resolveInstallFromSourceResultTarget as tn,resolveDeployResultTarget as ts,resolveDaemonCodeSignature as to}from"../180.js";import{parseSessionSurface as tl}from"../7462.js";import{runBatch as td,mergeParentFlags as tu}from"../1231.js";import{splitSelectorFromArgs as tc,findNearestHittableAncestor as tf,extractNodeText as tp,splitIsSelectorArgs as tm,tryParseSelectorChain as th,resolveSelectorChain as tg,resolveRefLabel as tw,buildSelectorChainForNode as ty,normalizeType as tv,pruneGroupNodes as tS}from"../940.js";import{attachRefs as tI,centerOfRect as tA}from"../4057.js";import{findBestMatchesByLocator as tb,parseFindArgs as t_}from"../7556.js";import{readVersion as tN}from"../9671.js";function tM(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 tx(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tD=/^-?\d+(\.\d+)?$/,tk=/^[^\s"\\]+$/,tP=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tR=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tL=new Map([["--delay-ms","delayMs"]]);function tO(e){return"click"===e||"press"===e}function tE(e){return"type"===e||"fill"===e}function tC(e){return tT(e,tF)}function t$(e){return JSON.stringify(e)}function tT(e,t){return t(e)?e:t$(e)}function tF(e){return tU(e)&&e.startsWith("@")||tD.test(e)}function tU(e){return tk.test(e)}function tV(e,t){let r=t.flags??{};if(tO(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}tE(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tG(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",tT(t.metroHost,tU)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tT(t.bundleUrl,tU)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tT(t.launchUrl,tU)))}function tj(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tT(r,tU)),a))e.push(tC(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 tq(e,t){let r=[],a={},i=tO(e)?tP:"swipe"===e?tR:tE(e)?tL:void 0;for(let n=0;n<t.length;n+=1){let s=t[n];if(tO(e)&&"--double-tap"===s){a.doubleTap=!0;continue}if(tO(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=tB(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 tH(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=tB(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 tB(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tK(e,t){for(let r of t.positionals??[])e.push(tC(r));t.flags?.relaunch&&e.push("--relaunch"),tG(e,t.runtime)}class tz{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=tz.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 tW)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),b({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=${t$(e.device.name)}${a} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(tO(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tC(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tC(a)),tV(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tC(r)),tV(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tC(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tC(a)),e.positionals.length>1&&t.push(tC(i)),tV(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tC(r)),t.push(tC(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tC(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",tC(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tC(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 tK(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tT(r,tU)),tG(t,e.flags),t.join(" ")}if("record"===e.command)return tj(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tC(r));return tV(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
2
|
-
`}(e,this.buildOptimizedActions(e));i.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=
|
|
3
|
-
`)}function
|
|
4
|
-
`)},flush:()=>{a&&(i(a),a="")}}}function
|
|
5
|
-
`,recoveredLineCount:o.length}}async function t9(e,t,r,a,i,n){let s="active",l=o("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return er(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",t4(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:i}),{stdio:["ignore","pipe","pipe"]}),d=t0(r,{redactionPatterns:a});"number"==typeof l.pid&&tX(n,l.pid);let u=t1(l,r,{endStreamOnClose:!0,writer:d}).then(e=>(0!==e.exitCode&&(s="failed"),tY(n),e));return{backend:"ios-simulator",getState:()=>s,startedAt:Date.now(),wait:u,stop:async()=>{l.killed||l.kill("SIGINT"),await tQ(u),l.killed||l.kill("SIGKILL"),await tQ(u),tY(n)}}}async function t7(e,t,r,a){let i="active",n=o("log",["stream","--style","compact","--predicate",t4(e)],{stdio:["ignore","pipe","pipe"]}),s=t0(t,{redactionPatterns:r});"number"==typeof n.pid&&tX(a,n.pid);let l=t1(n,t,{endStreamOnClose:!0,writer:s}).then(e=>(0!==e.exitCode&&(i="failed"),tY(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tQ(l),n.killed||n.kill("SIGKILL"),await tQ(l),tY(a)}}}async function re(e,t,r,a){let i="active",n=o("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),s=t0(t,{redactionPatterns:r});"number"==typeof n.pid&&tX(a,n.pid);let l=t1(n,t,{endStreamOnClose:!0,writer:s}).then(e=>(0!==e.exitCode&&(i="failed"),tY(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tQ(l),n.killed||n.kill("SIGKILL"),await tQ(l),tY(a)}}}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 t3(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 tZ(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),tJ));if(!o)return null;let l=await t8(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 re(e.id,n,s,a):await t9(e.id,t,n,s,e.simulatorSetPath,a);if("android"===e.platform)return t2(t),await t5(e.id,t,n,s,a);if("macos"===e.platform)return await t7(t,n,s,a);throw n.end(),new J("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rA(e){let t=await t6({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 tQ(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 E(e,["shell","echo","ok"],{allowFailure:!0,timeoutMs:1e3});r.adbAvailable=0===t.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await E(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 Q("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 Q("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await Q("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 J("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new J("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 Q("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=s.join(e.tempDir,t);if(!i.existsSync(r))throw new J("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rL(e){let t=await Q("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new J("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 J("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 J("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new J("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 J("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 J("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 J("INVALID_ARGS",`Archive entry must stay inside top-level "${s}" bundle: ${n}`)}for(let t of(await Q("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new J("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rO(e){if(e.includes("\0"))throw new J("INVALID_ARGS",`Invalid archive entry: ${e}`);if(s.posix.isAbsolute(e))throw new J("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=s.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new J("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rE=X(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 J("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 p({transform(e,t,r){u();let a=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e,t);(o+=a)>0x80000000?r(new J("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")):r(null,e)}});e.on("aborted",()=>{d(new J("COMMAND_FAILED","Artifact transfer was interrupted"))}),u(),m(e,c,l).then(()=>d(),e=>d(e))})}async function r$(e,t){if(e.destroy(),!e.closed)try{await f(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 J("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new J("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 J("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 J("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(c.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 J("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 J("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=W(new J("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=W(new J(K(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=e7(r.tenantId);if(!e){let e=W(new J("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(u(a).href)}catch(e){throw new J("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 J("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 l.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 J("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 J("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new J("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 J("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 J("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 J("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 J("INVALID_ARGS","Invalid params: source must specify either artifactId or artifactName, not both");if(!i&&n&&!s)throw new J("INVALID_ARGS","Invalid params: source.artifactName is required when source.runId is specified");if(!i&&!s)throw new J("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 J("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 J("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 J("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=eC(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:s},em(s);let d=()=>{i.writableFinished||ej(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=W(t);rH(i,rq(a.id??null,-32e3,e.message,e),rB(e.code))}finally{ez(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=W(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 J("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new J("UNAUTHORIZED","Artifact belongs to a different tenant");if(!i.existsSync(r.artifactPath))throw rx(e),new J("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=W(e);t.statusCode=rB(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rx(n)}),u.pipe(t)}catch(r){let e=W(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?W(new J("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 J("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=e7(e.tenantId);if(!r)throw new J("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=r8(e.runId);if(!i)throw new J("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 J("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new J("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 J("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=e7(e.tenantId);if(!r)throw new J("INVALID_ARGS","tenant isolation requires tenant id.");let a=r8(e.runId);if(!a)throw new J("INVALID_ARGS","tenant isolation requires run id.");let i=r3(e.leaseId);if(!i)throw new J("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new J("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new J("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 J("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 J("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=e7(t),i=r8(r);if(t&&!a)throw new J("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new J("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 J("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let r6=X(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),r9=new Map;async function r7(e){let t=await h.mkdtemp(s.join(c.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 h.rm(t,{recursive:!0,force:!0}),e}}async function ae(e,t){let r=r9.get(e);if(!r)throw new J("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new J("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),r9.delete(e),await h.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 h.stat(e);await h.mkdir(t,{recursive:!0});let a=s.join(t,s.basename(e));return r.isDirectory()?await h.cp(e,a,{recursive:!0}):await h.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 J("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await eB(e.session.device),e.session.device}if(!r)throw new J("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await ey(e.flags??{});return await eB(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 J("INVALID_ARGS","install_from_source requires a source payload");switch(t.kind){case"url":if(!t.url||0===t.url.trim().length)throw new J("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 J("INVALID_ARGS","install_from_source path source requires a non-empty path");return t;case"github-actions-artifact":throw new J("UNSUPPORTED_OPERATION","install_from_source github-actions-artifact sources require a compatible remote daemon");default:throw new J("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 J("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(!e0("install",d))return eh("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let u=e5(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 J("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=te(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 J("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=te(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:W(e)}}}function an(e){return`Installed: ${tn(e)}`}async function as(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new J("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:W(e)}}}let ao=X(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),al=X(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function ad(e,t,r){return t||au(r)?null:eh("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 ey(e.flags??{}):await am(e.session.device);return!1!==e.ensureReady&&await eB(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 ey(t)}catch(e){if(!(e instanceof J)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await ey({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!==M(e)}async function a_(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=M(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 E(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 E(e,a,{allowFailure:!0});if(0!==i.exitCode){let e=aT(i.stdout,i.stderr);throw new J("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 E(e,["shell","run-as",t,"mkdir","-p","shared_prefs"]),await E(e,["shell","run-as",t,"tee",ag],{stdin:r.trimEnd()})}catch(a){let e=z(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 J("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 Q("xcrun",eW(e,["spawn",e.id,"defaults","write",t,av,"-string",`${r.host}:${r.port}`])),await Q("xcrun",eW(e,["spawn",e.id,"defaults","write",t,aS,"-string",r.scheme]))}async function aR(e,t){await Q("xcrun",eW(e,["spawn",e.id,"defaults","delete",t,av]),{allowFailure:!0}),await Q("xcrun",eW(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}
|
|
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
|
+
`}(e,this.buildOptimizedActions(e));i.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=tK.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return s.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return s.join(this.sessionsDir,tK.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return s.join(this.sessionsDir,tK.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return y(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return tK.expandHome(e.saveScriptPath);i.existsSync(this.sessionsDir)||i.mkdirSync(this.sessionsDir,{recursive:!0});let t=tK.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return s.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let a=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(a.length>0&&(tL(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tL(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=tN(r);if(a.length>0){t.push({...r,positionals:[e,a]});continue}}if("get"===r.command){let a=r.positionals?.[0];if("text"===a||"attrs"===a){t.push({...r,positionals:[a,e]});continue}}}if(tL(r.command)||"fill"===r.command||"get"===r.command){let a=r.result?.refLabel;"string"==typeof a&&a.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:a.trim()},result:{scope:a.trim()}})}t.push(r)}return t}}let tz=["platform","device","udid","serial","out","verbose","metroHost","metroPort","bundleUrl","launchUrl","snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw","screenshotFullscreen","screenshotMaxSize","relaunch","saveScript","noRecord","fps","quality","hideTouches","count","intervalMs","delayMs","holdMs","jitterPx","doubleTap","clickButton","pauseMs","pattern"],tW="app-log.pid";function tJ(e){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t))return{pid:Number.parseInt(t,10)};try{let e=JSON.parse(t);if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}function tZ(e,t){if(!e)return;let r=s.dirname(e);i.existsSync(r)||i.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:x(t)??void 0,command:_(t)??void 0};i.writeFileSync(e,`${JSON.stringify(a)}
|
|
3
|
+
`)}function tX(e){if(e&&i.existsSync(e))try{i.unlinkSync(e)}catch{}}async function tY(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}function tQ(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],a="",i=a=>{(!(r.length>0)||r.some(e=>a.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(a,t.redactionPatterns))};return{onChunk:e=>{let t=`${a}${e}`.split("\n");for(let e of(a=t.pop()??"",t))i(`${e}
|
|
4
|
+
`)},flush:()=>{a&&(i(a),a="")}}}function 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
6
|
`:aA}function aO(e,t){return aL(e).replace("</map>",`${t}
|
|
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"
|
|
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 J("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return _(e)}}function aG(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new J("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 eh("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(e3(a.flags?.platform)??l?.platform??o?.device.platform);if(!d)return eh("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 eh("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:_(t?.metroHost),metroPort:aG(t?.metroPort),bundleUrl:_(t?.bundleUrl),launchUrl:_(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)?eh("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 eX();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=L(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 J("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 J("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 J("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 J?new J(u.code,u.message,{...u.details??{},metric:"fps",package:d},u):new J("COMMAND_FAILED",`Failed to sample Android fps for ${d}`,{metric:"fps",package:d},u)}}async function a3(e,t,r={}){let a=L(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=L(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=L(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 J("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 J("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 J?new J(r.code,r.message,{...r.details??{},metric:e,package:t},r):new J("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 G(t)?"macos"===e.platform?void 0:"device"===e.kind?T(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||G(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||!G(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&&G(t)?r:void 0)}function il(e){return eh("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=tl(r);if(!az.has(e))throw new J("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new J("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new J("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let n=r?tl(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new J("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return eh(e instanceof J?e.code:"INVALID_ARGS",String(e.message))}}function iu(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&G(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"===$(r)?il(q(r)):null:null}async function ic(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:s,existingSession:o}=e;await eB(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 J("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!aF.includes(e));if(i)throw new J("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 J("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new J("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 J("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 J("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 J("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=z(t);return eh(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 ed(t.id),await ea(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||G(d)||await ea(r,"open",[l],a.flags?.out,{...eO(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:{...eO(l,n.flags,v??g?.appBundleId,y)}})}await a_({device:d,appId:v,runtime:h});let S=Date.now();await ea(d,"open",c,n.flags?.out,{...eO(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),e$(n.meta?.requestId)){let e=ef();return eh(e.code,e.message,e.details)}g&&e9(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,...ti(`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 eh("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&&G(r)?il("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===$(r)?il(q(r)):null:null}({shouldRelaunch:n,openTarget:s,platform:t.flags?.platform==="android"?"android":void 0});if(o)return o;let l=await ey(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 ev(im,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return eh("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 E(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 el(t):await iv(t)}catch(t){let e=W(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function iI(e){if(await ed(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await e_("dismiss",t).catch(t=>{b({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),e2(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 eh("SESSION_NOT_FOUND","No active session");n.appLog&&await rb(n.appLog),t.positionals&&t.positionals.length>0&&(e2(n.device.platform)&&await iI(n),await ea(n.device,"close",t.positionals,t.flags?.out,{...eO(a,t.flags,n.appBundleId,n.trace?.outPath)}),await af(n.device,ao)),e2(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,...ti(`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:te({session:r,shutdown:s},`Closed: ${r}`)}:{ok:!0,data:{session:r,...ti(`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 eh("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):tz.expandHome(c);if(!i.existsSync(a))return eh("INVALID_ARGS",`App binary not found: ${a}`);let d=await ap({session:o,flags:l,ensureReady:!1});if(!e0(r,d))return eh("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=te(e,(p=e,`Installed: ${p.appName??ts(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 td(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 J("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 Q("xcrun",er(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:eY});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 Q("xcrun",er(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new J("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 J("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 Q("xcrun",er(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:eY});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=C(e.iosSimulatorDeviceSet);if(!r)return eh("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:eB});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=z(t);return eh(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=V(t.flags?.androidDeviceAllowlist),a=e3(t.flags?.platform),i=et({simulatorSetPath:C(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=z(t);return eh(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(!e0("apps",s))return eh("UNSUPPORTED_OPERATION","apps is not supported on this device");let o=t.flags?.appsFilter??"all";if(e2(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=e3(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return eh("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=e2(i?.device.platform)&&function(e,t){if(!t)return!1;if(!au(e))return!0;let r=e3(e?.platform);return!(r&&!eQ(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 eh("SESSION_NOT_FOUND",iC);if("macos"===s&&!l)return eh("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 eh("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 eh("SESSION_NOT_FOUND",iC);if("macos"===d.platform)return eh("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"===(e3(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!o)return eh("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=z(r);if(o&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return eh("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 eh("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(o&&l){if("android"!==e.platform||"emulator"!==e.kind)return eh("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 eh("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 eB(e)}else("android"!==e.platform||!0!==e.booted)&&await eB(e);return e0("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:eh("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=eZ(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 J("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,l,u;if("ios"!==e.platform||"device"!==e.kind)throw new J("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:tx(c.map(e=>s.basename(d(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=eZ(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,l=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:l,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(c.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 J("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 Q("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
|
-
${e.stderr}`.toLowerCase();return t.includes("_lockkperf")||t.includes("could not lock kperf")||t.includes("likely another session just started")}(s))break}return r}async function i8(e,t,r){let a=await n.stat(e.tracePath).catch(()=>null);if(!(a?.isDirectory()===!0?(await n.readdir(e.tracePath).catch(()=>[])).length>0:(a?.size??0)>0))throw new
|
|
10
|
-
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?
|
|
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):eh("INVALID_ARGS",nv):eh("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 eh("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return eh("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:W(a)}}}async function nk(e,t,r){if(e.appLog)return eh("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return eh("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:W(e)}}}async function nP(e,t,r){if(!e.appLog)return eh("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 eh("SESSION_NOT_FOUND","network requires an active session");if(!e0("network",i.device))return eh("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!nS.includes(n))return eh("INVALID_ARGS",nI);let s=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(s)||s<1||s>200)return eh("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 eh("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}:eh("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 J("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 J("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 J("INVALID_ARGS",`Invalid env directive on line ${t}: expected "env KEY=VALUE".`);let i=r.slice(0,a);if(!nL.test(i))throw new J("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 J("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 J("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 J("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 J("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;em(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=z(e);return eh(t.code,t.message)}).finally(()=>{ez(i)});try{return"number"==typeof n?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{c=!0,ej(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)||b({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await d(a)}catch(e){b({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:z(e).message}})}}}async function nK(e){return await Promise.race([e.then(()=>!0),g(2e3).then(()=>!1)])}async function nz(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:n}=e;if((t.positionals?.length??0)===0)return eh("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=tz.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 J("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[n]}return[]}if(r=e,!nH.test(r)&&(a=n,!nH.test(a)))throw new J("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 J("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=tz.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=z(t);return eh(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 eC(`${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=tc(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(!(tO(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),tO(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}=tm(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=nJ(e.positionals??[]);r&&t.push(r)}return tx(t).filter(e=>e.trim().length>0)})(t).map(e=>th(e)).filter(e=>null!==e);if(0===s.length)return null;let o=tO(t.command)||"fill"===t.command,l=tO(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=tg(d.nodes,e,{platform:n.device.platform,requireRect:o,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=ty(r.node,n.device.platform,{action:tO(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tO(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=tM(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}=tm(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 ea(e.device,"snapshot",[],t.flags?.out,{...eO(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),s=n?.nodes??[],o={nodes:tI(t.flags?.snapshotRaw?s:tS(s)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return eS(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 eh("INVALID_ARGS","replay requires a path");let d="",u=new Set;try{var c;let e;d=tz.expandHome(l,t.meta?.cwd);let f=i.readFileSync(d,"utf8"),p=f.trimStart()[0];if("{"===p||"["===p)return eh("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 J("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 J("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=tH(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=tH(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tO(a)){let e=tq(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=tq(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=tq(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 J("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 eh("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 eh("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 J("INVALID_ARGS",`Invalid -e entry "${r}": expected KEY=VALUE.`);let a=r.slice(0,e);if(!nL.test(a))throw new J("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=${t$(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",tC(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tK(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tT(r,tU));return tG(t,e.flags),t.join(" ")}if("record"===e.command)return tj(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tC(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(tC(r));return tV(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=z(t);return eh(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,tu(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=>tC(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(!e0(n,f))return eh("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await ea(f,n,s,t.flags?.out,{...eO(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 eh("INVALID_ARGS","clipboard requires a subcommand: read or write");let d=await ap({session:n,flags:s,ensureReady:!0});if(!e0("clipboard",d))return eh("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let u=await ea(d,"clipboard",t.positionals??[],t.flags?.out,{...eO(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"!==e3((t.flags??{}).platform)?await n6({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):eh("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=eT(s,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tz.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,s]}):eh("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 eh("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:u,value:c,timeoutMs:f}=t_(o);if(!d)return eh("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return eh("INVALID_ARGS","find accepts only one of --first or --last");let p=await eq({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 eh("SESSION_NOT_FOUND","No active session. Run open first.");let h=m?.device??await ey(t.flags??{});m||await eB(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&&!eJ(m))return{nodes:v};let{snapshot:n}=await eD({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&&(eS(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=tb(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=tp(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),eh("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 eh("COMMAND_FAILED","find did not match any element");let D="click"===u||"focus"===u||"fill"===u||"type"===u?tf(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(tb(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 Z(300)}return eh("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 ex({device:s,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eO(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?tA(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 eh("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?tA(t.node.rect):null;if(!l)return eh("COMMAND_FAILED","matched element has no bounds");let d=await ea(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eO(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 eh("INVALID_ARGS","find type requires text");let d=t.node.rect?tA(t.node.rect):null;if(!d)return eh("COMMAND_FAILED","matched element has no bounds");await ea(s,"focus",[String(d.x),String(d.y)],a.flags?.out,{...eO(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let u=await ea(s,"type",[r],a.flags?.out,{...eO(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=`
|
|
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
|
+
${e.stderr}`.toLowerCase();return t.includes("_lockkperf")||t.includes("could not lock kperf")||t.includes("likely another session just started")}(s))break}return r}async function i8(e,t,r){let a=await n.stat(e.tracePath).catch(()=>null);if(!(a?.isDirectory()===!0?(await n.readdir(e.tracePath).catch(()=>[])).length>0:(a?.size??0)>0))throw new W("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 i3(e,t,r,a,i){let n=["xctrace","export","--input",r,"--xpath",`/trace-toc/run/data/table[@schema="${a}"]`,"--output",i],s=await Y("xcrun",n,{allowFailure:!0,timeoutMs:15e3});if(0!==s.exitCode)throw new W("COMMAND_FAILED",`Failed to export iOS device ${a} data`,{cmd:"xcrun",args:n,exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr,appBundleId:t,deviceId:e.id,hint:no(s.stdout,s.stderr)})}async function i5(e,t,r,a,i){try{return await i3(e,t,r,a,i),!0}catch{return!1}}async function i4(e){let t=eJ(e),r=iG(t,"activity-monitor-process-live");if(0===r.length)throw new W("COMMAND_FAILED","Failed to parse xctrace activity-monitor-process-live schema");let a=r.indexOf("pid"),i=r.indexOf("process"),n=r.indexOf("cpu-total"),s=r.indexOf("memory-real");if(a<0||i<0||n<0||s<0)throw new W("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let o=iV(t,e=>"row"===e.name),l=[],d=new Map;for(let e of o){var u,c;let t=e.children;if(0===t.length)continue;for(let e of t){let t=iU(e.children,e=>"pid"===e.name&&"string"==typeof e.attributes.id);if(t?.attributes.id){let e=Number(t.text);d.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&d.set(e.attributes.id,{numberValue:ij(e),processName:ns(e)})}let r=iq(t[a],d),o=(u=t[i],c=d,u?u.attributes.ref?c.get(u.attributes.ref)?.processName??null:ns(u):null);null!==r&&Number.isFinite(r)&&o&&l.push({pid:r,processName:o,cpuTimeNs:iq(t[n],d),residentMemoryBytes:iq(t[s],d)})}return l}async function i6(e,t){let r="macos"===e.platform?await nr(t):await na(e,t),a="macos"===e.platform?s.join(r,"Contents","Info.plist"):s.join(r,"Info.plist"),i=await eB(a,"CFBundleExecutable");if(!i)throw new W("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?s.join(r,"Contents","MacOS",i):s.join(r,i)}}async function i9(e,t){let r=await i7(e,t),a=await ne(e,t),i=await ne(e,t),n=nt(await i4(a.xml),r,t,e),s=nt(await i4(i.xml),r,t,e),o=i.capturedAtMs-a.capturedAtMs;if(o<=0)throw new W("COMMAND_FAILED",`Invalid Activity Monitor sample window for ${t}`,{appBundleId:t,deviceId:e.id});if(null===n.cpuTimeNs||null===s.cpuTimeNs||null===s.residentMemoryBytes)throw new W("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 nn({usagePercent:Math.max(0,s.cpuTimeNs-n.cpuTimeNs)/(1e6*o)*100,residentMemoryKb:s.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:s.matchedProcesses,cpuMethod:iZ,memoryMethod:iX})}async function i7(e,t){let r=(await e0(e,"all")).find(e=>e.bundleId===t);if(!r)throw new W("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new W("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let a=r.url.replace(/\/$/,""),i=l(a),n=(await e2(e)).filter(e=>e.executable.startsWith(`${a}/`));if(0===n.length)throw new W("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,deviceId:e.id,appBundlePath:i,hint:"Run open <app> for this session again to ensure the iOS app is active, then retry perf."});return n}async function ne(e,t){let r=await n.mkdtemp(s.join(u.tmpdir(),"agent-device-ios-perf-")),a=s.join(r,"sample.trace"),i=s.join(r,"activity-monitor-process-live.xml");try{let r=await i1({device:e,appBundleId:t,tracePath:a,template:"Activity Monitor",duration:"1s",allProcesses:!0,failureMessage:`Failed to record iOS device Activity Monitor sample for ${t}`});return await i3(e,t,a,"activity-monitor-process-live",i),{capturedAtMs:r.capturedAtMs,xml:await n.readFile(i,"utf8")}}finally{await n.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function nt(e,t,r,a){let i=new Set(t.map(e=>e.pid)),n=new Set(t.map(e=>s.basename(l(e.executable)))),o=e.filter(e=>i.has(e.pid)||n.has(e.processName));if(0===o.length)throw new W("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:a.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let d=new Map;for(let e of o){let t=d.get(e.pid);if(!t){d.set(e.pid,e);continue}d.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:nl(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:nl(t.residentMemoryBytes,e.residentMemoryBytes)})}let u=[...d.values()],c=u.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=u.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:c.length>0?c.reduce((e,t)=>e+t,0):null,residentMemoryBytes:f.length>0?f.reduce((e,t)=>e+t,0):null,matchedProcesses:tM(u.map(e=>e.processName))}}async function nr(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await Y("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new W("COMMAND_FAILED",`Failed to resolve macOS app bundle for ${e}`,{appBundleId:e,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let a=r.stdout.split("\n").map(e=>e.trim()).find(e=>e.endsWith(".app"));if(!a)throw new W("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function na(e,t){let r=ez(e,["get_app_container",e.id,t,"app"]),a=await Y("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new W("COMMAND_FAILED",`Failed to resolve iOS simulator app container for ${t}`,{appBundleId:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Ensure the iOS simulator app is installed and booted, then retry perf."});let i=a.stdout.trim();if(0===i.length)throw new W("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return i}async function ni(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:ez(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let a=e.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!a)continue;let i=Number(a[1]),n=Number(a[2]),s=Number(a[3]),o=a[4].trim();Number.isFinite(i)&&Number.isFinite(n)&&Number.isFinite(s)&&t.push({pid:i,cpuPercent:n,rssKb:s,command:o})}return t})((await Y("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let i;return r=e.command,a=t,i=function(e){let[t=""]=e.trim().split(/\s+/,1);return t}(r),!!(a.executablePath&&(r===a.executablePath||i===a.executablePath||r.startsWith(`${a.executablePath} `)))||s.basename(i)===a.executableName})}function nn(e){return{cpu:{usagePercent:aJ(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 ns(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function no(e,t){let r=eh(e,t);if(r)return r;let a=`${e}
|
|
10
|
+
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?eP:a.includes("timed out")?"Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.":"Ensure the iOS device is unlocked, trusted, visible to xctrace, and the target app stays active while perf samples it."}function nl(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function nd(e,t={}){var r,a,i;let n,s,o,l,d=(o=(s=(n=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===aB&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:aB,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:s.durationMs,lastMeasuredAt:s.measuredAt,method:aB,sampleCount:n.length,samples:n}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:aB},{session:r.name,platform:r.device.platform,device:r.device.name,deviceId:r.device.id,metrics:{startup:o,fps:{available:!1,reason:"Dropped-frame sampling is currently available only on Android."},memory:{available:!1,reason:aK},cpu:{available:!1,reason:aK}},sampling:{startup:{method:aB,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:a4,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:a5,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"},fps:{method:aX,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:iH,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:iH,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:iX,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:iZ,description:"Recent CPU usage snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"percent"}};let a="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:iJ,description:`Resident memory snapshot from ${a}`,unit:"kB"},cpu:{method:iW,description:`Recent CPU usage snapshot from ${a}`,unit:"percent"}}}(r)}});return"android"!==(a=e).device.platform&&"ios"!==a.device.platform&&"macos"!==a.device.platform||(e.appBundleId?"android"===e.device.platform?await nu(d,e,t):await nc(d,e):(i=d,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.",i.metrics.fps={available:!1,reason:l},i.metrics.memory={available:!1,reason:l},i.metrics.cpu={available:!1,reason:l})),d}async function nu(e,t,r){let a=await nf(t,r);e.metrics.memory=nh(a.memory),e.metrics.cpu=nh(a.cpu),e.metrics.fps=ng(nh(a.fps),t)}async function nc(e,t){let r=await np(t);e.metrics.memory=nh(r.memory),e.metrics.cpu=nh(r.cpu),e.metrics.fps=ng(nh(r.fps),t)}async function nf(e,t){let r=e.appBundleId,a={adb:t.androidAdb},[i,n,s]=await Promise.allSettled([a9(e.device,r,a),a6(e.device,r,a),a8(e.device,r,a)]);return{memory:i,cpu:n,fps:s}}async function np(e){let t=e.appBundleId,r=await nm(iQ(e.device,t)),a=await nm(iY(e.device,t));if("fulfilled"===a.status){let e=a.value;return{memory:{status:"fulfilled",value:e.memory},cpu:{status:"fulfilled",value:e.cpu},fps:r}}return{memory:{status:"rejected",reason:a.reason},cpu:{status:"rejected",reason:a.reason},fps:r}}async function nm(e){try{return{status:"fulfilled",value:await e}}catch(e){return{status:"rejected",reason:e}}}function nh(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=z(e.reason);return{available:!1,reason:t.message,error:t}}function ng(e,t){var r,a;let i,n;if(!0!==e.available)return e;let s=(r=t.actions,i=nw((a=e).windowStartedAt),n=nw(a.windowEndedAt)??nw(a.measuredAt),void 0===i||void 0===n?[]:r.filter(e=>e.ts>=i&&e.ts<=n).map(e=>({command:e.command,at:new Date(e.ts).toISOString(),offsetMs:Math.max(0,Math.round(e.ts-i)),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===s.length?e:{...e,relatedActions:s}}function nw(e){if("string"!=typeof e)return;let t=Date.parse(e);return Number.isFinite(t)?t:void 0}let ny=["path","start","stop","doctor","mark","clear"],nv=`logs requires ${ny.slice(0,-1).join(", ")}, or ${ny.at(-1)}`,nS=["dump","log"],nI=`network requires ${nS.join(" or ")}`,nA=["summary","headers","body","all"],nb=`network include mode must be one of: ${nA.join(", ")}`;async function n_(e){let{req:t}=e;return"perf"===t.command?nN(e):"logs"===t.command?nM(e):"network"===t.command?nR(e):null}async function nN(e){let{sessionName:t,sessionStore:r,androidAdbExecutor:a}=e,i=r.get(t);if(!i)return em("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await nd(i,{androidAdb:a})}}catch(e){return{ok:!1,error:z(e)}}}async function nM(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return em("SESSION_NOT_FOUND","logs requires an active session");if(!eQ("logs",n.device))return em("UNSUPPORTED_OPERATION","logs is not supported on this device");let s=(t.positionals?.[0]??"path").toLowerCase(),o=!!t.flags?.restart;return ny.includes(s)?o&&"clear"!==s?em("INVALID_ARGS","logs --restart is only supported with logs clear"):"path"===s?function(e,t,r){let a=r.resolveAppLogPath(t),n=function(e){if(!i.existsSync(e))return{exists:!1,sizeBytes:0};let t=i.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(a);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android",sizeBytes:n.sizeBytes,modifiedAt:n.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}(n,r,a):"doctor"===s?nx(n,r,a):"mark"===s?function(e,t,r){let a,n=e.positionals?.slice(1).join(" ")??"",s=r.resolveAppLogPath(t);return ry(s),a=`[agent-device][mark][${new Date().toISOString()}] ${n.trim()||"marker"}
|
|
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=`
|
|
14
14
|
import Foundation
|
|
15
15
|
import AVFoundation
|
|
16
16
|
|
|
@@ -34,13 +34,13 @@ Task {
|
|
|
34
34
|
|
|
35
35
|
semaphore.wait()
|
|
36
36
|
exit(exitCode)
|
|
37
|
-
`.trim();async function su(e,t={}){let r,a=t.pollMs??150,n=t.attempts??12,s=0;for(let t=0;t<n;t+=1){let t=0;try{t=i.statSync(e).size}catch{t=0}if(t>0&&t===r){if((s+=1)>=2)return}else s=0;r=t,await
|
|
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 J&&"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 Z(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(d(import.meta.url)),r=[d(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 J("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(c.tmpdir(),"agent-device-record-overlay-")),l=s.join(o,`input${s.extname(t)||".mp4"}`),d=s.join(o,s.basename(t)),u=s.join(o,"home"),f=s.join(o,"module-cache");i.copyFileSync(t,l),i.mkdirSync(u,{recursive:!0}),i.mkdirSync(f,{recursive:!0});try{await Q("xcrun",["swift",r,"--input",l,"--output",d,...a],{timeoutMs:12e4,env:{...process.env,HOME:u,CLANG_MODULE_CACHE_PATH:f}}),await sf(d),i.copyFileSync(d,t)}catch(a){let e=a instanceof J?a:new J("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new J("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 E(O(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 Z(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 Z(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 Z(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=O(a),l=await P(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(b({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;b({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:n,outPath:s,attempt:e+1}})}e<1&&await Z(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 b({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 eh("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(b({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 eh("COMMAND_FAILED",s)}async function sC(e){let t,r,{deps:a,device:i,recording:n}=e;b({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(b({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(),eh("COMMAND_FAILED",e);await sb({recording:n,deps:a,targetLabel:"Android recording"})}if(await o(),t)return eh("COMMAND_FAILED",t);if(r)return eh("COMMAND_FAILED",r);return null;async function o(){let e=await s_(i.id,["shell","rm","-f",n.remotePath],{allowFailure:!0});b({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){b({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 eh("COMMAND_FAILED",`failed to start recording: ${sI(a)}`);b({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 eh("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 eh("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 eh("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){b({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 ee)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 eh("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){b({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 Z(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",eW(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 eh("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 eh("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==f&&(!Number.isInteger(f)||f<5||f>10))return eh("INVALID_ARGS","quality must be an integer between 5 and 10");if(!e0("record",l))return eh("UNSUPPORTED_OPERATION","record is not supported on this device");let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,m=tz.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 eh("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 eh("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 eh("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 eh("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?eh("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:Q,runCmdBackground:Y,runIosRunnerCommand:eH,waitForStableFile:su,isPlayableVideo:sc,trimRecordingStart:sy,resizeRecording:sS,overlayRecordingTouches:sv},s=a.get(r),o=s?.device??await ey(t.flags??{});s||await eB(o);let l=s??{name:r,device:o,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return eh("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 eh("INVALID_ARGS","trace requires start|stop");let n=a.get(r);if(!n)return eh("SESSION_NOT_FOUND","No active session");if("start"===e){if(n.trace)return eh("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(n),r=tz.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 eh("INVALID_ARGS","no active trace");let l=n.trace.outPath;if(t.positionals?.[1]){let e=tz.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),b({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??{},...ti(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}),ep(a)&&e9(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 eM(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){b({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:eh("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 J("SESSION_NOT_FOUND","No active session. Run open first.");return eN({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 ea(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 ea(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 ea(r.device,"type",[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),artifacts:eV("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&&(eS(t,r.snapshot),e.sessionStore.set(e.sessionName,t))}},policy:eu()})}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 eh("SESSION_NOT_FOUND","No active session. Run open first.");let o=on(n,s);if(o)return o;if(!e0("press",n.device))return eh("UNSUPPORTED_OPERATION","press is not supported on this device");let l=eP(r.flags),d=en(l);if("primary"!==l){let e=ec({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 eh(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:eh("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 eA(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&&!e0("fill",i.device))return eh("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!i)return eh("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:eh("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:eh("INVALID_ARGS","fill requires text after coordinates")}}let a=tc(e,{preferTrailingValue:!0});if(!a)return{ok:!1,response:eh("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:eh("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 eh("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=z(t);if(eG(e))throw e;return{ok:!1,error:W(t)}}}async function oh(e,t){if(!eJ(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){b({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 eD({device:e.device,session:e,flags:n,outPath:n.out,logPath:s.logPath??"",androidFreshnessMode:i.androidFreshnessMode});return eS(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}=tA(r.rect),n=await E(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))],{allowFailure:!0});if(0!==n.exitCode)return b({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 b({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 oA(t,t.appBundleId)))return b({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return b({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 b({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 tI(tS((await ew(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 Z(500)}return!o_(await oS(e))}async function oA(e,t){for(let r=0;r<12;r+=1){if((await U(e.device)).package===t)return!0;await Z(500)}return(await U(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:ei});if(t)return t;switch(e.req.command){case"type":return await oM({...e,captureSnapshotForSession:og});case"get":return await eI(e);case"is":return await ek(e);default:return null}}async function oM(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return eh("SESSION_NOT_FOUND","No active session. Run open first.");if(!e0("type",i.device))return eh("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===i.device.platform&&i.recording&&"failed"===await ov({session:i}))return eh("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,...ti(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:W(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=e3(t.platform);if(i&&!eQ(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=F(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=eN({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 ea(t.device,"screenshot",[],i,s)):oO(await ea(t.device,"screenshot",[i],void 0,s))}}}({session:t,outputPlacement:i,dispatchContext:o}),artifacts:{resolveInput:async()=>{throw new J("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(c.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(c.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:eu()});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=e4(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"===tv((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=tv(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=tf(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 tv(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)??tw(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:tA(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,w.sync.write(t)),r}function oU(e){let t=[e.type,e.role,e.subrole].map(e=>tv(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=>tv(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(e$(e.meta?.requestId))throw ef()}function o5(e,t,r,a){let i=A().requestId;return{...eO(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 ey(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 ey(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 es({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(!e0(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]?[tz.expandHome(i[0],t.meta?.cwd),...i.slice(1)]:i,o="screenshot"===a&&n?tz.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 ea(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=e6({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??{}}),ep(m)&&e9(c,m),{ok:!0,data:I??{}}}async function lt(e,t,r){let a=eL(await eE({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);eS(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}=tt(process.env.AGENT_DEVICE_STATE_DIR),lf=ta(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,tJ);if(i.existsSync(t))try{let e=tZ(i.readFileSync(t,"utf8"));if(e&&function(e){let t,r=D(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=N(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{tY(t)}}let lm=new tz(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=tN(),lw=a.randomBytes(24).toString("hex"),ly=D(process.pid)??void 0,lv=to(),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 S({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:u,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:W(new J("UNAUTHORIZED","Invalid token"))};try{return await eo(i,async()=>{let r=function(e){let t=tr(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=e7(r);if(r&&!a)throw new J("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new J("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);b({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=eU(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=e3(t);if(void 0!==e.platform&&s&&(a=e3(e.platform),i=s,a&&i&&a!==i&&("apple"===a?!e2(i):"apple"!==i||!e2(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 J("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=A();if(!t.ok){b({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=I({force:!0})??void 0;return{ok:!1,error:W(new J(K(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 b({level:"info",phase:"request_success"}),I(),{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 J("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 k(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 ev(o8,f,p)):(o3(r),await p())})}catch(r){b({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=A(),t=I({force:!0})??void 0;return{ok:!1,error:W(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 S({command:"daemon",session:"daemon",logPath:lu,debug:!0},async()=>{b({level:"error",phase:"daemon_fatal",data:{error:e instanceof Error?e.message:String(e)}}),I({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
|
-
`)});await Promise.race([t,
|
|
40
|
-
`)})]),lm.writeSessionLog(e),lm.delete(e.name)}async function l_(){let e,t,r=[];if("http"!==lf){let t,a,i=(t=new Set,(a=
|
|
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
|
|
37
|
+
`.trim();async function su(e,t={}){let r,a=t.pollMs??150,n=t.attempts??12,s=0;for(let t=0;t<n;t+=1){let t=0;try{t=i.statSync(e).size}catch{t=0}if(t>0&&t===r){if((s+=1)>=2)return}else s=0;r=t,await J(a)}}async function sc(e){try{var t,r;let a,i=await Y("swift",["-",e],{stdin:sd,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
|
|
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
|
+
`)});await Promise.race([t,J(5e3).then(()=>{process.stderr.write(`Daemon session teardown timed out (${e.name}).
|
|
40
|
+
`)})]),lm.writeSessionLog(e),lm.delete(e.name)}async function l_(){let e,t,r=[];if("http"!==lf){let t,a,i=(t=new Set,(a=w.createServer(e=>{t.add(e),e.on("close",()=>t.delete(e));let r="",a=0,i=new Set,n=!1,s=()=>{if(!n&&0!==a){for(let e of(n=!0,i))eG(e);A({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:a}}),(async()=>{try{let e=Date.now()+15e3;for(;a>0&&Date.now()<e&&(await eT(),!(a<=0));)await J(200)}catch(e){A({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:a}})}})()}};e.setEncoding("utf8"),e.on("close",s),e.on("error",s),e.on("data",async t=>{let n=(r+=t).indexOf("\n");for(;-1!==n;){let t,s,o=r.slice(0,n).trim();if(r=r.slice(n+1),0===o.length){n=r.indexOf("\n");continue}a+=1;try{let e=JSON.parse(o);if(s=eE(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:s},i.add(s),ep(s),eC(s))throw ec();t=await lS(e)}catch(e){t={ok:!1,error:z(e)}}finally{a-=1,s&&(i.delete(s),eK(s))}e.destroyed||e.write(`${JSON.stringify(t)}
|
|
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
42
|
`),r&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${r}
|
|
43
|
-
`)}catch(r){let t=
|
|
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
|
|
45
|
-
`),s({exitCode:1,cause:e})}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof
|
|
43
|
+
`)}catch(r){let t=K(r);for(let r of(process.stderr.write(`Daemon error: ${t.message}
|
|
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
46
|
`),s({exitCode:1,cause:t})})}();
|