agent-device 0.11.16 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/src/155.js +34 -34
- package/dist/src/818.js +1 -1
- package/dist/src/974.js +2 -2
- package/dist/src/bin.js +30 -31
- package/dist/src/daemon.js +15 -15
- package/dist/src/index.d.ts +9 -168
- package/dist/src/index.js +3 -3
- package/dist/src/metro.js +1 -1
- package/package.json +1 -17
- package/skills/agent-device/SKILL.md +1 -1
- package/skills/agent-device/references/exploration.md +19 -5
- package/skills/agent-device/references/macos-desktop.md +1 -0
- package/dist/src/164.js +0 -1
- package/dist/src/556.js +0 -1
- package/dist/src/940.js +0 -1
- package/dist/src/artifacts.d.ts +0 -3
- package/dist/src/artifacts.js +0 -1
- package/dist/src/finders.d.ts +0 -75
- package/dist/src/finders.js +0 -1
- package/dist/src/install-source.d.ts +0 -40
- package/dist/src/install-source.js +0 -1
- package/dist/src/selectors.d.ts +0 -110
- package/dist/src/selectors.js +0 -1
package/dist/src/daemon.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
let e,t;import r from"node:crypto";import a,{promises as i}from"node:fs";import n from"node:path";import{spawn as o}from"node:child_process";import s from"node:http";import{fileURLToPath as l,pathToFileURL as d}from"node:url";import"node:https";import u from"node:os";import c from"node:fs/promises";import{setTimeout as f}from"node:timers/promises";import{PNG as p}from"pngjs";import m from"node:net";import{resolveAppleSimulatorSetPathForSelector as h,buildSimctlArgs as g,dispatchCommand as w,isNodeVisibleInEffectiveViewport as v,isAgentDeviceDaemonProcess as y,handleSnapshotCommands as I,isNodeEditable as S,resolveSelectorChain as A,registerRequestAbort as b,resolveSessionIsolationMode as _,errorResponse as N,pickLargestRect as x,successText as
|
|
2
|
-
`}(e,this.buildOptimizedActions(e));a.writeFileSync(t,i)}catch{}}defaultTracePath(e){let t=
|
|
3
|
-
`)}function
|
|
4
|
-
`)},flush:()=>{a&&(i(a),a="")}}}function
|
|
5
|
-
`,recoveredLineCount:s.length}}async function t2(e,t,r,a,i,n){let s="active",l=o("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return g(["spawn",t,"log","stream","--style","compact","--level","info","--predicate",t0(r)],{simulatorSetPath:a})}({deviceId:e,appBundleId:t,simulatorSetPath:i}),{stdio:["ignore","pipe","pipe"]}),d=tW(r,{redactionPatterns:a});"number"==typeof l.pid&&tB(n,l.pid);let u=tJ(l,r,{endStreamOnClose:!0,writer:d}).then(e=>(0!==e.exitCode&&(s="failed"),tH(n),e));return{backend:"ios-simulator",getState:()=>s,startedAt:Date.now(),wait:u,stop:async()=>{l.killed||l.kill("SIGINT"),await tK(u),l.killed||l.kill("SIGKILL"),await tK(u),tH(n)}}}async function t5(e,t,r,a){let i="active",n=o("log",["stream","--style","compact","--predicate",t0(e)],{stdio:["ignore","pipe","pipe"]}),s=tW(t,{redactionPatterns:r});"number"==typeof n.pid&&tB(a,n.pid);let l=tJ(n,t,{endStreamOnClose:!0,writer:s}).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 tK(l),n.killed||n.kill("SIGKILL"),await tK(l),tH(a)}}}async function t4(e,t,r,a){let i="active",n=o("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),s=tW(t,{redactionPatterns:r});"number"==typeof n.pid&&tB(a,n.pid);let l=tJ(n,t,{endStreamOnClose:!0,writer:s}).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 tK(l),n.killed||n.kill("SIGKILL"),await tK(l),tH(a)}}}let t3=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),t8=/https?:\/\/[^\s"'<>\])]+/i,t6=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function t9(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>re(e)));for(let e of t.entries){let t=re(e);if(!i.has(t)&&(i.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function t7(e,t){let r=ru(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=ru(t?.maxPayloadChars,2048,64,16384),o=ru(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),d=s.slice(l),u=[];for(let e=d.length-1;e>=0&&u.length<r;e-=1){let t=d[e];if(!t?.trim())continue;let r=function(e,t,r,a,i,n){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=ro(s,["method","httpMethod"]),d=ro(s,["url","requestUrl"]),u=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=t3.exec(o),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=t8.exec(o),h=d??m?.[0];if(!h)return null;let g=u??rr(o)??void 0;if(!(l||f?.[1]||c?.[1]||void 0!==g||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let w={method:p,url:h,status:g,timestamp:ra(o),packetId:ri(o)??void 0,durationMs:rn(o)??void 0,raw:rd(o,n),line:r};if("android"===a&&function(e,t,r){let a=rt(t,r,5),i=e.packetId??a.map(e=>ri(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?rt(t,r,12).filter(e=>ri(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>ra(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>rr(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>rn(e)).find(e=>"number"==typeof e))}(w,e,t),"headers"===i||"all"===i){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return rl(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(w.headers=rd(e,n))}if("body"===i||"all"===i){let e=rs(o,s,["requestBody","body","payload","request"]),t=rs(o,s,["responseBody","response"]);e&&(w.requestBody=rd(e,n)),t&&(w.responseBody=rd(t,n))}return w}(d,e,l+e+1,a,i,n);r&&u.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:d.length,matchedLines:u.length,entries:u,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:o}}}function re(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function rt(e,t,r){let a=[],i=Math.max(0,t-r),n=Math.min(e.length-1,t+r);for(let t=i;t<=n;t+=1){let r=e[t]?.trim();r&&a.push(r)}return a}function rr(e){for(let t of t6){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function ra(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function ri(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function rn(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function ro(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function rs(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return rl(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function rl(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function rd(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function ru(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function rc(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 rf(e){let t=n.dirname(e);a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),function(e,t){if(a.existsSync(e)&&!(a.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,i=`${e}.${r}`;a.existsSync(t)&&(a.existsSync(i)&&a.unlinkSync(i),a.renameSync(t,i))}}(e,{maxBytes:rc("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rc("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rp(e){var t,r,i,n;let o,s,l,d,{device:u,appBundleId:c,appLogState:f,appLogStartedAt:p,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v}=e,y="macos"===u.platform?"macos":"ios"===u.platform?"device"===u.kind?"ios-device":"ios-simulator":"android",I=(t={backend:y,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v},o=ru(t?.maxEntries,25,1,200),s=t?.include??"summary",l=ru(t?.maxPayloadChars,2048,64,16384),d=ru(t?.maxScanLines,4e3,100,2e4),a.existsSync(m)?t7(a.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:s,limits:{maxEntries:o,maxPayloadChars:l,maxScanLines:d}}),S=[],A=await rm({device:u,appBundleId:c,appLogPath:m,appLogState:f});if(A){let e=await tX(u.id,c);if(e){let t=t7(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v});t.entries.length>0&&(I=t9(t,I,h),S.push((r=A,i=e.recoveredPids,"stale-active"===r.reason?`Session app log stream was still bound to prior Android PID ${r.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${i.join(", ")}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${i.join(", ")}.`)))}}if("ios"===u.platform&&"simulator"===u.kind&&c&&0===I.entries.length){let e=await rg({deviceId:u.id,appBundleId:c,startedAt:p,simulatorSetPath:u.simulatorSetPath,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v});e&&(e.dump.entries.length>0?(I=t9(e.dump,I,h),S.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&S.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===f?S.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==f&&0===S.length&&("ios"===u.platform&&"simulator"===u.kind?S.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):S.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===I.entries.length&&S.push("ios"===(n=u).platform&&"simulator"===n.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===n.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:y,dump:I,notes:S}}async function rm(e){let{device:t,appBundleId:r,appLogPath:i,appLogState:o}=e;if("android"!==t.platform||!r)return null;if(void 0!==o&&"active"!==o)return{reason:"inactive"};if("active"!==o)return null;let s=function(e){let t=function(e){if(!e||!a.existsSync(e))return null;try{return tj(a.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}(n.join(n.dirname(i),tq));if(!s)return null;let l=await tY(t.id,r);return l&&l!==s?{reason:"stale-active",trackedPid:s}:null}async function rh(e,t,r,i){rf(r);let n=a.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 t4(e.id,n,o,i):await t2(e.id,t,n,o,e.simulatorSetPath,i);if("android"===e.platform)return tZ(t),await tQ(e.id,t,n,o,i);if("macos"===e.platform)return await t5(t,n,o,i);throw n.end(),new tI("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rg(e){let t=await t1({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:t7(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 rw(e){await e.stop(),await tK(e.wait)}async function rv(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 tw("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await tw("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 tw("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 tw("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await tw("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function ry(e){let t=n.dirname(e),r=n.basename(e);a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),a.existsSync(e)?a.truncateSync(e,0):a.writeFileSync(e,"","utf8");let i=0;for(let e of a.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let o=e.slice(r.length+1);if(/^\d+$/.test(o))try{a.unlinkSync(n.join(t,e)),i+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:i}}let rI=new Map;function rS(e){let t=rI.get(e);if(t&&(clearTimeout(t.timer),rI.delete(e),t.deleteAfterDownload))try{a.rmSync(t.artifactPath,{force:!0})}catch{}}let rA=new Map;function rb(e,t){let r=rA.get(e);if(!r)throw new tI("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tI("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function r_(e){let t=rA.get(e);t&&(clearTimeout(t.timer),rA.delete(e),a.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rN(e){let t=await rx(e);await tw("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=n.join(e.tempDir,t);if(!a.existsSync(r))throw new tI("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rx(e){let t=await tw("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new tI("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 tI("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rM),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 tI("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new tI("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 tI("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 tI("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 tI("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await tw("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new tI("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rM(e){if(e.includes("\0"))throw new tI("INVALID_ARGS",`Invalid archive entry: ${e}`);if(n.posix.isAbsolute(e))throw new tI("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=n.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new tI("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rk=eW(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rD(e,t){return new Promise((r,i)=>{let n,o=a.createWriteStream(t),s=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,u=e=>{if(!l){if(l=!0,n&&clearTimeout(n),e){o.destroy(),a.rmSync(t,{force:!0}),i(e);return}r()}},c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let e=new tI("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rk});s(e),o.destroy(e),u(e)},rk)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new tI("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");s(e),o.destroy(e),u(e)}}),e.on("error",u),e.on("aborted",()=>{u(new tI("COMMAND_FAILED","Artifact transfer was interrupted"))}),o.on("error",u),o.on("finish",()=>u()),c(),e.pipe(o)})}async function rP(e){let t,r=e.headers["x-artifact-type"],i=e.headers["x-artifact-filename"];if(!r||!i)throw new tI("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new tI("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 tI("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let o=function(e){let t=e.trim(),r=n.basename(t);if(!r||"."===r||".."===r)throw new tI("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(i),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"),a.mkdtempSync(n.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=n.join(s,o);return await rD(e,t),{artifactPath:t,tempDir:s}}let t=n.join(s,"artifact.tar");await rD(e,t);let i=await rN({archivePath:t,tempDir:s,platform:"ios",expectedRootName:o});return a.rmSync(t,{force:!0}),{artifactPath:i,tempDir:s}}catch(e){throw a.rmSync(s,{recursive:!0,force:!0}),e}}let rL=new Set(["agent_device.command","agent-device.command"]),rR=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rO=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rE={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},rC=new Set([...rL,...rR,...rO,...Object.keys(rE)]);function r$(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rT(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rF(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rU(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,i="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??i??a??""}function rG(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rV(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rq(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=ty(new tI("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=ty(new tI(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=eK(r.tenantId);if(!e){let e=ty(new tI("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:r$(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rj(){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=n.isAbsolute(t)?t:n.resolve(t);try{e=await import(d(a).href)}catch(e){throw new tI("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 tI("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rB(e){let t=await rj(),{handleRequest:r,token:a}=e;return s.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 rH(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rK(e,i,t,a);if("POST"!==e.method||"/rpc"!==e.url){i.statusCode=404,i.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{i.headersSent||rT(i,r$(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rT(i,r$(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rT(i,r$(a.id??null,-32600,"Invalid Request"),400);if(!rC.has(a.method))return void rT(i,r$(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rT(i,r$(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rL.has(e))return{token:rU(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(rR.has(e)){let e,a=rG(t,"platform");if("ios"!==a&&"android"!==a)throw new tI("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rU(t,r),session:rG(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rG(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new tI("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new tI("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 tI("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 tI("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 tI("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new tI("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rV(t,"retentionMs")}}}if(rO.has(e)){let e=rG(t,"materializationId")?.trim();if(!e)throw new tI("INVALID_ARGS","Invalid params: materializationId is required");return{token:rU(t,r),session:rG(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rG(t,"requestId"),materializationId:e}}}let a=rE[e];if(a)return{token:rU(t,r),session:rG(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rG(t,"tenantId")??rG(t,"tenant"),runId:rG(t,"runId"),leaseId:rG(t,"leaseId"),leaseTtlMs:rV(t,"ttlMs"),leaseBackend:rG(t,"backend")}};throw new tI("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rL.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rT(i,r$(a.id??null,-32602,"Invalid params: command is required"),400);o=U(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},b(o);let d=()=>{i.writableFinished||e4(o)};e.on("aborted",d),i.on("close",d);let u=await rq(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rT(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rT(i,{jsonrpc:"2.0",id:a.id??null,result:c});rT(i,r$(a.id??null,-32e3,c.error.message,c.error),rF(c.error.code))}catch(t){let e=ty(t);rT(i,r$(a.id??null,-32e3,e.message,e),rF(e.code))}finally{K(o)}})})}async function rH(e,t,a,i){try{var n;let o,s,l=rU({},e.headers),d=rz(l,i);if(d){t.statusCode=rF(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await rq(a,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await rP(e),f=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},o=r.randomUUID(),(s=setTimeout(()=>{r_(o)},3e5)).unref(),rA.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=ty(r);t.statusCode=rF(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rK(e,t,r,i){let n=e.url?.slice("/upload/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let o=rU({},e.headers),s=rz(o,i);if(s){t.statusCode=rF(s.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.message,code:s.code}));return}let l=await rq(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:o,session:"default",command:"download_artifact",positionals:[n]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let d=function(e,t){let r=rI.get(e);if(!r)throw new tI("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tI("UNAUTHORIZED","Artifact belongs to a different tenant");if(!a.existsSync(r.artifactPath))throw rS(e),new tI("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),u=a.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=ty(e);t.statusCode=rF(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rS(n)}),u.pipe(t)}catch(r){let e=ty(r);t.statusCode=rF(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rz(e,t){return t&&e!==t?ty(new tI("UNAUTHORIZED","Invalid token")):null}function rW(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rJ(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rZ(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new tI("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rY{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=rZ(e.backend),a=eK(e.tenantId);if(!a)throw new tI("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=rW(e.runId);if(!i)throw new tI("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(a,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:r.randomBytes(16).toString("hex"),tenantId:a,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=rJ(e.leaseId);if(!t)throw new tI("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new tI("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=rJ(e.leaseId);if(!t)throw new tI("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=rZ(e.backend),r=eK(e.tenantId);if(!r)throw new tI("INVALID_ARGS","tenant isolation requires tenant id.");let a=rW(e.runId);if(!a)throw new tI("INVALID_ARGS","tenant isolation requires run id.");let i=rJ(e.leaseId);if(!i)throw new tI("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new tI("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new tI("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 tI("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 tI("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=eK(t),i=rW(r);if(t&&!a)throw new tI("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new tI("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 tI("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rX=eW(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),rQ=new Map;async function r0(e){let t=await c.mkdtemp(n.join(u.tmpdir(),"agent-device-materialized-"));try{let a=await r5(e.installablePath,n.join(t,"installable")),i=e.archivePath?await r5(e.archivePath,n.join(t,"archive")):void 0,o=r.randomUUID(),s=e.ttlMs??rX,l=Date.now()+s,d=setTimeout(()=>{r1(o)},s);return rQ.set(o,{rootPath:t,installablePath:a,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:l,timer:d}),{materializationId:o,installablePath:a,...i?{archivePath:i}:{},expiresAt:new Date(l).toISOString()}}catch(e){throw await c.rm(t,{recursive:!0,force:!0}),e}}async function r1(e,t){let r=rQ.get(e);if(!r)throw new tI("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tI("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),rQ.delete(e),await c.rm(r.rootPath,{recursive:!0,force:!0})}async function r2(e){let t=Array.from(rQ.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await r1(e)}))}async function r5(e,t){let r=await c.stat(e);await c.mkdir(t,{recursive:!0});let a=n.join(t,n.basename(e));return r.isDirectory()?await c.cp(e,a,{recursive:!0}):await c.copyFile(e,a),a}async function r4(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new tI("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await e9(e.session.device),e.session.device}if(!r)throw new tI("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await eR(e.flags??{});return await e9(a),a}async function r3(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 tI("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new tI("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new tI("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:rb(o,t.meta?.tenantId)},cleanup:()=>{r_(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 tI("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await r4({session:i,flags:t.flags});if(!tl("install",d))return N("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let u=th(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await import("./155.js"),{prepareIosInstallArtifact:o}=await import("./155.js"),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await r0({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(d,c.installablePath),!c.bundleId)throw new tI("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=ev(o,r8(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await r1(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await import("./155.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("./155.js"),p=await c(s.source,{signal:u});try{l.enabled&&(e=await r0({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 tI("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await import("./155.js"),s=o(n),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=ev(u,r8(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await r1(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:ty(e)}}}function r8(e){return`Installed: ${ee(e)}`}async function r6(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new tI("INVALID_ARGS","release_materialized_paths requires a materializationId");return await r1(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:ty(e)}}}let r9=eW(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),r7=eW(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function ae(e,t,r){return t||at(r)?null:N("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function at(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function ar(e){return"ios"===e.platform&&"simulator"===e.kind}async function aa(e,t){ar(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function ai(e){let t=at(e.flags)||!e.session?await eR(e.flags??{}):await an(e.session.device);return!1!==e.ensureReady&&await e9(t),t}async function an(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 eR(t)}catch(e){if(!(e instanceof tI)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await eR({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function ao(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 as=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function al(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function ad(e){let t=e?.trim();return t&&t.length>0?t:void 0}function au(e,t){if(void 0!==e){if("string"!=typeof e)throw new tI("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return ad(e)}}function ac(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new tI("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function af(e){if("ios"===e||"android"===e)return e}async function ap(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!em(r)||em(a)||await eG({device:i.device,appId:i.appBundleId})}async function am(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 N("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){em(l)&&s?.appBundleId&&await eG({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=af(tf(a.flags?.platform)??l?.platform??s?.device.platform);if(!d)return N("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 N("INVALID_ARGS",`runtime set targets ${d}, but session "${i}" is already bound to ${s.device.platform}.`);let u={platform:(t=a.flags,r={platform:d,metroHost:ad(t?.metroHost),metroPort:ac(t?.metroPort),bundleUrl:ad(t?.bundleUrl),launchUrl:ad(t?.launchUrl)}).platform??l?.platform,metroHost:r.metroHost??l?.metroHost,metroPort:r.metroPort??l?.metroPort,bundleUrl:r.bundleUrl??l?.bundleUrl,launchUrl:r.launchUrl??l?.launchUrl};return 0===al(u)?N("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(n.setRuntimeHints(i,u),{ok:!0,data:{session:i,configured:!0,runtime:u}})}let ah="open-command-roundtrip",ag="Not implemented for this platform in this release.",aw=new Set(["app","desktop","frontmost-app"]);async function av(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await tn();return{appBundleId:t.bundleId,appName:t.appName}}async function ay(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return eU(t)?"macos"===e.platform?void 0:"device"===e.kind?e3(r,t):void 0:await aI(e,t)}async function aI(e,t){try{let{resolveIosApp:r}=await import("./155.js");return await r(e,t)}catch{return}}async function aS(e,t){if(!("android"!==e.platform||!t||eU(t)))try{let{resolveAndroidApp:r}=await import("./155.js"),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function aA(e,t,r,a){return await ay(e,t,r)??await a(e,t)??("android"===e.platform&&t&&eU(t)?r:void 0)}function ab(e){return N("INVALID_ARGS",e)}function a_(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=ed(r);if(!aw.has(e))throw new tI("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new tI("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new tI("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let n=r?ed(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new tI("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return N(e instanceof tI?e.code:"INVALID_ARGS",String(e.message))}}function aN(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&eU(r)?ab("open --relaunch does not support URL targets."):"app"!==a?ab("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===e$(r)?ab(q(r)):null:null}async function ax(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await e9(i);let{appBundleId:l,appName:d}=await aM({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),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 tI("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!as.includes(e));if(i)throw new tI("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${as.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new tI("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new tI("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:au(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new tI("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return ac(e)}}(t.metroPort),bundleUrl:au(t.bundleUrl,"bundleUrl"),launchUrl:au(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:af(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=af(i);if(a.platform&&r&&!n)throw new tI("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 tI("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&al(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=tv(t);return N(e.code,e.message,e.details)}}({req:t,sessionStore:a,sessionName:r,device:i});if(!u.ok)return{type:"response",response:u};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await ap({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function aM(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await av(r);return{appBundleId:n.appBundleId??await aA(t,a,i,aS),appName:n.appName??a}}let ak=new Map;async function aD(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await eI(t.id),await w(t,"close",[r],a,i),await aa(t,r9)}async function aP(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||eU(d)||await w(r,"open",[l],a.flags?.out,{...eV(i,a.flags,n,o)})}async function aL(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:f,appBundleId:p,runtime:m,existingSession:h}=e,g=i.flags?.relaunch===!0,v=h?.trace?.outPath;if(g&&d){let e=p??d;await aD({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...eV(s,i.flags,p??h?.appBundleId,v)}})}await eL({device:l,appId:p,runtime:m});let y=Date.now();await w(l,"open",u,i.flags?.out,{...eV(s,i.flags,p)}),await aP({runtime:m,device:l,req:i,logPath:s,appBundleId:p,traceLogPath:v,openPositionals:u});let I=d?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:ah,appTarget:d,appBundleId:p}:void 0;if(await aa(l,r7),F(i.meta?.requestId)){let e=eA();return N(e.code,e.message,e.details)}h&&tm(h,"open",h.snapshot);let S=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:n,device:l,surface:f,appBundleId:p,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===al(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let A=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,...M(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:p,surface:f,startup:I,device:l,runtime:m,runtimeHintCount:al});return o.recordAction(S,{command:"open",positionals:u,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:A}),o.set(n,S),{ok:!0,data:A}}async function aR(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return N("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=a_(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?ab("open --relaunch requires an app name or an active session app."):ab("Session already active. Close it first or pass a new --session name.");let d=aN({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await an(e.device),c=await ax({req:t,sessionName:r,sessionStore:i,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await aL({req:t,sessionName:r,sessionStore:i,logPath:a,device:u,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return ab("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&eU(r)?ab("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===e$(r)?ab(q(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await eR(t.flags??{}),d=a_(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=aN({shouldRelaunch:n,openTarget:o,surface:d,device:l});return u||await D(ak,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return N("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name});let n=await ax({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:o});return"response"===n.type?n.response:await aL({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 aO(e){let t=await tw("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 aE(e){let{device:t,shutdownRequested:r}=e;if(r&&(ar(t)||"android"===t.platform&&"emulator"===t.kind))try{return ar(t)?await ey(t):await aO(t)}catch(t){let e=ty(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function aC(e){if(await eI(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await eF("dismiss",t).catch(t=>{ti({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function a$(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return N("SESSION_NOT_FOUND","No active session");n.appLog&&await rw(n.appLog),t.positionals&&t.positionals.length>0&&(("ios"===n.device.platform||"macos"===n.device.platform)&&await aC(n),await w(n.device,"close",t.positionals,t.flags?.out,{...eV(a,t.flags,n.appBundleId,n.trace?.outPath)}),await aa(n.device,r9)),("ios"===n.device.platform||"macos"===n.device.platform)&&await aC(n),em(i.getRuntimeHints(r))&&n.appBundleId&&await eG({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...M(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await r2(r).catch(()=>{}),i.delete(r);let o=await aE({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:ev({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...M(`Closed: ${r}`)}}}let aT=["platform","target","device","udid","serial","verbose","out"];function aF(e,t){let r=e??{};for(let e of aT)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let aU={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await import("./155.js");return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await import("./155.js");return await a(e,t,r)}},aG={ios:async(e,t,r)=>{let{installIosApp:a}=await import("./155.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("./155.js"),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function aV(e){let{req:t,command:r,sessionName:i,sessionStore:n,deployOps:o}=e,s=n.get(i),l=t.flags??{},d=ae(r,s,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return N("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let f=t.meta?.uploadedArtifactId;try{var p;let e,i=f?rb(f,t.meta?.tenantId):tG.expandHome(c);if(!a.existsSync(i))return N("INVALID_ARGS",`App binary not found: ${i}`);let d=await ai({session:s,flags:l,ensureReady:!1});if(!tl(r,d))return N("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await o.ios(d,u,i),r=t.bundleId;e=r?{app:u,appPath:i,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:i,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await o.android(d,u,i),r=t.package;e=r?{app:u,appPath:i,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:i,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=ev(e,(p=e,`Installed: ${p.appName??eh(p)}`));return s&&n.recordAction(s,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&r_(f)}}async function aq(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return N("INVALID_ARGS",`Unsupported batch on-error mode: ${a}.`);let i=e.flags?.batchMaxSteps??P;if(!Number.isInteger(i)||i<1||i>1e3)return N("INVALID_ARGS",`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`);try{let a=ec(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await aj(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=tv(t);return N(e.code,e.message,e.details)}}async function aj(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{};return aF(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: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 aB(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new tI("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await aH({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await aK({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await az(t,u),a=!0)}else t=(await aK({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await az(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function aH(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await tw("xcrun",g(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:J});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||aW(a).includes(aW(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 aK(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await tw("xcrun",g(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new tI("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 tI("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function az(e,t){let r=await tw("xcrun",g(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:J});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 aW(e){return e.toLowerCase().replace(/[._-]/g,"")}async function aJ(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=e5(e.iosSimulatorDeviceSet);if(!r)return N("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await aB({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:e9});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=tv(t);return N(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=er(t.flags?.androidDeviceAllowlist),a=tf(t.flags?.platform),i=h({simulatorSetPath:e5(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("./155.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("./155.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("./155.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("./155.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=tv(t);return N(e.code,e.message,e.details)}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=ae(t.command,e,i);if(n)return n;let o=await ai({session:e,flags:i,ensureReady:!0});if(!tl("apps",o))return N("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(Q(o.platform)){let{listIosApps:e}=await import("./155.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("./155.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 aZ(e){let{ensureAndroidEmulatorBooted:t}=await import("./155.js");return await t(e)}let aY='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',aX='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function aQ(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=tf(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return N("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=ae("appstate",i,n);if(s)return s;let l=(i?.device.platform==="ios"||i?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!at(e))return!0;let r=tf(e?.platform);return!(r&&!ts(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 N("SESSION_NOT_FOUND",aY);if("macos"===o&&!l)return N("SESSION_NOT_FOUND",aX);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 N("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 ai({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return N("SESSION_NOT_FOUND",aY);if("macos"===d.platform)return N("SESSION_NOT_FOUND",aX);let{getAndroidAppState:u}=await import("./155.js"),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function a0(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=ae(t.command,i,n);if(o)return o;let s="android"===(tf(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!s)return N("INVALID_ARGS","boot --headless is supported only for Android emulators.");let d=ao({flags:n,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await ai({session:i,flags:n,ensureReady:!1})}catch(r){let t=tv(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return N("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await aZ({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return N("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return N("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=ao({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return N("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await aZ({avdName:t,serial:n.serial,headless:!0})}await e9(e)}else("android"!==e.platform||!0!==e.booted)&&await e9(e);return tl("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:N("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await aQ({req:t,sessionName:r,sessionStore:a}):null}function a1(e){return Math.round(10*e)/10}let a2="adb-shell-dumpsys-cpuinfo",a5="adb-shell-dumpsys-meminfo";async function a4(e,t){try{let r=await tw("adb",eQ(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:a1(i),measuredAt:r,method:a2,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw a8("cpu",t,e)}}async function a3(e,t){try{let r=await tw("adb",eQ(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new tI("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=a6(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!==a9(e));if(!r)break;return a9(r)??void 0}}(e);if(void 0===a)throw new tI("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:a6(e,"TOTAL RSS"),measuredAt:r,method:a5}}(r.stdout,t,new Date().toISOString())}catch(e){throw a8("memory",t,e)}}function a8(e,t,r){return r instanceof tI&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new tI(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof tI?r:new tI("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function a6(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return a9(a[1])??void 0}function a9(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let a7="ps-process-snapshot",ie="ps-process-snapshot",it="xctrace-activity-monitor",ir="xctrace-activity-monitor";async function ia(e,t){if("ios"===e.platform&&"device"===e.kind)return await is(e,t);let r=await io(e,t),a=await im(e,r);if(0===a.length)throw new tI("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(),o=k(a.map(e=>n.basename(ih(e.command))));return ig({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:o,cpuMethod:a7,memoryMethod:ie})}async function ii(e){let t=z(e),r=iw(t,e=>"schema"===e.name&&"activity-monitor-process-live"===e.attributes.name);if(!r)throw new tI("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 tI("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=[],u=new Map;for(let e of l){var c,f;let t=e.children;if(0===t.length)continue;for(let e of t){let t=iw(e.children,e=>"pid"===e.name&&"string"==typeof e.attributes.id);if(t?.attributes.id){let e=Number(t.text);u.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&u.set(e.attributes.id,{numberValue:iv(e),processName:iI(e)})}let r=iy(t[i],u),a=(c=t[n],f=u,c?c.attributes.ref?f.get(c.attributes.ref)?.processName??null:iI(c):null);null!==r&&Number.isFinite(r)&&a&&d.push({pid:r,processName:a,cpuTimeNs:iy(t[o],u),residentMemoryBytes:iy(t[s],u)})}return d}async function io(e,t){let r="macos"===e.platform?await ic(t):await ip(e,t),a="macos"===e.platform?n.join(r,"Contents","Info.plist"):n.join(r,"Info.plist"),i=await te(a,"CFBundleExecutable");if(!i)throw new tI("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?n.join(r,"Contents","MacOS",i):void 0}}async function is(e,t){let r=await il(e,t),a=await id(e,t),i=await id(e,t),n=iu(await ii(a.xml),r,t,e),o=iu(await ii(i.xml),r,t,e),s=i.capturedAtMs-a.capturedAtMs;if(s<=0)throw new tI("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 tI("COMMAND_FAILED",`Incomplete Activity Monitor sample for ${t}`,{appBundleId:t,deviceId:e.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});return ig({usagePercent:Math.max(0,o.cpuTimeNs-n.cpuTimeNs)/(1e6*s)*100,residentMemoryKb:o.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:o.matchedProcesses,cpuMethod:it,memoryMethod:ir})}async function il(e,t){let r=(await Z(e,"all")).find(e=>e.bundleId===t);if(!r)throw new tI("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new tI("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let a=r.url.replace(/\/$/,""),i=l(a),n=(await en(e)).filter(e=>e.executable.startsWith(`${a}/`));if(0===n.length)throw new tI("COMMAND_FAILED",`No running process found for ${t}`,{appBundleId:t,deviceId:e.id,appBundlePath:i,hint:"Run open <app> for this session again to ensure the iOS app is active, then retry perf."});return n}async function id(e,t){let r=await i.mkdtemp(n.join(u.tmpdir(),"agent-device-ios-perf-")),a=n.join(r,"sample.trace"),o=n.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"],n=await tw("xcrun",r,{allowFailure:!0,timeoutMs:6e4}),s=Date.now();if(0!==n.exitCode)throw new tI("COMMAND_FAILED",`Failed to record iOS device Activity Monitor sample for ${t}`,{cmd:"xcrun",args:r,exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,appBundleId:t,deviceId:e.id,hint:iS(n.stdout,n.stderr)});let l=["xctrace","export","--input",a,"--xpath",'/trace-toc/run/data/table[@schema="activity-monitor-process-live"]',"--output",o],d=await tw("xcrun",l,{allowFailure:!0,timeoutMs:15e3});if(0!==d.exitCode)throw new tI("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:iS(d.stdout,d.stderr)});return{capturedAtMs:s,xml:await i.readFile(o,"utf8")}}finally{await i.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function iu(e,t,r,a){let i=new Set(t.map(e=>e.pid)),o=new Set(t.map(e=>n.basename(l(e.executable)))),s=e.filter(e=>i.has(e.pid)||o.has(e.processName));if(0===s.length)throw new tI("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:a.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let d=new Map;for(let e of s){let t=d.get(e.pid);if(!t){d.set(e.pid,e);continue}d.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:iA(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iA(t.residentMemoryBytes,e.residentMemoryBytes)})}let u=[...d.values()],c=u.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=u.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:c.length>0?c.reduce((e,t)=>e+t,0):null,residentMemoryBytes:f.length>0?f.reduce((e,t)=>e+t,0):null,matchedProcesses:k(u.map(e=>e.processName))}}async function ic(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await tw("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new tI("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 tI("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function ip(e,t){let r=tr(e,["get_app_container",e.id,t,"app"]),a=await tw("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new tI("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 tI("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return i}async function im(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:tr(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 tw("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let i;return r=e.command,a=t,i=ih(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||n.basename(i)===a.executableName})}function ih(e){let[t=""]=e.trim().split(/\s+/,1);return t}function ig(e){return{cpu:{usagePercent:a1(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 iw(e,t){for(let r of e){if(t(r))return r;let e=iw(r.children,t);if(e)return e}}function iv(e){if(!e||e.children.some(e=>"sentinel"===e.name)||!e.text)return null;let t=Number(e.text);return Number.isFinite(t)?t:null}function iy(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:iv(e):null}function iI(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function iS(e,t){let r=e_(e,t);if(r)return r;let a=`${e}
|
|
6
|
-
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?$: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
|
|
7
|
-
`,a.appendFileSync(o,i,"utf8"),{ok:!0,data:{path:o,marked:!0}}}(t,r,i):"clear"===o?i$(n,r,i,s):"start"===o?iT(n,r,i):"stop"===o?iF(n,r,i):N("INVALID_ARGS",iM):N("INVALID_ARGS",iM)}async function iC(e,t,r){let a=r.resolveAppLogPath(t),i=await rv(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 i$(e,t,r,a){if(e.appLog&&!a)return N("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return N("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let i=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:ry(i)};e.appLog&&await rw(e.appLog);let n=ry(i),o=r.resolveAppLogPidPath(t);try{let a=await rh(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:ty(a)}}}async function iT(e,t,r){if(e.appLog)return N("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return N("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 rh(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:ty(e)}}}async function iF(e,t,r){if(!e.appLog)return N("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await rw(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function iU(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return N("SESSION_NOT_FOUND","network requires an active session");if(!tl("network",i.device))return N("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!ik.includes(n))return N("INVALID_ARGS",iD);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return N("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 N("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return iP.includes(a)?{ok:!0,include:a}:N("INVALID_ARGS",iL)}(t);if(!s.ok)return s;let{include:l}=s,d=await rp({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 iG=new Set(["ios","android","macos","linux"]);function iV(e,t,r){let a=e[t];if(void 0!==a)throw new tI("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 iq(e){return!!e&&!Number.isNaN(Number(e))}let ij=/[*?[\]{}]/;async function iB(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,runReplay:s,cleanupSession:l}=e;b(i);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:i,artifactPaths:d}).catch(e=>{let t=tv(e);return N(t.code,t.message)}).finally(()=>{K(i)});try{return"number"==typeof n?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,e4(i),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(n,[...d]))},n)})]):await c}finally{t&&clearTimeout(t),u&&(await iH(c)||ti({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await l(a)}catch(e){ti({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:tv(e).message}})}}}async function iH(e){return await Promise.race([e.then(()=>!0),f(2e3).then(()=>!1)])}async function iK(e){let{req:t,sessionName:r,runReplay:i,cleanupSession:o}=e;if((t.positionals?.length??0)===0)return N("INVALID_ARGS","test requires at least one path or glob");try{var s,l,d,u,c,f;let e,p,m,h,g,w=function(e){let{inputs:t,cwd:r,platformFilter:i}=e,o=r??process.cwd(),s=[...new Set(t.flatMap(e=>(function(e,t){var r,i;let o=tG.expandHome(e,t);if(a.existsSync(o)){let t=a.statSync(o);if(t.isDirectory())return a.globSync("**/*.ad",{cwd:o}).map(e=>n.join(o,e));if(t.isFile()){if(".ad"!==n.extname(o))throw new tI("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[o]}return[]}if(r=e,!ij.test(r)&&(i=o,!ij.test(i)))throw new tI("INVALID_ARGS",`test input not found: ${e}`);let s=n.isAbsolute(o)?o:e;return a.globSync(s,{cwd:n.isAbsolute(o)?void 0:t}).map(e=>n.isAbsolute(e)?e:n.resolve(t,e)).filter(e=>".ad"===n.extname(e)&&function(e){try{return a.statSync(e).isFile()}catch{return!1}}(e))})(e,o)))].map(e=>n.normalize(e)).sort((e,t)=>e.localeCompare(t)),l=[];for(let e of s){var d,u;let t=function(e){let t=e.split(/\r?\n/),r={};for(let e of t){let t=e.trim();if(0===t.length||t.startsWith("#"))continue;if(!t.startsWith("context "))break;let a=t.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&iG.has(e)&&iV(r,"platform",e)}let i=t.match(/(?:^|\s)timeout=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=1&&iV(r,"timeoutMs",Math.floor(e))}let n=t.match(/(?:^|\s)retries=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=0&&iV(r,"retries",Math.floor(e))}}return r}(a.readFileSync(e,"utf8"));if(!i){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 ${i}`});continue}d=i,u=t.platform,("apple"===d?"apple"===u||"ios"===u||"macos"===u:u===d)&&l.push({kind:"run",path:e,metadata:t})}if(0===l.filter(e=>"run"===e.kind).length){let e=i?` for --platform ${i}`:"";throw new tI("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=tG.expandHome(t??".agent-device/test-artifacts",r);return n.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 a=await iz({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:i,cleanupSession:o});if(I.push(a),t.flags?.failFast===!0)break}let b=(u=w.length,c=I,f=Date.now()-S,e=c.filter(e=>"passed"===e.status).length,m=(p=c.filter(e=>"failed"===e.status)).length,h=c.filter(e=>"skipped"===e.status).length,g=e+m,{total:u,executed:g,passed:e,failed:m,skipped:h,notRun:Math.max(0,u-g-h),durationMs:f,failures:p,tests:c});return{ok:!0,data:b}}catch(t){let e=tv(t);return N(e.code,e.message)}}async function iz(e){var t,r;let i,o,{entry:s,sessionName:l,suiteInvocationId:d,caseIndex:u,cwd:c,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:g,cleanupSession:w}=e,v=Date.now(),y=n.join(h,(t=s.path,(0===(o=c?n.relative(c,t):n.basename(t)).length||o.startsWith("..")?n.basename(t):o).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 o=n.basename(r,n.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${o?`-${o}`:""}:attempt-${i+1}`}(l,d,s.path,u,e),o=n.join(y,`attempt-${S}`);r=s.path,a.mkdirSync(o,{recursive:!0}),a.copyFileSync(r,n.join(o,"replay.ad"));let c=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:o}=e;return U(`${t??r}:test:${i+1}:${n.basename(a)}:attempt:${o+1}`,r)}({requestId:f,suiteInvocationId:d,filePath:s.path,caseIndex:u,attemptIndex:e}),h=await iB({filePath:s.path,sessionName:t,requestId:c,timeoutMs:m,platform:s.metadata.platform,runReplay:g,cleanupSession:w});if(!function(e){let{response:t,filePath:r,sessionName:i,attempts:o,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 u=function(e,t){let r=[],i=new Map;for(let o of e){if(!function(e){try{return a.statSync(e).isFile()}catch{return!1}}(o))continue;let e=function(e,t){let r=n.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}`}(n.basename(o),i),s=n.join(t,e);n.resolve(o)!==n.resolve(s)&&a.copyFileSync(o,s),r.push(s)}return r}(d,l),c=[`file: ${r}`,`session: ${i}`,`attempt: ${o}/${s}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;c.push(`replayed: ${e}`,`healed: ${r}`)}else c.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&c.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&c.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&c.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&c.push("timeoutMode: cooperative");u.length>0&&c.push(`copiedArtifacts: ${u.map(e=>n.basename(e)).join(", ")}`);let f=n.join(l,"result.txt"),p=`${c.join("\n")}
|
|
8
|
-
`;a.writeFileSync(f,p),t.ok||a.writeFileSync(n.join(l,"failure.txt"),p)}({response:h,filePath:s.path,sessionName:t,attempts:S,maxAttempts:p+1,attemptArtifactsDir:o}),i=h,I=t,h.ok)break}let A=Date.now()-v;if(i?.ok)return{file:s.path,session:I,status:"passed",durationMs:A,attempts:S,artifactsDir:y,replayed:"number"==typeof i.data?.replayed?i.data.replayed:0,healed:"number"==typeof i.data?.healed?i.data.healed:0};let b=i?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:i?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:s.path,session:I,status:"failed",durationMs:A,attempts:S,artifactsDir:y,error:b}}function
|
|
9
|
-
`,o=`${e}.tmp-${process.pid}-${Date.now()}`;a.writeFileSync(o,n),a.renameSync(o,e)}(l,c,n.get(r)),{ok:!0,data:{replayed:c.length,healed:p,session:r,artifactPaths:[...d]}}}catch(t){let e=tv(t);return N(e.code,e.message,d.size>0?{artifactPaths:[...d]}:void 0)}}async function iX(e){var t;let{req:r,sessionName:a,action:i,invoke:n}=e;return await n({token:r.token,session:a,command:i.command,positionals:i.positionals??[],flags:(t=r.flags,aF(t,{...i.flags??{}})),runtime:i.runtime,meta:r.meta})}function iQ(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=>tk(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 i0(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 a.statSync(e).isFile()}catch{return!1}})(e)))]}async function i1(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await iY({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await iK({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await iY({req:{...t,command:"replay",session:r,positionals:[e],flags:void 0===o?t.flags:{...t.flags??{},platform:o},meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),l&&i0(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{i.get(e)&&await a$({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let i2=new Set(["session_list","ensure-simulator","devices","apps"]),i5=new Set(["boot","appstate"]),i4=new Set(["perf","logs","network"]),i3=new Set(["replay","test"]);async function i8(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=i.get(r),u=t.flags??{},c=ae(n,d,u);if(c)return c;let f=await ai({session:d,flags:u,ensureReady:!0});if(!tl(n,f))return N("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await w(f,n,o,t.flags?.out,{...eV(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 i6(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=ae("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return N("INVALID_ARGS","clipboard requires a subcommand: read or write");let d=await ai({session:n,flags:o,ensureReady:!0});if(!tl("clipboard",d))return N("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let u=await w(d,"clipboard",t.positionals??[],t.flags?.out,{...eV(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function i9(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(i2.has(t.command))return await aJ({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await am({req:t,sessionName:r,sessionStore:i});if(i5.has(t.command))return await a0({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await i6({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"!==tf((t.flags??{}).platform)?await i8({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):N("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(i4.has(t.command))return await iR({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await aV({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?aG:aU});if("install_source"===t.command)return await r3({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await r6({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await i8({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=e1(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tG.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):N("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await i8({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 aA(e.device,r,e.appBundleId,aS)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await aR({req:t,sessionName:r,logPath:a,sessionStore:i}):i3.has(t.command)?await i1({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await aq(t,r,n):"close"===t.command?await a$({req:t,sessionName:r,logPath:a,sessionStore:i}):null}function i7(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return N("INVALID_ARGS","No snapshot in session. Run snapshot first.");let s=eC(r);if(!s)return N("INVALID_ARGS",n);let l=eM(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=to(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:N("COMMAND_FAILED",o)}function ne(e){let t=nt(e);if(!t)return null;let r=et(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function nt(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}async function nr(e){let{session:t,refInput:r,fallbackLabel:a,commandLabel:i,promoteToHittableAncestor:n,invalidRefMessage:o,missingBoundsMessage:s,invalidBoundsMessage:l,reqFlags:d,sessionStore:u,contextFromFlags:c,captureSnapshotForSession:f,resolveRefTarget:p}=e,m=p({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:o,notFoundMessage:s});if(!m.ok)return m;let{ref:h}=m.target,g=n?na(m.target.snapshotNodes,m.target.node):m.target.node,w=m.target.snapshotNodes,y=ne(g.rect);if(!y){let e=await f(t,d,u,c,{interactiveOnly:!0}),r=eM(e.nodes,h),i=a.length>0?to(e.nodes,a):null,o=r&&n?na(e.nodes,r):r,s=i&&n?na(e.nodes,i):i,l=ne(s?.rect),p=ne(o?.rect)?o:l?s:o??s,m=ne(p?.rect);p&&m&&(g=p,w=e.nodes,y=m)}if(!y)return N("COMMAND_FAILED",l);let I=g.rect?e2(g,w):null;return g.rect&&I&&!v(g,w)?{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${r} is off-screen and not safe to ${i}`,hint:`Run scrollintoview ${r}, then retry ${i} with the returned currentRef or a fresh snapshot.`,details:{reason:"offscreen_ref",ref:h,rect:g.rect,viewport:I}}}:{ok:!0,target:{ref:h,node:g,snapshotNodes:w,point:y}}}function na(e,t){let r=function(e,t){let r=nt(t.rect);if(!r)return null;let a=t,i=new Set;for(;!i.has(a.ref);){i.add(a.ref);let t=e.filter(e=>{if(e.parentIndex!==a.index||!e.hittable)return!1;let t=nt(e.rect);return!!t&&ni(t,r)});if(1!==t.length)break;a=t[0]}return a===t?null:a}(e,t);if(r?.rect&&ne(r.rect))return r;let a=W(e,t);return a?.rect&&ne(a.rect)?!function(e,t,r){var a,i,n,o;let s,l,d,u=nt(e.rect),c=nt(t.rect);if(!u||!c)return!1;let f=function(e,t){let r=et(t),a=e.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}).map(e=>nt(e.rect)).filter(e=>null!==e);if(0===a.length)return null;let i=a.filter(e=>E(e,r.x,r.y));return x(i.length>0?i:a)}(r,u);return!!f&&(a=c,i=f,s=(n=a,o=i,Math.max(0,Math.min(n.x+n.width,o.x+o.width)-Math.max(n.x,o.x))*Math.max(0,Math.min(n.y+n.height,o.y+o.height)-Math.max(n.y,o.y))),l=a.width*a.height,d=i.width*i.height,!(s<=0)&&!(l<=0)&&!(d<=0)&&!!(s/d>=.9)&&!!(s/l>=.8))&&!ni(u,c)}(t,a,e)?a:t:t}function ni(e,t){return .5>=Math.abs(e.x-t.x)&&.5>=Math.abs(e.y-t.y)&&.5>=Math.abs(e.width-t.width)&&.5>=Math.abs(e.height-t.height)}async function nn(e){let{device:t,node:r,flags:a,appBundleId:i,traceOutPath:n,surface:o,contextFromFlags:s}=e,l=R(r),d=ne(r.rect);if(!d)return l;try{let e=await w(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,i,n),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return ti({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return ti({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}async function no(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 N("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:u,value:c,timeoutMs:f}=eq(s);if(!d)return N("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return N("INVALID_ARGS","find accepts only one of --first or --last");let p=i.get(r);if(!p&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return N("SESSION_NOT_FOUND","No active session. Run open first.");let m=p?.device??await eR(t.flags??{});p||await e9(m);let h="role"!==l?d:void 0,g="click"===u||"focus"===u||"fill"===u||"type"===u,w=0,v=null,y=async()=>{let e=Date.now();if(v&&e-w<750&&!tt(p))return{nodes:v};let{snapshot:n}=await eB({device:m,session:p,flags:{...t.flags,snapshotInteractiveOnly:g,snapshotCompact:g},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=n.nodes;return w=e,v=o,p&&(p.snapshot=n,i.set(r,p)),{nodes:o,truncated:n.truncated,backend:n.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:p,device:m,command:o,locator:l,query:d};if("wait"===u)return ns(I,y,l,d,f);let{nodes:S}=await y(),A=ta(S,l,d,{requireRect:g});if(g&&A.matches.length>1)if(t.flags?.findFirst)A.matches=[A.matches[0]];else{if(!t.flags?.findLast){var b,_,x;let e;return b=A.matches,_=l,x=d,e=b.slice(0,8).map(e=>{let t=C(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),N("AMBIGUOUS_MATCH",`find matched ${b.length} elements for ${_} "${x}". Use a more specific locator or selector.`,{locator:_,query:x,matches:b.length,candidates:e})}A.matches=[A.matches[A.matches.length-1]]}let M=A.matches[0]??null;if(!M)return N("COMMAND_FAILED","find did not match any element");let k="click"===u||"focus"===u||"fill"===u||"type"===u?W(S,M)??M:M,D=`@${k.ref}`,P={node:M,resolvedNode:k,ref:D,nodes:S,actionFlags:{...t.flags??{},noRecord:!0}},L={exists:()=>nl(I),get_text:()=>nd(I,P),get_attrs:()=>nu(I,P),click:()=>nc(I,P),fill:()=>nf(I,P,c),focus:()=>np(I,P),type:()=>nm(I,P,c)}[u];return L?L():null}async function ns(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,d=i??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(ta(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{found:!0,waitedMs:Date.now()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return N("COMMAND_FAILED","find wait timed out")}async function nl(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 nd(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await nn({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eV(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 nu(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 nc(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:d}=e,u=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?et(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:d};return c&&(f.x=c.x,f.y=c.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:f}}async function nf(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return N("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 np(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?et(t.node.rect):null;if(!l)return N("COMMAND_FAILED","matched element has no bounds");let d=await w(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eV(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 nm(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return N("INVALID_ARGS","find type requires text");let d=t.node.rect?et(t.node.rect):null;if(!d)return N("COMMAND_FAILED","matched element has no bounds");await w(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...eV(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let u=await w(o,"type",[r],a.flags?.out,{...eV(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:u??{ref:t.ref}}}let nh=`
|
|
1
|
+
let e,t;import r from"node:crypto";import a,{promises as i}from"node:fs";import n from"node:path";import{spawn as o}from"node:child_process";import s from"node:http";import{fileURLToPath as l,pathToFileURL as d}from"node:url";import"node:https";import u from"node:os";import c from"node:fs/promises";import{setTimeout as f}from"node:timers/promises";import{PNG as p}from"pngjs";import m from"node:net";import{resolveAppleSimulatorSetPathForSelector as h,buildSimctlArgs as g,dispatchCommand as w,isNodeVisibleInEffectiveViewport as v,isAgentDeviceDaemonProcess as y,handleSnapshotCommands as I,isNodeEditable as S,resolveSelectorChain as A,registerRequestAbort as b,resolveSessionIsolationMode as _,errorResponse as N,pickLargestRect as x,successText as D,uniqueStrings as M,withKeyedLock as k,DEFAULT_BATCH_MAX_STEPS as P,parseSerialAllowlist as L,extractNodeReadText as R,getAndroidScreenSize as O,rect_visibility_containsPoint as C,extractNodeText as E,IOS_DEVICECTL_DEFAULT_HINT as $,captureSnapshotData as T,isRequestCanceled as F,resolveRequestTrackingId as U,abortAllIosRunnerSessions as G,getRunnerSessionSnapshot as V,formatAndroidInstalledPackageRequiredMessage as q,tryParseSelectorChain as j,readVersion as H,clearRequestCanceled as B,parseXmlDocumentSync as K,findNearestHittableAncestor as z,IOS_SIMCTL_LIST_TIMEOUT_MS as W,listIosDeviceApps as J,readProcessStartTime as Z,withDiagnosticsScope as X,isApplePlatform as Y,resolveInstallFromSourceResultTarget as Q,centerOfRect as ee,resolveAndroidSerialAllowlist as et,isFillableType as er,attachRefs as ea,listIosDeviceProcesses as ei,buildScrollGesturePlan as en,splitSelectorFromArgs as eo,readProcessCommand as es,IOS_RUNNER_CONTAINER_BUNDLE_IDS as el,parseSessionSurface as ed,validateAndNormalizeBatchSteps as eu,resolveDaemonServerMode as ec,buttonTag as ef,hasRuntimeTransportHints as ep,resolveDeployResultTarget as em,inferFillText as eh,buildSelectorChainForNode as eg,withSuccessText as ew,shutdownSimulator as ev,stopIosRunnerSession as ey,formatSelectorFailure as eI,createRequestCanceledError as eS,isNavigationSensitiveAction as eA,resolveIosDevicectlHint as eb,getClickButtonValidationError as e_,isNodeVisible as eN,findNodeByRef as ex,snapshotAndroid as eD,withDiagnosticTimer as eM,pruneGroupNodes as ek,applyRuntimeHintsToApp as eP,resolveTargetDevice as eL,stopAllIosRunnerSessions as eR,findSelectorChainMatch as eO,normalizeRef as eC,classifyAndroidAppTarget as eE,getAndroidAppState as e$,runMacOsAlertAction as eT,isDeepLinkTarget as eF,clearRuntimeHintsFromApp as eU,contextFromFlags as eG,parseFindArgs as eV,resolveDaemonCodeSignature as eq,captureSnapshot as ej,parseSelectorChain as eH,normalizeTenantId as eB,resolveClickButton as eK,resolveTimeoutMs as ez,buildSnapshotState as eW,openAndroidApp as eJ,splitIsSelectorArgs as eZ,adbArgs as eX,resolveRefLabel as eY,resolvePayloadInput as eQ,resolveEffectiveViewportRect as e0,resolveIosSimulatorDeviceSetPath as e1,markRequestCanceled as e2,resolveIosDeviceDeepLinkBundleId as e5,runIosRunnerCommand as e3,resolveUserPath as e4,ensureDeviceReady as e8,getDiagnosticsMeta as e6,readInfoPlistString as e9,getActiveAndroidSnapshotFreshness as e7,buildSimctlArgsForDevice as te,findBestMatchesByLocator as tt,emitDiagnostic as tr,resolveFrontmostMacOsApp as ta,findNodeByLabel as ti,matchesPlatformSelector as tn,isCommandSupportedOnDevice as to,resolveDaemonPaths as ts,flushDiagnosticsToSessionFile as tl,normalizeType as td,normalizePlatformSelector as tu,decodePng as tc,markAndroidSnapshotFreshness as tf,getRequestSignal as tp}from"./155.js";import{runCmdBackground as tm,runCmd as th,asAppError as tg,normalizeError as tw,AppError as tv}from"./818.js";let ty=/^-?\d+(\.\d+)?$/,tI=/^[^\s"\\]+$/,tS=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tA=new Map([["--count","count"],["--pause-ms","pauseMs"]]),tb=new Map([["--delay-ms","delayMs"]]);function t_(e){return"click"===e||"press"===e}function tN(e){return"type"===e||"fill"===e}function tx(e){return tM(e,tk)}function tD(e){return JSON.stringify(e)}function tM(e,t){return t(e)?e:tD(e)}function tk(e){return tP(e)&&e.startsWith("@")||ty.test(e)}function tP(e){return tI.test(e)}function tL(e,t){let r=t.flags??{};if(t_(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}tN(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function tR(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,tP)),"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,tP)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tM(t.launchUrl,tP)))}function tO(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(tM(r,tP)),a))e.push(tx(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function tC(e,t){let r=[],a={},i=t_(e)?tS:"swipe"===e?tA:tN(e)?tb:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(t_(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(t_(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=t$(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 tE(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=t$(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 t$(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function tT(e,t){for(let r of t.positionals??[])e.push(tx(r));t.flags?.relaunch&&e.push("--relaunch"),tR(e,t.runtime)}class tF{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=tF.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 tU)void 0!==e[r]&&(t[r]=e[r]);return t}(t.flags),result:t.result}),tr({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=n.dirname(t);a.existsSync(r)||a.mkdirSync(r,{recursive:!0});let i=function(e,t){let r=[],a=e.device.kind?` kind=${e.device.kind}`:"";for(let i of(r.push(`context platform=${e.device.platform} device=${tD(e.device.name)}${a} theme=unknown`),t))i.flags?.noRecord||r.push(function(e){let t=[e.command];if(t_(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tx(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tx(a)),tL(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tx(r)),tL(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tx(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tx(a)),e.positionals.length>1&&t.push(tx(i)),tL(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tx(r)),t.push(tx(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tx(r))}return t.join(" ")}}if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tx(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tx(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}if("open"===e.command)return tT(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tM(r,tP)),tR(t,e.flags),t.join(" ")}if("record"===e.command)return tO(t,e),t.join(" ");for(let r of e.positionals??[])t.push(tx(r));return tL(t,e),t.join(" ")}(i));return`${r.join("\n")}
|
|
2
|
+
`}(e,this.buildOptimizedActions(e));a.writeFileSync(t,i)}catch{}}defaultTracePath(e){let t=tF.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return n.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return n.join(this.sessionsDir,tF.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return n.join(this.sessionsDir,tF.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return e4(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return tF.expandHome(e.saveScriptPath);a.existsSync(this.sessionsDir)||a.mkdirSync(this.sessionsDir,{recursive:!0});let t=tF.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return n.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&&(t_(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(t_(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=eh(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(t_(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 tU=["platform","device","udid","serial","out","verbose","metroHost","metroPort","bundleUrl","launchUrl","snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw","screenshotFullscreen","relaunch","saveScript","noRecord","fps","hideTouches","count","intervalMs","delayMs","holdMs","jitterPx","doubleTap","clickButton","pauseMs","pattern"],tG="app-log.pid";function tV(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=n.dirname(e);a.existsSync(r)||a.mkdirSync(r,{recursive:!0});let i={pid:t,startTime:Z(t)??void 0,command:es(t)??void 0};a.writeFileSync(e,`${JSON.stringify(i)}
|
|
3
|
+
`)}function tj(e){if(e&&a.existsSync(e))try{a.unlinkSync(e)}catch{}}async function tH(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function tB(e){await new Promise(t=>setTimeout(t,e))}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 tv("INVALID_ARGS",`Invalid Android package name for logs: ${e}`)}async function tJ(e,t){let r=(await th("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 th("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,s,l="recovering",d=!1,u=(async()=>{try{for(;!d;){let u=await tJ(e,t);if(!u){l="recovering",await tB(1e3);continue}let c=o("adb",["-s",e,"logcat","-v","time","--pid",u],{stdio:["ignore","pipe","pipe"]});n=c;let f=tK(r,{redactionPatterns:a});if(s=tz(c,r,{endStreamOnClose:!1,writer:f}),"number"==typeof c.pid&&(tq(i,c.pid),l="active"),await s,tj(i),n=void 0,s=void 0,d)break;l="recovering",await tB(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tj(i)}})();return{backend:"android",getState:()=>l,startedAt:Date.now(),wait:u,stop:async()=>{d=!0,n&&!n.killed&&n.kill("SIGINT"),s&&await tH(s),n&&!n.killed&&n.kill("SIGKILL"),await tH(u),tj(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=g(["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 th("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 s="active",l=o("xcrun",function(e){let{deviceId:t,appBundleId:r,simulatorSetPath:a}=e;return g(["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 u=tz(l,r,{endStreamOnClose:!0,writer:d}).then(e=>(0!==e.exitCode&&(s="failed"),tj(n),e));return{backend:"ios-simulator",getState:()=>s,startedAt:Date.now(),wait:u,stop:async()=>{l.killed||l.kill("SIGINT"),await tH(u),l.killed||l.kill("SIGKILL"),await tH(u),tj(n)}}}async function t1(e,t,r,a){let i="active",n=o("log",["stream","--style","compact","--predicate",tY(e)],{stdio:["ignore","pipe","pipe"]}),s=tK(t,{redactionPatterns:r});"number"==typeof n.pid&&tq(a,n.pid);let l=tz(n,t,{endStreamOnClose:!0,writer:s}).then(e=>(0!==e.exitCode&&(i="failed"),tj(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tH(l),n.killed||n.kill("SIGKILL"),await tH(l),tj(a)}}}async function t2(e,t,r,a){let i="active",n=o("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),s=tK(t,{redactionPatterns:r});"number"==typeof n.pid&&tq(a,n.pid);let l=tz(n,t,{endStreamOnClose:!0,writer:s}).then(e=>(0!==e.exitCode&&(i="failed"),tj(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:l,stop:async()=>{n.killed||n.kill("SIGINT"),await tH(l),n.killed||n.kill("SIGKILL"),await tH(l),tj(a)}}}let t5=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),t3=/https?:\/\/[^\s"'<>\])]+/i,t4=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function t8(e,t,r=e.limits.maxEntries){let a=[...e.entries],i=new Set(a.map(e=>t9(e)));for(let e of t.entries){let t=t9(e);if(!i.has(t)&&(i.add(t),a.push(e),a.length>=r))break}return{...e,matchedLines:a.length,entries:a}}function t6(e,t){let r=rl(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=rl(t?.maxPayloadChars,2048,64,16384),o=rl(t?.maxScanLines,4e3,100,2e4),s=e.split("\n"),l=Math.max(0,s.length-o),d=s.slice(l),u=[];for(let e=d.length-1;e>=0&&u.length<r;e-=1){let t=d[e];if(!t?.trim())continue;let r=function(e,t,r,a,i,n){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=ri(s,["method","httpMethod"]),d=ri(s,["url","requestUrl"]),u=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=t5.exec(o),f=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),p=(l??f?.[1]??c?.[1])?.toUpperCase(),m=t3.exec(o),h=d??m?.[0];if(!h)return null;let g=u??re(o)??void 0;if(!(l||f?.[1]||c?.[1]||void 0!==g||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let w={method:p,url:h,status:g,timestamp:rt(o),packetId:rr(o)??void 0,durationMs:ra(o)??void 0,raw:rs(o,n),line:r};if("android"===a&&function(e,t,r){let a=t7(t,r,5),i=e.packetId??a.map(e=>rr(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?t7(t,r,12).filter(e=>rr(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>rt(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>re(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>ra(e)).find(e=>"number"==typeof e))}(w,e,t),"headers"===i||"all"===i){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return ro(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(w.headers=rs(e,n))}if("body"===i||"all"===i){let e=rn(o,s,["requestBody","body","payload","request"]),t=rn(o,s,["responseBody","response"]);e&&(w.requestBody=rs(e,n)),t&&(w.responseBody=rs(t,n))}return w}(d,e,l+e+1,a,i,n);r&&u.push(r)}return{path:t?.path??"<memory>",exists:!0,scannedLines:d.length,matchedLines:u.length,entries:u,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:o}}}function t9(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function t7(e,t,r){let a=[],i=Math.max(0,t-r),n=Math.min(e.length-1,t+r);for(let t=i;t<=n;t+=1){let r=e[t]?.trim();r&&a.push(r)}return a}function re(e){for(let t of t4){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function rt(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function rr(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function ra(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function ri(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function rn(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return ro(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function ro(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function rs(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function rl(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}function rd(e,t){let r=process.env[e];if(!r)return t;let a=Number.parseInt(r,10);return Number.isInteger(a)&&a>0?a:t}function ru(e){let t=n.dirname(e);a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),function(e,t){if(a.existsSync(e)&&!(a.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,i=`${e}.${r}`;a.existsSync(t)&&(a.existsSync(i)&&a.unlinkSync(i),a.renameSync(t,i))}}(e,{maxBytes:rd("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rd("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rc(e){var t,r,i,n;let o,s,l,d,{device:u,appBundleId:c,appLogState:f,appLogStartedAt:p,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v}=e,y="macos"===u.platform?"macos":"ios"===u.platform?"device"===u.kind?"ios-device":"ios-simulator":"android",I=(t={backend:y,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v},o=rl(t?.maxEntries,25,1,200),s=t?.include??"summary",l=rl(t?.maxPayloadChars,2048,64,16384),d=rl(t?.maxScanLines,4e3,100,2e4),a.existsSync(m)?t6(a.readFileSync(m,"utf8"),{...t,path:m}):{path:m,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:s,limits:{maxEntries:o,maxPayloadChars:l,maxScanLines:d}}),S=[],A=await rf({device:u,appBundleId:c,appLogPath:m,appLogState:f});if(A){let e=await tZ(u.id,c);if(e){let t=t6(e.text,{path:`${m} (adb logcat recovery)`,backend:"android",maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v});t.entries.length>0&&(I=t8(t,I,h),S.push((r=A,i=e.recoveredPids,"stale-active"===r.reason?`Session app log stream was still bound to prior Android PID ${r.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${i.join(", ")}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${i.join(", ")}.`)))}}if("ios"===u.platform&&"simulator"===u.kind&&c&&0===I.entries.length){let e=await rm({deviceId:u.id,appBundleId:c,startedAt:p,simulatorSetPath:u.simulatorSetPath,appLogPath:m,maxEntries:h,include:g,maxPayloadChars:w,maxScanLines:v});e&&(e.dump.entries.length>0?(I=t8(e.dump,I,h),S.push(`Recovered ${e.dump.entries.length} iOS simulator HTTP entr${1===e.dump.entries.length?"y":"ies"} from simctl log show (${e.recoveredLineCount} app log lines scanned).`)):e.recoveredLineCount>0&&S.push(`Recovered ${e.recoveredLineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return void 0===f?S.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."):"active"!==f&&0===S.length&&("ios"===u.platform&&"simulator"===u.kind?S.push("Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop."):S.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.")),0===I.entries.length&&S.push("ios"===(n=u).platform&&"simulator"===n.kind?"No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.":"ios"===n.platform?"No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.":"No HTTP(s) entries were found in recent session app logs."),{backend:y,dump:I,notes:S}}async function rf(e){let{device:t,appBundleId:r,appLogPath:i,appLogState:o}=e;if("android"!==t.platform||!r)return null;if(void 0!==o&&"active"!==o)return{reason:"inactive"};if("active"!==o)return null;let s=function(e){let t=function(e){if(!e||!a.existsSync(e))return null;try{return tV(a.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}(n.join(n.dirname(i),tG));if(!s)return null;let l=await tJ(t.id,r);return l&&l!==s?{reason:"stale-active",trackedPid:s}:null}async function rp(e,t,r,i){ru(r);let n=a.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,i):await t0(e.id,t,n,o,e.simulatorSetPath,i);if("android"===e.platform)return tW(t),await tX(e.id,t,n,o,i);if("macos"===e.platform)return await t1(t,n,o,i);throw n.end(),new tv("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rm(e){let t=await tQ({deviceId:e.deviceId,appBundleId:e.appBundleId,startedAt:e.startedAt,simulatorSetPath:e.simulatorSetPath});return t?{dump:t6(t.text,{path:`${e.appLogPath} (simctl log show recovery)`,backend:"ios-simulator",maxEntries:e.maxEntries,include:e.include,maxPayloadChars:e.maxPayloadChars,maxScanLines:e.maxScanLines}),recoveredLineCount:t.recoveredLineCount}:null}async function rh(e){await e.stop(),await tH(e.wait)}async function rg(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await th("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await th("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 th("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 th("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await th("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function rw(e){let t=n.dirname(e),r=n.basename(e);a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),a.existsSync(e)?a.truncateSync(e,0):a.writeFileSync(e,"","utf8");let i=0;for(let e of a.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let o=e.slice(r.length+1);if(/^\d+$/.test(o))try{a.unlinkSync(n.join(t,e)),i+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:i}}let rv=new Map;function ry(e){let t=rv.get(e);if(t&&(clearTimeout(t.timer),rv.delete(e),t.deleteAfterDownload))try{a.rmSync(t.artifactPath,{force:!0})}catch{}}let rI=new Map;function rS(e,t){let r=rI.get(e);if(!r)throw new tv("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tv("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function rA(e){let t=rI.get(e);t&&(clearTimeout(t.timer),rI.delete(e),a.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rb(e){let t=await r_(e);await th("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=n.join(e.tempDir,t);if(!a.existsSync(r))throw new tv("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function r_(e){let t=await th("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new tv("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 tv("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rN),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new tv("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new tv("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 tv("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 tv("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 tv("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await th("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new tv("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rN(e){if(e.includes("\0"))throw new tv("INVALID_ARGS",`Invalid archive entry: ${e}`);if(n.posix.isAbsolute(e))throw new tv("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=n.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new tv("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rx=ez(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rD(e,t){return new Promise((r,i)=>{let n,o=a.createWriteStream(t),s=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,u=e=>{if(!l){if(l=!0,n&&clearTimeout(n),e){o.destroy(),a.rmSync(t,{force:!0}),i(e);return}r()}},c=()=>{n&&clearTimeout(n),n=setTimeout(()=>{let e=new tv("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rx});s(e),o.destroy(e),u(e)},rx)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new tv("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");s(e),o.destroy(e),u(e)}}),e.on("error",u),e.on("aborted",()=>{u(new tv("COMMAND_FAILED","Artifact transfer was interrupted"))}),o.on("error",u),o.on("finish",()=>u()),c(),e.pipe(o)})}async function rM(e){let t,r=e.headers["x-artifact-type"],i=e.headers["x-artifact-filename"];if(!r||!i)throw new tv("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new tv("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 tv("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let o=function(e){let t=e.trim(),r=n.basename(t);if(!r||"."===r||".."===r)throw new tv("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(i),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"),a.mkdtempSync(n.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=n.join(s,o);return await rD(e,t),{artifactPath:t,tempDir:s}}let t=n.join(s,"artifact.tar");await rD(e,t);let i=await rb({archivePath:t,tempDir:s,platform:"ios",expectedRootName:o});return a.rmSync(t,{force:!0}),{artifactPath:i,tempDir:s}}catch(e){throw a.rmSync(s,{recursive:!0,force:!0}),e}}let rk=new Set(["agent_device.command","agent-device.command"]),rP=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rL=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rR={"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"},rO=new Set([...rk,...rP,...rL,...Object.keys(rR)]);function rC(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rE(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function r$(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rT(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 rF(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rU(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rG(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=tw(new tv("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:rC(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=tw(new tv(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:rC(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=eB(r.tenantId);if(!e){let e=tw(new tv("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:rC(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rV(){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=n.isAbsolute(t)?t:n.resolve(t);try{e=await import(d(a).href)}catch(e){throw new tv("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 tv("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rq(e){let t=await rV(),{handleRequest:r,token:a}=e;return s.createServer((e,i)=>{if("GET"===e.method&&"/health"===e.url){i.statusCode=200,i.setHeader("content-type","application/json"),i.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void rj(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rH(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||rE(i,rC(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rE(i,rC(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rE(i,rC(a.id??null,-32600,"Invalid Request"),400);if(!rO.has(a.method))return void rE(i,rC(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rE(i,rC(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rk.has(e))return{token:rT(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(rP.has(e)){let e,a=rF(t,"platform");if("ios"!==a&&"android"!==a)throw new tv("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rT(t,r),session:rF(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rF(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new tv("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new tv("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 tv("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 tv("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 tv("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new tv("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rU(t,"retentionMs")}}}if(rL.has(e)){let e=rF(t,"materializationId")?.trim();if(!e)throw new tv("INVALID_ARGS","Invalid params: materializationId is required");return{token:rT(t,r),session:rF(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rF(t,"requestId"),materializationId:e}}}let a=rR[e];if(a)return{token:rT(t,r),session:rF(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rF(t,"tenantId")??rF(t,"tenant"),runId:rF(t,"runId"),leaseId:rF(t,"leaseId"),leaseTtlMs:rU(t,"ttlMs"),leaseBackend:rF(t,"backend")}};throw new tv("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rk.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rE(i,rC(a.id??null,-32602,"Invalid params: command is required"),400);o=U(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},b(o);let d=()=>{i.writableFinished||e2(o)};e.on("aborted",d),i.on("close",d);let u=await rG(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rE(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rE(i,{jsonrpc:"2.0",id:a.id??null,result:c});rE(i,rC(a.id??null,-32e3,c.error.message,c.error),r$(c.error.code))}catch(t){let e=tw(t);rE(i,rC(a.id??null,-32e3,e.message,e),r$(e.code))}finally{B(o)}})})}async function rj(e,t,a,i){try{var n;let o,s,l=rT({},e.headers),d=rB(l,i);if(d){t.statusCode=r$(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await rG(a,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await rM(e),f=(n={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},o=r.randomUUID(),(s=setTimeout(()=>{rA(o)},3e5)).unref(),rI.set(o,{artifactPath:n.artifactPath,tempDir:n.tempDir,tenantId:n.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:f}))}catch(r){let e=tw(r);t.statusCode=r$(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rH(e,t,r,i){let n=e.url?.slice("/upload/".length)??"";if(!n){t.statusCode=400,t.end("Missing artifact id");return}try{let o=rT({},e.headers),s=rB(o,i);if(s){t.statusCode=r$(s.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.message,code:s.code}));return}let l=await rG(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=rv.get(e);if(!r)throw new tv("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tv("UNAUTHORIZED","Artifact belongs to a different tenant");if(!a.existsSync(r.artifactPath))throw ry(e),new tv("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(n,l.tenantId),u=a.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=tw(e);t.statusCode=r$(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&ry(n)}),u.pipe(t)}catch(r){let e=tw(r);t.statusCode=r$(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rB(e,t){return t&&e!==t?tw(new tv("UNAUTHORIZED","Invalid token")):null}function rK(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rz(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rW(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new tv("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rJ{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=rW(e.backend),a=eB(e.tenantId);if(!a)throw new tv("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=rK(e.runId);if(!i)throw new tv("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(a,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:r.randomBytes(16).toString("hex"),tenantId:a,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=rz(e.leaseId);if(!t)throw new tv("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new tv("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=rz(e.leaseId);if(!t)throw new tv("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=rW(e.backend),r=eB(e.tenantId);if(!r)throw new tv("INVALID_ARGS","tenant isolation requires tenant id.");let a=rK(e.runId);if(!a)throw new tv("INVALID_ARGS","tenant isolation requires run id.");let i=rz(e.leaseId);if(!i)throw new tv("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new tv("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new tv("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 tv("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 tv("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=eB(t),i=rK(r);if(t&&!a)throw new tv("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new tv("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 tv("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rZ=ez(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),rX=new Map;async function rY(e){let t=await c.mkdtemp(n.join(u.tmpdir(),"agent-device-materialized-"));try{let a=await r1(e.installablePath,n.join(t,"installable")),i=e.archivePath?await r1(e.archivePath,n.join(t,"archive")):void 0,o=r.randomUUID(),s=e.ttlMs??rZ,l=Date.now()+s,d=setTimeout(()=>{rQ(o)},s);return rX.set(o,{rootPath:t,installablePath:a,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:l,timer:d}),{materializationId:o,installablePath:a,...i?{archivePath:i}:{},expiresAt:new Date(l).toISOString()}}catch(e){throw await c.rm(t,{recursive:!0,force:!0}),e}}async function rQ(e,t){let r=rX.get(e);if(!r)throw new tv("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new tv("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),rX.delete(e),await c.rm(r.rootPath,{recursive:!0,force:!0})}async function r0(e){let t=Array.from(rX.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await rQ(e)}))}async function r1(e,t){let r=await c.stat(e);await c.mkdir(t,{recursive:!0});let a=n.join(t,n.basename(e));return r.isDirectory()?await c.cp(e,a,{recursive:!0}):await c.copyFile(e,a),a}async function r2(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 tv("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await e8(e.session.device),e.session.device}if(!r)throw new tv("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await eL(e.flags??{});return await e8(a),a}async function r5(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 tv("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new tv("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new tv("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:rS(o,t.meta?.tenantId)},cleanup:()=>{rA(o)}}:{source:n,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new tv("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await r2({session:i,flags:t.flags});if(!to("install",d))return N("UNSUPPORTED_OPERATION","install_from_source is not supported on this device");let u=tp(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await import("./155.js"),{prepareIosInstallArtifact:o}=await import("./155.js"),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await rY({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(d,c.installablePath),!c.bundleId)throw new tv("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=ew(o,r3(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await rQ(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await import("./155.js"),{installAndroidInstallablePathAndResolvePackageName:f}=await import("./155.js"),p=await c(s.source,{signal:u});try{l.enabled&&(e=await rY({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 tv("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await import("./155.js"),s=o(n),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=ew(u,r3(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await rQ(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:tw(e)}}}function r3(e){return`Installed: ${Q(e)}`}async function r4(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new tv("INVALID_ARGS","release_materialized_paths requires a materializationId");return await rQ(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:tw(e)}}}let r8=ez(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),r6=ez(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function r9(e,t,r){return t||r7(r)?null:N("INVALID_ARGS",`${e} requires an active session or an explicit device selector (e.g. --platform ios).`)}function r7(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function ae(e){return"ios"===e.platform&&"simulator"===e.kind}async function at(e,t){ae(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function ar(e){let t=r7(e.flags)||!e.session?await eL(e.flags??{}):await aa(e.session.device);return!1!==e.ensureReady&&await e8(t),t}async function aa(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 eL(t)}catch(e){if(!(e instanceof tv)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await eL({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function ai(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 an=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function ao(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function as(e){let t=e?.trim();return t&&t.length>0?t:void 0}function al(e,t){if(void 0!==e){if("string"!=typeof e)throw new tv("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return as(e)}}function ad(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new tv("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function au(e){if("ios"===e||"android"===e)return e}async function ac(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!ep(r)||ep(a)||await eU({device:i.device,appId:i.appBundleId})}async function af(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 N("INVALID_ARGS","runtime requires set, show, or clear");if("clear"===o){ep(l)&&s?.appBundleId&&await eU({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=au(tu(a.flags?.platform)??l?.platform??s?.device.platform);if(!d)return N("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 N("INVALID_ARGS",`runtime set targets ${d}, but session "${i}" is already bound to ${s.device.platform}.`);let u={platform:(t=a.flags,r={platform:d,metroHost:as(t?.metroHost),metroPort:ad(t?.metroPort),bundleUrl:as(t?.bundleUrl),launchUrl:as(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===ao(u)?N("INVALID_ARGS","runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."):(n.setRuntimeHints(i,u),{ok:!0,data:{session:i,configured:!0,runtime:u}})}let ap="open-command-roundtrip",am="Not implemented for this platform in this release.",ah=new Set(["app","desktop","frontmost-app"]);async function ag(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await ta();return{appBundleId:t.bundleId,appName:t.appName}}async function aw(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return eF(t)?"macos"===e.platform?void 0:"device"===e.kind?e5(r,t):void 0:await av(e,t)}async function av(e,t){try{let{resolveIosApp:r}=await import("./155.js");return await r(e,t)}catch{return}}async function ay(e,t){if(!("android"!==e.platform||!t||eF(t)))try{let{resolveAndroidApp:r}=await import("./155.js"),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function aI(e,t,r,a){return await aw(e,t,r)??await a(e,t)??("android"===e.platform&&t&&eF(t)?r:void 0)}function aS(e){return N("INVALID_ARGS",e)}function aA(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=ed(r);if(!ah.has(e))throw new tv("INVALID_ARGS",`Linux supports --surface app, desktop, and frontmost-app (got "${r}")`);if("app"!==e&&a)throw new tv("INVALID_ARGS",`open --surface ${e} does not accept an app target`);return e}if("macos"!==t.platform){if(r)throw new tv("INVALID_ARGS","surface is only supported on macOS and Linux");return"app"}let n=r?ed(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new tv("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return N(e instanceof tv?e.code:"INVALID_ARGS",String(e.message))}}function ab(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&eF(r)?aS("open --relaunch does not support URL targets."):"app"!==a?aS("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===eE(r)?aS(q(r)):null:null}async function a_(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await e8(i);let{appBundleId:l,appName:d}=await aN({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),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 tv("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!an.includes(e));if(i)throw new tv("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${an.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new tv("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new tv("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:al(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new tv("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return ad(e)}}(t.metroPort),bundleUrl:al(t.bundleUrl,"bundleUrl"),launchUrl:al(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:au(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=au(i);if(a.platform&&r&&!n)throw new tv("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 tv("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&&ao(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=tg(t);return N(e.code,e.message,e.details)}}({req:t,sessionStore:a,sessionName:r,device:i});if(!u.ok)return{type:"response",response:u};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await ac({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function aN(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await ag(r);return{appBundleId:n.appBundleId??await aI(t,a,i,ay),appName:n.appName??a}}let ax=new Map;async function aD(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await ey(t.id),await w(t,"close",[r],a,i),await at(t,r8)}async function aM(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||eF(d)||await w(r,"open",[l],a.flags?.out,{...eG(i,a.flags,n,o)})}async function ak(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:f,appBundleId:p,runtime:m,existingSession:h}=e,g=i.flags?.relaunch===!0,v=h?.trace?.outPath;if(g&&d){let e=p??d;await aD({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...eG(s,i.flags,p??h?.appBundleId,v)}})}await eP({device:l,appId:p,runtime:m});let y=Date.now();await w(l,"open",u,i.flags?.out,{...eG(s,i.flags,p)}),await aM({runtime:m,device:l,req:i,logPath:s,appBundleId:p,traceLogPath:v,openPositionals:u});let I=d?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:ap,appTarget:d,appBundleId:p}:void 0;if(await at(l,r6),F(i.meta?.requestId)){let e=eS();return N(e.code,e.message,e.details)}h&&tf(h,"open",h.snapshot);let S=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:n,device:l,surface:f,appBundleId:p,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===ao(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let A=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,...D(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:p,surface:f,startup:I,device:l,runtime:m,runtimeHintCount:ao});return o.recordAction(S,{command:"open",positionals:u,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:A}),o.set(n,S),{ok:!0,data:A}}async function aP(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return N("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=aA(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?aS("open --relaunch requires an app name or an active session app."):aS("Session already active. Close it first or pass a new --session name.");let d=ab({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await aa(e.device),c=await a_({req:t,sessionName:r,sessionStore:i,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await ak({req:t,sessionName:r,sessionStore:i,logPath:a,device:u,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return aS("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&eF(r)?aS("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===eE(r)?aS(q(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await eL(t.flags??{}),d=aA(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=ab({shouldRelaunch:n,openTarget:o,surface:d,device:l});return u||await k(ax,l.id,async()=>{let e=i.toArray().find(e=>e.device.id===l.id);if(e)return N("DEVICE_IN_USE",`Device is already in use by session "${e.name}".`,{session:e.name,deviceId:l.id,deviceName:l.name});let n=await a_({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:o});return"response"===n.type?n.response:await ak({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 aL(e){let t=await th("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 aR(e){let{device:t,shutdownRequested:r}=e;if(r&&(ae(t)||"android"===t.platform&&"emulator"===t.kind))try{return ae(t)?await ev(t):await aL(t)}catch(t){let e=tw(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function aO(e){if(await ey(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await eT("dismiss",t).catch(t=>{tr({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function aC(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return N("SESSION_NOT_FOUND","No active session");n.appLog&&await rh(n.appLog),t.positionals&&t.positionals.length>0&&(("ios"===n.device.platform||"macos"===n.device.platform)&&await aO(n),await w(n.device,"close",t.positionals,t.flags?.out,{...eG(a,t.flags,n.appBundleId,n.trace?.outPath)}),await at(n.device,r8)),("ios"===n.device.platform||"macos"===n.device.platform)&&await aO(n),ep(i.getRuntimeHints(r))&&n.appBundleId&&await eU({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...D(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await r0(r).catch(()=>{}),i.delete(r);let o=await aR({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:ew({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...D(`Closed: ${r}`)}}}let aE=["platform","target","device","udid","serial","verbose","out"];function a$(e,t){let r=e??{};for(let e of aE)void 0===t[e]&&void 0!==r[e]&&(t[e]=r[e]);return t}let aT={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await import("./155.js");return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await import("./155.js");return await a(e,t,r)}},aF={ios:async(e,t,r)=>{let{installIosApp:a}=await import("./155.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("./155.js"),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function aU(e){let{req:t,command:r,sessionName:i,sessionStore:n,deployOps:o}=e,s=n.get(i),l=t.flags??{},d=r9(r,s,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return N("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let f=t.meta?.uploadedArtifactId;try{var p;let e,i=f?rS(f,t.meta?.tenantId):tF.expandHome(c);if(!a.existsSync(i))return N("INVALID_ARGS",`App binary not found: ${i}`);let d=await ar({session:s,flags:l,ensureReady:!1});if(!to(r,d))return N("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await o.ios(d,u,i),r=t.bundleId;e=r?{app:u,appPath:i,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:i,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await o.android(d,u,i),r=t.package;e=r?{app:u,appPath:i,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:i,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=ew(e,(p=e,`Installed: ${p.appName??em(p)}`));return s&&n.recordAction(s,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&rA(f)}}async function aG(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return N("INVALID_ARGS",`Unsupported batch on-error mode: ${a}.`);let i=e.flags?.batchMaxSteps??P;if(!Number.isInteger(i)||i<1||i>1e3)return N("INVALID_ARGS",`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`);try{let a=eu(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await aV(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=tg(t);return N(e.code,e.message,e.details)}}async function aV(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{};return a$(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: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 aq(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new tv("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await aj({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await aH({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await aB(t,u),a=!0)}else t=(await aH({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await aB(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function aj(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await th("xcrun",g(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:W});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||aK(a).includes(aK(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 aH(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await th("xcrun",g(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new tv("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 tv("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function aB(e,t){let r=await th("xcrun",g(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:W});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 aK(e){return e.toLowerCase().replace(/[._-]/g,"")}async function az(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=e1(e.iosSimulatorDeviceSet);if(!r)return N("INVALID_ARGS","ensure-simulator requires --device <name>");let n=await aq({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:e8});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=tg(t);return N(e.code,e.message,e.details)}if("devices"===t.command)try{let e=[],r=et(t.flags?.androidDeviceAllowlist),a=tu(t.flags?.platform),i=h({simulatorSetPath:e1(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await import("./155.js");e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await import("./155.js");e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await import("./155.js");try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await import("./155.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=tg(t);return N(e.code,e.message,e.details)}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=r9(t.command,e,i);if(n)return n;let o=await ar({session:e,flags:i,ensureReady:!0});if(!to("apps",o))return N("UNSUPPORTED_OPERATION","apps is not supported on this device");let s=t.flags?.appsFilter??"all";if(Y(o.platform)){let{listIosApps:e}=await import("./155.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("./155.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 aW(e){let{ensureAndroidEmulatorBooted:t}=await import("./155.js");return await t(e)}let aJ='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',aZ='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function aX(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=tu(n.platform);if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return N("SESSION_NOT_FOUND","ios"===o?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`);let s=r9("appstate",i,n);if(s)return s;let l=(i?.device.platform==="ios"||i?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!r7(e))return!0;let r=tu(e?.platform);return!(r&&!tn(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 N("SESSION_NOT_FOUND",aJ);if("macos"===o&&!l)return N("SESSION_NOT_FOUND",aZ);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 N("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 ar({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return N("SESSION_NOT_FOUND",aJ);if("macos"===d.platform)return N("SESSION_NOT_FOUND",aZ);let{getAndroidAppState:u}=await import("./155.js"),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function aY(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=r9(t.command,i,n);if(o)return o;let s="android"===(tu(n.platform)??i?.device.platform),l=!0===n.headless;if(l&&!s)return N("INVALID_ARGS","boot --headless is supported only for Android emulators.");let d=ai({flags:n,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await ar({session:i,flags:n,ensureReady:!1})}catch(r){let t=tg(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return N("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await aW({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return N("DEVICE_NOT_FOUND",`No ${e.platform} device found matching --target ${n.target}.`);if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return N("INVALID_ARGS","boot --headless is supported only for Android emulators.");if(!c){let t=ai({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return N("INVALID_ARGS","boot --headless requires --device <avd-name> (or an Android emulator session target).");e=await aW({avdName:t,serial:n.serial,headless:!0})}await e8(e)}else("android"!==e.platform||!0!==e.booted)&&await e8(e);return to("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:N("UNSUPPORTED_OPERATION","boot is not supported on this device")}return"appstate"===t.command?await aX({req:t,sessionName:r,sessionStore:a}):null}function aQ(e){return Math.round(10*e)/10}let a0="adb-shell-dumpsys-cpuinfo",a1="adb-shell-dumpsys-meminfo";async function a2(e,t){try{let r=await th("adb",eX(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:aQ(i),measuredAt:r,method:a0,matchedProcesses:[...a]}}(r.stdout,t,new Date().toISOString())}catch(e){throw a3("cpu",t,e)}}async function a5(e,t){try{let r=await th("adb",eX(e,["shell","dumpsys","meminfo",t]),{timeoutMs:15e3});return function(e,t,r){if(/no process found for:/i.test(e))throw new tv("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=a4(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!==a8(e));if(!r)break;return a8(r)??void 0}}(e);if(void 0===a)throw new tv("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:a4(e,"TOTAL RSS"),measuredAt:r,method:a1}}(r.stdout,t,new Date().toISOString())}catch(e){throw a3("memory",t,e)}}function a3(e,t,r){return r instanceof tv&&("TOOL_MISSING"===r.code||"COMMAND_FAILED"===r.code)?new tv(r.code,r.message,{...r.details??{},metric:e,package:t},r):r instanceof tv?r:new tv("COMMAND_FAILED",`Failed to sample Android ${e} for ${t}`,{metric:e,package:t},r)}function a4(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`${r}:\\s*([0-9][0-9,]*)`,"i"));if(a)return a8(a[1])??void 0}function a8(e){let t=e.replaceAll(",","").match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let r=Number(t[0]);return Number.isFinite(r)?r:null}let a6="ps-process-snapshot",a9="ps-process-snapshot",a7="xctrace-activity-monitor",ie="xctrace-activity-monitor";async function it(e,t){if("ios"===e.platform&&"device"===e.kind)return await ii(e,t);let r=await ia(e,t),a=await ic(e,r);if(0===a.length)throw new tv("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(),o=M(a.map(e=>n.basename(ip(e.command))));return im({usagePercent:a.reduce((e,t)=>e+t.cpuPercent,0),residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:i,matchedProcesses:o,cpuMethod:a6,memoryMethod:a9})}async function ir(e){let t=K(e),r=ih(t,e=>"schema"===e.name&&"activity-monitor-process-live"===e.attributes.name);if(!r)throw new tv("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 tv("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=[],u=new Map;for(let e of l){var c,f;let t=e.children;if(0===t.length)continue;for(let e of t){let t=ih(e.children,e=>"pid"===e.name&&"string"==typeof e.attributes.id);if(t?.attributes.id){let e=Number(t.text);u.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&u.set(e.attributes.id,{numberValue:ig(e),processName:iv(e)})}let r=iw(t[i],u),a=(c=t[n],f=u,c?c.attributes.ref?f.get(c.attributes.ref)?.processName??null:iv(c):null);null!==r&&Number.isFinite(r)&&a&&d.push({pid:r,processName:a,cpuTimeNs:iw(t[o],u),residentMemoryBytes:iw(t[s],u)})}return d}async function ia(e,t){let r="macos"===e.platform?await id(t):await iu(e,t),a="macos"===e.platform?n.join(r,"Contents","Info.plist"):n.join(r,"Info.plist"),i=await e9(a,"CFBundleExecutable");if(!i)throw new tv("COMMAND_FAILED",`Failed to resolve executable for ${t}`,{appBundleId:t,appPath:r});return{executableName:i,executablePath:"macos"===e.platform?n.join(r,"Contents","MacOS",i):void 0}}async function ii(e,t){let r=await io(e,t),a=await is(e,t),i=await is(e,t),n=il(await ir(a.xml),r,t,e),o=il(await ir(i.xml),r,t,e),s=i.capturedAtMs-a.capturedAtMs;if(s<=0)throw new tv("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 tv("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 im({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:a7,memoryMethod:ie})}async function io(e,t){let r=(await J(e,"all")).find(e=>e.bundleId===t);if(!r)throw new tv("APP_NOT_INSTALLED",`No iOS device app found for ${t}`,{appBundleId:t,deviceId:e.id});if(!r.url)throw new tv("COMMAND_FAILED",`Missing app bundle URL for ${t}`,{appBundleId:t,deviceId:e.id});let a=r.url.replace(/\/$/,""),i=l(a),n=(await ei(e)).filter(e=>e.executable.startsWith(`${a}/`));if(0===n.length)throw new tv("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 is(e,t){let r=await i.mkdtemp(n.join(u.tmpdir(),"agent-device-ios-perf-")),a=n.join(r,"sample.trace"),o=n.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"],n=await th("xcrun",r,{allowFailure:!0,timeoutMs:6e4}),s=Date.now();if(0!==n.exitCode)throw new tv("COMMAND_FAILED",`Failed to record iOS device Activity Monitor sample for ${t}`,{cmd:"xcrun",args:r,exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,appBundleId:t,deviceId:e.id,hint:iy(n.stdout,n.stderr)});let l=["xctrace","export","--input",a,"--xpath",'/trace-toc/run/data/table[@schema="activity-monitor-process-live"]',"--output",o],d=await th("xcrun",l,{allowFailure:!0,timeoutMs:15e3});if(0!==d.exitCode)throw new tv("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:iy(d.stdout,d.stderr)});return{capturedAtMs:s,xml:await i.readFile(o,"utf8")}}finally{await i.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}function il(e,t,r,a){let i=new Set(t.map(e=>e.pid)),o=new Set(t.map(e=>n.basename(l(e.executable)))),s=e.filter(e=>i.has(e.pid)||o.has(e.processName));if(0===s.length)throw new tv("COMMAND_FAILED",`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:a.id,hint:"Keep the app running in the foreground while perf samples the device, then retry."});let d=new Map;for(let e of s){let t=d.get(e.pid);if(!t){d.set(e.pid,e);continue}d.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,cpuTimeNs:iI(t.cpuTimeNs,e.cpuTimeNs),residentMemoryBytes:iI(t.residentMemoryBytes,e.residentMemoryBytes)})}let u=[...d.values()],c=u.map(e=>e.cpuTimeNs).filter(e=>null!==e),f=u.map(e=>e.residentMemoryBytes).filter(e=>null!==e);return{cpuTimeNs:c.length>0?c.reduce((e,t)=>e+t,0):null,residentMemoryBytes:f.length>0?f.reduce((e,t)=>e+t,0):null,matchedProcesses:M(u.map(e=>e.processName))}}async function id(e){let t=`kMDItemCFBundleIdentifier == "${e.replaceAll('"','\\"')}"`,r=await th("mdfind",[t],{allowFailure:!0,timeoutMs:15e3});if(0!==r.exitCode)throw new tv("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 tv("APP_NOT_INSTALLED",`No macOS app found for ${e}`,{appBundleId:e});return a}async function iu(e,t){let r=te(e,["get_app_container",e.id,t,"app"]),a=await th("xcrun",r,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode)throw new tv("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 tv("APP_NOT_INSTALLED",`No iOS simulator app container found for ${t}`,{appBundleId:t});return i}async function ic(e,t){let r="macos"===e.platform?["-axo","pid=,%cpu=,rss=,command="]:te(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 th("macos"===e.platform?"ps":"xcrun",r,{timeoutMs:15e3})).stdout).filter(e=>{var r,a;let i;return r=e.command,a=t,i=ip(r),!!(a.executablePath&&(i===a.executablePath||r.startsWith(`${a.executablePath} `)))||n.basename(i)===a.executableName})}function ip(e){let[t=""]=e.trim().split(/\s+/,1);return t}function im(e){return{cpu:{usagePercent:aQ(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 ih(e,t){for(let r of e){if(t(r))return r;let e=ih(r.children,t);if(e)return e}}function ig(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 iw(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:ig(e):null}function iv(e){let t=e?.attributes.fmt?.trim()??"";return t?t.replace(/\s+\(\d+\)$/,"").trim():null}function iy(e,t){let r=eb(e,t);if(r)return r;let a=`${e}
|
|
6
|
+
${t}`.toLowerCase();return a.includes("no device matched")||a.includes("failed to find device")?$: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 iI(e,t){return null===e?t:null===t?e:Math.max(e,t)}async function iS(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===ap&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:ap,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:ap,sampleCount:r.length,samples:r}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:ap},n={session:e.name,platform:e.device.platform,device:e.device.name,deviceId:e.device.id,metrics:{startup:i,fps:{available:!1,reason:am},memory:{available:!1,reason:am},cpu:{available:!1,reason:am}},sampling:{startup:{method:ap,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:a1,description:"Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.",unit:"kB"},cpu:{method:a0,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:ie,description:"Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.",unit:"kB"},cpu:{method:a7,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:a9,description:`Resident memory snapshot from ${r}`,unit:"kB"},cpu:{method:a6,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 iA(e);return n.metrics.memory=ib(o),n.metrics.cpu=ib(s),n}async function iA(e){let t=e.appBundleId;if("android"===e.device.platform){let[r,a]=await Promise.allSettled([a5(e.device,t),a2(e.device,t)]);return[r,a]}try{let r=await it(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 ib(e){if("fulfilled"===e.status)return{available:!0,...e.value};let t=tw(e.reason);return{available:!1,reason:t.message,error:t}}let i_=["path","start","stop","doctor","mark","clear"],iN=`logs requires ${i_.slice(0,-1).join(", ")}, or ${i_.at(-1)}`,ix=["dump","log"],iD=`network requires ${ix.join(" or ")}`,iM=["summary","headers","body","all"],ik=`network include mode must be one of: ${iM.join(", ")}`;async function iP(e){let{req:t}=e;return"perf"===t.command?iL(e):"logs"===t.command?iR(e):"network"===t.command?iT(e):null}async function iL(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return N("SESSION_NOT_FOUND","perf requires an active session. Run open first.");try{return{ok:!0,data:await iS(a)}}catch(e){return{ok:!1,error:tw(e)}}}async function iR(e){let{req:t,sessionName:r,sessionStore:i}=e,n=i.get(r);if(!n)return N("SESSION_NOT_FOUND","logs requires an active session");if(!to("logs",n.device))return N("UNSUPPORTED_OPERATION","logs is not supported on this device");let o=(t.positionals?.[0]??"path").toLowerCase(),s=!!t.flags?.restart;return i_.includes(o)?s&&"clear"!==o?N("INVALID_ARGS","logs --restart is only supported with logs clear"):"path"===o?function(e,t,r){let i=r.resolveAppLogPath(t),n=function(e){if(!a.existsSync(e))return{exists:!1,sizeBytes:0};let t=a.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(i);return{ok:!0,data:{path:i,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,i):"doctor"===o?iO(n,r,i):"mark"===o?function(e,t,r){let i,n=e.positionals?.slice(1).join(" ")??"",o=r.resolveAppLogPath(t);return ru(o),i=`[agent-device][mark][${new Date().toISOString()}] ${n.trim()||"marker"}
|
|
7
|
+
`,a.appendFileSync(o,i,"utf8"),{ok:!0,data:{path:o,marked:!0}}}(t,r,i):"clear"===o?iC(n,r,i,s):"start"===o?iE(n,r,i):"stop"===o?i$(n,r,i):N("INVALID_ARGS",iN):N("INVALID_ARGS",iN)}async function iO(e,t,r){let a=r.resolveAppLogPath(t),i=await rg(e.device,e.appBundleId);return{ok:!0,data:{path:a,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}async function iC(e,t,r,a){if(e.appLog&&!a)return N("INVALID_ARGS","logs clear requires logs to be stopped first; run logs stop");if(a&&!e.appBundleId)return N("INVALID_ARGS","logs clear --restart requires an app session; run open <app> first");let i=r.resolveAppLogPath(t);if(!a)return{ok:!0,data:rw(i)};e.appLog&&await rh(e.appLog);let n=rw(i),o=r.resolveAppLogPidPath(t);try{let a=await rp(e.device,e.appBundleId,i,o);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:a.backend,outPath:i,startedAt:a.startedAt,getState:a.getState,stop:a.stop,wait:a.wait}}),{ok:!0,data:{...n,restarted:!0}}}catch(a){return r.set(t,{...e,appLog:void 0}),{ok:!1,error:tw(a)}}}async function iE(e,t,r){if(e.appLog)return N("INVALID_ARGS","app log already streaming; run logs stop first");if(!e.appBundleId)return N("INVALID_ARGS","logs start requires an app session; run open <app> first");let a=r.resolveAppLogPath(t),i=r.resolveAppLogPidPath(t);try{let n=await rp(e.device,e.appBundleId,a,i);return r.set(t,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:a,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{path:a,started:!0}}}catch(e){return{ok:!1,error:tw(e)}}}async function i$(e,t,r){if(!e.appLog)return N("INVALID_ARGS","no app log stream active");let a=e.appLog.outPath;return await rh(e.appLog),r.set(t,{...e,appLog:void 0}),{ok:!0,data:{path:a,stopped:!0}}}async function iT(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);if(!i)return N("SESSION_NOT_FOUND","network requires an active session");if(!to("network",i.device))return N("UNSUPPORTED_OPERATION","network is not supported on this device");let n=(t.positionals?.[0]??"dump").toLowerCase();if(!ix.includes(n))return N("INVALID_ARGS",iD);let o=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(o)||o<1||o>200)return N("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 N("INVALID_ARGS","network include mode was provided both positionally and via --include with different values");let a=(r??t??"summary").toLowerCase();return iM.includes(a)?{ok:!0,include:a}:N("INVALID_ARGS",ik)}(t);if(!s.ok)return s;let{include:l}=s,d=await rc({device:i.device,appBundleId:i.appBundleId,appLogState:i.appLog?.getState(),appLogStartedAt:i.appLog?.startedAt,appLogPath:a.resolveAppLogPath(r),maxEntries:o,include:l,maxPayloadChars:2048,maxScanLines:4e3});return{ok:!0,data:{...d.dump,active:!!i.appLog,state:i.appLog?.getState()??"inactive",backend:d.backend,notes:d.notes}}}let iF=new Set(["ios","android","macos","linux"]);function iU(e,t,r){let a=e[t];if(void 0!==a)throw new tv("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 iG(e){return!!e&&!Number.isNaN(Number(e))}let iV=/[*?[\]{}]/;async function iq(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,runReplay:s,cleanupSession:l}=e;b(i);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:i,artifactPaths:d}).catch(e=>{let t=tg(e);return N(t.code,t.message)}).finally(()=>{B(i)});try{return"number"==typeof n?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,e2(i),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(n,[...d]))},n)})]):await c}finally{t&&clearTimeout(t),u&&(await ij(c)||tr({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await l(a)}catch(e){tr({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:tg(e).message}})}}}async function ij(e){return await Promise.race([e.then(()=>!0),f(2e3).then(()=>!1)])}async function iH(e){let{req:t,sessionName:r,runReplay:i,cleanupSession:o}=e;if((t.positionals?.length??0)===0)return N("INVALID_ARGS","test requires at least one path or glob");try{var s,l,d,u,c,f;let e,p,m,h,g,w=function(e){let{inputs:t,cwd:r,platformFilter:i}=e,o=r??process.cwd(),s=[...new Set(t.flatMap(e=>(function(e,t){var r,i;let o=tF.expandHome(e,t);if(a.existsSync(o)){let t=a.statSync(o);if(t.isDirectory())return a.globSync("**/*.ad",{cwd:o}).map(e=>n.join(o,e));if(t.isFile()){if(".ad"!==n.extname(o))throw new tv("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[o]}return[]}if(r=e,!iV.test(r)&&(i=o,!iV.test(i)))throw new tv("INVALID_ARGS",`test input not found: ${e}`);let s=n.isAbsolute(o)?o:e;return a.globSync(s,{cwd:n.isAbsolute(o)?void 0:t}).map(e=>n.isAbsolute(e)?e:n.resolve(t,e)).filter(e=>".ad"===n.extname(e)&&function(e){try{return a.statSync(e).isFile()}catch{return!1}}(e))})(e,o)))].map(e=>n.normalize(e)).sort((e,t)=>e.localeCompare(t)),l=[];for(let e of s){var d,u;let t=function(e){let t=e.split(/\r?\n/),r={};for(let e of t){let t=e.trim();if(0===t.length||t.startsWith("#"))continue;if(!t.startsWith("context "))break;let a=t.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&iF.has(e)&&iU(r,"platform",e)}let i=t.match(/(?:^|\s)timeout=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=1&&iU(r,"timeoutMs",Math.floor(e))}let n=t.match(/(?:^|\s)retries=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=0&&iU(r,"retries",Math.floor(e))}}return r}(a.readFileSync(e,"utf8"));if(!i){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 ${i}`});continue}d=i,u=t.platform,("apple"===d?"apple"===u||"ios"===u||"macos"===u:u===d)&&l.push({kind:"run",path:e,metadata:t})}if(0===l.filter(e=>"run"===e.kind).length){let e=i?` for --platform ${i}`:"";throw new tv("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=tF.expandHome(t??".agent-device/test-artifacts",r);return n.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 a=await iB({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:i,cleanupSession:o});if(I.push(a),t.flags?.failFast===!0)break}let b=(u=w.length,c=I,f=Date.now()-S,e=c.filter(e=>"passed"===e.status).length,m=(p=c.filter(e=>"failed"===e.status)).length,h=c.filter(e=>"skipped"===e.status).length,g=e+m,{total:u,executed:g,passed:e,failed:m,skipped:h,notRun:Math.max(0,u-g-h),durationMs:f,failures:p,tests:c});return{ok:!0,data:b}}catch(t){let e=tg(t);return N(e.code,e.message)}}async function iB(e){var t,r;let i,o,{entry:s,sessionName:l,suiteInvocationId:d,caseIndex:u,cwd:c,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:g,cleanupSession:w}=e,v=Date.now(),y=n.join(h,(t=s.path,(0===(o=c?n.relative(c,t):n.basename(t)).length||o.startsWith("..")?n.basename(t):o).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 o=n.basename(r,n.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${o?`-${o}`:""}:attempt-${i+1}`}(l,d,s.path,u,e),o=n.join(y,`attempt-${S}`);r=s.path,a.mkdirSync(o,{recursive:!0}),a.copyFileSync(r,n.join(o,"replay.ad"));let c=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:o}=e;return U(`${t??r}:test:${i+1}:${n.basename(a)}:attempt:${o+1}`,r)}({requestId:f,suiteInvocationId:d,filePath:s.path,caseIndex:u,attemptIndex:e}),h=await iq({filePath:s.path,sessionName:t,requestId:c,timeoutMs:m,platform:s.metadata.platform,runReplay:g,cleanupSession:w});if(!function(e){let{response:t,filePath:r,sessionName:i,attempts:o,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 u=function(e,t){let r=[],i=new Map;for(let o of e){if(!function(e){try{return a.statSync(e).isFile()}catch{return!1}}(o))continue;let e=function(e,t){let r=n.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}`}(n.basename(o),i),s=n.join(t,e);n.resolve(o)!==n.resolve(s)&&a.copyFileSync(o,s),r.push(s)}return r}(d,l),c=[`file: ${r}`,`session: ${i}`,`attempt: ${o}/${s}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;c.push(`replayed: ${e}`,`healed: ${r}`)}else c.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&c.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&c.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&c.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&c.push("timeoutMode: cooperative");u.length>0&&c.push(`copiedArtifacts: ${u.map(e=>n.basename(e)).join(", ")}`);let f=n.join(l,"result.txt"),p=`${c.join("\n")}
|
|
8
|
+
`;a.writeFileSync(f,p),t.ok||a.writeFileSync(n.join(l,"failure.txt"),p)}({response:h,filePath:s.path,sessionName:t,attempts:S,maxAttempts:p+1,attemptArtifactsDir:o}),i=h,I=t,h.ok)break}let A=Date.now()-v;if(i?.ok)return{file:s.path,session:I,status:"passed",durationMs:A,attempts:S,artifactsDir:y,replayed:"number"==typeof i.data?.replayed?i.data.replayed:0,healed:"number"==typeof i.data?.healed?i.data.healed:0};let b=i?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:i?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:s.path,session:I,status:"failed",durationMs:A,attempts:S,artifactsDir:y,error:b}}function iK(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=eo(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 iz(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(t_(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),t_(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}=eZ(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=iK(e.positionals??[]);r&&t.push(r)}return M(t).filter(e=>e.trim().length>0)})(t).map(e=>j(e)).filter(e=>null!==e);if(0===o.length)return null;let s=t_(t.command)||"fill"===t.command,l=t_(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await iW(n,t,a,s,i);for(let e of o){let r=A(d.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=eg(r.node,n.device.platform,{action:t_(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(t_(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=eh(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}=eZ(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}=iK(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function iW(e,t,r,a,i){let n=await w(e.device,"snapshot",[],t.flags?.out,{...eG(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:ea(t.flags?.snapshotRaw?o:ek(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return e.snapshot=s,i.set(e.name,e),s}async function iJ(e){let{req:t,sessionName:r,logPath:i,sessionStore:n,invoke:o}=e,s=t.positionals?.[0];if(!s)return N("INVALID_ARGS","replay requires a path");let l="",d=new Set;try{l=tF.expandHome(s,t.meta?.cwd);let e=a.readFileSync(l,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return N("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let c=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=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 tv("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=tE(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=tE(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(t_(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 iG(r)&&iG(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}e.push(r)}return n.positionals=e,n}if("screenshot"===a){let e=[];for(let t of i){if("--fullscreen"===t){n.flags.screenshotFullscreen=!0;continue}e.push(t)}return n.positionals=e,n}return n.positionals=i,n}(r);e&&t.push(e)}return t}(e),f=t.flags?.replayUpdate===!0,p=0;for(let e=0;e<c.length;e+=1){let a=c[e];if(!a||"replay"===a.command)continue;let s=await iZ({req:t,sessionName:r,action:a,invoke:o});if(s.ok){iY(s).forEach(e=>d.add(e));continue}if(!f)return iX(s,a,e,l,[...d]);let u=await iz({action:a,sessionName:r,logPath:i,sessionStore:n});if(!u)return iX(s,a,e,l,[...d]);if(c[e]=u,!(s=await iZ({req:t,sessionName:r,action:u,invoke:o})).ok)return iX(s,u,e,l,[...d]);iY(s).forEach(e=>d.add(e)),p+=1}return f&&p>0&&function(e,t,r){let i=[];if(r){let e=r.device.kind?` kind=${r.device.kind}`:"",t=r.device.target?` target=${r.device.target}`:"";i.push(`context platform=${r.device.platform}${t} device=${tD(r.device.name)}${e} theme=unknown`)}for(let e of t)i.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tx(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return tT(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(tM(r,tP));return tR(t,e.flags),t.join(" ")}if("record"===e.command)return tO(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(tx(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}for(let r of e.positionals??[])t.push(tx(r));return tL(t,e),t.join(" ")}(e));let n=`${i.join("\n")}
|
|
9
|
+
`,o=`${e}.tmp-${process.pid}-${Date.now()}`;a.writeFileSync(o,n),a.renameSync(o,e)}(l,c,n.get(r)),{ok:!0,data:{replayed:c.length,healed:p,session:r,artifactPaths:[...d]}}}catch(t){let e=tg(t);return N(e.code,e.message,d.size>0?{artifactPaths:[...d]}:void 0)}}async function iZ(e){var t;let{req:r,sessionName:a,action:i,invoke:n}=e;return await n({token:r.token,session:a,command:i.command,positionals:i.positionals??[],flags:(t=r.flags,a$(t,{...i.flags??{}})),runtime:i.runtime,meta:r.meta})}function iX(e,t,r,a,i=[]){let n;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${n=(t.positionals??[]).map(e=>tx(e)),[t.command,...n].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:a,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:i}}}}function iY(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 a.statSync(e).isFile()}catch{return!1}})(e)))]}async function iQ(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await iJ({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await iH({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await iJ({req:{...t,command:"replay",session:r,positionals:[e],flags:void 0===o?t.flags:{...t.flags??{},platform:o},meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),l&&iY(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{i.get(e)&&await aC({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let i0=new Set(["session_list","ensure-simulator","devices","apps"]),i1=new Set(["boot","appstate"]),i2=new Set(["perf","logs","network"]),i5=new Set(["replay","test"]);async function i3(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=i.get(r),u=t.flags??{},c=r9(n,d,u);if(c)return c;let f=await ar({session:d,flags:u,ensureReady:!0});if(!to(n,f))return N("UNSUPPORTED_OPERATION",`${n} is not supported on this device`);let p=await w(f,n,o,t.flags?.out,{...eG(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 i4(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=r9("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return N("INVALID_ARGS","clipboard requires a subcommand: read or write");let d=await ar({session:n,flags:o,ensureReady:!0});if(!to("clipboard",d))return N("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let u=await w(d,"clipboard",t.positionals??[],t.flags?.out,{...eG(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function i8(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(i0.has(t.command))return await az({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await af({req:t,sessionName:r,sessionStore:i});if(i1.has(t.command))return await aY({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await i4({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"!==tu((t.flags??{}).platform)?await i3({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):N("SESSION_NOT_FOUND","iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first.")}if(i2.has(t.command))return await iP({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await aU({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?aF:aT});if("install_source"===t.command)return await r5({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await r4({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await i3({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=eQ(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>tF.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):N("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return"trigger-app-event"===t.command?await i3({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 aI(e.device,r,e.appBundleId,ay)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await aP({req:t,sessionName:r,logPath:a,sessionStore:i}):i5.has(t.command)?await iQ({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await aG(t,r,n):"close"===t.command?await aC({req:t,sessionName:r,logPath:a,sessionStore:i}):null}function i6(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return N("INVALID_ARGS","No snapshot in session. Run snapshot first.");let s=eC(r);if(!s)return N("INVALID_ARGS",n);let l=ex(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=ti(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:N("COMMAND_FAILED",o)}function i9(e){let t=i7(e);if(!t)return null;let r=ee(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function i7(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}async function ne(e){let{session:t,refInput:r,fallbackLabel:a,commandLabel:i,promoteToHittableAncestor:n,invalidRefMessage:o,missingBoundsMessage:s,invalidBoundsMessage:l,reqFlags:d,sessionStore:u,contextFromFlags:c,captureSnapshotForSession:f,resolveRefTarget:p}=e,m=p({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:o,notFoundMessage:s});if(!m.ok)return m;let{ref:h}=m.target,g=n?nt(m.target.snapshotNodes,m.target.node):m.target.node,w=m.target.snapshotNodes,y=i9(g.rect);if(!y){let e=await f(t,d,u,c,{interactiveOnly:!0}),r=ex(e.nodes,h),i=a.length>0?ti(e.nodes,a):null,o=r&&n?nt(e.nodes,r):r,s=i&&n?nt(e.nodes,i):i,l=i9(s?.rect),p=i9(o?.rect)?o:l?s:o??s,m=i9(p?.rect);p&&m&&(g=p,w=e.nodes,y=m)}if(!y)return N("COMMAND_FAILED",l);let I=g.rect?e0(g,w):null;return g.rect&&I&&!v(g,w)?{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${r} is off-screen and not safe to ${i}`,hint:`Use scroll with the direction from the off-screen summary, take a fresh snapshot, then retry ${i} with the new ref or a selector.`,details:{reason:"offscreen_ref",ref:h,rect:g.rect,viewport:I}}}:{ok:!0,target:{ref:h,node:g,snapshotNodes:w,point:y}}}function nt(e,t){let r=function(e,t){let r=i7(t.rect);if(!r)return null;let a=t,i=new Set;for(;!i.has(a.ref);){i.add(a.ref);let t=e.filter(e=>{if(e.parentIndex!==a.index||!e.hittable)return!1;let t=i7(e.rect);return!!t&&nr(t,r)});if(1!==t.length)break;a=t[0]}return a===t?null:a}(e,t);if(r?.rect&&i9(r.rect))return r;let a=z(e,t);return a?.rect&&i9(a.rect)?!function(e,t,r){var a,i,n,o;let s,l,d,u=i7(e.rect),c=i7(t.rect);if(!u||!c)return!1;let f=function(e,t){let r=ee(t),a=e.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}).map(e=>i7(e.rect)).filter(e=>null!==e);if(0===a.length)return null;let i=a.filter(e=>C(e,r.x,r.y));return x(i.length>0?i:a)}(r,u);return!!f&&(a=c,i=f,s=(n=a,o=i,Math.max(0,Math.min(n.x+n.width,o.x+o.width)-Math.max(n.x,o.x))*Math.max(0,Math.min(n.y+n.height,o.y+o.height)-Math.max(n.y,o.y))),l=a.width*a.height,d=i.width*i.height,!(s<=0)&&!(l<=0)&&!(d<=0)&&!!(s/d>=.9)&&!!(s/l>=.8))&&!nr(u,c)}(t,a,e)?a:t:t}function nr(e,t){return .5>=Math.abs(e.x-t.x)&&.5>=Math.abs(e.y-t.y)&&.5>=Math.abs(e.width-t.width)&&.5>=Math.abs(e.height-t.height)}async function na(e){let{device:t,node:r,flags:a,appBundleId:i,traceOutPath:n,surface:o,contextFromFlags:s}=e,l=R(r),d=i9(r.rect);if(!d)return l;try{let e=await w(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,i,n),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return tr({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return tr({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}async function ni(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 N("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:u,value:c,timeoutMs:f}=eV(s);if(!d)return N("INVALID_ARGS","find requires a value");if(t.flags?.findFirst&&t.flags?.findLast)return N("INVALID_ARGS","find accepts only one of --first or --last");let p=i.get(r);if(!p&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return N("SESSION_NOT_FOUND","No active session. Run open first.");let m=p?.device??await eL(t.flags??{});p||await e8(m);let h="role"!==l?d:void 0,g="click"===u||"focus"===u||"fill"===u||"type"===u,w=0,v=null,y=async()=>{let e=Date.now();if(v&&e-w<750&&!e7(p))return{nodes:v};let{snapshot:n}=await ej({device:m,session:p,flags:{...t.flags,snapshotInteractiveOnly:g,snapshotCompact:g},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=n.nodes;return w=e,v=o,p&&(p.snapshot=n,i.set(r,p)),{nodes:o,truncated:n.truncated,backend:n.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:p,device:m,command:o,locator:l,query:d};if("wait"===u)return nn(I,y,l,d,f);let{nodes:S}=await y(),A=tt(S,l,d,{requireRect:g});if(g&&A.matches.length>1)if(t.flags?.findFirst)A.matches=[A.matches[0]];else{if(!t.flags?.findLast){var b,_,x;let e;return b=A.matches,_=l,x=d,e=b.slice(0,8).map(e=>{let t=E(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),N("AMBIGUOUS_MATCH",`find matched ${b.length} elements for ${_} "${x}". Use a more specific locator or selector.`,{locator:_,query:x,matches:b.length,candidates:e})}A.matches=[A.matches[A.matches.length-1]]}let D=A.matches[0]??null;if(!D)return N("COMMAND_FAILED","find did not match any element");let M="click"===u||"focus"===u||"fill"===u||"type"===u?z(S,D)??D:D,k=`@${M.ref}`,P={node:D,resolvedNode:M,ref:k,nodes:S,actionFlags:{...t.flags??{},noRecord:!0}},L={exists:()=>no(I),get_text:()=>ns(I,P),get_attrs:()=>nl(I,P),click:()=>nd(I,P),fill:()=>nu(I,P,c),focus:()=>nc(I,P),type:()=>nf(I,P,c)}[u];return L?L():null}async function nn(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,d=i??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(tt(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()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return N("COMMAND_FAILED","find wait timed out")}async function no(e){let{req:t,sessionStore:r,session:a,command:i}=e;return a&&r.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function ns(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await na({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>eG(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 nl(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 nd(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:d}=e,u=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?ee(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:d};return c&&(f.x=c.x,f.y=c.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:f}}async function nu(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return N("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 nc(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?ee(t.node.rect):null;if(!l)return N("COMMAND_FAILED","matched element has no bounds");let d=await w(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...eG(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 nf(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return N("INVALID_ARGS","find type requires text");let d=t.node.rect?ee(t.node.rect):null;if(!d)return N("COMMAND_FAILED","matched element has no bounds");await w(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...eG(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let u=await w(o,"type",[r],a.flags?.out,{...eG(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:u??{ref:t.ref}}}let np=`
|
|
10
10
|
import Foundation
|
|
11
11
|
import AVFoundation
|
|
12
12
|
|
|
@@ -30,11 +30,11 @@ Task {
|
|
|
30
30
|
|
|
31
31
|
semaphore.wait()
|
|
32
32
|
exit(exitCode)
|
|
33
|
-
`.trim();async function
|
|
34
|
-
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return ny(e);return!1}catch(t){if(t instanceof tI&&"TOOL_MISSING"===t.code)return ny(e);throw t}}async function nv(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nw(e))return;await new Promise(e=>setTimeout(e,r))}}function ny(e){try{let t=a.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=a.openSync(e,"r");try{let e=a.fstatSync(t).size,r=0,i=[];for(;r+8<=e&&i.length<16;){let e=Buffer.alloc(8);if(8>a.readSync(t,e,0,8,r))break;let n=e.readUInt32BE(0),o=e.toString("latin1",4,8);if(i.push(o),1===n){let e=Buffer.alloc(8);if(8>a.readSync(t,e,0,8,r+8))break;n=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(n)||n<=0)break;r+=n}return i}finally{a.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function nI(e){let t=n.parse(e);return n.join(t.dir,`${t.name}.gesture-telemetry.json`)}function nS(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nA(e){let t=n.dirname(l(import.meta.url)),r=[l(new URL(`./${e}`,import.meta.url)),n.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(a.existsSync(e))return e;throw new tI("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 nb(e){let{videoPath:t,scriptPath:r,scriptArgs:i,commandDescription:o}=e;await ng(t),await nv(t);let s=a.mkdtempSync(n.join(u.tmpdir(),"agent-device-record-overlay-")),l=n.join(s,`input${n.extname(t)||".mp4"}`),d=n.join(s,n.basename(t)),c=n.join(s,"home"),f=n.join(s,"module-cache");a.copyFileSync(t,l),a.mkdirSync(c,{recursive:!0}),a.mkdirSync(f,{recursive:!0});try{await tw("xcrun",["swift",r,"--input",l,"--output",d,...i],{timeoutMs:12e4,env:{...process.env,HOME:c,CLANG_MODULE_CACHE_PATH:f}}),await nv(d),a.copyFileSync(d,t)}catch(a){let e=a instanceof tI?a:new tI("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new tI("COMMAND_FAILED",o,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{a.rmSync(s,{recursive:!0,force:!0})}}async function n_(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nb({videoPath:r,scriptPath:t??=nA("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nN(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nb({videoPath:r,scriptPath:e??=nA("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function nx(e){return e instanceof Error?e.message:String(e)}function nM(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function nk(e){let{recording:t,deps:r,trimStartMs:i,targetLabel:n}=e,o=function(e){var t,r,i;let n,o,{recording:s,trimStartMs:l}=e,d=(n=nI((t={videoPath:s.outPath,events:s.gestureEvents,trimStartMs:l}).videoPath),o={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(i=t.trimStartMs??0)>0?nS(r.flatMap(e=>{let t=e.tMs-i,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):nS(r))},a.writeFileSync(n,JSON.stringify(o,null,2)),n);return s.telemetryPath=d,d}({recording:t,trimStartMs:i});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: ${nx(e)}`}}}async function nD(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 nP(e,t,r){for(let a=0;a<40;a+=1){if(!await nD(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await nD(e,t,r)}async function nL(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 new Promise(e=>setTimeout(e,250))}}async function nR(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 nD(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function nO(e){let t,{deps:r,deviceId:i,remotePath:n,outPath:o}=e;for(let e=0;e<2;e+=1){try{a.rmSync(o,{force:!0})}catch{}let s=await r.runCmd("adb",["-s",i,"pull",n,o],{allowFailure:!0});if(0!==s.exitCode)t=nM(s,"adb pull");else{await r.waitForStableFile(o,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(o);if(ti({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:i,remotePath:n,outPath:o,attempt:e+1,fileSize:(()=>{try{return a.statSync(o).size}catch{return 0}})(),playable:t}}),t)return;ti({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:i,remotePath:n,outPath:o,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,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 nE(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function nC(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return ti({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 nD(e,t,r))&&await nP(e,t,r)}async function n$(e){var t;let r,{deps:a,device:i,recordingBase:n}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",i.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${nM(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){o="failed to start recording: adb did not return a valid Android screenrecord pid",await nE(a,i.id,e);continue}if(ti({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await nR(a,i.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...n,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await nC(a,i.id,r),await nE(a,i.id,e)}return N("COMMAND_FAILED",o)}async function nT(e){let t,r,{deps:a,device:i,recording:n}=e;ti({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(ti({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 nD(a,i.id,n.remotePid)&&!await nC(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${nM(o,"adb shell kill")}`):await nP(a,i.id,n.remotePid)||await nC(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await nL(a,i.id,n.remotePath);let e=await nO({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),N("COMMAND_FAILED",e);await nk({recording:n,deps:a,targetLabel:"Android recording"})}if(await s(),t)return N("COMMAND_FAILED",t);if(r)return N("COMMAND_FAILED",r);return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});ti({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: ${nM(e,"adb shell rm")}`)}}function nF(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function nU(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function nG(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=nF(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},nU(t,i,r))}catch(e){ti({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:nx(e)}})}}async function nV(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=nU(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:f,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var g,w;if(!nx(a).toLowerCase().includes("recording already in progress"))return N("COMMAND_FAILED",`failed to start recording: ${nx(a)}`);ti({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:nx(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 N("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return N("COMMAND_FAILED",`failed to start recording: ${nx(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function nq(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,appBundleId:l},nU(t,i,r))}catch(e){return N("COMMAND_FAILED",`failed to start recording: ${nx(e)}`)}return{platform:"macos-runner",...s}}async function nj(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=nF(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nU(t,i,r))}catch(e){ti({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nx(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of ef)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 N("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 nk({recording:o,deps:n,trimStartMs:d,targetLabel:"iOS recording"}),null}async function nB(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=nF(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nU(t,i,r))}catch(e){ti({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:nx(e)}})}return await nk({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function nH(e){for(let t=0;t<2;t+=1){try{if(a.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function nK(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await nG({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:u,wait:c}=s.runCmdBackground("xcrun",tr(n,["io",n.id,"recordVideo",d]),{allowFailure:!0}),f=await nH(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:nF(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:u,wait:c,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function nz(e){let t,{req:r,sessionName:i,sessionStore:o,activeSession:s,device:l,logPath:d,deps:u}=e;if(s.recording)return N("INVALID_ARGS","recording already in progress");let c=r.flags?.fps;if(void 0!==c&&(!Number.isInteger(c)||c<1||c>120))return N("INVALID_ARGS","fps must be an integer between 1 and 120");if(!tl("record",l))return N("UNSUPPORTED_OPERATION","record is not supported on this device");let f=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,p=tG.expandHome(f,r.meta?.cwd),m={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(a.mkdirSync(n.dirname(p),{recursive:!0}),a.rmSync(p,{force:!0}),"ios"===l.platform&&"device"===l.kind){let e=nF(s);if(!e)return N("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await nV({req:r,activeSession:s,sessionStore:o,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:m,appBundleId:e})}else if("macos"===l.platform){let e=nF(s);if(!e)return N("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await nq({req:r,activeSession:s,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:m,appBundleId:e})}else t="ios"===l.platform?await nK({req:r,activeSession:s,device:l,logPath:d,deps:u,recordingBase:m,resolvedOut:p}):await n$({deps:u,device:l,recordingBase:m});return"ok"in t?t:(s.recording=t,o.set(i,s),o.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??f,showTouches:t.showTouches}})}async function nW(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await nT({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;return 0!==i.exitCode?N("COMMAND_FAILED",`failed to stop recording: ${nM(i,"simctl recordVideo")}`):(await nk({recording:a,deps:t,targetLabel:"iOS recording"}),null)}async function nJ(e){var t;let r,{req:a,activeSession:i,device:o,logPath:s,deps:l}=e;if(!i.recording)return N("INVALID_ARGS","no active recording");let d=i.recording,u=d.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===d.platform?await nj({req:a,activeSession:i,device:o,logPath:s,deps:l,recording:d}):"macos-runner"===d.platform?await nB({req:a,activeSession:i,device:o,logPath:s,deps:l,recording:d}):await nW({deps:l,device:o,recording:d});return c||(u?N("COMMAND_FAILED",u):(r=[{field:"outPath",path:(t=d).outPath,localPath:t.clientOutPath,fileName:n.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return nI(e.clientOutPath)}(t),fileName:n.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function nZ(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:tw,runCmdBackground:tg,runIosRunnerCommand:e8,waitForStableFile:ng,isPlayableVideo:nw,trimRecordingStart:n_,overlayRecordingTouches:nN},o=a.get(r),s=o?.device??await eR(t.flags??{});o||await e9(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return N("INVALID_ARGS","record requires start|stop");if("start"===d)return nz({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await nJ({req:t,activeSession:l,device:s,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function nY(e){let{req:t,sessionName:r,sessionStore:i,logPath:o}=e,s=t.command;if("record"===s)return nZ({req:t,sessionName:r,sessionStore:i,logPath:o});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return N("INVALID_ARGS","trace requires start|stop");let o=i.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session");if("start"===e){if(o.trace)return N("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??i.defaultTracePath(o),r=tG.expandHome(e);return a.mkdirSync(n.dirname(r),{recursive:!0}),a.appendFileSync(r,""),o.trace={outPath:r,startedAt:Date.now()},i.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!o.trace)return N("INVALID_ARGS","no active trace");let l=o.trace.outPath;if(t.positionals?.[1]){let e=tG.expandHome(t.positionals[1]);a.mkdirSync(n.dirname(e),{recursive:!0}),a.existsSync(l)?a.renameSync(l,e):a.appendFileSync(e,""),l=e}return o.trace=void 0,i.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l}}),{ok:!0,data:{trace:"stopped",outPath:l}}}return null}function nX(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 nQ=new WeakMap;function n0(e){if(!e)return;let t=nQ.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)&&n1(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(n1);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 nQ.set(e,r),r}function n1(e){return!!e&&e.width>0&&e.height>0}let n2={referenceWidth:1e3,referenceHeight:1e3};function n5(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,f=e.recording;if(!f)return;let p={...i,...a??{}},m=n6(p.effectiveDurationMs)??n6(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:n6(p.gestureStartUptimeMs),gestureEndUptimeMs:n6(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:n6(p.gestureStartUptimeMs),gestureEndUptimeMs:n6(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===n6(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=n9(n6(t.count),1)??1,r=!0===t.doubleTap,a=n9(n6(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 nX(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):nX(h),v=(l=e.snapshot,u=n6((d=p).referenceWidth),c=n6(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:n0(l)),y=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=n7(t,e);if(!i)return[];let{x:n,y:o}=i,s=n9(n6(t.count),1)??1,l=n9(n6(t.intervalMs),0)??0,d=!0===t.doubleTap,u=n9(n6(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(n3(t,n,o,u,a));continue}c.push(n4(t,n,o,a)),d&&c.push(n4(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=n7(t,e);if(!i)return[];let{x:n,y:o}=i;return[n4(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=n7(t,e);if(!n)return[];let{x:o,y:s}=n;return[n3(r,o,s,ot(a,[n6(t.durationMs),n6(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=oe(t,e),o=n8(t.contentDirection)??n8(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=ot(a,[],250),f=n6(t.amount)??n6(e[1]),p=n6(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==f?{amount:f}:{},...void 0!==p?{pixels:p}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=oe(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=ot(a,[n6(t.effectiveDurationMs),n6(t.durationMs),n6(e[4])],250),c=n9(n6(t.count),1)??1,f=n9(n6(t.pauseMs),0)??0,p="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===p&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,g=r+e*(u+f);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=n7(t,e,1),o=n6(t.scale)??n6(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:ot(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,w,g,v);0!==y.length&&(f.gestureEvents.push(...y),ti({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 n4(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function n3(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function n8(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 n6(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 n9(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function n7(e,t,r=0){let a=n6(e.x)??n6(t[r]),i=n6(e.y)??n6(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function oe(e,t){let r=n6(e.x1)??n6(t[0]),a=n6(e.y1)??n6(t[1]),i=n6(e.x2)??n6(t[2]),n=n6(e.y2)??n6(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 ot(e,t,r){return n9(e,1)??t.map(e=>n9(e,1)).find(e=>void 0!==e)??r}function or(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,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??{},...u??{},...o??{},...M(c)}}async function oa(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:i,flags:n,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,afterDispatch:u,buildPayloads:c}=e,f=await oi({session:t,flags:n,contextFromFlags:o,command:s,positionals:l,outPath:d});await u?.(f.data);let{result:p,responseData:m=p}=await c(f.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),eb(a)&&tm(t,a),n5(t,a,i,o,n??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:i,flags:n,result:p,responseData:m,actionStartedAt:f.actionStartedAt,actionFinishedAt:f.actionFinishedAt})}async function oi(e){let{session:t,flags:r,contextFromFlags:a,command:i,positionals:n,outPath:o}=e,s=Date.now(),l={...a(r,t.appBundleId,t.trace?.outPath)},d=await w(t.device,i,n,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function on(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 O(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=n0(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=n0(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oo(e){try{return await on(e)}catch(t){ti({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function os(e){return n0({nodes:e,createdAt:0})}function ol(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:N("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.`)}async function od(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r),d=t.command,u="click"===d?"click":"press";if(!l)return N("SESSION_NOT_FOUND","No active session. Run open first.");let c=ol(l,u);if(c)return c;if(!tl("press",l.device))return N("UNSUPPORTED_OPERATION","press is not supported on this device");let f=ez(t.flags),p=ep(f);if("primary"!==f){let e=eN({commandLabel:u,platform:l.device.platform,button:f,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(e)return N(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return oa({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,afterDispatch:async()=>{await ou(l,"coordinate tap")},buildPayloads:async e=>{let r=await oo({session:l,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}),o=or({data:e,fallbackX:m.x,fallbackY:m.y,referenceFrame:r,extra:p});return{result:o,responseData:o}}});let h="click",g=t.positionals?.[0]??"";if(g.startsWith("@")){let e=s("press",t.flags);if(e)return e;let r=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",c=await nr({session:l,refInput:g,fallbackLabel:r,commandLabel:u,promoteToHittableAncestor:!0,invalidRefMessage:`${u} requires a ref like @e2`,missingBoundsMessage:`Ref ${g} not found or has no bounds`,invalidBoundsMessage:`Ref ${g} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!c.ok)return c;let{ref:f,node:m,snapshotNodes:w,point:v}=c.target,y=e0(m,w),I=ew(m,l.device.platform,{action:h}),{x:S,y:A}=v;return oa({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(S),String(A)],outPath:t.flags?.out,afterDispatch:async()=>{await ou(l,`@${f}`)},buildPayloads:e=>{let t=or({data:e,fallbackX:S,fallbackY:A,referenceFrame:os(w),extra:{ref:f,refLabel:y,selectorChain:I,...p}});return{result:t,responseData:t}}})}let w=(t.positionals??[]).join(" ").trim();if(!w)return N("INVALID_ARGS",`${u} requires @ref, selector expression, or x y coordinates`);let v=eH(w),y=await n(l,t.flags,a,i,{interactiveOnly:!0}),I=await eD("selector_resolve",()=>A(y.nodes,v,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:d});if(!I||!I.node.rect)return N("COMMAND_FAILED",eS(v,I?.diagnostics??[],{unique:!0}));let S=na(y.nodes,I.node),b=ne(S.rect);if(!b)return N("COMMAND_FAILED",`Selector ${I.selector.raw} resolved to invalid bounds`);let{x:_,y:x}=b,M=ew(S,l.device.platform,{action:h}),k=e0(S,y.nodes);return oa({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(_),String(x)],outPath:t.flags?.out,afterDispatch:async()=>{await ou(l,I.selector.raw)},buildPayloads:e=>{let t=or({data:e,fallbackX:_,fallbackY:x,referenceFrame:os(y.nodes),extra:{selector:I.selector.raw,selectorChain:M,refLabel:k,...p}});return{result:t,responseData:t}}})}async function ou(e,t){if("android"!==e.device.platform||!e.appBundleId)return;let r=await eT(e.device),a=r.package?.trim();if(a&&a!==e.appBundleId){var i;if("com.android.settings"===(i=a)||"com.android.systemui"===i||"com.google.android.permissioncontroller"===i||i.includes("launcher"))throw new tI("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${a}. The tap likely escaped the app.`,{expectedPackage:e.appBundleId,foregroundPackage:a,activity:r.activity,hint:"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."})}}async function oc(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r);if(l){let e=ol(l,"fill");if(e)return e}if(l&&!tl("fill",l.device))return N("UNSUPPORTED_OPERATION","fill is not supported on this device");if(t.positionals?.[0]?.startsWith("@")){if(!l)return N("SESSION_NOT_FOUND","No active session. Run open first.");let e=s("fill",t.flags);if(e)return e;let r=t.positionals.length>=3?t.positionals[1]:"",d=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!d)return N("INVALID_ARGS","fill requires text after ref");let u=await nr({session:l,refInput:t.positionals[0],fallbackLabel:r,commandLabel:"fill",promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!u.ok)return u;let{ref:c,node:f,snapshotNodes:p,point:m}=u.target,h=f.type??"",g=h&&!ea(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,w=e0(f,p),v=ew(f,l.device.platform,{action:"fill"}),{x:y,y:I}=m;return oa({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(y),String(I),d],outPath:t.flags?.out,buildPayloads:e=>{let t=or({data:e,fallbackX:y,fallbackY:I,referenceFrame:os(p),extra:{ref:c,refLabel:w,selectorChain:v,text:d}}),r={...e??{ref:c,x:y,y:I}};return g&&(t.warning=g,r.warning=g),{result:t,responseData:r}}})}if(!l)return N("SESSION_NOT_FOUND","No active session. Run open first.");let d=es(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return N("INVALID_ARGS","fill requires text after selector");let e=d.rest.join(" ").trim();if(!e)return N("INVALID_ARGS","fill requires text after selector");let r=eH(d.selectorExpression),o=await n(l,t.flags,a,i,{interactiveOnly:!0}),s=await eD("selector_resolve",()=>A(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return N("COMMAND_FAILED",eS(r,s?.diagnostics??[],{unique:!0}));let u=s.node,c=s.node.rect,f=u.type??"",p=f&&!ea(f,l.device.platform)?`fill target ${s.selector.raw} resolved to "${f}", attempting fill anyway.`:void 0,{x:m,y:h}=et(c),g=ew(u,l.device.platform,{action:"fill"});return oa({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=or({data:t,fallbackX:m,fallbackY:h,referenceFrame:os(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:g,refLabel:e0(u,o.nodes)}});return p&&(r.warning=p),{result:r,responseData:r}}})}return N("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}async function of(e){switch(e.req.command){case"press":case"click":return await od(e);case"fill":return await oc(e);default:return null}}let op=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function om(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of op)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:N("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function oh(e,t,r,a,i){let n={...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},o=a(n,e.appBundleId,e.trace?.outPath),{snapshot:s}=await eB({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function og(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=eH(r),f=await oh(a,i,n,o,{interactiveOnly:s}),p=await eD("selector_resolve",()=>A(f.nodes,c,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return p&&(!l||p.node.rect)?{ok:!0,chain:c,snapshot:f,resolved:p}:{ok:!1,error:{code:"COMMAND_FAILED",message:eS(c,p?.diagnostics??[],{unique:d})}}}async function ow(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return N("INVALID_ARGS","get only supports text or attrs");let o=a.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!tl("get",o.device))return N("UNSUPPORTED_OPERATION","get is not supported on this device");let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=om("get",t.flags);if(e)return e;let r=i7({session:o,refInput:s,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${s} not found`});if(!r.ok)return r;let{ref:l,node:d}=r.target,u=ew(d,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,selectorChain:u}}),{ok:!0,data:{ref:l,node:d}};let c=await nn({device:o.device,node:d,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:ov(c),selectorChain:u}}),{ok:!0,data:{ref:l,text:c,node:d}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return N("INVALID_ARGS","get requires @ref or selector expression");let d=await og({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===n});if(!d.ok)return d;let{resolved:u}=d,c=u.node,f=ew(c,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:u.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:u.selector.raw,node:c}};let p=await nn({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:p,refLabel:ov(p),selector:u.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:u.selector.raw,text:p,node:c}}}function ov(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function oy(e){return!!(e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.width)&&Number.isFinite(e.height)&&e.width>0&&e.height>0)}async function oI(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(n))return N("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let o=a.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!tl("is",o.device))return N("UNSUPPORTED_OPERATION","is is not supported on this device");let{split:s}=eX(t.positionals);if(!s)return N("INVALID_ARGS","is requires a selector expression");let l=s.rest.join(" ").trim();if("text"===n&&!l)return N("INVALID_ARGS","is text requires expected text value");if("text"!==n&&s.rest.length>0)return N("INVALID_ARGS",`is ${n} does not accept trailing values`);let d=eH(s.selectorExpression);if("exists"===n){let e=eE((await oh(o,t.flags,a,i,{interactiveOnly:!1})).nodes,d,{platform:o.device.platform});return e?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:e.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:n,pass:!0,selector:e.selector.raw,matches:e.matches}}):N("COMMAND_FAILED",eS(d,[],{unique:!1}))}let u=await og({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!u.ok)return u;let{resolved:c}=u,f=function(e){let{predicate:t,node:r,nodes:a,expectedText:i,platform:n}=e,o=C(r),s=S(r,n),l=!0===r.selected,d="text"===t?ex(r):function(e,t){if(!0===e.hittable)return!0;if(oy(e.rect))return v(e,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),a=e,i=new Set;for(;"number"==typeof a.parentIndex&&!i.has(a.index);){i.add(a.index);let e=r.get(a.parentIndex);if(!e)break;if(function(e){let t=tc(e.type??"");return!(t.includes("application")||t.includes("window")||t.includes("scrollview")||t.includes("tableview")||t.includes("collectionview"))&&"table"!==t&&"list"!==t&&"listview"!==t&&(!0===e.hittable||oy(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!oy(r.rect)&&v(r,t))}(r,a),u=!1;switch(t){case"visible":u=d;break;case"hidden":u=!d;break;case"editable":u=s;break;case"selected":u=l;break;case"text":u=o===(i??"")}let c="text"===t?`expected="${i??""}" actual="${o}"`:`actual=${JSON.stringify({visible:d,editable:s,selected:l})}`;return{pass:u,actualText:o,details:c}}({predicate:n,node:c.node,nodes:u.snapshot.nodes,expectedText:l,platform:o.device.platform});return f.pass?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:c.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,text:"text"===n?f.actualText:void 0}}),{ok:!0,data:{predicate:n,pass:!0,selector:c.selector.raw}}):N("COMMAND_FAILED",`is ${n} failed for selector ${c.selector.raw}: ${f.details}`)}function oS(e,t){var r,a;let i=Math.max(1,t.height),n=Math.max(1,t.width),o=t.y,s=t.y+i,l=t.x,d=t.x+n,u=s-.25*i,c=Math.max(8,.1*n),f=e.y+e.height/2,p=e.x+e.width/2;if(f>=o+.25*i&&f<=u)return null;let m=Math.round((r=p,a=l+c,Math.min(d-c,Math.max(a,r)))),h=Math.round(o+.86*i),g=Math.round(o+.14*i);return f>u?{x:m,startY:h,endY:g,direction:"down"}:{x:m,startY:g,endY:h,direction:"up"}}async function oA(e){var t;let r,a,i,{req:n,sessionName:o,sessionStore:s,contextFromFlags:l}=e,d=s.get(o);if(!d)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!tl("scrollintoview",d.device))return N("UNSUPPORTED_OPERATION","scrollintoview is not supported on this device");let u=n.positionals?.[0]??"";if(!u.startsWith("@"))return null;let c=om("scrollintoview",n.flags);if(c)return c;let f=n.positionals&&n.positionals.length>1?n.positionals.slice(1).join(" ").trim():"",p=(r=i7({session:d,refInput:t=u,fallbackLabel:f,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${t} not found or has no bounds`})).ok?ob(t,0,r.target):"COMMAND_FAILED"!==r.error.code?r:o_(t,0,{message:r.error.message});if(!p.ok)return p;let{ref:m}=p.state,{currentRef:h,node:g,snapshotNodes:v,viewportRect:y}=p.state,I=e0(g,v),S=ew(g,d.device.platform,{action:"get"}),b=f||I||g.label||"";if(!oS(g.rect,y)){let e=oN({ref:m,currentRef:h,attempts:0,alreadyVisible:!0});return s.recordAction(d,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:{refLabel:I,selectorChain:S,...e}}),{ok:!0,data:e}}let _=n.flags?.maxScrolls??48,x=0,M=0,k=eY(g.rect,y);for(;x<_;){let e=oS(g.rect,y);if(!e)break;a=e.direction,i=await w(d.device,"swipe",[String(e.x),String(e.startY),String(e.x),String(e.endY),"16"],n.flags?.out,{...l(n.flags,d.appBundleId,d.trace?.outPath),count:1,pauseMs:0,pattern:"one-way"}),x+=1,await oh(d,n.flags,s,l,{interactiveOnly:!0});let t=function(e){let{session:t,targetInput:r,fallbackLabel:a,attempts:i,ref:n,selectorChain:o,platform:s}=e;if(t.snapshot){let e=function(e,t,r,a){for(let r of t){let t=A(e,eH(r),{platform:a,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?to(e,r):null}(t.snapshot.nodes,o,a,s);if(e)return ob(r,i,{ref:n,node:e,snapshotNodes:t.snapshot.nodes},{currentRef:e.ref})}let l=i7({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${r} not found or has no bounds`});return l.ok?ob(r,i,l.target,{ref:n,currentRef:l.target.node.ref,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${i} scroll${1===i?"":"s"}`}):"COMMAND_FAILED"!==l.error.code?l:o_(r,i,{message:`scrollintoview lost track of ${r} after ${i} scroll${1===i?"":"s"}`,ref:n})}({session:d,targetInput:u,fallbackLabel:b,attempts:x,ref:m,selectorChain:S,platform:d.device.platform});if(!t.ok)return t;({currentRef:h,node:g,snapshotNodes:v,viewportRect:y}=t.state);let r=eY(g.rect,y);if(0===r)break;if(r>=k){if((M+=1)>=2)return o_(u,x,{message:`scrollintoview made no progress toward ${u} after ${x} scroll${1===x?"":"s"}`,ref:m,stalled:!0})}else M=0;k=r}if(eY(g.rect,y)>0)return o_(u,x,{message:`scrollintoview reached --max-scrolls=${_} before ${u} entered view`,ref:m,maxScrolls:_});let D=oN({data:i,ref:m,currentRef:h,attempts:x,direction:a});return s.recordAction(d,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:{refLabel:I,selectorChain:S,...D}}),{ok:!0,data:D}}function ob(e,t,r,a={}){let{ref:i,currentRef:n,missingBoundsMessage:o}=a,s=r.node;if(!s.rect)return o_(e,t,{message:o??`Ref ${e} not found or has no bounds`,ref:i??r.ref});let l=j(r.snapshotNodes,s.rect);return l?{ok:!0,state:{ref:i??r.ref,currentRef:n??r.node.ref,node:s,snapshotNodes:r.snapshotNodes,viewportRect:l}}:N("COMMAND_FAILED",`scrollintoview could not infer viewport for ${e}`)}function o_(e,t,r={}){let{message:a,...i}=r;return N("COMMAND_FAILED","string"==typeof a?a:`scrollintoview could not find ${e}`,{reason:"not_found",attempts:t,...i})}function oN(e){let{data:t,ref:r,currentRef:a,attempts:i,alreadyVisible:n,direction:o}=e;return{...t??{},ref:r,currentRef:a,attempts:i,...n?{alreadyVisible:n}:{},...o?{direction:o}:{},...M(`Scrolled into view: @${r}`)}}async function ox(e){let t=await of({...e,captureSnapshotForSession:oh,resolveRefTarget:i7,refSnapshotFlagGuardResponse:om});if(t)return t;switch(e.req.command){case"get":return await ow(e);case"is":return await oI(e);case"scrollintoview":return await oA(e);default:return null}}function oM(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 ok(e){let{req:t,leaseRegistry:r}=e,a=oM(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 oD(e,t){if(!t)return[];let r=[],a=e.device,i=tf(t.platform);if(i&&!ts(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=L(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function oP(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let oL=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],oR=/\bis(?:n't| not)\s+responding\b/i,oO=/^close app$/i;async function oE(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oC(t),r=function(e){if(oU(e))return e.find(e=>{let t=oF(e);return t.length>0&&oO.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=et(r.rect),n=await tw("adb",eQ(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return ti({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 o$(t))return ti({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eZ(t.device,t.appBundleId),!await oT(t,t.appBundleId)))return ti({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return ti({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 ti({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 oC(e){return ei(eP((await ek(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function o$(e){for(let t=0;t<12;t+=1){if(!oU(await oC(e)))return!0;await oG(500)}return!oU(await oC(e))}async function oT(e,t){for(let r=0;r<12;r+=1){if((await eT(e.device)).package===t)return!0;await oG(500)}return(await eT(e.device)).package===t}function oF(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 oU(e){return e.some(e=>{let t=oF(e);return t.length>0&&oR.test(t)})}function oG(e){return new Promise(t=>setTimeout(t,e))}let oV=[255,59,48,255],oq=[255,214,10,255],oj=[0,0,0,255],oB={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 oH(e){let t=tp(await i.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)oz(r)&&oX(r.rect)&&(!t||oQ(r.rect)>oQ(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&&oX(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 oX(e.rect)&&!("image"===tc((t=e).type??"")&&!oW(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(oJ)||oZ(e.identifier);return oK(e)?t:t&&function(e){let t=tc(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 oK(e)&&!oz(e)}(t)&&oX(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(oK(t)&&!oz(t)&&oX(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&oX(r.rect))return r;if(t.hittable&&oX(t.rect)&&!oz(t))return t;let a=W(e,t);return a?.rect&&oX(a.rect)&&!oz(a)?a:null}(e.nodes,a);if(!o?.rect||!oX(o.rect))continue;let s=function(e,t,r){let a=oY(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=oY(a);if(!i)continue;let n=function(e){let t=0;return tc(e.type??"").includes("text")&&(t+=2),oJ(e.label)&&(t+=2),oJ(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(oY(t)??e0(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),oK(t)&&(a+=3),oK(e)&&(a+=2),r&&(a+=2),oZ(t.identifier)&&(a+=1),oW(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return o2({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 o2({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(!oX(d))continue;let u=n.get(o.ref);(!u||l>u.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)=>oQ(e.overlayRect)-oQ(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(o0(e.overlayRect,r.overlayRect)||o0(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}oQ(r.overlayRect)<oQ(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:o1(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:o1(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:et(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,n;(function(e,t,r){for(let a=0;a<2;a+=1)o4(e,t.x,t.x+t.width-1,t.y+a,r),o4(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),o3(e,t.x+a,t.y,t.y+t.height-1,r),o3(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(n=e).overlayRect,oV),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=o5(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:o5(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)o8(e,t+o,r+n,i)})(e,i,o,a,oq),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=oB[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]&&o8(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,oj)}(a,n.overlayRect,n.ref)}return await i.writeFile(e.screenshotPath,p.sync.write(t)),r}function oK(e){let t=[e.type,e.role,e.subrole].map(e=>tc(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 oz(e){let t=[e.type,e.role,e.subrole].map(e=>tc(e??"")).join(" ");return t.includes("application")||t.includes("window")}function oW(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function oJ(e){var t;let r;return!!oW(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function oZ(e){var t;return"string"==typeof e&&!!oJ(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function oY(e){let t=[e.label,e.value].find(oJ);return t?t.trim():oZ(e.identifier)?e.identifier.trim():void 0}function oX(e){return!!(e&&e.width>0&&e.height>0)}function oQ(e){return e.width*e.height}function o0(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 o1(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function o2(e,t,r){let a=o5(e.x,0,Math.max(0,t-1)),i=o5(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:o5(e.width,1,n),height:o5(e.height,1,o)}}function o5(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function o4(e,t,r,a,i){for(let n=t;n<=r;n+=1)o8(e,n,a,i)}function o3(e,t,r,a,i){for(let n=r;n<=a;n+=1)o8(e,t,n,i)}function o8(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 o6=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),o9=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),o7=new Set(o9),se=new Map;function st(e,t,r,a){let i=e7().requestId;return{...eV(e,t,r,a,i),requestId:i}}async function sr(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||at(e.flags))try{let t=await eR(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function sa(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await ok({req:t,leaseRegistry:n});if(l)return l;let d=await i9({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(d)return d;let u=await I({req:t,sessionName:r,logPath:a,sessionStore:i});if(u)return u;let c=await nY({req:t,sessionName:r,sessionStore:i,logPath:a});if(c)return c;let f=await no({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await ox({req:t,sessionName:r,sessionStore:i,contextFromFlags:s});return p||null}async function si(e){var t;let r,a,i,n,o,s,l,{req:d,session:u,logPath:c,sessionStore:f}=e,p=d.command;if(!tl(p,u.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${p} is not supported on this device`}};if("android"===u.device.platform&&u.recording&&"record"!==p&&"failed"===await oE({session:u}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:m,resolvedOut:h,recordedPositionals:g,recordedFlags:v}=(r=(t=d).command,a=t.positionals??[],i=t.flags?.out,n="screenshot"===r&&a[0]?[tG.expandHome(a[0],t.meta?.cwd),...a.slice(1)]:a,o="screenshot"===r&&i?tG.expandHome(i,t.meta?.cwd):i,s="screenshot"===r?n:a,l="screenshot"===r&&o?{...t.flags??{},out:o}:t.flags??{},{resolvedPositionals:n,resolvedOut:o,recordedPositionals:s,recordedFlags:l}),y=Date.now(),I={...st(c,d.flags,u.appBundleId,u.trace?.outPath),surface:u.surface},S=await w(u.device,p,m,h,{...I});return"screenshot"===p&&d.flags?.overlayRefs&&"string"==typeof S?.path&&await sn(u,S,c),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:i,recordedPositionals:n,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:d,flags:u}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let i=n0(e.snapshot),n={...a??{}},o=n8(n.direction)??n8(r[0]);if(!o)return a;let s=n6(n.amount)??n6(r[1]),l=n6(n.pixels),d=oe(n,[]),u=n6(n.referenceWidth),c=n6(n.referenceHeight),f=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:i??n2;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=eo({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);n5(t,a,i,c,u,l,d),r.recordAction(t,{command:a,positionals:n,flags:o,result:s??{}})}({session:u,sessionStore:f,command:p,resolvedPositionals:m,recordedPositionals:g,recordedFlags:v,data:S,actionStartedAt:y,actionFinishedAt:Date.now(),flags:d.flags??{}}),eb(p)&&tm(u,p),{ok:!0,data:S??{}}}async function sn(e,t,r){let a=eJ(await T({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=a;let i=await oH({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}function so(e){a.existsSync(e)&&a.unlinkSync(e)}function ss(e){if(!a.existsSync(e))return null;try{let t=JSON.parse(a.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function sl(e){let t=ss(e);if(!t||t.pid===process.pid)try{a.existsSync(e)&&a.unlinkSync(e)}catch{}}function sd(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:su,infoPath:sc,lockPath:sf,logPath:sp,sessionsDir:sm}=td(process.env.AGENT_DEVICE_STATE_DIR),sh=eu(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sg=sm;if(a.existsSync(sg))for(let e of a.readdirSync(sg,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=n.join(sg,e.name,tq);if(a.existsSync(t))try{let e=tj(a.readFileSync(t,"utf8"));if(e&&function(e){let t,r=Y(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=el(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 sw=new tG(sm),sv=new rY({maxActiveSimulatorLeases:sd(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sd(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sd(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sd(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),sy=H(),sI=r.randomBytes(24).toString("hex"),sS=Y(process.pid)??void 0,sA=ej(),sb=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:o}=e;async function s(e){let l=!!(e.meta?.debug||e.flags?.verbose);return await X({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:l,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:ty(new tI("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=_(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=eK(r);if(r&&!a)throw new tI("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new tI("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);ti({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=oM(r);o9.has(l)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:d.tenantId,runId:d.runId,leaseId:d.leaseId,backend:d.leaseBackend});let u=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),c=o7.has(l)?null:await sr(r,u,a),f=async()=>{let e=a.get(u);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=V(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(u,e));let d=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?oD(t,a):function(e,t,r){var a,i;let n=[],o=tf(t);if(void 0!==e.platform&&o&&(a=tf(e.platform),i=o,a&&i&&a!==i&&("apple"===a?!Q(i):"apple"!==i||!Q(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of oL){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 oL)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new tI("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(oP).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),c=e=>(function(e,t,r){let a=e7();if(!t.ok){ti({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=tu({force:!0})??void 0;return{ok:!1,error:ty(new tI(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 ti({level:"info",phase:"request_success"}),tu(),{ok:!0,data:function(e,t,r){var a,i;let o;if(!t)return t;let s=(a=e,i=t,o=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||o.some(e=>e?.field==="path")||"string"!=typeof i.path||o.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:n.basename(a.meta?.clientArtifactPaths?.path??i.path)}),o.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,o);if(e?.recording?.invalidatedReason&&"record"!==l&&"close"!==l)return c({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||d.meta?.lockPolicy||o6.has(l)||function(e,t){let r=oD(e,t);if(0!==r.length){var a;let t,i,n;throw new tI("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(oP).join(", ")}. Use a different --session name or close this session first.`)}}(e,d.flags);let f=await sa({req:d,sessionName:u,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...st(t,e,r,i),surface:a.get(u)?.surface})});if(f)return c(f);let p=a.get(u);if(!p)return c({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await si({req:d,session:p,sessionName:u,logPath:t,sessionStore:a});return c(m)};if(!c)return await f();return await D(se,c,f)}catch(r){ti({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=e7(),t=tu({force:!0})??void 0;return{ok:!1,error:ty(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return s}({logPath:sp,token:sI,sessionStore:sw,leaseRegistry:sv,trackDownloadableArtifact:function(e){let t=r.randomUUID(),a=setTimeout(()=>{rS(t)},9e5);return a.unref(),rI.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:a}),t}});!async function(){let e,t;if(!function(e,t,r){a.existsSync(e)||a.mkdirSync(e,{recursive:!0});let i=JSON.stringify(r,null,2),n=()=>{try{return a.writeFileSync(t,i,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(n())return!0;let o=ss(t);if(o?.pid&&o.pid!==process.pid&&y(o.pid,o.processStartTime))return!1;try{a.unlinkSync(t)}catch{}return n()}(su,sf,{pid:process.pid,version:sy,startedAt:Date.now(),processStartTime:sS})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var i;let n;if("socket"===sh||"dual"===sh){let t=m.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))e4(e);ti({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await G(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){ti({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=U(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),b(o),F(o))throw eA();i=await sb(e)}catch(e){i={ok:!1,error:ty(e)}}finally{r-=1,o&&(a.delete(o),K(o))}e.destroyed||e.write(`${JSON.stringify(i)}
|
|
35
|
-
`),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
|
|
33
|
+
`.trim();async function nm(e,t={}){let r,i=t.pollMs??150,n=t.attempts??12,o=0;for(let t=0;t<n;t+=1){let t=0;try{t=a.statSync(e).size}catch{t=0}if(t>0&&t===r){if((o+=1)>=2)return}else o=0;r=t,await new Promise(e=>setTimeout(e,i))}}async function nh(e){try{var t,r;let a,i=await th("swift",["-",e],{stdin:np,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
|
|
34
|
+
${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return nw(e);return!1}catch(t){if(t instanceof tv&&"TOOL_MISSING"===t.code)return nw(e);throw t}}async function ng(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await nh(e))return;await new Promise(e=>setTimeout(e,r))}}function nw(e){try{let t=a.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=a.openSync(e,"r");try{let e=a.fstatSync(t).size,r=0,i=[];for(;r+8<=e&&i.length<16;){let e=Buffer.alloc(8);if(8>a.readSync(t,e,0,8,r))break;let n=e.readUInt32BE(0),o=e.toString("latin1",4,8);if(i.push(o),1===n){let e=Buffer.alloc(8);if(8>a.readSync(t,e,0,8,r+8))break;n=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(n)||n<=0)break;r+=n}return i}finally{a.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function nv(e){let t=n.parse(e);return n.join(t.dir,`${t.name}.gesture-telemetry.json`)}function ny(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function nI(e){let t=n.dirname(l(import.meta.url)),r=[l(new URL(`./${e}`,import.meta.url)),n.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(a.existsSync(e))return e;throw new tv("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 nS(e){let{videoPath:t,scriptPath:r,scriptArgs:i,commandDescription:o}=e;await nm(t),await ng(t);let s=a.mkdtempSync(n.join(u.tmpdir(),"agent-device-record-overlay-")),l=n.join(s,`input${n.extname(t)||".mp4"}`),d=n.join(s,n.basename(t)),c=n.join(s,"home"),f=n.join(s,"module-cache");a.copyFileSync(t,l),a.mkdirSync(c,{recursive:!0}),a.mkdirSync(f,{recursive:!0});try{await th("xcrun",["swift",r,"--input",l,"--output",d,...i],{timeoutMs:12e4,env:{...process.env,HOME:c,CLANG_MODULE_CACHE_PATH:f}}),await ng(d),a.copyFileSync(d,t)}catch(a){let e=a instanceof tv?a:new tv("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new tv("COMMAND_FAILED",o,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{a.rmSync(s,{recursive:!0,force:!0})}}async function nA(e){let{videoPath:r,trimStartMs:a}=e;a>0&&await nS({videoPath:r,scriptPath:t??=nI("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function nb(t){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=t;await nS({videoPath:r,scriptPath:e??=nI("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function n_(e){return e instanceof Error?e.message:String(e)}function nN(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function nx(e){let{recording:t,deps:r,trimStartMs:i,targetLabel:n}=e,o=function(e){var t,r,i;let n,o,{recording:s,trimStartMs:l}=e,d=(n=nv((t={videoPath:s.outPath,events:s.gestureEvents,trimStartMs:l}).videoPath),o={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(i=t.trimStartMs??0)>0?ny(r.flatMap(e=>{let t=e.tMs-i,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):ny(r))},a.writeFileSync(n,JSON.stringify(o,null,2)),n);return s.telemetryPath=d,d}({recording:t,trimStartMs:i});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: ${n_(e)}`}}}async function nD(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 nM(e,t,r){for(let a=0;a<40;a+=1){if(!await nD(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await nD(e,t,r)}async function nk(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 new Promise(e=>setTimeout(e,250))}}async function nP(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 nD(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function nL(e){let t,{deps:r,deviceId:i,remotePath:n,outPath:o}=e;for(let e=0;e<2;e+=1){try{a.rmSync(o,{force:!0})}catch{}let s=await r.runCmd("adb",["-s",i,"pull",n,o],{allowFailure:!0});if(0!==s.exitCode)t=nN(s,"adb pull");else{await r.waitForStableFile(o,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(o);if(tr({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:i,remotePath:n,outPath:o,attempt:e+1,fileSize:(()=>{try{return a.statSync(o).size}catch{return 0}})(),playable:t}}),t)return;tr({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:i,remotePath:n,outPath:o,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,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 nR(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function nO(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return tr({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 nD(e,t,r))&&await nM(e,t,r)}async function nC(e){var t;let r,{deps:a,device:i,recordingBase:n}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",i.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${nN(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){o="failed to start recording: adb did not return a valid Android screenrecord pid",await nR(a,i.id,e);continue}if(tr({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await nP(a,i.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...n,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await nO(a,i.id,r),await nR(a,i.id,e)}return N("COMMAND_FAILED",o)}async function nE(e){let t,r,{deps:a,device:i,recording:n}=e;tr({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(tr({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 nD(a,i.id,n.remotePid)&&!await nO(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${nN(o,"adb shell kill")}`):await nM(a,i.id,n.remotePid)||await nO(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await nk(a,i.id,n.remotePath);let e=await nL({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),N("COMMAND_FAILED",e);await nx({recording:n,deps:a,targetLabel:"Android recording"})}if(await s(),t)return N("COMMAND_FAILED",t);if(r)return N("COMMAND_FAILED",r);return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});tr({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: ${nN(e,"adb shell rm")}`)}}function n$(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function nT(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function nF(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=n$(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},nT(t,i,r))}catch(e){tr({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:n_(e)}})}}async function nU(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=nT(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:f,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var g,w;if(!n_(a).toLowerCase().includes("recording already in progress"))return N("COMMAND_FAILED",`failed to start recording: ${n_(a)}`);tr({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:n_(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 N("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return N("COMMAND_FAILED",`failed to start recording: ${n_(e)}`)}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function nG(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,appBundleId:l},nT(t,i,r))}catch(e){return N("COMMAND_FAILED",`failed to start recording: ${n_(e)}`)}return{platform:"macos-runner",...s}}async function nV(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=n$(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nT(t,i,r))}catch(e){tr({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:n_(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of el)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 N("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 nx({recording:o,deps:n,trimStartMs:d,targetLabel:"iOS recording"}),null}async function nq(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=n$(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},nT(t,i,r))}catch(e){tr({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:n_(e)}})}return await nx({recording:o,deps:n,targetLabel:"macOS recording"}),null}async function nj(e){for(let t=0;t<2;t+=1){try{if(a.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function nH(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await nF({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:u,wait:c}=s.runCmdBackground("xcrun",te(n,["io",n.id,"recordVideo",d]),{allowFailure:!0}),f=await nj(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:n$(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:u,wait:c,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function nB(e){let t,{req:r,sessionName:i,sessionStore:o,activeSession:s,device:l,logPath:d,deps:u}=e;if(s.recording)return N("INVALID_ARGS","recording already in progress");let c=r.flags?.fps;if(void 0!==c&&(!Number.isInteger(c)||c<1||c>120))return N("INVALID_ARGS","fps must be an integer between 1 and 120");if(!to("record",l))return N("UNSUPPORTED_OPERATION","record is not supported on this device");let f=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,p=tF.expandHome(f,r.meta?.cwd),m={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(a.mkdirSync(n.dirname(p),{recursive:!0}),a.rmSync(p,{force:!0}),"ios"===l.platform&&"device"===l.kind){let e=n$(s);if(!e)return N("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await nU({req:r,activeSession:s,sessionStore:o,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:m,appBundleId:e})}else if("macos"===l.platform){let e=n$(s);if(!e)return N("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await nG({req:r,activeSession:s,device:l,logPath:d,deps:u,fpsFlag:c,recordingBase:m,appBundleId:e})}else t="ios"===l.platform?await nH({req:r,activeSession:s,device:l,logPath:d,deps:u,recordingBase:m,resolvedOut:p}):await nC({deps:u,device:l,recordingBase:m});return"ok"in t?t:(s.recording=t,o.set(i,s),o.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??f,showTouches:t.showTouches}})}async function nK(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await nE({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;return 0!==i.exitCode?N("COMMAND_FAILED",`failed to stop recording: ${nN(i,"simctl recordVideo")}`):(await nx({recording:a,deps:t,targetLabel:"iOS recording"}),null)}async function nz(e){var t;let r,{req:a,activeSession:i,device:o,logPath:s,deps:l}=e;if(!i.recording)return N("INVALID_ARGS","no active recording");let d=i.recording,u=d.invalidatedReason;i.recording=void 0;let c="ios-device-runner"===d.platform?await nV({req:a,activeSession:i,device:o,logPath:s,deps:l,recording:d}):"macos-runner"===d.platform?await nq({req:a,activeSession:i,device:o,logPath:s,deps:l,recording:d}):await nK({deps:l,device:o,recording:d});return c||(u?N("COMMAND_FAILED",u):(r=[{field:"outPath",path:(t=d).outPath,localPath:t.clientOutPath,fileName:n.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return nv(e.clientOutPath)}(t),fileName:n.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function nW(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:th,runCmdBackground:tm,runIosRunnerCommand:e3,waitForStableFile:nm,isPlayableVideo:nh,trimRecordingStart:nA,overlayRecordingTouches:nb},o=a.get(r),s=o?.device??await eL(t.flags??{});o||await e8(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return N("INVALID_ARGS","record requires start|stop");if("start"===d)return nB({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await nz({req:t,activeSession:l,device:s,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function nJ(e){let{req:t,sessionName:r,sessionStore:i,logPath:o}=e,s=t.command;if("record"===s)return nW({req:t,sessionName:r,sessionStore:i,logPath:o});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return N("INVALID_ARGS","trace requires start|stop");let o=i.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session");if("start"===e){if(o.trace)return N("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??i.defaultTracePath(o),r=tF.expandHome(e);return a.mkdirSync(n.dirname(r),{recursive:!0}),a.appendFileSync(r,""),o.trace={outPath:r,startedAt:Date.now()},i.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!o.trace)return N("INVALID_ARGS","no active trace");let l=o.trace.outPath;if(t.positionals?.[1]){let e=tF.expandHome(t.positionals[1]);a.mkdirSync(n.dirname(e),{recursive:!0}),a.existsSync(l)?a.renameSync(l,e):a.appendFileSync(e,""),l=e}return o.trace=void 0,i.recordAction(o,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l}}),{ok:!0,data:{trace:"stopped",outPath:l}}}return null}function nZ(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 nX=new WeakMap;function nY(e){if(!e)return;let t=nX.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)&&nQ(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(nQ);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 nX.set(e,r),r}function nQ(e){return!!e&&e.width>0&&e.height>0}let n0={referenceWidth:1e3,referenceHeight:1e3};function n1(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,f=e.recording;if(!f)return;let p={...i,...a??{}},m=n4(p.effectiveDurationMs)??n4(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:n4(p.gestureStartUptimeMs),gestureEndUptimeMs:n4(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},g="number"==typeof(s={gestureStartUptimeMs:n4(p.gestureStartUptimeMs),gestureEndUptimeMs:n4(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===n4(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=n8(n4(t.count),1)??1,r=!0===t.doubleTap,a=n8(n4(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 nZ(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:g}):nZ(h),v=(l=e.snapshot,u=n4((d=p).referenceWidth),c=n4(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:nY(l)),y=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=n6(t,e);if(!i)return[];let{x:n,y:o}=i,s=n8(n4(t.count),1)??1,l=n8(n4(t.intervalMs),0)??0,d=!0===t.doubleTap,u=n8(n4(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(n5(t,n,o,u,a));continue}c.push(n2(t,n,o,a)),d&&c.push(n2(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=n6(t,e);if(!i)return[];let{x:n,y:o}=i;return[n2(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=n6(t,e);if(!n)return[];let{x:o,y:s}=n;return[n5(r,o,s,n7(a,[n4(t.durationMs),n4(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=n9(t,e),o=n3(t.contentDirection)??n3(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=n7(a,[],250),f=n4(t.amount)??n4(e[1]),p=n4(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==f?{amount:f}:{},...void 0!==p?{pixels:p}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=n9(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=n7(a,[n4(t.effectiveDurationMs),n4(t.durationMs),n4(e[4])],250),c=n8(n4(t.count),1)??1,f=n8(n4(t.pauseMs),0)??0,p="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===p&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,g=r+e*(u+f);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:g,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=n6(t,e,1),o=n4(t.scale)??n4(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:n7(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,w,g,v);0!==y.length&&(f.gestureEvents.push(...y),tr({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 n2(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function n5(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function n3(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 n4(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 n8(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function n6(e,t,r=0){let a=n4(e.x)??n4(t[r]),i=n4(e.y)??n4(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function n9(e,t){let r=n4(e.x1)??n4(t[0]),a=n4(e.y1)??n4(t[1]),i=n4(e.x2)??n4(t[2]),n=n4(e.y2)??n4(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 n7(e,t,r){return n8(e,1)??t.map(e=>n8(e,1)).find(e=>void 0!==e)??r}function oe(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,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??{},...u??{},...o??{},...D(c)}}async function ot(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:i,flags:n,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,afterDispatch:u,buildPayloads:c}=e,f=await or({session:t,flags:n,contextFromFlags:o,command:s,positionals:l,outPath:d});await u?.(f.data);let{result:p,responseData:m=p}=await c(f.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),eA(a)&&tf(t,a),n1(t,a,i,o,n??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:i,flags:n,result:p,responseData:m,actionStartedAt:f.actionStartedAt,actionFinishedAt:f.actionFinishedAt})}async function or(e){let{session:t,flags:r,contextFromFlags:a,command:i,positionals:n,outPath:o}=e,s=Date.now(),l={...a(r,t.appBundleId,t.trace?.outPath)},d=await w(t.device,i,n,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function oa(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 O(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=nY(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=nY(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function oi(e){try{return await oa(e)}catch(t){tr({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function on(e){return nY({nodes:e,createdAt:0})}function oo(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:N("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.`)}async function os(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r),d=t.command,u="click"===d?"click":"press";if(!l)return N("SESSION_NOT_FOUND","No active session. Run open first.");let c=oo(l,u);if(c)return c;if(!to("press",l.device))return N("UNSUPPORTED_OPERATION","press is not supported on this device");let f=eK(t.flags),p=ef(f);if("primary"!==f){let e=e_({commandLabel:u,platform:l.device.platform,button:f,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(e)return N(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return ot({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,afterDispatch:async()=>{await ol(l,"coordinate tap")},buildPayloads:async e=>{let r=await oi({session:l,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}),o=oe({data:e,fallbackX:m.x,fallbackY:m.y,referenceFrame:r,extra:p});return{result:o,responseData:o}}});let h="click",g=t.positionals?.[0]??"";if(g.startsWith("@")){let e=s("press",t.flags);if(e)return e;let r=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",c=await ne({session:l,refInput:g,fallbackLabel:r,commandLabel:u,promoteToHittableAncestor:!0,invalidRefMessage:`${u} requires a ref like @e2`,missingBoundsMessage:`Ref ${g} not found or has no bounds`,invalidBoundsMessage:`Ref ${g} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!c.ok)return c;let{ref:f,node:m,snapshotNodes:w,point:v}=c.target,y=eY(m,w),I=eg(m,l.device.platform,{action:h}),{x:S,y:A}=v;return ot({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(S),String(A)],outPath:t.flags?.out,afterDispatch:async()=>{await ol(l,`@${f}`)},buildPayloads:e=>{let t=oe({data:e,fallbackX:S,fallbackY:A,referenceFrame:on(w),extra:{ref:f,refLabel:y,selectorChain:I,...p}});return{result:t,responseData:t}}})}let w=(t.positionals??[]).join(" ").trim();if(!w)return N("INVALID_ARGS",`${u} requires @ref, selector expression, or x y coordinates`);let v=eH(w),y=await n(l,t.flags,a,i,{interactiveOnly:!0}),I=await eM("selector_resolve",()=>A(y.nodes,v,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:d});if(!I||!I.node.rect)return N("COMMAND_FAILED",eI(v,I?.diagnostics??[],{unique:!0}));let S=nt(y.nodes,I.node),b=i9(S.rect);if(!b)return N("COMMAND_FAILED",`Selector ${I.selector.raw} resolved to invalid bounds`);let{x:_,y:x}=b,D=eg(S,l.device.platform,{action:h}),M=eY(S,y.nodes);return ot({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(_),String(x)],outPath:t.flags?.out,afterDispatch:async()=>{await ol(l,I.selector.raw)},buildPayloads:e=>{let t=oe({data:e,fallbackX:_,fallbackY:x,referenceFrame:on(y.nodes),extra:{selector:I.selector.raw,selectorChain:D,refLabel:M,...p}});return{result:t,responseData:t}}})}async function ol(e,t){if("android"!==e.device.platform||!e.appBundleId)return;let r=await e$(e.device),a=r.package?.trim();if(a&&a!==e.appBundleId){var i;if("com.android.settings"===(i=a)||"com.android.systemui"===i||"com.google.android.permissioncontroller"===i||i.includes("launcher"))throw new tv("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${a}. The tap likely escaped the app.`,{expectedPackage:e.appBundleId,foregroundPackage:a,activity:r.activity,hint:"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."})}}async function od(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r);if(l){let e=oo(l,"fill");if(e)return e}if(l&&!to("fill",l.device))return N("UNSUPPORTED_OPERATION","fill is not supported on this device");if(t.positionals?.[0]?.startsWith("@")){if(!l)return N("SESSION_NOT_FOUND","No active session. Run open first.");let e=s("fill",t.flags);if(e)return e;let r=t.positionals.length>=3?t.positionals[1]:"",d=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!d)return N("INVALID_ARGS","fill requires text after ref");let u=await ne({session:l,refInput:t.positionals[0],fallbackLabel:r,commandLabel:"fill",promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!u.ok)return u;let{ref:c,node:f,snapshotNodes:p,point:m}=u.target,h=f.type??"",g=h&&!er(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,w=eY(f,p),v=eg(f,l.device.platform,{action:"fill"}),{x:y,y:I}=m;return ot({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(y),String(I),d],outPath:t.flags?.out,buildPayloads:e=>{let t=oe({data:e,fallbackX:y,fallbackY:I,referenceFrame:on(p),extra:{ref:c,refLabel:w,selectorChain:v,text:d}}),r={...e??{ref:c,x:y,y:I}};return g&&(t.warning=g,r.warning=g),{result:t,responseData:r}}})}if(!l)return N("SESSION_NOT_FOUND","No active session. Run open first.");let d=eo(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return N("INVALID_ARGS","fill requires text after selector");let e=d.rest.join(" ").trim();if(!e)return N("INVALID_ARGS","fill requires text after selector");let r=eH(d.selectorExpression),o=await n(l,t.flags,a,i,{interactiveOnly:!0}),s=await eM("selector_resolve",()=>A(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return N("COMMAND_FAILED",eI(r,s?.diagnostics??[],{unique:!0}));let u=s.node,c=s.node.rect,f=u.type??"",p=f&&!er(f,l.device.platform)?`fill target ${s.selector.raw} resolved to "${f}", attempting fill anyway.`:void 0,{x:m,y:h}=ee(c),g=eg(u,l.device.platform,{action:"fill"});return ot({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=oe({data:t,fallbackX:m,fallbackY:h,referenceFrame:on(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:g,refLabel:eY(u,o.nodes)}});return p&&(r.warning=p),{result:r,responseData:r}}})}return N("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}async function ou(e){switch(e.req.command){case"press":case"click":return await os(e);case"fill":return await od(e);default:return null}}let oc=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function of(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of oc)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:N("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function op(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 ej({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function om(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=eH(r),f=await op(a,i,n,o,{interactiveOnly:s}),p=await eM("selector_resolve",()=>A(f.nodes,c,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return p&&(!l||p.node.rect)?{ok:!0,chain:c,snapshot:f,resolved:p}:{ok:!1,error:{code:"COMMAND_FAILED",message:eI(c,p?.diagnostics??[],{unique:d})}}}async function oh(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return N("INVALID_ARGS","get only supports text or attrs");let o=a.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!to("get",o.device))return N("UNSUPPORTED_OPERATION","get is not supported on this device");let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=of("get",t.flags);if(e)return e;let r=i6({session:o,refInput:s,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${s} not found`});if(!r.ok)return r;let{ref:l,node:d}=r.target,u=eg(d,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,selectorChain:u}}),{ok:!0,data:{ref:l,node:d}};let c=await na({device:o.device,node:d,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:og(c),selectorChain:u}}),{ok:!0,data:{ref:l,text:c,node:d}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return N("INVALID_ARGS","get requires @ref or selector expression");let d=await om({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===n});if(!d.ok)return d;let{resolved:u}=d,c=u.node,f=eg(c,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:u.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:u.selector.raw,node:c}};let p=await na({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:p,refLabel:og(p),selector:u.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:u.selector.raw,text:p,node:c}}}function og(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function ow(e){return!!(e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.width)&&Number.isFinite(e.height)&&e.width>0&&e.height>0)}async function ov(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(n))return N("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let o=a.get(r);if(!o)return N("SESSION_NOT_FOUND","No active session. Run open first.");if(!to("is",o.device))return N("UNSUPPORTED_OPERATION","is is not supported on this device");let{split:s}=eZ(t.positionals);if(!s)return N("INVALID_ARGS","is requires a selector expression");let l=s.rest.join(" ").trim();if("text"===n&&!l)return N("INVALID_ARGS","is text requires expected text value");if("text"!==n&&s.rest.length>0)return N("INVALID_ARGS",`is ${n} does not accept trailing values`);let d=eH(s.selectorExpression);if("exists"===n){let e=eO((await op(o,t.flags,a,i,{interactiveOnly:!1})).nodes,d,{platform:o.device.platform});return e?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:e.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:n,pass:!0,selector:e.selector.raw,matches:e.matches}}):N("COMMAND_FAILED",eI(d,[],{unique:!1}))}let u=await om({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!u.ok)return u;let{resolved:c}=u,f=function(e){let{predicate:t,node:r,nodes:a,expectedText:i,platform:n}=e,o=E(r),s=S(r,n),l=!0===r.selected,d="text"===t?eN(r):function(e,t){if(!0===e.hittable)return!0;if(ow(e.rect))return v(e,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),a=e,i=new Set;for(;"number"==typeof a.parentIndex&&!i.has(a.index);){i.add(a.index);let e=r.get(a.parentIndex);if(!e)break;if(function(e){let t=td(e.type??"");return!(t.includes("application")||t.includes("window")||t.includes("scrollview")||t.includes("tableview")||t.includes("collectionview"))&&"table"!==t&&"list"!==t&&"listview"!==t&&(!0===e.hittable||ow(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!ow(r.rect)&&v(r,t))}(r,a),u=!1;switch(t){case"visible":u=d;break;case"hidden":u=!d;break;case"editable":u=s;break;case"selected":u=l;break;case"text":u=o===(i??"")}let c="text"===t?`expected="${i??""}" actual="${o}"`:`actual=${JSON.stringify({visible:d,editable:s,selected:l})}`;return{pass:u,actualText:o,details:c}}({predicate:n,node:c.node,nodes:u.snapshot.nodes,expectedText:l,platform:o.device.platform});return f.pass?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:c.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,text:"text"===n?f.actualText:void 0}}),{ok:!0,data:{predicate:n,pass:!0,selector:c.selector.raw}}):N("COMMAND_FAILED",`is ${n} failed for selector ${c.selector.raw}: ${f.details}`)}async function oy(e){let t=await ou({...e,captureSnapshotForSession:op,resolveRefTarget:i6,refSnapshotFlagGuardResponse:of});if(t)return t;switch(e.req.command){case"get":return await oh(e);case"is":return await ov(e);default:return null}}function oI(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 oS(e){let{req:t,leaseRegistry:r}=e,a=oI(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 oA(e,t){if(!t)return[];let r=[],a=e.device,i=tu(t.platform);if(i&&!tn(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=L(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function ob(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 o_=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],oN=/\bis(?:n't| not)\s+responding\b/i,ox=/^close app$/i;async function oD(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await oM(t),r=function(e){if(oR(e))return e.find(e=>{let t=oL(e);return t.length>0&&ox.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=ee(r.rect),n=await th("adb",eX(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return tr({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 ok(t))return tr({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await eJ(t.device,t.appBundleId),!await oP(t,t.appBundleId)))return tr({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return tr({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 tr({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 oM(e){return ea(ek((await eD(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function ok(e){for(let t=0;t<12;t+=1){if(!oR(await oM(e)))return!0;await oO(500)}return!oR(await oM(e))}async function oP(e,t){for(let r=0;r<12;r+=1){if((await e$(e.device)).package===t)return!0;await oO(500)}return(await e$(e.device)).package===t}function oL(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 oR(e){return e.some(e=>{let t=oL(e);return t.length>0&&oN.test(t)})}function oO(e){return new Promise(t=>setTimeout(t,e))}let oC=[255,59,48,255],oE=[255,214,10,255],o$=[0,0,0,255],oT={e:["01110","10000","11110","10000","10000","10001","01110"],0:["01110","10001","10011","10101","11001","10001","01110"],1:["00100","01100","00100","00100","00100","00100","01110"],2:["01110","10001","00001","00010","00100","01000","11111"],3:["11110","00001","00001","01110","00001","00001","11110"],4:["00010","00110","01010","10010","11111","00010","00010"],5:["11111","10000","10000","11110","00001","00001","11110"],6:["01110","10000","10000","11110","10001","10001","01110"],7:["11111","00001","00010","00100","01000","01000","01000"],8:["01110","10001","10001","01110","10001","10001","01110"],9:["01110","10001","10001","01111","00001","00001","01110"]};async function oF(e){let t=tc(await i.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)oG(r)&&oB(r.rect)&&(!t||oK(r.rect)>oK(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,a=-1/0,i=-1/0;for(let n of e)n.rect&&oB(n.rect)&&(t=Math.min(t,n.rect.x),r=Math.min(r,n.rect.y),a=Math.max(a,n.rect.x+n.rect.width),i=Math.max(i,n.rect.y+n.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||a<=t||i<=r?null:{x:t,y:r,width:a-t,height:i-r}}(e.filter(e=>{var t;return oB(e.rect)&&!("image"===td((t=e).type??"")&&!oV(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(oq)||oj(e.identifier);return oU(e)?t:t&&function(e){let t=td(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 oU(e)&&!oG(e)}(t)&&oB(t.rect))return t;let r=function(e,t){let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){;a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(oU(t)&&!oG(t)&&oB(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&oB(r.rect))return r;if(t.hittable&&oB(t.rect)&&!oG(t))return t;let a=z(e,t);return a?.rect&&oB(a.rect)&&!oG(a)?a:null}(e.nodes,a);if(!o?.rect||!oB(o.rect))continue;let s=function(e,t,r){let a=oH(e);if(e.ref!==t.ref&&a)return a;let i=function(e,t){let r=null;for(let a of t){if(a.ref===e.ref||!function(e,t,r){let a=e;for(;void 0!==a.parentIndex;){let e=r[a.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;a=e}return!1}(a,e,t))continue;let i=oH(a);if(!i)continue;let n=function(e){let t=0;return td(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||(oH(t)??eY(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),oU(t)&&(a+=3),oU(e)&&(a+=2),r&&(a+=2),oj(t.identifier)&&(a+=1),oV(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return oJ({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,a);let i=r/e.width,n=a/e.height;return oJ({x:Math.round((t.x-e.x)*i),y:Math.round((t.y-e.y)*n),width:Math.max(1,Math.round(t.width*i)),height:Math.max(1,Math.round(t.height*n))},r,a)}(i,o.rect,t,r);if(!oB(d))continue;let u=n.get(o.ref);(!u||l>u.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)=>oK(e.overlayRect)-oK(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(oz(e.overlayRect,r.overlayRect)||oz(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}oK(r.overlayRect)<oK(t[e].overlayRect)&&(t[e]=r)}return t})([...n.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:oW(e.ref,t.ref)}).slice(0,a.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:oW(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:ee(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,n;(function(e,t,r){for(let a=0;a<2;a+=1)oX(e,t.x,t.x+t.width-1,t.y+a,r),oX(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),oY(e,t.x+a,t.y,t.y+t.height-1,r),oY(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(n=e).overlayRect,oC),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=oZ(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:oZ(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,i){for(let n=0;n<11;n+=1)for(let o=0;o<a;o+=1)oQ(e,t+o,r+n,i)})(e,i,o,a,oE),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=oT[t];if(a)for(let t=0;t<a.length;t+=1)for(let o=0;o<a[t].length;o+=1)"1"===a[t][o]&&oQ(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,o$)}(a,n.overlayRect,n.ref)}return await i.writeFile(e.screenshotPath,p.sync.write(t)),r}function oU(e){let t=[e.type,e.role,e.subrole].map(e=>td(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 oG(e){let t=[e.type,e.role,e.subrole].map(e=>td(e??"")).join(" ");return t.includes("application")||t.includes("window")}function oV(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!!oV(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function oj(e){var t;return"string"==typeof e&&!!oq(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function oH(e){let t=[e.label,e.value].find(oq);return t?t.trim():oj(e.identifier)?e.identifier.trim():void 0}function oB(e){return!!(e&&e.width>0&&e.height>0)}function oK(e){return e.width*e.height}function oz(e,t){return t.x>=e.x&&t.y>=e.y&&t.x+t.width<=e.x+e.width&&t.y+t.height<=e.y+e.height}function oW(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function oJ(e,t,r){let a=oZ(e.x,0,Math.max(0,t-1)),i=oZ(e.y,0,Math.max(0,r-1)),n=Math.max(1,t-a),o=Math.max(1,r-i);return{x:a,y:i,width:oZ(e.width,1,n),height:oZ(e.height,1,o)}}function oZ(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function oX(e,t,r,a,i){for(let n=t;n<=r;n+=1)oQ(e,n,a,i)}function oY(e,t,r,a,i){for(let n=r;n<=a;n+=1)oQ(e,t,n,i)}function oQ(e,t,r,a){if(t<0||r<0||t>=e.width||r>=e.height)return;let i=(e.width*r+t)*4;e.data[i]=a[0],e.data[i+1]=a[1],e.data[i+2]=a[2],e.data[i+3]=a[3]}let o0=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),o1=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]),o2=new Set(o1),o5=new Map;function o3(e,t,r,a){let i=e6().requestId;return{...eG(e,t,r,a,i),requestId:i}}async function o4(e,t,r){let a=r.get(t);if(a)return`device:${a.device.id}`;if("open"===e.command||r7(e.flags))try{let t=await eL(e.flags??{});return`device:${t.id}`}catch{}return`session:${t}`}async function o8(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,leaseRegistry:n,invoke:o,contextFromFlags:s}=e,l=await oS({req:t,leaseRegistry:n});if(l)return l;let d=await i8({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(d)return d;let u=await I({req:t,sessionName:r,logPath:a,sessionStore:i});if(u)return u;let c=await nJ({req:t,sessionName:r,sessionStore:i,logPath:a});if(c)return c;let f=await ni({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:o});if(f)return f;let p=await oy({req:t,sessionName:r,sessionStore:i,contextFromFlags:s});return p||null}async function o6(e){var t;let r,a,i,n,o,s,l,{req:d,session:u,logPath:c,sessionStore:f}=e,p=d.command;if(!to(p,u.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${p} is not supported on this device`}};if("android"===u.device.platform&&u.recording&&"record"!==p&&"failed"===await oD({session:u}))return{ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}};let{resolvedPositionals:m,resolvedOut:h,recordedPositionals:g,recordedFlags:v}=(r=(t=d).command,a=t.positionals??[],i=t.flags?.out,n="screenshot"===r&&a[0]?[tF.expandHome(a[0],t.meta?.cwd),...a.slice(1)]:a,o="screenshot"===r&&i?tF.expandHome(i,t.meta?.cwd):i,s="screenshot"===r?n:a,l="screenshot"===r&&o?{...t.flags??{},out:o}:t.flags??{},{resolvedPositionals:n,resolvedOut:o,recordedPositionals:s,recordedFlags:l}),y=Date.now(),I={...o3(c,d.flags,u.appBundleId,u.trace?.outPath),surface:u.surface},S=await w(u.device,p,m,h,{...I});return"screenshot"===p&&d.flags?.overlayRefs&&"string"==typeof S?.path&&await o9(u,S,c),function(e){let{session:t,sessionStore:r,command:a,resolvedPositionals:i,recordedPositionals:n,recordedFlags:o,data:s,actionStartedAt:l,actionFinishedAt:d,flags:u}=e,c=function(e,t,r,a){if("scroll"!==t)return a;let i=nY(e.snapshot),n={...a??{}},o=n3(n.direction)??n3(r[0]);if(!o)return a;let s=n4(n.amount)??n4(r[1]),l=n4(n.pixels),d=n9(n,[]),u=n4(n.referenceWidth),c=n4(n.referenceHeight),f=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:i??n0;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=en({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);n1(t,a,i,c,u,l,d),r.recordAction(t,{command:a,positionals:n,flags:o,result:s??{}})}({session:u,sessionStore:f,command:p,resolvedPositionals:m,recordedPositionals:g,recordedFlags:v,data:S,actionStartedAt:y,actionFinishedAt:Date.now(),flags:d.flags??{}}),eA(p)&&tf(u,p),{ok:!0,data:S??{}}}async function o9(e,t,r){let a=eW(await T({device:e.device,session:e,flags:void 0,logPath:r,snapshotScope:void 0}),void 0);e.snapshot=a;let i=await oF({screenshotPath:t.path,snapshot:a});t.overlayRefs=i}function o7(e){a.existsSync(e)&&a.unlinkSync(e)}function se(e){if(!a.existsSync(e))return null;try{let t=JSON.parse(a.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function st(e){let t=se(e);if(!t||t.pid===process.pid)try{a.existsSync(e)&&a.unlinkSync(e)}catch{}}function sr(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:sa,infoPath:si,lockPath:sn,logPath:so,sessionsDir:ss}=ts(process.env.AGENT_DEVICE_STATE_DIR),sl=ec(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var sd=ss;if(a.existsSync(sd))for(let e of a.readdirSync(sd,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=n.join(sd,e.name,tG);if(a.existsSync(t))try{let e=tV(a.readFileSync(t,"utf8"));if(e&&function(e){let t,r=Z(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=es(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{tj(t)}}let su=new tF(ss),sc=new rJ({maxActiveSimulatorLeases:sr(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:sr(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:sr(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:sr(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),sf=H(),sp=r.randomBytes(24).toString("hex"),sm=Z(process.pid)??void 0,sh=eq(),sg=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:o}=e;async function s(e){let l=!!(e.meta?.debug||e.flags?.verbose);return await X({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:l,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:tw(new tv("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=_(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=eB(r);if(r&&!a)throw new tv("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new tv("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);tr({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=oI(r);o1.has(l)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:d.tenantId,runId:d.runId,leaseId:d.leaseId,backend:d.leaseBackend});let u=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),c=o2.has(l)?null:await o4(r,u,a),f=async()=>{let e=a.get(u);e&&(!function(e){let t=e.recording;if(!t||"ios"!==e.device.platform)return;let r=V(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(u,e));let d=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?oA(t,a):function(e,t,r){var a,i;let n=[],o=tu(t);if(void 0!==e.platform&&o&&(a=tu(e.platform),i=o,a&&i&&a!==i&&("apple"===a?!Y(i):"apple"!==i||!Y(a)))&&n.push({key:"platform",value:e.platform}),"open"===r)return n;for(let t of o_){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 o_)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new tv("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(ob).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,e),c=e=>(function(e,t,r){let a=e6();if(!t.ok){tr({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=tl({force:!0})??void 0;return{ok:!1,error:tw(new tv(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 tr({level:"info",phase:"request_success"}),tl(),{ok:!0,data:function(e,t,r){var a,i;let o;if(!t)return t;let s=(a=e,i=t,o=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||o.some(e=>e?.field==="path")||"string"!=typeof i.path||o.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:n.basename(a.meta?.clientArtifactPaths?.path??i.path)}),o.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,o);if(e?.recording?.invalidatedReason&&"record"!==l&&"close"!==l)return c({ok:!1,error:{code:"COMMAND_FAILED",message:e.recording.invalidatedReason}});!e||d.meta?.lockPolicy||o0.has(l)||function(e,t){let r=oA(e,t);if(0!==r.length){var a;let t,i,n;throw new tv("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(ob).join(", ")}. Use a different --session name or close this session first.`)}}(e,d.flags);let f=await o8({req:d,sessionName:u,logPath:t,sessionStore:a,leaseRegistry:i,invoke:s,contextFromFlags:(e,r,i)=>({...o3(t,e,r,i),surface:a.get(u)?.surface})});if(f)return c(f);let p=a.get(u);if(!p)return c({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});let m=await o6({req:d,session:p,sessionName:u,logPath:t,sessionStore:a});return c(m)};if(!c)return await f();return await k(o5,c,f)}catch(r){tr({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=e6(),t=tl({force:!0})??void 0;return{ok:!1,error:tw(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return s}({logPath:so,token:sp,sessionStore:su,leaseRegistry:sc,trackDownloadableArtifact:function(e){let t=r.randomUUID(),a=setTimeout(()=>{ry(t)},9e5);return a.unref(),rv.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:a}),t}});!async function(){let e,t;if(!function(e,t,r){a.existsSync(e)||a.mkdirSync(e,{recursive:!0});let i=JSON.stringify(r,null,2),n=()=>{try{return a.writeFileSync(t,i,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(n())return!0;let o=se(t);if(o?.pid&&o.pid!==process.pid&&y(o.pid,o.processStartTime))return!1;try{a.unlinkSync(t)}catch{}return n()}(sa,sn,{pid:process.pid,version:sf,startedAt:Date.now(),processStartTime:sm})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var i;let n;if("socket"===sl||"dual"===sl){let t=m.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))e2(e);tr({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await G(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){tr({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=U(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),b(o),F(o))throw eS();i=await sg(e)}catch(e){i={ok:!1,error:tw(e)}}finally{r-=1,o&&(a.delete(o),B(o))}e.destroyed||e.write(`${JSON.stringify(i)}
|
|
35
|
+
`),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 tv("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===sl||"dual"===sl){let e=await rq({handleRequest:sg,token:sp});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 tv("COMMAND_FAILED","Failed to bind HTTP server"))})})}i={socketPort:e,httpPort:t,token:sp,version:sf,codeSignature:sh,processStartTime:sm},a.existsSync(sa)||a.mkdirSync(sa,{recursive:!0}),a.writeFileSync(so,""),n=i.socketPort&&i.httpPort?"dual":i.httpPort?"http":"socket",a.writeFileSync(si,JSON.stringify({port:i.socketPort,httpPort:i.httpPort,transport:n,token:i.token,pid:process.pid,version:i.version,codeSignature:i.codeSignature,processStartTime:i.processStartTime,stateDir:sa},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
|
|
36
36
|
`),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
|
|
37
|
-
`)}catch(t){let e=
|
|
38
|
-
`),r))try{t.close(()=>{})}catch{}
|
|
39
|
-
`),s()}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof
|
|
37
|
+
`)}catch(t){let e=tg(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
|
|
38
|
+
`),r))try{t.close(()=>{})}catch{}o7(si),st(sn),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(),su.toArray()))su.writeSessionLog(e);await eR(),o7(si),st(sn),process.exit(0)}};process.on("SIGINT",()=>{s()}),process.on("SIGTERM",()=>{s()}),process.on("SIGHUP",()=>{s()}),process.on("uncaughtException",e=>{let t=e instanceof tv?e:tg(e);process.stderr.write(`Daemon error: ${t.message}
|
|
39
|
+
`),s()}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof tv?t:tg(t);process.stderr.write(`Daemon error: ${r.message}
|
|
40
40
|
`),s()})}();
|