agent-device 0.13.2 → 0.13.3
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/bin/agent-device.mjs +6 -2
- package/dist/src/113.js +1 -1
- package/dist/src/1974.js +2 -2
- package/dist/src/2301.js +1 -1
- package/dist/src/3918.js +29 -29
- package/dist/src/7847.js +1 -1
- package/dist/src/8161.js +3 -0
- package/dist/src/8656.js +1 -1
- package/dist/src/940.js +1 -0
- package/dist/src/9542.js +2 -2
- package/dist/src/index.d.ts +170 -1927
- package/dist/src/index.js +1 -1
- package/dist/src/{bin.js → internal/bin.js} +31 -31
- package/dist/src/internal/companion-tunnel.js +1 -0
- package/dist/src/internal/daemon.js +43 -0
- package/dist/src/internal/update-check-entry.js +1 -0
- package/dist/src/metro.d.ts +5 -3
- package/dist/src/selectors.js +1 -1
- package/package.json +1 -17
- package/dist/src/4993.js +0 -1
- package/dist/src/5721.js +0 -1
- package/dist/src/7166.js +0 -1
- package/dist/src/8564.js +0 -3
- package/dist/src/9076.js +0 -1
- package/dist/src/backend.d.ts +0 -527
- package/dist/src/backend.js +0 -1
- package/dist/src/commands/index.d.ts +0 -1883
- package/dist/src/commands/index.js +0 -1
- package/dist/src/daemon.js +0 -43
- package/dist/src/metro-companion.js +0 -1
- package/dist/src/observability.d.ts +0 -91
- package/dist/src/observability.js +0 -1
- package/dist/src/testing/conformance.d.ts +0 -753
- package/dist/src/testing/conformance.js +0 -1
- package/dist/src/update-check-entry.js +0 -1
- /package/dist/src/{bin.d.ts → internal/bin.d.ts} +0 -0
- /package/dist/src/{daemon.d.ts → internal/companion-tunnel.d.ts} +0 -0
- /package/dist/src/{metro-companion.d.ts → internal/daemon.d.ts} +0 -0
- /package/dist/src/{update-check-entry.d.ts → internal/update-check-entry.d.ts} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export{bindCommands,commandCatalog,commands,createCommandRouter,ref,selector}from"../9076.js";
|
package/dist/src/daemon.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
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 d,pathToFileURL as c}from"node:url";import"node:https";import u from"node:os";import f from"node:fs/promises";import{setTimeout as p}from"node:timers/promises";import{PNG as m}from"pngjs";import h from"node:net";import{resolveUserPath as g}from"./3267.js";import{localCommandPolicy as w,createAgentDevice as v,readVersion as y,resolveDaemonCodeSignature as I,normalizeTenantId as S,resolveSessionIsolationMode as A,withDiagnosticsScope as _,resolveDaemonPaths as b,flushDiagnosticsToSessionFile as N,getDiagnosticsMeta as k,resolveDaemonServerMode as D,resolveDeployResultTarget as x,resolveInstallFromSourceResultTarget as M,emitDiagnostic as P}from"./8564.js";import{trimRuntimeValue as R,readProcessCommand as L,resolveRuntimeTransportHints as O,isAgentDeviceDaemonProcess as E,readProcessStartTime as C}from"./8656.js";import{toAppErrorCode as $,asAppError as T,normalizeError as F,AppError as U}from"./9152.js";import{runCmdBackground as G,runCmd as V}from"./9818.js";import{sleep as j,resolveTimeoutMs as q}from"./4829.js";import{resolveAndroidSerialAllowlist as H,IOS_RUNNER_CONTAINER_BUNDLE_IDS as B,resolveAppleSimulatorSetPathForSelector as K,buildSimctlArgs as z,dispatchCommand as W,validateAndNormalizeBatchSteps as J,refSnapshotFlagGuardResponse as Z,buttonTag as X,handleSnapshotCommands as Y,shutdownSimulator as Q,stopIosRunnerSession as ee,createRequestCanceledError as et,isNavigationSensitiveAction as er,registerRequestAbort as ea,resolveIosDevicectlHint as ei,getClickButtonValidationError as en,snapshotAndroid as eo,resolveTargetDevice as es,dispatchGetViaRuntime as el,withKeyedLock as ed,assertAndroidPressStayedInApp as ec,stopAllIosRunnerSessions as eu,parseSerialAllowlist as ef,classifyAndroidAppTarget as ep,DEFAULT_BATCH_MAX_STEPS as em,runMacOsAlertAction as eh,getAndroidAppState as eg,getAndroidScreenSize as ew,isDeepLinkTarget as ev,readTextForNode as ey,captureSnapshot as eI,dispatchIsViaRuntime as eS,resolveClickButton as eA,IOS_DEVICECTL_DEFAULT_HINT as e_,buildSnapshotState as eb,openAndroidApp as eN,context_contextFromFlags as ek,captureSnapshotData as eD,resolveRequestTrackingId as ex,isRequestCanceled as eM,adbArgs as eP,resolvePayloadInput as eR,abortAllIosRunnerSessions as eL,getRunnerSessionSnapshot as eO,formatAndroidInstalledPackageRequiredMessage as eE,createUnsupportedArtifactAdapter as eC,isAndroidEscapeError as e$,resolveIosSimulatorDeviceSetPath as eT,markRequestCanceled as eF,dispatchFindReadOnlyViaRuntime as eU,parseCoordinateTarget as eG,resolveIosDeviceDeepLinkBundleId as eV,response_errorResponse as ej,runIosRunnerCommand as eq,ensureDeviceReady as eH,readInfoPlistString as eB,clearRequestCanceled as eK,buildSimctlArgsForDevice as ez,getActiveAndroidSnapshotFreshness as eW,parseXmlDocumentSync as eJ,resolveFrontmostMacOsApp as eZ,IOS_SIMCTL_LIST_TIMEOUT_MS as eX,listIosDeviceApps as eY,matchesPlatformSelector as eQ,isCommandSupportedOnDevice as e0,listIosDeviceProcesses as e1,isApplePlatform as e2,normalizePlatformSelector as e3,getRequestSignal as e8,parseSessionSurface as e5,buildScrollGesturePlan as e4,markAndroidSnapshotFreshness as e9}from"./3918.js";import{mergeNetworkDumps as e6,readRecentNetworkTrafficFromText as e7,readRecentNetworkTraffic as te}from"./5721.js";import{withSuccessText as tt,decodePng as tr,successText as ta}from"./9076.js";import{splitSelectorFromArgs as ti,findNearestHittableAncestor as tn,extractNodeText as to,splitIsSelectorArgs as ts,tryParseSelectorChain as tl,resolveSelectorChain as td,resolveRefLabel as tc,buildSelectorChainForNode as tu,normalizeType as tf,pruneGroupNodes as tp}from"./7847.js";import{attachRefs as tm,centerOfRect as th}from"./4057.js";import{findBestMatchesByLocator as tg,parseFindArgs as tw}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 ty(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"]]),t_=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tb=new Map([["--delay-ms","delayMs"]]);function tN(e){return"click"===e||"press"===e}function tk(e){return"type"===e||"fill"===e}function tD(e){return tM(e,tP)}function tx(e){return JSON.stringify(e)}function tM(e,t){return t(e)?e:tx(e)}function tP(e){return tR(e)&&e.startsWith("@")||tI.test(e)}function tR(e){return tS.test(e)}function tL(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,tR)),"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,tR)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tM(t.launchUrl,tR)))}function tE(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tM(r,tR)),a))e.push(tD(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),"number"==typeof t.flags?.quality&&e.push("--quality",String(t.flags.quality)),t.flags?.hideTouches&&e.push("--hide-touches")}function tC(e,t){let r=[],a={},i=tN(e)?tA:"swipe"===e?t_:tk(e)?tb: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(tD(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}),P({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=o.dirname(t);i.existsSync(r)||i.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.kind?` kind=${e.device.kind}`:"";for(let i of(r.push(`context platform=${e.device.platform} device=${tx(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(tD(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tD(a)),tL(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tD(r)),tL(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)),tL(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 tF(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tM(r,tR)),tO(t,e.flags),t.join(" ")}if("record"===e.command)return tE(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tD(r));return tL(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
2
|
-
`}(e,this.buildOptimizedActions(e));i.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=tU.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,tU.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return o.join(this.sessionsDir,tU.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return g(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return tU.expandHome(e.saveScriptPath);i.existsSync(this.sessionsDir)||i.mkdirSync(this.sessionsDir,{recursive:!0});let t=tU.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&&(tN(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tN(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(tN(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 tG=["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"],tV="app-log.pid";function tj(e){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t))return{pid:Number.parseInt(t,10)};try{let e=JSON.parse(t);if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}function tq(e,t){if(!e)return;let r=o.dirname(e);i.existsSync(r)||i.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:C(t)??void 0,command:L(t)??void 0};i.writeFileSync(e,`${JSON.stringify(a)}
|
|
3
|
-
`)}function tH(e){if(e&&i.existsSync(e))try{i.unlinkSync(e)}catch{}}async function tB(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 tz(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 tW(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new U("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function tJ(e,t){let r=(await V("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function tZ(e,t){var r,a;let i;tW(t);let n=await tJ(e,t),o=await V("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 tX(e,t,r,a,i){let n,o,l="recovering",d=!1,c=(async()=>{try{for(;!d;){let c=await tJ(e,t);if(!c){l="recovering",await j(1e3);continue}let u=s("adb",["-s",e,"logcat","-v","time","--pid",c],{stdio:["ignore","pipe","pipe"]});n=u;let f=tK(r,{redactionPatterns:a});if(o=tz(u,r,{endStreamOnClose:!1,writer:f}),"number"==typeof u.pid&&(tq(i,u.pid),l="active"),await o,tH(i),n=void 0,o=void 0,d)break;l="recovering",await j(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tH(i)}})();return{backend:"android",getState:()=>l,startedAt:Date.now(),wait:c,stop:async()=>{d=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await tB(o),n&&!n.killed&&n.kill("SIGKILL"),await tB(c),tH(i)}}}function tY(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}"`}async function tQ(e){let{deviceId:t,appBundleId:r,startedAt:a,simulatorSetPath:i}=e,n=z(["spawn",t,"log","show","--style","compact","--info","--predicate",tY(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 V("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 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"]}),d=tK(r,{redactionPatterns:a});"number"==typeof l.pid&&tq(n,l.pid);let c=tz(l,r,{endStreamOnClose:!0,writer:d}).then(e=>(0!==e.exitCode&&(o="failed"),tH(n),e));return{backend:"ios-simulator",getState:()=>o,startedAt:Date.now(),wait:c,stop:async()=>{l.killed||l.kill("SIGINT"),await tB(c),l.killed||l.kill("SIGKILL"),await tB(c),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=tK(t,{redactionPatterns:r});"number"==typeof n.pid&&tq(a,n.pid);let l=tz(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=tK(t,{redactionPatterns:r});"number"==typeof n.pid&&tq(a,n.pid);let l=tz(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)}}}function t3(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 t8(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:t3("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:t3("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function t5(e){var t,r,a;let{device:i,appBundleId:n,appLogState:o,appLogStartedAt:s,appLogPath:l,maxEntries:d,include:c,maxPayloadChars:u,maxScanLines:f}=e,p="macos"===i.platform?"macos":"ios"===i.platform?"device"===i.kind?"ios-device":"ios-simulator":"android",m=te(l,{backend:p,maxEntries:d,include:c,maxPayloadChars:u,maxScanLines:f}),h=[],g=await t4({device:i,appBundleId:n,appLogPath:l,appLogState:o});if(g){let e=await tZ(i.id,n);if(e){let a=e7(e.text,{path:`${l} (adb logcat recovery)`,backend:"android",maxEntries:d,include:c,maxPayloadChars:u,maxScanLines:f});a.entries.length>0&&(m=e6(a,m,d),h.push((t=g,r=e.recoveredPids,"stale-active"===t.reason?`Session app log stream was still bound to prior Android PID ${t.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${r.join(", ")}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${r.join(", ")}.`)))}}if("ios"===i.platform&&"simulator"===i.kind&&n&&0===m.entries.length){let e=await t6({deviceId:i.id,appBundleId:n,startedAt:s,simulatorSetPath:i.simulatorSetPath,appLogPath:l,maxEntries:d,include:c,maxPayloadChars:u,maxScanLines:f});e&&(e.dump.entries.length>0?(m=e6(e.dump,m,d),h.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&&h.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===o?h.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==o&&0===h.length&&("ios"===i.platform&&"simulator"===i.kind?h.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."):h.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===m.entries.length&&h.push("ios"===(a=i).platform&&"simulator"===a.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===a.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:p,dump:m,notes:h}}async function t4(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 t9(e,t,r,a){t8(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 U("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function t6(e){let t=await tQ({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:e7(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 t7(e){await e.stop(),await tB(e.wait)}async function re(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await V("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await V("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await V("xcrun",["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await V("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await V("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function rt(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 rr=new Map;function ra(e){let t=rr.get(e);if(t&&(clearTimeout(t.timer),rr.delete(e),t.deleteAfterDownload))try{i.rmSync(t.artifactPath,{force:!0})}catch{}}let ri=new Map;function rn(e,t){let r=ri.get(e);if(!r)throw new U("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new U("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function ro(e){let t=ri.get(e);t&&(clearTimeout(t.timer),ri.delete(e),i.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rs(e){let t=await rl(e);await V("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=o.join(e.tempDir,t);if(!i.existsSync(r))throw new U("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rl(e){let t=await V("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new U("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new U("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rd),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new U("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new U("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===a.length)return a[0];throw new U("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===i||e.startsWith(`${i}/`)))throw new U("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,o=i;if(n!==o&&!n.startsWith(`${o}/`))throw new U("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await V("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new U("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rd(e){if(e.includes("\0"))throw new U("INVALID_ARGS",`Invalid archive entry: ${e}`);if(o.posix.isAbsolute(e))throw new U("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=o.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new U("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rc=q(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function ru(e,t){return new Promise((r,a)=>{let n,o=i.createWriteStream(t),s=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,c=e=>{if(!l){if(l=!0,n&&clearTimeout(n),e){o.destroy(),i.rmSync(t,{force:!0}),a(e);return}r()}},u=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let e=new U("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rc});s(e),o.destroy(e),c(e)},rc)};e.on("data",e=>{u();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new U("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");s(e),o.destroy(e),c(e)}}),e.on("error",c),e.on("aborted",()=>{c(new U("COMMAND_FAILED","Artifact transfer was interrupted"))}),o.on("error",c),o.on("finish",()=>c()),u(),e.pipe(o)})}async function rf(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new U("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new U("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new U("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let n=function(e){let t=e.trim(),r=o.basename(t);if(!r||"."===r||".."===r)throw new U("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),s=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),i.mkdtempSync(o.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=o.join(s,n);return await ru(e,t),{artifactPath:t,tempDir:s}}let t=o.join(s,"artifact.tar");await ru(e,t);let a=await rs({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"]),rm=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rh=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rg={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},rw=new Set([...rp,...rm,...rh,...Object.keys(rg)]);function rv(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function ry(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rI(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rS(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 rA(e,t){let r=e[t];return"string"==typeof r?r:void 0}function r_(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}function rb(e,t){let r="string"==typeof e[t]?e[t].trim():"";if(!r)throw new U("INVALID_ARGS",`Invalid params: source.${t} is required for github-actions-artifact sources`);return r}function rN(e,t){let r=e[t],a="number"==typeof r?r:"string"==typeof r?Number(r):NaN;if(!Number.isInteger(a))throw new U("INVALID_ARGS",`Invalid params: source.${t} must be an integer`);return a}async function rk(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=F(new U("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:rv(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=F(new U($(r.code,"UNAUTHORIZED"),r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:rv(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=S(r.tenantId);if(!e){let e=F(new U("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:rv(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rD(){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(c(a).href)}catch(e){throw new U("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let i=e[r];if("function"!=typeof i)throw new U("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rx(e){let t=await rD(),{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 rM(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/artifacts/"))return void rP(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||ry(i,rv(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{ry(i,rv(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void ry(i,rv(a.id??null,-32600,"Invalid Request"),400);if(!rw.has(a.method))return void ry(i,rv(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void ry(i,rv(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:rS(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(rm.has(e)){let e,a=rA(t,"platform");if("ios"!==a&&"android"!==a)throw new U("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rS(t,r),session:rA(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rA(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new U("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new U("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,a={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new U("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new U("INVALID_ARGS","Invalid params: source.headers values must be strings");a[e]=t}}return Object.keys(a).length>0?{kind:"url",url:e,headers:a}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new U("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}if("github-actions-artifact"===t.kind)return function(e){let t,r=rb(e,"owner"),a=rb(e,"repo"),i=void 0!==e.artifactId,n=void 0!==e.runId,o=void 0!==e.artifactName;if(i&&(n||o))throw new U("INVALID_ARGS","Invalid params: source must specify either artifactId or artifactName, not both");if(!i&&n&&!o)throw new U("INVALID_ARGS","Invalid params: source.artifactName is required when source.runId is specified");if(!i&&!o)throw new U("INVALID_ARGS","Invalid params: source must specify artifactId or artifactName");return i?{kind:"github-actions-artifact",owner:r,repo:a,artifactId:rN(e,"artifactId")}:(n&&(t=rN(e,"runId")),{kind:"github-actions-artifact",owner:r,repo:a,...n?{runId:t}:{},artifactName:rb(e,"artifactName")})}(t);throw new U("INVALID_ARGS",'Invalid params: source.kind must be "url", "path", or "github-actions-artifact"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:r_(t,"retentionMs")}}}if(rh.has(e)){let e=rA(t,"materializationId")?.trim();if(!e)throw new U("INVALID_ARGS","Invalid params: materializationId is required");return{token:rS(t,r),session:rA(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rA(t,"requestId"),materializationId:e}}}let a=rg[e];if(a)return{token:rS(t,r),session:rA(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rA(t,"tenantId")??rA(t,"tenant"),runId:rA(t,"runId"),leaseId:rA(t,"leaseId"),leaseTtlMs:r_(t,"ttlMs"),leaseBackend:rA(t,"backend")}};throw new U("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 ry(i,rv(a.id??null,-32602,"Invalid params: command is required"),400);o=ex(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},ea(o);let d=()=>{i.writableFinished||eF(o)};e.on("aborted",d),i.on("close",d);let c=await rk(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!c.ok)return void ry(i,c.response,c.statusCode);c.tenantId&&(l.meta={...l.meta,tenantId:c.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let u=await r(l);if(u.ok)return void ry(i,{jsonrpc:"2.0",id:a.id??null,result:u});ry(i,rv(a.id??null,-32e3,u.error.message,u.error),rI(u.error.code))}catch(t){let e=F(t);ry(i,rv(a.id??null,-32e3,e.message,e),rI(e.code))}finally{eK(o)}})})}async function rM(e,t,r,i){try{var n;let o,s,l=rS({},e.headers),d=rR(l,i);if(d){t.statusCode=rI(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let c=await rk(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!c.ok){t.statusCode=c.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:c.response.error?.data?.message??c.response.error?.message??"Unauthorized"}));return}let u=await rf(e),f=(n={artifactPath:u.artifactPath,tempDir:u.tempDir,tenantId:c.tenantId},o=a.randomUUID(),(s=setTimeout(()=>{ro(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=F(r);t.statusCode=rI(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rP(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=rS({},e.headers),s=rR(o,a);if(s){t.statusCode=rI(s.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.message,code:s.code}));return}let l=await rk(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 d=function(e,t){let r=rr.get(e);if(!r)throw new U("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new U("UNAUTHORIZED","Artifact belongs to a different tenant");if(!i.existsSync(r.artifactPath))throw ra(e),new U("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),c=i.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),c.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=F(e);t.statusCode=rI(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&ra(n)}),c.pipe(t)}catch(r){let e=F(r);t.statusCode=rI(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rR(e,t){return t&&e!==t?F(new U("UNAUTHORIZED","Invalid token")):null}function rL(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rO(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rE(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";if("ios-instance"===t||"android-instance"===t)return t;throw new U("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rC{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=rE(e.backend),r=S(e.tenantId);if(!r)throw new U("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=rL(e.runId);if(!i)throw new U("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(r,i,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,n);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),d={leaseId:a.randomBytes(16).toString("hex"),tenantId:r,runId:i,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+n};return this.leases.set(d.leaseId,d),this.runBindings.set(o,d.leaseId),{...d}}heartbeatLease(e){let t=rO(e.leaseId);if(!t)throw new U("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new U("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=rO(e.leaseId);if(!t)throw new U("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=rE(e.backend),r=S(e.tenantId);if(!r)throw new U("INVALID_ARGS","tenant isolation requires tenant id.");let a=rL(e.runId);if(!a)throw new U("INVALID_ARGS","tenant isolation requires run id.");let i=rO(e.leaseId);if(!i)throw new U("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new U("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new U("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}cleanupExpiredLeases(){let e=this.now();for(let t of this.leases.values())t.expiresAt>e||(this.leases.delete(t.leaseId),this.runBindings.delete(this.bindingKey(t.tenantId,t.runId,t.backend)))}enforceCapacity(e){if("ios-simulator"!==e||this.maxActiveSimulatorLeases<=0)return;let t=Array.from(this.leases.values()).filter(e=>"ios-simulator"===e.backend).length;if(!(t<this.maxActiveSimulatorLeases))throw new U("COMMAND_FAILED","No simulator lease capacity available",{reason:"LEASE_CAPACITY_EXCEEDED",activeLeases:t,maxActiveLeases:this.maxActiveSimulatorLeases,backend:e,hint:"Retry after releasing another simulator lease."})}resolveLeaseTtlMs(e){if(!Number.isInteger(e))return this.defaultLeaseTtlMs;let t=Number(e);if(t<this.minLeaseTtlMs||t>this.maxLeaseTtlMs)throw new U("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),a={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(a.leaseId,a),this.runBindings.set(this.bindingKey(a.tenantId,a.runId,a.backend),a.leaseId),{...a}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let a=S(t),i=rL(r);if(t&&!a)throw new U("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new U("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||i&&e.runId!==i)throw new U("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let r$=q(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),rT=new Map;async function rF(e){let t=await f.mkdtemp(o.join(u.tmpdir(),"agent-device-materialized-"));try{let r=await rV(e.installablePath,o.join(t,"installable")),i=e.archivePath?await rV(e.archivePath,o.join(t,"archive")):void 0,n=a.randomUUID(),s=e.ttlMs??r$,l=Date.now()+s,d=setTimeout(()=>{rU(n)},s);return rT.set(n,{rootPath:t,installablePath:r,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:l,timer:d}),{materializationId:n,installablePath:r,...i?{archivePath:i}:{},expiresAt:new Date(l).toISOString()}}catch(e){throw await f.rm(t,{recursive:!0,force:!0}),e}}async function rU(e,t){let r=rT.get(e);if(!r)throw new U("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new U("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),rT.delete(e),await f.rm(r.rootPath,{recursive:!0,force:!0})}async function rG(e){let t=Array.from(rT.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await rU(e)}))}async function rV(e,t){let r=await f.stat(e);await f.mkdir(t,{recursive:!0});let a=o.join(t,o.basename(e));return r.isDirectory()?await f.cp(e,a,{recursive:!0}):await f.copyFile(e,a),a}async function rj(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new U("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await eH(e.session.device),e.session.device}if(!r)throw new U("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await es(e.flags??{});return await eH(a),a}async function rq(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);try{let e,n,o,s=(n=function(e){let t=e.meta?.installSource;if(!t)throw new U("INVALID_ARGS","install_from_source requires a source payload");switch(t.kind){case"url":if(!t.url||0===t.url.trim().length)throw new U("INVALID_ARGS","install_from_source url source requires a non-empty url");return t;case"path":if(!t.path||0===t.path.trim().length)throw new U("INVALID_ARGS","install_from_source path source requires a non-empty path");return t;case"github-actions-artifact":throw new U("UNSUPPORTED_OPERATION","install_from_source github-actions-artifact sources require a compatible remote daemon");default:throw new U("UNSUPPORTED_OPERATION",`install_from_source ${String(t.kind)} sources require a compatible remote daemon`)}}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:rn(o,t.meta?.tenantId)},cleanup:()=>{ro(o)}}:{source:n,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new U("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await rj({session:i,flags:t.flags});if(!e0("install",d))return ej("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let c=e8(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await import("./3918.js"),{prepareIosInstallArtifact:o}=await import("./3918.js"),u=await o(s.source,{signal:c});try{if(l.enabled&&(e=await rF({archivePath:u.archivePath,installablePath:u.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(d,u.installablePath),!u.bundleId)throw new U("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:u.bundleId,...u.appName?{appName:u.appName}:{},launchTarget:u.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=tt(o,rH(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await rU(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await u.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:u}=await import("./3918.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("./3918.js"),p=await u(s.source,{signal:c});try{l.enabled&&(e=await rF({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await f(d,p.installablePath,p.packageName);if(!n)throw new U("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await import("./3918.js"),s=o(n),c={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},u=tt(c,rH(c));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:u}),{ok:!0,data:u}}catch(r){throw e&&await rU(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:F(e)}}}function rH(e){return`Installed: ${M(e)}`}async function rB(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new U("INVALID_ARGS","release_materialized_paths requires a materializationId");return await rU(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:F(e)}}}let rK=q(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),rz=q(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function rW(e,t,r){return t||rJ(r)?null:ej("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function rJ(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function rZ(e){return"ios"===e.platform&&"simulator"===e.kind}async function rX(e,t){rZ(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function rY(e){let t=rJ(e.flags)||!e.session?await es(e.flags??{}):await rQ(e.session.device);return!1!==e.ensureReady&&await eH(t),t}async function rQ(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 es(t)}catch(e){if(!(e instanceof U)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await es({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function r0(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 r1="shared_prefs/ReactNativeDevPrefs.xml",r2="debug_http_host",r3="dev_server_https",r8="RCT_jsLocation",r5="RCT_packager_scheme",r4="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.",r9='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function r6(e){return void 0!==O(e)}async function r7(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=O(a);if(i){if("android"===t.platform)return void await at(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await an(t,r,i)}}async function ae(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await ar(t,r);"ios"===t.platform&&"simulator"===t.kind&&await ao(t,r)}}async function at(e,t,r){var a,i,n,o,s,l;let d,c;ac(t);let u=(a=await aa(e,t),i=r2,n=`${r.host}:${r.port}`,d=` <string name="${au(i)}">${au(n)}</string>`,al(ad(a,i),d));o=u,s=r3,l="https"===r.scheme,c=` <boolean name="${au(s)}" value="${l?"true":"false"}" />`,u=al(ad(o,s),c),await ai(e,t,u)}async function ar(e,t){ac(t);let r=await aa(e,t),a=ad(r,r2),i=ad(a,r3);i!==r&&await ai(e,t,i)}async function aa(e,t){let r=await V("adb",eP(e,["shell","run-as",t,"cat",r1]),{allowFailure:!0});return 0!==r.exitCode?r9:as(r.stdout)}async function ai(e,t,r){let a=eP(e,["shell","run-as",t,"id"]),i=await V("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=af(i.stdout,i.stderr);throw new U("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?r4:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await V("adb",eP(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await V("adb",eP(e,["shell","run-as",t,"tee",r1]),{stdin:r.trimEnd()})}catch(a){let e=T(a);if("TOOL_MISSING"===e.code)throw e;let r=af("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new U("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?r4:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function an(e,t,r){await V("xcrun",ez(e,["spawn",e.id,"defaults","write",t,r8,"-string",`${r.host}:${r.port}`])),await V("xcrun",ez(e,["spawn",e.id,"defaults","write",t,r5,"-string",r.scheme]))}async function ao(e,t){await V("xcrun",ez(e,["spawn",e.id,"defaults","delete",t,r8]),{allowFailure:!0}),await V("xcrun",ez(e,["spawn",e.id,"defaults","delete",t,r5]),{allowFailure:!0})}function as(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
|
|
6
|
-
`:r9}function al(e,t){return as(e).replace("</map>",`${t}
|
|
7
|
-
</map>`)}function ad(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return as(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function ac(e){if("binary"!==ep(e))return;let t=eE(e);throw new U("INVALID_ARGS",t,{package:e,hint:t})}function au(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function af(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 ap=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function am(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function ah(e,t){if(void 0!==e){if("string"!=typeof e)throw new U("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return R(e)}}function ag(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new U("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function aw(e){if("ios"===e||"android"===e)return e}async function av(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!r6(r)||r6(a)||await ae({device:i.device,appId:i.appBundleId})}async function ay(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 ej("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){r6(l)&&s?.appBundleId&&await ae({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 d=aw(e3(a.flags?.platform)??l?.platform??s?.device.platform);if(!d)return ej("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!==d)return ej("INVALID_ARGS",`runtime set targets ${d}, but session "${i}" is already bound to ${s.device.platform}.`);let c={platform:(t=a.flags,r={platform:d,metroHost:R(t?.metroHost),metroPort:ag(t?.metroPort),bundleUrl:R(t?.bundleUrl),launchUrl:R(t?.launchUrl)}).platform??l?.platform,metroHost:r.metroHost??l?.metroHost,metroPort:r.metroPort??l?.metroPort,bundleUrl:r.bundleUrl??l?.bundleUrl,launchUrl:r.launchUrl??l?.launchUrl};return 0===am(c)?ej("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(n.setRuntimeHints(i,c),{ok:!0,data:{session:i,configured:!0,runtime:c}})}let aI="open-command-roundtrip",aS="Not implemented for this platform in this release.",aA=new Set(["app","desktop","frontmost-app"]);async function a_(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await eZ();return{appBundleId:t.bundleId,appName:t.appName}}async function ab(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return ev(t)?"macos"===e.platform?void 0:"device"===e.kind?eV(r,t):void 0:await aN(e,t)}async function aN(e,t){try{let{resolveIosApp:r}=await import("./3918.js");return await r(e,t)}catch{return}}async function ak(e,t){if(!("android"!==e.platform||!t||ev(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 aD(e,t,r,a){return await ab(e,t,r)??await a(e,t)??("android"===e.platform&&t&&ev(t)?r:void 0)}function ax(e){return ej("INVALID_ARGS",e)}function aM(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=e5(r);if(!aA.has(e))throw new U("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new U("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new U("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let n=r?e5(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new U("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return ej(e instanceof U?e.code:"INVALID_ARGS",String(e.message))}}function aP(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&ev(r)?ax("open --relaunch does not support URL targets."):"app"!==a?ax("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===ep(r)?ax(eE(r)):null:null}async function aR(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await eH(i);let{appBundleId:l,appName:d}=await aL({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),c=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new U("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!ap.includes(e));if(i)throw new U("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 U("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new U("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:ah(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new U("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return ag(e)}}(t.metroPort),bundleUrl:ah(t.bundleUrl,"bundleUrl"),launchUrl:ah(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:aw(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=aw(i);if(a.platform&&r&&!n)throw new U("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new U("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&am(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=T(t);return ej(e.code,e.message,e.details)}}({req:t,sessionStore:a,sessionName:r,device:i});if(!c.ok)return{type:"response",response:c};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=c.data;await av({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:c.data.runtime}}}async function aL(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await a_(r);return{appBundleId:n.appBundleId??await aD(t,a,i,ak),appName:n.appName??a}}let aO=new Map;async function aE(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await ee(t.id),await W(t,"close",[r],a,i),await rX(t,rK)}async function aC(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 d=s[0]?.trim();!d||ev(d)||await W(r,"open",[l],a.flags?.out,{...ek(i,a.flags,n,o)})}async function a$(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:c,appName:u,surface:f,appBundleId:p,runtime:m,existingSession:h}=e,g=i.flags?.relaunch===!0,w=h?.trace?.outPath;if(g&&d){let e=p??d;await aE({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...ek(s,i.flags,p??h?.appBundleId,w)}})}await r7({device:l,appId:p,runtime:m});let v=Date.now();await W(l,"open",c,i.flags?.out,{...ek(s,i.flags,p)}),await aC({runtime:m,device:l,req:i,logPath:s,appBundleId:p,traceLogPath:w,openPositionals:c});let y=d?{durationMs:Math.max(0,Date.now()-v),measuredAt:new Date().toISOString(),method:aI,appTarget:d,appBundleId:p}:void 0;if(await rX(l,rz),eM(i.meta?.requestId)){let e=et();return ej(e.code,e.message,e.details)}h&&e9(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:u,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===am(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,d={session:t,surface:i};return r&&(d.appName=r),a&&(d.appBundleId=a),n&&(d.startup=n),s&&l(s)>0&&(d.runtime=s),o&&(d.platform=o.platform,d.target=o.target??"mobile",d.device=o.name,d.id=o.id,d.kind=o.kind,"android"===o.platform&&(d.serial=o.id)),o?.platform==="ios"&&(d.device_udid=o.id,d.ios_simulator_device_set=o.simulatorSetPath??null),{...d,...ta(`Opened: ${r??a??t}`)}}({sessionName:n,appName:u,appBundleId:p,surface:f,startup:y,device:l,runtime:m,runtimeHintCount:am});return o.recordAction(I,{command:"open",positionals:c,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:S}),o.set(n,I),{ok:!0,data:S}}async function aT(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return ej("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=aM(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?ax("open --relaunch requires an app name or an active session app."):ax("Session already active. Close it first or pass a new --session name.");let d=aP({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(d)return d;let c=await rQ(e.device),u=await aR({req:t,sessionName:r,sessionStore:i,device:c,surface:l,openTarget:s,existingSession:e});return"response"===u.type?u.response:await a$({req:t,sessionName:r,sessionStore:i,logPath:a,device:c,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:u.details.appBundleId,appName:u.details.appName,runtime:u.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return ax("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&ev(r)?ax("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===ep(r)?ax(eE(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await es(t.flags??{}),d=aM(l,t.flags?.surface,o);if("string"!=typeof d)return d;let c=aP({shouldRelaunch:n,openTarget:o,surface:d,device:l});return c||await ed(aO,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return ej("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name});let n=await aR({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:o});return"response"===n.type?n.response:await a$({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:d})})}async function aF(e){let t=await V("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function aU(e){let{device:t,shutdownRequested:r}=e;if(r&&(rZ(t)||"android"===t.platform&&"emulator"===t.kind))try{return rZ(t)?await Q(t):await aF(t)}catch(t){let e=F(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function aG(e){if(await ee(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await eh("dismiss",t).catch(t=>{P({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function aV(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return ej("SESSION_NOT_FOUND","No active session");n.appLog&&await t7(n.appLog),t.positionals&&t.positionals.length>0&&(e2(n.device.platform)&&await aG(n),await W(n.device,"close",t.positionals,t.flags?.out,{...ek(a,t.flags,n.appBundleId,n.trace?.outPath)}),await rX(n.device,rK)),e2(n.device.platform)&&await aG(n),r6(i.getRuntimeHints(r))&&n.appBundleId&&await ae({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...ta(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await rG(r).catch(()=>{}),i.delete(r);let o=await aU({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:tt({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...ta(`Closed: ${r}`)}}}let aj=["platform","target","device","udid","serial","verbose","out"];function aq(e,t){let r=e??{};for(let e of aj)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let aH={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)}},aB={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 aK(e){let{req:t,command:r,sessionName:a,sessionStore:n,deployOps:o}=e,s=n.get(a),l=t.flags??{},d=rW(r,s,l);if(d)return d;let c=t.positionals?.[0]?.trim(),u=t.positionals?.[1]?.trim();if(!c||!u)return ej("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let f=t.meta?.uploadedArtifactId;try{var p;let e,a=f?rn(f,t.meta?.tenantId):tU.expandHome(u);if(!i.existsSync(a))return ej("INVALID_ARGS",`App binary not found: ${a}`);let d=await rY({session:s,flags:l,ensureReady:!1});if(!e0(r,d))return ej("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await o.ios(d,c,a),r=t.bundleId;e=r?{app:c,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await o.android(d,c,a),r=t.package;e=r?{app:c,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=tt(e,(p=e,`Installed: ${p.appName??x(p)}`));return s&&n.recordAction(s,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&ro(f)}}async function az(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return ej("INVALID_ARGS",`Unsupported batch on-error mode: ${a}.`);let i=e.flags?.batchMaxSteps??em;if(!Number.isInteger(i)||i<1||i>1e3)return ej("INVALID_ARGS",`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`);try{let a=J(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await aW(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=T(t);return ej(e.code,e.message,e.details)}}async function aW(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{};return aq(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 aJ(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new U("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let c={simulatorSetPath:o??void 0};if(s){let e=await aZ({deviceName:i,runtime:n,simctlOpts:c});e?(t=e.udid,r=e.runtime,a=!1):(t=(await aX({deviceName:i,runtime:n,simctlOpts:c})).udid,r=await aY(t,c),a=!0)}else t=(await aX({deviceName:i,runtime:n,simctlOpts:c})).udid,r=await aY(t,c),a=!0;let u=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),u=!0}return{udid:t,device:i,runtime:r,created:a,booted:u}}async function aZ(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await V("xcrun",z(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:eX});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||aQ(a).includes(aQ(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 aX(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await V("xcrun",z(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new U("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(n.stdout??"").trim();if(!o)throw new U("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function aY(e,t){let r=await V("xcrun",z(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:eX});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function aQ(e){return e.toLowerCase().replace(/[._-]/g,"")}async function a0(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=eT(e.iosSimulatorDeviceSet);if(!r)return ej("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await aJ({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:eH});return{ok:!0,data:{udid:n.udid,device:n.device,runtime:n.runtime,ios_simulator_device_set:i??null,created:n.created,booted:n.booted}}}catch(t){let e=T(t);return ej(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=H(t.flags?.androidDeviceAllowlist),a=e3(t.flags?.platform),i=K({simulatorSetPath:eT(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("./3918.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("./3918.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("./3918.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("./3918.js");try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=T(t);return ej(e.code,e.message,e.details)}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=rW(t.command,e,i);if(n)return n;let o=await rY({session:e,flags:i,ensureReady:!0});if(!e0("apps",o))return ej("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(e2(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 a1(e){let{ensureAndroidEmulatorBooted:t}=await import("./3918.js");return await t(e)}let a2='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',a3='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function a8(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=e3(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return ej("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=rW("appstate",i,n);if(s)return s;let l=e2(i?.device.platform)&&function(e,t){if(!t)return!1;if(!rJ(e))return!0;let r=e3(e?.platform);return!(r&&!eQ(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(n,i);if("ios"===o&&!l)return ej("SESSION_NOT_FOUND",a2);if("macos"===o&&!l)return ej("SESSION_NOT_FOUND",a3);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 ej("COMMAND_FAILED",`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`)}return{ok:!0,data:{platform:i.device.platform,appName:e??"unknown",appBundleId:i.appBundleId,source:"session",surface:i.surface??"app",..."ios"===i.device.platform?{device_udid:i.device.id,ios_simulator_device_set:i.device.simulatorSetPath??null}:{}}}}let d=await rY({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return ej("SESSION_NOT_FOUND",a2);if("macos"===d.platform)return ej("SESSION_NOT_FOUND",a3);let{getAndroidAppState:c}=await import("./3918.js"),u=await c(d);return{ok:!0,data:{platform:"android",package:u.package,activity:u.activity}}}async function a5(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=rW(t.command,i,n);if(o)return o;let s="android"===(e3(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!s)return ej("INVALID_ARGS","boot --headless is supported only for Android emulators.");let d=r0({flags:n,sessionDevice:i?.device}),c=s&&!!d,u=!1;try{e=await rY({session:i,flags:n,ensureReady:!1})}catch(r){let t=T(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return ej("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!c||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await a1({avdName:d,serial:n.serial,headless:l}),u=!0}if(n.target&&(e.target??"mobile")!==n.target)return ej("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return ej("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!u){let t=r0({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return ej("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await a1({avdName:t,serial:n.serial,headless:!0})}await eH(e)}else("android"!==e.platform||!0!==e.booted)&&await eH(e);return e0("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:ej("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await a8({req:t,sessionName:r,sessionStore:a}):null}function a4(e){return Math.round(10*e)/10}let a9="adb-shell-dumpsys-cpuinfo",a6="adb-shell-dumpsys-meminfo";async function a7(e,t){try{let r=await V("adb",eP(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]),d=s[2];Number.isFinite(l)&&(n=d,o=t,n===o||n.startsWith(`${o}:`))&&(i+=l,a.add(d))}return{usagePercent:a4(i),measuredAt:r,method:a9,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw it("cpu",t,e)}}async function ie(e,t){try{let r=await V("adb",eP(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new U("COMMAND_FAILED",`Android meminfo did not find a running process for ${t}`,{metric:"memory",package:t,hint:"Run open <app> for this session again to ensure the Android app is active, then retry perf."});let a=ir(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!==ia(e));if(!r)break;return ia(r)??void 0}}(e);if(void 0===a)throw new U("COMMAND_FAILED",`Failed to parse Android meminfo output for ${t}`,{metric:"memory",package:t,hint:"Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging."});return{totalPssKb:a,totalRssKb:ir(e,"TOTAL RSS"),measuredAt:r,method:a6}}(r.stdout,t,new Date().toISOString())}catch(e){throw it("memory",t,e)}}function it(e,t,r){return r instanceof U&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new U(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof U?r:new U("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function ir(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return ia(a[1])??void 0}function ia(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let ii="ps-process-snapshot",io="ps-process-snapshot",is="xctrace-activity-monitor",il="xctrace-activity-monitor";async function id(e,t){if("ios"===e.platform&&"device"===e.kind)return await ip(e,t);let r=await iu(e,t),a=await iy(e,r);if(0===a.length)throw new U("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,hint:"Run open <app> for this session again to ensure the Apple app is active, then retry perf."});let i=new Date().toISOString(),n=ty(a.map(e=>o.basename(iI(e.command))));return iS({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:n,cpuMethod:ii,memoryMethod:io})}async function ic(e){let t=eJ(e),r=iA(t,e=>"schema"===e.name&&"activity-monitor-process-live"===e.attributes.name);if(!r)throw new U("COMMAND_FAILED","Failed to parse xctrace activity-monitor-process-live schema");let a=r.children.filter(e=>"col"===e.name).map(e=>{let t;return t=e.children.find(e=>"mnemonic"===e.name),t?.text??null??""}),i=a.indexOf("pid"),n=a.indexOf("process"),o=a.indexOf("cpu-total"),s=a.indexOf("memory-real");if(i<0||n<0||o<0||s<0)throw new U("COMMAND_FAILED","xctrace activity-monitor-process-live export is missing expected columns");let l=function e(t,r){let a=[];for(let i of t)r(i)&&a.push(i),a.push(...e(i.children,r));return a}(t,e=>"row"===e.name),d=[],c=new Map;for(let e of l){var u,f;let t=e.children;if(0===t.length)continue;for(let e of t){let t=iA(e.children,e=>"pid"===e.name&&"string"==typeof e.attributes.id);if(t?.attributes.id){let e=Number(t.text);c.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&c.set(e.attributes.id,{numberValue:i_(e),processName:iN(e)})}let r=ib(t[i],c),a=(u=t[n],f=c,u?u.attributes.ref?f.get(u.attributes.ref)?.processName??null:iN(u):null);null!==r&&Number.isFinite(r)&&a&&d.push({pid:r,processName:a,cpuTimeNs:ib(t[o],c),residentMemoryBytes:ib(t[s],c)})}return d}async function iu(e,t){let r="macos"===e.platform?await iw(t):await iv(e,t),a="macos"===e.platform?o.join(r,"Contents","Info.plist"):o.join(r,"Info.plist"),i=await eB(a,"CFBundleExecutable");if(!i)throw new U("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?o.join(r,"Contents","MacOS",i):void 0}}async function ip(e,t){let r=await im(e,t),a=await ih(e,t),i=await ih(e,t),n=ig(await ic(a.xml),r,t,e),o=ig(await ic(i.xml),r,t,e),s=i.capturedAtMs-a.capturedAtMs;if(s<=0)throw new U("COMMAND_FAILED",`Invalid Activity Monitor sample window for ${t}`,{appBundleId:t,deviceId:e.id});if(null===n.cpuTimeNs||null===o.cpuTimeNs||null===o.residentMemoryBytes)throw new U("COMMAND_FAILED",`Incomplete Activity Monitor sample for ${t}`,{appBundleId:t,deviceId:e.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});return iS({usagePercent:Math.max(0,o.cpuTimeNs-n.cpuTimeNs)/(1e6*s)*100,residentMemoryKb:o.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:o.matchedProcesses,cpuMethod:is,memoryMethod:il})}async function im(e,t){let r=(await eY(e,"all")).find(e=>e.bundleId===t);if(!r)throw new U("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new U("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let a=r.url.replace(/\/$/,""),i=d(a),n=(await e1(e)).filter(e=>e.executable.startsWith(`${a}/`));if(0===n.length)throw new U("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,deviceId:e.id,appBundlePath:i,hint:"Run open <app> for this session again to ensure the iOS app is active, then retry perf."});return n}async function ih(e,t){let r=await n.mkdtemp(o.join(u.tmpdir(),"agent-device-ios-perf-")),a=o.join(r,"sample.trace"),i=o.join(r,"activity-monitor-process-live.xml");try{let r=["xctrace","record","--template","Activity Monitor","--device",e.id,"--all-processes","--time-limit","1s","--output",a,"--quiet","--no-prompt"],o=await V("xcrun",r,{allowFailure:!0,timeoutMs:6e4}),s=Date.now();if(0!==o.exitCode)throw new U("COMMAND_FAILED",`Failed to record iOS device Activity Monitor sample for ${t}`,{cmd:"xcrun",args:r,exitCode:o.exitCode,stdout:o.stdout,stderr:o.stderr,appBundleId:t,deviceId:e.id,hint:ik(o.stdout,o.stderr)});let l=["xctrace","export","--input",a,"--xpath",'/trace-toc/run/data/table[@schema="activity-monitor-process-live"]',"--output",i],d=await V("xcrun",l,{allowFailure:!0,timeoutMs:15e3});if(0!==d.exitCode)throw new U("COMMAND_FAILED",`Failed to export iOS device perf sample for ${t}`,{cmd:"xcrun",args:l,exitCode:d.exitCode,stdout:d.stdout,stderr:d.stderr,appBundleId:t,deviceId:e.id,hint:ik(d.stdout,d.stderr)});return{capturedAtMs:s,xml:await n.readFile(i,"utf8")}}finally{await n.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function ig(e,t,r,a){let i=new Set(t.map(e=>e.pid)),n=new Set(t.map(e=>o.basename(d(e.executable)))),s=e.filter(e=>i.has(e.pid)||n.has(e.processName));if(0===s.length)throw new U("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:a.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let l=new Map;for(let e of s){let t=l.get(e.pid);if(!t){l.set(e.pid,e);continue}l.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:iD(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iD(t.residentMemoryBytes,e.residentMemoryBytes)})}let c=[...l.values()],u=c.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=c.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:u.length>0?u.reduce((e,t)=>e+t,0):null,residentMemoryBytes:f.length>0?f.reduce((e,t)=>e+t,0):null,matchedProcesses:ty(c.map(e=>e.processName))}}async function iw(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await V("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new U("COMMAND_FAILED",`Failed to resolve macOS app bundle for ${e}`,{appBundleId:e,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let a=r.stdout.split("\n").map(e=>e.trim()).find(e=>e.endsWith(".app"));if(!a)throw new U("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function iv(e,t){let r=ez(e,["get_app_container",e.id,t,"app"]),a=await V("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new U("COMMAND_FAILED",`Failed to resolve iOS simulator app container for ${t}`,{appBundleId:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Ensure the iOS simulator app is installed and booted, then retry perf."});let i=a.stdout.trim();if(0===i.length)throw new U("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return i}async function iy(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:ez(e,["spawn",e.id,"ps","-axo","pid=,%cpu=,rss=,command="]);return(function(e){let t=[];for(let r of e.split("\n")){let e=r.trim();if(0===e.length)continue;let a=e.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!a)continue;let i=Number(a[1]),n=Number(a[2]),o=Number(a[3]),s=a[4].trim();Number.isFinite(i)&&Number.isFinite(n)&&Number.isFinite(o)&&t.push({pid:i,cpuPercent:n,rssKb:o,command:s})}return t})((await V("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let i;return r=e.command,a=t,i=iI(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||o.basename(i)===a.executableName})}function iI(e){let[t=""]=e.trim().split(/\s+/,1);return t}function iS(e){return{cpu:{usagePercent:a4(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 iA(e,t){for(let r of e){if(t(r))return r;let e=iA(r.children,t);if(e)return e}}function i_(e){if(!e||e.children.some(e=>"sentinel"===e.name)||!e.text)return null;let t=Number(e.text);return Number.isFinite(t)?t:null}function ib(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:i_(e):null}function iN(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function ik(e,t){let r=ei(e,t);if(r)return r;let a=`${e}
|
|
9
|
-
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?e_: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 iD(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function ix(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===aI&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:aI,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:aI,sampleCount:r.length,samples:r}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:aI},n={session:e.name,platform:e.device.platform,device:e.device.name,deviceId:e.device.id,metrics:{startup:i,fps:{available:!1,reason:aS},memory:{available:!1,reason:aS},cpu:{available:!1,reason:aS}},sampling:{startup:{method:aI,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:a6,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:a9,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:il,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:is,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:io,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:ii,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 iM(e);return n.metrics.memory=iP(o),n.metrics.cpu=iP(s),n}async function iM(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,a]=await Promise.allSettled([ie(e.device,t),a7(e.device,t)]);return[r,a]}try{let r=await id(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 iP(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=F(e.reason);return{available:!1,reason:t.message,error:t}}let iR=["path","start","stop","doctor","mark","clear"],iL=`logs requires ${iR.slice(0,-1).join(", ")}, or ${iR.at(-1)}`,iO=["dump","log"],iE=`network requires ${iO.join(" or ")}`,iC=["summary","headers","body","all"],i$=`network include mode must be one of: ${iC.join(", ")}`;async function iT(e){let{req:t}=e;return"perf"===t.command?iF(e):"logs"===t.command?iU(e):"network"===t.command?iH(e):null}async function iF(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return ej("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await ix(a)}}catch(e){return{ok:!1,error:F(e)}}}async function iU(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(!n)return ej("SESSION_NOT_FOUND","logs requires an active session");if(!e0("logs",n.device))return ej("UNSUPPORTED_OPERATION","logs is not supported on this device");let o=(t.positionals?.[0]??"path").toLowerCase(),s=!!t.flags?.restart;return iR.includes(o)?s&&"clear"!==o?ej("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?iG(n,r,a):"mark"===o?function(e,t,r){let a,n=e.positionals?.slice(1).join(" ")??"",o=r.resolveAppLogPath(t);return t8(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?iV(n,r,a,s):"start"===o?ij(n,r,a):"stop"===o?iq(n,r,a):ej("INVALID_ARGS",iL):ej("INVALID_ARGS",iL)}async function iG(e,t,r){let a=r.resolveAppLogPath(t),i=await re(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 iV(e,t,r,a){if(e.appLog&&!a)return ej("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return ej("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let i=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:rt(i)};e.appLog&&await t7(e.appLog);let n=rt(i),o=r.resolveAppLogPidPath(t);try{let a=await t9(e.device,e.appBundleId,i,o);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:i,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}}),{ok:!0,data:{...n,restarted:!0}}}catch(a){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:F(a)}}}async function ij(e,t,r){if(e.appLog)return ej("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return ej("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 t9(e.device,e.appBundleId,a,i);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:a,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{path:a,started:!0}}}catch(e){return{ok:!1,error:F(e)}}}async function iq(e,t,r){if(!e.appLog)return ej("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await t7(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function iH(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return ej("SESSION_NOT_FOUND","network requires an active session");if(!e0("network",i.device))return ej("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!iO.includes(n))return ej("INVALID_ARGS",iE);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return ej("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 ej("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return iC.includes(a)?{ok:!0,include:a}:ej("INVALID_ARGS",i$)}(t);if(!s.ok)return s;let{include:l}=s,d=await t5({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:{...d.dump,active:!!i.appLog,state:i.appLog?.getState()??"inactive",backend:d.backend,notes:d.notes}}}let iB=/^[A-Z_][A-Z0-9_]*$/,iK=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-((?:[^}\\]|\\.)*))?\}/g,iz="AD_VAR_";function iW(e){return e.startsWith("AD_")}function iJ(e){return new U("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function iZ(e,t,r){return e.replace(iK,(e,a,i,n)=>{if(a)return"${";if(!i)return e;if(Object.prototype.hasOwnProperty.call(t.values,i))return t.values[i];if(void 0!==n)return n.replace(/\\(.)/g,"$1");throw new U("INVALID_ARGS",`Unresolved variable \${${i}} at ${r.file}:${r.line}.`)})}function iX(e,t,r){if(!e)return e;let a={...e};for(let[e,i]of Object.entries(a))"string"==typeof i&&(a[e]=iZ(i,t,r));return a}let iY=new Set(["ios","android","macos","linux"]);function iQ(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(i0(a)){!function(e,t,r){let{key:a,value:i}=function(e,t){let r=e.slice(3).replace(/^[\s]+/,""),a=r.indexOf("=");if(a<=0)throw new U("INVALID_ARGS",`Invalid env directive on line ${t}: expected "env KEY=VALUE".`);let i=r.slice(0,a);if(!iB.test(i))throw new U("INVALID_ARGS",`Invalid env key "${i}" on line ${t}: keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(i.startsWith("AD_"))throw new U("INVALID_ARGS",`Invalid env key "${i}" on line ${t}: the AD_* namespace is reserved for built-in variables. Rename ${i} to avoid the AD_ prefix.`);return{key:i,value:function(e,t){if(0===e.length)return"";if(e.startsWith('"'))try{let t=JSON.parse(e);if("string"!=typeof t)throw Error("not a string literal");return t}catch{throw new U("INVALID_ARGS",`Invalid quoted env value on line ${t}.`)}return e}(r.slice(a+1),t)}}(t,r),n=e.env??{};if(Object.prototype.hasOwnProperty.call(n,a))throw new U("INVALID_ARGS",`Duplicate env directive "${a}" on line ${r}.`);n[a]=i,e.env=n}(r,a,e+1);continue}if(!a.startsWith("context "))break;let i=a.match(/(?:^|\s)platform=([^\s]+)/);if(i){let e=i[1];e&&iY.has(e)&&i1(r,"platform",e)}let n=a.match(/(?:^|\s)timeout=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=1&&i1(r,"timeoutMs",Math.floor(e))}let o=a.match(/(?:^|\s)retries=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=0&&i1(r,"retries",Math.floor(e))}}return r}function i0(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function i1(e,t,r){let a=e[t];if(void 0!==a)throw new U("INVALID_ARGS",a===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(a)} vs ${String(r)}.`);e[t]=r}function i2(e){return!!e&&!Number.isNaN(Number(e))}let i3=/[*?[\]{}]/;async function i8(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,artifactsDir:s,runReplay:l,cleanupSession:d}=e;ea(i);let c=new Set,u=!1,f=l({filePath:r,sessionName:a,platform:o,requestId:i,artifactsDir:s,artifactPaths:c}).catch(e=>{let t=T(e);return ej(t.code,t.message)}).finally(()=>{eK(i)});try{return"number"==typeof n?await Promise.race([f,new Promise(e=>{t=setTimeout(()=>{u=!0,eF(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,[...c]))},n)})]):await f}finally{t&&clearTimeout(t),u&&(await i5(f)||P({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await d(a)}catch(e){P({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:T(e).message}})}}}async function i5(e){return await Promise.race([e.then(()=>!0),p(2e3).then(()=>!1)])}async function i4(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:n}=e;if((t.positionals?.length??0)===0)return ej("INVALID_ARGS","test requires at least one path or glob");try{var s,l,d,c,u,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 U("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[n]}return[]}if(r=e,!i3.test(r)&&(a=n,!i3.test(a)))throw new U("INVALID_ARGS",`test input not found: ${e}`);let s=o.isAbsolute(n)?n:e;return i.globSync(s,{cwd:o.isAbsolute(n)?void 0:t}).map(e=>o.isAbsolute(e)?e:o.resolve(t,e)).filter(e=>".ad"===o.extname(e)&&function(e){try{return i.statSync(e).isFile()}catch{return!1}}(e))})(e,n)))].map(e=>o.normalize(e)).sort((e,t)=>e.localeCompare(t)),l=[];for(let e of s){var d,c;let t=iQ(i.readFileSync(e,"utf8"));if(!a){l.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){l.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${a}`});continue}d=a,c=t.platform,("apple"===d?"apple"===c||"ios"===c||"macos"===c:c===d)&&l.push({kind:"run",path:e,metadata:t})}if(0===l.filter(e=>"run"===e.kind).length){let e=a?` for --platform ${a}`:"";throw new U("INVALID_ARGS",`No .ad tests matched${e}.`)}return l}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),v=(s=t.meta?.requestId,(s?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),y=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:v}),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 i9({entry:e,sessionName:r,suiteInvocationId:v,caseIndex:A-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(l=t.flags?.timeoutMs,d=e.metadata.timeoutMs,"number"==typeof l?l:d),suiteArtifactsDir:y,runReplay:a,cleanupSession:n});if(I.push(i),t.flags?.failFast===!0)break}let _=(c=w.length,u=I,f=Date.now()-S,e=u.filter(e=>"passed"===e.status).length,m=(p=u.filter(e=>"failed"===e.status)).length,h=u.filter(e=>"skipped"===e.status).length,g=e+m,{total:c,executed:g,passed:e,failed:m,skipped:h,notRun:Math.max(0,c-g-h),durationMs:f,failures:p,tests:u});return{ok:!0,data:_}}catch(t){let e=T(t);return ej(e.code,e.message)}}async function i9(e){var t,r;let a,n,{entry:s,sessionName:l,suiteInvocationId:d,caseIndex:c,cwd:u,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:g,cleanupSession:w}=e,v=Date.now(),y=o.join(h,(t=s.path,(0===(n=u?o.relative(u,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,d,s.path,c,e),n=o.join(y,`attempt-${S}`);r=s.path,i.mkdirSync(n,{recursive:!0}),i.copyFileSync(r,o.join(n,"replay.ad"));let u=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:n}=e;return ex(`${t??r}:test:${i+1}:${o.basename(a)}:attempt:${n+1}`,r)}({requestId:f,suiteInvocationId:d,filePath:s.path,caseIndex:c,attemptIndex:e}),h=await i8({filePath:s.path,sessionName:t,requestId:u,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,d=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||d.push(t.error.logPath);let c=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}(d,l),u=[`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;u.push(`replayed: ${e}`,`healed: ${r}`)}else u.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&u.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&u.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&u.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&u.push("timeoutMode: cooperative");c.length>0&&u.push(`copiedArtifacts: ${c.map(e=>o.basename(e)).join(", ")}`);let f=o.join(l,"result.txt"),p=`${u.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()-v;if(a?.ok)return{file:s.path,session:I,status:"passed",durationMs:A,attempts:S,artifactsDir:y,replayed:"number"==typeof a.data?.replayed?a.data.replayed:0,healed:"number"==typeof a.data?.healed?a.data.healed:0};let _=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:y,error:_}}function i6(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 i7(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}=i6(e.positionals??[]);r&&t.push(r)}return ty(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",d=await ne(n,t,a,s,i);for(let e of o){let r=td(d.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=tu(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=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}=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}=i6(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function ne(e,t,r,a,i){let n=await W(e.device,"snapshot",[],t.flags?.out,{...ek(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 e.snapshot=s,i.set(e.name,e),s}async function nt(e){let{req:t,sessionName:r,logPath:a,sessionStore:n,invoke:s}=e,l=t.positionals?.[0];if(!l)return ej("INVALID_ARGS","replay requires a path");let d="",c=new Set;try{var u;let e;d=tU.expandHome(l,t.meta?.cwd);let f=i.readFileSync(d,"utf8"),p=f.trimStart()[0];if("{"===p||"["===p)return ej("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let m=iQ(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(i0(o)){if(i)throw new U("INVALID_ARGS",`env directives must precede all actions (line ${e+1}).`);continue}let s=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,i=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!i)break;i="\\"===t&&!i,"\\"!==t&&(i=!1),a+=1}if(a>=e.length)throw new U("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=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 i2(r)&&i2(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 U("INVALID_ARGS","screenshot --max-size requires a positive integer");n.flags.screenshotMaxSize=r,t+=1;continue}e.push(r)}return n.positionals=e,n}return n.positionals=i,n}(n);s&&(t.push(s),r.push(e+1),i=!0)}return{actions:t,actionLines:r}}(f),g=h.actions,w=h.actionLines;if(t.flags?.replayUpdate===!0&&m.env&&Object.keys(m.env).length>0)return ej("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 ej("INVALID_ARGS","replay -u does not yet preserve ${VAR} substitutions. Resolve or inline the variables before running with -u.");let v=function(e){let t={};if(e.builtins)for(let[r,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(iW(e))throw iJ(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},d=n.platform??a.platform;d&&(l.AD_PLATFORM=d);let c=n.device;"string"==typeof c&&c.length>0&&(l.AD_DEVICE=c);let u=n.artifactsDir;return"string"==typeof u&&u.length>0&&(l.AD_ARTIFACTS=u),l}({req:t,sessionName:r,metadata:m,resolvedPath:d}),fileEnv:m.env,shellEnv:function(e){let t={};for(let[r,a]of Object.entries(e)){if("string"!=typeof a||!r.startsWith(iz))continue;let e=r.slice(iz.length);0!==e.length&&iB.test(e)&&(iW(e)||(t[e]=a))}return t}(function(e){let t=e.flags?.replayShellEnv;if(t&&"object"==typeof t&&!Array.isArray(t)){let e={};for(let[r,a]of Object.entries(t))"string"==typeof a&&(e[r]=a);return e}return process.env}(t)),cliEnv:function(e){let t={};for(let r of e){let e=r.indexOf("=");if(e<=0)throw new U("INVALID_ARGS",`Invalid -e entry "${r}": expected KEY=VALUE.`);let a=r.slice(0,e);if(!iB.test(a))throw new U("INVALID_ARGS",`Invalid -e key "${a}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(iW(a))throw iJ(a);t[a]=r.slice(e+1)}return t}((u=t,e=u.flags?.replayEnv,Array.isArray(e)?e.filter(e=>"string"==typeof e):[]))}),y=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 nr({req:t,sessionName:r,action:i,scope:v,filePath:d,line:w[e]??0,invoke:s});if(o.ok){ni(o).forEach(e=>c.add(e));continue}if(!y)return na(o,i,e,d,[...c]);let l=await i7({action:i,sessionName:r,logPath:a,sessionStore:n});if(!l)return na(o,i,e,d,[...c]);if(g[e]=l,!(o=await nr({req:t,sessionName:r,action:l,scope:v,filePath:d,line:w[e]??0,invoke:s})).ok)return na(o,l,e,d,[...c]);ni(o).forEach(e=>c.add(e)),I+=1}return y&&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=${tx(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 tF(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tM(r,tR));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(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 tL(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)}(d,g,n.get(r)),{ok:!0,data:{replayed:g.length,healed:I,session:r,artifactPaths:[...c]}}}catch(t){let e=T(t);return ej(e.code,e.message,c.size>0?{artifactPaths:[...c]}:void 0)}}async function nr(e){var t,r;let{req:a,sessionName:i,action:n,scope:o,filePath:s,line:l,invoke:d}=e,c=(t={file:s,line:l},{...n,positionals:(n.positionals??[]).map(e=>iZ(e,o,t)),flags:iX(n.flags,o,t)??{},runtime:iX(n.runtime,o,t)});return await d({token:a.token,session:i,command:c.command,positionals:c.positionals??[],flags:(r=a.flags,aq(r,{...c.flags??{}})),runtime:c.runtime,meta:a.meta})}function na(e,t,r,a,i=[]){let n;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${n=(t.positionals??[]).map(e=>tD(e)),[t.command,...n].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:a,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:i}}}}function 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 nn(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await nt({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await i4({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactsDir:l,artifactPaths:d})=>{let c=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 nt({req:{...t,command:"replay",session:r,positionals:[e],flags:c,meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),d&&ni(t).forEach(e=>d.add(e)),t}})},cleanupSession:async e=>{i.get(e)&&await aV({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let no=new Set(["session_list","ensure-simulator","devices","apps"]),ns=new Set(["boot","appstate"]),nl=new Set(["perf","logs","network"]),nd=new Set(["replay","test"]);async function nc(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=i.get(r),c=t.flags??{},u=rW(n,d,c);if(u)return u;let f=await rY({session:d,flags:c,ensureReady:!0});if(!e0(n,f))return ej("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await W(f,n,o,t.flags?.out,{...ek(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,p,f):d;i.recordAction(e,{command:n,positionals:s??o,flags:t.flags??{},result:p??{}}),e!==d&&i.set(r,e)}return{ok:!0,data:p??{}}}async function nu(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=rW("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return ej("INVALID_ARGS","clipboard requires a subcommand: read or write");let d=await rY({session:n,flags:o,ensureReady:!0});if(!e0("clipboard",d))return ej("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let c=await W(d,"clipboard",t.positionals??[],t.flags?.out,{...ek(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:c??{}}),{ok:!0,data:{platform:d.platform,...c??{}}}}async function nf(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(no.has(t.command))return await a0({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await ay({req:t,sessionName:r,sessionStore:i});if(ns.has(t.command))return await a5({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await nu({req:t,sessionName:r,logPath:a,sessionStore:i});if("keyboard"===t.command){let e=i.get(r),n=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==n||"ios"!==e3((t.flags??{}).platform)?await nc({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):ej("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(nl.has(t.command))return await iT({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await aK({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?aB:aH});if("install_source"===t.command)return await rq({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await rB({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await nc({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=eR(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tU.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):ej("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await nc({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 aD(e.device,r,e.appBundleId,ak)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await aT({req:t,sessionName:r,logPath:a,sessionStore:i}):nd.has(t.command)?await nn({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await az(t,r,n):"close"===t.command?await aV({req:t,sessionName:r,logPath:a,sessionStore:i}):null}async function np(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 ej("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:c,value:u,timeoutMs:f}=tw(s);if(!d)return ej("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return ej("INVALID_ARGS","find accepts only one of --first or --last");let p=await eU({req:t,sessionName:r,logPath:a,sessionStore:i});if(p)return p;let m=i.get(r);if(!m&&"exists"!==c&&"wait"!==c&&"get_text"!==c&&"get_attrs"!==c)return ej("SESSION_NOT_FOUND","No active session. Run open first.");let h=m?.device??await es(t.flags??{});m||await eH(h);let g="role"!==l?d:void 0,w="click"===c||"focus"===c||"fill"===c||"type"===c,v=0,y=null,I=async()=>{let e=Date.now();if(y&&e-v<750&&!eW(m))return{nodes:y};let{snapshot:n}=await eI({device:h,session:m,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:g}),o=n.nodes;return v=e,y=o,m&&(m.snapshot=n,i.set(r,m)),{nodes:o,truncated:n.truncated,backend:n.backend}},S={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:m,device:h,command:o,locator:l,query:d};if("wait"===c)return nm(S,I,l,d,f);let{nodes:A}=await I(),_=tg(A,l,d,{requireRect:w});if(w&&_.matches.length>1)if(t.flags?.findFirst)_.matches=[_.matches[0]];else{if(!t.flags?.findLast){var b,N,k;let e;return b=_.matches,N=l,k=d,e=b.slice(0,8).map(e=>{let t=to(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),ej("AMBIGUOUS_MATCH",`find matched ${b.length} elements for ${N} "${k}". Use a more specific locator or selector.`,{locator:N,query:k,matches:b.length,candidates:e})}_.matches=[_.matches[_.matches.length-1]]}let D=_.matches[0]??null;if(!D)return ej("COMMAND_FAILED","find did not match any element");let x="click"===c||"focus"===c||"fill"===c||"type"===c?tn(A,D)??D:D,M=`@${x.ref}`,P={node:D,resolvedNode:x,ref:M,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},R={exists:()=>nh(S),get_text:()=>ng(S,P),get_attrs:()=>nw(S,P),click:()=>nv(S,P),fill:()=>ny(S,P,u),focus:()=>nI(S,P),type:()=>nS(S,P,u)}[c];return R?R():null}async function nm(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,d=i??1e4,c=Date.now();for(;Date.now()-c<d;){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()-c}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-c}};await j(300)}return ej("COMMAND_FAILED","find wait timed out")}async function nh(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 ng(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await ey({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>ek(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 nw(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 nv(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:d}=e,c=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!c.ok)return c;let u=t.resolvedNode.rect?th(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:d};return u&&(f.x=u.x,f.y=u.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:f}}async function ny(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return ej("INVALID_ARGS","find fill requires text");let d=await s({token:a.token,session:i,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return d.ok&&o&&n.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),d}async function nI(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 ej("COMMAND_FAILED","matched element has no bounds");let d=await W(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...ek(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:d??{ref:t.ref}}}async function nS(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return ej("INVALID_ARGS","find type requires text");let d=t.node.rect?th(t.node.rect):null;if(!d)return ej("COMMAND_FAILED","matched element has no bounds");await W(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...ek(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let c=await W(o,"type",[r],a.flags?.out,{...ek(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:c??{ref:t.ref}}}let nA=`
|
|
13
|
-
import Foundation
|
|
14
|
-
import AVFoundation
|
|
15
|
-
|
|
16
|
-
let url = URL(fileURLWithPath: CommandLine.arguments[1])
|
|
17
|
-
let asset = AVURLAsset(url: url)
|
|
18
|
-
let semaphore = DispatchSemaphore(value: 0)
|
|
19
|
-
var exitCode: Int32 = 1
|
|
20
|
-
|
|
21
|
-
Task {
|
|
22
|
-
defer { semaphore.signal() }
|
|
23
|
-
do {
|
|
24
|
-
let playable = try await asset.load(.isPlayable)
|
|
25
|
-
let duration = try await asset.load(.duration)
|
|
26
|
-
if playable && duration.isValid && !duration.isIndefinite && CMTimeGetSeconds(duration) > 0 {
|
|
27
|
-
exitCode = 0
|
|
28
|
-
}
|
|
29
|
-
} catch {
|
|
30
|
-
exitCode = 1
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
semaphore.wait()
|
|
35
|
-
exit(exitCode)
|
|
36
|
-
`.trim();async function n_(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 j(a)}}async function nb(e){try{var t,r;let a,i=await V("swift",["-",e],{stdin:nA,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 nk(e);return!1}catch(t){if(t instanceof U&&"TOOL_MISSING"===t.code)return nk(e);throw t}}async function nN(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nb(e))return;await j(r)}}function nk(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 nD(e){let t=o.parse(e);return o.join(t.dir,`${t.name}.gesture-telemetry.json`)}function nx(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nM(e){let t=o.dirname(d(import.meta.url)),r=[d(new URL(`./${e}`,import.meta.url)),o.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),o.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(i.existsSync(e))return e;throw new U("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}async function nP(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:n}=e;await n_(t),await nN(t);let s=i.mkdtempSync(o.join(u.tmpdir(),"agent-device-record-overlay-")),l=o.join(s,`input${o.extname(t)||".mp4"}`),d=o.join(s,o.basename(t)),c=o.join(s,"home"),f=o.join(s,"module-cache");i.copyFileSync(t,l),i.mkdirSync(c,{recursive:!0}),i.mkdirSync(f,{recursive:!0});try{await V("xcrun",["swift",r,"--input",l,"--output",d,...a],{timeoutMs:12e4,env:{...process.env,HOME:c,CLANG_MODULE_CACHE_PATH:f}}),await nN(d),i.copyFileSync(d,t)}catch(a){let e=a instanceof U?a:new U("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new U("COMMAND_FAILED",n,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{i.rmSync(s,{recursive:!0,force:!0})}}async function nR(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nP({videoPath:r,scriptPath:t??=nM("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nL(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nP({videoPath:r,scriptPath:e??=nM("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function nO(e){let{videoPath:t,quality:a,targetLabel:i="recording"}=e;await nP({videoPath:t,scriptPath:r??=nM("recording-resize.swift"),scriptArgs:["--quality",String(a)],commandDescription:`Failed to resize the ${i}`})}function nE(e){return e instanceof Error?e.message:String(e)}function nC(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function n$(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,d=(n=nD((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?nx(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)}]})):nx(r))},i.writeFileSync(n,JSON.stringify(o,null,2)),n);return s.telemetryPath=d,d}({recording:t,trimStartMs:a});if(t.showTouches){let e=function(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}();if(e)t.overlayWarning??=e;else try{await r.overlayRecordingTouches({videoPath:t.outPath,telemetryPath:o,targetLabel:n})}catch(e){t.overlayWarning??=`failed to overlay recording touches: ${nE(e)}`}}}async function nT(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 nF(e,t,r){for(let a=0;a<40;a+=1){if(!await nT(e,t,r))return!0;await j(250)}return!await nT(e,t,r)}async function nU(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await j(250)}}async function nG(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 nT(e,t,a))break;if(i+1>=2)return!0;await j(250)}return!1}async function nV(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=nC(s,"adb pull");else{await r.waitForStableFile(o,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(o);if(P({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:n,outPath:o,attempt:e+1,fileSize:(()=>{try{return i.statSync(o).size}catch{return 0}})(),playable:t}}),t)return;P({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:n,outPath:o,attempt:e+1}})}e<1&&await j(750)}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function nj(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: ${nC(i,"adb shell wm size")}`);return{width:nq(Number(n[1]),a),height:nq(Number(n[2]),a)}}function nq(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function nH(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function nB(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return P({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await nT(e,t,r))&&await nF(e,t,r)}async function nK(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 nj({deps:i,deviceId:n.id,quality:o.quality})}catch(e){return ej("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: ${nC(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 nH(i,n.id,e);continue}if(P({level:"debug",phase:"record_start_android_started",data:{deviceId:n.id,remotePath:e,remotePid:a}}),await nG(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 nB(i,n.id,a),await nH(i,n.id,e)}return ej("COMMAND_FAILED",s)}async function nz(e){let t,r,{deps:a,device:i,recording:n}=e;P({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(P({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await nT(a,i.id,n.remotePid)&&!await nB(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${nC(o,"adb shell kill")}`):await nF(a,i.id,n.remotePid)||await nB(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await nU(a,i.id,n.remotePath);let e=await nV({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),ej("COMMAND_FAILED",e);await n$({recording:n,deps:a,targetLabel:"Android recording"})}if(await s(),t)return ej("COMMAND_FAILED",t);if(r)return ej("COMMAND_FAILED",r);return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});P({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:i.id,remotePath:n.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${nC(e,"adb shell rm")}`)}}function nW(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function nJ(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function nZ(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=nW(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},nJ(t,i,r))}catch(e){P({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:nE(e)}})}}async function nX(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:c,appBundleId:u}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=nJ(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:f,fps:d,quality:c.quality,appBundleId:u},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(!nE(a).toLowerCase().includes("recording already in progress"))return ej("COMMAND_FAILED",`failed to start recording: ${nE(a)}`);P({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:nE(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 ej("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:u},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 ej("COMMAND_FAILED",`failed to start recording: ${nE(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...c}}async function nY(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},nJ(t,i,r))}catch(e){return ej("COMMAND_FAILED",`failed to start recording: ${nE(e)}`)}return{platform:"macos-runner",...s}}async function nQ(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=nW(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nJ(t,i,r))}catch(e){P({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nE(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of B)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 ej("COMMAND_FAILED",`failed to copy recording from device: ${e}`)}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);return d>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:d}),await n$({recording:o,deps:n,trimStartMs:d,targetLabel:"iOS recording"}),null}async function n0(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=nW(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nJ(t,i,r))}catch(e){P({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nE(e)}})}return await n$({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function n1(e){for(let t=0;t<2;t+=1){try{if(i.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await j(250)}return Date.now()}async function n2(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await nZ({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:c,wait:u}=s.runCmdBackground("xcrun",ez(n,["io",n.id,"recordVideo",d]),{allowFailure:!0}),f=await n1(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:nW(i)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:i.trace?.outPath}),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:c,wait:u,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function n3(e){let t,{req:r,sessionName:a,sessionStore:n,activeSession:s,device:l,logPath:d,deps:c}=e;if(s.recording)return ej("INVALID_ARGS","recording already in progress");let u=r.flags?.fps,f=r.flags?.quality;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return ej("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==f&&(!Number.isInteger(f)||f<5||f>10))return ej("INVALID_ARGS","quality must be an integer between 5 and 10");if(!e0("record",l))return ej("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=nW(s);if(!e)return ej("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await nX({req:r,activeSession:s,sessionStore:n,device:l,logPath:d,deps:c,fpsFlag:u,recordingBase:h,appBundleId:e})}else if("macos"===l.platform){let e=nW(s);if(!e)return ej("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await nY({req:r,activeSession:s,device:l,logPath:d,deps:c,fpsFlag:u,recordingBase:h,appBundleId:e})}else t="ios"===l.platform?await n2({req:r,activeSession:s,device:l,logPath:d,deps:c,recordingBase:h,resolvedOut:m}):await nK({deps:c,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 n8(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await nz({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return ej("COMMAND_FAILED",`failed to stop recording: ${nC(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: ${nE(e)}`}return await n$({recording:a,deps:t,targetLabel:"iOS recording"}),null}async function n5(e){var t;let r,{req:a,activeSession:i,device:n,logPath:s,deps:l}=e;if(!i.recording)return ej("INVALID_ARGS","no active recording");let d=i.recording,c=d.invalidatedReason;i.recording=void 0;let u="ios-device-runner"===d.platform?await nQ({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:d}):"macos-runner"===d.platform?await n0({req:a,activeSession:i,device:n,logPath:s,deps:l,recording:d}):await n8({deps:l,device:n,recording:d});return u||(c?ej("COMMAND_FAILED",c):(r=[{field:"outPath",path:(t=d).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 nD(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 n4(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:V,runCmdBackground:G,runIosRunnerCommand:eq,waitForStableFile:n_,isPlayableVideo:nb,trimRecordingStart:nR,resizeRecording:nO,overlayRecordingTouches:nL},o=a.get(r),s=o?.device??await es(t.flags??{});o||await eH(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return ej("INVALID_ARGS","record requires start|stop");if("start"===d)return n3({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let c=await n5({req:t,activeSession:l,device:s,logPath:i,deps:n});return c.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:c.data?.outPath,showTouches:c.data?.showTouches}}),c}async function n9(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,s=t.command;if("record"===s)return n4({req:t,sessionName:r,sessionStore:a,logPath:n});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return ej("INVALID_ARGS","trace requires start|stop");let n=a.get(r);if(!n)return ej("SESSION_NOT_FOUND","No active session");if("start"===e){if(n.trace)return ej("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 ej("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 n6(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 n7=new WeakMap;function oe(e){if(!e)return;let t=n7.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)&&ot(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(ot);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 n7.set(e,r),r}function ot(e){return!!e&&e.width>0&&e.height>0}let or={referenceWidth:1e3,referenceHeight:1e3};function oa(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let c,u,f=e.recording;if(!f)return;let p={...i,...a??{}},m=os(p.effectiveDurationMs)??os(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:os(p.gestureStartUptimeMs),gestureEndUptimeMs:os(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:os(p.gestureStartUptimeMs),gestureEndUptimeMs:os(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===os(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=ol(os(t.count),1)??1,r=!0===t.doubleTap,a=ol(os(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 n6(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):n6(h),v=(l=e.snapshot,c=os((d=p).referenceWidth),u=os(d.referenceHeight),void 0!==c&&c>0&&void 0!==u&&u>0?{referenceWidth:c,referenceHeight:u}:oe(l)),y=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=od(t,e);if(!i)return[];let{x:n,y:o}=i,s=ol(os(t.count),1)??1,l=ol(os(t.intervalMs),0)??0,d=!0===t.doubleTap,c=ol(os(t.holdMs),1),u=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==c&&c>0){u.push(on(t,n,o,c,a));continue}u.push(oi(t,n,o,a)),d&&u.push(oi(t+90,n,o,a))}return u}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=od(t,e);if(!i)return[];let{x:n,y:o}=i;return[oi(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=od(t,e);if(!n)return[];let{x:o,y:s}=n;return[on(r,o,s,ou(a,[os(t.durationMs),os(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=oc(t,e),o=oo(t.contentDirection)??oo(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:c}=n,u=ou(a,[],250),f=os(t.amount)??os(e[1]),p=os(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:c,...i,durationMs:u,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=oc(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,c=ou(a,[os(t.effectiveDurationMs),os(t.durationMs),os(e[4])],250),u=ol(os(t.count),1)??1,f=ol(os(t.pauseMs),0)??0,p="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<u;e+=1){let t="ping-pong"===p&&e%2==1,a=t?l:o,n=t?d:s,u=t?o:l,h=t?s:d,g=r+e*(c+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,u,h,i)){m.push({kind:"back-swipe",tMs:g,x:a,y:n,x2:u,y2:h,...i,durationMs:c,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,u,i)});continue}m.push({kind:"swipe",tMs:g,x:a,y:n,x2:u,y2:h,...i,durationMs:c})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=od(t,e,1),o=os(t.scale)??os(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:ou(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,w,g,v);0!==y.length&&(f.gestureEvents.push(...y),P({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:y.length,tMs:w,gestureDurationMs:g,kinds:y.map(e=>e.kind)}}))}function oi(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function on(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function oo(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 os(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 ol(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function od(e,t,r=0){let a=os(e.x)??os(t[r]),i=os(e.y)??os(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function oc(e,t){let r=os(e.x1)??os(t[0]),a=os(e.y1)??os(t[1]),i=os(e.x2)??os(t[2]),n=os(e.y2)??os(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 ou(e,t,r){return ol(e,1)??t.map(e=>ol(e,1)).find(e=>void 0!==e)??r}function of(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:c}=e,u=(t=c,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,...d??{},...c??{},...o??{},...ta(u)}}function op(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d,androidFreshnessBaseline:c}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),er(a)&&e9(t,a,c??t.snapshot),oa(t,a,i,o,n??{},l,d),{ok:!0,data:s}}async function om(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 ew(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=oe(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=oe(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oh(e){try{return await om(e)}catch(t){P({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function og(e){return oe({nodes:e,createdAt:0})}function ow(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:ej("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 ov(e){let t=e.sessionStore.get(e.sessionName);if(!t)throw new U("SESSION_NOT_FOUND","No active session. Run open first.");return v({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)=>oy(await W(r.device,"press",[String(i.x),String(i.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fill:async(a,i,n)=>oy(await W(r.device,"fill",[String(i.x),String(i.y),n],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(a,i)=>oy(await W(r.device,"type",[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:t}),artifacts:eC("interaction commands",{plural:!0}),sessions:{get:r=>r===e.sessionName?{name:e.sessionName,appBundleId:t.appBundleId,appName:t.appName,snapshot:t.snapshot,metadata:{surface:t.surface}}:void 0,set:r=>{r.snapshot&&(t.snapshot=r.snapshot,e.sessionStore.set(e.sessionName,t))}},policy:w()})}function oy(e){return e&&"object"==typeof e?e:void 0}function oI(e){return"ref"===e.kind?{ref:oS(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 oS(e){return e?.startsWith("@")?e.slice(1):e}async function oA(e){switch(e.req.command){case"press":case"click":return await o_(e);case"fill":return await ob(e);default:return null}}async function o_(e){let t,{req:r,sessionName:a,sessionStore:i}=e,n=i.get(a),o="click"===r.command?"click":"press";if(!n)return ej("SESSION_NOT_FOUND","No active session. Run open first.");let s=ow(n,o);if(s)return s;if(!e0("press",n.device))return ej("UNSUPPORTED_OPERATION","press is not supported on this device");let l=eA(r.flags),d=X(l);if("primary"!==l){let e=en({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 ej(e.code,e.message,e.details)}let c=function(e,t){let r=eG(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:ej("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}(r.positionals??[],o);if(!c.ok)return c.response;if("ref"===c.target.kind){let a=e.refSnapshotFlagGuardResponse("press",r.flags);if(a)return a;t=await ok(e,n)}return await oN(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(c.target,t):await e.interactions.press(c.target,t)},afterRun:async e=>{var t;await ec(n,(t=c.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 oh({session:n,flags:r.flags,sessionStore:i,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:e.captureSnapshotForSession}):og(n.snapshot?.nodes??[]),o=of({data:t.backendResult,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:a,extra:{...oI(t),...d}});return{result:o,responseData:o}}})}async function ob(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(i){let e=ow(i,"fill");if(e)return e}if(i&&!e0("fill",i.device))return ej("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!i)return ej("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:ej("INVALID_ARGS","fill requires text after ref")}}let r=eG(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:ej("INVALID_ARGS","fill requires text after coordinates")}}let a=ti(e,{preferTrailingValue:!0});if(!a)return{ok:!1,response:ej("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:ej("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 ok(e,i)}return await oN(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:og(i.snapshot?.nodes??[]),r=of({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...oI(e),text:n.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:oS(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 oN(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return ej("SESSION_NOT_FOUND","No active session. Run open first.");let a=ov(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 op({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags,result:s,responseData:l,actionStartedAt:i,actionFinishedAt:o,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=T(t);if(e$(e))throw e;return{ok:!1,error:F(t)}}}async function ok(e,t){if(!eW(t))return;let r=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:"ref-refresh"})}catch(t){P({level:"warn",phase:"android_ref_snapshot_refresh_failed",data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return r}async function oD(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 eI({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??"",androidFreshnessMode:i.androidFreshnessMode});return e.snapshot=s,r.set(e.name,e),e.snapshot}let ox=/\bis(?:n't| not)\s+responding\b/i,oM=/^close app$/i;async function oP(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oR(t),r=function(e){if(oC(e))return e.find(e=>{let t=oE(e);return t.length>0&&oM.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=th(r.rect),n=await V("adb",eP(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return P({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:n.exitCode,stdout:n.stdout.trim(),stderr:n.stderr.trim()}}),"failed";if(!await oL(t))return P({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eN(t.device,t.appBundleId),!await oO(t,t.appBundleId)))return P({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return P({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:a,y:i}}),"recovered"}catch(e){return P({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function oR(e){return tm(tp((await eo(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function oL(e){for(let t=0;t<12;t+=1){if(!oC(await oR(e)))return!0;await j(500)}return!oC(await oR(e))}async function oO(e,t){for(let r=0;r<12;r+=1){if((await eg(e.device)).package===t)return!0;await j(500)}return(await eg(e.device)).package===t}function oE(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 oC(e){return e.some(e=>{let t=oE(e);return t.length>0&&ox.test(t)})}async function o$(e){let t=await oA({...e,captureSnapshotForSession:oD,refSnapshotFlagGuardResponse:Z});if(t)return t;switch(e.req.command){case"type":return await oT({...e,captureSnapshotForSession:oD});case"get":return await el(e);case"is":return await eS(e);default:return null}}async function oT(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return ej("SESSION_NOT_FOUND","No active session. Run open first.");if(!e0("type",i.device))return ej("UNSUPPORTED_OPERATION","type is not supported on this device");if("android"===i.device.platform&&i.recording&&"failed"===await oP({session:i}))return ej("COMMAND_FAILED","Android system dialog blocked the recording session");let n=(t.positionals??[]).join(" "),o=ov(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(),d={...e.backendResult??{},text:e.text,delayMs:e.delayMs,...ta(e.message??`Typed ${Array.from(e.text).length} chars`)};return op({session:i,sessionStore:a,command:t.command,positionals:t.positionals??[],flags:t.flags,result:d,responseData:d,actionStartedAt:s,actionFinishedAt:l})}catch(e){return{ok:!1,error:F(e)}}}function oF(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 oU(e){let{req:t,leaseRegistry:r}=e,a=oF(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 oG(e,t){if(!t)return[];let r=[],a=e.device,i=e3(t.platform);if(i&&!eQ(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=ef(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function oV(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 oj=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"];async function oq(e){let{session:t,sessionName:r,outPath:a,outputPlacement:i,dispatchContext:s}=e,l=v({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?oH(await W(t.device,"screenshot",[],i,o)):oH(await W(t.device,"screenshot",[i],void 0,o))}}}({session:t,outputPlacement:i,dispatchContext:s}),artifacts:{resolveInput:async()=>{throw new U("UNSUPPORTED_OPERATION","screenshot does not resolve input artifacts")},reserveOutput:async e=>{let t,r;return e?.kind==="path"?r=e.path:(t=await n.mkdtemp(o.join(u.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(u.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:w()});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 oH(e){if("object"==typeof e&&null!==e)return{..."string"==typeof e.path?{path:e.path}:{},...Array.isArray(e.overlayRefs)?{overlayRefs:e.overlayRefs}:{}}}let oB=[255,59,48,255],oK=[255,214,10,255],oz=[0,0,0,255],oW={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 oJ(e){let t=tr(await n.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)oX(r)&&o2(r.rect)&&(!t||o3(r.rect)>o3(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&&o2(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 o2(e.rect)&&!("image"===tf((t=e).type??"")&&!oY(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(oQ)||o0(e.identifier);return oZ(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 oZ(e)&&!oX(e)}(t)&&o2(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(oZ(t)&&!oX(t)&&o2(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&o2(r.rect))return r;if(t.hittable&&o2(t.rect)&&!oX(t))return t;let a=tn(e,t);return a?.rect&&o2(a.rect)&&!oX(a)?a:null}(e.nodes,a);if(!o?.rect||!o2(o.rect))continue;let s=function(e,t,r){let a=o1(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=o1(a);if(!i)continue;let n=function(e){let t=0;return tf(e.type??"").includes("text")&&(t+=2),oQ(e.label)&&(t+=2),oQ(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(o1(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),oZ(t)&&(a+=3),oZ(e)&&(a+=2),r&&(a+=2),o0(t.identifier)&&(a+=1),oY(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return o4({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 o4({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(!o2(d))continue;let c=n.get(o.ref);(!c||l>c.score)&&n.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:d,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>o3(e.overlayRect)-o3(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(o8(e.overlayRect,r.overlayRect)||o8(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}o3(r.overlayRect)<o3(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:o5(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:o5(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)o6(e,t.x,t.x+t.width-1,t.y+a,r),o6(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),o7(e,t.x+a,t.y,t.y+t.height-1,r),o7(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,oB),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=o9(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:o9(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)se(e,t+o,r+n,i)})(e,i,o,a,oK),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=oW[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]&&se(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,oz)}(a,i.overlayRect,i.ref)}return await n.writeFile(e.screenshotPath,m.sync.write(t)),r}function oZ(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 oX(e){let t=[e.type,e.role,e.subrole].map(e=>tf(e??"")).join(" ");return t.includes("application")||t.includes("window")}function oY(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function oQ(e){var t;let r;return!!oY(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function o0(e){var t;return"string"==typeof e&&!!oQ(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function o1(e){let t=[e.label,e.value].find(oQ);return t?t.trim():o0(e.identifier)?e.identifier.trim():void 0}function o2(e){return!!(e&&e.width>0&&e.height>0)}function o3(e){return e.width*e.height}function o8(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 o5(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function o4(e,t,r){let a=o9(e.x,0,Math.max(0,t-1)),i=o9(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:o9(e.width,1,n),height:o9(e.height,1,o)}}function o9(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function o6(e,t,r,a,i){for(let n=t;n<=r;n+=1)se(e,n,a,i)}function o7(e,t,r,a,i){for(let n=r;n<=a;n+=1)se(e,t,n,i)}function se(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 st=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),sr=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),sa=new Set(sr),si=new Map;function sn(e,t,r,a){let i=k().requestId;return{...ek(e,t,r,a,i),requestId:i}}async function so(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||rJ(e.flags))try{let t=await es(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function ss(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await oU({req:t,leaseRegistry:n});if(l)return l;let d=await nf({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(d)return d;let c=await Y({req:t,sessionName:r,logPath:a,sessionStore:i});if(c)return c;let u=await n9({req:t,sessionName:r,sessionStore:i,logPath:a});if(u)return u;let f=await np({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await o$({req:t,sessionName:r,logPath:a,sessionStore:i,contextFromFlags:s});return p||null}async function sl(e){var t,r;let a,i,n,o,s,l,d,{req:c,session:u,logPath:f,sessionStore:p}=e,m=c.command;if(!e0(m,u.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${m} is not supported on this device`}};if("android"===u.device.platform&&u.recording&&"record"!==m&&"failed"===await oP({session:u}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:h,resolvedOut:g,recordedPositionals:w,recordedFlags:v}=(a=(t=c).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,d="screenshot"===a&&s?{...t.flags??{},out:s}:t.flags??{},{resolvedPositionals:o,resolvedOut:s,recordedPositionals:l,recordedFlags:d}),y=Date.now(),I={...sn(f,c.flags,u.appBundleId,u.trace?.outPath),surface:u.surface},S="screenshot"===m?await oq({session:u,sessionName:e.sessionName,outPath:h[0]??g,outputPlacement:"screenshot"!==(r=c).command?"default":(r.positionals??[])[0]?"positional":r.flags?.out?"out":"default",dispatchContext:I}):await W(u.device,m,h,g,{...I});return"screenshot"===m&&c.flags?.overlayRefs&&"string"==typeof S?.path&&await sd(u,S,f),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:i,recordedPositionals:n,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:d,flags:c}=e,u=function(e,t,r,a){if("scroll"!==t)return a;let i=oe(e.snapshot),n={...a??{}},o=oo(n.direction)??oo(r[0]);if(!o)return a;let s=os(n.amount)??os(r[1]),l=os(n.pixels),d=oc(n,[]),c=os(n.referenceWidth),u=os(n.referenceHeight),f=void 0!==c&&c>0&&void 0!==u&&u>0?{referenceWidth:c,referenceHeight:u}:i??or;if(d&&(d.x1!==d.x2||d.y1!==d.y2))return{...n,x1:d.x1,y1:d.y1,x2:d.x2,y2:d.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250};let p=e4({direction:o,amount:s,pixels:l,referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight});return{...n,x1:p.x1,y1:p.y1,x2:p.x2,y2:p.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==p.pixels?{pixels:p.pixels}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250}}(t,a,i,s);oa(t,a,i,u,c,l,d),r.recordAction(t,{command:a,positionals:n,flags:o,result:s??{}})}({session:u,sessionStore:p,command:m,resolvedPositionals:h,recordedPositionals:w,recordedFlags:v,data:S,actionStartedAt:y,actionFinishedAt:Date.now(),flags:c.flags??{}}),er(m)&&e9(u,m),{ok:!0,data:S??{}}}async function sd(e,t,r){let a=eb(await eD({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=a;let i=await oJ({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}function sc(e){i.existsSync(e)&&i.unlinkSync(e)}function su(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 sf(e){let t=su(e);if(!t||t.pid===process.pid)try{i.existsSync(e)&&i.unlinkSync(e)}catch{}}function sp(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:sm,infoPath:sh,lockPath:sg,logPath:sw,sessionsDir:sv}=b(process.env.AGENT_DEVICE_STATE_DIR),sy=D(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sI=sv;if(i.existsSync(sI))for(let e of i.readdirSync(sI,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=o.join(sI,e.name,tV);if(i.existsSync(t))try{let e=tj(i.readFileSync(t,"utf8"));if(e&&function(e){let t,r=C(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=L(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{tH(t)}}let sS=new tU(sv),sA=new rC({maxActiveSimulatorLeases:sp(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sp(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sp(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sp(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),s_=y(),sb=a.randomBytes(24).toString("hex"),sN=C(process.pid)??void 0,sk=I(),sD=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 _({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:l,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:F(new U("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=A(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=S(r);if(r&&!a)throw new U("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new U("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);P({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let l=r.command,d=oF(r);sr.has(l)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:d.tenantId,runId:d.runId,leaseId:d.leaseId,backend:d.leaseBackend});let c=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),u=sa.has(l)?null:await so(r,c,a),f=async()=>{let e=a.get(c);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=eO(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(c,e));let d=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?oG(t,a):function(e,t,r){var a,i;let n=[],o=e3(t);if(void 0!==e.platform&&o&&(a=e3(e.platform),i=o,a&&i&&a!==i&&("apple"===a?!e2(i):"apple"!==i||!e2(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of oj){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 oj)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new U("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(oV).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),u=e=>(function(e,t,r){let a=k();if(!t.ok){P({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=N({force:!0})??void 0;return{ok:!1,error:F(new U($(t.error.code),t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:a.diagnosticId,logPath:e})}}return P({level:"info",phase:"request_success"}),N(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let s=(a=e,i=t,n=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||n.some(e=>e?.field==="path")||"string"!=typeof i.path||n.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:o.basename(a.meta?.clientArtifactPaths?.path??i.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===s.length?t:{...t,artifacts:s.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(d,e,n);if(e?.recording?.invalidatedReason&&"record"!==l&&"close"!==l)return u({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||d.meta?.lockPolicy||st.has(l)||function(e,t){let r=oG(e,t);if(0!==r.length){var a;let t,i,n;throw new U("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(oV).join(", ")}. Use a different --session name or close this session first.`)}}(e,d.flags);let f=await ss({req:d,sessionName:c,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...sn(t,e,r,i),surface:a.get(c)?.surface})});if(f)return u(f);let p=a.get(c);if(!p)return u({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await sl({req:d,session:p,sessionName:c,logPath:t,sessionStore:a});return u(m)};if(!u)return await f();return await ed(si,u,f)}catch(r){P({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=k(),t=N({force:!0})??void 0;return{ok:!1,error:F(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return s}({logPath:sw,token:sb,sessionStore:sS,leaseRegistry:sA,trackDownloadableArtifact:function(e){let t=a.randomUUID(),r=setTimeout(()=>{ra(t)},9e5);return r.unref(),rr.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){i.existsSync(e)||i.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),n=()=>{try{return i.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(n())return!0;let o=su(t);if(o?.pid&&o.pid!==process.pid&&E(o.pid,o.processStartTime))return!1;try{i.unlinkSync(t)}catch{}return n()}(sm,sg,{pid:process.pid,version:s_,startedAt:Date.now(),processStartTime:sN})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let n;if("socket"===sy||"dual"===sy){let t=h.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))eF(e);P({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await eL(),!(r<=0));)await j(200)}catch(e){P({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async i=>{let n=(t+=i).indexOf("\n");for(;-1!==n;){let i,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=ex(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),ea(o),eM(o))throw et();i=await sD(e)}catch(e){i={ok:!1,error:F(e)}}finally{r-=1,o&&(a.delete(o),eK(o))}e.destroyed||e.write(`${JSON.stringify(i)}
|
|
38
|
-
`),n=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new U("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===sy||"dual"===sy){let e=await rx({handleRequest:sD,token:sb});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 U("COMMAND_FAILED","Failed to bind HTTP server"))})})}a={socketPort:e,httpPort:t,token:sb,version:s_,codeSignature:sk,processStartTime:sN},i.existsSync(sm)||i.mkdirSync(sm,{recursive:!0}),i.writeFileSync(sw,""),n=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",i.writeFileSync(sh,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:sm},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
|
|
39
|
-
`),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
|
|
40
|
-
`)}catch(t){let e=T(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
|
|
41
|
-
`),r))try{t.close(()=>{})}catch{}sc(sh),sf(sg),process.exit(1);return}let n=!1,o=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},s=async()=>{if(!n){for(let e of(n=!0,await o(),sS.toArray()))sS.writeSessionLog(e);await eu(),sc(sh),sf(sg),process.exit(0)}};process.on("SIGINT",()=>{s()}),process.on("SIGTERM",()=>{s()}),process.on("SIGHUP",()=>{s()}),process.on("uncaughtException",e=>{let t=e instanceof U?e:T(e);process.stderr.write(`Daemon error: ${t.message}
|
|
42
|
-
`),s()}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof U?t:T(t);process.stderr.write(`Daemon error: ${r.message}
|
|
43
|
-
`),s()})}();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import e from"node:fs";import{setTimeout as r}from"node:timers/promises";import{normalizeBaseUrl as t,ENV_COMPANION_TUNNEL_BEARER_TOKEN as s,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as n,ENV_COMPANION_TUNNEL_STATE_PATH as o,ENV_COMPANION_TUNNEL_LAUNCH_URL as a,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as i,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as c,ENV_COMPANION_TUNNEL_DEVICE_PORT as l,METRO_COMPANION_RUN_ARG as f,ENV_COMPANION_TUNNEL_SESSION as d,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as u,ENV_COMPANION_TUNNEL_REGISTER_PATH as m,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as p,REACT_DEVTOOLS_COMPANION_RUN_ARG as g,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as y}from"./2301.js";function w(e,r){return{authorization:`Bearer ${r}`,"content-type":"application/json",...e.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}}function h(e){return{...e.bridgeScope,...e.session?{session:e.session}:{},local_base_url:t(e.localBaseUrl),...e.devicePort?{device_port:e.devicePort}:{},...e.launchUrl?{launch_url:e.launchUrl}:{}}}async function b(e){let r,s,n=e.registerPath;try{r=await fetch(`${t(e.serverBaseUrl)}${n}`,{method:"POST",headers:w(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(h(e)),signal:AbortSignal.timeout(5e3)})}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw Error(`${n} timed out after 5000ms calling ${t(e.serverBaseUrl)}${n}`);throw r}let o=await r.text();try{s=o?JSON.parse(o):{}}catch{let e;throw Error(`Failed to register companion (${r.status}): invalid JSON response: ${(e=o.replaceAll(/\s+/g," ").trim()).length>300?`${e.slice(0,300)}...`:e}`)}if(!r.ok||!0!==s.ok||"string"!=typeof s.data?.ws_url)throw Error(`Failed to register companion (${r.status}): ${JSON.stringify(s)}`);return{wsUrl:s.data.ws_url}}async function S(e){let r=e.unregisterPath??null;if(r)try{await fetch(`${t(e.serverBaseUrl)}${r}`,{method:"POST",headers:w(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(h(e)),signal:AbortSignal.timeout(2e3)})}catch(e){console.error(e instanceof Error?e.message:String(e))}}async function v(e){return"string"==typeof e?Buffer.from(e,"utf8"):e instanceof ArrayBuffer?Buffer.from(e):ArrayBuffer.isView(e)?Buffer.from(e.buffer,e.byteOffset,e.byteLength):"u">typeof Blob&&e instanceof Blob?Buffer.from(await e.arrayBuffer()):Buffer.from(String(e),"utf8")}async function E(e){return JSON.parse((await v(e.data)).toString("utf8"))}function I(e,r){1===e.readyState&&e.send(JSON.stringify(r))}async function B(e,r){1!==e.readyState&&await new Promise((t,s)=>{let n=()=>{i(),t()},o=()=>{i(),s(Error(`${r} WebSocket failed before opening.`))},a=()=>{i(),s(Error(`${r} WebSocket closed before opening.`))},i=()=>{e.removeEventListener("open",n),e.removeEventListener("error",o),e.removeEventListener("close",a)};e.addEventListener("open",n,{once:!0}),e.addEventListener("error",o,{once:!0}),e.addEventListener("close",a,{once:!0})})}async function k(e){e.readyState>=WebSocket.CLOSING||await new Promise(r=>{let t=()=>{s(),r()},s=()=>{e.removeEventListener("close",t),e.removeEventListener("error",t)};e.addEventListener("close",t,{once:!0}),e.addEventListener("error",t,{once:!0}),e.readyState>=WebSocket.CLOSING&&t()})}function L(e,r,t){try{e.close(1e3===r||r>=3e3&&r<=4999?r:3001,t)}catch{}}function U(r){return!r.statePath||e.existsSync(r.statePath)}async function $(e,r,s,n){var o,a;switch(r.type){case"ping":return void I(e,{type:"pong",timestamp:r.timestamp});case"http-request":try{let n=await fetch(new URL(r.path,`${t(s.localBaseUrl)}/`),{method:r.method,headers:r.headers,...r.bodyBase64?{body:Buffer.from(r.bodyBase64,"base64")}:{}}),o=Buffer.from(await n.arrayBuffer());I(e,{type:"http-response",requestId:r.requestId,status:n.status,headers:Object.fromEntries(n.headers.entries()),...o.length>0?{bodyBase64:o.toString("base64")}:{}})}catch(t){I(e,{type:"http-error",requestId:r.requestId,message:t instanceof Error?t.message:String(t)})}return;case"ws-open":{let a,i=new WebSocket((o=s.localBaseUrl,(a=new URL(r.path,`${t(o)}/`)).protocol="https:"===a.protocol?"wss:":"ws:",a.toString()));i.binaryType="arraybuffer";let c=!1;i.addEventListener("message",t=>{(async()=>{if(!c)return;let s=await v(t.data);I(e,{type:"ws-frame",streamId:r.streamId,dataBase64:s.toString("base64"),binary:"string"!=typeof t.data})})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),i.addEventListener("close",t=>{n.delete(r.streamId),c&&I(e,{type:"ws-close",streamId:r.streamId,code:t.code,reason:t.reason})}),i.addEventListener("error",()=>{c&&I(e,{type:"ws-close",streamId:r.streamId,code:1011,reason:"Upstream WebSocket error."})}),n.set(r.streamId,i);try{await B(i,"Upstream"),c=!0,I(e,{type:"ws-open-result",streamId:r.streamId,success:!0,headers:{}})}catch(t){n.delete(r.streamId),L(i,1011,"open failed"),I(e,{type:"ws-open-result",streamId:r.streamId,success:!1,error:t instanceof Error?t.message:String(t)})}return}case"ws-frame":{let e=n.get(r.streamId);if(!e||1!==e.readyState)return;let t=Buffer.from(r.dataBase64,"base64");e.send(r.binary?t:t.toString("utf8"));return}case"ws-close":{let e=n.get(r.streamId);if(!e)return;n.delete(r.streamId),L(e,"number"==typeof(a=r.code)&&Number.isInteger(a)&&(1e3===a||a>=3e3&&a<=4999||a>=1001&&a<=1015&&1004!==a&&1005!==a&&1006!==a)?a:1011,r.reason??"bridge requested close");return}}}async function N(e){let t=new Map,s=!1,n=null,o=!1,a=()=>{s||(s=!0,o&&S(e).finally(()=>process.exit(0)),n&&L(n,1e3,"companion stopping"),setTimeout(()=>process.exit(0),900).unref())};process.once("SIGTERM",a),process.once("SIGINT",a);let i=setInterval(()=>{U(e)||process.exit(0)},250);for(i.unref();!s&&U(e);){let a=!1;try{o=!1;let r=await b(e);if(a=!0,o=!0,s||!U(e)){await S(e),a=!1,o=!1;break}let i=new WebSocket(r.wsUrl);n=i,i.binaryType="arraybuffer";try{await B(i,"Bridge"),i.addEventListener("message",r=>{(async()=>{let s=await E(r);await $(i,s,e,t)})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),await k(i)}finally{n=null,o=!1,t.forEach(e=>L(e,1012,"bridge disconnected")),t.clear(),a&&(await S(e),a=!1)}}catch(r){if(n=null,o=!1,a&&(await S(e),a=!1),s||!U(e))break;console.error(r instanceof Error?r.message:String(r))}if(s||!U(e))break;await r(1e3)}clearInterval(i)}(async function(e,r){let t=function(e,r){let t=e[0];if(t!==f&&t!==g)return null;let w=r[n]?.trim(),h=r[s]?.trim(),b=r[p]?.trim();if(!w||!h||!b)throw Error("Companion tunnel worker is missing required environment configuration.");let S=r[c]?.trim(),v=r[u]?.trim(),E=r[i]?.trim();if(!S||!v||!E)throw Error("Companion tunnel worker is missing required bridge scope configuration.");let I=r[m]?.trim();if(!I)throw Error("Companion tunnel worker is missing required register path configuration.");return{serverBaseUrl:w,bearerToken:h,localBaseUrl:b,registerPath:I,bridgeScope:{tenantId:S,runId:v,leaseId:E},launchUrl:r[a]?.trim()||void 0,statePath:r[o]?.trim()||void 0,unregisterPath:r[y]?.trim()||void 0,devicePort:function(e){if(!e?.trim())return;let r=Number.parseInt(e,10);if(!Number.isInteger(r)||r<1||r>65535)throw Error("Companion worker received invalid device port configuration.");return r}(r[l]),session:r[d]?.trim()||void 0}}(e,r);return!!t&&(await N(t),!0)})(process.argv.slice(2),process.env).catch(e=>{if(e instanceof Error&&e.message.includes("missing required environment")){console.error(e.message),process.exitCode=1;return}console.error(e instanceof Error?e.stack??e.message:String(e)),process.exitCode=1});
|