agent-device 0.14.0 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/android-snapshot-helper/README.md +1 -1
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.0.apk → agent-device-android-snapshot-helper-0.14.2.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.2.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.0.manifest.json → agent-device-android-snapshot-helper-0.14.2.manifest.json} +6 -6
- package/dist/src/1231.js +1 -0
- package/dist/src/2007.js +33 -0
- package/dist/src/221.js +4 -4
- package/dist/src/8656.js +1 -1
- package/dist/src/android-snapshot-helper.d.ts +1 -0
- package/dist/src/batch.d.ts +138 -0
- package/dist/src/batch.js +1 -0
- package/dist/src/internal/bin.js +53 -44
- package/dist/src/internal/daemon.js +17 -17
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +26 -2
- package/package.json +7 -3
- package/skills/agent-device/SKILL.md +2 -2
- package/skills/dogfood/SKILL.md +2 -2
- package/skills/react-devtools/SKILL.md +1 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.0.apk.sha256 +0 -1
- package/dist/src/3918.js +0 -33
|
@@ -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{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,readTextForNode as ex,captureSnapshot as eD,dispatchIsViaRuntime as eM,resolveClickButton as eP,IOS_DEVICECTL_DEFAULT_HINT as eL,buildSnapshotState as eR,openAndroidApp as eO,context_contextFromFlags as eE,captureSnapshotData as eC,resolveRequestTrackingId as e$,isRequestCanceled as eT,adbArgs as eF,resolvePayloadInput as eU,abortAllIosRunnerSessions as eG,getRunnerSessionSnapshot as eV,formatAndroidInstalledPackageRequiredMessage as ej,createUnsupportedArtifactAdapter as eq,isAndroidEscapeError as eH,resolveIosSimulatorDeviceSetPath as eB,markRequestCanceled as ez,dispatchFindReadOnlyViaRuntime as eK,resolveIosDeviceDeepLinkBundleId as eW,runIosRunnerCommand as eJ,ensureDeviceReady as eZ,readInfoPlistString as eX,clearRequestCanceled as eY,buildSimctlArgsForDevice as eQ,getActiveAndroidSnapshotFreshness as e0,parseXmlDocumentSync as e1,resolveFrontmostMacOsApp as e2,IOS_SIMCTL_LIST_TIMEOUT_MS as e3,listIosDeviceApps as e8,matchesPlatformSelector as e5,isCommandSupportedOnDevice as e4,listIosDeviceProcesses as e9,isApplePlatform as e6,normalizePlatformSelector as e7,getRequestSignal as te,parseSessionSurface as tt,buildScrollGesturePlan as tr,markAndroidSnapshotFreshness as ta}from"../3918.js";import{splitSelectorFromArgs as ti,findNearestHittableAncestor as tn,extractNodeText as to,splitIsSelectorArgs as ts,tryParseSelectorChain as tl,resolveSelectorChain as tu,resolveRefLabel as td,buildSelectorChainForNode as tc,normalizeType as tf,pruneGroupNodes as tp}from"../940.js";import{attachRefs as tm,centerOfRect as th}from"../4057.js";import{findBestMatchesByLocator as tg,parseFindArgs as tw}from"../7556.js";function ty(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 tv(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tI=/^-?\d+(\.\d+)?$/,tS=/^[^\s"\\]+$/,tA=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tb=new Map([["--count","count"],["--pause-ms","pauseMs"]]),t_=new Map([["--delay-ms","delayMs"]]);function tN(e){return"click"===e||"press"===e}function tk(e){return"type"===e||"fill"===e}function tx(e){return tM(e,tP)}function tD(e){return JSON.stringify(e)}function tM(e,t){return t(e)?e:tD(e)}function tP(e){return tL(e)&&e.startsWith("@")||tI.test(e)}function tL(e){return tS.test(e)}function tR(e,t){let r=t.flags??{};if(tN(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}tk(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tO(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",tM(t.metroHost,tL)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tM(t.bundleUrl,tL)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tM(t.launchUrl,tL)))}function tE(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tM(r,tL)),a))e.push(tx(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 tC(e,t){let r=[],a={},i=tN(e)?tA:"swipe"===e?tb:tk(e)?t_:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tN(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(tN(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=tT(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 t$(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=tT(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 tT(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tF(e,t){for(let r of t.positionals??[])e.push(tx(r));t.flags?.relaunch&&e.push("--relaunch"),tO(e,t.runtime)}class tU{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=tU.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 tG)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=${tD(e.device.name)}${a} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(tN(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tx(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tx(a)),tR(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tx(r)),tR(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tx(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tx(a)),e.positionals.length>1&&t.push(tx(i)),tR(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tx(r)),t.push(tx(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tx(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",tx(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tx(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 tF(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tM(r,tL)),tO(t,e.flags),t.join(" ")}if("record"===e.command)return tE(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tx(r));return tR(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 t0(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",tY(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:i}),{stdio:["ignore","pipe","pipe"]}),u=tz(r,{redactionPatterns:a});"number"==typeof l.pid&&tq(n,l.pid);let d=tK(l,r,{endStreamOnClose:!0,writer:u}).then(e=>(0!==e.exitCode&&(o="failed"),tH(n),e));return{backend:"ios-simulator",getState:()=>o,startedAt:Date.now(),wait:d,stop:async()=>{l.killed||l.kill("SIGINT"),await tB(d),l.killed||l.kill("SIGKILL"),await tB(d),tH(n)}}}async function t1(e,t,r,a){let i="active",n=s("log",["stream","--style","compact","--predicate",tY(e)],{stdio:["ignore","pipe","pipe"]}),o=tz(t,{redactionPatterns:r});"number"==typeof n.pid&&tq(a,n.pid);let l=tK(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tH(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tB(l),n.killed||n.kill("SIGKILL"),await tB(l),tH(a)}}}async function t2(e,t,r,a){let i="active",n=s("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tz(t,{redactionPatterns:r});"number"==typeof n.pid&&tq(a,n.pid);let l=tK(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tH(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tB(l),n.killed||n.kill("SIGKILL"),await tB(l),tH(a)}}}let t3=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),t8=/https?:\/\/[^\s"'<>\])]+/i,t5=[/\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 t4(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>t6(e)));for(let e of t.entries){let t=t6(e);if(!i.has(t)&&(i.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function t9(e,t){let r=rl(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=rl(t?.maxPayloadChars,2048,64,16384),o=rl(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=ri(s,["method","httpMethod"]),u=ri(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=t3.exec(o),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=t8.exec(o),h=u??m?.[0];if(!h)return null;let g=d??re(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:rt(o),packetId:rr(o)??void 0,durationMs:ra(o)??void 0,raw:rs(o,n),line:r};if("android"===a&&function(e,t,r){let a=t7(t,r,5),i=e.packetId??a.map(e=>rr(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?t7(t,r,12).filter(e=>rr(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>rt(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>re(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>ra(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 ro(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(w.headers=rs(e,n))}if("body"===i||"all"===i){let e=rn(o,s,["requestBody","body","payload","request"]),t=rn(o,s,["responseBody","response"]);e&&(w.requestBody=rs(e,n)),t&&(w.responseBody=rs(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 t6(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function t7(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 re(e){for(let t of t5){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function rt(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 rr(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function ra(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 ri(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 rn(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return ro(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 ro(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function rs(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function rl(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function ru(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 rd(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:ru("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:ru("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rc(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=rl(t?.maxEntries,25,1,200),s=t?.include??"summary",l=rl(t?.maxPayloadChars,2048,64,16384),u=rl(t?.maxScanLines,4e3,100,2e4),i.existsSync(m)?t9(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 rf({device:d,appBundleId:c,appLogPath:m,appLogState:f});if(A){let e=await tZ(d.id,c);if(e){let t=t9(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:y});t.entries.length>0&&(I=t4(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 rm({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=t4(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 rf(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 tj(i.readFileSync(e,"utf8"))}catch{return null}}(e)?.command;if(!t)return null;let r=/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(t);return r?.[1]??null}(o.join(o.dirname(a),tV));if(!s)return null;let l=await tJ(t.id,r);return l&&l!==s?{reason:"stale-active",trackedPid:s}:null}async function rp(e,t,r,a){rd(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 t2(e.id,n,o,a):await t0(e.id,t,n,o,e.simulatorSetPath,a);if("android"===e.platform)return tW(t),await tX(e.id,t,n,o,a);if("macos"===e.platform)return await t1(t,n,o,a);throw n.end(),new j("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rm(e){let t=await tQ({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:t9(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 rh(e){await e.stop(),await tB(e.wait)}async function rg(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 rw(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 ry=new Map;function rv(e){let t=ry.get(e);if(t&&(clearTimeout(t.timer),ry.delete(e),t.deleteAfterDownload))try{i.rmSync(t.artifactPath,{force:!0})}catch{}}let rI=new Map;function rS(e,t){let r=rI.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 rA(e){let t=rI.get(e);t&&(clearTimeout(t.timer),rI.delete(e),i.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rb(e){let t=await r_(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 r_(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(rN),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 rN(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 rk=z(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rx(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 rD(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:rk});"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t),c.destroy(t),u(t)},rk)},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 rD(e,t){if(e.destroy(),!e.closed)try{await f(e,"close")}catch{}await i.promises.rm(t,{force:!0}).catch(()=>{})}async function rM(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 rx(e,t),{artifactPath:t,tempDir:s}}let t=o.join(s,"artifact.tar");await rx(e,t);let a=await rb({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 rP=new Set(["agent_device.command","agent-device.command"]),rL=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rR=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rO={"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"},rE=new Set([...rP,...rL,...rR,...Object.keys(rO)]);function rC(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function r$(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rT(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rF(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 rU(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rG(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}function rV(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 rj(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 rq(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:rC(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:rC(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:rC(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rH(){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 rB(e){let t=await rH(),{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 rz(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/artifacts/"))return void rK(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||r$(i,rC(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{r$(i,rC(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void r$(i,rC(a.id??null,-32600,"Invalid Request"),400);if(!rE.has(a.method))return void r$(i,rC(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void r$(i,rC(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rP.has(e))return{token:rF(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(rL.has(e)){let e,a=rU(t,"platform");if("ios"!==a&&"android"!==a)throw new j("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rF(t,r),session:rU(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rU(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=rV(e,"owner"),a=rV(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:rj(e,"artifactId")}:(n&&(t=rj(e,"runId")),{kind:"github-actions-artifact",owner:r,repo:a,...n?{runId:t}:{},artifactName:rV(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:rG(t,"retentionMs")}}}if(rR.has(e)){let e=rU(t,"materializationId")?.trim();if(!e)throw new j("INVALID_ARGS","Invalid params: materializationId is required");return{token:rF(t,r),session:rU(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rU(t,"requestId"),materializationId:e}}}let a=rO[e];if(a)return{token:rF(t,r),session:rU(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rU(t,"tenantId")??rU(t,"tenant"),runId:rU(t,"runId"),leaseId:rU(t,"leaseId"),leaseTtlMs:rG(t,"ttlMs"),leaseBackend:rU(t,"backend")}};throw new j("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rP.has(s)&&("string"!=typeof l.command||0===l.command.length))return void r$(i,rC(a.id??null,-32602,"Invalid params: command is required"),400);o=e$(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},el(o);let u=()=>{i.writableFinished||ez(o)};e.on("aborted",u),i.on("close",u);let d=await rq(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!d.ok)return void r$(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 r$(i,{jsonrpc:"2.0",id:a.id??null,result:c});r$(i,rC(a.id??null,-32e3,c.error.message,c.error),rT(c.error.code))}catch(t){let e=V(t);r$(i,rC(a.id??null,-32e3,e.message,e),rT(e.code))}finally{eY(o)}})})}async function rz(e,t,r,i){try{var n;let o,s,l=rF({},e.headers),u=rW(l,i);if(u){t.statusCode=rT(u.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.message,code:u.code}));return}let d=await rq(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 rM(e),f=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:d.tenantId},o=a.randomUUID(),(s=setTimeout(()=>{rA(o)},3e5)).unref(),rI.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=rT(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rK(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=rF({},e.headers),s=rW(o,a);if(s){t.statusCode=rT(s.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.message,code:s.code}));return}let l=await rq(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=ry.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 rv(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=rT(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rv(n)}),d.pipe(t)}catch(r){let e=V(r);t.statusCode=rT(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rW(e,t){return t&&e!==t?V(new j("UNAUTHORIZED","Invalid token")):null}function rJ(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 rX(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 rY{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=rX(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=rJ(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=rZ(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=rZ(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=rX(e.backend),r=b(e.tenantId);if(!r)throw new j("INVALID_ARGS","tenant isolation requires tenant id.");let a=rJ(e.runId);if(!a)throw new j("INVALID_ARGS","tenant isolation requires run id.");let i=rZ(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=rJ(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 rQ=z(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),r0=new Map;async function r1(e){let t=await h.mkdtemp(o.join(c.tmpdir(),"agent-device-materialized-"));try{let r=await r8(e.installablePath,o.join(t,"installable")),i=e.archivePath?await r8(e.archivePath,o.join(t,"archive")):void 0,n=a.randomUUID(),s=e.ttlMs??rQ,l=Date.now()+s,u=setTimeout(()=>{r2(n)},s);return r0.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 r2(e,t){let r=r0.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),r0.delete(e),await h.rm(r.rootPath,{recursive:!0,force:!0})}async function r3(e){let t=Array.from(r0.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await r2(e)}))}async function r8(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 r5(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 eZ(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 eZ(a),a}async function r4(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:rS(o,t.meta?.tenantId)},cleanup:()=>{rA(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 r5({session:i,flags:t.flags});if(!e4("install",u))return eu("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let d=te(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 r1({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,r9(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await r2(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 r1({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,r9(d));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await r2(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:V(e)}}}function r9(e){return`Installed: ${I(e)}`}async function r6(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 r2(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:V(e)}}}let r7=z(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),ae=z(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function at(e,t,r){return t||ar(r)?null:eu("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function ar(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function aa(e){return"ios"===e.platform&&"simulator"===e.kind}async function ai(e,t){aa(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function an(e){let t=ar(e.flags)||!e.session?await ep(e.flags??{}):await ao(e.session.device);return!1!==e.ensureReady&&await eZ(t),t}async function ao(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 as(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 al="shared_prefs/ReactNativeDevPrefs.xml",au="debug_http_host",ad="dev_server_https",ac="RCT_jsLocation",af="RCT_packager_scheme",ap="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.",am='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function ah(e){return void 0!==$(e)}async function ag(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=$(a);if(i){if("android"===t.platform)return void await ay(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await aA(t,r,i)}}async function aw(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await av(t,r);"ios"===t.platform&&"simulator"===t.kind&&await ab(t,r)}}async function ay(e,t,r){var a,i,n,o,s,l;let u,d;ax(t);let c=(a=await aI(e,t),i=au,n=`${r.host}:${r.port}`,u=` <string name="${aD(i)}">${aD(n)}</string>`,aN(ak(a,i),u));o=c,s=ad,l="https"===r.scheme,d=` <boolean name="${aD(s)}" value="${l?"true":"false"}" />`,c=aN(ak(o,s),d),await aS(e,t,c)}async function av(e,t){ax(t);let r=await aI(e,t),a=ak(r,au),i=ak(a,ad);i!==r&&await aS(e,t,i)}async function aI(e,t){let r=await H("adb",eF(e,["shell","run-as",t,"cat",al]),{allowFailure:!0});return 0!==r.exitCode?am:a_(r.stdout)}async function aS(e,t,r){let a=eF(e,["shell","run-as",t,"id"]),i=await H("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=aM(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?ap:"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",eF(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await H("adb",eF(e,["shell","run-as",t,"tee",al]),{stdin:r.trimEnd()})}catch(a){let e=G(a);if("TOOL_MISSING"===e.code)throw e;let r=aM("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?ap:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function aA(e,t,r){await H("xcrun",eQ(e,["spawn",e.id,"defaults","write",t,ac,"-string",`${r.host}:${r.port}`])),await H("xcrun",eQ(e,["spawn",e.id,"defaults","write",t,af,"-string",r.scheme]))}async function ab(e,t){await H("xcrun",eQ(e,["spawn",e.id,"defaults","delete",t,ac]),{allowFailure:!0}),await H("xcrun",eQ(e,["spawn",e.id,"defaults","delete",t,af]),{allowFailure:!0})}function a_(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 aP=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function aL(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function aR(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 aO(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 aE(e){if("ios"===e||"android"===e)return e}async function aC(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!ah(r)||ah(a)||await aw({device:i.device,appId:i.appBundleId})}async function a$(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){ah(l)&&s?.appBundleId&&await aw({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=aE(e7(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:aO(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===aL(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 aT="open-command-roundtrip",aF="Not implemented for this platform in this release.",aU=new Set(["app","desktop","frontmost-app"]);async function aG(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await e2();return{appBundleId:t.bundleId,appName:t.appName}}async function aV(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return eN(t)?"macos"===e.platform?void 0:"device"===e.kind?eW(r,t):void 0:await aj(e,t)}async function aj(e,t){try{let{resolveIosApp:r}=await import("../3918.js");return await r(e,t)}catch{return}}async function aq(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 aH(e,t,r,a){return await aV(e,t,r)??await a(e,t)??("android"===e.platform&&t&&eN(t)?r:void 0)}function aB(e){return eu("INVALID_ARGS",e)}function az(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=tt(r);if(!aU.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?tt(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 aK(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&eN(r)?aB("open --relaunch does not support URL targets."):"app"!==a?aB("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===ev(r)?aB(ej(r)):null:null}async function aW(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await eZ(i);let{appBundleId:l,appName:u}=await aJ({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=>!aP.includes(e));if(i)throw new j("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${aP.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:aR(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 aO(e)}}(t.metroPort),bundleUrl:aR(t.bundleUrl,"bundleUrl"),launchUrl:aR(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:aE(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=aE(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&&aL(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 aC({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:u,runtime:d.data.runtime}}}async function aJ(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await aG(r);return{appBundleId:n.appBundleId??await aH(t,a,i,aq),appName:n.appName??a}}let aZ=new Map;async function aX(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 ai(t,r7)}async function aY(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,{...eE(i,a.flags,n,o)})}async function aQ(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 aX({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...eE(s,i.flags,p??h?.appBundleId,w)}})}await ag({device:l,appId:p,runtime:m});let y=Date.now();await X(l,"open",d,i.flags?.out,{...eE(s,i.flags,p)}),await aY({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:aT,appTarget:u,appBundleId:p}:void 0;if(await ai(l,ae),eT(i.meta?.requestId)){let e=eo();return eu(e.code,e.message,e.details)}h&&ta(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===aL(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:aL});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 a0(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=az(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?aB("open --relaunch requires an app name or an active session app."):aB("Session already active. Close it first or pass a new --session name.");let u=aK({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(u)return u;let d=await ao(e.device),c=await aW({req:t,sessionName:r,sessionStore:i,device:d,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await aQ({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 aB("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&eN(r)?aB("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===ev(r)?aB(ej(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=az(l,t.flags?.surface,o);if("string"!=typeof u)return u;let d=aK({shouldRelaunch:n,openTarget:o,surface:u,device:l});return d||await eg(aZ,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 aW({req:t,sessionName:r,sessionStore:i,device:l,surface:u,openTarget:o});return"response"===n.type?n.response:await aQ({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 a1(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 a2(e){let{device:t,shutdownRequested:r}=e;if(r&&(aa(t)||"android"===t.platform&&"emulator"===t.kind))try{return aa(t)?await ea(t):await a1(t)}catch(t){let e=V(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function a3(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 a8(e,t){e.appLog&&await rh(e.appLog),e6(e.device.platform)&&await a3(e),await r3(t).catch(()=>{})}async function a5(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 rh(n.appLog),t.positionals&&t.positionals.length>0&&(e6(n.device.platform)&&await a3(n),await X(n.device,"close",t.positionals,t.flags?.out,{...eE(a,t.flags,n.appBundleId,n.trace?.outPath)}),await ai(n.device,r7)),e6(n.device.platform)&&await a3(n),ah(i.getRuntimeHints(r))&&n.appBundleId&&await aw({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 r3(r).catch(()=>{}),i.delete(r);let o=await a2({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 a4=["platform","target","device","udid","serial","verbose","out"];function a9(e,t){let r=e??{};for(let e of a4)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let a6={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)}},a7={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 ie(e){let{req:t,command:r,sessionName:a,sessionStore:n,deployOps:o}=e,s=n.get(a),l=t.flags??{},u=at(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?rS(f,t.meta?.tenantId):tU.expandHome(c);if(!i.existsSync(a))return eu("INVALID_ARGS",`App binary not found: ${a}`);let u=await an({session:s,flags:l,ensureReady:!1});if(!e4(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&&rA(f)}}async function it(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 ir(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 ir(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{};return a9(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 ia(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 ii({deviceName:i,runtime:n,simctlOpts:d});e?(t=e.udid,r=e.runtime,a=!1):(t=(await io({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await is(t,d),a=!0)}else t=(await io({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await is(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 ii(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await H("xcrun",Z(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:e3});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||il(a).includes(il(r))){for(let e of i)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function io(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 is(e,t){let r=await H("xcrun",Z(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:e3});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function il(e){return e.toLowerCase().replace(/[._-]/g,"")}async function iu(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=eB(e.iosSimulatorDeviceSet);if(!r)return eu("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await ia({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:eZ});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=e7(t.flags?.platform),i=J({simulatorSetPath:eB(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=at(t.command,e,i);if(n)return n;let o=await an({session:e,flags:i,ensureReady:!0});if(!e4("apps",o))return eu("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(e6(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 id(e){let{ensureAndroidEmulatorBooted:t}=await import("../3918.js");return await t(e)}let ic='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',ip='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function im(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=e7(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=at("appstate",i,n);if(s)return s;let l=e6(i?.device.platform)&&function(e,t){if(!t)return!1;if(!ar(e))return!0;let r=e7(e?.platform);return!(r&&!e5(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",ic);if("macos"===o&&!l)return eu("SESSION_NOT_FOUND",ip);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 an({session:i,flags:n,ensureReady:!0});if("ios"===u.platform)return eu("SESSION_NOT_FOUND",ic);if("macos"===u.platform)return eu("SESSION_NOT_FOUND",ip);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 ih(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=at(t.command,i,n);if(o)return o;let s="android"===(e7(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=as({flags:n,sessionDevice:i?.device}),d=s&&!!u,c=!1;try{e=await an({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 id({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=as({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 id({avdName:t,serial:n.serial,headless:!0})}await eZ(e)}else("android"!==e.platform||!0!==e.booted)&&await eZ(e);return e4("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 im({req:t,sessionName:r,sessionStore:a}):null}function ig(e){return Math.round(10*e)/10}let iw="adb-shell-dumpsys-cpuinfo",iy="adb-shell-dumpsys-meminfo";async function iv(e,t){try{let r=await H("adb",eF(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:ig(i),measuredAt:r,method:iw,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw iS("cpu",t,e)}}async function iI(e,t){try{let r=await H("adb",eF(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=iA(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!==ib(e));if(!r)break;return ib(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:iA(e,"TOTAL RSS"),measuredAt:r,method:iy}}(r.stdout,t,new Date().toISOString())}catch(e){throw iS("memory",t,e)}}function iS(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 iA(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return ib(a[1])??void 0}function ib(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let i_="ps-process-snapshot",iN="ps-process-snapshot",ik="xctrace-activity-monitor",ix="xctrace-activity-monitor";async function iD(e,t){if("ios"===e.platform&&"device"===e.kind)return await iL(e,t);let r=await iP(e,t),a=await iT(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=tv(a.map(e=>o.basename(iF(e.command))));return iU({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:n,cpuMethod:i_,memoryMethod:iN})}async function iM(e){let t=e1(e),r=iG(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=iG(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:iV(e),processName:iq(e)})}let r=ij(t[i],d),a=(c=t[n],f=d,c?c.attributes.ref?f.get(c.attributes.ref)?.processName??null:iq(c):null);null!==r&&Number.isFinite(r)&&a&&u.push({pid:r,processName:a,cpuTimeNs:ij(t[o],d),residentMemoryBytes:ij(t[s],d)})}return u}async function iP(e,t){let r="macos"===e.platform?await iC(t):await i$(e,t),a="macos"===e.platform?o.join(r,"Contents","Info.plist"):o.join(r,"Info.plist"),i=await eX(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 iL(e,t){let r=await iR(e,t),a=await iO(e,t),i=await iO(e,t),n=iE(await iM(a.xml),r,t,e),o=iE(await iM(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 iU({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:ik,memoryMethod:ix})}async function iR(e,t){let r=(await e8(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 e9(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 iO(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:iH(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:iH(u.stdout,u.stderr)});return{capturedAtMs:s,xml:await n.readFile(i,"utf8")}}finally{await n.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function iE(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:iB(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iB(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:tv(d.map(e=>e.processName))}}async function iC(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 i$(e,t){let r=eQ(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 iT(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:eQ(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=iF(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||o.basename(i)===a.executableName})}function iF(e){let[t=""]=e.trim().split(/\s+/,1);return t}function iU(e){return{cpu:{usagePercent:ig(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 iG(e,t){for(let r of e){if(t(r))return r;let e=iG(r.children,t);if(e)return e}}function iV(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 ij(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:iV(e):null}function iq(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function iH(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")?
|
|
10
|
-
`,i.appendFileSync(o,a,"utf8"),{ok:!0,data:{path:o,marked:!0}}}(t,r,a):"clear"===o?i5(n,r,a,s):"start"===o?i4(n,r,a):"stop"===o?i9(n,r,a):eu("INVALID_ARGS",iZ):eu("INVALID_ARGS",iZ)}async function i8(e,t,r){let a=r.resolveAppLogPath(t),i=await rg(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 i5(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:rw(i)};e.appLog&&await rh(e.appLog);let n=rw(i),o=r.resolveAppLogPidPath(t);try{let a=await rp(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 i4(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 rp(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 i9(e,t,r){if(!e.appLog)return eu("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await rh(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function i6(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(!e4("network",i.device))return eu("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!iX.includes(n))return eu("INVALID_ARGS",iY);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 iQ.includes(a)?{ok:!0,include:a}:eu("INVALID_ARGS",i0)}(t);if(!s.ok)return s;let{include:l}=s,u=await rc({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 i7=/^[A-Z_][A-Z0-9_]*$/,ne=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-((?:[^}\\]|\\.)*))?\}/g,nt="AD_VAR_";function nr(e){return e.startsWith("AD_")}function na(e){return new j("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function ni(e,t,r){return e.replace(ne,(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 nn(e,t,r){if(!e)return e;let a={...e};for(let[e,i]of Object.entries(a))"string"==typeof i&&(a[e]=ni(i,t,r));return a}let no=new Set(["ios","android","macos","linux"]);function ns(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(nl(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(!i7.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&&no.has(e)&&nu(r,"platform",e)}let n=a.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&nu(r,"timeoutMs",Math.floor(e))}let o=a.match(/(?:^|\s)retries=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=0&&nu(r,"retries",Math.floor(e))}}return r}function nl(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function nu(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 nd(e){return!!e&&!Number.isNaN(Number(e))}let nc=/[*?[\]{}]/;async function nf(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(()=>{eY(i)});try{return"number"==typeof n?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{c=!0,ez(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 np(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 np(e){return await Promise.race([e.then(()=>!0),g(2e3).then(()=>!1)])}async function nm(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=tU.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,!nc.test(r)&&(a=n,!nc.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=ns(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=tU.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 nh({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 nh(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 e$(`${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 nf({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 ng(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=ti(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 nw(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(tN(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),tN(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}=ts(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=ng(e.positionals??[]);r&&t.push(r)}return tv(t).filter(e=>e.trim().length>0)})(t).map(e=>tl(e)).filter(e=>null!==e);if(0===o.length)return null;let s=tN(t.command)||"fill"===t.command,l=tN(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await ny(n,t,a,s,i);for(let e of o){let r=tu(u.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=tc(r.node,n.device.platform,{action:tN(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tN(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=ty(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}=ts(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}=ng(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function ny(e,t,r,a,i){let n=await X(e.device,"snapshot",[],t.flags?.out,{...eE(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:tm(t.flags?.snapshotRaw?o:tp(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return eh(e,s),i.set(e.name,e),s}async function nv(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=tU.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=ns(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(nl(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=t$(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=t$(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tN(a)){let e=tC(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 nd(r)&&nd(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=tC(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=tC(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(nr(e))throw na(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(nt))continue;let e=r.slice(nt.length);0!==e.length&&i7.test(e)&&(nr(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(!i7.test(a))throw new j("INVALID_ARGS",`Invalid -e key "${a}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(nr(a))throw na(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 nI({req:t,sessionName:r,action:i,scope:y,filePath:u,line:w[e]??0,invoke:s});if(o.ok){nA(o).forEach(e=>d.add(e));continue}if(!v)return nS(o,i,e,u,[...d]);let l=await nw({action:i,sessionName:r,logPath:a,sessionStore:n});if(!l)return nS(o,i,e,u,[...d]);if(g[e]=l,!(o=await nI({req:t,sessionName:r,action:l,scope:y,filePath:u,line:w[e]??0,invoke:s})).ok)return nS(o,l,e,u,[...d]);nA(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=${tD(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",tx(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tF(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tM(r,tL));return tO(t,e.flags),t.join(" ")}if("record"===e.command)return tE(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tx(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(tx(r));return tR(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 nI(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=>ni(e,o,t)),flags:nn(n.flags,o,t)??{},runtime:nn(n.runtime,o,t)});return await u({token:a.token,session:i,command:d.command,positionals:d.positionals??[],flags:(r=a.flags,a9(r,{...d.flags??{}})),runtime:d.runtime,meta:a.meta})}function nS(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=>tx(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 nA(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 nb(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await nv({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await nm({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 nv({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&&nA(t).forEach(e=>u.add(e)),t}})},cleanupSession:async e=>{i.get(e)&&await a5({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let n_=new Set(["session_list","ensure-simulator","devices","apps"]),nN=new Set(["boot","appstate"]),nk=new Set(["perf","logs","network"]),nx=new Set(["replay","test"]);async function nD(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=at(n,u,d);if(c)return c;let f=await an({session:u,flags:d,ensureReady:!0});if(!e4(n,f))return eu("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await X(f,n,o,t.flags?.out,{...eE(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 nM(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=at("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 an({session:n,flags:o,ensureReady:!0});if(!e4("clipboard",u))return eu("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let d=await X(u,"clipboard",t.positionals??[],t.flags?.out,{...eE(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 nP(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(n_.has(t.command))return await iu({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await a$({req:t,sessionName:r,sessionStore:i});if(nN.has(t.command))return await ih({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await nM({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"!==e7((t.flags??{}).platform)?await nD({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(nk.has(t.command))return await i1({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await ie({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?a7:a6});if("install_source"===t.command)return await r4({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await r6({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await nD({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=eU(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tU.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 nD({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 aH(e.device,r,e.appBundleId,aq)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await a0({req:t,sessionName:r,logPath:a,sessionStore:i}):nx.has(t.command)?await nb({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await it(t,r,n):"close"===t.command?await a5({req:t,sessionName:r,logPath:a,sessionStore:i}):null}async function nL(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}=tw(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 eK({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 eZ(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&&!e0(m))return{nodes:v};let{snapshot:n}=await eD({device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:g}),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 nR(S,I,l,u,f);let{nodes:A}=await I(),b=tg(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=to(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?tn(A,x)??x:x,M=`@${D.ref}`,P={node:x,resolvedNode:D,ref:M,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},L={exists:()=>nO(S),get_text:()=>nE(S,P),get_attrs:()=>nC(S,P),click:()=>n$(S,P),fill:()=>nT(S,P,c),focus:()=>nF(S,P),type:()=>nU(S,P,c)}[d];return L?L():null}async function nR(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(tg(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 nO(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 nE(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await ex({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eE(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 nC(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 n$(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?th(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 nT(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 nF(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?th(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,{...eE(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 nU(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?th(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,{...eE(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let d=await X(o,"type",[r],a.flags?.out,{...eE(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 nG=`
|
|
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 R,resolveDeployResultTarget as L,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,IOS_RUNNER_CONTAINER_BUNDLE_IDS as Y,refSnapshotFlagGuardResponse as Q,buttonTag as ee,handleSnapshotCommands as et,shutdownSimulator as er,stopIosRunnerSession as ea,localCommandPolicy as ei,createRequestCanceledError as en,isNavigationSensitiveAction as eo,registerRequestAbort as es,errorResponse as el,resolveIosDevicectlHint as eu,getClickButtonValidationError as ed,snapshotAndroid as ec,resolveTargetDevice as ef,dispatchGetViaRuntime as ep,setSessionSnapshot as em,withKeyedLock as eh,assertAndroidPressStayedInApp as eg,classifyAndroidAppTarget as ew,parseSerialAllowlist as ey,stopAllIosRunnerSessions as ev,runMacOsAlertAction as eI,createAgentDevice as eS,getAndroidAppState as eA,getAndroidScreenSize as eb,isDeepLinkTarget as e_,withResolveTargetDeviceCacheScope as eN,readTextForNode as ek,captureSnapshot as ex,dispatchIsViaRuntime as eD,resolveClickButton as eM,IOS_DEVICECTL_DEFAULT_HINT as eP,buildSnapshotState as eR,openAndroidApp as eL,context_contextFromFlags as eO,captureSnapshotData as eE,resolveRequestTrackingId as eC,isRequestCanceled as e$,adbArgs as eT,resolvePayloadInput as eF,abortAllIosRunnerSessions as eU,getRunnerSessionSnapshot as eG,formatAndroidInstalledPackageRequiredMessage as eV,createUnsupportedArtifactAdapter as ej,isAndroidEscapeError as eq,resolveIosSimulatorDeviceSetPath as eH,markRequestCanceled as eB,dispatchFindReadOnlyViaRuntime as ez,resolveIosDeviceDeepLinkBundleId as eK,runIosRunnerCommand as eW,ensureDeviceReady as eJ,readInfoPlistString as eZ,clearRequestCanceled as eX,buildSimctlArgsForDevice as eY,getActiveAndroidSnapshotFreshness as eQ,parseXmlDocumentSync as e0,resolveFrontmostMacOsApp as e1,IOS_SIMCTL_LIST_TIMEOUT_MS as e2,listIosDeviceApps as e3,matchesPlatformSelector as e5,isCommandSupportedOnDevice as e4,listIosDeviceProcesses as e8,isApplePlatform as e7,normalizePlatformSelector as e6,getRequestSignal as e9,parseSessionSurface as te,buildScrollGesturePlan as tt,markAndroidSnapshotFreshness as tr}from"../2007.js";import{runBatch as ta,mergeParentFlags as ti}from"../1231.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,tR)}function tM(e){return JSON.stringify(e)}function tP(e,t){return t(e)?e:tM(e)}function tR(e){return tL(e)&&e.startsWith("@")||tS.test(e)}function tL(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,tL)),"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,tL)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tP(t.launchUrl,tL)))}function tC(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tP(r,tL)),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,tL)),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 t5=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),t4=/https?:\/\/[^\s"'<>\])]+/i,t8=[/\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 t7(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>t9(e)));for(let e of t.entries){let t=t9(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=t5.exec(o),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=t4.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 t9(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 t8){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=t7(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=t7(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 rR=new Set(["agent_device.command","agent-device.command"]),rL=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([...rR,...rL,...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(rR.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(rL.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,rR.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=eC(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},es(o);let u=()=>{i.writableFinished||eB(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{eX(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 r4(e.installablePath,o.join(t,"installable")),i=e.archivePath?await r4(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 r5(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 r4(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 r8(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 eJ(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 ef(e.flags??{});return await eJ(a),a}async function r7(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 r8({session:i,flags:t.flags});if(!e4("install",u))return el("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("../2007.js"),{prepareIosInstallArtifact:o}=await import("../2007.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("../2007.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("../2007.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("../2007.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 r9(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:el("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 ef(e.flags??{}):await as(e.session.device);return!1!==e.ensureReady&&await eJ(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 ef(t)}catch(e){if(!(e instanceof j)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await ef({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",eT(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=eT(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",eT(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await H("adb",eT(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",eY(e,["spawn",e.id,"defaults","write",t,af,"-string",`${r.host}:${r.port}`])),await H("xcrun",eY(e,["spawn",e.id,"defaults","write",t,ap,"-string",r.scheme]))}async function a_(e,t){await H("xcrun",eY(e,["spawn",e.id,"defaults","delete",t,af]),{allowFailure:!0}),await H("xcrun",eY(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"!==ew(e))return;let t=eV(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 aR=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function aL(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 el("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(e6(a.flags?.platform)??l?.platform??s?.device.platform);if(!u)return el("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 el("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===aL(d)?el("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 e1();return{appBundleId:t.bundleId,appName:t.appName}}async function aj(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return e_(t)?"macos"===e.platform?void 0:"device"===e.kind?eK(r,t):void 0:await aq(e,t)}async function aq(e,t){try{let{resolveIosApp:r}=await import("../2007.js");return await r(e,t)}catch{return}}async function aH(e,t){if(!("android"!==e.platform||!t||e_(t)))try{let{resolveAndroidApp:r}=await import("../2007.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&&e_(t)?r:void 0)}function az(e){return el("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=te(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?te(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 el(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&&e_(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"===ew(r)?az(eV(r)):null:null}async function aJ(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await eJ(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=>!aR.includes(e));if(i)throw new j("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${aR.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&&aL(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=G(t);return el(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 ea(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||e_(u)||await X(r,"open",[l],a.flags?.out,{...eO(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:{...eO(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,{...eO(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),e$(i.meta?.requestId)){let e=en();return el(e.code,e.message,e.details)}h&&tr(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===aL(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,...R(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:p,surface:f,startup:v,device:l,runtime:m,runtimeHintCount:aL});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 el("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&&e_(r)?az("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===ew(r)?az(eV(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await ef(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 eh(aX,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return el("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 er(t):await a2(t)}catch(t){let e=V(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function a5(e){if(await ea(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await eI("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 a4(e,t){e.appLog&&await rg(e.appLog),e7(e.device.platform)&&await a5(e),await r5(t).catch(()=>{})}async function a8(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return el("SESSION_NOT_FOUND","No active session");n.appLog&&await rg(n.appLog),t.positionals&&t.positionals.length>0&&(e7(n.device.platform)&&await a5(n),await X(n.device,"close",t.positionals,t.flags?.out,{...eO(a,t.flags,n.appBundleId,n.trace?.outPath)}),await an(n.device,ae)),e7(n.device.platform)&&await a5(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,...R(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await r5(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,...R(`Closed: ${r}`)}}}let a7={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await import("../2007.js");return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await import("../2007.js");return await a(e,t,r)}},a6={ios:async(e,t,r)=>{let{installIosApp:a}=await import("../2007.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("../2007.js"),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function a9(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 el("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 el("INVALID_ARGS",`App binary not found: ${a}`);let u=await ao({session:s,flags:l,ensureReady:!1});if(!e4(r,u))return el("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??L(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 ie(e,t,r){return await ta(e,t,r)}async function it(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 ir({deviceName:i,runtime:n,simctlOpts:d});e?(t=e.udid,r=e.runtime,a=!1):(t=(await ia({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await ii(t,d),a=!0)}else t=(await ia({deviceName:i,runtime:n,simctlOpts:d})).udid,r=await ii(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 ir(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await H("xcrun",Z(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:e2});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||io(a).includes(io(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 ia(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 ii(e,t){let r=await H("xcrun",Z(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:e2});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 io(e){return e.toLowerCase().replace(/[._-]/g,"")}async function is(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=eH(e.iosSimulatorDeviceSet);if(!r)return el("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await it({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:eJ});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 el(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=K(t.flags?.androidDeviceAllowlist),a=e6(t.flags?.platform),i=J({simulatorSetPath:eH(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("../2007.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("../2007.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("../2007.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("../2007.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 el(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(!e4("apps",o))return el("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(e7(o.platform)){let{listIosApps:e}=await import("../2007.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("../2007.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 il(e){let{ensureAndroidEmulatorBooted:t}=await import("../2007.js");return await t(e)}let iu='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',id='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function ic(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=e6(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return el("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=e6(e?.platform);return!(r&&!e5(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 el("SESSION_NOT_FOUND",iu);if("macos"===o&&!l)return el("SESSION_NOT_FOUND",id);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 el("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 el("SESSION_NOT_FOUND",iu);if("macos"===u.platform)return el("SESSION_NOT_FOUND",id);let{getAndroidAppState:d}=await import("../2007.js"),c=await d(u);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function ip(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"===(e6(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!s)return el("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 el("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 il({avdName:u,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return el("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return el("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 el("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await il({avdName:t,serial:n.serial,headless:!0})}await eJ(e)}else("android"!==e.platform||!0!==e.booted)&&await eJ(e);return e4("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:el("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await ic({req:t,sessionName:r,sessionStore:a}):null}function im(e){return Math.round(10*e)/10}let ih="adb-shell-dumpsys-cpuinfo",ig="adb-shell-dumpsys-meminfo";async function iw(e,t){try{let r=await H("adb",eT(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:im(i),measuredAt:r,method:ih,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw iv("cpu",t,e)}}async function iy(e,t){try{let r=await H("adb",eT(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=iI(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!==iS(e));if(!r)break;return iS(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:iI(e,"TOTAL RSS"),measuredAt:r,method:ig}}(r.stdout,t,new Date().toISOString())}catch(e){throw iv("memory",t,e)}}function iv(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 iI(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return iS(a[1])??void 0}function iS(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let iA="ps-process-snapshot",ib="ps-process-snapshot",i_="xctrace-activity-monitor",iN="xctrace-activity-monitor";async function ik(e,t){if("ios"===e.platform&&"device"===e.kind)return await iM(e,t);let r=await iD(e,t),a=await iC(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(i$(e.command))));return iT({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:n,cpuMethod:iA,memoryMethod:ib})}async function ix(e){let t=e0(e),r=iF(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=iF(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:iU(e),processName:iV(e)})}let r=iG(t[i],d),a=(c=t[n],f=d,c?c.attributes.ref?f.get(c.attributes.ref)?.processName??null:iV(c):null);null!==r&&Number.isFinite(r)&&a&&u.push({pid:r,processName:a,cpuTimeNs:iG(t[o],d),residentMemoryBytes:iG(t[s],d)})}return u}async function iD(e,t){let r="macos"===e.platform?await iO(t):await iE(e,t),a="macos"===e.platform?o.join(r,"Contents","Info.plist"):o.join(r,"Info.plist"),i=await eZ(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 iM(e,t){let r=await iP(e,t),a=await iR(e,t),i=await iR(e,t),n=iL(await ix(a.xml),r,t,e),o=iL(await ix(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 iT({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:i_,memoryMethod:iN})}async function iP(e,t){let r=(await e3(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 e8(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 iR(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:ij(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:ij(u.stdout,u.stderr)});return{capturedAtMs:s,xml:await n.readFile(i,"utf8")}}finally{await n.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function iL(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:iq(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iq(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 iO(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 iE(e,t){let r=eY(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 iC(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:eY(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=i$(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||o.basename(i)===a.executableName})}function i$(e){let[t=""]=e.trim().split(/\s+/,1);return t}function iT(e){return{cpu:{usagePercent:im(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 iF(e,t){for(let r of e){if(t(r))return r;let e=iF(r.children,t);if(e)return e}}function iU(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 iG(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:iU(e):null}function iV(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function ij(e,t){let r=eu(e,t);if(r)return r;let a=`${e}
|
|
9
|
+
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?eP:a.includes("timed out")?"Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.":"Ensure the iOS device is unlocked, trusted, visible to xctrace, and the target app stays active while perf samples it."}function iq(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function iH(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:ig,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:ih,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:iN,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:i_,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:ib,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:iA,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 iB(e);return n.metrics.memory=iz(o),n.metrics.cpu=iz(s),n}async function iB(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,a]=await Promise.allSettled([iy(e.device,t),iw(e.device,t)]);return[r,a]}try{let r=await ik(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 iz(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=V(e.reason);return{available:!1,reason:t.message,error:t}}let iK=["path","start","stop","doctor","mark","clear"],iW=`logs requires ${iK.slice(0,-1).join(", ")}, or ${iK.at(-1)}`,iJ=["dump","log"],iZ=`network requires ${iJ.join(" or ")}`,iX=["summary","headers","body","all"],iY=`network include mode must be one of: ${iX.join(", ")}`;async function iQ(e){let{req:t}=e;return"perf"===t.command?i0(e):"logs"===t.command?i1(e):"network"===t.command?i8(e):null}async function i0(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return el("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await iH(a)}}catch(e){return{ok:!1,error:V(e)}}}async function i1(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return el("SESSION_NOT_FOUND","logs requires an active session");if(!e4("logs",n.device))return el("UNSUPPORTED_OPERATION","logs is not supported on this device");let o=(t.positionals?.[0]??"path").toLowerCase(),s=!!t.flags?.restart;return iK.includes(o)?s&&"clear"!==o?el("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?i2(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?i3(n,r,a,s):"start"===o?i5(n,r,a):"stop"===o?i4(n,r,a):el("INVALID_ARGS",iW):el("INVALID_ARGS",iW)}async function i2(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 i3(e,t,r,a){if(e.appLog&&!a)return el("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return el("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 i5(e,t,r){if(e.appLog)return el("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return el("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 i4(e,t,r){if(!e.appLog)return el("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 i8(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return el("SESSION_NOT_FOUND","network requires an active session");if(!e4("network",i.device))return el("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!iJ.includes(n))return el("INVALID_ARGS",iZ);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return el("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 el("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return iX.includes(a)?{ok:!0,include:a}:el("INVALID_ARGS",iY)}(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 i7=/^[A-Z_][A-Z0-9_]*$/,i6=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-((?:[^}\\]|\\.)*))?\}/g,i9="AD_VAR_";function ne(e){return e.startsWith("AD_")}function nt(e){return new j("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function nr(e,t,r){return e.replace(i6,(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 na(e,t,r){if(!e)return e;let a={...e};for(let[e,i]of Object.entries(a))"string"==typeof i&&(a[e]=nr(i,t,r));return a}let ni=new Set(["ios","android","macos","linux"]);function nn(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(no(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(!i7.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&&ni.has(e)&&ns(r,"platform",e)}let n=a.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&ns(r,"timeoutMs",Math.floor(e))}let o=a.match(/(?:^|\s)retries=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=0&&ns(r,"retries",Math.floor(e))}}return r}function no(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function ns(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 nl(e){return!!e&&!Number.isNaN(Number(e))}let nu=/[*?[\]{}]/;async function nd(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,artifactsDir:s,runReplay:l,cleanupSession:u}=e;es(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 el(t.code,t.message)}).finally(()=>{eX(i)});try{return"number"==typeof n?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{c=!0,eB(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 nc(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 nc(e){return await Promise.race([e.then(()=>!0),g(2e3).then(()=>!1)])}async function nf(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:n}=e;if((t.positionals?.length??0)===0)return el("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,!nu.test(r)&&(a=n,!nu.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=nn(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 np({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 el(e.code,e.message)}}async function np(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 eC(`${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 nd({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 nm(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 nh(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}=nm(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 ng(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}=nm(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function ng(e,t,r,a,i){let n=await X(e.device,"snapshot",[],t.flags?.out,{...eO(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 em(e,s),i.set(e.name,e),s}async function nw(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:s}=e,l=t.positionals?.[0];if(!l)return el("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 el("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let m=nn(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(no(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 nl(r)&&nl(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 el("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 el("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(ne(e))throw nt(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(i9))continue;let e=r.slice(i9.length);0!==e.length&&i7.test(e)&&(ne(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(!i7.test(a))throw new j("INVALID_ARGS",`Invalid -e key "${a}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(ne(a))throw nt(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 ny({req:t,sessionName:r,action:i,scope:y,filePath:u,line:w[e]??0,invoke:s});if(o.ok){nI(o).forEach(e=>d.add(e));continue}if(!v)return nv(o,i,e,u,[...d]);let l=await nh({action:i,sessionName:r,logPath:a,sessionStore:n});if(!l)return nv(o,i,e,u,[...d]);if(g[e]=l,!(o=await ny({req:t,sessionName:r,action:l,scope:y,filePath:u,line:w[e]??0,invoke:s})).ok)return nv(o,l,e,u,[...d]);nI(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,tL));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 el(e.code,e.message,d.size>0?{artifactPaths:[...d]}:void 0)}}async function ny(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=>nr(e,o,t)),flags:na(n.flags,o,t)??{},runtime:na(n.runtime,o,t)});return await u({token:a.token,session:i,command:d.command,positionals:d.positionals??[],flags:(r=a.flags,ti(r,{...d.flags??{}})),runtime:d.runtime,meta:a.meta})}function nv(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 nI(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 nS(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await nw({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await nf({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 nw({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&&nI(t).forEach(e=>u.add(e)),t}})},cleanupSession:async e=>{i.get(e)&&await a8({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let nA=new Set(["session_list","ensure-simulator","devices","apps"]),nb=new Set(["boot","appstate"]),n_=new Set(["perf","logs","network"]),nN=new Set(["replay","test"]);async function nk(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(!e4(n,f))return el("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await X(f,n,o,t.flags?.out,{...eO(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 nx(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 el("INVALID_ARGS","clipboard requires a subcommand: read or write");let u=await ao({session:n,flags:o,ensureReady:!0});if(!e4("clipboard",u))return el("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let d=await X(u,"clipboard",t.positionals??[],t.flags?.out,{...eO(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:d??{}}),{ok:!0,data:{platform:u.platform,...d??{}}}}async function nD(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(nA.has(t.command))return await is({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await aT({req:t,sessionName:r,sessionStore:i});if(nb.has(t.command))return await ip({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await nx({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"!==e6((t.flags??{}).platform)?await nk({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):el("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(n_.has(t.command))return await iQ({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await a9({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?a6:a7});if("install_source"===t.command)return await r7({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await r9({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await nk({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=eF(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tG.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):el("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await nk({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}):nN.has(t.command)?await nS({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await ie(t,r,n):"close"===t.command?await a8({req:t,sessionName:r,logPath:a,sessionStore:i}):null}async function nM(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 el("INVALID_ARGS","find requires a locator or text");let{locator:l,query:u,action:d,value:c,timeoutMs:f}=ty(s);if(!u)return el("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return el("INVALID_ARGS","find accepts only one of --first or --last");let p=await ez({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 el("SESSION_NOT_FOUND","No active session. Run open first.");let h=m?.device??await ef(t.flags??{});m||await eJ(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&&!eQ(m))return{nodes:v};let{snapshot:n}=await ex({device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:g}),o=n.nodes;return y=e,v=o,m&&(em(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 nP(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})`:""}`}),el("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 el("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}},R={exists:()=>nR(S),get_text:()=>nL(S,P),get_attrs:()=>nO(S,P),click:()=>nE(S,P),fill:()=>nC(S,P,c),focus:()=>n$(S,P),type:()=>nT(S,P,c)}[d];return R?R():null}async function nP(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 el("COMMAND_FAILED","find wait timed out")}async function nR(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 nL(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await ek({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eO(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 nO(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 nE(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 nC(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return el("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 n$(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 el("COMMAND_FAILED","matched element has no bounds");let u=await X(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eO(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 nT(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return el("INVALID_ARGS","find type requires text");let u=t.node.rect?tg(t.node.rect):null;if(!u)return el("COMMAND_FAILED","matched element has no bounds");await X(o,"focus",[String(u.x),String(u.y)],a.flags?.out,{...eO(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let d=await X(o,"type",[r],a.flags?.out,{...eO(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 nF=`
|
|
13
13
|
import Foundation
|
|
14
14
|
import AVFoundation
|
|
15
15
|
|
|
@@ -33,13 +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 nH(e);return!1}catch(t){if(t instanceof j&&"TOOL_MISSING"===t.code)return nH(e);throw t}}async function nq(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nj(e))return;await B(r)}}function nH(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 nB(e){let t=o.parse(e);return o.join(t.dir,`${t.name}.gesture-telemetry.json`)}function nz(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nK(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 nW(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await nV(t),await nq(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 nq(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 nJ(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nW({videoPath:r,scriptPath:t??=nK("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nZ(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nW({videoPath:r,scriptPath:e??=nK("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function nX(e){let{videoPath:t,quality:a,targetLabel:i="recording"}=e;await nW({videoPath:t,scriptPath:r??=nK("recording-resize.swift"),scriptArgs:["--quality",String(a)],commandDescription:`Failed to resize the ${i}`})}function nY(e){return e instanceof Error?e.message:String(e)}function nQ(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function n0(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=nB((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?nz(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)}]})):nz(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: ${nY(e)}`}}}async function n1(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 n2(e,t,r){for(let a=0;a<40;a+=1){if(!await n1(e,t,r))return!0;await B(250)}return!await n1(e,t,r)}async function n3(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 n8(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 n1(e,t,a))break;if(i+1>=2)return!0;await B(250)}return!1}async function n5(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=nQ(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 n4(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: ${nQ(i,"adb shell wm size")}`);return{width:n9(Number(n[1]),a),height:n9(Number(n[2]),a)}}function n9(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function n6(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function n7(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 n1(e,t,r))&&await n2(e,t,r)}async function oe(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 n4({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: ${nQ(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 n6(i,n.id,e);continue}if(O({level:"debug",phase:"record_start_android_started",data:{deviceId:n.id,remotePath:e,remotePid:a}}),await n8(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 n7(i,n.id,a),await n6(i,n.id,e)}return eu("COMMAND_FAILED",s)}async function ot(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 n1(a,i.id,n.remotePid)&&!await n7(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${nQ(o,"adb shell kill")}`):await n2(a,i.id,n.remotePid)||await n7(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await n3(a,i.id,n.remotePath);let e=await n5({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),eu("COMMAND_FAILED",e);await n0({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: ${nQ(e,"adb shell rm")}`)}}function or(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function oa(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function oi(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=or(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},oa(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:nY(e)}})}}async function on(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=oa(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(!nY(a).toLowerCase().includes("recording already in progress"))return eu("COMMAND_FAILED",`failed to start recording: ${nY(a)}`);O({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:nY(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: ${nY(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...d}}async function oo(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},oa(t,i,r))}catch(e){return eu("COMMAND_FAILED",`failed to start recording: ${nY(e)}`)}return{platform:"macos-runner",...s}}async function os(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=or(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},oa(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:nY(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 n0({recording:o,deps:n,trimStartMs:u,targetLabel:"iOS recording"}),null}async function ol(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=or(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},oa(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:nY(e)}})}return await n0({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function ou(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 od(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:u}=e;await oi({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:d,wait:c}=s.runCmdBackground("xcrun",eQ(n,["io",n.id,"recordVideo",u]),{allowFailure:!0}),f=await ou(u);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:or(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 oc(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(!e4("record",l))return eu("UNSUPPORTED_OPERATION","record is not supported on this device");let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,m=tU.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=or(s);if(!e)return eu("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await on({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=or(s);if(!e)return eu("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await oo({req:r,activeSession:s,device:l,logPath:u,deps:d,fpsFlag:c,recordingBase:h,appBundleId:e})}else t="ios"===l.platform?await od({req:r,activeSession:s,device:l,logPath:u,deps:d,recordingBase:h,resolvedOut:m}):await oe({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 of(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await ot({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: ${nQ(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: ${nY(e)}`}return await n0({recording:a,deps:t,targetLabel:"iOS recording"}),null}async function op(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 os({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):"macos-runner"===u.platform?await ol({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):await of({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 nB(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 om(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:H,runCmdBackground:q,runIosRunnerCommand:eJ,waitForStableFile:nV,isPlayableVideo:nj,trimRecordingStart:nJ,resizeRecording:nX,overlayRecordingTouches:nZ},o=a.get(r),s=o?.device??await ep(t.flags??{});o||await eZ(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 oc({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let d=await op({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 oh(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,s=t.command;if("record"===s)return om({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=tU.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=tU.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 og(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 ow=new WeakMap;function oy(e){if(!e)return;let t=ow.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)&&ov(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(ov);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 ow.set(e,r),r}function ov(e){return!!e&&e.width>0&&e.height>0}let oI={referenceWidth:1e3,referenceHeight:1e3};function oS(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=oN(p.effectiveDurationMs)??oN(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:oN(p.gestureStartUptimeMs),gestureEndUptimeMs:oN(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:oN(p.gestureStartUptimeMs),gestureEndUptimeMs:oN(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===oN(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=ok(oN(t.count),1)??1,r=!0===t.doubleTap,a=ok(oN(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 og(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):og(h),y=(l=e.snapshot,d=oN((u=p).referenceWidth),c=oN(u.referenceHeight),void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:oy(l)),v=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=ox(t,e);if(!i)return[];let{x:n,y:o}=i,s=ok(oN(t.count),1)??1,l=ok(oN(t.intervalMs),0)??0,u=!0===t.doubleTap,d=ok(oN(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(ob(t,n,o,d,a));continue}c.push(oA(t,n,o,a)),u&&c.push(oA(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=ox(t,e);if(!i)return[];let{x:n,y:o}=i;return[oA(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=ox(t,e);if(!n)return[];let{x:o,y:s}=n;return[ob(r,o,s,oM(a,[oN(t.durationMs),oN(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=oD(t,e),o=o_(t.contentDirection)??o_(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:u,y2:d}=n,c=oM(a,[],250),f=oN(t.amount)??oN(e[1]),p=oN(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=oD(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:u}=n,d=oM(a,[oN(t.effectiveDurationMs),oN(t.durationMs),oN(e[4])],250),c=ok(oN(t.count),1)??1,f=ok(oN(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=ox(t,e,1),o=oN(t.scale)??oN(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:oM(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 oA(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function ob(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function o_(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 oN(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 ok(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function ox(e,t,r=0){let a=oN(e.x)??oN(t[r]),i=oN(e.y)??oN(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function oD(e,t){let r=oN(e.x1)??oN(t[0]),a=oN(e.y1)??oN(t[1]),i=oN(e.x2)??oN(t[2]),n=oN(e.y2)??oN(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 oM(e,t,r){return ok(e,1)??t.map(e=>ok(e,1)).find(e=>void 0!==e)??r}function oP(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 oL(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)&&ta(t,a,d??t.snapshot),oS(t,a,i,o,n??{},l,u),{ok:!0,data:s}}async function oR(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await e_(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=oy(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=oy(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oO(e){try{return await oR(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 oE(e){return oy({nodes:e,createdAt:0})}function oC(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 o$(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)=>oT(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)=>oT(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)=>oT(await X(r.device,"type",[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),artifacts:eq("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 oT(e){return e&&"object"==typeof e?e:void 0}function oF(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 oU(e){return"ref"===e.kind?{ref:oG(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 oG(e){return e?.startsWith("@")?e.slice(1):e}async function oV(e){switch(e.req.command){case"press":case"click":return await oj(e);case"fill":return await oq(e);default:return null}}async function oj(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=oC(n,o);if(s)return s;if(!e4("press",n.device))return eu("UNSUPPORTED_OPERATION","press is not supported on this device");let l=eP(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=oF(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 oB(e,n)}return await oH(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 oO({session:n,flags:r.flags,sessionStore:i,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:e.captureSnapshotForSession}):oE(n.snapshot?.nodes??[]),o=oP({data:t.backendResult,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:a,extra:{...oU(t),...u}});return{result:o,responseData:o}}})}async function oq(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(i){let e=oC(i,"fill");if(e)return e}if(i&&!e4("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=oF(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=ti(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 oB(e,i)}return await oH(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:oE(i.snapshot?.nodes??[]),r=oP({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...oU(e),text:n.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:oG(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 oH(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return eu("SESSION_NOT_FOUND","No active session. Run open first.");let a=o$(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 oL({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(eH(e))throw e;return{ok:!1,error:V(t)}}}async function oB(e,t){if(!e0(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 oz(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 eD({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 oK=/\bis(?:n't| not)\s+responding\b/i,oW=/^close app$/i;async function oJ(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oZ(t),r=function(e){if(o0(e))return e.find(e=>{let t=oQ(e);return t.length>0&&oW.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=th(r.rect),n=await H("adb",eF(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 oX(t))return O({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eO(t.device,t.appBundleId),!await oY(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 oZ(e){return tm(tp((await ef(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function oX(e){for(let t=0;t<12;t+=1){if(!o0(await oZ(e)))return!0;await B(500)}return!o0(await oZ(e))}async function oY(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 oQ(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 o0(e){return e.some(e=>{let t=oQ(e);return t.length>0&&oK.test(t)})}async function o1(e){let t=await oV({...e,captureSnapshotForSession:oz,refSnapshotFlagGuardResponse:Q});if(t)return t;switch(e.req.command){case"type":return await o2({...e,captureSnapshotForSession:oz});case"get":return await em(e);case"is":return await eM(e);default:return null}}async function o2(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(!e4("type",i.device))return eu("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===i.device.platform&&i.recording&&"failed"===await oJ({session:i}))return eu("COMMAND_FAILED","Android system dialog blocked the recording session");let n=(t.positionals??[]).join(" "),o=o$(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 oL({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 o3(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 o8(e){let{req:t,leaseRegistry:r}=e,a=o3(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 o5(e,t){if(!t)return[];let r=[],a=e.device,i=e7(t.platform);if(i&&!e5(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 o4(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 o9=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"];async function o6(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?o7(await X(t.device,"screenshot",[],i,o)):o7(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 o7(e){if("object"==typeof e&&null!==e)return{..."string"==typeof e.path?{path:e.path}:{},...Array.isArray(e.overlayRefs)?{overlayRefs:e.overlayRefs}:{}}}let se=[255,59,48,255],st=[255,214,10,255],sr=[0,0,0,255],sa={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 si(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)so(r)&&sc(r.rect)&&(!t||sf(r.rect)>sf(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&&sc(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 sc(e.rect)&&!("image"===tf((t=e).type??"")&&!ss(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(sl)||su(e.identifier);return sn(e)?t:t&&function(e){let t=tf(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 sn(e)&&!so(e)}(t)&&sc(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(sn(t)&&!so(t)&&sc(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&sc(r.rect))return r;if(t.hittable&&sc(t.rect)&&!so(t))return t;let a=tn(e,t);return a?.rect&&sc(a.rect)&&!so(a)?a:null}(e.nodes,a);if(!o?.rect||!sc(o.rect))continue;let s=function(e,t,r){let a=sd(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=sd(a);if(!i)continue;let n=function(e){let t=0;return tf(e.type??"").includes("text")&&(t+=2),sl(e.label)&&(t+=2),sl(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(sd(t)??td(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),sn(t)&&(a+=3),sn(e)&&(a+=2),r&&(a+=2),su(t.identifier)&&(a+=1),ss(t.value)&&(a+=1),a}(a,o,s),u=function(e,t,r,a){if(!e)return sh({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 sh({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(!sc(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)=>sf(e.overlayRect)-sf(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(sp(e.overlayRect,r.overlayRect)||sp(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}sf(r.overlayRect)<sf(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:sm(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:sm(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:th(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)sw(e,t.x,t.x+t.width-1,t.y+a,r),sw(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),sy(e,t.x+a,t.y,t.y+t.height-1,r),sy(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,se),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=sg(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:sg(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)sv(e,t+o,r+n,i)})(e,i,o,a,st),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=sa[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]&&sv(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,sr)}(a,i.overlayRect,i.ref)}return await n.writeFile(e.screenshotPath,w.sync.write(t)),r}function sn(e){let t=[e.type,e.role,e.subrole].map(e=>tf(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 so(e){let t=[e.type,e.role,e.subrole].map(e=>tf(e??"")).join(" ");return t.includes("application")||t.includes("window")}function ss(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function sl(e){var t;let r;return!!ss(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function su(e){var t;return"string"==typeof e&&!!sl(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function sd(e){let t=[e.label,e.value].find(sl);return t?t.trim():su(e.identifier)?e.identifier.trim():void 0}function sc(e){return!!(e&&e.width>0&&e.height>0)}function sf(e){return e.width*e.height}function sp(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 sm(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function sh(e,t,r){let a=sg(e.x,0,Math.max(0,t-1)),i=sg(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:sg(e.width,1,n),height:sg(e.height,1,o)}}function sg(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function sw(e,t,r,a,i){for(let n=t;n<=r;n+=1)sv(e,n,a,i)}function sy(e,t,r,a,i){for(let n=r;n<=a;n+=1)sv(e,t,n,i)}function sv(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 sI=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),sS=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),sA=new Set(sS),sb=new Map;function s_(e){if(eT(e.meta?.requestId))throw eo()}function sN(e,t,r,a){let i=M().requestId;return{...eE(e,t,r,a,i),requestId:i}}async function sk(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||ar(e.flags))try{let t=await ep(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function sx(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await o8({req:t,leaseRegistry:n});if(l)return l;let u=await nP({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 oh({req:t,sessionName:r,sessionStore:i,logPath:a});if(c)return c;let f=await nL({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await o1({req:t,sessionName:r,logPath:a,sessionStore:i,contextFromFlags:s});return p||null}async function sD(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(!e4(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 oJ({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]?[tU.expandHome(i[0],t.meta?.cwd),...i.slice(1)]:i,s="screenshot"===a&&n?tU.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={...sN(f,d.flags,c.appBundleId,c.trace?.outPath),surface:c.surface},S="screenshot"===m?await o6({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 sM(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=oy(e.snapshot),n={...a??{}},o=o_(n.direction)??o_(r[0]);if(!o)return a;let s=oN(n.amount)??oN(r[1]),l=oN(n.pixels),u=oD(n,[]),d=oN(n.referenceWidth),c=oN(n.referenceHeight),f=void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:i??oI;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=tr({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);oS(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)&&ta(c,m),{ok:!0,data:S??{}}}async function sM(e,t,r){let a=eR(await eC({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);eh(e,a);let i=await si({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}async function sP(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 sL(e){i.existsSync(e)&&i.unlinkSync(e)}function sR(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 sO(e){let t=sR(e);if(!t||t.pid===process.pid)try{i.existsSync(e)&&i.unlinkSync(e)}catch{}}function sE(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:sC,infoPath:s$,lockPath:sT,logPath:sF,sessionsDir:sU}=x(process.env.AGENT_DEVICE_STATE_DIR),sG=P(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sV=sU;if(i.existsSync(sV))for(let e of i.readdirSync(sV,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=o.join(sV,e.name,tV);if(i.existsSync(t))try{let e=tj(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{tH(t)}}let sj=new tU(sU),sq=new rY({maxActiveSimulatorLeases:sE(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sE(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sE(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sE(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),sH=S(),sB=a.randomBytes(24).toString("hex"),sz=F(process.pid)??void 0,sK=A(),sW=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{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=o3(r);sS.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=sA.has(l)?null:await sk(r,d,a),f=async()=>{s_(r);let e=a.get(d);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=eV(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?o5(t,a):function(e,t,r){var a,i;let n=[],o=e7(t);if(void 0!==e.platform&&o&&(a=e7(e.platform),i=o,a&&i&&a!==i&&("apple"===a?!e6(i):"apple"!==i||!e6(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of o9){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 o9)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(o4).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||sI.has(l)||function(e,t){let r=o5(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(o4).join(", ")}. Use a different --session name or close this session first.`)}}(e,u.flags);let f=await sx({req:u,sessionName:d,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...sN(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 sD({req:u,session:p,sessionName:d,logPath:t,sessionStore:a});return c(m)};if(!c)return s_(r),await f();return s_(r),await eg(sb,c,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:sF,token:sB,sessionStore:sj,leaseRegistry:sq,trackDownloadableArtifact:function(e){let t=a.randomUUID(),r=setTimeout(()=>{rv(t)},9e5);return r.unref(),ry.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});async function sJ(e){await k({command:"daemon",session:"daemon",logPath:sF,debug:!0},async()=>{O({level:"error",phase:"daemon_fatal",data:{error:e instanceof Error?e.message:String(e)}}),D({force:!0})})}async function sZ(){let e=sj.toArray();await Promise.all(e.map(sX))}async function sX(e){let t=a8(e,e.name).catch(t=>{process.stderr.write(`Daemon session teardown error (${e.name}): ${t instanceof Error?t.message:String(t)}
|
|
36
|
+
`.trim();async function nU(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 nG(e){try{var t,r;let a,i=await H("swift",["-",e],{stdin:nF,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 nj(e);return!1}catch(t){if(t instanceof j&&"TOOL_MISSING"===t.code)return nj(e);throw t}}async function nV(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nG(e))return;await B(r)}}function nj(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 nq(e){let t=o.parse(e);return o.join(t.dir,`${t.name}.gesture-telemetry.json`)}function nH(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nB(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 nz(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await nU(t),await nV(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 nV(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 nK(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nz({videoPath:r,scriptPath:t??=nB("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nW(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nz({videoPath:r,scriptPath:e??=nB("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function nJ(e){let{videoPath:t,quality:a,targetLabel:i="recording"}=e;await nz({videoPath:t,scriptPath:r??=nB("recording-resize.swift"),scriptArgs:["--quality",String(a)],commandDescription:`Failed to resize the ${i}`})}function nZ(e){return e instanceof Error?e.message:String(e)}function nX(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function nY(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=nq((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?nH(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)}]})):nH(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: ${nZ(e)}`}}}async function nQ(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 n0(e,t,r){for(let a=0;a<40;a+=1){if(!await nQ(e,t,r))return!0;await B(250)}return!await nQ(e,t,r)}async function n1(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 n2(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 nQ(e,t,a))break;if(i+1>=2)return!0;await B(250)}return!1}async function n3(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=nX(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 n5(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: ${nX(i,"adb shell wm size")}`);return{width:n4(Number(n[1]),a),height:n4(Number(n[2]),a)}}function n4(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function n8(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function n7(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 nQ(e,t,r))&&await n0(e,t,r)}async function n6(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 n5({deps:i,deviceId:n.id,quality:o.quality})}catch(e){return el("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: ${nX(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 n8(i,n.id,e);continue}if(O({level:"debug",phase:"record_start_android_started",data:{deviceId:n.id,remotePath:e,remotePid:a}}),await n2(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 n7(i,n.id,a),await n8(i,n.id,e)}return el("COMMAND_FAILED",s)}async function n9(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 nQ(a,i.id,n.remotePid)&&!await n7(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${nX(o,"adb shell kill")}`):await n0(a,i.id,n.remotePid)||await n7(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await n1(a,i.id,n.remotePath);let e=await n3({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),el("COMMAND_FAILED",e);await nY({recording:n,deps:a,targetLabel:"Android recording"})}if(await s(),t)return el("COMMAND_FAILED",t);if(r)return el("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: ${nX(e,"adb shell rm")}`)}}function oe(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function ot(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function or(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=oe(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},ot(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:nZ(e)}})}}async function oa(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=ot(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(!nZ(a).toLowerCase().includes("recording already in progress"))return el("COMMAND_FAILED",`failed to start recording: ${nZ(a)}`);O({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:nZ(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 el("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 el("COMMAND_FAILED",`failed to start recording: ${nZ(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...d}}async function oi(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},ot(t,i,r))}catch(e){return el("COMMAND_FAILED",`failed to start recording: ${nZ(e)}`)}return{platform:"macos-runner",...s}}async function on(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=oe(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},ot(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:nZ(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of Y)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 el("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 nY({recording:o,deps:n,trimStartMs:u,targetLabel:"iOS recording"}),null}async function oo(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=oe(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},ot(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:nZ(e)}})}return await nY({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function os(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 ol(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:u}=e;await or({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:d,wait:c}=s.runCmdBackground("xcrun",eY(n,["io",n.id,"recordVideo",u]),{allowFailure:!0}),f=await os(u);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:oe(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 ou(e){let t,{req:r,sessionName:a,sessionStore:n,activeSession:s,device:l,logPath:u,deps:d}=e;if(s.recording)return el("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 el("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==f&&(!Number.isInteger(f)||f<5||f>10))return el("INVALID_ARGS","quality must be an integer between 5 and 10");if(!e4("record",l))return el("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=oe(s);if(!e)return el("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await oa({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=oe(s);if(!e)return el("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await oi({req:r,activeSession:s,device:l,logPath:u,deps:d,fpsFlag:c,recordingBase:h,appBundleId:e})}else t="ios"===l.platform?await ol({req:r,activeSession:s,device:l,logPath:u,deps:d,recordingBase:h,resolvedOut:m}):await n6({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 od(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await n9({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return el("COMMAND_FAILED",`failed to stop recording: ${nX(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: ${nZ(e)}`}return await nY({recording:a,deps:t,targetLabel:"iOS recording"}),null}async function oc(e){var t;let r,{req:a,activeSession:i,device:n,logPath:s,deps:l}=e;if(!i.recording)return el("INVALID_ARGS","no active recording");let u=i.recording,d=u.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===u.platform?await on({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):"macos-runner"===u.platform?await oo({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:u}):await od({deps:l,device:n,recording:u});return c||(d?el("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 nq(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 of(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:H,runCmdBackground:q,runIosRunnerCommand:eW,waitForStableFile:nU,isPlayableVideo:nG,trimRecordingStart:nK,resizeRecording:nJ,overlayRecordingTouches:nW},o=a.get(r),s=o?.device??await ef(t.flags??{});o||await eJ(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},u=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(u))return el("INVALID_ARGS","record requires start|stop");if("start"===u)return ou({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let d=await oc({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 op(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,s=t.command;if("record"===s)return of({req:t,sessionName:r,sessionStore:a,logPath:n});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return el("INVALID_ARGS","trace requires start|stop");let n=a.get(r);if(!n)return el("SESSION_NOT_FOUND","No active session");if("start"===e){if(n.trace)return el("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 el("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 om(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 oh=new WeakMap;function og(e){if(!e)return;let t=oh.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)&&ow(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(ow);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 oh.set(e,r),r}function ow(e){return!!e&&e.width>0&&e.height>0}let oy={referenceWidth:1e3,referenceHeight:1e3};function ov(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=ob(p.effectiveDurationMs)??ob(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:ob(p.gestureStartUptimeMs),gestureEndUptimeMs:ob(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:ob(p.gestureStartUptimeMs),gestureEndUptimeMs:ob(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===ob(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=o_(ob(t.count),1)??1,r=!0===t.doubleTap,a=o_(ob(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 om(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):om(h),y=(l=e.snapshot,d=ob((u=p).referenceWidth),c=ob(u.referenceHeight),void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:og(l)),v=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=oN(t,e);if(!i)return[];let{x:n,y:o}=i,s=o_(ob(t.count),1)??1,l=o_(ob(t.intervalMs),0)??0,u=!0===t.doubleTap,d=o_(ob(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(oS(t,n,o,d,a));continue}c.push(oI(t,n,o,a)),u&&c.push(oI(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=oN(t,e);if(!i)return[];let{x:n,y:o}=i;return[oI(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=oN(t,e);if(!n)return[];let{x:o,y:s}=n;return[oS(r,o,s,ox(a,[ob(t.durationMs),ob(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=ok(t,e),o=oA(t.contentDirection)??oA(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:u,y2:d}=n,c=ox(a,[],250),f=ob(t.amount)??ob(e[1]),p=ob(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=ok(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:u}=n,d=ox(a,[ob(t.effectiveDurationMs),ob(t.durationMs),ob(e[4])],250),c=o_(ob(t.count),1)??1,f=o_(ob(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=oN(t,e,1),o=ob(t.scale)??ob(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:ox(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 oI(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function oS(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function oA(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 ob(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 o_(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function oN(e,t,r=0){let a=ob(e.x)??ob(t[r]),i=ob(e.y)??ob(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function ok(e,t){let r=ob(e.x1)??ob(t[0]),a=ob(e.y1)??ob(t[1]),i=ob(e.x2)??ob(t[2]),n=ob(e.y2)??ob(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 ox(e,t,r){return o_(e,1)??t.map(e=>o_(e,1)).find(e=>void 0!==e)??r}function oD(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??{},...R(c)}}function oM(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}),eo(a)&&tr(t,a,d??t.snapshot),ov(t,a,i,o,n??{},l,u),{ok:!0,data:s}}async function oP(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 eb(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=og(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=og(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oR(e){try{return await oP(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 oL(e){return og({nodes:e,createdAt:0})}function oO(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:el("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 oE(e){let t=e.sessionStore.get(e.sessionName);if(!t)throw new j("SESSION_NOT_FOUND","No active session. Run open first.");return eS({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)=>oC(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)=>oC(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)=>oC(await X(r.device,"type",[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),artifacts:ej("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&&(em(t,r.snapshot),e.sessionStore.set(e.sessionName,t))}},policy:ei()})}function oC(e){return e&&"object"==typeof e?e:void 0}function o$(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 oT(e){return"ref"===e.kind?{ref:oF(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 oF(e){return e?.startsWith("@")?e.slice(1):e}async function oU(e){switch(e.req.command){case"press":case"click":return await oG(e);case"fill":return await oV(e);default:return null}}async function oG(e){let t,{req:r,sessionName:a,sessionStore:i}=e,n=i.get(a),o="click"===r.command?"click":"press";if(!n)return el("SESSION_NOT_FOUND","No active session. Run open first.");let s=oO(n,o);if(s)return s;if(!e4("press",n.device))return el("UNSUPPORTED_OPERATION","press is not supported on this device");let l=eM(r.flags),u=ee(l);if("primary"!==l){let e=ed({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 el(e.code,e.message,e.details)}let d=function(e,t){let r=o$(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:el("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 oq(e,n)}return await oj(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 eg(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 oR({session:n,flags:r.flags,sessionStore:i,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:e.captureSnapshotForSession}):oL(n.snapshot?.nodes??[]),o=oD({data:t.backendResult,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:a,extra:{...oT(t),...u}});return{result:o,responseData:o}}})}async function oV(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(i){let e=oO(i,"fill");if(e)return e}if(i&&!e4("fill",i.device))return el("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!i)return el("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:el("INVALID_ARGS","fill requires text after ref")}}let r=o$(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:el("INVALID_ARGS","fill requires text after coordinates")}}let a=tn(e,{preferTrailingValue:!0});if(!a)return{ok:!1,response:el("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:el("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 oq(e,i)}return await oj(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:oL(i.snapshot?.nodes??[]),r=oD({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...oT(e),text:n.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:oF(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 oj(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return el("SESSION_NOT_FOUND","No active session. Run open first.");let a=oE(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 oM({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(eq(e))throw e;return{ok:!1,error:V(t)}}}async function oq(e,t){if(!eQ(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 oH(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 ex({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??"",androidFreshnessMode:i.androidFreshnessMode});return em(e,s),r.set(e.name,e),s}let oB=/\bis(?:n't| not)\s+responding\b/i,oz=/^close app$/i;async function oK(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oW(t),r=function(e){if(oY(e))return e.find(e=>{let t=oX(e);return t.length>0&&oz.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=tg(r.rect),n=await H("adb",eT(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 oJ(t))return O({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eL(t.device,t.appBundleId),!await oZ(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 oW(e){return th(tm((await ec(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function oJ(e){for(let t=0;t<12;t+=1){if(!oY(await oW(e)))return!0;await B(500)}return!oY(await oW(e))}async function oZ(e,t){for(let r=0;r<12;r+=1){if((await eA(e.device)).package===t)return!0;await B(500)}return(await eA(e.device)).package===t}function oX(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 oY(e){return e.some(e=>{let t=oX(e);return t.length>0&&oB.test(t)})}async function oQ(e){let t=await oU({...e,captureSnapshotForSession:oH,refSnapshotFlagGuardResponse:Q});if(t)return t;switch(e.req.command){case"type":return await o0({...e,captureSnapshotForSession:oH});case"get":return await ep(e);case"is":return await eD(e);default:return null}}async function o0(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return el("SESSION_NOT_FOUND","No active session. Run open first.");if(!e4("type",i.device))return el("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===i.device.platform&&i.recording&&"failed"===await oK({session:i}))return el("COMMAND_FAILED","Android system dialog blocked the recording session");let n=(t.positionals??[]).join(" "),o=oE(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,...R(e.message??`Typed ${Array.from(e.text).length} chars`)};return oM({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 o1(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 o2(e){let{req:t,leaseRegistry:r}=e,a=o1(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 o3(e,t){if(!t)return[];let r=[],a=e.device,i=e6(t.platform);if(i&&!e5(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 o5(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 o4=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"];async function o8(e){let{session:t,sessionName:r,outPath:a,outputPlacement:i,dispatchContext:s}=e,l=eS({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?o7(await X(t.device,"screenshot",[],i,o)):o7(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:ei()});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 o7(e){if("object"==typeof e&&null!==e)return{..."string"==typeof e.path?{path:e.path}:{},...Array.isArray(e.overlayRefs)?{overlayRefs:e.overlayRefs}:{}}}let o6=[255,59,48,255],o9=[255,214,10,255],se=[0,0,0,255],st={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 sr(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)si(r)&&su(r.rect)&&(!t||sd(r.rect)>sd(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&&su(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 su(e.rect)&&!("image"===tp((t=e).type??"")&&!sn(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(so)||ss(e.identifier);return sa(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 sa(e)&&!si(e)}(t)&&su(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(sa(t)&&!si(t)&&su(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&su(r.rect))return r;if(t.hittable&&su(t.rect)&&!si(t))return t;let a=to(e,t);return a?.rect&&su(a.rect)&&!si(a)?a:null}(e.nodes,a);if(!o?.rect||!su(o.rect))continue;let s=function(e,t,r){let a=sl(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=sl(a);if(!i)continue;let n=function(e){let t=0;return tp(e.type??"").includes("text")&&(t+=2),so(e.label)&&(t+=2),so(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(sl(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),sa(t)&&(a+=3),sa(e)&&(a+=2),r&&(a+=2),ss(t.identifier)&&(a+=1),sn(t.value)&&(a+=1),a}(a,o,s),u=function(e,t,r,a){if(!e)return sp({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 sp({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(!su(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)=>sd(e.overlayRect)-sd(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(sc(e.overlayRect,r.overlayRect)||sc(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}sd(r.overlayRect)<sd(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:sf(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:sf(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)sh(e,t.x,t.x+t.width-1,t.y+a,r),sh(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),sg(e,t.x+a,t.y,t.y+t.height-1,r),sg(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,o6),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=sm(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:sm(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)sw(e,t+o,r+n,i)})(e,i,o,a,o9),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=st[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]&&sw(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,se)}(a,i.overlayRect,i.ref)}return await n.writeFile(e.screenshotPath,w.sync.write(t)),r}function sa(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 si(e){let t=[e.type,e.role,e.subrole].map(e=>tp(e??"")).join(" ");return t.includes("application")||t.includes("window")}function sn(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function so(e){var t;let r;return!!sn(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function ss(e){var t;return"string"==typeof e&&!!so(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function sl(e){let t=[e.label,e.value].find(so);return t?t.trim():ss(e.identifier)?e.identifier.trim():void 0}function su(e){return!!(e&&e.width>0&&e.height>0)}function sd(e){return e.width*e.height}function sc(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 sf(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function sp(e,t,r){let a=sm(e.x,0,Math.max(0,t-1)),i=sm(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:sm(e.width,1,n),height:sm(e.height,1,o)}}function sm(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function sh(e,t,r,a,i){for(let n=t;n<=r;n+=1)sw(e,n,a,i)}function sg(e,t,r,a,i){for(let n=r;n<=a;n+=1)sw(e,t,n,i)}function sw(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 sy=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),sv=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),sI=new Set(sv),sS=new Map;function sA(e){if(e$(e.meta?.requestId))throw en()}function sb(e,t,r,a){let i=M().requestId;return{...eO(e,t,r,a,i),requestId:i}}async function s_(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 ef(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function sN(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await o2({req:t,leaseRegistry:n});if(l)return l;let u=await nD({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(u)return u;let d=await et({req:t,sessionName:r,logPath:a,sessionStore:i});if(d)return d;let c=await op({req:t,sessionName:r,sessionStore:i,logPath:a});if(c)return c;let f=await nM({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await oQ({req:t,sessionName:r,logPath:a,sessionStore:i,contextFromFlags:s});return p||null}async function sk(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(!e4(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 oK({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={...sb(f,d.flags,c.appBundleId,c.trace?.outPath),surface:c.surface},S="screenshot"===m?await o8({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 sx(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=og(e.snapshot),n={...a??{}},o=oA(n.direction)??oA(r[0]);if(!o)return a;let s=ob(n.amount)??ob(r[1]),l=ob(n.pixels),u=ok(n,[]),d=ob(n.referenceWidth),c=ob(n.referenceHeight),f=void 0!==d&&d>0&&void 0!==c&&c>0?{referenceWidth:d,referenceHeight:c}:i??oy;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=tt({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);ov(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??{}}),eo(m)&&tr(c,m),{ok:!0,data:S??{}}}async function sx(e,t,r){let a=eR(await eE({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);em(e,a);let i=await sr({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}async function sD(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 sM(e){i.existsSync(e)&&i.unlinkSync(e)}function sP(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 sR(e){let t=sP(e);if(!t||t.pid===process.pid)try{i.existsSync(e)&&i.unlinkSync(e)}catch{}}function sL(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:sO,infoPath:sE,lockPath:sC,logPath:s$,sessionsDir:sT}=x(process.env.AGENT_DEVICE_STATE_DIR),sF=P(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sU=sT;if(i.existsSync(sU))for(let e of i.readdirSync(sU,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=o.join(sU,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 sG=new tG(sT),sV=new rQ({maxActiveSimulatorLeases:sL(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sL(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sL(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sL(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),sj=S(),sq=a.randomBytes(24).toString("hex"),sH=F(process.pid)??void 0,sB=A(),sz=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 eN(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=o1(r);sv.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=sI.has(l)?null:await s_(r,d,a),f=async()=>{sA(r);let e=a.get(d);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=eG(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?o3(t,a):function(e,t,r){var a,i;let n=[],o=e6(t);if(void 0!==e.platform&&o&&(a=e6(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 o4){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 o4)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(o5).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||sy.has(l)||function(e,t){let r=o3(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(o5).join(", ")}. Use a different --session name or close this session first.`)}}(e,u.flags);let f=await sN({req:u,sessionName:d,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...sb(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 sk({req:u,session:p,sessionName:d,logPath:t,sessionStore:a});return c(m)};return c?(sA(r),await eh(sS,c,f)):(sA(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:s$,token:sq,sessionStore:sG,leaseRegistry:sV,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 sK(e){await k({command:"daemon",session:"daemon",logPath:s$,debug:!0},async()=>{O({level:"error",phase:"daemon_fatal",data:{error:e instanceof Error?e.message:String(e)}}),D({force:!0})})}async function sW(){let e=sG.toArray();await Promise.all(e.map(sJ))}async function sJ(e){let t=a4(e,e.name).catch(t=>{process.stderr.write(`Daemon session teardown error (${e.name}): ${t instanceof Error?t.message:String(t)}
|
|
38
38
|
`)});await Promise.race([t,B(5e3).then(()=>{process.stderr.write(`Daemon session teardown timed out (${e.name}).
|
|
39
|
-
`)})]),
|
|
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"!==
|
|
39
|
+
`)})]),sG.writeSessionLog(e),sG.delete(e.name)}async function sZ(){let e,t,r=[];if("http"!==sF){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))eB(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 eU(),!(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=eC(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},i.add(o),es(o),e$(o))throw en();t=await sz(e)}catch(e){t={ok:!1,error:V(e)}}finally{a-=1,o&&(i.delete(o),eX(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"!==sF){let e=await rz({handleRequest:sz,token:sq});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=sP(t);if(o?.pid&&o.pid!==process.pid&&T(o.pid,o.processStartTime))return!1;try{i.unlinkSync(t)}catch{}return n()}(sO,sC,{pid:process.pid,version:sj,startedAt:Date.now(),processStartTime:sH})){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 sZ();e=o.servers,t=o.socketPort,r=o.httpPort,a={socketPort:t,httpPort:r,token:sq,version:sj,codeSignature:sB,processStartTime:sH},i.existsSync(sO)||i.mkdirSync(sO,{recursive:!0}),i.writeFileSync(s$,""),n=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",i.writeFileSync(sE,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:sO},null,2),{mode:384}),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${t}
|
|
41
41
|
`),r&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${r}
|
|
42
42
|
`)}catch(r){let t=G(r);for(let r of(process.stderr.write(`Daemon error: ${t.message}
|
|
43
|
-
`),e))try{r.close(()=>{})}catch{}
|
|
43
|
+
`),e))try{r.close(()=>{})}catch{}sM(sE),sR(sC),process.exit(1);return}let n=!1,o=async(t={})=>{n||(n=!0,t.cause&&await sK(t.cause),await sD(e),await sW(),await ev(),sM(sE),sR(sC),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
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
45
|
`),o({exitCode:1,cause:t})})}();
|