agent-device 0.13.3 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -63
- package/android-snapshot-helper/README.md +75 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.1.apk +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.1.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.1.manifest.json +17 -0
- package/dist/src/221.js +4 -0
- package/dist/src/3918.js +29 -29
- package/dist/src/8161.js +3 -3
- package/dist/src/8656.js +1 -1
- package/dist/src/9152.js +1 -1
- package/dist/src/9542.js +2 -2
- package/dist/src/9818.js +1 -1
- package/dist/src/989.js +1 -1
- package/dist/src/android-snapshot-helper.d.ts +182 -0
- package/dist/src/android-snapshot-helper.js +1 -0
- package/dist/src/index.d.ts +19 -0
- package/dist/src/internal/bin.js +413 -69
- package/dist/src/internal/daemon.js +22 -20
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +26 -2
- package/package.json +29 -9
- package/skills/agent-device/SKILL.md +20 -62
- package/skills/dogfood/SKILL.md +9 -168
- package/skills/react-devtools/SKILL.md +15 -31
- package/skills/agent-device/references/bootstrap-install.md +0 -244
- package/skills/agent-device/references/coordinate-system.md +0 -28
- package/skills/agent-device/references/debugging.md +0 -138
- package/skills/agent-device/references/exploration.md +0 -362
- package/skills/agent-device/references/macos-desktop.md +0 -88
- package/skills/agent-device/references/remote-tenancy.md +0 -188
- package/skills/agent-device/references/verification.md +0 -134
- package/skills/dogfood/references/issue-taxonomy.md +0 -83
- package/skills/dogfood/templates/dogfood-report-template.md +0 -52
- package/skills/react-devtools/references/commands.md +0 -91
- package/skills/react-devtools/references/profiling.md +0 -74
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
let e,t,r;import a from"node:crypto";import i,{promises as n}from"node:fs";import o from"node:path";import{spawn as s}from"node:child_process";import l from"node:http";import{fileURLToPath as u,pathToFileURL as d}from"node:url";import"node:https";import c from"node:os";import f from"node:fs/promises";import{setTimeout as p}from"node:timers/promises";import{PNG as m}from"pngjs";import h from"node:net";import{resolveUserPath as g}from"../3267.js";import{resolveInstallFromSourceResultTarget as w,readVersion as y,resolveDaemonCodeSignature as v,normalizeTenantId as I,withSuccessText as S,resolveSessionIsolationMode as A,withDiagnosticsScope as b,resolveDaemonPaths as _,flushDiagnosticsToSessionFile as N,getDiagnosticsMeta as k,resolveDaemonServerMode as x,successText as D,resolveDeployResultTarget as M,emitDiagnostic as P}from"../8161.js";import{trimRuntimeValue as R,readProcessCommand as L,resolveRuntimeTransportHints as O,isAgentDeviceDaemonProcess as E,readProcessStartTime as C}from"../8656.js";import{toAppErrorCode as $,asAppError as T,normalizeError as F,AppError as U}from"../9152.js";import{runCmdBackground as G,runCmd as V}from"../9818.js";import{sleep as j,resolveTimeoutMs as q}from"../4829.js";import{resolveAndroidSerialAllowlist as H,decodePng as B,resolveAppleSimulatorSetPathForSelector as z,buildSimctlArgs as K,dispatchCommand as W,validateAndNormalizeBatchSteps as J,refSnapshotFlagGuardResponse as Z,IOS_RUNNER_CONTAINER_BUNDLE_IDS as X,buttonTag as Y,handleSnapshotCommands as Q,shutdownSimulator as ee,stopIosRunnerSession as et,localCommandPolicy as er,createRequestCanceledError as ea,isNavigationSensitiveAction as ei,registerRequestAbort as en,resolveIosDevicectlHint as eo,getClickButtonValidationError as es,snapshotAndroid as el,resolveTargetDevice as eu,dispatchGetViaRuntime as ed,withKeyedLock as ec,assertAndroidPressStayedInApp as ef,stopAllIosRunnerSessions as ep,parseSerialAllowlist as em,classifyAndroidAppTarget as eh,DEFAULT_BATCH_MAX_STEPS as eg,runMacOsAlertAction as ew,createAgentDevice as ey,getAndroidAppState as ev,getAndroidScreenSize as eI,isDeepLinkTarget as eS,readTextForNode as eA,captureSnapshot as eb,dispatchIsViaRuntime as e_,resolveClickButton as eN,IOS_DEVICECTL_DEFAULT_HINT as ek,buildSnapshotState as ex,openAndroidApp as eD,context_contextFromFlags as eM,captureSnapshotData as eP,resolveRequestTrackingId as eR,isRequestCanceled as eL,adbArgs as eO,resolvePayloadInput as eE,abortAllIosRunnerSessions as eC,getRunnerSessionSnapshot as e$,formatAndroidInstalledPackageRequiredMessage as eT,createUnsupportedArtifactAdapter as eF,isAndroidEscapeError as eU,resolveIosSimulatorDeviceSetPath as eG,markRequestCanceled as eV,dispatchFindReadOnlyViaRuntime as ej,resolveIosDeviceDeepLinkBundleId as eq,response_errorResponse as eH,runIosRunnerCommand as eB,parseCoordinateTarget as ez,ensureDeviceReady as eK,readInfoPlistString as eW,clearRequestCanceled as eJ,buildSimctlArgsForDevice as eZ,getActiveAndroidSnapshotFreshness as eX,parseXmlDocumentSync as eY,resolveFrontmostMacOsApp as eQ,IOS_SIMCTL_LIST_TIMEOUT_MS as e0,listIosDeviceApps as e1,matchesPlatformSelector as e2,isCommandSupportedOnDevice as e3,listIosDeviceProcesses as e8,isApplePlatform as e4,normalizePlatformSelector as e5,getRequestSignal as e9,parseSessionSurface as e6,buildScrollGesturePlan as e7,markAndroidSnapshotFreshness as te}from"../3918.js";import{splitSelectorFromArgs as tt,findNearestHittableAncestor as tr,extractNodeText as ta,splitIsSelectorArgs as ti,tryParseSelectorChain as tn,resolveSelectorChain as to,resolveRefLabel as ts,buildSelectorChainForNode as tl,normalizeType as tu,pruneGroupNodes as td}from"../940.js";import{attachRefs as tc,centerOfRect as tf}from"../4057.js";import{findBestMatchesByLocator as tp,parseFindArgs as tm}from"../7556.js";function th(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 tg(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tw=/^-?\d+(\.\d+)?$/,ty=/^[^\s"\\]+$/,tv=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tI=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tS=new Map([["--delay-ms","delayMs"]]);function tA(e){return"click"===e||"press"===e}function tb(e){return"type"===e||"fill"===e}function t_(e){return tk(e,tx)}function tN(e){return JSON.stringify(e)}function tk(e,t){return t(e)?e:tN(e)}function tx(e){return tD(e)&&e.startsWith("@")||tw.test(e)}function tD(e){return ty.test(e)}function tM(e,t){let r=t.flags??{};if(tA(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}tb(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tP(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",tk(t.metroHost,tD)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tk(t.bundleUrl,tD)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tk(t.launchUrl,tD)))}function tR(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tk(r,tD)),a))e.push(t_(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 tL(e,t){let r=[],a={},i=tA(e)?tv:"swipe"===e?tI:tb(e)?tS:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tA(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tA(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=tE(t[n+1]);if(null!==e){a[s]=e,n+=1;continue}}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:a}}function tO(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=tE(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 tE(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tC(e,t){for(let r of t.positionals??[])e.push(t_(r));t.flags?.relaunch&&e.push("--relaunch"),tP(e,t.runtime)}class t${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=t$.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 tT)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),P({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=o.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=${tN(e.device.name)}${a} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(tA(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(t_(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(t_(a)),tM(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(t_(r)),tM(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(t_(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(t_(a)),e.positionals.length>1&&t.push(t_(i)),tM(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(t_(r)),t.push(t_(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(t_(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",t_(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(t_(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 tC(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tk(r,tD)),tP(t,e.flags),t.join(" ")}if("record"===e.command)return tR(t,e),t.join(" ");for(let r of e.positionals??[])t.push(t_(r));return tM(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:s.length}}async function tX(e,t,r,a,i,n){let o="active",l=s("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return K(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",tJ(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:i}),{stdio:["ignore","pipe","pipe"]}),u=tq(r,{redactionPatterns:a});"number"==typeof l.pid&&tG(n,l.pid);let d=tH(l,r,{endStreamOnClose:!0,writer:u}).then(e=>(0!==e.exitCode&&(o="failed"),tV(n),e));return{backend:"ios-simulator",getState:()=>o,startedAt:Date.now(),wait:d,stop:async()=>{l.killed||l.kill("SIGINT"),await tj(d),l.killed||l.kill("SIGKILL"),await tj(d),tV(n)}}}async function tY(e,t,r,a){let i="active",n=s("log",["stream","--style","compact","--predicate",tJ(e)],{stdio:["ignore","pipe","pipe"]}),o=tq(t,{redactionPatterns:r});"number"==typeof n.pid&&tG(a,n.pid);let l=tH(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tV(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tj(l),n.killed||n.kill("SIGKILL"),await tj(l),tV(a)}}}async function tQ(e,t,r,a){let i="active",n=s("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tq(t,{redactionPatterns:r});"number"==typeof n.pid&&tG(a,n.pid);let l=tH(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tV(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tj(l),n.killed||n.kill("SIGKILL"),await tj(l),tV(a)}}}let t0=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),t1=/https?:\/\/[^\s"'<>\])]+/i,t2=[/\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 t3(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>t4(e)));for(let e of t.entries){let t=t4(e);if(!i.has(t)&&(i.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function t8(e,t){let r=rn(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=rn(t?.maxPayloadChars,2048,64,16384),o=rn(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),u=s.slice(l),d=[];for(let e=u.length-1;e>=0&&d.length<r;e-=1){let t=u[e];if(!t?.trim())continue;let r=function(e,t,r,a,i,n){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=rt(s,["method","httpMethod"]),u=rt(s,["url","requestUrl"]),d=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=t0.exec(o),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=t1.exec(o),h=u??m?.[0];if(!h)return null;let g=d??t9(o)??void 0;if(!(l||f?.[1]||c?.[1]||void 0!==g||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let w={method:p,url:h,status:g,timestamp:t6(o),packetId:t7(o)??void 0,durationMs:re(o)??void 0,raw:ri(o,n),line:r};if("android"===a&&function(e,t,r){let a=t5(t,r,5),i=e.packetId??a.map(e=>t7(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?t5(t,r,12).filter(e=>t7(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>t6(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>t9(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>re(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 ra(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(w.headers=ri(e,n))}if("body"===i||"all"===i){let e=rr(o,s,["requestBody","body","payload","request"]),t=rr(o,s,["responseBody","response"]);e&&(w.requestBody=ri(e,n)),t&&(w.responseBody=ri(t,n))}return w}(u,e,l+e+1,a,i,n);r&&d.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:u.length,matchedLines:d.length,entries:d,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:o}}}function t4(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function t5(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 t9(e){for(let t of t2){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function t6(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 t7(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function re(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 rt(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 rr(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return ra(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 ra(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function ri(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function rn(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function ro(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 rs(e){let t=o.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:ro("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:ro("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rl(e){var t,r,a,n;let o,s,l,u,{device:d,appBundleId:c,appLogState:f,appLogStartedAt:p,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y}=e,v="macos"===d.platform?"macos":"ios"===d.platform?"device"===d.kind?"ios-device":"ios-simulator":"android",I=(t={backend:v,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y},o=rn(t?.maxEntries,25,1,200),s=t?.include??"summary",l=rn(t?.maxPayloadChars,2048,64,16384),u=rn(t?.maxScanLines,4e3,100,2e4),i.existsSync(m)?t8(i.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:s,limits:{maxEntries:o,maxPayloadChars:l,maxScanLines:u}}),S=[],A=await ru({device:d,appBundleId:c,appLogPath:m,appLogState:f});if(A){let e=await tK(d.id,c);if(e){let t=t8(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y});t.entries.length>0&&(I=t3(t,I,h),S.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"===d.platform&&"simulator"===d.kind&&c&&0===I.entries.length){let e=await rc({deviceId:d.id,appBundleId:c,startedAt:p,simulatorSetPath:d.simulatorSetPath,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y});e&&(e.dump.entries.length>0?(I=t3(e.dump,I,h),S.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&&S.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?S.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==f&&0===S.length&&("ios"===d.platform&&"simulator"===d.kind?S.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."):S.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===I.entries.length&&S.push("ios"===(n=d).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:I,notes:S}}async function ru(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 s=function(e){let t=function(e){if(!e||!i.existsSync(e))return null;try{return tU(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}(o.join(o.dirname(a),tF));if(!s)return null;let l=await tz(t.id,r);return l&&l!==s?{reason:"stale-active",trackedPid:s}:null}async function rd(e,t,r,a){rs(r);let n=i.createWriteStream(r,{flags:"a"}),o=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 tQ(e.id,n,o,a):await tX(e.id,t,n,o,e.simulatorSetPath,a);if("android"===e.platform)return tB(t),await tW(e.id,t,n,o,a);if("macos"===e.platform)return await tY(t,n,o,a);throw n.end(),new U("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rc(e){let t=await tZ({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:t8(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 rf(e){await e.stop(),await tj(e.wait)}async function rp(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 e=await V("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await V("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await V("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 V("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await V("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function rm(e){let t=o.dirname(e),r=o.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(o.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let rh=new Map;function rg(e){let t=rh.get(e);if(t&&(clearTimeout(t.timer),rh.delete(e),t.deleteAfterDownload))try{i.rmSync(t.artifactPath,{force:!0})}catch{}}let rw=new Map;function ry(e,t){let r=rw.get(e);if(!r)throw new U("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new U("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function rv(e){let t=rw.get(e);t&&(clearTimeout(t.timer),rw.delete(e),i.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rI(e){let t=await rS(e);await V("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=o.join(e.tempDir,t);if(!i.existsSync(r))throw new U("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rS(e){let t=await V("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new U("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 U("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rA),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 U("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new U("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 U("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 U("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,o=i;if(n!==o&&!n.startsWith(`${o}/`))throw new U("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await V("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new U("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rA(e){if(e.includes("\0"))throw new U("INVALID_ARGS",`Invalid archive entry: ${e}`);if(o.posix.isAbsolute(e))throw new U("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=o.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new U("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rb=q(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function r_(e,t){return new Promise((r,a)=>{let n,o=i.createWriteStream(t),s=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,u=0,d=e=>{if(!l){if(l=!0,n&&clearTimeout(n),e){o.destroy(),i.rmSync(t,{force:!0}),a(e);return}r()}},c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let e=new U("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rb});s(e),o.destroy(e),d(e)},rb)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((u+=t)>0x80000000){let e=new U("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");s(e),o.destroy(e),d(e)}}),e.on("error",d),e.on("aborted",()=>{d(new U("COMMAND_FAILED","Artifact transfer was interrupted"))}),o.on("error",d),o.on("finish",()=>d()),c(),e.pipe(o)})}async function rN(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new U("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new U("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 U("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let n=function(e){let t=e.trim(),r=o.basename(t);if(!r||"."===r||".."===r)throw new U("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),s=(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(o.join(c.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=o.join(s,n);return await r_(e,t),{artifactPath:t,tempDir:s}}let t=o.join(s,"artifact.tar");await r_(e,t);let a=await rI({archivePath:t,tempDir:s,platform:"ios",expectedRootName:n});return i.rmSync(t,{force:!0}),{artifactPath:a,tempDir:s}}catch(e){throw i.rmSync(s,{recursive:!0,force:!0}),e}}let rk=new Set(["agent_device.command","agent-device.command"]),rx=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rD=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rM={"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"},rP=new Set([...rk,...rx,...rD,...Object.keys(rM)]);function rR(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rL(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rO(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rE(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 rC(e,t){let r=e[t];return"string"==typeof r?r:void 0}function r$(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}function rT(e,t){let r="string"==typeof e[t]?e[t].trim():"";if(!r)throw new U("INVALID_ARGS",`Invalid params: source.${t} is required for github-actions-artifact sources`);return r}function rF(e,t){let r=e[t],a="number"==typeof r?r:"string"==typeof r?Number(r):NaN;if(!Number.isInteger(a))throw new U("INVALID_ARGS",`Invalid params: source.${t} must be an integer`);return a}async function rU(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=F(new U("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:rR(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=F(new U($(r.code,"UNAUTHORIZED"),r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:rR(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=I(r.tenantId);if(!e){let e=F(new U("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:rR(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rG(){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=o.isAbsolute(t)?t:o.resolve(t);try{e=await import(d(a).href)}catch(e){throw new U("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 U("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rV(e){let t=await rG(),{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 rj(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/artifacts/"))return void rq(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||rL(i,rR(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rL(i,rR(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rL(i,rR(a.id??null,-32600,"Invalid Request"),400);if(!rP.has(a.method))return void rL(i,rR(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rL(i,rR(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rk.has(e))return{token:rE(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(rx.has(e)){let e,a=rC(t,"platform");if("ios"!==a&&"android"!==a)throw new U("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rE(t,r),session:rC(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rC(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new U("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new U("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 U("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 U("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 U("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=rT(e,"owner"),a=rT(e,"repo"),i=void 0!==e.artifactId,n=void 0!==e.runId,o=void 0!==e.artifactName;if(i&&(n||o))throw new U("INVALID_ARGS","Invalid params: source must specify either artifactId or artifactName, not both");if(!i&&n&&!o)throw new U("INVALID_ARGS","Invalid params: source.artifactName is required when source.runId is specified");if(!i&&!o)throw new U("INVALID_ARGS","Invalid params: source must specify artifactId or artifactName");return i?{kind:"github-actions-artifact",owner:r,repo:a,artifactId:rF(e,"artifactId")}:(n&&(t=rF(e,"runId")),{kind:"github-actions-artifact",owner:r,repo:a,...n?{runId:t}:{},artifactName:rT(e,"artifactName")})}(t);throw new U("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:r$(t,"retentionMs")}}}if(rD.has(e)){let e=rC(t,"materializationId")?.trim();if(!e)throw new U("INVALID_ARGS","Invalid params: materializationId is required");return{token:rE(t,r),session:rC(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rC(t,"requestId"),materializationId:e}}}let a=rM[e];if(a)return{token:rE(t,r),session:rC(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rC(t,"tenantId")??rC(t,"tenant"),runId:rC(t,"runId"),leaseId:rC(t,"leaseId"),leaseTtlMs:r$(t,"ttlMs"),leaseBackend:rC(t,"backend")}};throw new U("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rk.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rL(i,rR(a.id??null,-32602,"Invalid params: command is required"),400);o=eR(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},en(o);let u=()=>{i.writableFinished||eV(o)};e.on("aborted",u),i.on("close",u);let d=await rU(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!d.ok)return void rL(i,d.response,d.statusCode);d.tenantId&&(l.meta={...l.meta,tenantId:d.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rL(i,{jsonrpc:"2.0",id:a.id??null,result:c});rL(i,rR(a.id??null,-32e3,c.error.message,c.error),rO(c.error.code))}catch(t){let e=F(t);rL(i,rR(a.id??null,-32e3,e.message,e),rO(e.code))}finally{eJ(o)}})})}async function rj(e,t,r,i){try{var n;let o,s,l=rE({},e.headers),u=rH(l,i);if(u){t.statusCode=rO(u.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.message,code:u.code}));return}let d=await rU(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let c=await rN(e),f=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:d.tenantId},o=a.randomUUID(),(s=setTimeout(()=>{rv(o)},3e5)).unref(),rw.set(o,{artifactPath:n.artifactPath,tempDir:n.tempDir,tenantId:n.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:f}))}catch(r){let e=F(r);t.statusCode=rO(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rq(e,t,r,a){let n=e.url?.slice("/artifacts/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let o=rE({},e.headers),s=rH(o,a);if(s){t.statusCode=rO(s.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.message,code:s.code}));return}let l=await rU(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:o,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 u=function(e,t){let r=rh.get(e);if(!r)throw new U("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new U("UNAUTHORIZED","Artifact belongs to a different tenant");if(!i.existsSync(r.artifactPath))throw rg(e),new U("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),d=i.createReadStream(u.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),u.fileName&&t.setHeader("content-disposition",`attachment; filename="${u.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=F(e);t.statusCode=rO(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rg(n)}),d.pipe(t)}catch(r){let e=F(r);t.statusCode=rO(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rH(e,t){return t&&e!==t?F(new U("UNAUTHORIZED","Invalid token")):null}function rB(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rz(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rK(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 U("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rW{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=rK(e.backend),r=I(e.tenantId);if(!r)throw new U("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=rB(e.runId);if(!i)throw new U("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(r,i,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,n);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),u={leaseId:a.randomBytes(16).toString("hex"),tenantId:r,runId:i,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+n};return this.leases.set(u.leaseId,u),this.runBindings.set(o,u.leaseId),{...u}}heartbeatLease(e){let t=rz(e.leaseId);if(!t)throw new U("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new U("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=rz(e.leaseId);if(!t)throw new U("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=rK(e.backend),r=I(e.tenantId);if(!r)throw new U("INVALID_ARGS","tenant isolation requires tenant id.");let a=rB(e.runId);if(!a)throw new U("INVALID_ARGS","tenant isolation requires run id.");let i=rz(e.leaseId);if(!i)throw new U("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new U("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new U("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 U("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 U("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=I(t),i=rB(r);if(t&&!a)throw new U("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new U("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 U("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rJ=q(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),rZ=new Map;async function rX(e){let t=await f.mkdtemp(o.join(c.tmpdir(),"agent-device-materialized-"));try{let r=await r0(e.installablePath,o.join(t,"installable")),i=e.archivePath?await r0(e.archivePath,o.join(t,"archive")):void 0,n=a.randomUUID(),s=e.ttlMs??rJ,l=Date.now()+s,u=setTimeout(()=>{rY(n)},s);return rZ.set(n,{rootPath:t,installablePath:r,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:l,timer:u}),{materializationId:n,installablePath:r,...i?{archivePath:i}:{},expiresAt:new Date(l).toISOString()}}catch(e){throw await f.rm(t,{recursive:!0,force:!0}),e}}async function rY(e,t){let r=rZ.get(e);if(!r)throw new U("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new U("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),rZ.delete(e),await f.rm(r.rootPath,{recursive:!0,force:!0})}async function rQ(e){let t=Array.from(rZ.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await rY(e)}))}async function r0(e,t){let r=await f.stat(e);await f.mkdir(t,{recursive:!0});let a=o.join(t,o.basename(e));return r.isDirectory()?await f.cp(e,a,{recursive:!0}):await f.copyFile(e,a),a}async function r1(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 U("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await eK(e.session.device),e.session.device}if(!r)throw new U("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await eu(e.flags??{});return await eK(a),a}async function r2(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);try{let e,n,o,s=(n=function(e){let t=e.meta?.installSource;if(!t)throw new U("INVALID_ARGS","install_from_source requires a source payload");switch(t.kind){case"url":if(!t.url||0===t.url.trim().length)throw new U("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 U("INVALID_ARGS","install_from_source path source requires a non-empty path");return t;case"github-actions-artifact":throw new U("UNSUPPORTED_OPERATION","install_from_source github-actions-artifact sources require a compatible remote daemon");default:throw new U("UNSUPPORTED_OPERATION",`install_from_source ${String(t.kind)} sources require a compatible remote daemon`)}}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:ry(o,t.meta?.tenantId)},cleanup:()=>{rv(o)}}:{source:n,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new U("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),u=await r1({session:i,flags:t.flags});if(!e3("install",u))return eH("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let d=e9(t.meta?.requestId);if("ios"===u.platform){let e,{installIosInstallablePath:n}=await import("../3918.js"),{prepareIosInstallArtifact:o}=await import("../3918.js"),c=await o(s.source,{signal:d});try{if(l.enabled&&(e=await rX({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(u,c.installablePath),!c.bundleId)throw new U("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=S(o,r3(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await rY(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await import("../3918.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("../3918.js"),p=await c(s.source,{signal:d});try{l.enabled&&(e=await rX({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await f(u,p.installablePath,p.packageName);if(!n)throw new U("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await import("../3918.js"),s=o(n),d={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=S(d,r3(d));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await rY(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:F(e)}}}function r3(e){return`Installed: ${w(e)}`}async function r8(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new U("INVALID_ARGS","release_materialized_paths requires a materializationId");return await rY(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:F(e)}}}let r4=q(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),r5=q(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function r9(e,t,r){return t||r6(r)?null:eH("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function r6(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function r7(e){return"ios"===e.platform&&"simulator"===e.kind}async function ae(e,t){r7(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function at(e){let t=r6(e.flags)||!e.session?await eu(e.flags??{}):await ar(e.session.device);return!1!==e.ensureReady&&await eK(t),t}async function ar(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 eu(t)}catch(e){if(!(e instanceof U)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await eu({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function aa(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 ai="shared_prefs/ReactNativeDevPrefs.xml",an="debug_http_host",ao="dev_server_https",as="RCT_jsLocation",al="RCT_packager_scheme",au="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.",ad='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function ac(e){return void 0!==O(e)}async function af(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=O(a);if(i){if("android"===t.platform)return void await am(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await ay(t,r,i)}}async function ap(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await ah(t,r);"ios"===t.platform&&"simulator"===t.kind&&await av(t,r)}}async function am(e,t,r){var a,i,n,o,s,l;let u,d;ab(t);let c=(a=await ag(e,t),i=an,n=`${r.host}:${r.port}`,u=` <string name="${a_(i)}">${a_(n)}</string>`,aS(aA(a,i),u));o=c,s=ao,l="https"===r.scheme,d=` <boolean name="${a_(s)}" value="${l?"true":"false"}" />`,c=aS(aA(o,s),d),await aw(e,t,c)}async function ah(e,t){ab(t);let r=await ag(e,t),a=aA(r,an),i=aA(a,ao);i!==r&&await aw(e,t,i)}async function ag(e,t){let r=await V("adb",eO(e,["shell","run-as",t,"cat",ai]),{allowFailure:!0});return 0!==r.exitCode?ad:aI(r.stdout)}async function aw(e,t,r){let a=eO(e,["shell","run-as",t,"id"]),i=await V("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=aN(i.stdout,i.stderr);throw new U("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?au:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await V("adb",eO(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await V("adb",eO(e,["shell","run-as",t,"tee",ai]),{stdin:r.trimEnd()})}catch(a){let e=T(a);if("TOOL_MISSING"===e.code)throw e;let r=aN("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new U("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?au:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function ay(e,t,r){await V("xcrun",eZ(e,["spawn",e.id,"defaults","write",t,as,"-string",`${r.host}:${r.port}`])),await V("xcrun",eZ(e,["spawn",e.id,"defaults","write",t,al,"-string",r.scheme]))}async function av(e,t){await V("xcrun",eZ(e,["spawn",e.id,"defaults","delete",t,as]),{allowFailure:!0}),await V("xcrun",eZ(e,["spawn",e.id,"defaults","delete",t,al]),{allowFailure:!0})}function aI(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
6
|
-
`:
|
|
7
|
-
</map>`)}function
|
|
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 ak=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function ax(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function aD(e,t){if(void 0!==e){if("string"!=typeof e)throw new U("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return R(e)}}function aM(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new U("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function aP(e){if("ios"===e||"android"===e)return e}async function aR(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!ac(r)||ac(a)||await ap({device:i.device,appId:i.appBundleId})}async function aL(e){var t,r;let{req:a,sessionName:i,sessionStore:n}=e,o=(a.positionals?.[0]??"show").toLowerCase(),s=n.get(i),l=n.getRuntimeHints(i);if(!["set","show","clear"].includes(o))return eH("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){ac(l)&&s?.appBundleId&&await ap({device:s.device,appId:s.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===o)return{ok:!0,data:{session:i,configured:!!l,runtime:l}};let u=aP(e5(a.flags?.platform)??l?.platform??s?.device.platform);if(!u)return eH("INVALID_ARGS","runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first.");if(s&&s.device.platform!==u)return eH("INVALID_ARGS",`runtime set targets ${u}, but session "${i}" is already bound to ${s.device.platform}.`);let d={platform:(t=a.flags,r={platform:u,metroHost:R(t?.metroHost),metroPort:aM(t?.metroPort),bundleUrl:R(t?.bundleUrl),launchUrl:R(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===ax(d)?eH("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(n.setRuntimeHints(i,d),{ok:!0,data:{session:i,configured:!0,runtime:d}})}let aO="open-command-roundtrip",aE="Not implemented for this platform in this release.",aC=new Set(["app","desktop","frontmost-app"]);async function a$(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await eQ();return{appBundleId:t.bundleId,appName:t.appName}}async function aT(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return eS(t)?"macos"===e.platform?void 0:"device"===e.kind?eq(r,t):void 0:await aF(e,t)}async function aF(e,t){try{let{resolveIosApp:r}=await import("../3918.js");return await r(e,t)}catch{return}}async function aU(e,t){if(!("android"!==e.platform||!t||eS(t)))try{let{resolveAndroidApp:r}=await import("../3918.js"),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function aG(e,t,r,a){return await aT(e,t,r)??await a(e,t)??("android"===e.platform&&t&&eS(t)?r:void 0)}function aV(e){return eH("INVALID_ARGS",e)}function aj(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=e6(r);if(!aC.has(e))throw new U("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new U("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new U("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let n=r?e6(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new U("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 U?e.code:"INVALID_ARGS",String(e.message))}}function aq(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&eS(r)?aV("open --relaunch does not support URL targets."):"app"!==a?aV("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===eh(r)?aV(eT(r)):null:null}async function aH(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await eK(i);let{appBundleId:l,appName:u}=await aB({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),d=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=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 U("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!ak.includes(e));if(i)throw new U("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${ak.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new U("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new U("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:aD(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new U("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return aM(e)}}(t.metroPort),bundleUrl:aD(t.bundleUrl,"bundleUrl"),launchUrl:aD(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:aP(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=aP(i);if(a.platform&&r&&!n)throw new U("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 U("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:o&&ax(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=T(t);return eH(e.code,e.message,e.details)}}({req:t,sessionStore:a,sessionName:r,device:i});if(!d.ok)return{type:"response",response:d};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=d.data;await aR({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:u,runtime:d.data.runtime}}}async function aB(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await a$(r);return{appBundleId:n.appBundleId??await aG(t,a,i,aU),appName:n.appName??a}}let az=new Map;async function aK(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await et(t.id),await W(t,"close",[r],a,i),await ae(t,r4)}async function aW(e){let{runtime:t,device:r,req:a,logPath:i,appBundleId:n,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let u=s[0]?.trim();!u||eS(u)||await W(r,"open",[l],a.flags?.out,{...eM(i,a.flags,n,o)})}async function aJ(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:u,openPositionals:d,appName:c,surface:f,appBundleId:p,runtime:m,existingSession:h}=e,g=i.flags?.relaunch===!0,w=h?.trace?.outPath;if(g&&u){let e=p??u;await aK({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...eM(s,i.flags,p??h?.appBundleId,w)}})}await af({device:l,appId:p,runtime:m});let y=Date.now();await W(l,"open",d,i.flags?.out,{...eM(s,i.flags,p)}),await aW({runtime:m,device:l,req:i,logPath:s,appBundleId:p,traceLogPath:w,openPositionals:d});let v=u?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:aO,appTarget:u,appBundleId:p}:void 0;if(await ae(l,r5),eL(i.meta?.requestId)){let e=ea();return eH(e.code,e.message,e.details)}h&&te(h,"open",h.snapshot);let I=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:n,device:l,surface:f,appBundleId:p,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===ax(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let S=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:i,startup:n,device:o,runtime:s,runtimeHintCount:l}=e,u={session:t,surface:i};return r&&(u.appName=r),a&&(u.appBundleId=a),n&&(u.startup=n),s&&l(s)>0&&(u.runtime=s),o&&(u.platform=o.platform,u.target=o.target??"mobile",u.device=o.name,u.id=o.id,u.kind=o.kind,"android"===o.platform&&(u.serial=o.id)),o?.platform==="ios"&&(u.device_udid=o.id,u.ios_simulator_device_set=o.simulatorSetPath??null),{...u,...D(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:p,surface:f,startup:v,device:l,runtime:m,runtimeHintCount:ax});return o.recordAction(I,{command:"open",positionals:d,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:S}),o.set(n,I),{ok:!0,data:S}}async function aZ(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,o=t.positionals?.[0],s=o??(n?e.appName:void 0),l=aj(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?aV("open --relaunch requires an app name or an active session app."):aV("Session already active. Close it first or pass a new --session name.");let u=aq({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(u)return u;let d=await ar(e.device),c=await aH({req:t,sessionName:r,sessionStore:i,device:d,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await aJ({req:t,sessionName:r,sessionStore:i,logPath:a,device:d,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return aV("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&eS(r)?aV("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===eh(r)?aV(eT(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await eu(t.flags??{}),u=aj(l,t.flags?.surface,o);if("string"!=typeof u)return u;let d=aq({shouldRelaunch:n,openTarget:o,surface:u,device:l});return d||await ec(az,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 aH({req:t,sessionName:r,sessionStore:i,device:l,surface:u,openTarget:o});return"response"===n.type?n.response:await aJ({req:t,sessionName:r,sessionStore:i,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:n.details.appBundleId,appName:n.details.appName,runtime:n.details.runtime,surface:u})})}async function aX(e){let t=await V("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function aY(e){let{device:t,shutdownRequested:r}=e;if(r&&(r7(t)||"android"===t.platform&&"emulator"===t.kind))try{return r7(t)?await ee(t):await aX(t)}catch(t){let e=F(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function aQ(e){if(await et(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await ew("dismiss",t).catch(t=>{P({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function a0(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 rf(n.appLog),t.positionals&&t.positionals.length>0&&(e4(n.device.platform)&&await aQ(n),await W(n.device,"close",t.positionals,t.flags?.out,{...eM(a,t.flags,n.appBundleId,n.trace?.outPath)}),await ae(n.device,r4)),e4(n.device.platform)&&await aQ(n),ac(i.getRuntimeHints(r))&&n.appBundleId&&await ap({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...D(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await rQ(r).catch(()=>{}),i.delete(r);let o=await aY({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:S({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...D(`Closed: ${r}`)}}}let a1=["platform","target","device","udid","serial","verbose","out"];function a2(e,t){let r=e??{};for(let e of a1)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let a3={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await import("../3918.js");return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await import("../3918.js");return await a(e,t,r)}},a8={ios:async(e,t,r)=>{let{installIosApp:a}=await import("../3918.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("../3918.js"),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function a4(e){let{req:t,command:r,sessionName:a,sessionStore:n,deployOps:o}=e,s=n.get(a),l=t.flags??{},u=r9(r,s,l);if(u)return u;let d=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!d||!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?ry(f,t.meta?.tenantId):t$.expandHome(c);if(!i.existsSync(a))return eH("INVALID_ARGS",`App binary not found: ${a}`);let u=await at({session:s,flags:l,ensureReady:!1});if(!e3(r,u))return eH("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===u.platform){let t=await o.ios(u,d,a),r=t.bundleId;e=r?{app:d,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await o.android(u,d,a),r=t.package;e=r?{app:d,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=S(e,(p=e,`Installed: ${p.appName??M(p)}`));return s&&n.recordAction(s,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&rv(f)}}async function a5(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return eH("INVALID_ARGS",`Unsupported batch on-error mode: ${a}.`);let i=e.flags?.batchMaxSteps??eg;if(!Number.isInteger(i)||i<1||i>1e3)return eH("INVALID_ARGS",`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`);try{let a=J(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await a9(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=T(t);return eH(e.code,e.message,e.details)}}async function a9(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{};return a2(e,n)}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:void 0===r.runtime?e.runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}async function a6(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:u}=e;if("darwin"!==process.platform)throw new U("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let d={simulatorSetPath:o??void 0};if(s){let e=await a7({deviceName:i,runtime:n,simctlOpts:d});e?(t=e.udid,r=e.runtime,a=!1):(t=(await ie({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await it(t,d),a=!0)}else t=(await ie({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await it(t,d),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await u(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function a7(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await V("xcrun",K(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:e0});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||ir(a).includes(ir(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 ie(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await V("xcrun",K(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new U("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 o=String(n.stdout??"").trim();if(!o)throw new U("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function it(e,t){let r=await V("xcrun",K(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:e0});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 ir(e){return e.toLowerCase().replace(/[._-]/g,"")}async function ia(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=eG(e.iosSimulatorDeviceSet);if(!r)return eH("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await a6({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:eK});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=T(t);return eH(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=H(t.flags?.androidDeviceAllowlist),a=e5(t.flags?.platform),i=z({simulatorSetPath:eG(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("../3918.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("../3918.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("../3918.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("../3918.js");try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=T(t);return eH(e.code,e.message,e.details)}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=r9(t.command,e,i);if(n)return n;let o=await at({session:e,flags:i,ensureReady:!0});if(!e3("apps",o))return eH("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(e4(o.platform)){let{listIosApps:e}=await import("../3918.js");return{ok:!0,data:{apps:(await e(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await import("../3918.js");return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function ii(e){let{ensureAndroidEmulatorBooted:t}=await import("../3918.js");return await t(e)}let io='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',is='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function il(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=e5(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return eH("SESSION_NOT_FOUND","ios"===o?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`);let s=r9("appstate",i,n);if(s)return s;let l=e4(i?.device.platform)&&function(e,t){if(!t)return!1;if(!r6(e))return!0;let r=e5(e?.platform);return!(r&&!e2(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"===o&&!l)return eH("SESSION_NOT_FOUND",io);if("macos"===o&&!l)return eH("SESSION_NOT_FOUND",is);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 u=await at({session:i,flags:n,ensureReady:!0});if("ios"===u.platform)return eH("SESSION_NOT_FOUND",io);if("macos"===u.platform)return eH("SESSION_NOT_FOUND",is);let{getAndroidAppState:d}=await import("../3918.js"),c=await d(u);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function iu(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=r9(t.command,i,n);if(o)return o;let s="android"===(e5(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!s)return eH("INVALID_ARGS","boot --headless is supported only for Android emulators.");let u=aa({flags:n,sessionDevice:i?.device}),d=s&&!!u,c=!1;try{e=await at({session:i,flags:n,ensureReady:!1})}catch(r){let t=T(r);if(s&&l&&!u&&"DEVICE_NOT_FOUND"===t.code)return eH("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!d||"DEVICE_NOT_FOUND"!==t.code||!u)throw r;e=await ii({avdName:u,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(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return eH("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=aa({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 ii({avdName:t,serial:n.serial,headless:!0})}await eK(e)}else("android"!==e.platform||!0!==e.booted)&&await eK(e);return e3("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 il({req:t,sessionName:r,sessionStore:a}):null}function id(e){return Math.round(10*e)/10}let ic="adb-shell-dumpsys-cpuinfo",ip="adb-shell-dumpsys-meminfo";async function im(e,t){try{let r=await V("adb",eO(e,["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,o;let e=r.trim();if(0===e.length)continue;let s=e.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!s)continue;let l=Number(s[1]),u=s[2];Number.isFinite(l)&&(n=u,o=t,n===o||n.startsWith(`${o}:`))&&(i+=l,a.add(u))}return{usagePercent:id(i),measuredAt:r,method:ic,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw ig("cpu",t,e)}}async function ih(e,t){try{let r=await V("adb",eO(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new U("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=iw(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!==iy(e));if(!r)break;return iy(r)??void 0}}(e);if(void 0===a)throw new U("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:iw(e,"TOTAL RSS"),measuredAt:r,method:ip}}(r.stdout,t,new Date().toISOString())}catch(e){throw ig("memory",t,e)}}function ig(e,t,r){return r instanceof U&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new U(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof U?r:new U("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function iw(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return iy(a[1])??void 0}function iy(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let iv="ps-process-snapshot",iI="ps-process-snapshot",iS="xctrace-activity-monitor",iA="xctrace-activity-monitor";async function ib(e,t){if("ios"===e.platform&&"device"===e.kind)return await ik(e,t);let r=await iN(e,t),a=await iL(e,r);if(0===a.length)throw new U("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(),n=tg(a.map(e=>o.basename(iO(e.command))));return iE({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:n,cpuMethod:iv,memoryMethod:iI})}async function i_(e){let t=eY(e),r=iC(t,e=>"schema"===e.name&&"activity-monitor-process-live"===e.attributes.name);if(!r)throw new U("COMMAND_FAILED","Failed to parse xctrace activity-monitor-process-live schema");let a=r.children.filter(e=>"col"===e.name).map(e=>{let t;return t=e.children.find(e=>"mnemonic"===e.name),t?.text??null??""}),i=a.indexOf("pid"),n=a.indexOf("process"),o=a.indexOf("cpu-total"),s=a.indexOf("memory-real");if(i<0||n<0||o<0||s<0)throw new U("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let l=function e(t,r){let a=[];for(let i of t)r(i)&&a.push(i),a.push(...e(i.children,r));return a}(t,e=>"row"===e.name),u=[],d=new Map;for(let e of l){var c,f;let t=e.children;if(0===t.length)continue;for(let e of t){let t=iC(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:i$(e),processName:iF(e)})}let r=iT(t[i],d),a=(c=t[n],f=d,c?c.attributes.ref?f.get(c.attributes.ref)?.processName??null:iF(c):null);null!==r&&Number.isFinite(r)&&a&&u.push({pid:r,processName:a,cpuTimeNs:iT(t[o],d),residentMemoryBytes:iT(t[s],d)})}return u}async function iN(e,t){let r="macos"===e.platform?await iP(t):await iR(e,t),a="macos"===e.platform?o.join(r,"Contents","Info.plist"):o.join(r,"Info.plist"),i=await eW(a,"CFBundleExecutable");if(!i)throw new U("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?o.join(r,"Contents","MacOS",i):void 0}}async function ik(e,t){let r=await ix(e,t),a=await iD(e,t),i=await iD(e,t),n=iM(await i_(a.xml),r,t,e),o=iM(await i_(i.xml),r,t,e),s=i.capturedAtMs-a.capturedAtMs;if(s<=0)throw new U("COMMAND_FAILED",`Invalid Activity Monitor sample window for ${t}`,{appBundleId:t,deviceId:e.id});if(null===n.cpuTimeNs||null===o.cpuTimeNs||null===o.residentMemoryBytes)throw new U("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 iE({usagePercent:Math.max(0,o.cpuTimeNs-n.cpuTimeNs)/(1e6*s)*100,residentMemoryKb:o.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:o.matchedProcesses,cpuMethod:iS,memoryMethod:iA})}async function ix(e,t){let r=(await e1(e,"all")).find(e=>e.bundleId===t);if(!r)throw new U("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new U("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let a=r.url.replace(/\/$/,""),i=u(a),n=(await e8(e)).filter(e=>e.executable.startsWith(`${a}/`));if(0===n.length)throw new U("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 iD(e,t){let r=await n.mkdtemp(o.join(c.tmpdir(),"agent-device-ios-perf-")),a=o.join(r,"sample.trace"),i=o.join(r,"activity-monitor-process-live.xml");try{let r=["xctrace","record","--template","Activity Monitor","--device",e.id,"--all-processes","--time-limit","1s","--output",a,"--quiet","--no-prompt"],o=await V("xcrun",r,{allowFailure:!0,timeoutMs:6e4}),s=Date.now();if(0!==o.exitCode)throw new U("COMMAND_FAILED",`Failed to record iOS device Activity Monitor sample for ${t}`,{cmd:"xcrun",args:r,exitCode:o.exitCode,stdout:o.stdout,stderr:o.stderr,appBundleId:t,deviceId:e.id,hint:iU(o.stdout,o.stderr)});let l=["xctrace","export","--input",a,"--xpath",'/trace-toc/run/data/table[@schema="activity-monitor-process-live"]',"--output",i],u=await V("xcrun",l,{allowFailure:!0,timeoutMs:15e3});if(0!==u.exitCode)throw new U("COMMAND_FAILED",`Failed to export iOS device perf sample for ${t}`,{cmd:"xcrun",args:l,exitCode:u.exitCode,stdout:u.stdout,stderr:u.stderr,appBundleId:t,deviceId:e.id,hint:iU(u.stdout,u.stderr)});return{capturedAtMs:s,xml:await n.readFile(i,"utf8")}}finally{await n.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function iM(e,t,r,a){let i=new Set(t.map(e=>e.pid)),n=new Set(t.map(e=>o.basename(u(e.executable)))),s=e.filter(e=>i.has(e.pid)||n.has(e.processName));if(0===s.length)throw new U("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 l=new Map;for(let e of s){let t=l.get(e.pid);if(!t){l.set(e.pid,e);continue}l.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:iG(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iG(t.residentMemoryBytes,e.residentMemoryBytes)})}let d=[...l.values()],c=d.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=d.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:tg(d.map(e=>e.processName))}}async function iP(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await V("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new U("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 U("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function iR(e,t){let r=eZ(e,["get_app_container",e.id,t,"app"]),a=await V("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new U("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 U("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return i}async function iL(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]),o=Number(a[3]),s=a[4].trim();Number.isFinite(i)&&Number.isFinite(n)&&Number.isFinite(o)&&t.push({pid:i,cpuPercent:n,rssKb:o,command:s})}return t})((await V("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let i;return r=e.command,a=t,i=iO(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||o.basename(i)===a.executableName})}function iO(e){let[t=""]=e.trim().split(/\s+/,1);return t}function iE(e){return{cpu:{usagePercent:id(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 iC(e,t){for(let r of e){if(t(r))return r;let e=iC(r.children,t);if(e)return e}}function i$(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 iT(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:i$(e):null}function iF(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function iU(e,t){let r=eo(e,t);if(r)return r;let a=`${e}
|
|
9
|
-
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?
|
|
10
|
-
`,i.appendFileSync(o,a,"utf8"),{ok:!0,data:{path:o,marked:!0}}}(t,r,a):"clear"===o?i0(n,r,a,s):"start"===o?i1(n,r,a):"stop"===o?i2(n,r,a):eH("INVALID_ARGS",iB):eH("INVALID_ARGS",iB)}async function iQ(e,t,r){let a=r.resolveAppLogPath(t),i=await rp(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 i0(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:rm(i)};e.appLog&&await rf(e.appLog);let n=rm(i),o=r.resolveAppLogPidPath(t);try{let a=await rd(e.device,e.appBundleId,i,o);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:F(a)}}}async function i1(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 rd(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:F(e)}}}async function i2(e,t,r){if(!e.appLog)return eH("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await rf(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function i3(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(!e3("network",i.device))return eH("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!iz.includes(n))return eH("INVALID_ARGS",iK);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return eH("INVALID_ARGS","network dump limit must be an integer in range 1..200");let s=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return eH("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return iW.includes(a)?{ok:!0,include:a}:eH("INVALID_ARGS",iJ)}(t);if(!s.ok)return s;let{include:l}=s,u=await rl({device:i.device,appBundleId:i.appBundleId,appLogState:i.appLog?.getState(),appLogStartedAt:i.appLog?.startedAt,appLogPath:a.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...u.dump,active:!!i.appLog,state:i.appLog?.getState()??"inactive",backend:u.backend,notes:u.notes}}}let i8=/^[A-Z_][A-Z0-9_]*$/,i4=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-((?:[^}\\]|\\.)*))?\}/g,i5="AD_VAR_";function i9(e){return e.startsWith("AD_")}function i6(e){return new U("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function i7(e,t,r){return e.replace(i4,(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 U("INVALID_ARGS",`Unresolved variable \${${i}} at ${r.file}:${r.line}.`)})}function ne(e,t,r){if(!e)return e;let a={...e};for(let[e,i]of Object.entries(a))"string"==typeof i&&(a[e]=i7(i,t,r));return a}let nt=new Set(["ios","android","macos","linux"]);function nr(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(na(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 U("INVALID_ARGS",`Invalid env directive on line ${t}: expected "env KEY=VALUE".`);let i=r.slice(0,a);if(!i8.test(i))throw new U("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 U("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 U("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 U("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&&nt.has(e)&&ni(r,"platform",e)}let n=a.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&ni(r,"timeoutMs",Math.floor(e))}let o=a.match(/(?:^|\s)retries=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=0&&ni(r,"retries",Math.floor(e))}}return r}function na(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function ni(e,t,r){let a=e[t];if(void 0!==a)throw new U("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 nn(e){return!!e&&!Number.isNaN(Number(e))}let no=/[*?[\]{}]/;async function ns(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,artifactsDir:s,runReplay:l,cleanupSession:u}=e;en(i);let d=new Set,c=!1,f=l({filePath:r,sessionName:a,platform:o,requestId:i,artifactsDir:s,artifactPaths:d}).catch(e=>{let t=T(e);return eH(t.code,t.message)}).finally(()=>{eJ(i)});try{return"number"==typeof n?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{c=!0,eV(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,[...d]))},n)})]):await f}finally{t&&clearTimeout(t),c&&(await nl(f)||P({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await u(a)}catch(e){P({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:T(e).message}})}}}async function nl(e){return await Promise.race([e.then(()=>!0),p(2e3).then(()=>!1)])}async function nu(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 s,l,u,d,c,f;let e,p,m,h,g,w=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,n=r??process.cwd(),s=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let n=t$.expandHome(e,t);if(i.existsSync(n)){let t=i.statSync(n);if(t.isDirectory())return i.globSync("**/*.ad",{cwd:n}).map(e=>o.join(n,e));if(t.isFile()){if(".ad"!==o.extname(n))throw new U("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[n]}return[]}if(r=e,!no.test(r)&&(a=n,!no.test(a)))throw new U("INVALID_ARGS",`test input not found: ${e}`);let s=o.isAbsolute(n)?n:e;return i.globSync(s,{cwd:o.isAbsolute(n)?void 0:t}).map(e=>o.isAbsolute(e)?e:o.resolve(t,e)).filter(e=>".ad"===o.extname(e)&&function(e){try{return i.statSync(e).isFile()}catch{return!1}}(e))})(e,n)))].map(e=>o.normalize(e)).sort((e,t)=>e.localeCompare(t)),l=[];for(let e of s){var u,d;let t=nr(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}u=a,d=t.platform,("apple"===u?"apple"===d||"ios"===d||"macos"===d:d===u)&&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 U("INVALID_ARGS",`No .ad tests matched${e}.`)}return l}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),y=(s=t.meta?.requestId,(s?.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=t$.expandHome(t??".agent-device/test-artifacts",r);return o.join(i,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),I=[],S=Date.now(),A=0;for(let e of w){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}A+=1;let i=await nd({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,u=e.metadata.timeoutMs,"number"==typeof l?l:u),suiteArtifactsDir:v,runReplay:a,cleanupSession:n});if(I.push(i),t.flags?.failFast===!0)break}let b=(d=w.length,c=I,f=Date.now()-S,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:d,executed:g,passed:e,failed:m,skipped:h,notRun:Math.max(0,d-g-h),durationMs:f,failures:p,tests:c});return{ok:!0,data:b}}catch(t){let e=T(t);return eH(e.code,e.message)}}async function nd(e){var t,r;let a,n,{entry:s,sessionName:l,suiteInvocationId:u,caseIndex:d,cwd:c,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:g,cleanupSession:w}=e,y=Date.now(),v=o.join(h,(t=s.path,(0===(n=c?o.relative(c,t):o.basename(t)).length||n.startsWith("..")?o.basename(t):n).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",S=0;for(let e=0;e<=p;e+=1){S=e+1;let t=function(e,t,r,a,i=0){let n=o.basename(r,o.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${n?`-${n}`:""}:attempt-${i+1}`}(l,u,s.path,d,e),n=o.join(v,`attempt-${S}`);r=s.path,i.mkdirSync(n,{recursive:!0}),i.copyFileSync(r,o.join(n,"replay.ad"));let c=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:n}=e;return eR(`${t??r}:test:${i+1}:${o.basename(a)}:attempt:${n+1}`,r)}({requestId:f,suiteInvocationId:u,filePath:s.path,caseIndex:d,attemptIndex:e}),h=await ns({filePath:s.path,sessionName:t,requestId:c,timeoutMs:m,platform:s.metadata.platform,artifactsDir:n,runReplay:g,cleanupSession:w});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:n,maxAttempts:s,attemptArtifactsDir:l}=e,u=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||u.push(t.error.logPath);let d=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=o.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}`}(o.basename(n),a),s=o.join(t,e);o.resolve(n)!==o.resolve(s)&&i.copyFileSync(n,s),r.push(s)}return r}(u,l),c=[`file: ${r}`,`session: ${a}`,`attempt: ${n}/${s}`,`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");d.length>0&&c.push(`copiedArtifacts: ${d.map(e=>o.basename(e)).join(", ")}`);let f=o.join(l,"result.txt"),p=`${c.join("\n")}
|
|
11
|
-
`;i.writeFileSync(f,p),t.ok||i.writeFileSync(o.join(l,"failure.txt"),p)}({response:h,filePath:s.path,sessionName:t,attempts:S,maxAttempts:p+1,attemptArtifactsDir:n}),a=h,I=t,h.ok)break}let A=Date.now()-y;if(a?.ok)return{file:s.path,session:I,status:"passed",durationMs:A,attempts:S,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:s.path,session:I,status:"failed",durationMs:A,attempts:S,artifactsDir:v,error:b}}function nc(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=tt(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 nf(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(tA(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let n=i.get(r);if(!n)return null;let o=(function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),tA(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}=ti(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=nc(e.positionals??[]);r&&t.push(r)}return tg(t).filter(e=>e.trim().length>0)})(t).map(e=>tn(e)).filter(e=>null!==e);if(0===o.length)return null;let s=tA(t.command)||"fill"===t.command,l=tA(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await np(n,t,a,s,i);for(let e of o){let r=to(u.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=tl(r.node,n.device.platform,{action:tA(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tA(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=th(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}=ti(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}=nc(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function np(e,t,r,a,i){let n=await W(e.device,"snapshot",[],t.flags?.out,{...eM(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:tc(t.flags?.snapshotRaw?o:td(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return e.snapshot=s,i.set(e.name,e),s}async function nm(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:s}=e,l=t.positionals?.[0];if(!l)return eH("INVALID_ARGS","replay requires a path");let u="",d=new Set;try{var c;let e;u=t$.expandHome(l,t.meta?.cwd);let f=i.readFileSync(u,"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=nr(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],o=n.trim();if(0===o.length||o.startsWith("#"))continue;if(na(o)){if(i)throw new U("INVALID_ARGS",`env directives must precede all actions (line ${e+1}).`);continue}let s=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){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 U("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=tO(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=tO(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tA(a)){let e=tL(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],o=e.positionals[1];return nn(r)&&nn(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=tL(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=tL(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 U("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);s&&(t.push(s),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(i9(e))throw i6(e);t[e]=a}return{values:t}}({builtins:function(e){let{req:t,sessionName:r,metadata:a,resolvedPath:i}=e,n=t.flags??{},s=t.meta?.cwd??process.cwd(),l={AD_SESSION:r,AD_FILENAME:o.relative(s,i)||i},u=n.platform??a.platform;u&&(l.AD_PLATFORM=u);let d=n.device;"string"==typeof d&&d.length>0&&(l.AD_DEVICE=d);let c=n.artifactsDir;return"string"==typeof c&&c.length>0&&(l.AD_ARTIFACTS=c),l}({req:t,sessionName:r,metadata:m,resolvedPath:u}),fileEnv:m.env,shellEnv:function(e){let t={};for(let[r,a]of Object.entries(e)){if("string"!=typeof a||!r.startsWith(i5))continue;let e=r.slice(i5.length);0!==e.length&&i8.test(e)&&(i9(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 U("INVALID_ARGS",`Invalid -e entry "${r}": expected KEY=VALUE.`);let a=r.slice(0,e);if(!i8.test(a))throw new U("INVALID_ARGS",`Invalid -e key "${a}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(i9(a))throw i6(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,I=0;for(let e=0;e<g.length;e+=1){let i=g[e];if(!i||"replay"===i.command)continue;let o=await nh({req:t,sessionName:r,action:i,scope:y,filePath:u,line:w[e]??0,invoke:s});if(o.ok){nw(o).forEach(e=>d.add(e));continue}if(!v)return ng(o,i,e,u,[...d]);let l=await nf({action:i,sessionName:r,logPath:a,sessionStore:n});if(!l)return ng(o,i,e,u,[...d]);if(g[e]=l,!(o=await nh({req:t,sessionName:r,action:l,scope:y,filePath:u,line:w[e]??0,invoke:s})).ok)return ng(o,l,e,u,[...d]);nw(o).forEach(e=>d.add(e)),I+=1}return v&&I>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=${tN(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",t_(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tC(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tk(r,tD));return tP(t,e.flags),t.join(" ")}if("record"===e.command)return tR(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(t_(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(t_(r));return tM(t,e),t.join(" ")}(e));let n=`${a.join("\n")}
|
|
12
|
-
`,o=`${e}.tmp-${process.pid}-${Date.now()}`;i.writeFileSync(o,n),i.renameSync(o,e)}(u,g,n.get(r)),{ok:!0,data:{replayed:g.length,healed:I,session:r,artifactPaths:[...d]}}}catch(t){let e=T(t);return eH(e.code,e.message,d.size>0?{artifactPaths:[...d]}:void 0)}}async function nh(e){var t,r;let{req:a,sessionName:i,action:n,scope:o,filePath:s,line:l,invoke:u}=e,d=(t={file:s,line:l},{...n,positionals:(n.positionals??[]).map(e=>i7(e,o,t)),flags:ne(n.flags,o,t)??{},runtime:ne(n.runtime,o,t)});return await u({token:a.token,session:i,command:d.command,positionals:d.positionals??[],flags:(r=a.flags,a2(r,{...d.flags??{}})),runtime:d.runtime,meta:a.meta})}function ng(e,t,r,a,i=[]){let n;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${n=(t.positionals??[]).map(e=>t_(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:o,action:t.command,positionals:t.positionals??[],artifactPaths:i}}}}function nw(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 ny(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await nm({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await nu({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactsDir:l,artifactPaths:u})=>{let d=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:o,artifactsDir:l});return await nm({req:{...t,command:"replay",session:r,positionals:[e],flags:d,meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),u&&nw(t).forEach(e=>u.add(e)),t}})},cleanupSession:async e=>{i.get(e)&&await a0({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let nv=new Set(["session_list","ensure-simulator","devices","apps"]),nI=new Set(["boot","appstate"]),nS=new Set(["perf","logs","network"]),nA=new Set(["replay","test"]);async function nb(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,u=i.get(r),d=t.flags??{},c=r9(n,u,d);if(c)return c;let f=await at({session:u,flags:d,ensureReady:!0});if(!e3(n,f))return eH("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await W(f,n,o,t.flags?.out,{...eM(a,t.flags,u?.appBundleId,u?.trace?.outPath)});if(u){let e=l?await l(u,p,f):u;i.recordAction(e,{command:n,positionals:s??o,flags:t.flags??{},result:p??{}}),e!==u&&i.set(r,e)}return{ok:!0,data:p??{}}}async function n_(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=r9("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return eH("INVALID_ARGS","clipboard requires a subcommand: read or write");let u=await at({session:n,flags:o,ensureReady:!0});if(!e3("clipboard",u))return eH("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let d=await W(u,"clipboard",t.positionals??[],t.flags?.out,{...eM(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:d??{}}),{ok:!0,data:{platform:u.platform,...d??{}}}}async function nN(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(nv.has(t.command))return await ia({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await aL({req:t,sessionName:r,sessionStore:i});if(nI.has(t.command))return await iu({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await n_({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"!==e5((t.flags??{}).platform)?await nb({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(nS.has(t.command))return await iZ({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await a4({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?a8:a3});if("install_source"===t.command)return await r2({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await r8({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await nb({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=eE(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>t$.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):eH("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await nb({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 aG(e.device,r,e.appBundleId,aU)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await aZ({req:t,sessionName:r,logPath:a,sessionStore:i}):nA.has(t.command)?await ny({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await a5(t,r,n):"close"===t.command?await a0({req:t,sessionName:r,logPath:a,sessionStore:i}):null}async function nk(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return eH("INVALID_ARGS","find requires a locator or text");let{locator:l,query:u,action:d,value:c,timeoutMs:f}=tm(s);if(!u)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 ej({req:t,sessionName:r,logPath:a,sessionStore:i});if(p)return p;let m=i.get(r);if(!m&&"exists"!==d&&"wait"!==d&&"get_text"!==d&&"get_attrs"!==d)return eH("SESSION_NOT_FOUND","No active session. Run open first.");let h=m?.device??await eu(t.flags??{});m||await eK(h);let g="role"!==l?u:void 0,w="click"===d||"focus"===d||"fill"===d||"type"===d,y=0,v=null,I=async()=>{let e=Date.now();if(v&&e-y<750&&!eX(m))return{nodes:v};let{snapshot:n}=await eb({device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:g}),o=n.nodes;return y=e,v=o,m&&(m.snapshot=n,i.set(r,m)),{nodes:o,truncated:n.truncated,backend:n.backend}},S={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:m,device:h,command:o,locator:l,query:u};if("wait"===d)return nx(S,I,l,u,f);let{nodes:A}=await I(),b=tp(A,l,u,{requireRect:w});if(w&&b.matches.length>1)if(t.flags?.findFirst)b.matches=[b.matches[0]];else{if(!t.flags?.findLast){var _,N,k;let e;return _=b.matches,N=l,k=u,e=_.slice(0,8).map(e=>{let t=ta(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),eH("AMBIGUOUS_MATCH",`find matched ${_.length} elements for ${N} "${k}". Use a more specific locator or selector.`,{locator:N,query:k,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"===d||"focus"===d||"fill"===d||"type"===d?tr(A,x)??x:x,M=`@${D.ref}`,P={node:x,resolvedNode:D,ref:M,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},R={exists:()=>nD(S),get_text:()=>nM(S,P),get_attrs:()=>nP(S,P),click:()=>nR(S,P),fill:()=>nL(S,P,c),focus:()=>nO(S,P),type:()=>nE(S,P,c)}[d];return R?R():null}async function nx(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,u=i??1e4,d=Date.now();for(;Date.now()-d<u;){let{nodes:e}=await t();if(tp(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{found:!0,waitedMs:Date.now()-d}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-d}};await j(300)}return eH("COMMAND_FAILED","find wait timed out")}async function nD(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 nM(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await eA({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eM(s,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 nP(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 nR(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:u}=e,d=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!d.ok)return d;let c=t.resolvedNode.rect?tf(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:u};return c&&(f.x=c.x,f.y=c.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:u}}),{ok:!0,data:f}}async function nL(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return eH("INVALID_ARGS","find fill requires text");let u=await s({token:a.token,session:i,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return u.ok&&o&&n.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),u}async function nO(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?tf(t.node.rect):null;if(!l)return eH("COMMAND_FAILED","matched element has no bounds");let u=await W(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eM(s,r.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:u??{ref:t.ref}}}async function nE(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return eH("INVALID_ARGS","find type requires text");let u=t.node.rect?tf(t.node.rect):null;if(!u)return eH("COMMAND_FAILED","matched element has no bounds");await W(o,"focus",[String(u.x),String(u.y)],a.flags?.out,{...eM(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let d=await W(o,"type",[r],a.flags?.out,{...eM(l,a.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:s,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:d??{ref:t.ref}}}let nC=`
|
|
1
|
+
let e,t,r;import a from"node:crypto";import i,{promises as n}from"node:fs";import o from"node:path";import{spawn as s}from"node:child_process";import l from"node:http";import{fileURLToPath as u,pathToFileURL as d}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{resolveInstallFromSourceResultTarget as I,readVersion as S,resolveDaemonCodeSignature as A,normalizeTenantId as b,withSuccessText as _,resolveSessionIsolationMode as N,withDiagnosticsScope as k,resolveDaemonPaths as x,flushDiagnosticsToSessionFile as D,getDiagnosticsMeta as M,resolveDaemonServerMode as P,successText as L,resolveDeployResultTarget as R,emitDiagnostic as O}from"../8161.js";import{trimRuntimeValue as E,readProcessCommand as C,resolveRuntimeTransportHints as $,isAgentDeviceDaemonProcess as T,readProcessStartTime as F}from"../8656.js";import{toAppErrorCode as U,asAppError as G,normalizeError as V,AppError as j}from"../9152.js";import{runCmdBackground as q,runCmd as H}from"../9818.js";import{sleep as B,resolveTimeoutMs as z}from"../4829.js";import{resolveAndroidSerialAllowlist as K,decodePng as W,resolveAppleSimulatorSetPathForSelector as J,buildSimctlArgs as Z,dispatchCommand as X,validateAndNormalizeBatchSteps as Y,refSnapshotFlagGuardResponse as Q,IOS_RUNNER_CONTAINER_BUNDLE_IDS as ee,buttonTag as et,handleSnapshotCommands as er,shutdownSimulator as ea,stopIosRunnerSession as ei,localCommandPolicy as en,createRequestCanceledError as eo,isNavigationSensitiveAction as es,registerRequestAbort as el,errorResponse as eu,resolveIosDevicectlHint as ed,getClickButtonValidationError as ec,snapshotAndroid as ef,resolveTargetDevice as ep,dispatchGetViaRuntime as em,setSessionSnapshot as eh,withKeyedLock as eg,assertAndroidPressStayedInApp as ew,parseSerialAllowlist as ey,classifyAndroidAppTarget as ev,DEFAULT_BATCH_MAX_STEPS as eI,runMacOsAlertAction as eS,createAgentDevice as eA,stopAllIosRunnerSessions as eb,getAndroidScreenSize as e_,isDeepLinkTarget as eN,getAndroidAppState as ek,withResolveTargetDeviceCacheScope as ex,readTextForNode as eD,captureSnapshot as eM,dispatchIsViaRuntime as eP,resolveClickButton as eL,IOS_DEVICECTL_DEFAULT_HINT as eR,buildSnapshotState as eO,openAndroidApp as eE,context_contextFromFlags as eC,captureSnapshotData as e$,resolveRequestTrackingId as eT,isRequestCanceled as eF,adbArgs as eU,resolvePayloadInput as eG,abortAllIosRunnerSessions as eV,getRunnerSessionSnapshot as ej,formatAndroidInstalledPackageRequiredMessage as eq,createUnsupportedArtifactAdapter as eH,isAndroidEscapeError as eB,resolveIosSimulatorDeviceSetPath as ez,markRequestCanceled as eK,dispatchFindReadOnlyViaRuntime as eW,resolveIosDeviceDeepLinkBundleId as eJ,runIosRunnerCommand as eZ,ensureDeviceReady as eX,readInfoPlistString as eY,clearRequestCanceled as eQ,buildSimctlArgsForDevice as e0,getActiveAndroidSnapshotFreshness as e1,parseXmlDocumentSync as e2,resolveFrontmostMacOsApp as e3,IOS_SIMCTL_LIST_TIMEOUT_MS as e8,listIosDeviceApps as e5,matchesPlatformSelector as e4,isCommandSupportedOnDevice as e9,listIosDeviceProcesses as e6,isApplePlatform as e7,normalizePlatformSelector as te,getRequestSignal as tt,parseSessionSurface as tr,buildScrollGesturePlan as ta,markAndroidSnapshotFreshness as ti}from"../3918.js";import{splitSelectorFromArgs as tn,findNearestHittableAncestor as to,extractNodeText as ts,splitIsSelectorArgs as tl,tryParseSelectorChain as tu,resolveSelectorChain as td,resolveRefLabel as tc,buildSelectorChainForNode as tf,normalizeType as tp,pruneGroupNodes as tm}from"../940.js";import{attachRefs as th,centerOfRect as tg}from"../4057.js";import{findBestMatchesByLocator as tw,parseFindArgs as ty}from"../7556.js";function tv(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 tI(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tS=/^-?\d+(\.\d+)?$/,tA=/^[^\s"\\]+$/,tb=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),t_=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tN=new Map([["--delay-ms","delayMs"]]);function tk(e){return"click"===e||"press"===e}function tx(e){return"type"===e||"fill"===e}function tD(e){return tP(e,tL)}function tM(e){return JSON.stringify(e)}function tP(e,t){return t(e)?e:tM(e)}function tL(e){return tR(e)&&e.startsWith("@")||tS.test(e)}function tR(e){return tA.test(e)}function tO(e,t){let r=t.flags??{};if(tk(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}tx(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tE(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",tP(t.metroHost,tR)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tP(t.bundleUrl,tR)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tP(t.launchUrl,tR)))}function tC(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tP(r,tR)),a))e.push(tD(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 t$(e,t){let r=[],a={},i=tk(e)?tb:"swipe"===e?t_:tx(e)?tN:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tk(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tk(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=tF(t[n+1]);if(null!==e){a[s]=e,n+=1;continue}}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:a}}function tT(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=tF(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 tF(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tU(e,t){for(let r of t.positionals??[])e.push(tD(r));t.flags?.relaunch&&e.push("--relaunch"),tE(e,t.runtime)}class tG{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=tG.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 tV)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),O({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=o.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=${tM(e.device.name)}${a} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(tk(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tD(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tD(a)),tO(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tD(r)),tO(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tD(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tD(a)),e.positionals.length>1&&t.push(tD(i)),tO(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tD(r)),t.push(tD(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tD(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",tD(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tD(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 tU(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tP(r,tR)),tE(t,e.flags),t.join(" ")}if("record"===e.command)return tC(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tD(r));return tO(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
2
|
+
`}(e,this.buildOptimizedActions(e));i.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=tG.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return o.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return o.join(this.sessionsDir,tG.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return o.join(this.sessionsDir,tG.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return v(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return tG.expandHome(e.saveScriptPath);i.existsSync(this.sessionsDir)||i.mkdirSync(this.sessionsDir,{recursive:!0});let t=tG.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return o.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&&(tk(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tk(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=tv(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(tk(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 tV=["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"],tj="app-log.pid";function tq(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 tH(e,t){if(!e)return;let r=o.dirname(e);i.existsSync(r)||i.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:F(t)??void 0,command:C(t)??void 0};i.writeFileSync(e,`${JSON.stringify(a)}
|
|
3
|
+
`)}function tB(e){if(e&&i.existsSync(e))try{i.unlinkSync(e)}catch{}}async function tz(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}function tK(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 tW(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 tJ(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new j("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function tZ(e,t){let r=(await H("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function tX(e,t){var r,a;let i;tJ(t);let n=await tZ(e,t),o=await H("adb",["-s",e,"logcat","-d","-v","time","-t","4000"],{allowFailure:!0,timeoutMs:3e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=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.stdout,t,n);if(0===s.length)return null;let l=(r=o.stdout,a=t,i=new Set(s),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===l.trim().length?null:{pid:n,text:l,recoveredPids:s}}async function tY(e,t,r,a,i){let n,o,l="recovering",u=!1,d=(async()=>{try{for(;!u;){let d=await tZ(e,t);if(!d){l="recovering",await B(1e3);continue}let c=s("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=c;let f=tK(r,{redactionPatterns:a});if(o=tW(c,r,{endStreamOnClose:!1,writer:f}),"number"==typeof c.pid&&(tH(i,c.pid),l="active"),await o,tB(i),n=void 0,o=void 0,u)break;l="recovering",await B(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tB(i)}})();return{backend:"android",getState:()=>l,startedAt:Date.now(),wait:d,stop:async()=>{u=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await tz(o),n&&!n.killed&&n.kill("SIGKILL"),await tz(d),tB(i)}}}function tQ(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}"`}async function t0(e){let{deviceId:t,appBundleId:r,startedAt:a,simulatorSetPath:i}=e,n=Z(["spawn",t,"log","show","--style","compact","--info","--predicate",tQ(r)],{simulatorSetPath:i});"number"==typeof a&&Number.isFinite(a)&&a>0?n.push("--start",`@${Math.floor(a/1e3)}`):n.push("--last","5m");let o=await H("xcrun",n,{allowFailure:!0,timeoutMs:4e3});if(0!==o.exitCode||0===o.stdout.trim().length)return null;let s=o.stdout.split("\n").map(e=>e.trimEnd()).filter(e=>{let t=e.trim();return t.length>0&&!t.startsWith("Timestamp Ty Process[PID:TID]")});return 0===s.length?null:{text:`${s.join("\n")}
|
|
5
|
+
`,recoveredLineCount:s.length}}async function t1(e,t,r,a,i,n){let o="active",l=s("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return Z(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",tQ(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:i}),{stdio:["ignore","pipe","pipe"]}),u=tK(r,{redactionPatterns:a});"number"==typeof l.pid&&tH(n,l.pid);let d=tW(l,r,{endStreamOnClose:!0,writer:u}).then(e=>(0!==e.exitCode&&(o="failed"),tB(n),e));return{backend:"ios-simulator",getState:()=>o,startedAt:Date.now(),wait:d,stop:async()=>{l.killed||l.kill("SIGINT"),await tz(d),l.killed||l.kill("SIGKILL"),await tz(d),tB(n)}}}async function t2(e,t,r,a){let i="active",n=s("log",["stream","--style","compact","--predicate",tQ(e)],{stdio:["ignore","pipe","pipe"]}),o=tK(t,{redactionPatterns:r});"number"==typeof n.pid&&tH(a,n.pid);let l=tW(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tB(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tz(l),n.killed||n.kill("SIGKILL"),await tz(l),tB(a)}}}async function t3(e,t,r,a){let i="active",n=s("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tK(t,{redactionPatterns:r});"number"==typeof n.pid&&tH(a,n.pid);let l=tW(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tB(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tz(l),n.killed||n.kill("SIGKILL"),await tz(l),tB(a)}}}let t8=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),t5=/https?:\/\/[^\s"'<>\])]+/i,t4=[/\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 t9(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>t7(e)));for(let e of t.entries){let t=t7(e);if(!i.has(t)&&(i.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function t6(e,t){let r=ru(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=ru(t?.maxPayloadChars,2048,64,16384),o=ru(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),u=s.slice(l),d=[];for(let e=u.length-1;e>=0&&d.length<r;e-=1){let t=u[e];if(!t?.trim())continue;let r=function(e,t,r,a,i,n){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=rn(s,["method","httpMethod"]),u=rn(s,["url","requestUrl"]),d=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=t8.exec(o),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=t5.exec(o),h=u??m?.[0];if(!h)return null;let g=d??rt(o)??void 0;if(!(l||f?.[1]||c?.[1]||void 0!==g||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let w={method:p,url:h,status:g,timestamp:rr(o),packetId:ra(o)??void 0,durationMs:ri(o)??void 0,raw:rl(o,n),line:r};if("android"===a&&function(e,t,r){let a=re(t,r,5),i=e.packetId??a.map(e=>ra(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?re(t,r,12).filter(e=>ra(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>rr(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>rt(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>ri(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 rs(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(w.headers=rl(e,n))}if("body"===i||"all"===i){let e=ro(o,s,["requestBody","body","payload","request"]),t=ro(o,s,["responseBody","response"]);e&&(w.requestBody=rl(e,n)),t&&(w.responseBody=rl(t,n))}return w}(u,e,l+e+1,a,i,n);r&&d.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:u.length,matchedLines:d.length,entries:d,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:o}}}function t7(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function re(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 rt(e){for(let t of t4){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function rr(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 ra(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function ri(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 rn(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 ro(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return rs(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 rs(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function rl(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function ru(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function rd(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 rc(e){let t=o.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:rd("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rd("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rf(e){var t,r,a,n;let o,s,l,u,{device:d,appBundleId:c,appLogState:f,appLogStartedAt:p,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y}=e,v="macos"===d.platform?"macos":"ios"===d.platform?"device"===d.kind?"ios-device":"ios-simulator":"android",I=(t={backend:v,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y},o=ru(t?.maxEntries,25,1,200),s=t?.include??"summary",l=ru(t?.maxPayloadChars,2048,64,16384),u=ru(t?.maxScanLines,4e3,100,2e4),i.existsSync(m)?t6(i.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:s,limits:{maxEntries:o,maxPayloadChars:l,maxScanLines:u}}),S=[],A=await rp({device:d,appBundleId:c,appLogPath:m,appLogState:f});if(A){let e=await tX(d.id,c);if(e){let t=t6(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y});t.entries.length>0&&(I=t9(t,I,h),S.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"===d.platform&&"simulator"===d.kind&&c&&0===I.entries.length){let e=await rh({deviceId:d.id,appBundleId:c,startedAt:p,simulatorSetPath:d.simulatorSetPath,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y});e&&(e.dump.entries.length>0?(I=t9(e.dump,I,h),S.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&&S.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?S.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==f&&0===S.length&&("ios"===d.platform&&"simulator"===d.kind?S.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."):S.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===I.entries.length&&S.push("ios"===(n=d).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:I,notes:S}}async function rp(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 s=function(e){let t=function(e){if(!e||!i.existsSync(e))return null;try{return tq(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}(o.join(o.dirname(a),tj));if(!s)return null;let l=await tZ(t.id,r);return l&&l!==s?{reason:"stale-active",trackedPid:s}:null}async function rm(e,t,r,a){rc(r);let n=i.createWriteStream(r,{flags:"a"}),o=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 t3(e.id,n,o,a):await t1(e.id,t,n,o,e.simulatorSetPath,a);if("android"===e.platform)return tJ(t),await tY(e.id,t,n,o,a);if("macos"===e.platform)return await t2(t,n,o,a);throw n.end(),new j("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rh(e){let t=await t0({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:t6(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 rg(e){await e.stop(),await tz(e.wait)}async function rw(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 e=await H("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await H("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await H("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 H("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await H("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function ry(e){let t=o.dirname(e),r=o.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(o.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let rv=new Map;function rI(e){let t=rv.get(e);if(t&&(clearTimeout(t.timer),rv.delete(e),t.deleteAfterDownload))try{i.rmSync(t.artifactPath,{force:!0})}catch{}}let rS=new Map;function rA(e,t){let r=rS.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 rb(e){let t=rS.get(e);t&&(clearTimeout(t.timer),rS.delete(e),i.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function r_(e){let t=await rN(e);await H("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=o.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 rN(e){let t=await H("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(rk),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,o=i;if(n!==o&&!n.startsWith(`${o}/`))throw new j("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await H("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 rk(e){if(e.includes("\0"))throw new j("INVALID_ARGS",`Invalid archive entry: ${e}`);if(o.posix.isAbsolute(e))throw new j("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=o.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new j("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rx=z(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rD(e,t){return new Promise((r,a)=>{let n,o=!1,s=0,l=i.createWriteStream(t),u=e=>{if(!o){if(o=!0,n&&clearTimeout(n),e)return void rM(l,t).finally(()=>a(e));r()}},d=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let t=new j("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rx});"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t),c.destroy(t),u(t)},rx)},c=new p({transform(e,t,r){d();let a=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e,t);(s+=a)>0x80000000?r(new j("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")):r(null,e)}});e.on("aborted",()=>{u(new j("COMMAND_FAILED","Artifact transfer was interrupted"))}),d(),m(e,c,l).then(()=>u(),e=>u(e))})}async function rM(e,t){if(e.destroy(),!e.closed)try{await f(e,"close")}catch{}await i.promises.rm(t,{force:!0}).catch(()=>{})}async function rP(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=o.basename(t);if(!r||"."===r||".."===r)throw new j("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),s=(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(o.join(c.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=o.join(s,n);return await rD(e,t),{artifactPath:t,tempDir:s}}let t=o.join(s,"artifact.tar");await rD(e,t);let a=await r_({archivePath:t,tempDir:s,platform:"ios",expectedRootName:n});return i.rmSync(t,{force:!0}),{artifactPath:a,tempDir:s}}catch(e){throw i.rmSync(s,{recursive:!0,force:!0}),e}}let rL=new Set(["agent_device.command","agent-device.command"]),rR=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rO=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rE={"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"},rC=new Set([...rL,...rR,...rO,...Object.keys(rE)]);function r$(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rT(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rF(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rU(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 rG(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rV(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 rq(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 rH(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=V(new j("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=V(new j(U(r.code,"UNAUTHORIZED"),r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=b(r.tenantId);if(!e){let e=V(new j("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:r$(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rB(){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=o.isAbsolute(t)?t:o.resolve(t);try{e=await import(d(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 rz(e){let t=await rB(),{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 rK(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/artifacts/"))return void rW(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||rT(i,r$(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rT(i,r$(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rT(i,r$(a.id??null,-32600,"Invalid Request"),400);if(!rC.has(a.method))return void rT(i,r$(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rT(i,r$(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rL.has(e))return{token:rU(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(rR.has(e)){let e,a=rG(t,"platform");if("ios"!==a&&"android"!==a)throw new j("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rU(t,r),session:rG(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rG(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,o=void 0!==e.artifactName;if(i&&(n||o))throw new j("INVALID_ARGS","Invalid params: source must specify either artifactId or artifactName, not both");if(!i&&n&&!o)throw new j("INVALID_ARGS","Invalid params: source.artifactName is required when source.runId is specified");if(!i&&!o)throw new j("INVALID_ARGS","Invalid params: source must specify artifactId or artifactName");return i?{kind:"github-actions-artifact",owner:r,repo:a,artifactId:rq(e,"artifactId")}:(n&&(t=rq(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:rV(t,"retentionMs")}}}if(rO.has(e)){let e=rG(t,"materializationId")?.trim();if(!e)throw new j("INVALID_ARGS","Invalid params: materializationId is required");return{token:rU(t,r),session:rG(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rG(t,"requestId"),materializationId:e}}}let a=rE[e];if(a)return{token:rU(t,r),session:rG(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rG(t,"tenantId")??rG(t,"tenant"),runId:rG(t,"runId"),leaseId:rG(t,"leaseId"),leaseTtlMs:rV(t,"ttlMs"),leaseBackend:rG(t,"backend")}};throw new j("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rL.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rT(i,r$(a.id??null,-32602,"Invalid params: command is required"),400);o=eT(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},el(o);let u=()=>{i.writableFinished||eK(o)};e.on("aborted",u),i.on("close",u);let d=await rH(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!d.ok)return void rT(i,d.response,d.statusCode);d.tenantId&&(l.meta={...l.meta,tenantId:d.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rT(i,{jsonrpc:"2.0",id:a.id??null,result:c});rT(i,r$(a.id??null,-32e3,c.error.message,c.error),rF(c.error.code))}catch(t){let e=V(t);rT(i,r$(a.id??null,-32e3,e.message,e),rF(e.code))}finally{eQ(o)}})})}async function rK(e,t,r,i){try{var n;let o,s,l=rU({},e.headers),u=rJ(l,i);if(u){t.statusCode=rF(u.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.message,code:u.code}));return}let d=await rH(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let c=await rP(e),f=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:d.tenantId},o=a.randomUUID(),(s=setTimeout(()=>{rb(o)},3e5)).unref(),rS.set(o,{artifactPath:n.artifactPath,tempDir:n.tempDir,tenantId:n.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:f}))}catch(r){let e=V(r);t.statusCode=rF(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rW(e,t,r,a){let n=e.url?.slice("/artifacts/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let o=rU({},e.headers),s=rJ(o,a);if(s){t.statusCode=rF(s.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.message,code:s.code}));return}let l=await rH(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:o,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 u=function(e,t){let r=rv.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 rI(e),new j("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),d=i.createReadStream(u.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),u.fileName&&t.setHeader("content-disposition",`attachment; filename="${u.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=V(e);t.statusCode=rF(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rI(n)}),d.pipe(t)}catch(r){let e=V(r);t.statusCode=rF(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rJ(e,t){return t&&e!==t?V(new j("UNAUTHORIZED","Invalid token")):null}function rZ(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rX(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rY(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 rQ{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=rY(e.backend),r=b(e.tenantId);if(!r)throw new j("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=rZ(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),o=this.bindingKey(r,i,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,n);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),u={leaseId:a.randomBytes(16).toString("hex"),tenantId:r,runId:i,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+n};return this.leases.set(u.leaseId,u),this.runBindings.set(o,u.leaseId),{...u}}heartbeatLease(e){let t=rX(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=rX(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=rY(e.backend),r=b(e.tenantId);if(!r)throw new j("INVALID_ARGS","tenant isolation requires tenant id.");let a=rZ(e.runId);if(!a)throw new j("INVALID_ARGS","tenant isolation requires run id.");let i=rX(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=b(t),i=rZ(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 r0=z(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),r1=new Map;async function r2(e){let t=await h.mkdtemp(o.join(c.tmpdir(),"agent-device-materialized-"));try{let r=await r5(e.installablePath,o.join(t,"installable")),i=e.archivePath?await r5(e.archivePath,o.join(t,"archive")):void 0,n=a.randomUUID(),s=e.ttlMs??r0,l=Date.now()+s,u=setTimeout(()=>{r3(n)},s);return r1.set(n,{rootPath:t,installablePath:r,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:l,timer:u}),{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 r3(e,t){let r=r1.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),r1.delete(e),await h.rm(r.rootPath,{recursive:!0,force:!0})}async function r8(e){let t=Array.from(r1.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await r3(e)}))}async function r5(e,t){let r=await h.stat(e);await h.mkdir(t,{recursive:!0});let a=o.join(t,o.basename(e));return r.isDirectory()?await h.cp(e,a,{recursive:!0}):await h.copyFile(e,a),a}async function r4(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 eX(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 ep(e.flags??{});return await eX(a),a}async function r9(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);try{let e,n,o,s=(n=function(e){let t=e.meta?.installSource;if(!t)throw new 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),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:rA(o,t.meta?.tenantId)},cleanup:()=>{rb(o)}}:{source:n,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new j("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),u=await r4({session:i,flags:t.flags});if(!e9("install",u))return eu("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let d=tt(t.meta?.requestId);if("ios"===u.platform){let e,{installIosInstallablePath:n}=await import("../3918.js"),{prepareIosInstallArtifact:o}=await import("../3918.js"),c=await o(s.source,{signal:d});try{if(l.enabled&&(e=await r2({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(u,c.installablePath),!c.bundleId)throw new j("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=_(o,r6(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await r3(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await import("../3918.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("../3918.js"),p=await c(s.source,{signal:d});try{l.enabled&&(e=await r2({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await f(u,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:o}=await import("../3918.js"),s=o(n),d={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=_(d,r6(d));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await r3(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:V(e)}}}function r6(e){return`Installed: ${I(e)}`}async function r7(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 r3(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:V(e)}}}let ae=z(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),at=z(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function ar(e,t,r){return t||aa(r)?null:eu("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function aa(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function ai(e){return"ios"===e.platform&&"simulator"===e.kind}async function an(e,t){ai(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function ao(e){let t=aa(e.flags)||!e.session?await ep(e.flags??{}):await as(e.session.device);return!1!==e.ensureReady&&await eX(t),t}async function as(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 ep(t)}catch(e){if(!(e instanceof j)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await ep({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function al(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 au="shared_prefs/ReactNativeDevPrefs.xml",ad="debug_http_host",ac="dev_server_https",af="RCT_jsLocation",ap="RCT_packager_scheme",am="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.",ah='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function ag(e){return void 0!==$(e)}async function aw(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=$(a);if(i){if("android"===t.platform)return void await av(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await ab(t,r,i)}}async function ay(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await aI(t,r);"ios"===t.platform&&"simulator"===t.kind&&await a_(t,r)}}async function av(e,t,r){var a,i,n,o,s,l;let u,d;aD(t);let c=(a=await aS(e,t),i=ad,n=`${r.host}:${r.port}`,u=` <string name="${aM(i)}">${aM(n)}</string>`,ak(ax(a,i),u));o=c,s=ac,l="https"===r.scheme,d=` <boolean name="${aM(s)}" value="${l?"true":"false"}" />`,c=ak(ax(o,s),d),await aA(e,t,c)}async function aI(e,t){aD(t);let r=await aS(e,t),a=ax(r,ad),i=ax(a,ac);i!==r&&await aA(e,t,i)}async function aS(e,t){let r=await H("adb",eU(e,["shell","run-as",t,"cat",au]),{allowFailure:!0});return 0!==r.exitCode?ah:aN(r.stdout)}async function aA(e,t,r){let a=eU(e,["shell","run-as",t,"id"]),i=await H("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=aP(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?am:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await H("adb",eU(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await H("adb",eU(e,["shell","run-as",t,"tee",au]),{stdin:r.trimEnd()})}catch(a){let e=G(a);if("TOOL_MISSING"===e.code)throw e;let r=aP("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?am:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function ab(e,t,r){await H("xcrun",e0(e,["spawn",e.id,"defaults","write",t,af,"-string",`${r.host}:${r.port}`])),await H("xcrun",e0(e,["spawn",e.id,"defaults","write",t,ap,"-string",r.scheme]))}async function a_(e,t){await H("xcrun",e0(e,["spawn",e.id,"defaults","delete",t,af]),{allowFailure:!0}),await H("xcrun",e0(e,["spawn",e.id,"defaults","delete",t,ap]),{allowFailure:!0})}function aN(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
6
|
+
`:ah}function ak(e,t){return aN(e).replace("</map>",`${t}
|
|
7
|
+
</map>`)}function ax(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return aN(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 aD(e){if("binary"!==ev(e))return;let t=eq(e);throw new j("INVALID_ARGS",t,{package:e,hint:t})}function aM(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function aP(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 aL=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function aR(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function aO(e,t){if(void 0!==e){if("string"!=typeof e)throw new j("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return E(e)}}function aE(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 aC(e){if("ios"===e||"android"===e)return e}async function a$(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!ag(r)||ag(a)||await ay({device:i.device,appId:i.appBundleId})}async function aT(e){var t,r;let{req:a,sessionName:i,sessionStore:n}=e,o=(a.positionals?.[0]??"show").toLowerCase(),s=n.get(i),l=n.getRuntimeHints(i);if(!["set","show","clear"].includes(o))return eu("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){ag(l)&&s?.appBundleId&&await ay({device:s.device,appId:s.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===o)return{ok:!0,data:{session:i,configured:!!l,runtime:l}};let u=aC(te(a.flags?.platform)??l?.platform??s?.device.platform);if(!u)return eu("INVALID_ARGS","runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first.");if(s&&s.device.platform!==u)return eu("INVALID_ARGS",`runtime set targets ${u}, but session "${i}" is already bound to ${s.device.platform}.`);let d={platform:(t=a.flags,r={platform:u,metroHost:E(t?.metroHost),metroPort:aE(t?.metroPort),bundleUrl:E(t?.bundleUrl),launchUrl:E(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===aR(d)?eu("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(n.setRuntimeHints(i,d),{ok:!0,data:{session:i,configured:!0,runtime:d}})}let aF="open-command-roundtrip",aU="Not implemented for this platform in this release.",aG=new Set(["app","desktop","frontmost-app"]);async function aV(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await e3();return{appBundleId:t.bundleId,appName:t.appName}}async function aj(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return eN(t)?"macos"===e.platform?void 0:"device"===e.kind?eJ(r,t):void 0:await aq(e,t)}async function aq(e,t){try{let{resolveIosApp:r}=await import("../3918.js");return await r(e,t)}catch{return}}async function aH(e,t){if(!("android"!==e.platform||!t||eN(t)))try{let{resolveAndroidApp:r}=await import("../3918.js"),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function aB(e,t,r,a){return await aj(e,t,r)??await a(e,t)??("android"===e.platform&&t&&eN(t)?r:void 0)}function az(e){return eu("INVALID_ARGS",e)}function aK(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=tr(r);if(!aG.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?tr(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 eu(e instanceof j?e.code:"INVALID_ARGS",String(e.message))}}function aW(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&eN(r)?az("open --relaunch does not support URL targets."):"app"!==a?az("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===ev(r)?az(eq(r)):null:null}async function aJ(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await eX(i);let{appBundleId:l,appName:u}=await aZ({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),d=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=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=>!aL.includes(e));if(i)throw new j("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${aL.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:aO(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 aE(e)}}(t.metroPort),bundleUrl:aO(t.bundleUrl,"bundleUrl"),launchUrl:aO(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:aC(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=aC(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:o&&aR(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=G(t);return eu(e.code,e.message,e.details)}}({req:t,sessionStore:a,sessionName:r,device:i});if(!d.ok)return{type:"response",response:d};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=d.data;await a$({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:u,runtime:d.data.runtime}}}async function aZ(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await aV(r);return{appBundleId:n.appBundleId??await aB(t,a,i,aH),appName:n.appName??a}}let aX=new Map;async function aY(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await ei(t.id),await X(t,"close",[r],a,i),await an(t,ae)}async function aQ(e){let{runtime:t,device:r,req:a,logPath:i,appBundleId:n,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let u=s[0]?.trim();!u||eN(u)||await X(r,"open",[l],a.flags?.out,{...eC(i,a.flags,n,o)})}async function a0(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:u,openPositionals:d,appName:c,surface:f,appBundleId:p,runtime:m,existingSession:h}=e,g=i.flags?.relaunch===!0,w=h?.trace?.outPath;if(g&&u){let e=p??u;await aY({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...eC(s,i.flags,p??h?.appBundleId,w)}})}await aw({device:l,appId:p,runtime:m});let y=Date.now();await X(l,"open",d,i.flags?.out,{...eC(s,i.flags,p)}),await aQ({runtime:m,device:l,req:i,logPath:s,appBundleId:p,traceLogPath:w,openPositionals:d});let v=u?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:aF,appTarget:u,appBundleId:p}:void 0;if(await an(l,at),eF(i.meta?.requestId)){let e=eo();return eu(e.code,e.message,e.details)}h&&ti(h,"open",h.snapshot);let I=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:n,device:l,surface:f,appBundleId:p,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===aR(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let S=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:i,startup:n,device:o,runtime:s,runtimeHintCount:l}=e,u={session:t,surface:i};return r&&(u.appName=r),a&&(u.appBundleId=a),n&&(u.startup=n),s&&l(s)>0&&(u.runtime=s),o&&(u.platform=o.platform,u.target=o.target??"mobile",u.device=o.name,u.id=o.id,u.kind=o.kind,"android"===o.platform&&(u.serial=o.id)),o?.platform==="ios"&&(u.device_udid=o.id,u.ios_simulator_device_set=o.simulatorSetPath??null),{...u,...L(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:p,surface:f,startup:v,device:l,runtime:m,runtimeHintCount:aR});return o.recordAction(I,{command:"open",positionals:d,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:S}),o.set(n,I),{ok:!0,data:S}}async function a1(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return eu("SESSION_NOT_FOUND",`Session "${r}" not found.`);let n=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(n?e.appName:void 0),l=aK(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?az("open --relaunch requires an app name or an active session app."):az("Session already active. Close it first or pass a new --session name.");let u=aW({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(u)return u;let d=await as(e.device),c=await aJ({req:t,sessionName:r,sessionStore:i,device:d,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await a0({req:t,sessionName:r,sessionStore:i,logPath:a,device:d,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return az("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&eN(r)?az("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===ev(r)?az(eq(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await ep(t.flags??{}),u=aK(l,t.flags?.surface,o);if("string"!=typeof u)return u;let d=aW({shouldRelaunch:n,openTarget:o,surface:u,device:l});return d||await eg(aX,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return eu("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name});let n=await aJ({req:t,sessionName:r,sessionStore:i,device:l,surface:u,openTarget:o});return"response"===n.type?n.response:await a0({req:t,sessionName:r,sessionStore:i,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:n.details.appBundleId,appName:n.details.appName,runtime:n.details.runtime,surface:u})})}async function a2(e){let t=await H("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function a3(e){let{device:t,shutdownRequested:r}=e;if(r&&(ai(t)||"android"===t.platform&&"emulator"===t.kind))try{return ai(t)?await ea(t):await a2(t)}catch(t){let e=V(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function a8(e){if(await ei(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await eS("dismiss",t).catch(t=>{O({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function a5(e,t){e.appLog&&await rg(e.appLog),e7(e.device.platform)&&await a8(e),await r8(t).catch(()=>{})}async function a4(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return eu("SESSION_NOT_FOUND","No active session");n.appLog&&await rg(n.appLog),t.positionals&&t.positionals.length>0&&(e7(n.device.platform)&&await a8(n),await X(n.device,"close",t.positionals,t.flags?.out,{...eC(a,t.flags,n.appBundleId,n.trace?.outPath)}),await an(n.device,ae)),e7(n.device.platform)&&await a8(n),ag(i.getRuntimeHints(r))&&n.appBundleId&&await ay({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...L(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await r8(r).catch(()=>{}),i.delete(r);let o=await a3({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:_({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...L(`Closed: ${r}`)}}}let a9=["platform","target","device","udid","serial","verbose","out"];function a6(e,t){let r=e??{};for(let e of a9)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let a7={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await import("../3918.js");return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await import("../3918.js");return await a(e,t,r)}},ie={ios:async(e,t,r)=>{let{installIosApp:a}=await import("../3918.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("../3918.js"),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function it(e){let{req:t,command:r,sessionName:a,sessionStore:n,deployOps:o}=e,s=n.get(a),l=t.flags??{},u=ar(r,s,l);if(u)return u;let d=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!d||!c)return eu("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let f=t.meta?.uploadedArtifactId;try{var p;let e,a=f?rA(f,t.meta?.tenantId):tG.expandHome(c);if(!i.existsSync(a))return eu("INVALID_ARGS",`App binary not found: ${a}`);let u=await ao({session:s,flags:l,ensureReady:!1});if(!e9(r,u))return eu("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===u.platform){let t=await o.ios(u,d,a),r=t.bundleId;e=r?{app:d,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await o.android(u,d,a),r=t.package;e=r?{app:d,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:d,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=_(e,(p=e,`Installed: ${p.appName??R(p)}`));return s&&n.recordAction(s,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&rb(f)}}async function ir(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return eu("INVALID_ARGS",`Unsupported batch on-error mode: ${a}.`);let i=e.flags?.batchMaxSteps??eI;if(!Number.isInteger(i)||i<1||i>1e3)return eu("INVALID_ARGS",`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`);try{let a=Y(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await ia(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=G(t);return eu(e.code,e.message,e.details)}}async function ia(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{};return a6(e,n)}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:void 0===r.runtime?e.runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}async function ii(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:u}=e;if("darwin"!==process.platform)throw new j("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let d={simulatorSetPath:o??void 0};if(s){let e=await io({deviceName:i,runtime:n,simctlOpts:d});e?(t=e.udid,r=e.runtime,a=!1):(t=(await is({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await il(t,d),a=!0)}else t=(await is({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await il(t,d),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await u(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function io(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await H("xcrun",Z(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:e8});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||iu(a).includes(iu(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 is(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await H("xcrun",Z(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 o=String(n.stdout??"").trim();if(!o)throw new j("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function il(e,t){let r=await H("xcrun",Z(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:e8});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 iu(e){return e.toLowerCase().replace(/[._-]/g,"")}async function id(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=ez(e.iosSimulatorDeviceSet);if(!r)return eu("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await ii({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:eX});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=G(t);return eu(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=K(t.flags?.androidDeviceAllowlist),a=te(t.flags?.platform),i=J({simulatorSetPath:ez(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("../3918.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("../3918.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("../3918.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("../3918.js");try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=G(t);return eu(e.code,e.message,e.details)}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=ar(t.command,e,i);if(n)return n;let o=await ao({session:e,flags:i,ensureReady:!0});if(!e9("apps",o))return eu("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(e7(o.platform)){let{listIosApps:e}=await import("../3918.js");return{ok:!0,data:{apps:(await e(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await import("../3918.js");return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function ic(e){let{ensureAndroidEmulatorBooted:t}=await import("../3918.js");return await t(e)}let ip='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',im='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function ih(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=te(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return eu("SESSION_NOT_FOUND","ios"===o?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`);let s=ar("appstate",i,n);if(s)return s;let l=e7(i?.device.platform)&&function(e,t){if(!t)return!1;if(!aa(e))return!0;let r=te(e?.platform);return!(r&&!e4(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"===o&&!l)return eu("SESSION_NOT_FOUND",ip);if("macos"===o&&!l)return eu("SESSION_NOT_FOUND",im);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 eu("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 u=await ao({session:i,flags:n,ensureReady:!0});if("ios"===u.platform)return eu("SESSION_NOT_FOUND",ip);if("macos"===u.platform)return eu("SESSION_NOT_FOUND",im);let{getAndroidAppState:d}=await import("../3918.js"),c=await d(u);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function ig(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=ar(t.command,i,n);if(o)return o;let s="android"===(te(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!s)return eu("INVALID_ARGS","boot --headless is supported only for Android emulators.");let u=al({flags:n,sessionDevice:i?.device}),d=s&&!!u,c=!1;try{e=await ao({session:i,flags:n,ensureReady:!1})}catch(r){let t=G(r);if(s&&l&&!u&&"DEVICE_NOT_FOUND"===t.code)return eu("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!d||"DEVICE_NOT_FOUND"!==t.code||!u)throw r;e=await ic({avdName:u,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return eu("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return eu("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=al({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return eu("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await ic({avdName:t,serial:n.serial,headless:!0})}await eX(e)}else("android"!==e.platform||!0!==e.booted)&&await eX(e);return e9("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:eu("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await ih({req:t,sessionName:r,sessionStore:a}):null}function iw(e){return Math.round(10*e)/10}let iy="adb-shell-dumpsys-cpuinfo",iv="adb-shell-dumpsys-meminfo";async function iI(e,t){try{let r=await H("adb",eU(e,["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,o;let e=r.trim();if(0===e.length)continue;let s=e.match(/^([0-9]+(?:\.[0-9]+)?)%\s+\d+\/([^\s]+):\s/);if(!s)continue;let l=Number(s[1]),u=s[2];Number.isFinite(l)&&(n=u,o=t,n===o||n.startsWith(`${o}:`))&&(i+=l,a.add(u))}return{usagePercent:iw(i),measuredAt:r,method:iy,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw iA("cpu",t,e)}}async function iS(e,t){try{let r=await H("adb",eU(e,["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=ib(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!==i_(e));if(!r)break;return i_(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:ib(e,"TOTAL RSS"),measuredAt:r,method:iv}}(r.stdout,t,new Date().toISOString())}catch(e){throw iA("memory",t,e)}}function iA(e,t,r){return r instanceof j&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new j(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof j?r:new j("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function ib(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return i_(a[1])??void 0}function i_(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let iN="ps-process-snapshot",ik="ps-process-snapshot",ix="xctrace-activity-monitor",iD="xctrace-activity-monitor";async function iM(e,t){if("ios"===e.platform&&"device"===e.kind)return await iR(e,t);let r=await iL(e,t),a=await iF(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(),n=tI(a.map(e=>o.basename(iU(e.command))));return iG({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:n,cpuMethod:iN,memoryMethod:ik})}async function iP(e){let t=e2(e),r=iV(t,e=>"schema"===e.name&&"activity-monitor-process-live"===e.attributes.name);if(!r)throw new j("COMMAND_FAILED","Failed to parse xctrace activity-monitor-process-live schema");let a=r.children.filter(e=>"col"===e.name).map(e=>{let t;return t=e.children.find(e=>"mnemonic"===e.name),t?.text??null??""}),i=a.indexOf("pid"),n=a.indexOf("process"),o=a.indexOf("cpu-total"),s=a.indexOf("memory-real");if(i<0||n<0||o<0||s<0)throw new j("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let l=function e(t,r){let a=[];for(let i of t)r(i)&&a.push(i),a.push(...e(i.children,r));return a}(t,e=>"row"===e.name),u=[],d=new Map;for(let e of l){var c,f;let t=e.children;if(0===t.length)continue;for(let e of t){let t=iV(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:iH(e)})}let r=iq(t[i],d),a=(c=t[n],f=d,c?c.attributes.ref?f.get(c.attributes.ref)?.processName??null:iH(c):null);null!==r&&Number.isFinite(r)&&a&&u.push({pid:r,processName:a,cpuTimeNs:iq(t[o],d),residentMemoryBytes:iq(t[s],d)})}return u}async function iL(e,t){let r="macos"===e.platform?await i$(t):await iT(e,t),a="macos"===e.platform?o.join(r,"Contents","Info.plist"):o.join(r,"Info.plist"),i=await eY(a,"CFBundleExecutable");if(!i)throw new j("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?o.join(r,"Contents","MacOS",i):void 0}}async function iR(e,t){let r=await iO(e,t),a=await iE(e,t),i=await iE(e,t),n=iC(await iP(a.xml),r,t,e),o=iC(await iP(i.xml),r,t,e),s=i.capturedAtMs-a.capturedAtMs;if(s<=0)throw new j("COMMAND_FAILED",`Invalid Activity Monitor sample window for ${t}`,{appBundleId:t,deviceId:e.id});if(null===n.cpuTimeNs||null===o.cpuTimeNs||null===o.residentMemoryBytes)throw new j("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 iG({usagePercent:Math.max(0,o.cpuTimeNs-n.cpuTimeNs)/(1e6*s)*100,residentMemoryKb:o.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:o.matchedProcesses,cpuMethod:ix,memoryMethod:iD})}async function iO(e,t){let r=(await e5(e,"all")).find(e=>e.bundleId===t);if(!r)throw new j("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new j("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let a=r.url.replace(/\/$/,""),i=u(a),n=(await e6(e)).filter(e=>e.executable.startsWith(`${a}/`));if(0===n.length)throw new j("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 iE(e,t){let r=await n.mkdtemp(o.join(c.tmpdir(),"agent-device-ios-perf-")),a=o.join(r,"sample.trace"),i=o.join(r,"activity-monitor-process-live.xml");try{let r=["xctrace","record","--template","Activity Monitor","--device",e.id,"--all-processes","--time-limit","1s","--output",a,"--quiet","--no-prompt"],o=await H("xcrun",r,{allowFailure:!0,timeoutMs:6e4}),s=Date.now();if(0!==o.exitCode)throw new j("COMMAND_FAILED",`Failed to record iOS device Activity Monitor sample for ${t}`,{cmd:"xcrun",args:r,exitCode:o.exitCode,stdout:o.stdout,stderr:o.stderr,appBundleId:t,deviceId:e.id,hint:iB(o.stdout,o.stderr)});let l=["xctrace","export","--input",a,"--xpath",'/trace-toc/run/data/table[@schema="activity-monitor-process-live"]',"--output",i],u=await H("xcrun",l,{allowFailure:!0,timeoutMs:15e3});if(0!==u.exitCode)throw new j("COMMAND_FAILED",`Failed to export iOS device perf sample for ${t}`,{cmd:"xcrun",args:l,exitCode:u.exitCode,stdout:u.stdout,stderr:u.stderr,appBundleId:t,deviceId:e.id,hint:iB(u.stdout,u.stderr)});return{capturedAtMs:s,xml:await n.readFile(i,"utf8")}}finally{await n.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function iC(e,t,r,a){let i=new Set(t.map(e=>e.pid)),n=new Set(t.map(e=>o.basename(u(e.executable)))),s=e.filter(e=>i.has(e.pid)||n.has(e.processName));if(0===s.length)throw new j("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 l=new Map;for(let e of s){let t=l.get(e.pid);if(!t){l.set(e.pid,e);continue}l.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:iz(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iz(t.residentMemoryBytes,e.residentMemoryBytes)})}let d=[...l.values()],c=d.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=d.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:tI(d.map(e=>e.processName))}}async function i$(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await H("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new j("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 j("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function iT(e,t){let r=e0(e,["get_app_container",e.id,t,"app"]),a=await H("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new j("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 j("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return i}async function iF(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:e0(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]),o=Number(a[3]),s=a[4].trim();Number.isFinite(i)&&Number.isFinite(n)&&Number.isFinite(o)&&t.push({pid:i,cpuPercent:n,rssKb:o,command:s})}return t})((await H("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let i;return r=e.command,a=t,i=iU(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||o.basename(i)===a.executableName})}function iU(e){let[t=""]=e.trim().split(/\s+/,1);return t}function iG(e){return{cpu:{usagePercent:iw(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 iV(e,t){for(let r of e){if(t(r))return r;let e=iV(r.children,t);if(e)return e}}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}function iH(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function iB(e,t){let r=ed(e,t);if(r)return r;let a=`${e}
|
|
9
|
+
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?eR: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 iz(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function iK(e){var t;let r=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===aF&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:aF,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)}(e.actions),a=r.at(-1),i=a?{available:!0,lastDurationMs:a.durationMs,lastMeasuredAt:a.measuredAt,method:aF,sampleCount:r.length,samples:r}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:aF},n={session:e.name,platform:e.device.platform,device:e.device.name,deviceId:e.device.id,metrics:{startup:i,fps:{available:!1,reason:aU},memory:{available:!1,reason:aU},cpu:{available:!1,reason:aU}},sampling:{startup:{method:aF,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:iv,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:iy,description:"Aggregated CPU usage for app processes matched from adb shell dumpsys cpuinfo.",unit:"percent"}};var t=e.device;if("ios"===t.platform&&"device"===t.kind)return{memory:{method:iD,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:ix,description:"Recent CPU usage snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"percent"}};let r="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{memory:{method:ik,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:iN,description:`Recent CPU usage snapshot from ${r}`,unit:"percent"}}}(e)}};if("android"!==(t=e).device.platform&&"ios"!==t.device.platform&&"macos"!==t.device.platform)return n;if(!e.appBundleId){let t="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.";return n.metrics.memory={available:!1,reason:t},n.metrics.cpu={available:!1,reason:t},n}let[o,s]=await iW(e);return n.metrics.memory=iJ(o),n.metrics.cpu=iJ(s),n}async function iW(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,a]=await Promise.allSettled([iS(e.device,t),iI(e.device,t)]);return[r,a]}try{let r=await iM(e.device,t);return[{status:"fulfilled",value:r.memory},{status:"fulfilled",value:r.cpu}]}catch(e){return[{status:"rejected",reason:e},{status:"rejected",reason:e}]}}function iJ(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=V(e.reason);return{available:!1,reason:t.message,error:t}}let iZ=["path","start","stop","doctor","mark","clear"],iX=`logs requires ${iZ.slice(0,-1).join(", ")}, or ${iZ.at(-1)}`,iY=["dump","log"],iQ=`network requires ${iY.join(" or ")}`,i0=["summary","headers","body","all"],i1=`network include mode must be one of: ${i0.join(", ")}`;async function i2(e){let{req:t}=e;return"perf"===t.command?i3(e):"logs"===t.command?i8(e):"network"===t.command?i7(e):null}async function i3(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return eu("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await iK(a)}}catch(e){return{ok:!1,error:V(e)}}}async function i8(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return eu("SESSION_NOT_FOUND","logs requires an active session");if(!e9("logs",n.device))return eu("UNSUPPORTED_OPERATION","logs is not supported on this device");let o=(t.positionals?.[0]??"path").toLowerCase(),s=!!t.flags?.restart;return iZ.includes(o)?s&&"clear"!==o?eu("INVALID_ARGS","logs --restart is only supported with logs clear"):"path"===o?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"===o?i5(n,r,a):"mark"===o?function(e,t,r){let a,n=e.positionals?.slice(1).join(" ")??"",o=r.resolveAppLogPath(t);return rc(o),a=`[agent-device][mark][${new Date().toISOString()}] ${n.trim()||"marker"}
|
|
10
|
+
`,i.appendFileSync(o,a,"utf8"),{ok:!0,data:{path:o,marked:!0}}}(t,r,a):"clear"===o?i4(n,r,a,s):"start"===o?i9(n,r,a):"stop"===o?i6(n,r,a):eu("INVALID_ARGS",iX):eu("INVALID_ARGS",iX)}async function i5(e,t,r){let a=r.resolveAppLogPath(t),i=await rw(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 i4(e,t,r,a){if(e.appLog&&!a)return eu("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return eu("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let i=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:ry(i)};e.appLog&&await rg(e.appLog);let n=ry(i),o=r.resolveAppLogPidPath(t);try{let a=await rm(e.device,e.appBundleId,i,o);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:V(a)}}}async function i9(e,t,r){if(e.appLog)return eu("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return eu("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 rm(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:V(e)}}}async function i6(e,t,r){if(!e.appLog)return eu("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await rg(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function i7(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return eu("SESSION_NOT_FOUND","network requires an active session");if(!e9("network",i.device))return eu("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!iY.includes(n))return eu("INVALID_ARGS",iQ);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return eu("INVALID_ARGS","network dump limit must be an integer in range 1..200");let s=function(e){let t=e.positionals?.[2]?.toLowerCase(),r=e.flags?.networkInclude;if(t&&r&&t!==r)return eu("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return i0.includes(a)?{ok:!0,include:a}:eu("INVALID_ARGS",i1)}(t);if(!s.ok)return s;let{include:l}=s,u=await rf({device:i.device,appBundleId:i.appBundleId,appLogState:i.appLog?.getState(),appLogStartedAt:i.appLog?.startedAt,appLogPath:a.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...u.dump,active:!!i.appLog,state:i.appLog?.getState()??"inactive",backend:u.backend,notes:u.notes}}}let ne=/^[A-Z_][A-Z0-9_]*$/,nt=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-((?:[^}\\]|\\.)*))?\}/g,nr="AD_VAR_";function na(e){return e.startsWith("AD_")}function ni(e){return new j("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function nn(e,t,r){return e.replace(nt,(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 no(e,t,r){if(!e)return e;let a={...e};for(let[e,i]of Object.entries(a))"string"==typeof i&&(a[e]=nn(i,t,r));return a}let ns=new Set(["ios","android","macos","linux"]);function nl(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(nu(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(!ne.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&&ns.has(e)&&nd(r,"platform",e)}let n=a.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&nd(r,"timeoutMs",Math.floor(e))}let o=a.match(/(?:^|\s)retries=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=0&&nd(r,"retries",Math.floor(e))}}return r}function nu(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function nd(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 nc(e){return!!e&&!Number.isNaN(Number(e))}let nf=/[*?[\]{}]/;async function np(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,artifactsDir:s,runReplay:l,cleanupSession:u}=e;el(i);let d=new Set,c=!1,f=l({filePath:r,sessionName:a,platform:o,requestId:i,artifactsDir:s,artifactPaths:d}).catch(e=>{let t=G(e);return eu(t.code,t.message)}).finally(()=>{eQ(i)});try{return"number"==typeof n?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{c=!0,eK(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,[...d]))},n)})]):await f}finally{t&&clearTimeout(t),c&&(await nm(f)||O({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await u(a)}catch(e){O({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:G(e).message}})}}}async function nm(e){return await Promise.race([e.then(()=>!0),g(2e3).then(()=>!1)])}async function nh(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:n}=e;if((t.positionals?.length??0)===0)return eu("INVALID_ARGS","test requires at least one path or glob");try{var s,l,u,d,c,f;let e,p,m,h,g,w=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,n=r??process.cwd(),s=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let n=tG.expandHome(e,t);if(i.existsSync(n)){let t=i.statSync(n);if(t.isDirectory())return i.globSync("**/*.ad",{cwd:n}).map(e=>o.join(n,e));if(t.isFile()){if(".ad"!==o.extname(n))throw new j("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[n]}return[]}if(r=e,!nf.test(r)&&(a=n,!nf.test(a)))throw new j("INVALID_ARGS",`test input not found: ${e}`);let s=o.isAbsolute(n)?n:e;return i.globSync(s,{cwd:o.isAbsolute(n)?void 0:t}).map(e=>o.isAbsolute(e)?e:o.resolve(t,e)).filter(e=>".ad"===o.extname(e)&&function(e){try{return i.statSync(e).isFile()}catch{return!1}}(e))})(e,n)))].map(e=>o.normalize(e)).sort((e,t)=>e.localeCompare(t)),l=[];for(let e of s){var u,d;let t=nl(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}u=a,d=t.platform,("apple"===u?"apple"===d||"ios"===d||"macos"===d:d===u)&&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=(s=t.meta?.requestId,(s?.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=tG.expandHome(t??".agent-device/test-artifacts",r);return o.join(i,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),I=[],S=Date.now(),A=0;for(let e of w){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}A+=1;let i=await ng({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,u=e.metadata.timeoutMs,"number"==typeof l?l:u),suiteArtifactsDir:v,runReplay:a,cleanupSession:n});if(I.push(i),t.flags?.failFast===!0)break}let b=(d=w.length,c=I,f=Date.now()-S,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:d,executed:g,passed:e,failed:m,skipped:h,notRun:Math.max(0,d-g-h),durationMs:f,failures:p,tests:c});return{ok:!0,data:b}}catch(t){let e=G(t);return eu(e.code,e.message)}}async function ng(e){var t,r;let a,n,{entry:s,sessionName:l,suiteInvocationId:u,caseIndex:d,cwd:c,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:g,cleanupSession:w}=e,y=Date.now(),v=o.join(h,(t=s.path,(0===(n=c?o.relative(c,t):o.basename(t)).length||n.startsWith("..")?o.basename(t):n).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",S=0;for(let e=0;e<=p;e+=1){S=e+1;let t=function(e,t,r,a,i=0){let n=o.basename(r,o.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${n?`-${n}`:""}:attempt-${i+1}`}(l,u,s.path,d,e),n=o.join(v,`attempt-${S}`);r=s.path,i.mkdirSync(n,{recursive:!0}),i.copyFileSync(r,o.join(n,"replay.ad"));let c=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:n}=e;return eT(`${t??r}:test:${i+1}:${o.basename(a)}:attempt:${n+1}`,r)}({requestId:f,suiteInvocationId:u,filePath:s.path,caseIndex:d,attemptIndex:e}),h=await np({filePath:s.path,sessionName:t,requestId:c,timeoutMs:m,platform:s.metadata.platform,artifactsDir:n,runReplay:g,cleanupSession:w});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:n,maxAttempts:s,attemptArtifactsDir:l}=e,u=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||u.push(t.error.logPath);let d=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=o.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}`}(o.basename(n),a),s=o.join(t,e);o.resolve(n)!==o.resolve(s)&&i.copyFileSync(n,s),r.push(s)}return r}(u,l),c=[`file: ${r}`,`session: ${a}`,`attempt: ${n}/${s}`,`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");d.length>0&&c.push(`copiedArtifacts: ${d.map(e=>o.basename(e)).join(", ")}`);let f=o.join(l,"result.txt"),p=`${c.join("\n")}
|
|
11
|
+
`;i.writeFileSync(f,p),t.ok||i.writeFileSync(o.join(l,"failure.txt"),p)}({response:h,filePath:s.path,sessionName:t,attempts:S,maxAttempts:p+1,attemptArtifactsDir:n}),a=h,I=t,h.ok)break}let A=Date.now()-y;if(a?.ok)return{file:s.path,session:I,status:"passed",durationMs:A,attempts:S,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:s.path,session:I,status:"failed",durationMs:A,attempts:S,artifactsDir:v,error:b}}function nw(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=tn(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 ny(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(tk(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let n=i.get(r);if(!n)return null;let o=(function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),tk(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}=tl(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=nw(e.positionals??[]);r&&t.push(r)}return tI(t).filter(e=>e.trim().length>0)})(t).map(e=>tu(e)).filter(e=>null!==e);if(0===o.length)return null;let s=tk(t.command)||"fill"===t.command,l=tk(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await nv(n,t,a,s,i);for(let e of o){let r=td(u.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=tf(r.node,n.device.platform,{action:tk(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tk(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=tv(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}=tl(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}=nw(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function nv(e,t,r,a,i){let n=await X(e.device,"snapshot",[],t.flags?.out,{...eC(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:th(t.flags?.snapshotRaw?o:tm(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return eh(e,s),i.set(e.name,e),s}async function nI(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:s}=e,l=t.positionals?.[0];if(!l)return eu("INVALID_ARGS","replay requires a path");let u="",d=new Set;try{var c;let e;u=tG.expandHome(l,t.meta?.cwd);let f=i.readFileSync(u,"utf8"),p=f.trimStart()[0];if("{"===p||"["===p)return eu("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let m=nl(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],o=n.trim();if(0===o.length||o.startsWith("#"))continue;if(nu(o)){if(i)throw new j("INVALID_ARGS",`env directives must precede all actions (line ${e+1}).`);continue}let s=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){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=tT(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=tT(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tk(a)){let e=t$(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],o=e.positionals[1];return nc(r)&&nc(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=t$(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=t$(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);s&&(t.push(s),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 eu("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 eu("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(na(e))throw ni(e);t[e]=a}return{values:t}}({builtins:function(e){let{req:t,sessionName:r,metadata:a,resolvedPath:i}=e,n=t.flags??{},s=t.meta?.cwd??process.cwd(),l={AD_SESSION:r,AD_FILENAME:o.relative(s,i)||i},u=n.platform??a.platform;u&&(l.AD_PLATFORM=u);let d=n.device;"string"==typeof d&&d.length>0&&(l.AD_DEVICE=d);let c=n.artifactsDir;return"string"==typeof c&&c.length>0&&(l.AD_ARTIFACTS=c),l}({req:t,sessionName:r,metadata:m,resolvedPath:u}),fileEnv:m.env,shellEnv:function(e){let t={};for(let[r,a]of Object.entries(e)){if("string"!=typeof a||!r.startsWith(nr))continue;let e=r.slice(nr.length);0!==e.length&&ne.test(e)&&(na(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(!ne.test(a))throw new j("INVALID_ARGS",`Invalid -e key "${a}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(na(a))throw ni(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,I=0;for(let e=0;e<g.length;e+=1){let i=g[e];if(!i||"replay"===i.command)continue;let o=await nS({req:t,sessionName:r,action:i,scope:y,filePath:u,line:w[e]??0,invoke:s});if(o.ok){nb(o).forEach(e=>d.add(e));continue}if(!v)return nA(o,i,e,u,[...d]);let l=await ny({action:i,sessionName:r,logPath:a,sessionStore:n});if(!l)return nA(o,i,e,u,[...d]);if(g[e]=l,!(o=await nS({req:t,sessionName:r,action:l,scope:y,filePath:u,line:w[e]??0,invoke:s})).ok)return nA(o,l,e,u,[...d]);nb(o).forEach(e=>d.add(e)),I+=1}return v&&I>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=${tM(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",tD(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tU(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tP(r,tR));return tE(t,e.flags),t.join(" ")}if("record"===e.command)return tC(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tD(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(tD(r));return tO(t,e),t.join(" ")}(e));let n=`${a.join("\n")}
|
|
12
|
+
`,o=`${e}.tmp-${process.pid}-${Date.now()}`;i.writeFileSync(o,n),i.renameSync(o,e)}(u,g,n.get(r)),{ok:!0,data:{replayed:g.length,healed:I,session:r,artifactPaths:[...d]}}}catch(t){let e=G(t);return eu(e.code,e.message,d.size>0?{artifactPaths:[...d]}:void 0)}}async function nS(e){var t,r;let{req:a,sessionName:i,action:n,scope:o,filePath:s,line:l,invoke:u}=e,d=(t={file:s,line:l},{...n,positionals:(n.positionals??[]).map(e=>nn(e,o,t)),flags:no(n.flags,o,t)??{},runtime:no(n.runtime,o,t)});return await u({token:a.token,session:i,command:d.command,positionals:d.positionals??[],flags:(r=a.flags,a6(r,{...d.flags??{}})),runtime:d.runtime,meta:a.meta})}function nA(e,t,r,a,i=[]){let n;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${n=(t.positionals??[]).map(e=>tD(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:o,action:t.command,positionals:t.positionals??[],artifactPaths:i}}}}function nb(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 n_(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await nI({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await nh({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactsDir:l,artifactPaths:u})=>{let d=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:o,artifactsDir:l});return await nI({req:{...t,command:"replay",session:r,positionals:[e],flags:d,meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),u&&nb(t).forEach(e=>u.add(e)),t}})},cleanupSession:async e=>{i.get(e)&&await a4({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let nN=new Set(["session_list","ensure-simulator","devices","apps"]),nk=new Set(["boot","appstate"]),nx=new Set(["perf","logs","network"]),nD=new Set(["replay","test"]);async function nM(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,u=i.get(r),d=t.flags??{},c=ar(n,u,d);if(c)return c;let f=await ao({session:u,flags:d,ensureReady:!0});if(!e9(n,f))return eu("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await X(f,n,o,t.flags?.out,{...eC(a,t.flags,u?.appBundleId,u?.trace?.outPath)});if(u){let e=l?await l(u,p,f):u;i.recordAction(e,{command:n,positionals:s??o,flags:t.flags??{},result:p??{}}),e!==u&&i.set(r,e)}return{ok:!0,data:p??{}}}async function nP(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=ar("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return eu("INVALID_ARGS","clipboard requires a subcommand: read or write");let u=await ao({session:n,flags:o,ensureReady:!0});if(!e9("clipboard",u))return eu("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let d=await X(u,"clipboard",t.positionals??[],t.flags?.out,{...eC(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:d??{}}),{ok:!0,data:{platform:u.platform,...d??{}}}}async function nL(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(nN.has(t.command))return await id({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await aT({req:t,sessionName:r,sessionStore:i});if(nk.has(t.command))return await ig({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await nP({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"!==te((t.flags??{}).platform)?await nM({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):eu("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(nx.has(t.command))return await i2({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await it({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?ie:a7});if("install_source"===t.command)return await r9({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await r7({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await nM({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=eG(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tG.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):eu("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await nM({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 aB(e.device,r,e.appBundleId,aH)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await a1({req:t,sessionName:r,logPath:a,sessionStore:i}):nD.has(t.command)?await n_({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await ir(t,r,n):"close"===t.command?await a4({req:t,sessionName:r,logPath:a,sessionStore:i}):null}async function nR(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return eu("INVALID_ARGS","find requires a locator or text");let{locator:l,query:u,action:d,value:c,timeoutMs:f}=ty(s);if(!u)return eu("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return eu("INVALID_ARGS","find accepts only one of --first or --last");let p=await eW({req:t,sessionName:r,logPath:a,sessionStore:i});if(p)return p;let m=i.get(r);if(!m&&"exists"!==d&&"wait"!==d&&"get_text"!==d&&"get_attrs"!==d)return eu("SESSION_NOT_FOUND","No active session. Run open first.");let h=m?.device??await ep(t.flags??{});m||await eX(h);let g="role"!==l?u:void 0,w="click"===d||"focus"===d||"fill"===d||"type"===d,y=0,v=null,I=async()=>{let e=Date.now();if(v&&e-y<750&&!e1(m))return{nodes:v};let{snapshot:n}=await eM({device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:g}),o=n.nodes;return y=e,v=o,m&&(eh(m,n),i.set(r,m)),{nodes:o,truncated:n.truncated,backend:n.backend}},S={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:m,device:h,command:o,locator:l,query:u};if("wait"===d)return nO(S,I,l,u,f);let{nodes:A}=await I(),b=tw(A,l,u,{requireRect:w});if(w&&b.matches.length>1)if(t.flags?.findFirst)b.matches=[b.matches[0]];else{if(!t.flags?.findLast){var _,N,k;let e;return _=b.matches,N=l,k=u,e=_.slice(0,8).map(e=>{let t=ts(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),eu("AMBIGUOUS_MATCH",`find matched ${_.length} elements for ${N} "${k}". Use a more specific locator or selector.`,{locator:N,query:k,matches:_.length,candidates:e})}b.matches=[b.matches[b.matches.length-1]]}let x=b.matches[0]??null;if(!x)return eu("COMMAND_FAILED","find did not match any element");let D="click"===d||"focus"===d||"fill"===d||"type"===d?to(A,x)??x:x,M=`@${D.ref}`,P={node:x,resolvedNode:D,ref:M,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},L={exists:()=>nE(S),get_text:()=>nC(S,P),get_attrs:()=>n$(S,P),click:()=>nT(S,P),fill:()=>nF(S,P,c),focus:()=>nU(S,P),type:()=>nG(S,P,c)}[d];return L?L():null}async function nO(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,u=i??1e4,d=Date.now();for(;Date.now()-d<u;){let{nodes:e}=await t();if(tw(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{found:!0,waitedMs:Date.now()-d}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-d}};await B(300)}return eu("COMMAND_FAILED","find wait timed out")}async function nE(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 nC(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await eD({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eC(s,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 n$(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 nT(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:u}=e,d=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!d.ok)return d;let c=t.resolvedNode.rect?tg(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:u};return c&&(f.x=c.x,f.y=c.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:u}}),{ok:!0,data:f}}async function nF(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return eu("INVALID_ARGS","find fill requires text");let u=await s({token:a.token,session:i,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return u.ok&&o&&n.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),u}async function nU(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?tg(t.node.rect):null;if(!l)return eu("COMMAND_FAILED","matched element has no bounds");let u=await X(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eC(s,r.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:u??{ref:t.ref}}}async function nG(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return eu("INVALID_ARGS","find type requires text");let u=t.node.rect?tg(t.node.rect):null;if(!u)return eu("COMMAND_FAILED","matched element has no bounds");await X(o,"focus",[String(u.x),String(u.y)],a.flags?.out,{...eC(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let d=await X(o,"type",[r],a.flags?.out,{...eC(l,a.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:s,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:d??{ref:t.ref}}}let nV=`
|
|
13
13
|
import Foundation
|
|
14
14
|
import AVFoundation
|
|
15
15
|
|
|
@@ -33,11 +33,13 @@ Task {
|
|
|
33
33
|
|
|
34
34
|
semaphore.wait()
|
|
35
35
|
exit(exitCode)
|
|
36
|
-
`.trim();async function
|
|
37
|
-
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return nU(e);return!1}catch(t){if(t instanceof U&&"TOOL_MISSING"===t.code)return nU(e);throw t}}async function nF(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nT(e))return;await j(r)}}function nU(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),o=e.toString("latin1",4,8);if(a.push(o),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 nG(e){let t=o.parse(e);return o.join(t.dir,`${t.name}.gesture-telemetry.json`)}function nV(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nj(e){let t=o.dirname(u(import.meta.url)),r=[u(new URL(`./${e}`,import.meta.url)),o.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(i.existsSync(e))return e;throw new U("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 nq(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await n$(t),await nF(t);let s=i.mkdtempSync(o.join(c.tmpdir(),"agent-device-record-overlay-")),l=o.join(s,`input${o.extname(t)||".mp4"}`),u=o.join(s,o.basename(t)),d=o.join(s,"home"),f=o.join(s,"module-cache");i.copyFileSync(t,l),i.mkdirSync(d,{recursive:!0}),i.mkdirSync(f,{recursive:!0});try{await V("xcrun",["swift",r,"--input",l,"--output",u,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:f}}),await nF(u),i.copyFileSync(u,t)}catch(a){let e=a instanceof U?a:new U("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new U("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(s,{recursive:!0,force:!0})}}async function nH(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nq({videoPath:r,scriptPath:t??=nj("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nB(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nq({videoPath:r,scriptPath:e??=nj("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function nz(e){let{videoPath:t,quality:a,targetLabel:i="recording"}=e;await nq({videoPath:t,scriptPath:r??=nj("recording-resize.swift"),scriptArgs:["--quality",String(a)],commandDescription:`Failed to resize the ${i}`})}function nK(e){return e instanceof Error?e.message:String(e)}function nW(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function nJ(e){let{recording:t,deps:r,trimStartMs:a,targetLabel:n}=e,o=function(e){var t,r,a;let n,o,{recording:s,trimStartMs:l}=e,u=(n=nG((t={videoPath:s.outPath,events:s.gestureEvents,trimStartMs:l}).videoPath),o={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?nV(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)}]})):nV(r))},i.writeFileSync(n,JSON.stringify(o,null,2)),n);return s.telemetryPath=u,u}({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:o,targetLabel:n})}catch(e){t.overlayWarning??=`failed to overlay recording touches: ${nK(e)}`}}}async function nZ(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===a.exitCode&&a.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function nX(e,t,r){for(let a=0;a<40;a+=1){if(!await nZ(e,t,r))return!0;await j(250)}return!await nZ(e,t,r)}async function nY(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await j(250)}}async function nQ(e,t,r,a){for(let i=0;i<8;i+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?Number(n.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await nZ(e,t,a))break;if(i+1>=2)return!0;await j(250)}return!1}async function n0(e){let t,{deps:r,deviceId:a,remotePath:n,outPath:o}=e;for(let e=0;e<2;e+=1){try{i.rmSync(o,{force:!0})}catch{}let s=await r.runCmd("adb",["-s",a,"pull",n,o],{allowFailure:!0});if(0!==s.exitCode)t=nW(s,"adb pull");else{await r.waitForStableFile(o,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(o);if(P({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:n,outPath:o,attempt:e+1,fileSize:(()=>{try{return i.statSync(o).size}catch{return 0}})(),playable:t}}),t)return;P({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:n,outPath:o,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 n1(e){let{deps:t,deviceId:r,quality:a}=e;if(void 0===a||a>=10)return;let i=await t.runCmd("adb",["-s",r,"shell","wm","size"],{allowFailure:!0}),n=i.stdout.match(/Override size:\s*(\d+)x(\d+)/)??i.stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(0!==i.exitCode||!n)throw Error(`failed to resolve Android screen size for recording quality: ${nW(i,"adb shell wm size")}`);return{width:n2(Number(n[1]),a),height:n2(Number(n[2]),a)}}function n2(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function n3(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function n8(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return P({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await nZ(e,t,r))&&await nX(e,t,r)}async function n4(e){var t;let r,a,{deps:i,device:n,recordingBase:o}=e,s="failed to start recording: Android screenrecord did not begin producing frames";try{r=await n1({deps:i,deviceId:n.id,quality:o.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 i.runCmd("adb",["-s",n.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: ${nW(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 n3(i,n.id,e);continue}if(P({level:"debug",phase:"record_start_android_started",data:{deviceId:n.id,remotePath:e,remotePid:a}}),await nQ(i,n.id,e,a))return{platform:"android",remotePath:e,remotePid:a,...o,startedAt:Date.now()};s="failed to start recording: Android screenrecord did not begin producing frames",await n8(i,n.id,a),await n3(i,n.id,e)}return eH("COMMAND_FAILED",s)}async function n5(e){let t,r,{deps:a,device:i,recording:n}=e;P({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(P({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await nZ(a,i.id,n.remotePid)&&!await n8(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${nW(o,"adb shell kill")}`):await nX(a,i.id,n.remotePid)||await n8(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await nY(a,i.id,n.remotePath);let e=await n0({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),eH("COMMAND_FAILED",e);await nJ({recording:n,deps:a,targetLabel:"Android recording"})}if(await s(),t)return eH("COMMAND_FAILED",t);if(r)return eH("COMMAND_FAILED",r);return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});P({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: ${nW(e,"adb shell rm")}`)}}function n9(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function n6(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function n7(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=n9(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},n6(t,i,r))}catch(e){P({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:nK(e)}})}}async function oe(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:u,recordingBase:d,appBundleId:c}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=n6(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:f,fps:u,quality:d.quality,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var g,w;if(!nK(a).toLowerCase().includes("recording already in progress"))return eH("COMMAND_FAILED",`failed to start recording: ${nK(a)}`);P({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:nK(a)}});let e=(g=o.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(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return eH("COMMAND_FAILED",`failed to start recording: ${nK(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...d}}async function ot(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,quality:s.quality,appBundleId:l},n6(t,i,r))}catch(e){return eH("COMMAND_FAILED",`failed to start recording: ${nK(e)}`)}return{platform:"macos-runner",...s}}async function or(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=n9(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},n6(t,i,r))}catch(e){P({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nK(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of X)if(0===(l=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.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 u="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);return u>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:u}),await nJ({recording:o,deps:n,trimStartMs:u,targetLabel:"iOS recording"}),null}async function oa(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=n9(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},n6(t,i,r))}catch(e){P({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nK(e)}})}return await nJ({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function oi(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 on(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:u}=e;await n7({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:d,wait:c}=s.runCmdBackground("xcrun",eZ(n,["io",n.id,"recordVideo",u]),{allowFailure:!0}),f=await oi(u);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:n9(i)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:i.trace?.outPath}),u=Date.now();t=Math.round((e+u)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:d,wait:c,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function oo(e){let t,{req:r,sessionName:a,sessionStore:n,activeSession:s,device:l,logPath:u,deps:d}=e;if(s.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(!e3("record",l))return eH("UNSUPPORTED_OPERATION","record is not supported on this device");let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,m=t$.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(o.dirname(m),{recursive:!0}),i.rmSync(m,{force:!0}),"ios"===l.platform&&"device"===l.kind){let e=n9(s);if(!e)return eH("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await oe({req:r,activeSession:s,sessionStore:n,device:l,logPath:u,deps:d,fpsFlag:c,recordingBase:h,appBundleId:e})}else if("macos"===l.platform){let e=n9(s);if(!e)return eH("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await ot({req:r,activeSession:s,device:l,logPath:u,deps:d,fpsFlag:c,recordingBase:h,appBundleId:e})}else t="ios"===l.platform?await on({req:r,activeSession:s,device:l,logPath:u,deps:d,recordingBase:h,resolvedOut:m}):await n4({deps:d,device:l,recordingBase:h});return"ok"in t?t:(s.recording=t,n.set(a,s),n.recordAction(s,{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 os(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await n5({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: ${nW(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: ${nK(e)}`}return await nJ({recording:a,deps:t,targetLabel:"iOS recording"}),null}async function ol(e){var t;let r,{req:a,activeSession:i,device:n,logPath:s,deps:l}=e;if(!i.recording)return eH("INVALID_ARGS","no active recording");let u=i.recording,d=u.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===u.platform?await or({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):"macos-runner"===u.platform?await oa({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):await os({deps:l,device:n,recording:u});return c||(d?eH("COMMAND_FAILED",d):(r=[{field:"outPath",path:(t=u).outPath,localPath:t.clientOutPath,fileName:o.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return nG(e.clientOutPath)}(t),fileName:o.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function ou(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:V,runCmdBackground:G,runIosRunnerCommand:eB,waitForStableFile:n$,isPlayableVideo:nT,trimRecordingStart:nH,resizeRecording:nz,overlayRecordingTouches:nB},o=a.get(r),s=o?.device??await eu(t.flags??{});o||await eK(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},u=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(u))return eH("INVALID_ARGS","record requires start|stop");if("start"===u)return oo({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let d=await ol({req:t,activeSession:l,device:s,logPath:i,deps:n});return d.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:d.data?.outPath,showTouches:d.data?.showTouches}}),d}async function od(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,s=t.command;if("record"===s)return ou({req:t,sessionName:r,sessionStore:a,logPath:n});if("trace"===s){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=t$.expandHome(e);return i.mkdirSync(o.dirname(r),{recursive:!0}),i.appendFileSync(r,""),n.trace={outPath:r,startedAt:Date.now()},a.recordAction(n,{command:s,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=t$.expandHome(t.positionals[1]);i.mkdirSync(o.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:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l}}),{ok:!0,data:{trace:"stopped",outPath:l}}}return null}function oc(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 of=new WeakMap;function op(e){if(!e)return;let t=of.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)&&om(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(om);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 of.set(e,r),r}function om(e){return!!e&&e.width>0&&e.height>0}let oh={referenceWidth:1e3,referenceHeight:1e3};function og(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,u;let d,c,f=e.recording;if(!f)return;let p={...i,...a??{}},m=oI(p.effectiveDurationMs)??oI(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:oI(p.gestureStartUptimeMs),gestureEndUptimeMs:oI(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:oI(p.gestureStartUptimeMs),gestureEndUptimeMs:oI(p.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),w="ios"===e.device.platform&&void 0===oI(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=oS(oI(t.count),1)??1,r=!0===t.doubleTap,a=oS(oI(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 oc(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):oc(h),y=(l=e.snapshot,d=oI((u=p).referenceWidth),c=oI(u.referenceHeight),void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:op(l)),v=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=oA(t,e);if(!i)return[];let{x:n,y:o}=i,s=oS(oI(t.count),1)??1,l=oS(oI(t.intervalMs),0)??0,u=!0===t.doubleTap,d=oS(oI(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==d&&d>0){c.push(oy(t,n,o,d,a));continue}c.push(ow(t,n,o,a)),u&&c.push(ow(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=oA(t,e);if(!i)return[];let{x:n,y:o}=i;return[ow(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=oA(t,e);if(!n)return[];let{x:o,y:s}=n;return[oy(r,o,s,o_(a,[oI(t.durationMs),oI(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=ob(t,e),o=ov(t.contentDirection)??ov(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:u,y2:d}=n,c=o_(a,[],250),f=oI(t.amount)??oI(e[1]),p=oI(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:u,y2:d,...i,durationMs:c,contentDirection:o,...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=ob(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:u}=n,d=o_(a,[oI(t.effectiveDurationMs),oI(t.durationMs),oI(e[4])],250),c=oS(oI(t.count),1)??1,f=oS(oI(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:o,n=t?u:s,c=t?o:l,h=t?s:u,g=r+e*(d+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:d,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:d})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=oA(t,e,1),o=oI(t.scale)??oI(e[0]);if(!n||void 0===o||o<=0)return[];let{x:s,y:l}=n;return[{kind:"pinch",tMs:r,x:s,y:l,...i,scale:o,durationMs:o_(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,w,g,y);0!==v.length&&(f.gestureEvents.push(...v),P({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 ow(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function oy(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function ov(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 oI(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 oS(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function oA(e,t,r=0){let a=oI(e.x)??oI(t[r]),i=oI(e.y)??oI(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function ob(e,t){let r=oI(e.x1)??oI(t[0]),a=oI(e.y1)??oI(t[1]),i=oI(e.x2)??oI(t[2]),n=oI(e.y2)??oI(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 o_(e,t,r){return oS(e,1)??t.map(e=>oS(e,1)).find(e=>void 0!==e)??r}function oN(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:u,extra:d}=e,c=(t=d,r=s,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 o?.message?o.message:void 0));return{x:s,y:l,...u??{},...d??{},...o??{},...D(c)}}function ok(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:u,androidFreshnessBaseline:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),ei(a)&&te(t,a,d??t.snapshot),og(t,a,i,o,n??{},l,u),{ok:!0,data:s}}async function ox(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 eI(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=op(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=op(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oD(e){try{return await ox(e)}catch(t){P({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function oM(e){return op({nodes:e,createdAt:0})}function oP(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 oR(e){let t=e.sessionStore.get(e.sessionName);if(!t)throw new U("SESSION_NOT_FOUND","No active session. Run open first.");return ey({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)=>oL(await W(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)=>oL(await W(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)=>oL(await W(r.device,"type",[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),artifacts:eF("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&&(t.snapshot=r.snapshot,e.sessionStore.set(e.sessionName,t))}},policy:er()})}function oL(e){return e&&"object"==typeof e?e:void 0}function oO(e){return"ref"===e.kind?{ref:oE(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 oE(e){return e?.startsWith("@")?e.slice(1):e}async function oC(e){switch(e.req.command){case"press":case"click":return await o$(e);case"fill":return await oT(e);default:return null}}async function o$(e){let t,{req:r,sessionName:a,sessionStore:i}=e,n=i.get(a),o="click"===r.command?"click":"press";if(!n)return eH("SESSION_NOT_FOUND","No active session. Run open first.");let s=oP(n,o);if(s)return s;if(!e3("press",n.device))return eH("UNSUPPORTED_OPERATION","press is not supported on this device");let l=eN(r.flags),u=Y(l);if("primary"!==l){let e=es({commandLabel:o,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 d=function(e,t){let r=ez(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??[],o);if(!d.ok)return d.response;if("ref"===d.target.kind){let a=e.refSnapshotFlagGuardResponse("press",r.flags);if(a)return a;t=await oU(e,n)}return await oF(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"===o?await e.interactions.click(d.target,t):await e.interactions.press(d.target,t)},afterRun:async e=>{var t;await ef(n,(t=d.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 oD({session:n,flags:r.flags,sessionStore:i,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:e.captureSnapshotForSession}):oM(n.snapshot?.nodes??[]),o=oN({data:t.backendResult,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:a,extra:{...oO(t),...u}});return{result:o,responseData:o}}})}async function oT(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(i){let e=oP(i,"fill");if(e)return e}if(i&&!e3("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=ez(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=tt(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 oU(e,i)}return await oF(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:oM(i.snapshot?.nodes??[]),r=oN({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...oO(e),text:n.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:oE(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 oF(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return eH("SESSION_NOT_FOUND","No active session. Run open first.");let a=oR(e),i=Date.now();try{let n=await t.run(a);await t.afterRun?.(n);let o=Date.now(),{result:s,responseData:l}=await t.buildPayloads(n);return ok({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags,result:s,responseData:l,actionStartedAt:i,actionFinishedAt:o,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=T(t);if(eU(e))throw e;return{ok:!1,error:F(t)}}}async function oU(e,t){if(!eX(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){P({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},o=a(n,e.appBundleId,e.trace?.outPath),{snapshot:s}=await eb({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??"",androidFreshnessMode:i.androidFreshnessMode});return e.snapshot=s,r.set(e.name,e),e.snapshot}let oV=/\bis(?:n't| not)\s+responding\b/i,oj=/^close app$/i;async function oq(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oH(t),r=function(e){if(oW(e))return e.find(e=>{let t=oK(e);return t.length>0&&oj.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=tf(r.rect),n=await V("adb",eO(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return P({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 oB(t))return P({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eD(t.device,t.appBundleId),!await oz(t,t.appBundleId)))return P({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return P({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 P({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 oH(e){return tc(td((await el(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function oB(e){for(let t=0;t<12;t+=1){if(!oW(await oH(e)))return!0;await j(500)}return!oW(await oH(e))}async function oz(e,t){for(let r=0;r<12;r+=1){if((await ev(e.device)).package===t)return!0;await j(500)}return(await ev(e.device)).package===t}function oK(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 oW(e){return e.some(e=>{let t=oK(e);return t.length>0&&oV.test(t)})}async function oJ(e){let t=await oC({...e,captureSnapshotForSession:oG,refSnapshotFlagGuardResponse:Z});if(t)return t;switch(e.req.command){case"type":return await oZ({...e,captureSnapshotForSession:oG});case"get":return await ed(e);case"is":return await e_(e);default:return null}}async function oZ(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(!e3("type",i.device))return eH("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===i.device.platform&&i.recording&&"failed"===await oq({session:i}))return eH("COMMAND_FAILED","Android system dialog blocked the recording session");let n=(t.positionals??[]).join(" "),o=oR(e),s=Date.now();try{let e=await o.interactions.typeText(n,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),l=Date.now(),u={...e.backendResult??{},text:e.text,delayMs:e.delayMs,...D(e.message??`Typed ${Array.from(e.text).length} chars`)};return ok({session:i,sessionStore:a,command:t.command,positionals:t.positionals??[],flags:t.flags,result:u,responseData:u,actionStartedAt:s,actionFinishedAt:l})}catch(e){return{ok:!1,error:F(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 oY(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 oQ(e,t){if(!t)return[];let r=[],a=e.device,i=e5(t.platform);if(i&&!e2(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=em(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function o0(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 o1=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"];async function o2(e){let{session:t,sessionName:r,outPath:a,outputPlacement:i,dispatchContext:s}=e,l=ey({backend:function(e){let{session:t,outputPlacement:r,dispatchContext:a}=e;return{platform:t.device.platform,captureScreenshot:async(e,i,n)=>{let o={...a,screenshotFullscreen:n?.fullscreen,overlayRefs:n?.overlayRefs,surface:n?.surface};return"out"===r?o3(await W(t.device,"screenshot",[],i,o)):o3(await W(t.device,"screenshot",[i],void 0,o))}}}({session:t,outputPlacement:i,dispatchContext:s}),artifacts:{resolveInput:async()=>{throw new U("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(o.join(c.tmpdir(),"agent-device-screenshot-")),r=o.join(t,"screenshot.png")),await n.mkdir(o.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(o.join(c.tmpdir(),`${e.prefix}-`));return{path:o.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:er()});return await l.capture.screenshot({session:r,requestId:s.requestId,appBundleId:t.appBundleId,fullscreen:s.screenshotFullscreen,maxSize:s.screenshotMaxSize,surface:t.surface,...a?{out:{kind:"path",path:a}}:{}})}function o3(e){if("object"==typeof e&&null!==e)return{..."string"==typeof e.path?{path:e.path}:{},...Array.isArray(e.overlayRefs)?{overlayRefs:e.overlayRefs}:{}}}let o8=[255,59,48,255],o4=[255,214,10,255],o5=[0,0,0,255],o9={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 o6(e){let t=B(await n.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)se(r)&&sn(r.rect)&&(!t||so(r.rect)>so(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&&sn(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 sn(e.rect)&&!("image"===tu((t=e).type??"")&&!st(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(sr)||sa(e.identifier);return o7(e)?t:t&&function(e){let t=tu(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(a))continue;let o=function(e,t){if(function(e){return o7(e)&&!se(e)}(t)&&sn(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(o7(t)&&!se(t)&&sn(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&sn(r.rect))return r;if(t.hittable&&sn(t.rect)&&!se(t))return t;let a=tr(e,t);return a?.rect&&sn(a.rect)&&!se(a)?a:null}(e.nodes,a);if(!o?.rect||!sn(o.rect))continue;let s=function(e,t,r){let a=si(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=si(a);if(!i)continue;let n=function(e){let t=0;return tu(e.type??"").includes("text")&&(t+=2),sr(e.label)&&(t+=2),sr(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(si(t)??ts(t,r))}(a,o,e.nodes),l=function(e,t,r){let a=0;return e.ref===t.ref&&(a+=4),t.hittable&&(a+=3),o7(t)&&(a+=3),o7(e)&&(a+=2),r&&(a+=2),sa(t.identifier)&&(a+=1),st(t.value)&&(a+=1),a}(a,o,s),u=function(e,t,r,a){if(!e)return su({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 su({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,o.rect,t,r);if(!sn(u))continue;let d=n.get(o.ref);(!d||l>d.score)&&n.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:u,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>so(e.overlayRect)-so(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(ss(e.overlayRect,r.overlayRect)||ss(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}so(r.overlayRect)<so(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:sl(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:sl(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:tf(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)sc(e,t.x,t.x+t.width-1,t.y+a,r),sc(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),sf(e,t.x+a,t.y,t.y+t.height-1,r),sf(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,o8),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=sd(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:sd(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 o=0;o<a;o+=1)sp(e,t+o,r+n,i)})(e,i,o,a,o4),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=o9[t];if(a)for(let t=0;t<a.length;t+=1)for(let o=0;o<a[t].length;o+=1)"1"===a[t][o]&&sp(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,o5)}(a,i.overlayRect,i.ref)}return await n.writeFile(e.screenshotPath,m.sync.write(t)),r}function o7(e){let t=[e.type,e.role,e.subrole].map(e=>tu(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 se(e){let t=[e.type,e.role,e.subrole].map(e=>tu(e??"")).join(" ");return t.includes("application")||t.includes("window")}function st(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function sr(e){var t;let r;return!!st(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function sa(e){var t;return"string"==typeof e&&!!sr(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function si(e){let t=[e.label,e.value].find(sr);return t?t.trim():sa(e.identifier)?e.identifier.trim():void 0}function sn(e){return!!(e&&e.width>0&&e.height>0)}function so(e){return e.width*e.height}function ss(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 sl(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function su(e,t,r){let a=sd(e.x,0,Math.max(0,t-1)),i=sd(e.y,0,Math.max(0,r-1)),n=Math.max(1,t-a),o=Math.max(1,r-i);return{x:a,y:i,width:sd(e.width,1,n),height:sd(e.height,1,o)}}function sd(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function sc(e,t,r,a,i){for(let n=t;n<=r;n+=1)sp(e,n,a,i)}function sf(e,t,r,a,i){for(let n=r;n<=a;n+=1)sp(e,t,n,i)}function sp(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 sm=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),sh=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),sg=new Set(sh),sw=new Map;function sy(e,t,r,a){let i=k().requestId;return{...eM(e,t,r,a,i),requestId:i}}async function sv(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||r6(e.flags))try{let t=await eu(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function sI(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await oY({req:t,leaseRegistry:n});if(l)return l;let u=await nN({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(u)return u;let d=await Q({req:t,sessionName:r,logPath:a,sessionStore:i});if(d)return d;let c=await od({req:t,sessionName:r,sessionStore:i,logPath:a});if(c)return c;let f=await nk({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await oJ({req:t,sessionName:r,logPath:a,sessionStore:i,contextFromFlags:s});return p||null}async function sS(e){var t,r;let a,i,n,o,s,l,u,{req:d,session:c,logPath:f,sessionStore:p}=e,m=d.command;if(!e3(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 oq({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=d).command,i=t.positionals??[],n=t.flags?.out,o="screenshot"===a&&i[0]?[t$.expandHome(i[0],t.meta?.cwd),...i.slice(1)]:i,s="screenshot"===a&&n?t$.expandHome(n,t.meta?.cwd):n,l="screenshot"===a?o:i,u="screenshot"===a&&s?{...t.flags??{},out:s}:t.flags??{},{resolvedPositionals:o,resolvedOut:s,recordedPositionals:l,recordedFlags:u}),v=Date.now(),I={...sy(f,d.flags,c.appBundleId,c.trace?.outPath),surface:c.surface},S="screenshot"===m?await o2({session:c,sessionName:e.sessionName,outPath:h[0]??g,outputPlacement:"screenshot"!==(r=d).command?"default":(r.positionals??[])[0]?"positional":r.flags?.out?"out":"default",dispatchContext:I}):await W(c.device,m,h,g,{...I});return"screenshot"===m&&d.flags?.overlayRefs&&"string"==typeof S?.path&&await sA(c,S,f),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:i,recordedPositionals:n,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:u,flags:d}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let i=op(e.snapshot),n={...a??{}},o=ov(n.direction)??ov(r[0]);if(!o)return a;let s=oI(n.amount)??oI(r[1]),l=oI(n.pixels),u=ob(n,[]),d=oI(n.referenceWidth),c=oI(n.referenceHeight),f=void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:i??oh;if(u&&(u.x1!==u.x2||u.y1!==u.y2))return{...n,x1:u.x1,y1:u.y1,x2:u.x2,y2:u.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250};let p=e7({direction:o,amount:s,pixels:l,referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight});return{...n,x1:p.x1,y1:p.y1,x2:p.x2,y2:p.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==p.pixels?{pixels:p.pixels}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250}}(t,a,i,s);og(t,a,i,c,d,l,u),r.recordAction(t,{command:a,positionals:n,flags:o,result:s??{}})}({session:c,sessionStore:p,command:m,resolvedPositionals:h,recordedPositionals:w,recordedFlags:y,data:S,actionStartedAt:v,actionFinishedAt:Date.now(),flags:d.flags??{}}),ei(m)&&te(c,m),{ok:!0,data:S??{}}}async function sA(e,t,r){let a=ex(await eP({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=a;let i=await o6({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}function sb(e){i.existsSync(e)&&i.unlinkSync(e)}function s_(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 sN(e){let t=s_(e);if(!t||t.pid===process.pid)try{i.existsSync(e)&&i.unlinkSync(e)}catch{}}function sk(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:sx,infoPath:sD,lockPath:sM,logPath:sP,sessionsDir:sR}=_(process.env.AGENT_DEVICE_STATE_DIR),sL=x(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sO=sR;if(i.existsSync(sO))for(let e of i.readdirSync(sO,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=o.join(sO,e.name,tF);if(i.existsSync(t))try{let e=tU(i.readFileSync(t,"utf8"));if(e&&function(e){let t,r=C(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=L(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{tV(t)}}let sE=new t$(sR),sC=new rW({maxActiveSimulatorLeases:sk(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sk(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sk(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sk(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),s$=y(),sT=a.randomBytes(24).toString("hex"),sF=C(process.pid)??void 0,sU=v(),sG=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:n}=e;async function s(e){let l=!!(e.meta?.debug||e.flags?.verbose);return await b({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:l,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:F(new U("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=A(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=I(r);if(r&&!a)throw new U("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new U("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);P({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let l=r.command,u=oX(r);sh.has(l)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:u.tenantId,runId:u.runId,leaseId:u.leaseId,backend:u.leaseBackend});let d=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,a),c=sg.has(l)?null:await sv(r,d,a),f=async()=>{let e=a.get(d);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=e$(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),a.set(d,e));let u=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?oQ(t,a):function(e,t,r){var a,i;let n=[],o=e5(t);if(void 0!==e.platform&&o&&(a=e5(e.platform),i=o,a&&i&&a!==i&&("apple"===a?!e4(i):"apple"!==i||!e4(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of o1){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 o1)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new U("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(o0).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),c=e=>(function(e,t,r){let a=k();if(!t.ok){P({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=N({force:!0})??void 0;return{ok:!1,error:F(new U($(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 P({level:"info",phase:"request_success"}),N(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let s=(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:o.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===s.length?t:{...t,artifacts:s.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"!==l&&"close"!==l)return c({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||u.meta?.lockPolicy||sm.has(l)||function(e,t){let r=oQ(e,t);if(0!==r.length){var a;let t,i,n;throw new U("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(o0).join(", ")}. Use a different --session name or close this session first.`)}}(e,u.flags);let f=await sI({req:u,sessionName:d,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...sy(t,e,r,i),surface:a.get(d)?.surface})});if(f)return c(f);let p=a.get(d);if(!p)return c({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await sS({req:u,session:p,sessionName:d,logPath:t,sessionStore:a});return c(m)};if(!c)return await f();return await ec(sw,c,f)}catch(r){P({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=k(),t=N({force:!0})??void 0;return{ok:!1,error:F(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return s}({logPath:sP,token:sT,sessionStore:sE,leaseRegistry:sC,trackDownloadableArtifact:function(e){let t=a.randomUUID(),r=setTimeout(()=>{rg(t)},9e5);return r.unref(),rh.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;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 o=s_(t);if(o?.pid&&o.pid!==process.pid&&E(o.pid,o.processStartTime))return!1;try{i.unlinkSync(t)}catch{}return n()}(sx,sM,{pid:process.pid,version:s$,startedAt:Date.now(),processStartTime:sF})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let n;if("socket"===sL||"dual"===sL){let t=h.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))eV(e);P({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await eC(),!(r<=0));)await j(200)}catch(e){P({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async i=>{let n=(t+=i).indexOf("\n");for(;-1!==n;){let i,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=eR(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),en(o),eL(o))throw ea();i=await sG(e)}catch(e){i={ok:!1,error:F(e)}}finally{r-=1,o&&(a.delete(o),eJ(o))}e.destroyed||e.write(`${JSON.stringify(i)}
|
|
38
|
-
`)
|
|
39
|
-
`),t&&
|
|
40
|
-
`)}
|
|
41
|
-
`),r
|
|
42
|
-
`)
|
|
43
|
-
`),
|
|
36
|
+
`.trim();async function nj(e,t={}){let r,a=t.pollMs??150,n=t.attempts??12,o=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((o+=1)>=2)return}else o=0;r=t,await B(a)}}async function nq(e){try{var t,r;let a,i=await H("swift",["-",e],{stdin:nV,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
|
|
37
|
+
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return nB(e);return!1}catch(t){if(t instanceof j&&"TOOL_MISSING"===t.code)return nB(e);throw t}}async function nH(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nq(e))return;await B(r)}}function nB(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),o=e.toString("latin1",4,8);if(a.push(o),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 nz(e){let t=o.parse(e);return o.join(t.dir,`${t.name}.gesture-telemetry.json`)}function nK(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nW(e){let t=o.dirname(u(import.meta.url)),r=[u(new URL(`./${e}`,import.meta.url)),o.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.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 nJ(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await nj(t),await nH(t);let s=i.mkdtempSync(o.join(c.tmpdir(),"agent-device-record-overlay-")),l=o.join(s,`input${o.extname(t)||".mp4"}`),u=o.join(s,o.basename(t)),d=o.join(s,"home"),f=o.join(s,"module-cache");i.copyFileSync(t,l),i.mkdirSync(d,{recursive:!0}),i.mkdirSync(f,{recursive:!0});try{await H("xcrun",["swift",r,"--input",l,"--output",u,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:f}}),await nH(u),i.copyFileSync(u,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(s,{recursive:!0,force:!0})}}async function nZ(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nJ({videoPath:r,scriptPath:t??=nW("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nX(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nJ({videoPath:r,scriptPath:e??=nW("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function nY(e){let{videoPath:t,quality:a,targetLabel:i="recording"}=e;await nJ({videoPath:t,scriptPath:r??=nW("recording-resize.swift"),scriptArgs:["--quality",String(a)],commandDescription:`Failed to resize the ${i}`})}function nQ(e){return e instanceof Error?e.message:String(e)}function n0(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function n1(e){let{recording:t,deps:r,trimStartMs:a,targetLabel:n}=e,o=function(e){var t,r,a;let n,o,{recording:s,trimStartMs:l}=e,u=(n=nz((t={videoPath:s.outPath,events:s.gestureEvents,trimStartMs:l}).videoPath),o={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?nK(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)}]})):nK(r))},i.writeFileSync(n,JSON.stringify(o,null,2)),n);return s.telemetryPath=u,u}({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:o,targetLabel:n})}catch(e){t.overlayWarning??=`failed to overlay recording touches: ${nQ(e)}`}}}async function n2(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===a.exitCode&&a.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function n3(e,t,r){for(let a=0;a<40;a+=1){if(!await n2(e,t,r))return!0;await B(250)}return!await n2(e,t,r)}async function n8(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await B(250)}}async function n5(e,t,r,a){for(let i=0;i<8;i+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?Number(n.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await n2(e,t,a))break;if(i+1>=2)return!0;await B(250)}return!1}async function n4(e){let t,{deps:r,deviceId:a,remotePath:n,outPath:o}=e;for(let e=0;e<2;e+=1){try{i.rmSync(o,{force:!0})}catch{}let s=await r.runCmd("adb",["-s",a,"pull",n,o],{allowFailure:!0});if(0!==s.exitCode)t=n0(s,"adb pull");else{await r.waitForStableFile(o,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(o);if(O({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:n,outPath:o,attempt:e+1,fileSize:(()=>{try{return i.statSync(o).size}catch{return 0}})(),playable:t}}),t)return;O({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:n,outPath:o,attempt:e+1}})}e<1&&await B(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 n9(e){let{deps:t,deviceId:r,quality:a}=e;if(void 0===a||a>=10)return;let i=await t.runCmd("adb",["-s",r,"shell","wm","size"],{allowFailure:!0}),n=i.stdout.match(/Override size:\s*(\d+)x(\d+)/)??i.stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(0!==i.exitCode||!n)throw Error(`failed to resolve Android screen size for recording quality: ${n0(i,"adb shell wm size")}`);return{width:n6(Number(n[1]),a),height:n6(Number(n[2]),a)}}function n6(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function n7(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function oe(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return O({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await n2(e,t,r))&&await n3(e,t,r)}async function ot(e){var t;let r,a,{deps:i,device:n,recordingBase:o}=e,s="failed to start recording: Android screenrecord did not begin producing frames";try{r=await n9({deps:i,deviceId:n.id,quality:o.quality})}catch(e){return eu("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 i.runCmd("adb",["-s",n.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: ${n0(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 n7(i,n.id,e);continue}if(O({level:"debug",phase:"record_start_android_started",data:{deviceId:n.id,remotePath:e,remotePid:a}}),await n5(i,n.id,e,a))return{platform:"android",remotePath:e,remotePid:a,...o,startedAt:Date.now()};s="failed to start recording: Android screenrecord did not begin producing frames",await oe(i,n.id,a),await n7(i,n.id,e)}return eu("COMMAND_FAILED",s)}async function or(e){let t,r,{deps:a,device:i,recording:n}=e;O({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(O({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await n2(a,i.id,n.remotePid)&&!await oe(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${n0(o,"adb shell kill")}`):await n3(a,i.id,n.remotePid)||await oe(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await n8(a,i.id,n.remotePath);let e=await n4({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),eu("COMMAND_FAILED",e);await n1({recording:n,deps:a,targetLabel:"Android recording"})}if(await s(),t)return eu("COMMAND_FAILED",t);if(r)return eu("COMMAND_FAILED",r);return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});O({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: ${n0(e,"adb shell rm")}`)}}function oa(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function oi(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function on(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=oa(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},oi(t,i,r))}catch(e){O({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:nQ(e)}})}}async function oo(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:u,recordingBase:d,appBundleId:c}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=oi(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:f,fps:u,quality:d.quality,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var g,w;if(!nQ(a).toLowerCase().includes("recording already in progress"))return eu("COMMAND_FAILED",`failed to start recording: ${nQ(a)}`);O({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:nQ(a)}});let e=(g=o.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 eu("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return eu("COMMAND_FAILED",`failed to start recording: ${nQ(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...d}}async function os(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,quality:s.quality,appBundleId:l},oi(t,i,r))}catch(e){return eu("COMMAND_FAILED",`failed to start recording: ${nQ(e)}`)}return{platform:"macos-runner",...s}}async function ol(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=oa(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},oi(t,i,r))}catch(e){O({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nQ(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",o.remotePath,"--destination",o.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 eu("COMMAND_FAILED",`failed to copy recording from device: ${e}`)}let u="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);return u>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:u}),await n1({recording:o,deps:n,trimStartMs:u,targetLabel:"iOS recording"}),null}async function ou(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=oa(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},oi(t,i,r))}catch(e){O({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nQ(e)}})}return await n1({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function od(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 B(250)}return Date.now()}async function oc(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:u}=e;await on({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:d,wait:c}=s.runCmdBackground("xcrun",e0(n,["io",n.id,"recordVideo",u]),{allowFailure:!0}),f=await od(u);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:oa(i)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:i.trace?.outPath}),u=Date.now();t=Math.round((e+u)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:d,wait:c,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function of(e){let t,{req:r,sessionName:a,sessionStore:n,activeSession:s,device:l,logPath:u,deps:d}=e;if(s.recording)return eu("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 eu("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==f&&(!Number.isInteger(f)||f<5||f>10))return eu("INVALID_ARGS","quality must be an integer between 5 and 10");if(!e9("record",l))return eu("UNSUPPORTED_OPERATION","record is not supported on this device");let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,m=tG.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(o.dirname(m),{recursive:!0}),i.rmSync(m,{force:!0}),"ios"===l.platform&&"device"===l.kind){let e=oa(s);if(!e)return eu("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await oo({req:r,activeSession:s,sessionStore:n,device:l,logPath:u,deps:d,fpsFlag:c,recordingBase:h,appBundleId:e})}else if("macos"===l.platform){let e=oa(s);if(!e)return eu("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await os({req:r,activeSession:s,device:l,logPath:u,deps:d,fpsFlag:c,recordingBase:h,appBundleId:e})}else t="ios"===l.platform?await oc({req:r,activeSession:s,device:l,logPath:u,deps:d,recordingBase:h,resolvedOut:m}):await ot({deps:d,device:l,recordingBase:h});return"ok"in t?t:(s.recording=t,n.set(a,s),n.recordAction(s,{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 op(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await or({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return eu("COMMAND_FAILED",`failed to stop recording: ${n0(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: ${nQ(e)}`}return await n1({recording:a,deps:t,targetLabel:"iOS recording"}),null}async function om(e){var t;let r,{req:a,activeSession:i,device:n,logPath:s,deps:l}=e;if(!i.recording)return eu("INVALID_ARGS","no active recording");let u=i.recording,d=u.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===u.platform?await ol({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):"macos-runner"===u.platform?await ou({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):await op({deps:l,device:n,recording:u});return c||(d?eu("COMMAND_FAILED",d):(r=[{field:"outPath",path:(t=u).outPath,localPath:t.clientOutPath,fileName:o.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return nz(e.clientOutPath)}(t),fileName:o.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function oh(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:H,runCmdBackground:q,runIosRunnerCommand:eZ,waitForStableFile:nj,isPlayableVideo:nq,trimRecordingStart:nZ,resizeRecording:nY,overlayRecordingTouches:nX},o=a.get(r),s=o?.device??await ep(t.flags??{});o||await eX(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},u=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(u))return eu("INVALID_ARGS","record requires start|stop");if("start"===u)return of({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let d=await om({req:t,activeSession:l,device:s,logPath:i,deps:n});return d.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:d.data?.outPath,showTouches:d.data?.showTouches}}),d}async function og(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,s=t.command;if("record"===s)return oh({req:t,sessionName:r,sessionStore:a,logPath:n});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return eu("INVALID_ARGS","trace requires start|stop");let n=a.get(r);if(!n)return eu("SESSION_NOT_FOUND","No active session");if("start"===e){if(n.trace)return eu("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(n),r=tG.expandHome(e);return i.mkdirSync(o.dirname(r),{recursive:!0}),i.appendFileSync(r,""),n.trace={outPath:r,startedAt:Date.now()},a.recordAction(n,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!n.trace)return eu("INVALID_ARGS","no active trace");let l=n.trace.outPath;if(t.positionals?.[1]){let e=tG.expandHome(t.positionals[1]);i.mkdirSync(o.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:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l}}),{ok:!0,data:{trace:"stopped",outPath:l}}}return null}function ow(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 oy=new WeakMap;function ov(e){if(!e)return;let t=oy.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)&&oI(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(oI);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 oy.set(e,r),r}function oI(e){return!!e&&e.width>0&&e.height>0}let oS={referenceWidth:1e3,referenceHeight:1e3};function oA(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,u;let d,c,f=e.recording;if(!f)return;let p={...i,...a??{}},m=ok(p.effectiveDurationMs)??ok(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:ok(p.gestureStartUptimeMs),gestureEndUptimeMs:ok(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:ok(p.gestureStartUptimeMs),gestureEndUptimeMs:ok(p.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),w="ios"===e.device.platform&&void 0===ok(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=ox(ok(t.count),1)??1,r=!0===t.doubleTap,a=ox(ok(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 ow(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):ow(h),y=(l=e.snapshot,d=ok((u=p).referenceWidth),c=ok(u.referenceHeight),void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:ov(l)),v=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=oD(t,e);if(!i)return[];let{x:n,y:o}=i,s=ox(ok(t.count),1)??1,l=ox(ok(t.intervalMs),0)??0,u=!0===t.doubleTap,d=ox(ok(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==d&&d>0){c.push(o_(t,n,o,d,a));continue}c.push(ob(t,n,o,a)),u&&c.push(ob(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=oD(t,e);if(!i)return[];let{x:n,y:o}=i;return[ob(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=oD(t,e);if(!n)return[];let{x:o,y:s}=n;return[o_(r,o,s,oP(a,[ok(t.durationMs),ok(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=oM(t,e),o=oN(t.contentDirection)??oN(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:u,y2:d}=n,c=oP(a,[],250),f=ok(t.amount)??ok(e[1]),p=ok(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:u,y2:d,...i,durationMs:c,contentDirection:o,...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=oM(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:u}=n,d=oP(a,[ok(t.effectiveDurationMs),ok(t.durationMs),ok(e[4])],250),c=ox(ok(t.count),1)??1,f=ox(ok(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:o,n=t?u:s,c=t?o:l,h=t?s:u,g=r+e*(d+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:d,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:d})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=oD(t,e,1),o=ok(t.scale)??ok(e[0]);if(!n||void 0===o||o<=0)return[];let{x:s,y:l}=n;return[{kind:"pinch",tMs:r,x:s,y:l,...i,scale:o,durationMs:oP(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,w,g,y);0!==v.length&&(f.gestureEvents.push(...v),O({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 ob(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function o_(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function oN(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 ok(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 ox(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function oD(e,t,r=0){let a=ok(e.x)??ok(t[r]),i=ok(e.y)??ok(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function oM(e,t){let r=ok(e.x1)??ok(t[0]),a=ok(e.y1)??ok(t[1]),i=ok(e.x2)??ok(t[2]),n=ok(e.y2)??ok(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 oP(e,t,r){return ox(e,1)??t.map(e=>ox(e,1)).find(e=>void 0!==e)??r}function oL(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:u,extra:d}=e,c=(t=d,r=s,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 o?.message?o.message:void 0));return{x:s,y:l,...u??{},...d??{},...o??{},...L(c)}}function oR(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:u,androidFreshnessBaseline:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),es(a)&&ti(t,a,d??t.snapshot),oA(t,a,i,o,n??{},l,u),{ok:!0,data:s}}async function oO(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 e_(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=ov(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=ov(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oE(e){try{return await oO(e)}catch(t){O({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function oC(e){return ov({nodes:e,createdAt:0})}function o$(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:eu("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 oT(e){let t=e.sessionStore.get(e.sessionName);if(!t)throw new j("SESSION_NOT_FOUND","No active session. Run open first.");return eA({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)=>oF(await X(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)=>oF(await X(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)=>oF(await X(r.device,"type",[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),artifacts:eH("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&&(eh(t,r.snapshot),e.sessionStore.set(e.sessionName,t))}},policy:en()})}function oF(e){return e&&"object"==typeof e?e:void 0}function oU(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 oG(e){return"ref"===e.kind?{ref:oV(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 oV(e){return e?.startsWith("@")?e.slice(1):e}async function oj(e){switch(e.req.command){case"press":case"click":return await oq(e);case"fill":return await oH(e);default:return null}}async function oq(e){let t,{req:r,sessionName:a,sessionStore:i}=e,n=i.get(a),o="click"===r.command?"click":"press";if(!n)return eu("SESSION_NOT_FOUND","No active session. Run open first.");let s=o$(n,o);if(s)return s;if(!e9("press",n.device))return eu("UNSUPPORTED_OPERATION","press is not supported on this device");let l=eL(r.flags),u=et(l);if("primary"!==l){let e=ec({commandLabel:o,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 eu(e.code,e.message,e.details)}let d=function(e,t){let r=oU(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:eu("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}(r.positionals??[],o);if(!d.ok)return d.response;if("ref"===d.target.kind){let a=e.refSnapshotFlagGuardResponse("press",r.flags);if(a)return a;t=await oz(e,n)}return await oB(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"===o?await e.interactions.click(d.target,t):await e.interactions.press(d.target,t)},afterRun:async e=>{var t;await ew(n,(t=d.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 oE({session:n,flags:r.flags,sessionStore:i,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:e.captureSnapshotForSession}):oC(n.snapshot?.nodes??[]),o=oL({data:t.backendResult,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:a,extra:{...oG(t),...u}});return{result:o,responseData:o}}})}async function oH(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(i){let e=o$(i,"fill");if(e)return e}if(i&&!e9("fill",i.device))return eu("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!i)return eu("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:eu("INVALID_ARGS","fill requires text after ref")}}let r=oU(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:eu("INVALID_ARGS","fill requires text after coordinates")}}let a=tn(e,{preferTrailingValue:!0});if(!a)return{ok:!1,response:eu("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:eu("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 oz(e,i)}return await oB(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:oC(i.snapshot?.nodes??[]),r=oL({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...oG(e),text:n.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:oV(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 oB(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return eu("SESSION_NOT_FOUND","No active session. Run open first.");let a=oT(e),i=Date.now();try{let n=await t.run(a);await t.afterRun?.(n);let o=Date.now(),{result:s,responseData:l}=await t.buildPayloads(n);return oR({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags,result:s,responseData:l,actionStartedAt:i,actionFinishedAt:o,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=G(t);if(eB(e))throw e;return{ok:!1,error:V(t)}}}async function oz(e,t){if(!e1(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){O({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 oK(e,t,r,a,i){let n={...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},o=a(n,e.appBundleId,e.trace?.outPath),{snapshot:s}=await eM({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??"",androidFreshnessMode:i.androidFreshnessMode});return eh(e,s),r.set(e.name,e),s}let oW=/\bis(?:n't| not)\s+responding\b/i,oJ=/^close app$/i;async function oZ(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oX(t),r=function(e){if(o1(e))return e.find(e=>{let t=o0(e);return t.length>0&&oJ.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=tg(r.rect),n=await H("adb",eU(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return O({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 oY(t))return O({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eE(t.device,t.appBundleId),!await oQ(t,t.appBundleId)))return O({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return O({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 O({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 oX(e){return th(tm((await ef(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function oY(e){for(let t=0;t<12;t+=1){if(!o1(await oX(e)))return!0;await B(500)}return!o1(await oX(e))}async function oQ(e,t){for(let r=0;r<12;r+=1){if((await ek(e.device)).package===t)return!0;await B(500)}return(await ek(e.device)).package===t}function o0(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 o1(e){return e.some(e=>{let t=o0(e);return t.length>0&&oW.test(t)})}async function o2(e){let t=await oj({...e,captureSnapshotForSession:oK,refSnapshotFlagGuardResponse:Q});if(t)return t;switch(e.req.command){case"type":return await o3({...e,captureSnapshotForSession:oK});case"get":return await em(e);case"is":return await eP(e);default:return null}}async function o3(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return eu("SESSION_NOT_FOUND","No active session. Run open first.");if(!e9("type",i.device))return eu("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===i.device.platform&&i.recording&&"failed"===await oZ({session:i}))return eu("COMMAND_FAILED","Android system dialog blocked the recording session");let n=(t.positionals??[]).join(" "),o=oT(e),s=Date.now();try{let e=await o.interactions.typeText(n,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),l=Date.now(),u={...e.backendResult??{},text:e.text,delayMs:e.delayMs,...L(e.message??`Typed ${Array.from(e.text).length} chars`)};return oR({session:i,sessionStore:a,command:t.command,positionals:t.positionals??[],flags:t.flags,result:u,responseData:u,actionStartedAt:s,actionFinishedAt:l})}catch(e){return{ok:!1,error:V(e)}}}function o8(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 o5(e){let{req:t,leaseRegistry:r}=e,a=o8(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 o4(e,t){if(!t)return[];let r=[],a=e.device,i=te(t.platform);if(i&&!e4(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=ey(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function o9(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 o6=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"];async function o7(e){let{session:t,sessionName:r,outPath:a,outputPlacement:i,dispatchContext:s}=e,l=eA({backend:function(e){let{session:t,outputPlacement:r,dispatchContext:a}=e;return{platform:t.device.platform,captureScreenshot:async(e,i,n)=>{let o={...a,screenshotFullscreen:n?.fullscreen,overlayRefs:n?.overlayRefs,surface:n?.surface};return"out"===r?se(await X(t.device,"screenshot",[],i,o)):se(await X(t.device,"screenshot",[i],void 0,o))}}}({session:t,outputPlacement:i,dispatchContext:s}),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(o.join(c.tmpdir(),"agent-device-screenshot-")),r=o.join(t,"screenshot.png")),await n.mkdir(o.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(o.join(c.tmpdir(),`${e.prefix}-`));return{path:o.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:en()});return await l.capture.screenshot({session:r,requestId:s.requestId,appBundleId:t.appBundleId,fullscreen:s.screenshotFullscreen,maxSize:s.screenshotMaxSize,surface:t.surface,...a?{out:{kind:"path",path:a}}:{}})}function se(e){if("object"==typeof e&&null!==e)return{..."string"==typeof e.path?{path:e.path}:{},...Array.isArray(e.overlayRefs)?{overlayRefs:e.overlayRefs}:{}}}let st=[255,59,48,255],sr=[255,214,10,255],sa=[0,0,0,255],si={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 sn(e){let t=W(await n.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)ss(r)&&sf(r.rect)&&(!t||sp(r.rect)>sp(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&&sf(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 sf(e.rect)&&!("image"===tp((t=e).type??"")&&!sl(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(su)||sd(e.identifier);return so(e)?t:t&&function(e){let t=tp(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(a))continue;let o=function(e,t){if(function(e){return so(e)&&!ss(e)}(t)&&sf(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(so(t)&&!ss(t)&&sf(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&sf(r.rect))return r;if(t.hittable&&sf(t.rect)&&!ss(t))return t;let a=to(e,t);return a?.rect&&sf(a.rect)&&!ss(a)?a:null}(e.nodes,a);if(!o?.rect||!sf(o.rect))continue;let s=function(e,t,r){let a=sc(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=sc(a);if(!i)continue;let n=function(e){let t=0;return tp(e.type??"").includes("text")&&(t+=2),su(e.label)&&(t+=2),su(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(sc(t)??tc(t,r))}(a,o,e.nodes),l=function(e,t,r){let a=0;return e.ref===t.ref&&(a+=4),t.hittable&&(a+=3),so(t)&&(a+=3),so(e)&&(a+=2),r&&(a+=2),sd(t.identifier)&&(a+=1),sl(t.value)&&(a+=1),a}(a,o,s),u=function(e,t,r,a){if(!e)return sg({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 sg({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,o.rect,t,r);if(!sf(u))continue;let d=n.get(o.ref);(!d||l>d.score)&&n.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:u,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>sp(e.overlayRect)-sp(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(sm(e.overlayRect,r.overlayRect)||sm(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}sp(r.overlayRect)<sp(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:sh(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:sh(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:tg(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)sy(e,t.x,t.x+t.width-1,t.y+a,r),sy(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),sv(e,t.x+a,t.y,t.y+t.height-1,r),sv(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,st),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=sw(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:sw(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 o=0;o<a;o+=1)sI(e,t+o,r+n,i)})(e,i,o,a,sr),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=si[t];if(a)for(let t=0;t<a.length;t+=1)for(let o=0;o<a[t].length;o+=1)"1"===a[t][o]&&sI(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,sa)}(a,i.overlayRect,i.ref)}return await n.writeFile(e.screenshotPath,w.sync.write(t)),r}function so(e){let t=[e.type,e.role,e.subrole].map(e=>tp(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 ss(e){let t=[e.type,e.role,e.subrole].map(e=>tp(e??"")).join(" ");return t.includes("application")||t.includes("window")}function sl(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function su(e){var t;let r;return!!sl(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function sd(e){var t;return"string"==typeof e&&!!su(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function sc(e){let t=[e.label,e.value].find(su);return t?t.trim():sd(e.identifier)?e.identifier.trim():void 0}function sf(e){return!!(e&&e.width>0&&e.height>0)}function sp(e){return e.width*e.height}function sm(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 sh(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function sg(e,t,r){let a=sw(e.x,0,Math.max(0,t-1)),i=sw(e.y,0,Math.max(0,r-1)),n=Math.max(1,t-a),o=Math.max(1,r-i);return{x:a,y:i,width:sw(e.width,1,n),height:sw(e.height,1,o)}}function sw(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function sy(e,t,r,a,i){for(let n=t;n<=r;n+=1)sI(e,n,a,i)}function sv(e,t,r,a,i){for(let n=r;n<=a;n+=1)sI(e,t,n,i)}function sI(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 sS=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),sA=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),sb=new Set(sA),s_=new Map;function sN(e){if(eF(e.meta?.requestId))throw eo()}function sk(e,t,r,a){let i=M().requestId;return{...eC(e,t,r,a,i),requestId:i}}async function sx(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||aa(e.flags))try{let t=await ep(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function sD(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await o5({req:t,leaseRegistry:n});if(l)return l;let u=await nL({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(u)return u;let d=await er({req:t,sessionName:r,logPath:a,sessionStore:i});if(d)return d;let c=await og({req:t,sessionName:r,sessionStore:i,logPath:a});if(c)return c;let f=await nR({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await o2({req:t,sessionName:r,logPath:a,sessionStore:i,contextFromFlags:s});return p||null}async function sM(e){var t,r;let a,i,n,o,s,l,u,{req:d,session:c,logPath:f,sessionStore:p}=e,m=d.command;if(!e9(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 oZ({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=d).command,i=t.positionals??[],n=t.flags?.out,o="screenshot"===a&&i[0]?[tG.expandHome(i[0],t.meta?.cwd),...i.slice(1)]:i,s="screenshot"===a&&n?tG.expandHome(n,t.meta?.cwd):n,l="screenshot"===a?o:i,u="screenshot"===a&&s?{...t.flags??{},out:s}:t.flags??{},{resolvedPositionals:o,resolvedOut:s,recordedPositionals:l,recordedFlags:u}),v=Date.now(),I={...sk(f,d.flags,c.appBundleId,c.trace?.outPath),surface:c.surface},S="screenshot"===m?await o7({session:c,sessionName:e.sessionName,outPath:h[0]??g,outputPlacement:"screenshot"!==(r=d).command?"default":(r.positionals??[])[0]?"positional":r.flags?.out?"out":"default",dispatchContext:I}):await X(c.device,m,h,g,{...I});return"screenshot"===m&&d.flags?.overlayRefs&&"string"==typeof S?.path&&await sP(c,S,f),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:i,recordedPositionals:n,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:u,flags:d}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let i=ov(e.snapshot),n={...a??{}},o=oN(n.direction)??oN(r[0]);if(!o)return a;let s=ok(n.amount)??ok(r[1]),l=ok(n.pixels),u=oM(n,[]),d=ok(n.referenceWidth),c=ok(n.referenceHeight),f=void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:i??oS;if(u&&(u.x1!==u.x2||u.y1!==u.y2))return{...n,x1:u.x1,y1:u.y1,x2:u.x2,y2:u.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250};let p=ta({direction:o,amount:s,pixels:l,referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight});return{...n,x1:p.x1,y1:p.y1,x2:p.x2,y2:p.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==p.pixels?{pixels:p.pixels}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250}}(t,a,i,s);oA(t,a,i,c,d,l,u),r.recordAction(t,{command:a,positionals:n,flags:o,result:s??{}})}({session:c,sessionStore:p,command:m,resolvedPositionals:h,recordedPositionals:w,recordedFlags:y,data:S,actionStartedAt:v,actionFinishedAt:Date.now(),flags:d.flags??{}}),es(m)&&ti(c,m),{ok:!0,data:S??{}}}async function sP(e,t,r){let a=eO(await e$({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);eh(e,a);let i=await sn({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}async function sL(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 sR(e){i.existsSync(e)&&i.unlinkSync(e)}function sO(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 sE(e){let t=sO(e);if(!t||t.pid===process.pid)try{i.existsSync(e)&&i.unlinkSync(e)}catch{}}function sC(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:s$,infoPath:sT,lockPath:sF,logPath:sU,sessionsDir:sG}=x(process.env.AGENT_DEVICE_STATE_DIR),sV=P(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sj=sG;if(i.existsSync(sj))for(let e of i.readdirSync(sj,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=o.join(sj,e.name,tj);if(i.existsSync(t))try{let e=tq(i.readFileSync(t,"utf8"));if(e&&function(e){let t,r=F(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=C(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{tB(t)}}let sq=new tG(sG),sH=new rQ({maxActiveSimulatorLeases:sC(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sC(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sC(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sC(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),sB=S(),sz=a.randomBytes(24).toString("hex"),sK=F(process.pid)??void 0,sW=A(),sJ=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:n}=e;async function s(e){let l=!!(e.meta?.debug||e.flags?.verbose);return await k({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:l,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:V(new j("UNAUTHORIZED","Invalid token"))};try{return await ex(async()=>{let r=function(e){let t=N(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=b(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);O({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let l=r.command,u=o8(r);sA.has(l)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:u.tenantId,runId:u.runId,leaseId:u.leaseId,backend:u.leaseBackend});let d=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,a),c=sb.has(l)?null:await sx(r,d,a),f=async()=>{sN(r);let e=a.get(d);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=ej(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),a.set(d,e));let u=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?o4(t,a):function(e,t,r){var a,i;let n=[],o=te(t);if(void 0!==e.platform&&o&&(a=te(e.platform),i=o,a&&i&&a!==i&&("apple"===a?!e7(i):"apple"!==i||!e7(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of o6){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 o6)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(o9).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),c=e=>(function(e,t,r){let a=M();if(!t.ok){O({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=D({force:!0})??void 0;return{ok:!1,error:V(new j(U(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 O({level:"info",phase:"request_success"}),D(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let s=(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:o.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===s.length?t:{...t,artifacts:s.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"!==l&&"close"!==l)return c({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||u.meta?.lockPolicy||sS.has(l)||function(e,t){let r=o4(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(o9).join(", ")}. Use a different --session name or close this session first.`)}}(e,u.flags);let f=await sD({req:u,sessionName:d,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...sk(t,e,r,i),surface:a.get(d)?.surface})});if(f)return c(f);let p=a.get(d);if(!p)return c({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await sM({req:u,session:p,sessionName:d,logPath:t,sessionStore:a});return c(m)};return c?(sN(r),await eg(s_,c,f)):(sN(r),await f())})}catch(r){O({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=M(),t=D({force:!0})??void 0;return{ok:!1,error:V(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return s}({logPath:sU,token:sz,sessionStore:sq,leaseRegistry:sH,trackDownloadableArtifact:function(e){let t=a.randomUUID(),r=setTimeout(()=>{rI(t)},9e5);return r.unref(),rv.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});async function sZ(e){await k({command:"daemon",session:"daemon",logPath:sU,debug:!0},async()=>{O({level:"error",phase:"daemon_fatal",data:{error:e instanceof Error?e.message:String(e)}}),D({force:!0})})}async function sX(){let e=sq.toArray();await Promise.all(e.map(sY))}async function sY(e){let t=a5(e,e.name).catch(t=>{process.stderr.write(`Daemon session teardown error (${e.name}): ${t instanceof Error?t.message:String(t)}
|
|
38
|
+
`)});await Promise.race([t,B(5e3).then(()=>{process.stderr.write(`Daemon session teardown timed out (${e.name}).
|
|
39
|
+
`)})]),sq.writeSessionLog(e),sq.delete(e.name)}async function sQ(){let e,t,r=[];if("http"!==sV){let t,a,i=(t=new Set,(a=y.createServer(e=>{t.add(e),e.on("close",()=>t.delete(e));let r="",a=0,i=new Set,n=!1,o=()=>{if(!n&&0!==a){for(let e of(n=!0,i))eK(e);O({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:a}}),(async()=>{try{let e=Date.now()+15e3;for(;a>0&&Date.now()<e&&(await eV(),!(a<=0));)await B(200)}catch(e){O({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",o),e.on("error",o),e.on("data",async t=>{let n=(r+=t).indexOf("\n");for(;-1!==n;){let t,o,s=r.slice(0,n).trim();if(r=r.slice(n+1),0===s.length){n=r.indexOf("\n");continue}a+=1;try{let e=JSON.parse(s);if(o=eT(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},i.add(o),el(o),eF(o))throw eo();t=await sJ(e)}catch(e){t={ok:!1,error:V(e)}}finally{a-=1,o&&(i.delete(o),eQ(o))}e.destroyed||e.write(`${JSON.stringify(t)}
|
|
40
|
+
`),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 j("COMMAND_FAILED","Failed to bind socket server"))})})}if("socket"!==sV){let e=await rz({handleRequest:sJ,token:sz});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 j("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 o=sO(t);if(o?.pid&&o.pid!==process.pid&&T(o.pid,o.processStartTime))return!1;try{i.unlinkSync(t)}catch{}return n()}(s$,sF,{pid:process.pid,version:sB,startedAt:Date.now(),processStartTime:sK})){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,o=await sQ();e=o.servers,t=o.socketPort,r=o.httpPort,a={socketPort:t,httpPort:r,token:sz,version:sB,codeSignature:sW,processStartTime:sK},i.existsSync(s$)||i.mkdirSync(s$,{recursive:!0}),i.writeFileSync(sU,""),n=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",i.writeFileSync(sT,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:s$},null,2),{mode:384}),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${t}
|
|
41
|
+
`),r&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${r}
|
|
42
|
+
`)}catch(r){let t=G(r);for(let r of(process.stderr.write(`Daemon error: ${t.message}
|
|
43
|
+
`),e))try{r.close(()=>{})}catch{}sR(sT),sE(sF),process.exit(1);return}let n=!1,o=async(t={})=>{n||(n=!0,t.cause&&await sZ(t.cause),await sL(e),await sX(),await eb(),sR(sT),sE(sF),process.exit(t.exitCode??0))};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof j?e:G(e);process.stderr.write(`Daemon error: ${t.message}
|
|
44
|
+
`),o({exitCode:1,cause:e})}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof j?t:G(t);process.stderr.write(`Daemon error: ${r.message}
|
|
45
|
+
`),o({exitCode:1,cause:t})})}();
|