agent-device 0.16.8 → 0.16.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.8.apk → agent-device-android-multitouch-helper-0.16.10.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.10.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.8.manifest.json → agent-device-android-multitouch-helper-0.16.10.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.8.apk → agent-device-android-snapshot-helper-0.16.10.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.10.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.8.manifest.json → agent-device-android-snapshot-helper-0.16.10.manifest.json} +6 -6
- package/dist/src/2415.js +19 -19
- package/dist/src/8114.js +3 -3
- package/dist/src/apps.js +2 -2
- package/dist/src/generic.js +4 -3
- package/dist/src/input-actions.js +1 -1
- package/dist/src/session.js +2 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +197 -232
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +282 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +29 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +8 -771
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +30 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -20
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +10 -50
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +723 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +64 -22
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +7 -4
- package/package.json +1 -1
- package/server.json +2 -2
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.8.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.8.apk.sha256 +0 -1
package/dist/src/8114.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e from"node:path";import t from"node:crypto";import n from"node:fs";import{resolveUserPath as r,expandUserHomePath as o}from"./3267.js";import{findProjectRoot as s}from"./9671.js";function i(e,t){let n=[],r=e+t.toString(),o=r.indexOf("\n");for(;-1!==o;){let e=r.slice(0,o).trim();r=r.slice(o+1),e&&n.push(e),o=r.indexOf("\n")}return{lines:n,buffer:r}}function a(t){let n,s=(n=(t??"").trim())?r(n):e.join(o("~"),".agent-device");return{baseDir:s,infoPath:e.join(s,"daemon.json"),lockPath:e.join(s,"daemon.lock"),logPath:e.join(s,"daemon.log"),sessionsDir:e.join(s,"sessions")}}function
|
|
2
|
-
`}function D(e){return`${JSON.stringify({type:"response",response:e})}
|
|
1
|
+
import e from"node:path";import t from"node:crypto";import n from"node:fs";import{resolveUserPath as r,expandUserHomePath as o}from"./3267.js";import{findProjectRoot as s}from"./9671.js";function i(e,t){let n=[],r=e+t.toString(),o=r.indexOf("\n");for(;-1!==o;){let e=r.slice(0,o).trim();r=r.slice(o+1),e&&n.push(e),o=r.indexOf("\n")}return{lines:n,buffer:r}}function a(t){let n,s=(n=(t??"").trim())?r(n):e.join(o("~"),".agent-device");return{baseDir:s,infoPath:e.join(s,"daemon.json"),lockPath:e.join(s,"daemon.lock"),logPath:e.join(s,"daemon.log"),sessionsDir:e.join(s,"sessions")}}function l(e){let t=(e??"").trim().toLowerCase();return"http"===t?"http":"dual"===t?"dual":"socket"}function u(e){let t=(e??"").trim().toLowerCase();return"auto"===t?"auto":"socket"===t?"socket":"http"===t?"http":"auto"}function p(e){return"tenant"===(e??"").trim().toLowerCase()?"tenant":"none"}function f(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}let m=/(?:^|[^\w$.])(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s+)?['"]([^'"]+)['"]/gm,c=/import\(\s*['"]([^'"]+)['"]\s*\)/gm,d=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];function $(){let e=process.argv[1];return e?g(e):"unknown"}function g(r,o=s()){try{let s=e.resolve(o),i=[e.resolve(r)],a=new Set,l=[];for(;i.length>0;){let t=i.pop();if(!t||a.has(t))continue;a.add(t);let r=n.statSync(t);if(!r.isFile())continue;let o=e.relative(s,t)||t;l.push(`${o}:${r.size}:${Math.trunc(r.mtimeMs)}`);let u=n.readFileSync(t,"utf8");for(let n of function(e){let t=new Set;return h(e,m,t),h(e,c,t),[...t]}(u)){let r=function(t,n){let r=e.resolve(e.dirname(t),n),o=y(r);if(o)return o;for(let e of d){let t=y(`${r}${e}`);if(t)return t}for(let t of d){let n=y(e.join(r,`index${t}`));if(n)return n}return null}(t,n);r&&i.push(r)}}let u=l.sort().join("|"),p=t.createHash("sha1").update(u).digest("hex");return`graph:${l.length}:${p}`}catch{return"unknown"}}function h(e,t,n){t.lastIndex=0;let r=null;for(;null!==(r=t.exec(e));){let e=r[1]?.trim();e?.startsWith(".")&&n.add(e)}}function y(e){try{return n.statSync(e).isFile()?e:null}catch{return null}}function v(e){return e.meta?.requestProgress==="replay-test"}function S(e){return!!e&&"object"==typeof e&&"progress"===e.type&&!!e.event}function x(e){return!!e&&"object"==typeof e&&"response"===e.type&&!!e.response}function j(e){return`${JSON.stringify({type:"progress",event:e})}
|
|
3
2
|
`}function P(e){return`${JSON.stringify({type:"response",response:e})}
|
|
4
|
-
`}function
|
|
3
|
+
`}function D(e){return`${JSON.stringify({type:"response",response:e})}
|
|
4
|
+
`}function _(t){var n,r,o;let s,i,a;if("replay-test"!==t.type)return;let l=(n=t,(s=n.title?.trim())?JSON.stringify(s):e.basename(n.file)),u=void 0!==t.durationMs?` (${a=(i=Math.max(0,(r=t).durationMs??0)/1e3)>=10?`${i.toFixed(1)}s`:i>=1?`${i.toFixed(2)}s`:`${i.toFixed(3).replace(/0+$/,"").replace(/\.$/,"")}s`,r.attempt&&r.attempt>1&&!r.retrying?`total ${a}`:a})`:"",p=void 0===(o=t).attempt?"":"fail"===o.status&&o.retrying&&void 0!==o.maxAttempts?` attempt ${o.attempt}/${o.maxAttempts} retrying`:o.attempt>1?` after ${o.attempt} attempts`:"",f=t.message?.replace(/\s+/g," ").trim();return"pass"===t.status?`PASS ${l}${p}${u}`:"skip"===t.status?[`SKIP ${l}`,f?` ${f}`:""].filter(Boolean).join("\n"):[`FAIL ${l}${p}${u}`,f?` ${f}`:"",t.artifactsDir?` artifacts: ${t.artifactsDir}`:""].filter(Boolean).join("\n")}export{g as computeDaemonCodeSignature,i as consumeTextLines,_ as formatRequestProgressEvent,S as isDaemonProgressEnvelope,x as isDaemonResponseEnvelope,f as normalizeTenantId,$ as resolveDaemonCodeSignature,a as resolveDaemonPaths,l as resolveDaemonServerMode,u as resolveDaemonTransportPreference,p as resolveSessionIsolationMode,j as serializeDaemonProgressEnvelope,P as serializeDaemonResponseEnvelope,D as serializeDaemonRpcResponseEnvelope,v as shouldStreamRequestProgress};
|
package/dist/src/apps.js
CHANGED
|
@@ -3,10 +3,10 @@ ${i}
|
|
|
3
3
|
${a}`.toLowerCase();return r.includes("unknown option '--device'")||r.includes("unknown subcommand")&&r.includes("screenshot")||r.includes("unrecognized subcommand")&&r.includes("screenshot")}(t))throw t;eP(e,"devicectl_screenshot",t)}await eL(e,t,i,a,r)}async function eN(e,t,i,a,r=eC,o){if("simulator"!==e.kind)throw new n("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let l="object"==typeof a&&null!==a?a:r;await l.ensureBooted(e);let s=async()=>{};try{s=await l.prepareStatusBarForScreenshot(e)}catch(t){ex(e,"prepare_failed",t)}try{try{await l.captureWithRetry(e,t);return}catch(t){if(!l.shouldFallbackToRunner(t))throw t;eP(e,"simctl_screenshot",t)}await l.captureWithRunner(e,t,i,"boolean"==typeof a?a:void 0,o)}finally{await s().catch(t=>ex(e,"restore_failed",t))}}async function eS(e,t){let i=G.fromTimeoutMs(2e4);await B(async({deadline:i})=>{var a;await (a=["io",e.id,"screenshot",t],p(e,a,{timeoutMs:Math.max(1e3,i?.remainingMs()??2e4)}))},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>eF(e)},{deadline:i,phase:"ios_simulator_screenshot"})}async function eL(e,i,a,r,o){let l=(await u(e,{command:"screenshot",appBundleId:a,fullscreen:r},o)).message;if(!l)throw new n("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await t.copyFile(l,i):"simulator"===e.kind?await eM(e,l,i):await eD(e,l,i)}async function eD(e,t,i){let a=G.fromTimeoutMs(2e4),r={exitCode:1,stdout:"",stderr:""};for(let n of l)if(0===(r=await o(["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",i,"--domain-type","appDataContainer","--domain-identifier",n],{allowFailure:!0,timeoutMs:eO(a,2e4,"runner screenshot copy")})).exitCode)return;let s=r.stderr.trim()||r.stdout.trim()||`devicectl exited with code ${r.exitCode}`;throw new n("COMMAND_FAILED",`Failed to capture iOS screenshot: ${s}`)}async function eM(e,i,r){let o=G.fromTimeoutMs(2e4),s="Unable to locate runner container for simulator screenshot";for(let n of l){var d;let l=await (d=["get_app_container",e.id,n,"data"],p(e,d,{allowFailure:!0,timeoutMs:eO(o,2e4,"runner screenshot container lookup")}));if(0!==l.exitCode){let e=l.stderr.trim();e&&(s=e);continue}let u=l.stdout.trim();if(!u){s="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let i=a.resolve(e),r=t.trim();if(!r)return[];let n=[],o=new Set,l=e=>{let t=a.normalize(e);o.has(t)||(o.add(t),n.push(t))},s=r.replace(/^\/+/,""),d=s.replace(/\\/g,"/");if(s&&l(a.join(i,s)),a.isAbsolute(r)&&l(a.normalize(r)),d.startsWith("tmp/"))l(a.join(i,d));else{let e=d.lastIndexOf("/tmp/");if(e>=0){let t=d.slice(e+1);l(a.join(i,t))}}let u=a.basename(r);return u&&l(a.join(i,"tmp",u)),n}(u,i))try{await t.copyFile(e,r);return}catch(e){s=e instanceof Error?e.message:String(e)}}throw new n("COMMAND_FAILED",`Failed to capture iOS screenshot: ${s}`)}function eO(e,t,i){let a=e.remainingMs();if(a>0)return a;throw new n("COMMAND_FAILED",`iOS ${i} timed out after ${t}ms`,{timeoutMs:t,step:i})}function eP(e,t,i){let a=ep(i);V({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function ex(e,t,i){V({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...ep(i)}})}function eF(e){if(!(e instanceof n)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},i="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",o=`${e.message}
|
|
4
4
|
${i}
|
|
5
5
|
${a}
|
|
6
|
-
${r}`.toLowerCase();return o.includes("timeout waiting for screen surfaces")||o.includes("nsposixerrordomain")&&o.includes("code=60")&&o.includes("screenshot")||o.includes("timed out")&&o.includes("screenshot")}let eR={settings:"com.apple.Preferences"},e$=E(),eE=null;function ek(e){return{platform:"ios",deviceId:e.id,variant:e.kind}}function eT(e,t,i){return o(m(e,t),i)}function eU(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function eB(e,t){if("macos"===e.platform)return await ea(t);let i=t.trim();if(i.includes("."))return i;let a=eR[i.toLowerCase()];if(a)return a;let r=ek(e),o=e$.get(r,i);if(o)return o;let l=("simulator"===e.kind?await e2(e):await v(e,"all")).filter(e=>e.name.toLowerCase()===i.toLowerCase()),s=l[0];if(void 0!==s&&1===l.length)return e$.set(r,i,s.bundleId);if(l.length>1)throw new n("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:l});throw new n("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function eG(e,t){var i;let r;if("ios"!==e.platform||"simulator"!==e.kind)return;let n=(i=t,r=/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(i.trim()),r?.[1]?.toLowerCase());if(!n)return;let o=await e3(e),l=[];for(let e of o)!e.bundleId.startsWith("com.callstack.agentdevice.runner")&&e.path&&(await
|
|
6
|
+
${r}`.toLowerCase();return o.includes("timeout waiting for screen surfaces")||o.includes("nsposixerrordomain")&&o.includes("code=60")&&o.includes("screenshot")||o.includes("timed out")&&o.includes("screenshot")}let eR={settings:"com.apple.Preferences"},e$=E(),eE=null;function ek(e){return{platform:"ios",deviceId:e.id,variant:e.kind}}function eT(e,t,i){return o(m(e,t),i)}function eU(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function eB(e,t){if("macos"===e.platform)return await ea(t);let i=t.trim();if(i.includes("."))return i;let a=eR[i.toLowerCase()];if(a)return a;let r=ek(e),o=e$.get(r,i);if(o)return o;let l=("simulator"===e.kind?await e2(e):await v(e,"all")).filter(e=>e.name.toLowerCase()===i.toLowerCase()),s=l[0];if(void 0!==s&&1===l.length)return e$.set(r,i,s.bundleId);if(l.length>1)throw new n("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:l});throw new n("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function eG(e,t){var i;let r;if("ios"!==e.platform||"simulator"!==e.kind)return;let n=(i=t,r=/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(i.trim()),r?.[1]?.toLowerCase());if(!n)return;let o=await e3(e),l=[];for(let e of o)!e.bundleId.startsWith("com.callstack.agentdevice.runner")&&e.path&&(await e5(a.join(e.path,"Info.plist"))).has(n)&&l.push(e);let s=l.filter(e=>"User"===e.applicationType);return 1===s.length?s[0]?.bundleId:s.length>1?void 0:1===l.length?l[0]?.bundleId:void 0}async function eV(e,t,i){let a=i?.launchConsole?.trim(),r=i?.launchArgs;if(a&&("ios"!==e.platform||"simulator"!==e.kind))throw new n("UNSUPPORTED_OPERATION",S);if("macos"===e.platform){if(r&&r.length>0)throw new n("UNSUPPORTED_OPERATION","--launch-args is not supported on macOS; launch arguments are currently iOS-only.");await er(e,t,i);return}let o=i?.url?.trim();if(o){if(a)throw new n("INVALID_ARGS",d);if(!k(o))throw new n("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind)return void await ej(e,o,r);let l=U(i?.appBundleId??await eB(e,t),o);if(!l)throw new n("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");return void await tr(e,l,{payloadUrl:o,launchArgs:r})}let l=t.trim();if(k(l)){if(a)throw new n("INVALID_ARGS",d);if("simulator"===e.kind)return void await ej(e,l,r);let t=U(i?.appBundleId,l);if(!t)throw new n("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");return void await tr(e,t,{payloadUrl:l,launchArgs:r})}let s=i?.appBundleId??await eB(e,t);"simulator"===e.kind?await tt(e,s,{...a?{launchConsole:a}:{},...r?{launchArgs:r}:{}}):await tr(e,s,{launchArgs:r})}async function ej(e,t,i){if(i&&i.length>0)throw new n("INVALID_ARGS","--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.");await b(e),await eT(e,["openurl",e.id,t])}async function eW(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await L(e)&&await b(e)}async function eK(e,t){if("macos"===e.platform)return void await en(e,t);let i=await eB(e,t);if("simulator"===e.kind){await b(e);let t=m(e,["terminate",e.id,i]),a=await o(t,{allowFailure:!0,timeoutMs:15e3});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new n("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await A(["device","process","terminate","--device",e.id,i],{action:"terminate iOS app",deviceId:e.id})}async function eH(e,i){if("ios"!==e.platform||"simulator"!==e.kind)throw new n("UNSUPPORTED_OPERATION","Clearing app state is currently supported only on iOS simulators.");let r=await eB(e,i);await b(e),await eK(e,r);let o=await eT(e,["get_app_container",e.id,r,"data"],{allowFailure:!0});if(0!==o.exitCode)throw new n("COMMAND_FAILED",`simctl get_app_container failed for ${r}`,{stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode});let l=o.stdout.trim();if(!l)throw new n("COMMAND_FAILED",`simctl get_app_container returned an empty data container path for ${r}`);let s=await t.readdir(l);return await Promise.all(s.map(e=>t.rm(a.join(l,e),{recursive:!0,force:!0}))),{bundleId:r,containerPath:l}}async function ez(e,t){return await e$.invalidateWhile(ek(e),async()=>{let i=await eB(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,i],a=await o(t,{allowFailure:!0,timeoutMs:2e4});if(0!==a.exitCode){let r=String(a.stdout??""),o=String(a.stderr??"");if(!eU(`${r}
|
|
7
7
|
${o}`.toLowerCase()))throw new n("COMMAND_FAILED",`Failed to uninstall iOS app ${i}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:r,stderr:o,deviceId:e.id,hint:s(r,o)??f})}return{bundleId:i}}await b(e);let a=await eT(e,["uninstall",e.id,i],{allowFailure:!0});if(0!==a.exitCode&&!eU(`${a.stdout}
|
|
8
8
|
${a.stderr}`.toLowerCase()))throw new n("COMMAND_FAILED",`simctl uninstall failed for ${i}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:i}})}async function eq(e,t,i){let a=await q({kind:"path",path:t},i);try{return await eZ(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function eJ(e,t,i){return await e$.invalidateWhile(ek(e),async()=>{let{bundleId:a}=await ez(e,t);return await eq(e,i,{appIdentifierHint:t}),{bundleId:a}})}async function eZ(e,t){await e$.invalidateWhile(ek(e),async()=>{"simulator"!==e.kind?await A(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await b(e),await eT(e,["install",e.id,t]))})}async function eQ(e){if("macos"===e.platform)return await eo();w(e,"clipboard"),await b(e);let t=await eT(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new n("COMMAND_FAILED","Failed to read iOS simulator clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return t.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function eX(e,t){if("macos"===e.platform)return void await el(t);w(e,"clipboard"),await b(e);let i=await eT(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==i.exitCode)throw new n("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function eY(e,r,n){w(e,"push"),await b(e);let o=await t.mkdtemp(a.join(i.tmpdir(),"agent-device-ios-push-")),l=a.join(o,"payload.apns");try{await t.writeFile(l,`${JSON.stringify(n)}
|
|
9
|
-
`,"utf8"),await eT(e,["push",e.id,r,l])}finally{await t.rm(o,{recursive:!0,force:!0})}}async function e0(e,t,i,a,r){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await ed(i);if("permission"===e){let e=$(i);if("deny"===e)throw new n("INVALID_ARGS",W("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new n("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(r?.permissionTarget);return await h(e,t)}throw new n("INVALID_ARGS",W(t))}w(e,"settings"),await b(e);let o=t.toLowerCase();switch(o){case"clear-app-state":{if("clear"!==i.toLowerCase())throw new n("INVALID_ARGS","settings clear-app-state only supports clear.");if(!a)throw new n("INVALID_ARGS","settings clear-app-state requires an app id or an active app session.");let t=await eH(e,a);return{bundleId:t.bundleId,containerPath:t.containerPath,cleared:!0}}case"wifi":{let t=F(i);await eT(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(F(i)?await eT(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await eT(e,["status_bar",e.id,"clear"]));case"location":{if("set"===i.toLowerCase()){let{latitude:t,longitude:i}=j(r);return await eT(e,["location",e.id,"set",`${t},${i}`]),{latitude:t,longitude:i}}let t=F(i);if(!a)throw new n("INVALID_ARGS","location setting requires an active app in session");await eT(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=e9[o],a=function(e,t){let i=e.trim().toLowerCase();if("match"===i)return"match";if("nonmatch"===i)return"nonmatch";if("enroll"===i)return"enroll";if("unenroll"===i)return"unenroll";throw new n("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(i,o);await te(e,a,{settingName:o,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await
|
|
9
|
+
`,"utf8"),await eT(e,["push",e.id,r,l])}finally{await t.rm(o,{recursive:!0,force:!0})}}async function e0(e,t,i,a,r){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await ed(i);if("permission"===e){let e=$(i);if("deny"===e)throw new n("INVALID_ARGS",W("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new n("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(r?.permissionTarget);return await h(e,t)}throw new n("INVALID_ARGS",W(t))}w(e,"settings"),await b(e);let o=t.toLowerCase();switch(o){case"clear-app-state":{if("clear"!==i.toLowerCase())throw new n("INVALID_ARGS","settings clear-app-state only supports clear.");if(!a)throw new n("INVALID_ARGS","settings clear-app-state requires an app id or an active app session.");let t=await eH(e,a);return{bundleId:t.bundleId,containerPath:t.containerPath,cleared:!0}}case"wifi":{let t=F(i);await eT(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(F(i)?await eT(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await eT(e,["status_bar",e.id,"clear"]));case"location":{if("set"===i.toLowerCase()){let{latitude:t,longitude:i}=j(r);return await eT(e,["location",e.id,"set",`${t},${i}`]),{latitude:t,longitude:i}}let t=F(i);if(!a)throw new n("INVALID_ARGS","location setting requires an active app in session");await eT(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=e9[o],a=function(e,t){let i=e.trim().toLowerCase();if("match"===i)return"match";if("nonmatch"===i)return"nonmatch";if("enroll"===i)return"enroll";if("unenroll"===i)return"unenroll";throw new n("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(i,o);await te(e,a,{settingName:o,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await e4(e,i);await eT(e,["ui",e.id,"appearance",t]);return}case"permission":{var l;if(!a)throw new n("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(l=$(i))?"revoke":l,o=function(e,t){let i=R(e);if("photos"!==i&&t?.trim())throw new n("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===i)return"camera";if("microphone"===i)return"microphone";if("contacts"===i)return"contacts";if("contacts-limited"===i)return"contacts-limited";if("notifications"===i)return"notifications";if("calendar"===i)return"calendar";if("location"===i)return"location";if("location-always"===i)return"location-always";if("media-library"===i)return"media-library";if("motion"===i)return"motion";if("reminders"===i)return"reminders";if("siri"===i)return"siri";if("photos"===i){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new n("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new n("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(r?.permissionTarget,r?.permissionMode);await e8(e,t,o,a);return}default:throw new n("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function e1(e,t){return"macos"===e.platform?await eu(t):"simulator"===e.kind?I(await e2(e),t):await v(e,t)}async function e2(e){return(await e3(e)).map(e=>({bundleId:e.bundleId,name:e.name}))}async function e3(e){let t=(await eT(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let i=null;if(t.startsWith("{"))try{i=JSON.parse(t)}catch{i=null}if(!i&&t.startsWith("{"))try{let e=await g("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(i=JSON.parse(e.stdout))}catch{i=null}return i?Object.entries(i).map(([e,t])=>{let i=function(e){if(e.Path)return e.Path;if(e.Bundle)try{return r(e.Bundle)}catch{return}}(t);return{bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e,...i?{path:i}:{},...t.ApplicationType?{applicationType:t.ApplicationType}:{}}}):[]}async function e5(e){let t=await g("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode)return new Set;try{let e=JSON.parse(t.stdout),i=new Set;for(let t of e.CFBundleURLTypes??[])if(Array.isArray(t.CFBundleURLSchemes))for(let e of t.CFBundleURLSchemes)"string"==typeof e&&e.trim()&&i.add(e.trim().toLowerCase());return i}catch{return new Set}}async function e4(e,t){let i=P(t);if("toggle"!==i)return i;let a=await eT(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new n("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let r=function(e,t){let i=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
|
|
10
10
|
${t}`);if(!i)return null;let a=i[1]?.toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!r)throw new n("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===r?"light":"dark"}let e9={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function e8(e,t,i,a){let r=await e7(e);if(!r.has(i))throw new n("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${i}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(r).sort().join(", ")}`});let o=["privacy",e.id,t,i,a],l="notifications"===i;if(!("reset"===t&&l))try{await eT(e,o);return}catch(t){if(!(l&&e6(t)))throw t;throw new n("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:a,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await eT(e,o);return}catch(e){if(!e6(e))throw e}try{await eT(e,["privacy",e.id,"reset","all",a])}catch(t){throw new n("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:a,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function e6(e){if(!(e instanceof n)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return(t.includes("failed to grant access")||t.includes("failed to revoke access")||t.includes("failed to reset access"))&&t.includes("operation not permitted")}async function e7(t){let i=T(t.simulatorSetPath),a=`${process.env.PATH??""}::${i??""}`;if(eE&&e===a)return eE;let r=await eT(t,["privacy","help"],{allowFailure:!0}),o=function(e){let t=new Set,i=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){i=!0;continue}if(!i)continue;if(e.startsWith("bundle identifier"))break;let r=/^([a-z-]+)\s+-\s+/.exec(e),n=r?.[1];void 0!==n&&t.add(n)}return t}(`${r.stdout}
|
|
11
11
|
${r.stderr}`);if(0===o.size)throw new n("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return eE=o,e=a,o}async function te(e,t,i){let a=function(e,t,i){let a=i.length>0?i:["face"];switch(t){case"match":return a.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return a.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,i.modalityAliases),r=[];for(let t of a){let i=m(e,t),a=await o(i,{allowFailure:!0});if(0===a.exitCode)return;r.push({args:i,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let l=x(r);if(r.length>0&&r.every(e=>{var t,i;let a;return t=e.stdout,i=e.stderr,(a=`${t}
|
|
12
12
|
${i}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new n("UNSUPPORTED_OPERATION",`${i.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:i.settingName,attempts:l});throw new n("COMMAND_FAILED",`Failed to simulate ${i.settingName}.`,{deviceId:e.id,action:t,setting:i.settingName,attempts:l})}async function tt(e,t,i){await b(e);let a=0,r=G.fromTimeoutMs(6e4);try{await B(async({deadline:a})=>{var r,l,s,d;let u;if(a?.isExpired())throw new n("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:6e4});let c=(l=e.id,s=t,d=i,u=["launch"],d?.launchConsole&&u.push("--console-pty"),u.push(l,s),d?.launchArgs&&d.launchArgs.length>0&&u.push(...d.launchArgs),r=u,m(e,r)),p=i?.launchConsole?await ti(c,i.launchConsole):await o(c,{allowFailure:!0});if(0!==p.exitCode)throw new n("COMMAND_FAILED",`xcrun exited with code ${p.exitCode}`,{cmd:"xcrun",args:c,stdout:p.stdout,stderr:p.stderr,exitCode:p.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!K(e)&&(a+=1)<3},{deadline:r})}catch(i){if(K(i)){var l;let a=(l=await H(e,t)).installed?!1===l.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";i.details={...i.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw i}}async function ti(e,i){await t.mkdir(a.dirname(i),{recursive:!0});try{let t=await o(e,{allowFailure:!0,timeoutMs:25e3});return await ta(i,t.stdout,t.stderr),t}catch(t){let e=(t instanceof n?t:void 0)?.details;if(e?.timeoutMs===25e3){let t="string"==typeof e.stdout?e.stdout:"",a="string"==typeof e.stderr?e.stderr:"";return await ta(i,t,a),V({level:"warn",phase:"ios_simulator_launch_console_capture_timeout",data:{timeoutMs:25e3,logPath:i,stdoutBytes:Buffer.byteLength(t),stderrBytes:Buffer.byteLength(a)}}),{stdout:t,stderr:a,exitCode:0}}throw t}}async function ta(e,i,a){var r,n;await t.writeFile(e,(r=i,n=a,!r||!n||r.endsWith("\n")||r.endsWith("\r")?`${r}${n}`:`${r}
|
package/dist/src/generic.js
CHANGED
|
@@ -2,11 +2,12 @@ import t from"node:fs";import e from"node:path";import{AppError as r}from"./9152
|
|
|
2
2
|
`),process.stdout.write(` ${t.error?.message??"Unknown test failure"}
|
|
3
3
|
`),s=t,[s.error?.hint?`hint: ${s.error.hint}`:"",s.artifactsDir?`artifacts: ${s.artifactsDir}`:"",s.error?.logPath?`log: ${s.error.logPath}`:"",s.error?.diagnosticId?`diagnostic: ${s.error.diagnosticId}`:""].filter(Boolean)))process.stdout.write(` ${u}
|
|
4
4
|
`);for(let e of u(t))process.stdout.write(` ${e}
|
|
5
|
-
`)}function u(r){var s,i,n;if("skipped"===r.status)return[];let o=(s=r).artifactsDir?e.join(s.artifactsDir,`attempt-${s.attempts}`,"replay-timing.ndjson"):void 0;if(!o)return[];let a=function(e){try{return t.readFileSync(e,"utf8").split(/\r?\n/).filter(t=>t.trim().length>0).flatMap(t=>{try{let e=JSON.parse(t);return c(e)?[e]:[]}catch{return[]}})}catch{return[]}}(o);if(0===a.length)return[];let u=new Map,m=[];for(let t of a){"replay_action_start"===(i=t).type&&l(i)&&f(i,"line")&&p(i,"command")&&(void 0===i.positionals||Array.isArray(i.positionals))&&u.set(t.step,t),"replay_action_stop"===(n=t).type&&l(n)&&f(n,"line")&&p(n,"command")&&(void 0===n.ok||"boolean"==typeof n.ok)&&f(n,"durationMs")&&p(n,"errorCode")&&(void 0===n.resultTiming||c(n.resultTiming))&&m.push(t)}return 0===m.length?[]:[
|
|
5
|
+
`)}function u(r){var s,i,n;if("skipped"===r.status)return[];let o=(s=r).artifactsDir?e.join(s.artifactsDir,`attempt-${s.attempts}`,"replay-timing.ndjson"):void 0;if(!o)return[];let a=function(e){try{return t.readFileSync(e,"utf8").split(/\r?\n/).filter(t=>t.trim().length>0).flatMap(t=>{try{let e=JSON.parse(t);return c(e)?[e]:[]}catch{return[]}})}catch{return[]}}(o);if(0===a.length)return[];let u=new Map,m=[];for(let t of a){"replay_action_start"===(i=t).type&&l(i)&&f(i,"line")&&p(i,"command")&&(void 0===i.positionals||Array.isArray(i.positionals))&&u.set(t.step,t),"replay_action_stop"===(n=t).type&&l(n)&&f(n,"line")&&p(n,"command")&&(void 0===n.ok||"boolean"==typeof n.ok)&&f(n,"durationMs")&&p(n,"errorCode")&&(void 0===n.resultTiming||c(n.resultTiming))&&m.push(t)}return 0===m.length?[]:[r.attempts>1?`steps (attempt ${r.attempts}):`:"steps:",...m.map(t=>{var e,r,s,i,n,o;let a,l,f;return e=t,r=u.get(t.step),a=!1===e.ok?"[FAIL] ":!0===e.ok?"":"[info] ",` ${a}${s=r,i=e,[function(t){if(!t)return"unknown";if(!t.startsWith("__maestro"))return t;let e=t.slice(9);return e.length>0?e[0].toLowerCase()+e.slice(1):t}(s?.command??i.command),...(s?.positionals??[]).map(d)].join(" ")}${n=e,o=r,(f=["number"==typeof(l=o?.line??n.line)?`line ${l}`:"","number"==typeof n.durationMs?A(n.durationMs):"",n.errorCode??"",n.resultTiming?`timing ${JSON.stringify(n.resultTiming)}`:""].filter(Boolean)).length>0?` (${f.join(", ")})`:""}`})]}function l(t){return"number"==typeof t.step}function f(t,e){return void 0===t[e]||"number"==typeof t[e]}function p(t,e){return void 0===t[e]||"string"==typeof t[e]}function d(t){return"string"==typeof t?JSON.stringify(t):"number"==typeof t||"boolean"==typeof t?String(t):JSON.stringify(t)}function c(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function m(t){return"passed"===t.status&&t.attempts>1}function $(t){let r=g(t);return r&&r.length>0?JSON.stringify(r):e.basename(t.file)}function g(t){let e=t.title?.trim();return e&&e.length>0?e:void 0}function h(t){if("passed"===t.status&&t.attempts>1)return y(t);if("failed"===t.status&&t.attempts>1&&t.durationMs>0)return` (total ${A(t.durationMs)})`;let e="passed"===t.status&&"number"==typeof t.finalAttemptDurationMs?t.finalAttemptDurationMs:t.durationMs;return e>0?` (${A(e)})`:""}function y(t){let e=["number"==typeof t.finalAttemptDurationMs?`passed attempt ${A(t.finalAttemptDurationMs)}`:"",t.durationMs>0?`total ${A(t.durationMs)}`:""].filter(Boolean);return e.length>0?` (${e.join(", ")})`:""}function M(t,e,r={}){r.includeMessage&&t.push(`errorMessage: ${e.message}`),e.hint&&t.push(`hint: ${e.hint}`),e.diagnosticId&&t.push(`diagnosticId: ${e.diagnosticId}`),e.logPath&&t.push(`logPath: ${e.logPath}`),!1!==r.includeDetails&&v(t,e,r.detailsIndent)}function v(t,e,r){let s=e.details?JSON.stringify(e.details,null,r):void 0;s&&t.push(`details: ${s}`)}function S(t,e){e&&t.push(e)}function w(t){return(Math.max(0,t)/1e3).toFixed(3)}function A(t){let e=Math.max(0,t)/1e3;return e>=10?`${e.toFixed(1)}s`:e>=1?`${e.toFixed(2)}s`:`${e.toFixed(3).replace(/0+$/,"").replace(/\.$/,"")}s`}function _(t){return t.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}async function D({command:l,positionals:f,flags:p,client:d}){var c,k,b,j,F;"test"===l&&(({json:p.json}).json||process.stderr.write("Running replay suite...\n"));let{result:C,cliOutput:N}=await s({client:d,command:l,positionals:f,flags:p});if(N){c=p,k=N,!c.json&&k.stderr&&process.stderr.write(k.stderr),n(c,c.json?k.jsonData??k.data:k.data,()=>k.text)}else{let s=(b=l,j=p,F=C,"test"===b?function(s){let{suite:n,json:o,verbose:l,reportJunit:f}=s;return(f&&function(s,i){let n=e.dirname(s);try{t.mkdirSync(n,{recursive:!0}),t.writeFileSync(s,function(t){let r=['<?xml version="1.0" encoding="UTF-8"?>',"<testsuites>",` <testsuite name="agent-device replay suite" tests="${t.total}" failures="${t.failed}" skipped="${t.skipped}" time="${w(t.durationMs)}">`];for(let s of t.tests)r.push(...function(t){let r=_(g(t)??e.basename(t.file)),s=_("."===e.dirname(t.file)?t.file:e.dirname(t.file)),i=_(t.file),n=w(t.durationMs),o=[` <testcase classname="${s}" name="${r}" file="${i}" time="${n}">`];"failed"===t.status?o.push(` <failure message="${_(t.error.message)}">${_(function(t){let e=[t.error.message];return M(e,t.error,{includeDetails:!1}),t.artifactsDir&&e.push(`artifactsDir: ${t.artifactsDir}`),v(e,t.error,2),e.join("\n")}(t))}</failure>`):"skipped"===t.status&&o.push(` <skipped message="${_(t.message)}" />`);let a=function(t){let e=[`status: ${t.status}`,`durationMs: ${t.durationMs}`];return function(t,e){var r,s;S(t,"attempts"in e?`attempts: ${e.attempts}`:void 0),S(t,"session"in e?`session: ${e.session}`:void 0),S(t,"replayed"in e?`replayed: ${e.replayed}`:void 0),S(t,"healed"in e?`healed: ${e.healed}`:void 0),S(t,"artifactsDir"in e&&e.artifactsDir?`artifactsDir: ${e.artifactsDir}`:void 0),"failed"===e.status&&(r=t,s=e,r.push(`errorCode: ${s.error.code}`),M(r,s.error,{includeMessage:!0})),S(t,m(e)?"flaky: true":void 0)}(e,t),e.join("\n")}(t);return a&&o.push(` <system-out>${_(a)}</system-out>`),o.push(" </testcase>"),o}(s));return r.push(" </testsuite>"),r.push("</testsuites>"),`${r.join("\n")}
|
|
6
6
|
`}(i),"utf8")}catch(e){let t=e instanceof Error?e.message:String(e);throw new r("COMMAND_FAILED",`Failed to write JUnit report to ${s}: ${t}`)}}(f,n),o)?(i({success:!0,data:n}),+(n.failed>0)):function(t,e={}){let r=t.tests.filter(m);if(e.verbose)for(let e of t.tests)!function(t){var e;if("failed"===t.status)return a(t);let r=h(t);for(let s of(process.stdout.write(`${"passed"===(e=t).status?"PASS":"skipped"===e.status?"SKIP":"INFO"} ${$(t)}${r}
|
|
7
7
|
`),"skipped"===t.status&&process.stdout.write(` ${t.message??"skipped"}
|
|
8
8
|
`),u(t)))process.stdout.write(` ${s}
|
|
9
|
-
`)}(e);else for(let e of t.
|
|
9
|
+
`)}(e);else for(let e of t.tests){var s;"failed"===(s=e).status?a(s):"passed"===s.status&&process.stdout.write(`PASS ${$(s)}${h(s)}
|
|
10
|
+
`)}let i="number"==typeof t.durationMs?t.durationMs:void 0,n=r.length>0?`, ${r.length} flaky`:"",o=void 0!==i?` in ${A(i)}`:"";return process.stdout.write(`Test summary: ${t.passed} passed, ${t.failed} failed${n}${o}
|
|
10
11
|
`),function(t){if(0!==t.length)for(let e of(process.stdout.write("Flaky tests:\n"),t))for(let t of(process.stdout.write(` PASS ${$(e)} after ${e.attempts} attempts${y(e)}
|
|
11
12
|
`),e.attemptFailures??[])){let e="number"==typeof t.durationMs?` (${A(t.durationMs)})`:"";process.stdout.write(` attempt ${t.attempt} failed${e}: ${t.message}
|
|
12
|
-
`)}}(r),+(t.failed>0)}(n,{verbose:l})}({suite:F,verbose:j.verbose,json:j.json,reportJunit:j.reportJunit}):(n(j,F,()=>o(F)),0));0!==s&&process.exit(s)}return!0}export{
|
|
13
|
+
`)}}(r),+(t.failed>0)}(n,{verbose:l})}({suite:F,verbose:j.verbose,json:j.json,reportJunit:j.reportJunit}):(n(j,F,()=>o(F)),0));0!==s&&process.exit(s)}return!0}export{D as runGenericClientBackedCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{emitDiagnostic as t}from"./7599.js";import{runAndroidAdb as e}from"./8806.js";import{getAndroidKeyboardState as n,isAndroidInputMethodOwnedNode as
|
|
1
|
+
import{emitDiagnostic as t}from"./7599.js";import{runAndroidAdb as e}from"./8806.js";import{getAndroidKeyboardState as n,isAndroidInputMethodOwnedNode as a}from"./8133.js";import{captureAndroidUiHierarchyXml as r}from"./2415.js";import{androidUiNodes as i}from"./221.js";import{AppError as o}from"./9152.js";import{buildScrollGesturePlan as u}from"./9533.js";import{resolveAndroidTextInjector as l}from"./9639.js";import{sleep as c}from"./4829.js";function s(t){var e;return!!t&&(!!t.password||!!(e=t.text)&&Array.from(e).every(f))}function d(t){if(!t)return null;let e=s(t);return{...t,text:e?null:t.text,...e?{textRedacted:!0}:{}}}function f(t){return"•"===t||"*"===t||"●"===t}async function p(t,e,n,a){let r=null,i=null,o=await y(t);for(let u of[0,150,350]){u>0&&await c(u);let l=await g(t,e,n,a,o);if(r=l,"ime_capture"===l.reason)return l;i=l.ok?l:null}return i??r??{ok:!1,actual:null,reason:"text_mismatch",targetInput:null,actualInput:null}}async function h(t,e,n){var a,i,o;return a=await r(t),i=e,o=n,m(a,i,o).actualInput?.text??null}async function g(t,e,n,a,i){return function(t,e,n,a,r={}){var i,o;let u,l=m(t,e,n,r);return!function(t){let{targetInput:e,actualInput:n}=t;return!!e&&!!n&&n!==e&&n.inputMethodOwned&&!e.inputMethodOwned}(l)?function(t,e){let n=t.actualInput;if(!n||!s(n))return null;let a=n.text??null,r=Array.from(a??"").length,i=Array.from(e).length,o=null!==a&&r>0&&i>0&&r===i;return{ok:o,actual:a,reason:o?void 0:"masked_unverified",masked:!0,targetInput:t.targetInput,actualInput:n}}(l,a)??(i=l,o=a,{ok:function(t,e){if(t===e)return!0;let n=w(t),a=w(e);return!!n&&!!a&&!!(n===a||function(t,e){if(t.length!==e.length||0===t.length||t.slice(1)!==e.slice(1))return!1;let n=t[0],a=e[0];return!!n&&!!a&&a.toLowerCase()===a&&n===a.toUpperCase()}(n,a))}(u=i.actualInput?.text??null,o),actual:u,reason:"text_mismatch",targetInput:i.targetInput,actualInput:i.actualInput}):{ok:!1,actual:l.actualInput?.text??null,reason:"ime_capture",targetInput:l.targetInput,actualInput:l.actualInput}}(await r(t),e,n,a,i)}function m(t,e,n,r={}){var o;let u,l={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let o of i(t)){let t=function(t,e){if(!t.rect)return null;let n=t.text??"",r=Math.max(1,t.rect.width*t.rect.height);return{text:n||null,className:t.className,resourceId:t.resourceId,packageName:t.packageName,rect:t.rect,focused:t.focused??!1,password:!0===t.password,inputMethodOwned:a({packageName:t.packageName,resourceId:t.resourceId,activeInputMethodPackage:e.activeInputMethodPackage}),area:r,editText:function(t){let e=t.toLowerCase();return e.includes("edittext")||e.includes("textfield")}(t.className??"")}}(o,r);t&&function(t,e,n,a){var r,i,o;let u=(r=e.rect,i=n,o=a,i>=r.x&&i<=r.x+r.width&&o>=r.y&&o<=r.y+r.height);if(u&&e.editText&&(t.editAtPoint=_(t.editAtPoint,e)),e.focused&&e.editText){t.focusedEdit=_(t.focusedEdit,e);return}u&&e.text&&(t.anyAtPoint=_(t.anyAtPoint,e))}(l,t,e,n)}return{targetInput:u=(o=l).editAtPoint??o.anyAtPoint,actualInput:(o.focusedEdit?.text?o.focusedEdit:null)??u}}function w(t){return(t??"").replace(/\s+/g," ").trim()}async function y(e){try{return{activeInputMethodPackage:(await n(e)).inputMethodPackage}}catch(e){return t({level:"warn",phase:"android_fill_verification_input_method_probe_failed",data:{error:e instanceof Error?e.message:String(e)}}),{}}}function _(t,e){return t&&t.area<e.area?t:e}async function A(t,n,a){await e(t,["shell","input","tap",String(n),String(a)])}async function x(t,n,a,r,i,o=250){await e(t,["shell","input","swipe",String(n),String(a),String(r),String(i),String(o)])}async function I(t){await e(t,["shell","input","keyevent","4"])}async function S(t){await e(t,["shell","input","keyevent","3"])}async function M(t){await e(t,["shell","input","keyevent","ENTER"])}async function k(t,n){let a=function(t){switch(t){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new o("INVALID_ARGS",`Unsupported Android rotation: ${t}`)}}(n);await e(t,["shell","settings","put","system","accelerometer_rotation","0"]),await e(t,["shell","settings","put","system","user_rotation",a])}async function E(t){await e(t,["shell","input","keyevent","187"])}async function v(t,n,a,r=800){await e(t,["shell","input","swipe",String(n),String(a),String(n),String(a),String(r)])}async function C(t,e,n=0){let a=l(t);if(a){await a({action:"type",text:e,delayMs:n}),T("type","provider-native",e);return}(z(e),await D(t,"type"),n>0&&Array.from(e).length>1)?await L(t,{action:"type",text:e,chunkSize:1,delayMs:n}):await L(t,{action:"type",text:e,chunkSize:O,delayMs:0})}async function P(t,e,n){await A(t,e,n)}async function N(t,e,n,a,r=0){let i=l(t);if(i){await i({action:"fill",target:{x:e,y:n},text:a,delayMs:r}),T("fill","provider-native",a);let o=await p(t,e,n,a);if(o.ok)return;b(a,o)}z(a);let o=Array.from(a).length,u=null;for(let i of[{clearPadding:12,minClear:8,maxClear:48,chunkSize:r>0?1:O,inputDelayMs:r},{clearPadding:24,minClear:16,maxClear:96,chunkSize:r>0?1:4,inputDelayMs:r>0?r:15}]){var c,s;await P(t,e,n),await D(t,"fill");let r=(c=o+i.clearPadding,s=i.minClear,Math.max(s,Math.min(i.maxClear,c)));await F(t,r),await L(t,{action:"fill",text:a,chunkSize:i.chunkSize,delayMs:i.inputDelayMs});let l=await p(t,e,n,a);if(u=l,l.ok)return;"ime_capture"===l.reason&&b(a,l)}b(a,u)}function b(t,e){let n;throw new o("COMMAND_FAILED",e?.reason==="ime_capture"?"Android fill input was captured by the active keyboard instead of the app field":e?.reason==="masked_unverified"?"Android fill verification could not confirm masked text value":"Android fill verification failed",(n=function(t,e){var n;if(!e)return{expected:t,actual:null,failureReason:"text_mismatch",targetInput:null,actualInput:null};let a=!0===(n=e).masked||s(n.targetInput)||s(n.actualInput),r={failureReason:e.reason??"text_mismatch",targetInput:d(e.targetInput),actualInput:d(e.actualInput)};return a?{...r,expectedLength:Array.from(t).length,actual:null,masked:!0,actualLength:Array.from(e.actual??"").length}:{...r,expected:t,actual:e.actual}}(t,e),e?.reason==="ime_capture"&&(n.hint="The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill."),n))}async function K(t,n,a){let r=await R(t),i=u({direction:n,amount:a?.amount,pixels:a?.pixels,referenceWidth:r.width,referenceHeight:r.height});return await e(t,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"]),i}async function D(e,a){let r;try{r=await n(e)}catch(e){t({level:"warn",phase:"android_input_ownership_probe_failed",data:{action:a,error:e instanceof Error?e.message:String(e)}});return}if("ime"===r.inputOwner)throw new o("COMMAND_FAILED","KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.",{failureReason:"ime_capture",action:a,inputOwner:r.inputOwner,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,nextAction:"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry."})}async function R(t){let n=(await e(t,["shell","wm","size"])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new o("COMMAND_FAILED","Unable to read screen size");return{width:Number(n[1]),height:Number(n[2])}}let O=8;async function L(t,n){let a=n.text.split("\n");for(let[r,i]of a.entries()){let o=function(t,e){let n=Math.max(1,Math.floor(e)),a=[],r=Array.from(t);for(let t=0;t<r.length;t+=n)a.push(r.slice(t,t+n).join(""));return a.length>0?a:[""]}(i,n.chunkSize);for(let[e,i]of o.entries())await U(t,i),n.delayMs>0&&(e+1<o.length||r+1<a.length)&&await c(n.delayMs);r+1<a.length&&await e(t,["shell","input","keyevent","ENTER"])}T(n.action,"adb-shell",n.text)}async function U(t,n){if(n)try{await e(t,["shell","input","text",n.replace(/ /g,"%s")])}catch(t){if(function(t){if(!(t instanceof o)||"COMMAND_FAILED"!==t.code)return!1;let e=t.details?.stderr,n=("string"==typeof e?e:"").toLowerCase();return!!(n.includes("exception occurred while executing 'text'")||n.includes("nullpointerexception")&&n.includes("inputshellcommand.sendtext"))}(t))throw H(n,t);throw t}}function z(t){if(!function(t){for(let e of t){let t=e.codePointAt(0);if(void 0!==t&&"\n"!==e&&(t<32||t>126))return!1}return!0}(t))throw H(t)}function H(t,e){return new o("COMMAND_FAILED","Android text input requires provider-native text injection for non-ASCII/control characters; the current adb-shell fallback supports ASCII text only.",{backend:"adb-shell",textLength:Array.from(t).length,textPreview:t.slice(0,32)},e instanceof Error?e:void 0)}function T(e,n,a){t({phase:"android_text_injection",data:{action:e,backend:n,textLength:Array.from(a).length}})}async function F(t,n){let a=Math.max(0,n);await e(t,["shell","input","keyevent","KEYCODE_MOVE_END"],{allowFailure:!0});for(let n=0;n<a;n+=24){let r=Math.min(24,a-n);await e(t,["shell","input","keyevent",...Array(r).fill("KEYCODE_DEL")],{allowFailure:!0})}}export{E as appSwitcherAndroid,I as backAndroid,N as fillAndroid,P as focusAndroid,R as getAndroidScreenSize,S as homeAndroid,v as longPressAndroid,A as pressAndroid,M as pressAndroidEnter,h as readAndroidTextAtPoint,k as rotateAndroid,K as scrollAndroid,x as swipeAndroid,C as typeAndroid};
|
package/dist/src/session.js
CHANGED
|
@@ -21,9 +21,9 @@ fetch(input.url, {
|
|
|
21
21
|
console.error(error && error.stack ? error.stack : String(error));
|
|
22
22
|
process.exit(1);
|
|
23
23
|
});
|
|
24
|
-
`;function at(e){if("string"!=typeof e)throw new d("COMMAND_FAILED",`Maestro runScript json() expected a string body, received ${typeof e}.`);if(0===e.trim().length)throw new d("COMMAND_FAILED","Maestro runScript json() received an empty body. Check the preceding http response status and setup server output.");try{return JSON.parse(e,ar)}catch(t){throw new d("COMMAND_FAILED",`Maestro runScript json() could not parse response body: ${t instanceof Error?t.message:String(t)}`,{bodyPreview:e.slice(0,1e3)},t instanceof Error?t:void 0)}}function ar(e,t){return"__proto__"===e||"constructor"===e||"prototype"===e?void 0:t}let an={launchApp:({value:e,config:t,context:r})=>[nP(e,t,r)],tapOn:({value:e,context:t})=>[function(e,t){if("string"==typeof e)return nS(nz,[n1(nO(e,t))],n6(e));if(n_(e)&&"string"==typeof e.point){nI(e,"tapOn",["point","repeat","delay","optional","label"]);let t=nU(e.point);return"percent"===t.kind?nS(nJ,[String(t.x),String(t.y)],n5(e)):nS("click",[String(t.x),String(t.y)],n5(e))}n_(e)&&nI(e,"tapOn",["id","text","childOf","enabled","index","selected","repeat","delay","optional","label"]);let r=n6(e);return nS(nz,[n0(e,"tapOn",["repeat","delay","optional","label","index","childOf"],t),...function(e,t){if(!n_(e))return[];let r={};if(void 0!==e.index){if("number"!=typeof e.index||!Number.isInteger(e.index)||e.index<0)throw new d("INVALID_ARGS","tapOn.index must be a non-negative integer.");r.index=e.index}return void 0!==e.childOf&&(r.childOf=n0(e.childOf,"tapOn.childOf",[],t)),Object.keys(r).length>0?[JSON.stringify(r)]:[]}(e,t)],r)}(e,t)],doubleTapOn:({value:e,context:t})=>[function(e,t){if(n_(e)&&"string"==typeof e.point){nI(e,"doubleTapOn",["point","delay"]);let t=nV(e.point);return nS("click",[String(t.x),String(t.y)],n8(e))}return n_(e)&&nI(e,"doubleTapOn",["id","text","enabled","selected","delay"]),nS("click",[n0(e,"doubleTapOn",["delay"],t)],n8(e))}(e,t)],longPressOn:({value:e,context:t})=>[function(e,t){if(n_(e)&&"string"==typeof e.point){nI(e,"longPressOn",["point"]);let t=nV(e.point);return nS("longpress",[String(t.x),String(t.y),"3000"])}return n_(e)&&nI(e,"longPressOn",["id","text","enabled","selected"]),nS("click",[n0(e,"longPressOn",[],t)],{holdMs:3e3})}(e,t)],inputText:({value:e,context:t})=>[nS("type",[nO(function(e){if("string"==typeof e)return e;if(!n_(e))throw new d("INVALID_ARGS","inputText expects a string or map.");if(nI(e,"inputText",["text","label"]),"string"!=typeof e.text)throw new d("INVALID_ARGS","inputText map requires a string text field.");return e.text}(e),t)])],eraseText:({value:e})=>[nX(e)],pasteText:({value:e,context:t,name:r})=>[nS("type",[nO(nk(r,e),t)])],openLink:({value:e,config:t,context:r,name:n})=>{var a,i,o,s,l,u;let c;return[(a=e,i=t,o=r,s=n,c=nO((l=a,u=s,"string"==typeof l?l:n_(l)?(nI(l,u,["link"]),nk(`${u}.link`,l.link)):nk(u,l)),o),("ios"===o.platform||"android"===o.platform)&&i.appId?nS("open",[nO(nD(i,s),o),c],"ios"===o.platform?{maestro:{prewarmRunnerBeforeOpen:!0}}:void 0):nS("open",[c]))]},assertVisible:({value:e,context:t,name:r})=>[nS(nG,[n0(e,r,[],t),"5000"])],assertNotVisible:({value:e,context:t,name:r})=>[nS(nj,[n0(e,r,[],t)])],extendedWaitUntil:({value:e,context:t})=>(function(e,t){if(!n_(e))throw new d("INVALID_ARGS","extendedWaitUntil expects a map.");nI(e,"extendedWaitUntil",["visible","notVisible","timeout"]);let r=e.visible??e.notVisible;if(void 0===r)throw nL("Only Maestro extendedWaitUntil.visible/notVisible is supported.");let n=n0(r,"extendedWaitUntil",[],t),a=String(nx(e,3e4));return void 0!==e.notVisible?[nS(nj,[n,a])]:[nS(nG,[n,a],{maestro:{allowAlreadyPastLoading:!0}})]})(e,t),takeScreenshot:({value:e,context:t,name:r})=>[nS("screenshot",[nO(nk(r,e),t)])],scroll:({value:e})=>[function(e){if(null!=e)throw nL("Maestro scroll options are not supported yet.");return nS("scroll",["down"])}(e)],scrollUntilVisible:({value:e,context:t})=>(function(e,t){if("string"==typeof e)return[nS(nB,[n1(nO(e,t)),"5000","down"])];if(!n_(e))throw new d("INVALID_ARGS","scrollUntilVisible expects a string or map.");nI(e,"scrollUntilVisible",["element","direction","timeout"]);let r=n0(e.element,"scrollUntilVisible.element",[],t),n="string"==typeof e.direction?nZ(e.direction,"scrollUntilVisible.direction"):"down";return[nS(nB,[r,String(nx(e,5e3)),n])]})(e,t),swipe:({value:e,context:t})=>[function(e,t){var r,n,a;let i;if(!n_(e))throw new d("INVALID_ARGS","swipe expects a map.");nI(e,"swipe",["start","end","direction","duration","from","label"]);let o=e.from??("string"==typeof e.label?e.label:void 0);return void 0!==o?(r=e,n=o,a=t,i=nQ("string"==typeof r.direction?r.direction:"up"),nS(nW,[n0(n,"swipe.from",[],a),i,...n2(r)])):"string"==typeof e.direction?nS(nH,["direction",nQ(e.direction),...n2(e)]):function(e){let{start:t,end:r}=function(e){if("string"==typeof e.start&&"string"==typeof e.end)return{start:nU(e.start),end:nU(e.end)};throw nL("Only Maestro swipe start/end coordinates are supported.")}(e);var n=t,a=r,i=nY(e.duration);if("absolute"===n.kind&&"absolute"===a.kind)return nS("swipe",[String(n.x),String(n.y),String(a.x),String(a.y),...i?[i]:[]]);if("percent"===n.kind&&"percent"===a.kind)return nS(nH,["percent",String(n.x),String(n.y),String(a.x),String(a.y),...i?[i]:[]]);throw nL("Maestro swipe start/end must both be absolute pixels or both be percentages.")}(e)}(e,t)],hideKeyboard:()=>[nS("keyboard",["dismiss"])],pressKey:({value:e})=>[function(e){let t=nk("pressKey",e).toLowerCase();if("back"===t)return nS("back");if("enter"===t||"return"===t)return nS(nq);if("home"===t)return nS("home");throw nL(`Maestro pressKey "${t}" is not supported yet.`)}(e)],back:()=>[nS("back")],waitForAnimationToEnd:({value:e})=>[nS(nK,[String(nx(e,15e3))])],stopApp:({value:e,config:t,context:r})=>[n$(e,t,r)],runScript:({value:e,context:t})=>{let r;return[nS(nT,[function(e,t){if(a.isAbsolute(e))return e;if(!t.baseDir)throw new d("INVALID_ARGS","runScript file paths require replay input to have a source path.");return a.resolve(t.baseDir,e)}((r=function(e,t){if("string"==typeof e)return{file:nO(e,t),env:{}};if(!n_(e))throw new d("INVALID_ARGS","runScript expects a file path string or map.");return nI(e,"runScript",["file","env"]),{file:nO(nk("runScript.file",e.file),t),env:Object.fromEntries(Object.entries(nM(e.env,"runScript.env")).map(([e,r])=>[e,nO(r,t)]))}}(e,t)).file,t)],{...Object.keys(r.env).length>0?{maestro:{runScriptEnv:r.env}}:{}})]},runFlow:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){if("string"==typeof e)return n.parseRunFlowFile(nO(e,r),r).actions;if(!n_(e))throw new d("INVALID_ARGS","runFlow expects a file path string or map.");nI(e,"runFlow",["file","commands","env","when","label"]);let i=function(e,t){var r,n;if(null==e)return{shouldRun:!0};if(!n_(e))throw new d("INVALID_ARGS","runFlow.when expects a map.");return(nI(e,"runFlow.when",["platform","visible","notVisible","true"]),!function(e,t){if(void 0!==e.true&&!function(e,t){let r;if("boolean"==typeof e)return e;if("string"!=typeof e)throw new d("INVALID_ARGS","runFlow.when.true expects a boolean or expression string.");return new n9(function(e){let t=[],r=0;for(;r<e.length;){var n,a;let i=e.slice(r),o=(n=i,/^\s+/.exec(n)?.[0].length??0);if(o>0){r+=o;continue}let s=function(e){let t="maestro.platform";return e.startsWith(t)?{token:{type:"platform"},length:t.length}:null}(a=i)??function(e){let t=/^(==|!=|&&|\|\|)/.exec(e)?.[1];return t?{token:{type:"operator",value:t},length:t.length}:null}(a)??function(e){let t=e[0];return"("===t||")"===t?{token:{type:"paren",value:t},length:1}:null}(a)??function(e){let t=/^(['"])(.*?)\1/.exec(e);return t?{token:{type:"string",value:t[2]??""},length:t[0].length}:null}(a)??function(e){let t=/^(true|false)\b/.exec(e)?.[1];return t?{token:{type:"boolean",value:"true"===t},length:t.length}:null}(a);if(s){t.push(s.token),r+=s.length;continue}throw new d("INVALID_ARGS",`Unsupported runFlow.when.true expression near "${i.slice(0,24)}".`)}return t}((r=nO(e,t).trim()).startsWith("${")&&r.endsWith("}")?r.slice(2,-1).trim():r),{platform:t.platform}).parse()}(e.true,t))return!1;if(void 0===e.platform)return!0;let r=function(e,t){if("string"!=typeof e)throw new d("INVALID_ARGS",`${t} expects Android, iOS, or Web.`);let r=e.trim().toLowerCase();if("android"===r||"ios"===r||"web"===r)return r;throw new d("INVALID_ARGS",`${t} expects Android, iOS, or Web.`)}(e.platform,"runFlow.when.platform");if(!t.platform)throw new d("INVALID_ARGS","Maestro runFlow.when.platform requires replay to be run with --platform ios|android.");return r===t.platform}(e,t))?{shouldRun:!1}:{shouldRun:!0,...(r=e,n=t,{...void 0!==r.visible?{visibleSelector:n0(r.visible,"runFlow.when.visible",[],n)}:{},...void 0!==r.notVisible?{notVisibleSelector:n0(r.notVisible,"runFlow.when.notVisible",[],n)}:{}})}}(e.when,r);if(!i.shouldRun)return[];let o={...r,env:{...r.env,...nM(e.env,"runFlow.env"),...r.envOverrides}};return function(e,t){let{visibleSelector:r,notVisibleSelector:n}=t;if(!r&&!n)return e;if(r&&n)throw nL("Maestro runFlow.when cannot combine visible and notVisible yet.");let a=r?"visible":"notVisible",i=r??n??"";return[n4("runFlow.when",[a,i],{kind:"maestroRunFlowWhen",mode:a,selector:i,actions:e})]}(function(e,t,r,n,a){if("string"==typeof e.file)return n.parseRunFlowFile(nO(e.file,r),r).actions;if(Array.isArray(e.commands))return a(nN(e.commands),t,r,n);throw new d("INVALID_ARGS","runFlow map requires either file or commands.")}(e,t,o,n,a),i)})(e,t,r,n,ao),repeat:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){var i;if(!n_(e))throw new d("INVALID_ARGS","repeat expects a map.");if(nI(e,"repeat",["times","commands","while"]),void 0!==e.while)throw nL("Maestro repeat.while is not supported yet. Only deterministic repeat.times is supported.");let o=(i=e.times,n7(i,r,"repeat.times"));if(!Array.isArray(e.commands))throw new d("INVALID_ARGS","repeat requires a commands list.");if(o>1e3)throw new d("INVALID_ARGS","repeat.times must be <= 1000 for deterministic replay expansion.");let s=nN(e.commands);return Array.from({length:o}).flatMap(()=>a(s,t,r,n))})(e,t,r,n,ao),retry:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){var i,o;if(!n_(e))throw new d("INVALID_ARGS","retry expects a map.");if(nI(e,"retry",["maxRetries","commands"]),!Array.isArray(e.commands))throw new d("INVALID_ARGS","retry requires a commands list.");let s=(i=e.maxRetries,o=r,void 0===i?1:n7(i,o,"retry.maxRetries")),l=a(nN(e.commands),t,r,n);return[n4("retry",[String(s)],{kind:"retry",maxRetries:s,actions:l})]})(e,t,r,n,ao)},aa={launchApp:(e,t)=>[nP(void 0,e,t)],scroll:()=>[nS("scroll",["down"])],hideKeyboard:()=>[nS("keyboard",["dismiss"])],eraseText:()=>[nX(void 0)],back:()=>[nS("back")],waitForAnimationToEnd:()=>[nS(nK,["15000"])],stopApp:(e,t)=>[n$(void 0,e,t)]};function ai(e,t,r,n,a){try{return function(e,t,r,n){if("string"==typeof e){var a,i,o;let n;return a=e,i=t,o=r,(n=aa[a])?n(i,o):nR(a)}let s=Object.entries(e);if(1!==s.length)throw new d("INVALID_ARGS","Maestro command maps must contain exactly one command.");let[l,u]=s[0],c=an[l];return c?c({value:u,config:t,context:r,deps:n,name:l}):nR(l)}(e,t,n,a)}catch(e){if(e instanceof d&&!/\bline \d+\b/.test(e.message))throw new d(e.code,`${e.message} (line ${r})`,e.details);throw e}}function ao(e,t,r,n){return e.flatMap((e,a)=>ai(e,t,a+1,r,n))}function as(e,t){let{config:r,commands:n}=au(al(e)),a={...t,env:{...t.env,...r.env??{},...t.envOverrides}},{actions:i,actionLines:o}=function(e){let{config:t,commands:r,commandLines:n,context:a}=e,i=[...t.onFlowStart??[],...r,...t.onFlowComplete??[]],o=[...Array.from({length:t.onFlowStart?.length??0},()=>1),...n,...Array.from({length:t.onFlowComplete?.length??0},()=>n.at(-1)??1)],s=[],l=[];for(let[e,r]of i.entries()){let n=o[e]??e+1,i=ai(r,t,n,a,{parseRunFlowFile:ac});s.push(...i),i.forEach(()=>l.push(n))}return function(e,t){let r=[],n=[];for(let a=0;a<e.length;a+=1){let i=e[a],o=function(e,t,r){var n;let a=function(e,t,r){let n=e[r],a=e[r+1],i=e[r+2];if(i?.command!==nq||n.flags?.maestro?.optional===!0)return null;let o=function(e){if(e?.command!=="type"||e.flags&&Object.keys(e.flags).length>0)return null;let[t,...r]=e.positionals??[];return r.length>0||"string"!=typeof t?null:t}(a),s=function(e){if(e?.command!==nz)return null;let[t,...r]=e.positionals??[];return r.length>0||"string"!=typeof t?null:t}(n);return a&&null!==o&&null!==s?{action:n,nextAction:a,pressEnterAction:i,tapSelector:s,typedAfterTap:o,line:t[r]??1}:null}(e,t,r);if(!a)return null;let{action:i,nextAction:o,pressEnterAction:s,tapSelector:l,typedAfterTap:u,line:c}=a;return(n=l,/\b(input|textfield|textarea|field|email|password|username|search|query)\b/i.test(n.replace(/([a-z])([A-Z])/g,"$1 $2")))?{actions:[{...i,command:"wait",positionals:[l,"30000"]},{...o,command:"fill",positionals:[l,u],flags:i.flags},s],actionLines:[c,c,t[r+2]??c],consumed:3}:{actions:[function(e){let t={...e.flags?.maestro??{}};return delete t.allowNonHittableCoordinateFallback,{...e,flags:{...e.flags??{},maestro:{...t}}}}(i)],actionLines:[c],consumed:1}}(e,t,a);if(o){r.push(...o.actions),n.push(...o.actionLines),a+=o.consumed-1;continue}r.push(i),n.push(t[a]??1)}return{actions:r,actionLines:n}}(s,l)}({config:r,commands:n,commandLines:function(e){let t=e.split(/\r?\n/),r=t.findIndex(e=>"---"===e.trim()),n=-1===r?0:r+1,a=[];for(let e=n;e<t.length;e+=1)/^-\s+/.test(t[e]??"")&&a.push(e+1);return a}(e),context:a});return{actions:i,actionLines:o,metadata:{env:r.env}}}function al(e){let t=o(e);for(let e of t)if(e.errors.length>0){let t=e.errors[0]?.message??"Invalid Maestro YAML flow.";throw new d("INVALID_ARGS",`Invalid Maestro YAML flow: ${t}`)}return t.map(e=>e.toJSON()).filter(e=>null!==e)}function au(e){if(0===e.length)throw new d("INVALID_ARGS","Maestro flow is empty.");if(Array.isArray(e[0]))return{config:{},commands:nN(e[0])};let t=function(e){if(!n_(e))throw new d("INVALID_ARGS","Maestro flow config must be a YAML map.");return{..."string"==typeof e.name&&e.name.length>0?{name:e.name}:{},..."string"==typeof e.appId&&e.appId.length>0?{appId:e.appId}:{},...n_(e.env)?{env:nM(e.env,"env")}:{},...Array.isArray(e.onFlowStart)?{onFlowStart:nN(e.onFlowStart)}:{},...Array.isArray(e.onFlowComplete)?{onFlowComplete:nN(e.onFlowComplete)}:{}}}(e[0]),r=e[1];if(!Array.isArray(r))throw new d("INVALID_ARGS","Maestro flow must contain a command list after the YAML document separator.");return{config:t,commands:nN(r)}}function ac(e,r){let n=function(e,t){if(a.isAbsolute(e))return e;if(!t.baseDir)throw new d("INVALID_ARGS","runFlow file paths require replay input to have a source path.");return a.resolve(t.baseDir,e)}(e,r);if(r.visitedPaths.has(n))throw new d("INVALID_ARGS",`Maestro runFlow cycle detected at ${n}.`);let i=t.readFileSync(n,"utf8"),o=new Set(r.visitedPaths);return o.add(n),as(i,{...r,baseDir:a.dirname(n),visitedPaths:o})}let ad=/[*?[\]{}]/;function ap(e){return"maestro"===e}let af=["failed to start daemon","runner did not accept connection","xcodebuild exited early","device is offline","device offline","device unauthorized"];function am(e){var t,r,n,a;let i,o,s="ok"in(t=e)?t.ok?null:t.error:"failed"===t.status?t.error:null;return!!s&&(r=s.details,"timeout_cleanup_pending"===(i="string"==typeof r?.reason?r.reason:"")||!!i&&eT(i)||(n=s.code,a=s.message,o=`${n}
|
|
24
|
+
`;function at(e){if("string"!=typeof e)throw new d("COMMAND_FAILED",`Maestro runScript json() expected a string body, received ${typeof e}.`);if(0===e.trim().length)throw new d("COMMAND_FAILED","Maestro runScript json() received an empty body. Check the preceding http response status and setup server output.");try{return JSON.parse(e,ar)}catch(t){throw new d("COMMAND_FAILED",`Maestro runScript json() could not parse response body: ${t instanceof Error?t.message:String(t)}`,{bodyPreview:e.slice(0,1e3)},t instanceof Error?t:void 0)}}function ar(e,t){return"__proto__"===e||"constructor"===e||"prototype"===e?void 0:t}let an={launchApp:({value:e,config:t,context:r})=>[nP(e,t,r)],tapOn:({value:e,context:t})=>[function(e,t){if("string"==typeof e)return nS(nz,[n1(nO(e,t))],n6(e));if(n_(e)&&"string"==typeof e.point){nI(e,"tapOn",["point","repeat","delay","optional","label"]);let t=nU(e.point);return"percent"===t.kind?nS(nJ,[String(t.x),String(t.y)],n5(e)):nS("click",[String(t.x),String(t.y)],n5(e))}n_(e)&&nI(e,"tapOn",["id","text","childOf","enabled","index","selected","repeat","delay","optional","label"]);let r=n6(e);return nS(nz,[n0(e,"tapOn",["repeat","delay","optional","label","index","childOf"],t),...function(e,t){if(!n_(e))return[];let r={};if(void 0!==e.index){if("number"!=typeof e.index||!Number.isInteger(e.index)||e.index<0)throw new d("INVALID_ARGS","tapOn.index must be a non-negative integer.");r.index=e.index}return void 0!==e.childOf&&(r.childOf=n0(e.childOf,"tapOn.childOf",[],t)),Object.keys(r).length>0?[JSON.stringify(r)]:[]}(e,t)],r)}(e,t)],doubleTapOn:({value:e,context:t})=>[function(e,t){if(n_(e)&&"string"==typeof e.point){nI(e,"doubleTapOn",["point","delay"]);let t=nV(e.point);return nS("click",[String(t.x),String(t.y)],n8(e))}return n_(e)&&nI(e,"doubleTapOn",["id","text","enabled","selected","delay"]),nS("click",[n0(e,"doubleTapOn",["delay"],t)],n8(e))}(e,t)],longPressOn:({value:e,context:t})=>[function(e,t){if(n_(e)&&"string"==typeof e.point){nI(e,"longPressOn",["point"]);let t=nV(e.point);return nS("longpress",[String(t.x),String(t.y),"3000"])}return n_(e)&&nI(e,"longPressOn",["id","text","enabled","selected"]),nS("click",[n0(e,"longPressOn",[],t)],{holdMs:3e3})}(e,t)],inputText:({value:e,context:t})=>[nS("type",[nO(function(e){if("string"==typeof e)return e;if(!n_(e))throw new d("INVALID_ARGS","inputText expects a string or map.");if(nI(e,"inputText",["text","label"]),"string"!=typeof e.text)throw new d("INVALID_ARGS","inputText map requires a string text field.");return e.text}(e),t)])],eraseText:({value:e})=>[nX(e)],pasteText:({value:e,context:t,name:r})=>[nS("type",[nO(nk(r,e),t)])],openLink:({value:e,config:t,context:r,name:n})=>{var a,i,o,s,l,u;let c;return[(a=e,i=t,o=r,s=n,c=nO((l=a,u=s,"string"==typeof l?l:n_(l)?(nI(l,u,["link"]),nk(`${u}.link`,l.link)):nk(u,l)),o),("ios"===o.platform||"android"===o.platform)&&i.appId?nS("open",[nO(nD(i,s),o),c],"ios"===o.platform?{maestro:{prewarmRunnerBeforeOpen:!0}}:void 0):nS("open",[c]))]},assertVisible:({value:e,context:t,name:r})=>[nS(nG,[n0(e,r,[],t),"7000"])],assertNotVisible:({value:e,context:t,name:r})=>[nS(nj,[n0(e,r,[],t)])],extendedWaitUntil:({value:e,context:t})=>(function(e,t){if(!n_(e))throw new d("INVALID_ARGS","extendedWaitUntil expects a map.");nI(e,"extendedWaitUntil",["visible","notVisible","timeout"]);let r=e.visible??e.notVisible;if(void 0===r)throw nL("Only Maestro extendedWaitUntil.visible/notVisible is supported.");let n=n0(r,"extendedWaitUntil",[],t),a=String(nx(e,3e4));return void 0!==e.notVisible?[nS(nj,[n,a])]:[nS(nG,[n,a],{maestro:{allowAlreadyPastLoading:!0}})]})(e,t),takeScreenshot:({value:e,context:t,name:r})=>[nS("screenshot",[nO(nk(r,e),t)])],scroll:({value:e})=>[function(e){if(null!=e)throw nL("Maestro scroll options are not supported yet.");return nS("scroll",["down"])}(e)],scrollUntilVisible:({value:e,context:t})=>(function(e,t){if("string"==typeof e)return[nS(nB,[n1(nO(e,t)),"5000","down"])];if(!n_(e))throw new d("INVALID_ARGS","scrollUntilVisible expects a string or map.");nI(e,"scrollUntilVisible",["element","direction","timeout"]);let r=n0(e.element,"scrollUntilVisible.element",[],t),n="string"==typeof e.direction?nZ(e.direction,"scrollUntilVisible.direction"):"down";return[nS(nB,[r,String(nx(e,5e3)),n])]})(e,t),swipe:({value:e,context:t})=>[function(e,t){var r,n,a;let i;if(!n_(e))throw new d("INVALID_ARGS","swipe expects a map.");nI(e,"swipe",["start","end","direction","duration","from","label"]);let o=e.from??("string"==typeof e.label?e.label:void 0);return void 0!==o?(r=e,n=o,a=t,i=nQ("string"==typeof r.direction?r.direction:"up"),nS(nW,[n0(n,"swipe.from",[],a),i,...n2(r)])):"string"==typeof e.direction?nS(nH,["direction",nQ(e.direction),...n2(e)]):function(e){let{start:t,end:r}=function(e){if("string"==typeof e.start&&"string"==typeof e.end)return{start:nU(e.start),end:nU(e.end)};throw nL("Only Maestro swipe start/end coordinates are supported.")}(e);var n=t,a=r,i=nY(e.duration);if("absolute"===n.kind&&"absolute"===a.kind)return nS("swipe",[String(n.x),String(n.y),String(a.x),String(a.y),...i?[i]:[]]);if("percent"===n.kind&&"percent"===a.kind)return nS(nH,["percent",String(n.x),String(n.y),String(a.x),String(a.y),...i?[i]:[]]);throw nL("Maestro swipe start/end must both be absolute pixels or both be percentages.")}(e)}(e,t)],hideKeyboard:()=>[nS("keyboard",["dismiss"])],pressKey:({value:e})=>[function(e){let t=nk("pressKey",e).toLowerCase();if("back"===t)return nS("back");if("enter"===t||"return"===t)return nS(nq);if("home"===t)return nS("home");throw nL(`Maestro pressKey "${t}" is not supported yet.`)}(e)],back:()=>[nS("back")],waitForAnimationToEnd:({value:e})=>[nS(nK,[String(nx(e,15e3))])],stopApp:({value:e,config:t,context:r})=>[n$(e,t,r)],runScript:({value:e,context:t})=>{let r;return[nS(nT,[function(e,t){if(a.isAbsolute(e))return e;if(!t.baseDir)throw new d("INVALID_ARGS","runScript file paths require replay input to have a source path.");return a.resolve(t.baseDir,e)}((r=function(e,t){if("string"==typeof e)return{file:nO(e,t),env:{}};if(!n_(e))throw new d("INVALID_ARGS","runScript expects a file path string or map.");return nI(e,"runScript",["file","env"]),{file:nO(nk("runScript.file",e.file),t),env:Object.fromEntries(Object.entries(nM(e.env,"runScript.env")).map(([e,r])=>[e,nO(r,t)]))}}(e,t)).file,t)],{...Object.keys(r.env).length>0?{maestro:{runScriptEnv:r.env}}:{}})]},runFlow:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){if("string"==typeof e)return n.parseRunFlowFile(nO(e,r),r).actions;if(!n_(e))throw new d("INVALID_ARGS","runFlow expects a file path string or map.");nI(e,"runFlow",["file","commands","env","when","label"]);let i=function(e,t){var r,n;if(null==e)return{shouldRun:!0};if(!n_(e))throw new d("INVALID_ARGS","runFlow.when expects a map.");return(nI(e,"runFlow.when",["platform","visible","notVisible","true"]),!function(e,t){if(void 0!==e.true&&!function(e,t){let r;if("boolean"==typeof e)return e;if("string"!=typeof e)throw new d("INVALID_ARGS","runFlow.when.true expects a boolean or expression string.");return new n9(function(e){let t=[],r=0;for(;r<e.length;){var n,a;let i=e.slice(r),o=(n=i,/^\s+/.exec(n)?.[0].length??0);if(o>0){r+=o;continue}let s=function(e){let t="maestro.platform";return e.startsWith(t)?{token:{type:"platform"},length:t.length}:null}(a=i)??function(e){let t=/^(==|!=|&&|\|\|)/.exec(e)?.[1];return t?{token:{type:"operator",value:t},length:t.length}:null}(a)??function(e){let t=e[0];return"("===t||")"===t?{token:{type:"paren",value:t},length:1}:null}(a)??function(e){let t=/^(['"])(.*?)\1/.exec(e);return t?{token:{type:"string",value:t[2]??""},length:t[0].length}:null}(a)??function(e){let t=/^(true|false)\b/.exec(e)?.[1];return t?{token:{type:"boolean",value:"true"===t},length:t.length}:null}(a);if(s){t.push(s.token),r+=s.length;continue}throw new d("INVALID_ARGS",`Unsupported runFlow.when.true expression near "${i.slice(0,24)}".`)}return t}((r=nO(e,t).trim()).startsWith("${")&&r.endsWith("}")?r.slice(2,-1).trim():r),{platform:t.platform}).parse()}(e.true,t))return!1;if(void 0===e.platform)return!0;let r=function(e,t){if("string"!=typeof e)throw new d("INVALID_ARGS",`${t} expects Android, iOS, or Web.`);let r=e.trim().toLowerCase();if("android"===r||"ios"===r||"web"===r)return r;throw new d("INVALID_ARGS",`${t} expects Android, iOS, or Web.`)}(e.platform,"runFlow.when.platform");if(!t.platform)throw new d("INVALID_ARGS","Maestro runFlow.when.platform requires replay to be run with --platform ios|android.");return r===t.platform}(e,t))?{shouldRun:!1}:{shouldRun:!0,...(r=e,n=t,{...void 0!==r.visible?{visibleSelector:n0(r.visible,"runFlow.when.visible",[],n)}:{},...void 0!==r.notVisible?{notVisibleSelector:n0(r.notVisible,"runFlow.when.notVisible",[],n)}:{}})}}(e.when,r);if(!i.shouldRun)return[];let o={...r,env:{...r.env,...nM(e.env,"runFlow.env"),...r.envOverrides}};return function(e,t){let{visibleSelector:r,notVisibleSelector:n}=t;if(!r&&!n)return e;if(r&&n)throw nL("Maestro runFlow.when cannot combine visible and notVisible yet.");let a=r?"visible":"notVisible",i=r??n??"";return[n4("runFlow.when",[a,i],{kind:"maestroRunFlowWhen",mode:a,selector:i,actions:e})]}(function(e,t,r,n,a){if("string"==typeof e.file)return n.parseRunFlowFile(nO(e.file,r),r).actions;if(Array.isArray(e.commands))return a(nN(e.commands),t,r,n);throw new d("INVALID_ARGS","runFlow map requires either file or commands.")}(e,t,o,n,a),i)})(e,t,r,n,ao),repeat:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){var i;if(!n_(e))throw new d("INVALID_ARGS","repeat expects a map.");if(nI(e,"repeat",["times","commands","while"]),void 0!==e.while)throw nL("Maestro repeat.while is not supported yet. Only deterministic repeat.times is supported.");let o=(i=e.times,n7(i,r,"repeat.times"));if(!Array.isArray(e.commands))throw new d("INVALID_ARGS","repeat requires a commands list.");if(o>1e3)throw new d("INVALID_ARGS","repeat.times must be <= 1000 for deterministic replay expansion.");let s=nN(e.commands);return Array.from({length:o}).flatMap(()=>a(s,t,r,n))})(e,t,r,n,ao),retry:({value:e,config:t,context:r,deps:n})=>(function(e,t,r,n,a){var i,o;if(!n_(e))throw new d("INVALID_ARGS","retry expects a map.");if(nI(e,"retry",["maxRetries","commands"]),!Array.isArray(e.commands))throw new d("INVALID_ARGS","retry requires a commands list.");let s=(i=e.maxRetries,o=r,void 0===i?1:n7(i,o,"retry.maxRetries")),l=a(nN(e.commands),t,r,n);return[n4("retry",[String(s)],{kind:"retry",maxRetries:s,actions:l})]})(e,t,r,n,ao)},aa={launchApp:(e,t)=>[nP(void 0,e,t)],scroll:()=>[nS("scroll",["down"])],hideKeyboard:()=>[nS("keyboard",["dismiss"])],eraseText:()=>[nX(void 0)],back:()=>[nS("back")],waitForAnimationToEnd:()=>[nS(nK,["15000"])],stopApp:(e,t)=>[n$(void 0,e,t)]};function ai(e,t,r,n,a){try{return function(e,t,r,n){if("string"==typeof e){var a,i,o;let n;return a=e,i=t,o=r,(n=aa[a])?n(i,o):nR(a)}let s=Object.entries(e);if(1!==s.length)throw new d("INVALID_ARGS","Maestro command maps must contain exactly one command.");let[l,u]=s[0],c=an[l];return c?c({value:u,config:t,context:r,deps:n,name:l}):nR(l)}(e,t,n,a)}catch(e){if(e instanceof d&&!/\bline \d+\b/.test(e.message))throw new d(e.code,`${e.message} (line ${r})`,e.details);throw e}}function ao(e,t,r,n){return e.flatMap((e,a)=>ai(e,t,a+1,r,n))}function as(e,t){let{config:r,commands:n}=au(al(e)),a={...t,env:{...t.env,...r.env??{},...t.envOverrides}},{actions:i,actionLines:o}=function(e){let{config:t,commands:r,commandLines:n,context:a}=e,i=[...t.onFlowStart??[],...r,...t.onFlowComplete??[]],o=[...Array.from({length:t.onFlowStart?.length??0},()=>1),...n,...Array.from({length:t.onFlowComplete?.length??0},()=>n.at(-1)??1)],s=[],l=[];for(let[e,r]of i.entries()){let n=o[e]??e+1,i=ai(r,t,n,a,{parseRunFlowFile:ac});s.push(...i),i.forEach(()=>l.push(n))}return function(e,t){let r=[],n=[];for(let a=0;a<e.length;a+=1){let i=e[a],o=function(e,t,r){var n;let a=function(e,t,r){let n=e[r],a=e[r+1],i=e[r+2];if(i?.command!==nq||n.flags?.maestro?.optional===!0)return null;let o=function(e){if(e?.command!=="type"||e.flags&&Object.keys(e.flags).length>0)return null;let[t,...r]=e.positionals??[];return r.length>0||"string"!=typeof t?null:t}(a),s=function(e){if(e?.command!==nz)return null;let[t,...r]=e.positionals??[];return r.length>0||"string"!=typeof t?null:t}(n);return a&&null!==o&&null!==s?{action:n,nextAction:a,pressEnterAction:i,tapSelector:s,typedAfterTap:o,line:t[r]??1}:null}(e,t,r);if(!a)return null;let{action:i,nextAction:o,pressEnterAction:s,tapSelector:l,typedAfterTap:u,line:c}=a;return(n=l,/\b(input|textfield|textarea|field|email|password|username|search|query)\b/i.test(n.replace(/([a-z])([A-Z])/g,"$1 $2")))?{actions:[{...i,command:"wait",positionals:[l,"30000"]},{...o,command:"fill",positionals:[l,u],flags:i.flags},s],actionLines:[c,c,t[r+2]??c],consumed:3}:{actions:[function(e){let t={...e.flags?.maestro??{}};return delete t.allowNonHittableCoordinateFallback,{...e,flags:{...e.flags??{},maestro:{...t}}}}(i)],actionLines:[c],consumed:1}}(e,t,a);if(o){r.push(...o.actions),n.push(...o.actionLines),a+=o.consumed-1;continue}r.push(i),n.push(t[a]??1)}return{actions:r,actionLines:n}}(s,l)}({config:r,commands:n,commandLines:function(e){let t=e.split(/\r?\n/),r=t.findIndex(e=>"---"===e.trim()),n=-1===r?0:r+1,a=[];for(let e=n;e<t.length;e+=1)/^-\s+/.test(t[e]??"")&&a.push(e+1);return a}(e),context:a});return{actions:i,actionLines:o,metadata:{env:r.env}}}function al(e){let t=o(e);for(let e of t)if(e.errors.length>0){let t=e.errors[0]?.message??"Invalid Maestro YAML flow.";throw new d("INVALID_ARGS",`Invalid Maestro YAML flow: ${t}`)}return t.map(e=>e.toJSON()).filter(e=>null!==e)}function au(e){if(0===e.length)throw new d("INVALID_ARGS","Maestro flow is empty.");if(Array.isArray(e[0]))return{config:{},commands:nN(e[0])};let t=function(e){if(!n_(e))throw new d("INVALID_ARGS","Maestro flow config must be a YAML map.");return{..."string"==typeof e.name&&e.name.length>0?{name:e.name}:{},..."string"==typeof e.appId&&e.appId.length>0?{appId:e.appId}:{},...n_(e.env)?{env:nM(e.env,"env")}:{},...Array.isArray(e.onFlowStart)?{onFlowStart:nN(e.onFlowStart)}:{},...Array.isArray(e.onFlowComplete)?{onFlowComplete:nN(e.onFlowComplete)}:{}}}(e[0]),r=e[1];if(!Array.isArray(r))throw new d("INVALID_ARGS","Maestro flow must contain a command list after the YAML document separator.");return{config:t,commands:nN(r)}}function ac(e,r){let n=function(e,t){if(a.isAbsolute(e))return e;if(!t.baseDir)throw new d("INVALID_ARGS","runFlow file paths require replay input to have a source path.");return a.resolve(t.baseDir,e)}(e,r);if(r.visitedPaths.has(n))throw new d("INVALID_ARGS",`Maestro runFlow cycle detected at ${n}.`);let i=t.readFileSync(n,"utf8"),o=new Set(r.visitedPaths);return o.add(n),as(i,{...r,baseDir:a.dirname(n),visitedPaths:o})}let ad=/[*?[\]{}]/;function ap(e){return"maestro"===e}let af=["failed to start daemon","runner did not accept connection","xcodebuild exited early","device is offline","device offline","device unauthorized"];function am(e){var t,r,n,a;let i,o,s="ok"in(t=e)?t.ok?null:t.error:"failed"===t.status?t.error:null;return!!s&&(r=s.details,"timeout_cleanup_pending"===(i="string"==typeof r?.reason?r.reason:"")||!!i&&eT(i)||(n=s.code,a=s.message,o=`${n}
|
|
25
25
|
${a}`.toLowerCase(),af.some(e=>o.includes(e))))}async function ah(e){let r,n,{filePath:i,sessionName:o,requestId:s,timeoutMs:l,platform:u,target:d,artifactsDir:p,runReplay:f,cleanupSession:m}=e;O(s);let h=new Set,w=!1,g=Date.now(),y=function(e){let{artifactsDir:r,artifactPaths:n,filePath:i,sessionName:o,requestId:s,timeoutMs:l,platform:u,target:c}=e;if(!r)return;let d=a.join(r,"replay-timing.ndjson");return t.mkdirSync(a.dirname(d),{recursive:!0}),t.writeFileSync(d,""),n.add(d),ay(d,{type:"replay_test_attempt_start",ts:new Date().toISOString(),replayPath:i,session:o,requestId:s,timeoutMs:l,platform:u,target:c}),d}({artifactsDir:p,artifactPaths:h,filePath:i,sessionName:o,requestId:s,timeoutMs:l,platform:u,target:d}),v=f({filePath:i,sessionName:o,platform:u,target:d,requestId:s,artifactsDir:p,artifactPaths:h,tracePath:y}).catch(e=>({ok:!1,error:c(e)})).finally(()=>{ep(s)});try{return n="number"==typeof l?await Promise.race([v,new Promise(e=>{r=setTimeout(()=>{w=!0,eu(s),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}}}}(l,[...h]))},l)})]):await v,ay(y,{type:"replay_test_attempt_stop",ts:new Date().toISOString(),session:o,ok:n.ok,timedOut:w,durationMs:Date.now()-g,errorCode:n.ok?void 0:n.error.code}),n}finally{var A;r&&clearTimeout(r),w&&(await aw(v)||((A=n)&&!A.ok&&(A.error.details={...A.error.details??{},reason:"timeout_cleanup_pending",timeoutCleanupPending:!0}),eQ({level:"warn",phase:"test_timeout_cleanup_race",data:{session:o,requestId:s,graceMs:2e3}}),ag({replayPromise:v,cleanupSession:m,sessionName:o,requestId:s})));let e=Date.now();try{ay(y,{type:"replay_test_cleanup_start",ts:new Date().toISOString(),session:o}),await m(o),ay(y,{type:"replay_test_cleanup_stop",ts:new Date().toISOString(),session:o,ok:!0,durationMs:Date.now()-e})}catch(r){let t=c(r);ay(y,{type:"replay_test_cleanup_stop",ts:new Date().toISOString(),session:o,ok:!1,durationMs:Date.now()-e,errorCode:t.code}),eQ({level:"warn",phase:"test_cleanup_failed",data:{session:o,error:t.message}})}}}async function aw(e){return await Promise.race([e.then(()=>!0),l(2e3).then(()=>!1)])}async function ag(e){let{replayPromise:t,cleanupSession:r,sessionName:n,requestId:a}=e;try{await t}finally{try{await r(n)}catch(e){eQ({level:"warn",phase:"test_late_cleanup_failed",data:{session:n,requestId:a,error:c(e).message}})}}}function ay(e,r){e&&t.appendFileSync(e,`${JSON.stringify(r)}
|
|
26
26
|
`)}async function av(e){let{req:r,sessionName:n,runReplay:i,cleanupSession:o}=e;if((r.positionals?.length??0)===0)return R("INVALID_ARGS","test requires at least one path or glob");try{var s,l,c,p,f,m;let e,u,h,w,g,y=function(e){var r,n,i,o,s,l;let{inputs:u,cwd:c,platformFilter:p,replayBackend:f}=e,m=(r=f,new Set(ap(r)?[".ad",".yaml",".yml"]:[".ad"])),h=c??process.cwd(),w=[...new Set(u.flatMap(e=>(function(e,r,n){var i,o;let s=Q.expandHome(e,r);if(t.existsSync(s)){let r=t.statSync(s);if(r.isDirectory())return[...n].map(e=>`**/*${e}`).flatMap(e=>t.globSync(e,{cwd:s}).map(e=>a.join(s,e)));if(r.isFile()){if(!n.has(a.extname(s)))throw new d("INVALID_ARGS",`test does not support this file type: ${e}`);return[s]}return[]}if(i=e,!ad.test(i)&&(o=s,!ad.test(o)))throw new d("INVALID_ARGS",`test input not found: ${e}`);let l=a.isAbsolute(s)?s:e;return t.globSync(l,{cwd:a.isAbsolute(s)?void 0:r}).map(e=>a.isAbsolute(e)?e:a.resolve(r,e)).filter(e=>n.has(a.extname(e))&&function(e){try{return t.statSync(e).isFile()}catch{return!1}}(e))})(e,h,m)))].map(e=>a.normalize(e)).sort((e,t)=>e.localeCompare(t)),g=[];for(let e of w){let r=t.readFileSync(e,"utf8"),u=ny(r),c=(n=r,i=e,o=f,ap(o)&&".ad"!==a.extname(i)?function(e){let{config:t}=au(al(e));return t.name}(n):void 0);if(!p){g.push({kind:"run",path:e,title:c,metadata:u});continue}if(!u.platform){ap(f)?g.push({kind:"run",path:e,title:c,metadata:u}):g.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${p}`});continue}s=p,l=u.platform,("apple"===s?"apple"===l||"ios"===l||"macos"===l:l===s)&&g.push({kind:"run",path:e,title:c,metadata:u})}if(0===g.filter(e=>"run"===e.kind).length){let e=p?` for --platform ${p}`:"";throw new d("INVALID_ARGS",`No replay tests matched${e}.`)}return g}({inputs:r.positionals,cwd:r.meta?.cwd,platformFilter:r.flags?.platform,replayBackend:r.flags?.replayBackend}),v=(s=r.meta?.requestId,(s?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),A=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:n}=e,i=Q.expandHome(t??".agent-device/test-artifacts",r);return a.join(i,n)}({artifactsDir:"string"==typeof r.flags?.artifactsDir?r.flags.artifactsDir:void 0,cwd:r.meta?.cwd,suiteInvocationId:v}),b=[],S=Date.now(),I=0;for(let[e,t]of y.entries()){if("skip"===t.kind){ex({type:"replay-test",file:t.path,status:"skip",index:e+1,total:y.length,message:t.message}),b.push({file:t.path,status:"skipped",durationMs:0,reason:t.reason,message:t.message});continue}I+=1;let a=await aA({entry:t,sessionName:n,suiteInvocationId:v,caseIndex:I-1,cwd:r.meta?.cwd,requestId:r.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))}(r.flags?.retries,t.metadata.retries),timeoutMs:(l=r.flags?.timeoutMs,c=t.metadata.timeoutMs,"number"==typeof l?l:c),suiteArtifactsDir:A,suiteIndex:e+1,suiteTotal:y.length,runReplay:i,cleanupSession:o});if(b.push(a),r.flags?.failFast===!0||am(a))break}let _=(p=y.length,f=b,m=Date.now()-S,e=f.filter(e=>"passed"===e.status).length,h=(u=f.filter(e=>"failed"===e.status)).length,w=f.filter(e=>"skipped"===e.status).length,g=e+h,{total:p,executed:g,passed:e,failed:h,skipped:w,notRun:Math.max(0,p-g-w),durationMs:m,failures:u,tests:f});return{ok:!0,data:_}}catch(t){let e=u(t);return R(e.code,e.message)}}async function aA(e){var r,n;let i,o,{entry:s,sessionName:l,suiteInvocationId:u,caseIndex:c,cwd:d,requestId:p,retries:f,timeoutMs:m,suiteArtifactsDir:h,suiteIndex:w,suiteTotal:g,runReplay:y,cleanupSession:v}=e,A=Date.now(),b=a.join(h,(r=s.path,(0===(o=d?a.relative(d,r):a.basename(r)).length||o.startsWith("..")?a.basename(r):o).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),S="",I=0,_=0,N=[];for(let e=0;e<=f;e+=1){I=e+1;let r=Date.now(),o=function(e,t,r,n,i=0){let o=a.basename(r,a.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${n+1}${o?`-${o}`:""}:attempt-${i+1}`}(l,u,s.path,c,e),d=a.join(b,`attempt-${I}`);n=s.path,t.mkdirSync(d,{recursive:!0}),function(e,r){let n=a.join(r,"replay.ad");if(t.copyFileSync(e,n),!function(e){let t=a.extname(e).toLowerCase();return".yml"===t||".yaml"===t}(e))return;let i=a.join(r,a.basename(e));a.resolve(i)!==a.resolve(n)&&t.copyFileSync(e,i)}(n,d);let h=function(e){let{requestId:t,suiteInvocationId:r,filePath:n,caseIndex:i,attemptIndex:o}=e;return en(`${t??r}:test:${i+1}:${a.basename(n)}:attempt:${o+1}`,r)}({requestId:p,suiteInvocationId:u,filePath:s.path,caseIndex:c,attemptIndex:e}),A=await ah({filePath:s.path,sessionName:o,requestId:h,timeoutMs:m,platform:s.metadata.platform,target:s.metadata.target,artifactsDir:d,runReplay:y,cleanupSession:v});if(_=Date.now()-r,!function(e){let{response:r,filePath:n,sessionName:i,attempts:o,maxAttempts:s,attemptArtifactsDir:l}=e,u=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(r)];r.ok||"string"!=typeof r.error.logPath||u.push(r.error.logPath);let c=function(e,r){let n=[],i=new Map;for(let o of e){if(!function(e){try{return t.statSync(e).isFile()}catch{return!1}}(o))continue;let e=function(e,t){let r=a.extname(e),n=r?e.slice(0,-r.length):e,i=t.get(e)??0;return(t.set(e,i+1),0===i)?e:`${n}-${i+1}${r}`}(a.basename(o),i),s=a.join(r,e);a.resolve(o)!==a.resolve(s)&&t.copyFileSync(o,s),n.push(s)}return n}(u,l),d=[`file: ${n}`,`session: ${i}`,`attempt: ${o}/${s}`,`status: ${r.ok?"passed":"failed"}`];if(r.ok){let e="number"==typeof r.data?.replayed?r.data.replayed:0,t="number"==typeof r.data?.healed?r.data.healed:0;d.push(`replayed: ${e}`,`healed: ${t}`)}else d.push(`code: ${r.error.code}`,`message: ${r.error.message}`),r.error.hint&&d.push(`hint: ${r.error.hint}`),r.error.diagnosticId&&d.push(`diagnosticId: ${r.error.diagnosticId}`),r.error.logPath&&d.push(`logPath: ${r.error.logPath}`),r.error.details?.reason==="timeout"&&d.push("timeoutMode: cooperative");c.length>0&&d.push(`copiedArtifacts: ${c.map(e=>a.basename(e)).join(", ")}`);let p=a.join(l,"result.txt"),f=`${d.join("\n")}
|
|
27
|
-
`;t.writeFileSync(p,f),r.ok||t.writeFileSync(a.join(l,"failure.txt"),f)}({response:A,filePath:s.path,sessionName:o,attempts:I,maxAttempts:f+1,attemptArtifactsDir:d}),i=A,S=o,A.ok||(N.push({attempt:I,message:A.error.message,durationMs:_}),am(A)||e>=f))break;ex({type:"replay-test",file:s.path,status:"fail",index:w,total:g,attempt:I,maxAttempts:f+1,retrying:!0,message:A.error.message})}let M=Date.now()-A;if(i?.ok)return ex({type:"replay-test",file:s.path,status:"pass",index:w,total:g,attempt:I,maxAttempts:f+1,durationMs:M,artifactsDir:b}),{file:s.path,title:s.title,session:S,status:"passed",durationMs:M,finalAttemptDurationMs:_,attempts:I,artifactsDir:b,replayed:"number"==typeof i.data?.replayed?i.data.replayed:0,healed:"number"==typeof i.data?.healed?i.data.healed:0,...N.length>0?{attemptFailures:N}:{}};let x=i?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:i?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return ex({type:"replay-test",file:s.path,status:"fail",index:w,total:g,attempt:I,maxAttempts:f+1,durationMs:M,artifactsDir:b,message:x.message}),{file:s.path,title:s.title,session:S,status:"failed",durationMs:M,attempts:I,artifactsDir:b,error:x}}let ab={maestro:{parse:function(e,t={}){var r;let n;return as(e,(n=(r=t).visitedPaths??new Set,r.sourcePath&&n.add(a.resolve(r.sourcePath)),{baseDir:r.sourcePath?a.dirname(r.sourcePath):void 0,platform:function(e){if(e){let t;return"android"===(t=e.trim().toLowerCase())?"android":"ios"===t?"ios":void 0}}(r.platform),env:{},envOverrides:r.env??{},visitedPaths:n}))}}};function aS(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=void 0!==t&&/^\d+$/.test(t)?t:null,n=e0(null!==r?e.slice(0,-1):e.slice());return!n||n.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:n.selectorExpression,selectorTimeout:r}}async function aI(e){let{action:t,sessionName:r,logPath:n,sessionStore:a}=e;if(!(_(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let i=a.get(r);if(!i)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),_(e.command)){let r=function(e){let t=e.positionals??[];if("longpress"!==e.command)return t;let r=t.at(-1);return t.length>1&&a_(r)?t.slice(0,-1):t}(e),n=r[0]??"";n&&!n.startsWith("@")&&t.push(r.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}=e5(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=aS(e.positionals??[]);r&&t.push(r)}return C(t).filter(e=>e.trim().length>0)})(t).map(e=>e6(e)).filter(e=>null!==e);if(0===o.length)return null;let s=_(t.command)||"fill"===t.command,l=_(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await aN(i,t,n,s,a);for(let e of o){let r=e9(u.nodes,e,{platform:i.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let n=e4(r.node,i.device.platform,{action:"fill"===t.command?"fill":_(t.command)?"click":"get"}).join(" || ");if(_(t.command))return{...t,positionals:"longpress"===t.command?function(e,t){let r="number"==typeof e.result?.durationMs?String(e.result.durationMs):function(e){let t=e.at(-1);return e.length>1&&a_(t)?t:void 0}(e.positionals??[]);return r?[t,r]:[t]}(t,n):[n]};if("fill"===t.command){let e=A(t);if(!e)continue;return{...t,positionals:[n,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,n]}}if("is"===t.command){let{predicate:e,split:r}=e5(t.positionals);if(!e)continue;let a=r?.rest.join(" ").trim()??"",i=[e,n];return"text"===e&&a.length>0&&i.push(a),{...t,positionals:i}}if("wait"===t.command){let{selectorTimeout:e}=aS(t.positionals??[]),r=[n];return e&&r.push(e),{...t,positionals:r}}}return null}function a_(e){return void 0!==e&&""!==e.trim()&&Number.isFinite(Number(e))}async function aN(e,t,r,n,a){let i=X(await m(e.device,"snapshot",[],t.flags?.out,{...Y(r,{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n},e.appBundleId,e.trace?.outPath)}),{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n});return j(e,i),a.set(e.name,e),i}let aM=new WeakMap,ax=new WeakMap;function aD(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}async function ak(e){var t;let r,n=await e.invoke({...e.baseReq,command:"snapshot",positionals:[],flags:{...e.baseReq.flags,noRecord:!0,snapshotRaw:!0,snapshotForceFull:!0}});return n.ok&&e.scope&&(t=e.scope,(r=q(aO(n.data)))&&aM.set(t,r)),n}function aO(e){if("object"==typeof e&&null!==e&&Array.isArray(e.nodes))return e}let aR=new Map([["button",0],["link",0],["textfield",0],["textview",0],["searchfield",0],["switch",0],["slider",0],["cell",1],["statictext",2]]);function aL(e,t,r,n){let a=aC(e,t,r,{allowLeadingCompositeLabelMatch:!1}),i=aP({nodes:e.nodes,matches:a,platform:r}),o=aU(e.nodes,i.matches,void 0,aF(t),n,!0);return o?{ok:!0,node:o.node,rect:o.rect,matches:i.matches.length}:{ok:!1,message:i.blockedByReactNativeOverlay?`React Native overlay is covering app content: ${t}`:a.length>0?`Maestro selector matched ${a.length} element(s), but none were visible: ${t}`:`Maestro selector did not match: ${t}`}}function aP(e){let t=e.matches.filter(t=>ts({predicate:"visible",node:t,nodes:e.nodes,platform:e.platform}).pass),r=function(e,t,r){let n=tc(e);if(!n.detected||!n.redBox)return{matches:t,blockedByReactNativeOverlay:!1};let a=tu(n),i=a.filter(t=>ts({predicate:"visible",node:t,nodes:e,platform:r}).pass);if(0===i.length)return 0===a.length?{matches:[],blockedByReactNativeOverlay:!0}:{matches:t,blockedByReactNativeOverlay:!1};let o=new Set(i.map(e=>e.index)),s=t.filter(e=>o.has(e.index));return{matches:s,blockedByReactNativeOverlay:t.length>0&&0===s.length}}(e.nodes,t,e.platform);return{matches:r.matches,blockedByReactNativeOverlay:r.blockedByReactNativeOverlay}}function a$(e){return e?.platform==="android"?"android":"ios"}function aF(e){let t=e8(e).selectors.flatMap(e=>e.terms);if(0===t.length||!t.some(e=>"label"===e.key||"text"===e.key)||!t.every(e=>["label","text","id"].includes(e.key)))return null;let r=t.map(e=>"string"==typeof e.value?e.value:""),n=r[0];return n&&r.every(e=>e===n)?n:null}function aC(e,t,r,n={}){for(let a of e8(t).selectors){let t=e.nodes.filter(e=>(function(e,t,r,n){return!!te(e,t,r)||t.terms.every(t=>(function(e,t,r,n){var a,i,o;return"string"!=typeof t.value||"id"!==(a=t.key)&&"label"!==a&&"text"!==a&&"value"!==a?te(e,{raw:t.key,terms:[t]},r):aE((i=e,"id"===(o=t.key)?i.identifier:"label"===o?i.label:"value"===o?i.value:e1(i)),t.value,n)})(e,t,r,n))})(e,a,r,n));if(t.length>0)return t}return[]}function aE(e,t,r={}){var n;let a=e??"",i=tr(a),o=tr(t);if(i===o||!1!==r.allowLeadingCompositeLabelMatch&&function(e,t){if(!e||!t||!e.startsWith(t))return!1;let r=e.at(t.length);return","===r||":"===r||";"===r}(i,o))return!0;if(n=t,!/(?:\.\*|\.\+|\[[^\]]+\]|\([^)]*\)|\||\^|\$|\\[dDsSwWbB])/.test(n))return!1;try{return new RegExp(t).test(a)}catch{return!1}}function aV(e,t,r){if(t.rect&&t.rect.width>0&&t.rect.height>0)return{rect:t.rect,inherited:!1};if(t.rect)return null;let n=function(e,t,r){let n=t;for(;"number"==typeof n.parentIndex&&(n=r.get(n.parentIndex)??e[n.parentIndex]);)if(n.rect)return n.rect.width>0&&n.rect.height>0?n.rect:null;return null}(e,t,r);return n?{rect:n,inherited:!0}:null}function aU(e,t,r,n,a,i=!1,o=!1,s){var l,u,c,d,p,f,m,h,w,g,y,v,A,b,S,I,_,N,M;let x,D,k,O,R=e7(e),L=(l=e,u=t,c=R,d=n,p=r,f=a,m=i,k=(D=(x=u.map(e=>{var t;let r;return(r=aV(l,t=e,c))?{node:t,rect:r.rect,inheritedRect:r.inherited}:null}).filter(e=>!!e)).filter(e=>!e.inheritedRect)).length>0?D:x,d&&void 0===p?(h=k,w=f,g=m,O=h.filter(e=>{var t,r;let n,a;return t=e.rect,r=w,n=r?.referenceWidth??1/0,a=r?.referenceHeight??1/0,t.x<n&&t.y<a&&t.x+t.width>0&&t.y+t.height>0}),g||O.length>0?O:h):x),P=function(e,t,r,n,a,i){var o,s,l,u,c,d,p;if(void 0!==r)return t[r]??null;let f=(o=e,s=t,l=n,u=a,c=i,u&&l?function(e,t,r,n){let a=t.filter(e=>0===az(e.node,r));if(a.length>=2){let t=aG(e,a,r,n);if(t)return t}let i=t.filter(e=>1===az(e.node,r));return a.length>0||i.length<2?null:aG(e,i,r,n)}(o,s,l,c)??aT(o,s,l,c):aT(o,s,l,c));return(d=f,p=n,a&&p&&d)?function(e,t,r){var n,a,i,o,s,l,u,c,d,p,f,m,h,w,g,y,v;let A,b,S,I,_,N,M,x;if(n=t,a=r,!(("other"===(A=tt(n.node.type??""))||"scrollview"===A||"scroll-area"===A)&&!(n.rect.width<120)&&!(n.rect.height<32)&&!(n.rect.height>80)&&1>=az(n.node,a)))return null;let D=(i=e,o=t,s=r,i.filter(e=>{var t,r,n,a,i;let l,u;return e.parentIndex===o.node.index&&!!e.rect&&(t=e,r=o.rect,n=s,!("button"!==(l=tt(t.type??""))&&"cell"!==l&&"other"!==l||1>=az(t,n))&&!(t.rect.width<16)&&!(t.rect.height<16)&&!!aH(r,t.rect)&&(a=r,i=t.rect,u=Math.max(a.y,i.y),Math.max(0,Math.min(a.y+a.height,i.y+i.height)-u)/Math.max(1,Math.min(a.height,i.height))>=.5))}).sort((e,t)=>e.rect.x-t.rect.x));if(0===D.length)return null;let k=(S=Math.floor((b=[...D.map(e=>e.rect.width)].sort((e,t)=>e-t)).length/2),b[S]??0),O=function(e,t){let r=[],n=e.x,a=e.x+e.width;for(let i of t){let t=Math.max(e.x,i.x),o=Math.min(a,i.x+i.width);t>n&&r.push({x:n,width:t-n}),n=Math.max(n,o)}return a>n&&r.push({x:n,width:a-n}),r}(t.rect,D.map(e=>e.rect)),R=(l=t,u=r,c=O,d=k,N=c.filter(e=>{var t,r;return t=e.width,r=d,!(t<24)&&!(r<24)&&t>=.4*r&&t<=1.6*r}),M=(p=l,f=u,I=c.find(e=>1>Math.abs(e.x-p.rect.x)),_=Math.max(48,Math.min(220,8*f.length+24)),(m=p,h=f,w=I,g=_,w&&"scrollview"===tt(m.node.type??"")&&1>=az(m.node,h)&&m.rect.width>=240&&m.rect.height>=32&&m.rect.height<=80&&w.width<=.55*m.rect.width&&w.width>=.6*g)?{x:p.rect.x,width:Math.min(_,I.width)}:null),x=N.some(e=>{var t;return t=l.rect,1>Math.abs(e.x-t.x)}),M&&!x?M:1===N.length?N[0]??null:M);return R?(y=t,v=R,{...y,rect:{x:v.x,y:y.rect.y,width:v.width,height:y.rect.height}}):null}(e,f,n)??f:f}(e,L,r,n,o,s);return y=e,v=P,A=R,b=o,S=a,v?b?(I=y,_=v,N=A,M=S,(aB(_.node)?null:e2(I,_.node,N,e=>{if(!aB(e))return null;let t=aV(I,e,N);return t&&function(e,t,r){if(!aH(t,e))return!1;let n=aq(t),a=aq(e);if(a>0&&n>30*a)return!1;if(r){let e=r.referenceWidth*r.referenceHeight;if(e>0&&n>.5*e)return!1}return!0}(_.rect,t.rect,M)?{node:e,rect:t.rect}:null}))??{node:v.node,rect:v.rect}):{node:v.node,rect:v.rect}:null}function aT(e,t,r,n){return(function(e,t,r,n){var a;let i,o,s;if(!r||t.length<2)return t;let l=t.filter(e=>0===az(e.node,r));if(l.length<2)return t;let u=e7(e),c=l.map(t=>({candidate:t,container:aj(e,t.node,u)})).filter(e=>!!e.container);if(c.length<2||c.length!==l.length)return t;let d=c.filter(e=>{var t;return t=e,c.some(e=>e!==t&&t.container.index!==e.container.index&&aW(t.container.rect,e.container.rect)>=.6)});if(d.length<2)return t;let p=(o=Math.max(...i=(a=d).map(e=>aq(e.container.rect))),(s=Math.min(...i))<=0||o<1.2*s?[]:a.filter(e=>aq(e.container.rect)===o).map(e=>e.candidate));if(p.length>0)return p;let f=function(e,t,r,n){if(!r)return[];let a=aj(e,r.node,n),i=a&&aH(a.rect,r.rect)?a:null,o=t.map(e=>({entry:e,score:function(e,t,r){if(r)return e.index===r.index?0:.6>aW(e.rect,r.rect)?1/0:Math.abs(e.index-r.index);if(aW(e.rect,t.rect)>=.6)return 0;let n=e.index-t.node.index;return n>=0?n:1e5+Math.abs(n)}(e.container,r,i)})),s=Math.min(...o.map(e=>e.score));return Number.isFinite(s)?o.filter(e=>e.score===s).map(e=>e.entry.candidate):[]}(e,d,n,u);if(f.length>0)return f;let m=Math.max(...d.map(e=>e.container.index)),h=d.filter(e=>e.container.index===m).map(e=>e.candidate);return h.length>0?h:t})(e,t,r,n).sort((e,t)=>(function(e,t,r){var n,a;let i=function(e,t,r){if(r){let n=az(e.node,r)-az(t.node,r);if(0!==n)return n}let n=aK(e.node)-aK(t.node);if(0!==n)return n;let a=Number(e.inheritedRect)-Number(t.inheritedRect);if(0!==a)return a;let i=r&&aK(e.node)===aK(t.node)?aq(t.rect)-aq(e.rect):aq(e.rect)-aq(t.rect);return 0!==i?i:0}(e,t,r);if(0!==i)return i;if(n=e.rect,a=t.rect,Math.round(n.x)!==Math.round(a.x)||Math.round(n.y)!==Math.round(a.y)||Math.round(n.width)!==Math.round(a.width)||Math.round(n.height)!==Math.round(a.height))return e.node.index-t.node.index;let o=(t.node.depth??0)-(e.node.depth??0);return 0!==o?o:t.node.index-e.node.index})(e,t,r))[0]??null}function aG(e,t,r,n){let a=e7(e),i=t.filter(r=>{var n;return(n=r).rect.width>=16&&n.rect.width<=260&&n.rect.height>=24&&n.rect.height<=80&&t.some(t=>{var n,i,o,s;return n=e,i=t,o=r,s=a,!(i.node.index===o.node.index||!aH(i.rect,o.rect)||aq(i.rect)<2*aq(o.rect))&&e3(n,o.node,i.node,s)})});return aT(e,i,r,n)}function aj(e,t,r){return e2(e,t,r,e=>{let t;return!e.rect||"scrollview"!==(t=tt(e.type??""))&&"scroll-area"!==t&&"list"!==t||e.rect.width<240||e.rect.height<320?null:e})}function aq(e){return e.width*e.height}function aK(e){return aR.get(tt(e.type??""))??3}function aB(e){let t=tt(e.type??"");return!0===e.hittable||"button"===t||"link"===t||"cell"===t||"textfield"===t||"searchfield"===t||"switch"===t||"slider"===t}function aH(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 aW(e,t){let r=Math.max(e.x,t.x),n=Math.min(e.x+e.width,t.x+t.width),a=Math.max(e.y,t.y);return Math.max(0,n-r)*Math.max(0,Math.min(e.y+e.height,t.y+t.height)-a)/Math.max(1,Math.min(aq(e),aq(t)))}function az(e,t){let r=[e.label,e1(e),e.identifier,e.value].filter(e=>!!e);return r.some(e=>e===t)?0:r.some(e=>tr(e)===tr(t))?1:r.some(e=>aE(e,t))?2:3}async function aJ(e){var t,r,n;let a=aQ(e.positionals,{command:"assertVisible",defaultTimeoutMs:5e3});if(!a.ok)return a.response;let i=(t=e.baseReq,r=a.selector,n=a.timeoutMs,t.flags?.platform!=="ios"||t.flags?.maestro?.allowAlreadyPastLoading===!0||n<3e4?null:aF(r));return i?await aX(e,a,i):await aZ(e,a)}async function aX(e,t,r){let n=Date.now(),a=await aY(e,t,r);return a.ok?a3({ok:!0,data:{selector:t.selector,nativeWait:!0,query:r,response:a.data}},t.selector,n):a}async function aY(e,t,r){return await e.invoke({...e.baseReq,command:"wait",positionals:[r,String(t.timeoutMs)]})}async function aZ(e,t){let r,n=Date.now(),a=t.timeoutMs+1e3,i=!1;for(;;){let o=Date.now(),s=await a0(e,t.selector,"assertVisible");if(s.visible)return a3(s.response,t.selector,n);r=s.response;let l=function(e,t,r,n){var a,i,o,s,l,u,c;return!(a=r.response).ok&&"COMMAND_FAILED"===a.error.code&&a.error.message.includes("React Native overlay")?{kind:"return",response:r.response}:(i=e,o=t.selector,s=r.snapshot,i.flags?.maestro?.allowAlreadyPastLoading===!0&&void 0!==s&&function(e,t){let r=a1(aF(e));if(!a2(r))return!1;let n=t.nodes.flatMap(e=>[e.label,e.value,e.identifier]).filter(e=>!!e?.trim()).map(e=>a1(e));return!n.some(e=>e.includes("something went wrong"))&&n.some(e=>e!==r&&!a2(e))}(o,s))?{kind:"return",response:(l=t.selector,u=t.timeoutMs,c=n,{ok:!0,data:{selector:l,alreadyPastLoading:!0,waitedMs:Date.now()-c,timeoutMs:u}})}:{kind:"continue"}}(e.baseReq,t,s,n);if("return"===l.kind)return l.response;let u=function(e){var t,r,n,a;return Date.now()-e.startedAt<e.deadlineMs?"wait":(t=e.capturedAfterDeadline,r=e.captureStartedAt,n=e.startedAt,a=e.deadlineMs,!t&&r-n<a)?"capture-again":"finish"}({captureStartedAt:o,capturedAfterDeadline:i,startedAt:n,deadlineMs:a});if("capture-again"===u){i=!0;continue}if("finish"===u)break;await tp(250)}return r??aD("COMMAND_FAILED",`Expected visible but did not match: ${t.selector}`,{selector:t.selector,timeoutMs:t.timeoutMs})}function aQ(e,t){let[r,n=String(t.defaultTimeoutMs)]=e;if(!r)return{ok:!1,response:aD("INVALID_ARGS",`${t.command} requires a selector.`)};let a=Number(n);return!Number.isFinite(a)||a<0?{ok:!1,response:aD("INVALID_ARGS",`${t.command} timeout must be a non-negative number.`)}:{ok:!0,selector:r,timeoutMs:a}}async function a0(e,t,r){var n;let a=await ak(e);if(!a.ok)return{visible:!1,response:a,infrastructureFailure:!0};let i=aO(a.data);if(!i)return{visible:!1,response:aD("COMMAND_FAILED",`Unable to read snapshot data for ${r}.`),infrastructureFailure:!0};let o=aL(i,t,a$(e.baseReq.flags),q(i));return o.ok?(n=e.scope,n&&ax.set(n,{selector:t}),{visible:!0,response:{ok:!0,data:{selector:t,matches:o.matches,nodeIndex:o.node.index,nodeType:o.node.type,nodeLabel:o.node.label,nodeIdentifier:o.node.identifier,rect:o.rect}}}):{visible:!1,response:aD("COMMAND_FAILED",o.message,{selector:t}),infrastructureFailure:!1,snapshot:i}}function a1(e){return e?.trim().toLowerCase().replace(/\u2026/g,"...")??""}function a2(e){return"loading"===e||"loading..."===e}function a3(e,t,r){return e.ok?{ok:!0,data:{selector:t,...e.data,waitedMs:Date.now()-r}}:e}async function a5(e){let t,r=aQ(e.positionals,{command:"assertNotVisible",defaultTimeoutMs:3e3});if(!r.ok)return r.response;let n=Date.now(),a=0;for(;Date.now()-n<=r.timeoutMs;){let i=await a0(e,r.selector,"assertNotVisible");if(!i.visible&&i.infrastructureFailure)return i.response;if(i.visible)a=0,t=i.response;else{a+=1;let e=Date.now()-n;if(a>=2||e>=r.timeoutMs)return{ok:!0,data:{pass:!0,selector:r.selector,stableSamples:a,waitedMs:e,timeoutMs:r.timeoutMs}}}await tp(250)}return a>0?{ok:!0,data:{pass:!0,selector:r.selector,stableSamples:a,waitedMs:Date.now()-n,timeoutMs:r.timeoutMs}}:aD("COMMAND_FAILED",`Expected not visible but matched: ${r.selector}`,{selector:r.selector,timeoutMs:r.timeoutMs,lastResponse:t})}async function a6(e){let t,r,n=Number(e.positionals[0]??15e3);if(!Number.isFinite(n)||n<0)return aD("INVALID_ARGS","waitForAnimationToEnd timeout must be a number.");let a=Date.now();for(;Date.now()-a<n;){let a=await ak(e),i=function(e,t,r){let n=function(e){if(!e.ok)return null;let t=aO(e.data);return t?JSON.stringify(t.nodes.map(e=>({index:e.index,parentIndex:e.parentIndex,type:e.type,identifier:e.identifier,label:e.label,value:e.value,rect:e.rect?{x:Math.round(e.rect.x),y:Math.round(e.rect.y),width:Math.round(e.rect.width),height:Math.round(e.rect.height)}:void 0}))):null}(e);return e.ok?n?t===n?{done:!0,response:{ok:!0,data:{stable:!0,timeoutMs:r}}}:{done:!1,signature:n}:{done:!0,response:e}:{done:!1}}(a,t,n);if(i.done)return i.response;t=i.signature??t,r=a,await tp(250)}return r?.ok===!1?r:{ok:!0,data:{stable:!1,timeoutMs:n}}}let a8=.35,a9=120,a4=360,a7=8,ie=120,it=70,ir=200,ia=168,ii=48;function io(e,t){return Math.round(Math.min(a4,Math.max(a9,"number"==typeof e?e*a8:0,1.5*t)))}async function is(e){var t,r,n;let[a,i="5000",o="down"]=e.positionals;if(!a)return aD("INVALID_ARGS","scrollUntilVisible requires a selector.");let s=Number(i);if(!Number.isFinite(s)||s<=0)return aD("INVALID_ARGS","scrollUntilVisible timeout must be a positive number.");let l=aF(a),u=Math.max(1,Math.ceil(s/500)),c=null;for(let t=0;t<u;t+=1){let r=await ig(e,a,l,Math.min(500,Math.max(1,s-500*t)));if(r.ok)return r;if(c=r,t===u-1)break;let n=await e.invoke({...e.baseReq,command:"scroll",positionals:[o]});if(!n.ok)return n}return t=c,r=a,n=s,t?{ok:!1,error:{...t.error,message:`scrollUntilVisible timed out after ${n}ms for selector: ${r}. Last wait: ${t.error.message}`}}:aD("COMMAND_FAILED",`scrollUntilVisible timed out after ${n}ms for selector: ${r}`)}async function il(e){let[t,r]=e.positionals,n=Number(t),a=Number(r);if(!Number.isFinite(n)||!Number.isFinite(a))return aD("INVALID_ARGS","tapOn percentage point requires numeric x/y values.");let i=await ak(e);if(!i.ok)return i;let o=aO(i.data);if(!o)return aD("COMMAND_FAILED","Unable to read snapshot data for Maestro percentage point tap.");let s=q(o);if(!s)return aD("COMMAND_FAILED","Unable to resolve screen size for Maestro percentage point tap.");let l=tn(s,n,a);return await e.invoke({...e.baseReq,command:"click",positionals:[String(l.x),String(l.y)]})}async function iu(e){let t=await ic(e);if(t)return t;let r=await ih(e);return r.ok?await im(e,r,r.durationMs):r.response}async function ic(e){let[t,r,n]=e.positionals;if("direction"===t&&("left"===r||"right"===r))return await e.invoke({...e.baseReq,command:"gesture",positionals:["swipe",r,...n?[n]:[]]})}async function id(e){var t,r,n,a;let i,[o,s]=e.positionals;if(!o)return aD("INVALID_ARGS","tapOn requires a selector.");let l=function(e){if(!e)return{ok:!0,value:null};try{let t=JSON.parse(e);return{ok:!0,value:t}}catch{return{ok:!1,response:aD("INVALID_ARGS","tapOn runtime options must be valid JSON.")}}}(s);if(!l.ok)return l.response;let u=Date.now(),c=(t=e,t.baseReq.flags?.maestro?.optional===!0?3e3:3e4);for(;Date.now()-u<c;){let t=await iy(e,o,l.value??{});if(!t.retry)return t.response;i=t.response,await tp(250)}return r=e,n=o,a=i,r.baseReq.flags?.maestro?.optional===!0?{ok:!0,data:{skipped:!0,optional:!0,selector:n}}:a??aD("COMMAND_FAILED",`tapOn timed out for selector: ${n}`)}async function ip(e){let[t,r="up",n]=e.positionals;if(!t)return aD("INVALID_ARGS","swipe.label requires a label selector.");let a=await iS(e,t,{},"swipe.label",{promoteTapTarget:!1});if(!a.ok)return a.response;let i=function(e,t){let r=tl(e.rect),n=e.frame,a=io(n?.referenceWidth,e.rect.width),i=io(n?.referenceHeight,e.rect.height),o=a7,s=n?n.referenceWidth-o:r.x+a,l=n?n.referenceHeight-o:r.y+i;switch(t.toLowerCase()){case"up":return{ok:!0,start:r,end:{x:r.x,y:ti(r.y-i,o,l)}};case"down":return{ok:!0,start:r,end:{x:r.x,y:ti(r.y+i,o,l)}};case"left":return{ok:!0,start:r,end:{x:ti(r.x-a,o,s),y:r.y}};case"right":return{ok:!0,start:r,end:{x:ti(r.x+a,o,s),y:r.y}};default:return{ok:!1,message:"swipe.label direction must be up, down, left, or right."}}}(a.target,r);return i.ok?await im(e,i,n):aD("INVALID_ARGS",i.message)}async function im(e,t,r){return await e.invoke({...e.baseReq,command:"swipe",positionals:[String(t.start.x),String(t.start.y),String(t.end.x),String(t.end.y),...r?[r]:[]]})}async function ih(e){var t;let r=((t=e.scope)?aM.get(t):void 0)??await iw(e);if(!r)return{ok:!1,response:aD("COMMAND_FAILED","Unable to resolve screen size for Maestro swipe.")};let[n,...a]=e.positionals;return"direction"===n?function(e,t){let[r,n]=e;if(!r)return{ok:!1,response:aD("INVALID_ARGS","Maestro direction swipe requires a direction.")};switch(r){case"up":case"down":var a,i,o;let s;return a=r,i=t,o=n,{ok:!0,start:td({x:(s=ta({direction:a,amount:.6,referenceWidth:i.referenceWidth,referenceHeight:i.referenceHeight})).x1,y:s.y1},i,8),end:td({x:s.x2,y:s.y2},i,8),durationMs:o};default:return{ok:!1,response:aD("INVALID_ARGS","Maestro swipe direction must be UP, DOWN, LEFT, or RIGHT.")}}}(a,r):"percent"===n?function(e,t,r){var n,a,i,o,s;let[l,u,c,d,p]=e,f=[l,u,c,d].map(Number);if(f.some(e=>!Number.isFinite(e)))return{ok:!1,response:aD("INVALID_ARGS","Maestro percentage swipe requires numeric points.")};let[m,h,w,g]=f,y=(n=r,a=m,i=h,o=w,s=g,"android"!==n||i!==s||50!==i||30>Math.abs(o-a)?{startY:i,endY:s}:{startY:65,endY:65});return{ok:!0,start:tn(t,m,y.startY,{marginPx:1}),end:tn(t,w,y.endY,{marginPx:1}),durationMs:p}}(a,r,a$(e.baseReq.flags)):{ok:!1,response:aD("INVALID_ARGS","Maestro screen swipe requires direction or percent.")}}async function iw(e){let t=await ak(e);if(t.ok)return q(aO(t.data))}async function ig(e,t,r,n){let a=await e.invoke({...e.baseReq,command:"wait",positionals:[t,String(n)]});return a.ok||!r?a:await e.invoke({...e.baseReq,command:"find",positionals:[r,"wait",String(n)]})}async function iy(e,t,r){let n=aF(t),a=await iv(e,t,r);return a.response.ok?{retry:!1,response:a.response}:a.targetResolved&&n?await ib(e,n):{retry:!0,response:a.response}}async function iv(e,t,r){let n=await iS(e,t,r,"tapOn",{promoteTapTarget:!0});return n.ok?await iA(e,t,n.target):{response:n.response,targetResolved:!1}}async function iA(e,t,r){var n,a;let i=(n=null!==aF(t),!function(e,t,r){if(!t||r.width<ie)return!1;let n=tt(e.type??"");return!(r.height<it)&&!(r.height>ir)&&("cell"===n||"other"===n||"scrollview"===n||"scroll-area"===n)}(r.node,n,r.rect)?tl(r.rect):{x:to(r.rect.x,Math.min(r.rect.width,ia)),y:to(r.rect.y,Math.min(r.rect.height,ii))});eQ({level:"debug",phase:"maestro_tap_target",data:{selector:t,node:{index:r.node.index,type:r.node.type,label:r.node.label,value:r.node.value,identifier:r.node.identifier,visibleToUser:r.node.visibleToUser},rect:r.rect,point:i}});let o=await e.invoke({...e.baseReq,command:"click",positionals:[String(i.x),String(i.y)],flags:{...e.baseReq.flags,interactionOutcome:{retryOnNoChange:!0}}});return o.ok&&(a=e.scope)&&ax.delete(a),{response:o,targetResolved:!0}}async function ib(e,t){let r=await e.invoke({...e.baseReq,command:"find",positionals:[t,"click"],flags:{...e.baseReq.flags,findFirst:!0,interactionOutcome:{retryOnNoChange:!0}}});return r.ok?{retry:!1,response:r}:{retry:!0,response:r}}async function iS(e,t,r,n,a){let i=await ak(e);if(!i.ok)return{ok:!1,response:i};let o=aO(i.data);if(!o)return{ok:!1,response:aD("COMMAND_FAILED",`Unable to read snapshot data for ${n}.`)};let s=q(o),l=a$(e.baseReq.flags),u=function(e,t,r,n){var a;let i=(a=e.scope)?ax.get(a):void 0;if(!i)return;let o=aL(t,i.selector,r,n);if(o.ok)return eQ({level:"debug",phase:"maestro_preferred_context",data:{selector:i.selector,node:{index:o.node.index,type:o.node.type,label:o.node.label,value:o.node.value,identifier:o.node.identifier},rect:o.rect}}),{node:o.node,rect:o.rect}}(e,o,l,s),c=function(e,t,r,n,a,i={}){let o=aC(e,t,n);if(r.childOf){let t=aC(e,r.childOf,n);if(0===t.length)return{ok:!1,message:`Maestro childOf parent did not match: ${r.childOf}`};let a=e7(e.nodes);o=o.filter(r=>t.some(t=>e3(e.nodes,r,t,a)))}let s=aP({nodes:e.nodes,matches:o,platform:n}),l=aU(e.nodes,s.matches,r.index,aF(t),a,!1,i.promoteTapTarget,i.preferredContext);if(!l){let e=r.index??0;return{ok:!1,message:s.blockedByReactNativeOverlay?`React Native overlay is covering app content: ${t}`:o.length>0&&0===s.matches.length?`Maestro selector matched ${o.length} element(s), but none were visible: ${t}`:`Maestro selector did not match index ${e}: ${t}`}}return{ok:!0,node:l.node,rect:l.rect}}(o,t,r,l,s,{...a,preferredContext:u});if(!c.ok){let e=aF(t);if(e){let t=function(e,t,r,n,a={}){let i=function(e,t){let r=tr(t);if(!r)return[];let n=[],a=[];for(let t of e.nodes){let e=[t.label,e1(t),t.identifier,t.value].filter(e=>!!e).map(e=>tr(e));e.some(e=>e===r)?n.push(t):e.some(e=>e.includes(r))&&a.push(t)}return n.length>0?n:a}(e,t),o=aP({nodes:e.nodes,matches:i,platform:r}),s=aU(e.nodes,o.matches,void 0,t,n,!1,a.promoteTapTarget,a.preferredContext);return s?{ok:!0,node:s.node,rect:s.rect}:{ok:!1,message:`Maestro fuzzy text did not match: ${t}`}}(o,e,l,s,{...a,preferredContext:u});if(t.ok)return{ok:!0,target:{node:t.node,rect:t.rect,frame:s,snapshot:o}}}}return c.ok?{ok:!0,target:{node:c.node,rect:c.rect,frame:s,snapshot:o}}:{ok:!1,response:aD("ELEMENT_NOT_FOUND",c.message,{selector:t,options:r,command:n})}}async function iI(e){switch(e.command){case nG:return await aJ(e);case nj:return await a5(e);case nq:return await i_(e);case nK:return await a6(e);case nB:return await is(e);case nH:return await iu(e);case nW:return await ip(e);case nz:return await id(e);case nJ:return await il(e);case nT:return function(e){let[r]=e.positionals;if(!r)return aD("INVALID_ARGS","runScript requires a file path.");try{let n=function(e){let{scriptPath:r,env:n}=e,a=t.readFileSync(r,"utf8"),i=Object.create(null);try{var o,l;s.runInNewContext(a,(o=n,l=i,{...o,output:l,json:at,http:{post:(e,t)=>(function(e,t,r){let n=eZ(process.execPath,["-e",ae],{stdin:JSON.stringify({method:e,url:t,headers:r?.headers??{},body:r?.body??""}),timeoutMs:3e4,allowFailure:!0});if(0!==n.exitCode){let r;throw new d("COMMAND_FAILED",`Maestro runScript http.${e.toLowerCase()} failed for ${t}: ${(r=n.stderr.trim()).length>0?r.slice(0,1e3):"request process exited without stderr"}`,{exitCode:n.exitCode,stderr:n.stderr})}try{return JSON.parse(n.stdout)}catch(r){throw new d("COMMAND_FAILED",`Maestro runScript http.${e.toLowerCase()} returned invalid JSON for ${t}`,{stdout:n.stdout.slice(0,1e3),stderr:n.stderr.slice(0,1e3)},r instanceof Error?r:void 0)}})("POST",e,t)}}),{filename:r,timeout:3e4})}catch(e){throw new d("COMMAND_FAILED",`Maestro runScript failed for ${r}: ${e instanceof Error?e.message:String(e)}`,{scriptPath:r},e instanceof Error?e:void 0)}return function(e,t){for(let r of Object.keys(e))if(r.includes("."))throw new d("INVALID_ARGS",`Maestro runScript output key cannot contain ".": ${r}`,{scriptPath:t,key:r})}(i,r),Object.fromEntries(Object.entries(i).map(([e,t])=>{var r;return[`output.${e}`,(r=t,"string"==typeof r?r:"number"==typeof r||"boolean"==typeof r?String(r):JSON.stringify(r))]}))}({scriptPath:r,env:{...e.scope.values,...e.baseReq.flags?.maestro?.runScriptEnv??{}}});return{ok:!0,data:{outputEnv:n}}}catch(t){let e=u(t);return aD(e.code,e.message,e.details)}}(e);default:return}}async function i_(e){let t=await e.invoke({...e.baseReq,command:"keyboard",positionals:["enter"]});return t.ok?t:await e.invoke({...e.baseReq,command:"type",positionals:["\n"]})}async function iN(e){for(let[t,r]of e.actions.entries()){let n=await e.invokeReplayAction({action:r,line:e.line,step:e.step+t/1e3});if(!n.ok)return n}return{ok:!0,data:{ran:e.actions.length}}}async function iM(e){let t;for(let r=0;r<=e.maxRetries;r+=1){let n=await iN({actions:e.actions,line:e.line,step:e.step+r,invokeReplayAction:e.invokeReplayAction});if(n.ok)return{ok:!0,data:{attempts:r+1,retried:r>0}};t=n}return t??{ok:!1,error:{code:"COMMAND_FAILED",message:"retry commands failed."}}}async function ix(e){let t=await iD(e,e.control);return t.ok?t.matched?await iR(e):{ok:!0,data:{skipped:!0,condition:e.control.mode,selector:e.control.selector}}:t.response}async function iD(e,t){if("visible"===t.mode)return await ik(e,t);let r=await ak(e);if(!r.ok)return{ok:!1,response:r};let n=iO(e,t.selector,r);return n.ok?{ok:!0,matched:!n.matched}:{ok:!1,response:n.response}}async function ik(e,t){let r=Date.now();for(;;){let n=await ak(e);if(!n.ok)return{ok:!1,response:n};let a=iO(e,t.selector,n);if(!a.ok)return{ok:!1,response:a.response};if(a.matched)return{ok:!0,matched:!0};if(Date.now()-r>=3e3)return{ok:!0,matched:!1};await tp(250)}}function iO(e,t,r){let n=aO(r.data);return n?{ok:!0,matched:aL(n,t,a$(e.baseReq.flags),q(n)).ok}:{ok:!1,response:aD("COMMAND_FAILED","Unable to read snapshot data for runFlow.when.")}}async function iR(e){let t=await iN({actions:e.control.actions,line:e.line,step:e.step,invokeReplayAction:e.invokeReplayAction});return t.ok?{ok:!0,data:{ran:t.data?.ran,condition:e.control.mode,selector:e.control.selector}}:t}async function iL(e){var t;let{req:r,sessionName:n,action:a,scope:i,filePath:o,line:s,step:l,tracePath:u,invoke:c}=e,d=(t={file:o,line:s},{...a,positionals:(a.positionals??[]).map(e=>nm(e,i,t)),flags:nh(a.flags,i,t)??{},runtime:nh(a.runtime,i,t),replayControl:function(e,t,r){if(!e)return e;if(e.kind==="maestroRunFlowWhen"){return{...e,selector:nm(e.selector,t,r)}}return e}(a.replayControl,i,t)}),p=Date.now();iF(u,{type:"replay_action_start",ts:new Date(p).toISOString(),replayPath:o,line:s,step:l,command:d.command,positionals:d.positionals??[]});let f=await iP({req:r,sessionName:n,resolved:d,scope:i,line:s,step:l,invoke:c,invokeReplayAction:e=>iL({req:r,sessionName:n,action:e.action,scope:i,filePath:o,line:e.line,step:e.step,tracePath:u,invoke:c})}),m=Date.now();return iF(u,{type:"replay_action_stop",ts:new Date(m).toISOString(),replayPath:o,line:s,step:l,command:d.command,ok:f.ok,durationMs:m-p,resultTiming:f.ok?function(e){if(!e||"object"!=typeof e||Array.isArray(e))return;let t=e.timing;if(!(!t||"object"!=typeof t||Array.isArray(t)))return Object.fromEntries(Object.entries(t).filter(([,e])=>{let t=typeof e;return"number"===t||"string"===t||"boolean"===t}))}(f.data):void 0,errorCode:f.ok?void 0:f.error.code}),f}async function iP(e){var t;let{req:r,sessionName:n,resolved:a,scope:i,line:o,step:s,invoke:l,invokeReplayAction:u}=e,c=(t=r.flags,eW(t,{...a.flags??{}})),d={token:r.token,session:n,flags:c,runtime:a.runtime,meta:r.meta},p=await i$({control:a.replayControl,baseReq:d,line:o,step:s,invoke:l,invokeReplayAction:u})??await iI({command:a.command,baseReq:d,positionals:a.positionals??[],scope:i,line:o,step:s,invoke:l,invokeReplayAction:u})??await l({...d,command:a.command,positionals:a.positionals??[]});if(p.ok){let e=function(e){if(!e||"object"!=typeof e)return null;let t=e.outputEnv;if(!t||"object"!=typeof t||Array.isArray(t))return null;let r=Object.entries(t).filter(e=>"string"==typeof e[1]);return r.length>0?Object.fromEntries(r):null}(p.data);e&&Object.assign(i.values,e)}return p}async function i$(e){let{control:t,baseReq:r,line:n,step:a,invoke:i,invokeReplayAction:o}=e;if(t){switch(t.kind){case"retry":return await iM({actions:t.actions,maxRetries:t.maxRetries,line:n,step:a,invokeReplayAction:o});case"maestroRunFlowWhen":return await ix({baseReq:r,control:t,line:n,step:a,invoke:i,invokeReplayAction:o})}return t}}function iF(e,r){e&&t.appendFileSync(e,`${JSON.stringify(r)}
|
|
27
|
+
`;t.writeFileSync(p,f),r.ok||t.writeFileSync(a.join(l,"failure.txt"),f)}({response:A,filePath:s.path,sessionName:o,attempts:I,maxAttempts:f+1,attemptArtifactsDir:d}),i=A,S=o,A.ok||(N.push({attempt:I,message:A.error.message,durationMs:_}),am(A)||e>=f))break;ex({type:"replay-test",file:s.path,title:s.title,status:"fail",index:w,total:g,attempt:I,maxAttempts:f+1,durationMs:_,retrying:!0,message:A.error.message})}let M=Date.now()-A;if(i?.ok)return ex({type:"replay-test",file:s.path,title:s.title,status:"pass",index:w,total:g,attempt:I,maxAttempts:f+1,durationMs:M,artifactsDir:b}),{file:s.path,title:s.title,session:S,status:"passed",durationMs:M,finalAttemptDurationMs:_,attempts:I,artifactsDir:b,replayed:"number"==typeof i.data?.replayed?i.data.replayed:0,healed:"number"==typeof i.data?.healed?i.data.healed:0,...N.length>0?{attemptFailures:N}:{}};let x=i?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:i?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return ex({type:"replay-test",file:s.path,title:s.title,status:"fail",index:w,total:g,attempt:I,maxAttempts:f+1,durationMs:M,artifactsDir:b,message:x.message}),{file:s.path,title:s.title,session:S,status:"failed",durationMs:M,attempts:I,artifactsDir:b,error:x}}let ab={maestro:{parse:function(e,t={}){var r;let n;return as(e,(n=(r=t).visitedPaths??new Set,r.sourcePath&&n.add(a.resolve(r.sourcePath)),{baseDir:r.sourcePath?a.dirname(r.sourcePath):void 0,platform:function(e){if(e){let t;return"android"===(t=e.trim().toLowerCase())?"android":"ios"===t?"ios":void 0}}(r.platform),env:{},envOverrides:r.env??{},visitedPaths:n}))}}};function aS(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=void 0!==t&&/^\d+$/.test(t)?t:null,n=e0(null!==r?e.slice(0,-1):e.slice());return!n||n.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:n.selectorExpression,selectorTimeout:r}}async function aI(e){let{action:t,sessionName:r,logPath:n,sessionStore:a}=e;if(!(_(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let i=a.get(r);if(!i)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),_(e.command)){let r=function(e){let t=e.positionals??[];if("longpress"!==e.command)return t;let r=t.at(-1);return t.length>1&&a_(r)?t.slice(0,-1):t}(e),n=r[0]??"";n&&!n.startsWith("@")&&t.push(r.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}=e5(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=aS(e.positionals??[]);r&&t.push(r)}return C(t).filter(e=>e.trim().length>0)})(t).map(e=>e6(e)).filter(e=>null!==e);if(0===o.length)return null;let s=_(t.command)||"fill"===t.command,l=_(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",u=await aN(i,t,n,s,a);for(let e of o){let r=e9(u.nodes,e,{platform:i.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let n=e4(r.node,i.device.platform,{action:"fill"===t.command?"fill":_(t.command)?"click":"get"}).join(" || ");if(_(t.command))return{...t,positionals:"longpress"===t.command?function(e,t){let r="number"==typeof e.result?.durationMs?String(e.result.durationMs):function(e){let t=e.at(-1);return e.length>1&&a_(t)?t:void 0}(e.positionals??[]);return r?[t,r]:[t]}(t,n):[n]};if("fill"===t.command){let e=A(t);if(!e)continue;return{...t,positionals:[n,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,n]}}if("is"===t.command){let{predicate:e,split:r}=e5(t.positionals);if(!e)continue;let a=r?.rest.join(" ").trim()??"",i=[e,n];return"text"===e&&a.length>0&&i.push(a),{...t,positionals:i}}if("wait"===t.command){let{selectorTimeout:e}=aS(t.positionals??[]),r=[n];return e&&r.push(e),{...t,positionals:r}}}return null}function a_(e){return void 0!==e&&""!==e.trim()&&Number.isFinite(Number(e))}async function aN(e,t,r,n,a){let i=X(await m(e.device,"snapshot",[],t.flags?.out,{...Y(r,{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n},e.appBundleId,e.trace?.outPath)}),{...t.flags??{},snapshotInteractiveOnly:n,snapshotCompact:n});return j(e,i),a.set(e.name,e),i}let aM=new WeakMap,ax=new WeakMap;function aD(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}async function ak(e){var t;let r,n=await e.invoke({...e.baseReq,command:"snapshot",positionals:[],flags:{...e.baseReq.flags,noRecord:!0,snapshotRaw:!0,snapshotForceFull:!0}});return n.ok&&e.scope&&(t=e.scope,(r=q(aO(n.data)))&&aM.set(t,r)),n}function aO(e){if("object"==typeof e&&null!==e&&Array.isArray(e.nodes))return e}let aR=new Map([["button",0],["link",0],["textfield",0],["textview",0],["searchfield",0],["switch",0],["slider",0],["cell",1],["statictext",2]]);function aL(e,t,r,n){let a=aC(e,t,r,{allowLeadingCompositeLabelMatch:!1}),i=aP({nodes:e.nodes,matches:a,platform:r}),o=aU(e.nodes,i.matches,void 0,aF(t),n,!0);return o?{ok:!0,node:o.node,rect:o.rect,matches:i.matches.length}:{ok:!1,message:i.blockedByReactNativeOverlay?`React Native overlay is covering app content: ${t}`:a.length>0?`Maestro selector matched ${a.length} element(s), but none were visible: ${t}`:`Maestro selector did not match: ${t}`}}function aP(e){let t=e.matches.filter(t=>ts({predicate:"visible",node:t,nodes:e.nodes,platform:e.platform}).pass),r=function(e,t,r){let n=tc(e);if(!n.detected||!n.redBox)return{matches:t,blockedByReactNativeOverlay:!1};let a=tu(n),i=a.filter(t=>ts({predicate:"visible",node:t,nodes:e,platform:r}).pass);if(0===i.length)return 0===a.length?{matches:[],blockedByReactNativeOverlay:!0}:{matches:t,blockedByReactNativeOverlay:!1};let o=new Set(i.map(e=>e.index)),s=t.filter(e=>o.has(e.index));return{matches:s,blockedByReactNativeOverlay:t.length>0&&0===s.length}}(e.nodes,t,e.platform);return{matches:r.matches,blockedByReactNativeOverlay:r.blockedByReactNativeOverlay}}function a$(e){return e?.platform==="android"?"android":"ios"}function aF(e){let t=e8(e).selectors.flatMap(e=>e.terms);if(0===t.length||!t.some(e=>"label"===e.key||"text"===e.key)||!t.every(e=>["label","text","id"].includes(e.key)))return null;let r=t.map(e=>"string"==typeof e.value?e.value:""),n=r[0];return n&&r.every(e=>e===n)?n:null}function aC(e,t,r,n={}){for(let a of e8(t).selectors){let t=e.nodes.filter(e=>(function(e,t,r,n){return!!te(e,t,r)||t.terms.every(t=>(function(e,t,r,n){var a,i,o;return"string"!=typeof t.value||"id"!==(a=t.key)&&"label"!==a&&"text"!==a&&"value"!==a?te(e,{raw:t.key,terms:[t]},r):aE((i=e,"id"===(o=t.key)?i.identifier:"label"===o?i.label:"value"===o?i.value:e1(i)),t.value,n)})(e,t,r,n))})(e,a,r,n));if(t.length>0)return t}return[]}function aE(e,t,r={}){var n;let a=e??"",i=tr(a),o=tr(t);if(i===o||!1!==r.allowLeadingCompositeLabelMatch&&function(e,t){if(!e||!t||!e.startsWith(t))return!1;let r=e.at(t.length);return","===r||":"===r||";"===r}(i,o))return!0;if(n=t,!/(?:\.\*|\.\+|\[[^\]]+\]|\([^)]*\)|\||\^|\$|\\[dDsSwWbB])/.test(n))return!1;try{return new RegExp(t).test(a)}catch{return!1}}function aV(e,t,r){if(t.rect&&t.rect.width>0&&t.rect.height>0)return{rect:t.rect,inherited:!1};if(t.rect)return null;let n=function(e,t,r){let n=t;for(;"number"==typeof n.parentIndex&&(n=r.get(n.parentIndex)??e[n.parentIndex]);)if(n.rect)return n.rect.width>0&&n.rect.height>0?n.rect:null;return null}(e,t,r);return n?{rect:n,inherited:!0}:null}function aU(e,t,r,n,a,i=!1,o=!1,s){var l,u,c,d,p,f,m,h,w,g,y,v,A,b,S,I,_,N,M;let x,D,k,O,R=e7(e),L=(l=e,u=t,c=R,d=n,p=r,f=a,m=i,k=(D=(x=u.map(e=>{var t;let r;return(r=aV(l,t=e,c))?{node:t,rect:r.rect,inheritedRect:r.inherited}:null}).filter(e=>!!e)).filter(e=>!e.inheritedRect)).length>0?D:x,d&&void 0===p?(h=k,w=f,g=m,O=h.filter(e=>{var t,r;let n,a;return t=e.rect,r=w,n=r?.referenceWidth??1/0,a=r?.referenceHeight??1/0,t.x<n&&t.y<a&&t.x+t.width>0&&t.y+t.height>0}),g||O.length>0?O:h):x),P=function(e,t,r,n,a,i){var o,s,l,u,c,d,p;if(void 0!==r)return t[r]??null;let f=(o=e,s=t,l=n,u=a,c=i,u&&l?function(e,t,r,n){let a=t.filter(e=>0===az(e.node,r));if(a.length>=2){let t=aG(e,a,r,n);if(t)return t}let i=t.filter(e=>1===az(e.node,r));return a.length>0||i.length<2?null:aG(e,i,r,n)}(o,s,l,c)??aT(o,s,l,c):aT(o,s,l,c));return(d=f,p=n,a&&p&&d)?function(e,t,r){var n,a,i,o,s,l,u,c,d,p,f,m,h,w,g,y,v;let A,b,S,I,_,N,M,x;if(n=t,a=r,!(("other"===(A=tt(n.node.type??""))||"scrollview"===A||"scroll-area"===A)&&!(n.rect.width<120)&&!(n.rect.height<32)&&!(n.rect.height>80)&&1>=az(n.node,a)))return null;let D=(i=e,o=t,s=r,i.filter(e=>{var t,r,n,a,i;let l,u;return e.parentIndex===o.node.index&&!!e.rect&&(t=e,r=o.rect,n=s,!("button"!==(l=tt(t.type??""))&&"cell"!==l&&"other"!==l||1>=az(t,n))&&!(t.rect.width<16)&&!(t.rect.height<16)&&!!aH(r,t.rect)&&(a=r,i=t.rect,u=Math.max(a.y,i.y),Math.max(0,Math.min(a.y+a.height,i.y+i.height)-u)/Math.max(1,Math.min(a.height,i.height))>=.5))}).sort((e,t)=>e.rect.x-t.rect.x));if(0===D.length)return null;let k=(S=Math.floor((b=[...D.map(e=>e.rect.width)].sort((e,t)=>e-t)).length/2),b[S]??0),O=function(e,t){let r=[],n=e.x,a=e.x+e.width;for(let i of t){let t=Math.max(e.x,i.x),o=Math.min(a,i.x+i.width);t>n&&r.push({x:n,width:t-n}),n=Math.max(n,o)}return a>n&&r.push({x:n,width:a-n}),r}(t.rect,D.map(e=>e.rect)),R=(l=t,u=r,c=O,d=k,N=c.filter(e=>{var t,r;return t=e.width,r=d,!(t<24)&&!(r<24)&&t>=.4*r&&t<=1.6*r}),M=(p=l,f=u,I=c.find(e=>1>Math.abs(e.x-p.rect.x)),_=Math.max(48,Math.min(220,8*f.length+24)),(m=p,h=f,w=I,g=_,w&&"scrollview"===tt(m.node.type??"")&&1>=az(m.node,h)&&m.rect.width>=240&&m.rect.height>=32&&m.rect.height<=80&&w.width<=.55*m.rect.width&&w.width>=.6*g)?{x:p.rect.x,width:Math.min(_,I.width)}:null),x=N.some(e=>{var t;return t=l.rect,1>Math.abs(e.x-t.x)}),M&&!x?M:1===N.length?N[0]??null:M);return R?(y=t,v=R,{...y,rect:{x:v.x,y:y.rect.y,width:v.width,height:y.rect.height}}):null}(e,f,n)??f:f}(e,L,r,n,o,s);return y=e,v=P,A=R,b=o,S=a,v?b?(I=y,_=v,N=A,M=S,(aB(_.node)?null:e2(I,_.node,N,e=>{if(!aB(e))return null;let t=aV(I,e,N);return t&&function(e,t,r){if(!aH(t,e))return!1;let n=aq(t),a=aq(e);if(a>0&&n>30*a)return!1;if(r){let e=r.referenceWidth*r.referenceHeight;if(e>0&&n>.5*e)return!1}return!0}(_.rect,t.rect,M)?{node:e,rect:t.rect}:null}))??{node:v.node,rect:v.rect}):{node:v.node,rect:v.rect}:null}function aT(e,t,r,n){return(function(e,t,r,n){var a;let i,o,s;if(!r||t.length<2)return t;let l=t.filter(e=>0===az(e.node,r));if(l.length<2)return t;let u=e7(e),c=l.map(t=>({candidate:t,container:aj(e,t.node,u)})).filter(e=>!!e.container);if(c.length<2||c.length!==l.length)return t;let d=c.filter(e=>{var t;return t=e,c.some(e=>e!==t&&t.container.index!==e.container.index&&aW(t.container.rect,e.container.rect)>=.6)});if(d.length<2)return t;let p=(o=Math.max(...i=(a=d).map(e=>aq(e.container.rect))),(s=Math.min(...i))<=0||o<1.2*s?[]:a.filter(e=>aq(e.container.rect)===o).map(e=>e.candidate));if(p.length>0)return p;let f=function(e,t,r,n){if(!r)return[];let a=aj(e,r.node,n),i=a&&aH(a.rect,r.rect)?a:null,o=t.map(e=>({entry:e,score:function(e,t,r){if(r)return e.index===r.index?0:.6>aW(e.rect,r.rect)?1/0:Math.abs(e.index-r.index);if(aW(e.rect,t.rect)>=.6)return 0;let n=e.index-t.node.index;return n>=0?n:1e5+Math.abs(n)}(e.container,r,i)})),s=Math.min(...o.map(e=>e.score));return Number.isFinite(s)?o.filter(e=>e.score===s).map(e=>e.entry.candidate):[]}(e,d,n,u);if(f.length>0)return f;let m=Math.max(...d.map(e=>e.container.index)),h=d.filter(e=>e.container.index===m).map(e=>e.candidate);return h.length>0?h:t})(e,t,r,n).sort((e,t)=>(function(e,t,r){var n,a;let i=function(e,t,r){if(r){let n=az(e.node,r)-az(t.node,r);if(0!==n)return n}let n=aK(e.node)-aK(t.node);if(0!==n)return n;let a=Number(e.inheritedRect)-Number(t.inheritedRect);if(0!==a)return a;let i=r&&aK(e.node)===aK(t.node)?aq(t.rect)-aq(e.rect):aq(e.rect)-aq(t.rect);return 0!==i?i:0}(e,t,r);if(0!==i)return i;if(n=e.rect,a=t.rect,Math.round(n.x)!==Math.round(a.x)||Math.round(n.y)!==Math.round(a.y)||Math.round(n.width)!==Math.round(a.width)||Math.round(n.height)!==Math.round(a.height))return e.node.index-t.node.index;let o=(t.node.depth??0)-(e.node.depth??0);return 0!==o?o:t.node.index-e.node.index})(e,t,r))[0]??null}function aG(e,t,r,n){let a=e7(e),i=t.filter(r=>{var n;return(n=r).rect.width>=16&&n.rect.width<=260&&n.rect.height>=24&&n.rect.height<=80&&t.some(t=>{var n,i,o,s;return n=e,i=t,o=r,s=a,!(i.node.index===o.node.index||!aH(i.rect,o.rect)||aq(i.rect)<2*aq(o.rect))&&e3(n,o.node,i.node,s)})});return aT(e,i,r,n)}function aj(e,t,r){return e2(e,t,r,e=>{let t;return!e.rect||"scrollview"!==(t=tt(e.type??""))&&"scroll-area"!==t&&"list"!==t||e.rect.width<240||e.rect.height<320?null:e})}function aq(e){return e.width*e.height}function aK(e){return aR.get(tt(e.type??""))??3}function aB(e){let t=tt(e.type??"");return!0===e.hittable||"button"===t||"link"===t||"cell"===t||"textfield"===t||"searchfield"===t||"switch"===t||"slider"===t}function aH(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 aW(e,t){let r=Math.max(e.x,t.x),n=Math.min(e.x+e.width,t.x+t.width),a=Math.max(e.y,t.y);return Math.max(0,n-r)*Math.max(0,Math.min(e.y+e.height,t.y+t.height)-a)/Math.max(1,Math.min(aq(e),aq(t)))}function az(e,t){let r=[e.label,e1(e),e.identifier,e.value].filter(e=>!!e);return r.some(e=>e===t)?0:r.some(e=>tr(e)===tr(t))?1:r.some(e=>aE(e,t))?2:3}async function aJ(e){var t,r,n;let a=aQ(e.positionals,{command:"assertVisible",defaultTimeoutMs:7e3});if(!a.ok)return a.response;let i=(t=e.baseReq,r=a.selector,n=a.timeoutMs,t.flags?.platform!=="ios"||t.flags?.maestro?.allowAlreadyPastLoading===!0||n<3e4?null:aF(r));return i?await aX(e,a,i):await aZ(e,a)}async function aX(e,t,r){let n=Date.now(),a=await aY(e,t,r);return a.ok?a3({ok:!0,data:{selector:t.selector,nativeWait:!0,query:r,response:a.data}},t.selector,n):a}async function aY(e,t,r){return await e.invoke({...e.baseReq,command:"wait",positionals:[r,String(t.timeoutMs)]})}async function aZ(e,t){let r,n=Date.now(),a=t.timeoutMs+1e3,i=!1;for(;;){let o=Date.now(),s=await a0(e,t.selector,"assertVisible");if(s.visible)return a3(s.response,t.selector,n);r=s.response;let l=function(e,t,r,n){var a,i,o,s,l,u,c;return!(a=r.response).ok&&"COMMAND_FAILED"===a.error.code&&a.error.message.includes("React Native overlay")?{kind:"return",response:r.response}:(i=e,o=t.selector,s=r.snapshot,i.flags?.maestro?.allowAlreadyPastLoading===!0&&void 0!==s&&function(e,t){let r=a1(aF(e));if(!a2(r))return!1;let n=t.nodes.flatMap(e=>[e.label,e.value,e.identifier]).filter(e=>!!e?.trim()).map(e=>a1(e));return!n.some(e=>e.includes("something went wrong"))&&n.some(e=>e!==r&&!a2(e))}(o,s))?{kind:"return",response:(l=t.selector,u=t.timeoutMs,c=n,{ok:!0,data:{selector:l,alreadyPastLoading:!0,waitedMs:Date.now()-c,timeoutMs:u}})}:{kind:"continue"}}(e.baseReq,t,s,n);if("return"===l.kind)return l.response;let u=function(e){var t,r,n,a;return Date.now()-e.startedAt<e.deadlineMs?"wait":(t=e.capturedAfterDeadline,r=e.captureStartedAt,n=e.startedAt,a=e.deadlineMs,!t&&r-n<a)?"capture-again":"finish"}({captureStartedAt:o,capturedAfterDeadline:i,startedAt:n,deadlineMs:a});if("capture-again"===u){i=!0;continue}if("finish"===u)break;await tp(250)}return r??aD("COMMAND_FAILED",`Expected visible but did not match: ${t.selector}`,{selector:t.selector,timeoutMs:t.timeoutMs})}function aQ(e,t){let[r,n=String(t.defaultTimeoutMs)]=e;if(!r)return{ok:!1,response:aD("INVALID_ARGS",`${t.command} requires a selector.`)};let a=Number(n);return!Number.isFinite(a)||a<0?{ok:!1,response:aD("INVALID_ARGS",`${t.command} timeout must be a non-negative number.`)}:{ok:!0,selector:r,timeoutMs:a}}async function a0(e,t,r){var n;let a=await ak(e);if(!a.ok)return{visible:!1,response:a,infrastructureFailure:!0};let i=aO(a.data);if(!i)return{visible:!1,response:aD("COMMAND_FAILED",`Unable to read snapshot data for ${r}.`),infrastructureFailure:!0};let o=aL(i,t,a$(e.baseReq.flags),q(i));return o.ok?(n=e.scope,n&&ax.set(n,{selector:t}),{visible:!0,response:{ok:!0,data:{selector:t,matches:o.matches,nodeIndex:o.node.index,nodeType:o.node.type,nodeLabel:o.node.label,nodeIdentifier:o.node.identifier,rect:o.rect}}}):{visible:!1,response:aD("COMMAND_FAILED",o.message,{selector:t}),infrastructureFailure:!1,snapshot:i}}function a1(e){return e?.trim().toLowerCase().replace(/\u2026/g,"...")??""}function a2(e){return"loading"===e||"loading..."===e}function a3(e,t,r){return e.ok?{ok:!0,data:{selector:t,...e.data,waitedMs:Date.now()-r}}:e}async function a5(e){let t,r=aQ(e.positionals,{command:"assertNotVisible",defaultTimeoutMs:3e3});if(!r.ok)return r.response;let n=Date.now(),a=0;for(;Date.now()-n<=r.timeoutMs;){let i=await a0(e,r.selector,"assertNotVisible");if(!i.visible&&i.infrastructureFailure)return i.response;if(i.visible)a=0,t=i.response;else{a+=1;let e=Date.now()-n;if(a>=2||e>=r.timeoutMs)return{ok:!0,data:{pass:!0,selector:r.selector,stableSamples:a,waitedMs:e,timeoutMs:r.timeoutMs}}}await tp(250)}return a>0?{ok:!0,data:{pass:!0,selector:r.selector,stableSamples:a,waitedMs:Date.now()-n,timeoutMs:r.timeoutMs}}:aD("COMMAND_FAILED",`Expected not visible but matched: ${r.selector}`,{selector:r.selector,timeoutMs:r.timeoutMs,lastResponse:t})}async function a6(e){let t,r,n=Number(e.positionals[0]??15e3);if(!Number.isFinite(n)||n<0)return aD("INVALID_ARGS","waitForAnimationToEnd timeout must be a number.");let a=Date.now();for(;Date.now()-a<n;){let a=await ak(e),i=function(e,t,r){let n=function(e){if(!e.ok)return null;let t=aO(e.data);return t?JSON.stringify(t.nodes.map(e=>({index:e.index,parentIndex:e.parentIndex,type:e.type,identifier:e.identifier,label:e.label,value:e.value,rect:e.rect?{x:Math.round(e.rect.x),y:Math.round(e.rect.y),width:Math.round(e.rect.width),height:Math.round(e.rect.height)}:void 0}))):null}(e);return e.ok?n?t===n?{done:!0,response:{ok:!0,data:{stable:!0,timeoutMs:r}}}:{done:!1,signature:n}:{done:!0,response:e}:{done:!1}}(a,t,n);if(i.done)return i.response;t=i.signature??t,r=a,await tp(250)}return r?.ok===!1?r:{ok:!0,data:{stable:!1,timeoutMs:n}}}let a8=.35,a9=120,a4=360,a7=8,ie=120,it=70,ir=200,ia=168,ii=48;function io(e,t){return Math.round(Math.min(a4,Math.max(a9,"number"==typeof e?e*a8:0,1.5*t)))}async function is(e){var t,r,n;let[a,i="5000",o="down"]=e.positionals;if(!a)return aD("INVALID_ARGS","scrollUntilVisible requires a selector.");let s=Number(i);if(!Number.isFinite(s)||s<=0)return aD("INVALID_ARGS","scrollUntilVisible timeout must be a positive number.");let l=aF(a),u=Math.max(1,Math.ceil(s/500)),c=null;for(let t=0;t<u;t+=1){let r=await ig(e,a,l,Math.min(500,Math.max(1,s-500*t)));if(r.ok)return r;if(c=r,t===u-1)break;let n=await e.invoke({...e.baseReq,command:"scroll",positionals:[o]});if(!n.ok)return n}return t=c,r=a,n=s,t?{ok:!1,error:{...t.error,message:`scrollUntilVisible timed out after ${n}ms for selector: ${r}. Last wait: ${t.error.message}`}}:aD("COMMAND_FAILED",`scrollUntilVisible timed out after ${n}ms for selector: ${r}`)}async function il(e){let[t,r]=e.positionals,n=Number(t),a=Number(r);if(!Number.isFinite(n)||!Number.isFinite(a))return aD("INVALID_ARGS","tapOn percentage point requires numeric x/y values.");let i=await ak(e);if(!i.ok)return i;let o=aO(i.data);if(!o)return aD("COMMAND_FAILED","Unable to read snapshot data for Maestro percentage point tap.");let s=q(o);if(!s)return aD("COMMAND_FAILED","Unable to resolve screen size for Maestro percentage point tap.");let l=tn(s,n,a);return await e.invoke({...e.baseReq,command:"click",positionals:[String(l.x),String(l.y)]})}async function iu(e){let t=await ic(e);if(t)return t;let r=await ih(e);return r.ok?await im(e,r,r.durationMs):r.response}async function ic(e){let[t,r,n]=e.positionals;if("direction"===t&&("left"===r||"right"===r))return await e.invoke({...e.baseReq,command:"gesture",positionals:["swipe",r,...n?[n]:[]]})}async function id(e){var t,r,n,a;let i,[o,s]=e.positionals;if(!o)return aD("INVALID_ARGS","tapOn requires a selector.");let l=function(e){if(!e)return{ok:!0,value:null};try{let t=JSON.parse(e);return{ok:!0,value:t}}catch{return{ok:!1,response:aD("INVALID_ARGS","tapOn runtime options must be valid JSON.")}}}(s);if(!l.ok)return l.response;let u=Date.now(),c=(t=e,t.baseReq.flags?.maestro?.optional===!0?3e3:3e4);for(;Date.now()-u<c;){let t=await iy(e,o,l.value??{});if(!t.retry)return t.response;i=t.response,await tp(250)}return r=e,n=o,a=i,r.baseReq.flags?.maestro?.optional===!0?{ok:!0,data:{skipped:!0,optional:!0,selector:n}}:a??aD("COMMAND_FAILED",`tapOn timed out for selector: ${n}`)}async function ip(e){let[t,r="up",n]=e.positionals;if(!t)return aD("INVALID_ARGS","swipe.label requires a label selector.");let a=await iS(e,t,{},"swipe.label",{promoteTapTarget:!1});if(!a.ok)return a.response;let i=function(e,t){let r=tl(e.rect),n=e.frame,a=io(n?.referenceWidth,e.rect.width),i=io(n?.referenceHeight,e.rect.height),o=a7,s=n?n.referenceWidth-o:r.x+a,l=n?n.referenceHeight-o:r.y+i;switch(t.toLowerCase()){case"up":return{ok:!0,start:r,end:{x:r.x,y:ti(r.y-i,o,l)}};case"down":return{ok:!0,start:r,end:{x:r.x,y:ti(r.y+i,o,l)}};case"left":return{ok:!0,start:r,end:{x:ti(r.x-a,o,s),y:r.y}};case"right":return{ok:!0,start:r,end:{x:ti(r.x+a,o,s),y:r.y}};default:return{ok:!1,message:"swipe.label direction must be up, down, left, or right."}}}(a.target,r);return i.ok?await im(e,i,n):aD("INVALID_ARGS",i.message)}async function im(e,t,r){return await e.invoke({...e.baseReq,command:"swipe",positionals:[String(t.start.x),String(t.start.y),String(t.end.x),String(t.end.y),...r?[r]:[]]})}async function ih(e){var t;let r=((t=e.scope)?aM.get(t):void 0)??await iw(e);if(!r)return{ok:!1,response:aD("COMMAND_FAILED","Unable to resolve screen size for Maestro swipe.")};let[n,...a]=e.positionals;return"direction"===n?function(e,t){let[r,n]=e;if(!r)return{ok:!1,response:aD("INVALID_ARGS","Maestro direction swipe requires a direction.")};switch(r){case"up":case"down":var a,i,o;let s;return a=r,i=t,o=n,{ok:!0,start:td({x:(s=ta({direction:a,amount:.6,referenceWidth:i.referenceWidth,referenceHeight:i.referenceHeight})).x1,y:s.y1},i,8),end:td({x:s.x2,y:s.y2},i,8),durationMs:o};default:return{ok:!1,response:aD("INVALID_ARGS","Maestro swipe direction must be UP, DOWN, LEFT, or RIGHT.")}}}(a,r):"percent"===n?function(e,t,r){var n,a,i,o,s;let[l,u,c,d,p]=e,f=[l,u,c,d].map(Number);if(f.some(e=>!Number.isFinite(e)))return{ok:!1,response:aD("INVALID_ARGS","Maestro percentage swipe requires numeric points.")};let[m,h,w,g]=f,y=(n=r,a=m,i=h,o=w,s=g,"android"!==n||i!==s||50!==i||30>Math.abs(o-a)?{startY:i,endY:s}:{startY:65,endY:65});return{ok:!0,start:tn(t,m,y.startY,{marginPx:1}),end:tn(t,w,y.endY,{marginPx:1}),durationMs:p}}(a,r,a$(e.baseReq.flags)):{ok:!1,response:aD("INVALID_ARGS","Maestro screen swipe requires direction or percent.")}}async function iw(e){let t=await ak(e);if(t.ok)return q(aO(t.data))}async function ig(e,t,r,n){let a=await e.invoke({...e.baseReq,command:"wait",positionals:[t,String(n)]});return a.ok||!r?a:await e.invoke({...e.baseReq,command:"find",positionals:[r,"wait",String(n)]})}async function iy(e,t,r){let n=aF(t),a=await iv(e,t,r);return a.response.ok?{retry:!1,response:a.response}:a.targetResolved&&n?await ib(e,n):{retry:!0,response:a.response}}async function iv(e,t,r){let n=await iS(e,t,r,"tapOn",{promoteTapTarget:!0});return n.ok?await iA(e,t,n.target):{response:n.response,targetResolved:!1}}async function iA(e,t,r){var n,a;let i=(n=null!==aF(t),!function(e,t,r){if(!t||r.width<ie)return!1;let n=tt(e.type??"");return!(r.height<it)&&!(r.height>ir)&&("cell"===n||"other"===n||"scrollview"===n||"scroll-area"===n)}(r.node,n,r.rect)?tl(r.rect):{x:to(r.rect.x,Math.min(r.rect.width,ia)),y:to(r.rect.y,Math.min(r.rect.height,ii))});eQ({level:"debug",phase:"maestro_tap_target",data:{selector:t,node:{index:r.node.index,type:r.node.type,label:r.node.label,value:r.node.value,identifier:r.node.identifier,visibleToUser:r.node.visibleToUser},rect:r.rect,point:i}});let o=await e.invoke({...e.baseReq,command:"click",positionals:[String(i.x),String(i.y)],flags:{...e.baseReq.flags,interactionOutcome:{retryOnNoChange:!0}}});return o.ok&&(a=e.scope)&&ax.delete(a),{response:o,targetResolved:!0}}async function ib(e,t){let r=await e.invoke({...e.baseReq,command:"find",positionals:[t,"click"],flags:{...e.baseReq.flags,findFirst:!0,interactionOutcome:{retryOnNoChange:!0}}});return r.ok?{retry:!1,response:r}:{retry:!0,response:r}}async function iS(e,t,r,n,a){let i=await ak(e);if(!i.ok)return{ok:!1,response:i};let o=aO(i.data);if(!o)return{ok:!1,response:aD("COMMAND_FAILED",`Unable to read snapshot data for ${n}.`)};let s=q(o),l=a$(e.baseReq.flags),u=function(e,t,r,n){var a;let i=(a=e.scope)?ax.get(a):void 0;if(!i)return;let o=aL(t,i.selector,r,n);if(o.ok)return eQ({level:"debug",phase:"maestro_preferred_context",data:{selector:i.selector,node:{index:o.node.index,type:o.node.type,label:o.node.label,value:o.node.value,identifier:o.node.identifier},rect:o.rect}}),{node:o.node,rect:o.rect}}(e,o,l,s),c=function(e,t,r,n,a,i={}){let o=aC(e,t,n);if(r.childOf){let t=aC(e,r.childOf,n);if(0===t.length)return{ok:!1,message:`Maestro childOf parent did not match: ${r.childOf}`};let a=e7(e.nodes);o=o.filter(r=>t.some(t=>e3(e.nodes,r,t,a)))}let s=aP({nodes:e.nodes,matches:o,platform:n}),l=aU(e.nodes,s.matches,r.index,aF(t),a,!1,i.promoteTapTarget,i.preferredContext);if(!l){let e=r.index??0;return{ok:!1,message:s.blockedByReactNativeOverlay?`React Native overlay is covering app content: ${t}`:o.length>0&&0===s.matches.length?`Maestro selector matched ${o.length} element(s), but none were visible: ${t}`:`Maestro selector did not match index ${e}: ${t}`}}return{ok:!0,node:l.node,rect:l.rect}}(o,t,r,l,s,{...a,preferredContext:u});if(!c.ok){let e=aF(t);if(e){let t=function(e,t,r,n,a={}){let i=function(e,t){let r=tr(t);if(!r)return[];let n=[],a=[];for(let t of e.nodes){let e=[t.label,e1(t),t.identifier,t.value].filter(e=>!!e).map(e=>tr(e));e.some(e=>e===r)?n.push(t):e.some(e=>e.includes(r))&&a.push(t)}return n.length>0?n:a}(e,t),o=aP({nodes:e.nodes,matches:i,platform:r}),s=aU(e.nodes,o.matches,void 0,t,n,!1,a.promoteTapTarget,a.preferredContext);return s?{ok:!0,node:s.node,rect:s.rect}:{ok:!1,message:`Maestro fuzzy text did not match: ${t}`}}(o,e,l,s,{...a,preferredContext:u});if(t.ok)return{ok:!0,target:{node:t.node,rect:t.rect,frame:s,snapshot:o}}}}return c.ok?{ok:!0,target:{node:c.node,rect:c.rect,frame:s,snapshot:o}}:{ok:!1,response:aD("ELEMENT_NOT_FOUND",c.message,{selector:t,options:r,command:n})}}async function iI(e){switch(e.command){case nG:return await aJ(e);case nj:return await a5(e);case nq:return await i_(e);case nK:return await a6(e);case nB:return await is(e);case nH:return await iu(e);case nW:return await ip(e);case nz:return await id(e);case nJ:return await il(e);case nT:return function(e){let[r]=e.positionals;if(!r)return aD("INVALID_ARGS","runScript requires a file path.");try{let n=function(e){let{scriptPath:r,env:n}=e,a=t.readFileSync(r,"utf8"),i=Object.create(null);try{var o,l;s.runInNewContext(a,(o=n,l=i,{...o,output:l,json:at,http:{post:(e,t)=>(function(e,t,r){let n=eZ(process.execPath,["-e",ae],{stdin:JSON.stringify({method:e,url:t,headers:r?.headers??{},body:r?.body??""}),timeoutMs:3e4,allowFailure:!0});if(0!==n.exitCode){let r;throw new d("COMMAND_FAILED",`Maestro runScript http.${e.toLowerCase()} failed for ${t}: ${(r=n.stderr.trim()).length>0?r.slice(0,1e3):"request process exited without stderr"}`,{exitCode:n.exitCode,stderr:n.stderr})}try{return JSON.parse(n.stdout)}catch(r){throw new d("COMMAND_FAILED",`Maestro runScript http.${e.toLowerCase()} returned invalid JSON for ${t}`,{stdout:n.stdout.slice(0,1e3),stderr:n.stderr.slice(0,1e3)},r instanceof Error?r:void 0)}})("POST",e,t)}}),{filename:r,timeout:3e4})}catch(e){throw new d("COMMAND_FAILED",`Maestro runScript failed for ${r}: ${e instanceof Error?e.message:String(e)}`,{scriptPath:r},e instanceof Error?e:void 0)}return function(e,t){for(let r of Object.keys(e))if(r.includes("."))throw new d("INVALID_ARGS",`Maestro runScript output key cannot contain ".": ${r}`,{scriptPath:t,key:r})}(i,r),Object.fromEntries(Object.entries(i).map(([e,t])=>{var r;return[`output.${e}`,(r=t,"string"==typeof r?r:"number"==typeof r||"boolean"==typeof r?String(r):JSON.stringify(r))]}))}({scriptPath:r,env:{...e.scope.values,...e.baseReq.flags?.maestro?.runScriptEnv??{}}});return{ok:!0,data:{outputEnv:n}}}catch(t){let e=u(t);return aD(e.code,e.message,e.details)}}(e);default:return}}async function i_(e){let t=await e.invoke({...e.baseReq,command:"keyboard",positionals:["enter"]});return t.ok?t:await e.invoke({...e.baseReq,command:"type",positionals:["\n"]})}async function iN(e){for(let[t,r]of e.actions.entries()){let n=await e.invokeReplayAction({action:r,line:e.line,step:e.step+t/1e3});if(!n.ok)return n}return{ok:!0,data:{ran:e.actions.length}}}async function iM(e){let t;for(let r=0;r<=e.maxRetries;r+=1){let n=await iN({actions:e.actions,line:e.line,step:e.step+r,invokeReplayAction:e.invokeReplayAction});if(n.ok)return{ok:!0,data:{attempts:r+1,retried:r>0}};t=n}return t??{ok:!1,error:{code:"COMMAND_FAILED",message:"retry commands failed."}}}async function ix(e){let t=await iD(e,e.control);return t.ok?t.matched?await iR(e):{ok:!0,data:{skipped:!0,condition:e.control.mode,selector:e.control.selector}}:t.response}async function iD(e,t){if("visible"===t.mode)return await ik(e,t);let r=await ak(e);if(!r.ok)return{ok:!1,response:r};let n=iO(e,t.selector,r);return n.ok?{ok:!0,matched:!n.matched}:{ok:!1,response:n.response}}async function ik(e,t){let r=Date.now();for(;;){let n=await ak(e);if(!n.ok)return{ok:!1,response:n};let a=iO(e,t.selector,n);if(!a.ok)return{ok:!1,response:a.response};if(a.matched)return{ok:!0,matched:!0};if(Date.now()-r>=3e3)return{ok:!0,matched:!1};await tp(250)}}function iO(e,t,r){let n=aO(r.data);return n?{ok:!0,matched:aL(n,t,a$(e.baseReq.flags),q(n)).ok}:{ok:!1,response:aD("COMMAND_FAILED","Unable to read snapshot data for runFlow.when.")}}async function iR(e){let t=await iN({actions:e.control.actions,line:e.line,step:e.step,invokeReplayAction:e.invokeReplayAction});return t.ok?{ok:!0,data:{ran:t.data?.ran,condition:e.control.mode,selector:e.control.selector}}:t}async function iL(e){var t;let{req:r,sessionName:n,action:a,scope:i,filePath:o,line:s,step:l,tracePath:u,invoke:c}=e,d=(t={file:o,line:s},{...a,positionals:(a.positionals??[]).map(e=>nm(e,i,t)),flags:nh(a.flags,i,t)??{},runtime:nh(a.runtime,i,t),replayControl:function(e,t,r){if(!e)return e;if(e.kind==="maestroRunFlowWhen"){return{...e,selector:nm(e.selector,t,r)}}return e}(a.replayControl,i,t)}),p=Date.now();iF(u,{type:"replay_action_start",ts:new Date(p).toISOString(),replayPath:o,line:s,step:l,command:d.command,positionals:d.positionals??[]});let f=await iP({req:r,sessionName:n,resolved:d,scope:i,line:s,step:l,invoke:c,invokeReplayAction:e=>iL({req:r,sessionName:n,action:e.action,scope:i,filePath:o,line:e.line,step:e.step,tracePath:u,invoke:c})}),m=Date.now();return iF(u,{type:"replay_action_stop",ts:new Date(m).toISOString(),replayPath:o,line:s,step:l,command:d.command,ok:f.ok,durationMs:m-p,resultTiming:f.ok?function(e){if(!e||"object"!=typeof e||Array.isArray(e))return;let t=e.timing;if(!(!t||"object"!=typeof t||Array.isArray(t)))return Object.fromEntries(Object.entries(t).filter(([,e])=>{let t=typeof e;return"number"===t||"string"===t||"boolean"===t}))}(f.data):void 0,errorCode:f.ok?void 0:f.error.code}),f}async function iP(e){var t;let{req:r,sessionName:n,resolved:a,scope:i,line:o,step:s,invoke:l,invokeReplayAction:u}=e,c=(t=r.flags,eW(t,{...a.flags??{}})),d={token:r.token,session:n,flags:c,runtime:a.runtime,meta:r.meta},p=await i$({control:a.replayControl,baseReq:d,line:o,step:s,invoke:l,invokeReplayAction:u})??await iI({command:a.command,baseReq:d,positionals:a.positionals??[],scope:i,line:o,step:s,invoke:l,invokeReplayAction:u})??await l({...d,command:a.command,positionals:a.positionals??[]});if(p.ok){let e=function(e){if(!e||"object"!=typeof e)return null;let t=e.outputEnv;if(!t||"object"!=typeof t||Array.isArray(t))return null;let r=Object.entries(t).filter(e=>"string"==typeof e[1]);return r.length>0?Object.fromEntries(r):null}(p.data);e&&Object.assign(i.values,e)}return p}async function i$(e){let{control:t,baseReq:r,line:n,step:a,invoke:i,invokeReplayAction:o}=e;if(t){switch(t.kind){case"retry":return await iM({actions:t.actions,maxRetries:t.maxRetries,line:n,step:a,invokeReplayAction:o});case"maestroRunFlowWhen":return await ix({baseReq:r,control:t,line:n,step:a,invoke:i,invokeReplayAction:o})}return t}}function iF(e,r){e&&t.appendFileSync(e,`${JSON.stringify(r)}
|
|
28
28
|
`)}async function iC(e){let{req:r,sessionName:n,logPath:i,sessionStore:o,tracePath:s,invoke:l}=e,c=r.positionals?.[0];if(!c)return R("INVALID_ARGS","replay requires a path");let p="",f=new Set;try{var m,h;p=Q.expandHome(c,r.meta?.cwd);let e=t.readFileSync(p,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return R("INVALID_ARGS","replay accepts .ad script files. JSON replay payloads are no longer supported.");let w=function(e,t,r={}){var n;let a=function(e){let t=e?.replayBackend;if("string"!=typeof t)return;let r=ab[t];if(!r)throw new d("INVALID_ARGS",`Unsupported replay backend "${t}".`);return r}(t);return a?{...a.parse(e,{...r,platform:t?.platform,env:(n=t,{...nc(nf(n?.replayShellEnv)),...nd(np(n?.replayEnv))})}),updateUnsupportedMessage:"replay -u is not supported for compat flow input. Convert to .ad first, then update that replay file."}:{...function(e){let t=[],r=[],n=e.split(/\r?\n/),a=!1;for(let[e,i]of n.entries()){let n=i.trim();if(0===n.length||n.startsWith("#"))continue;if(nv(n)){if(a)throw new d("INVALID_ARGS",`env directives must precede all actions (line ${e+1}).`);continue}let o=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let[r,...n]=function(e){let t=[],r=0;for(;r<e.length&&!((r=function(e,t){let r=t;for(;r<e.length&&/\s/.test(e.charAt(r));)r+=1;return r}(e,r))>=e.length);){let n='"'===e[r]?function(e,t){let r=!1,n=t+1;for(;n<e.length;n+=1){let t=e.charAt(n);if('"'===t&&!r)break;if(r){r=!1;continue}r="\\"===t}if(n>=e.length)throw new d("INVALID_ARGS",`Invalid replay script line: ${e}`);return{value:JSON.parse(e.slice(t,n+1)),nextCursor:n+1}}(e,r):function(e,t){let r=t;for(;r<e.length&&!/\s/.test(e.charAt(r));)r+=1;return{value:e.slice(t,r),nextCursor:r}}(e,r);t.push(n.value),r=n.nextCursor}return t}(t);if(void 0===r||"context"===r)return null;let a={ts:Date.now(),command:r,positionals:[],flags:{}};if("snapshot"===r){a.positionals=[];for(let e=0;e<n.length;e+=1){let t=n[e];if("-i"===t){a.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){a.flags.snapshotCompact=!0;continue}if("--raw"===t){a.flags.snapshotRaw=!0;continue}if("--force-full"===t){a.flags.snapshotForceFull=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<n.length){let t=Number(n[e+1]);Number.isFinite(t)&&t>=0&&(a.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<n.length){a.flags.snapshotScope=n[e+1],e+=1;continue}if("--backend"===t&&e+1<n.length){e+=1;continue}}return a}if("open"===r){let e=P(n);return a.positionals=e.positionals,Object.assign(a.flags,e.flags),a.runtime=e.runtime,a}if("runtime"===r){let e=G(n);return a.positionals=e.positionals,Object.assign(a.flags,e.flags),a}if(M(r)){let e=eh(r,n);Object.assign(a.flags,e.flags);let t=e.positionals[0];if(void 0===t)return a;if(t.startsWith("@"))return a.positionals=[t],e.positionals[1]&&(a.result={refLabel:e.positionals[1]}),a;let i=e.positionals[0],o=e.positionals[1];return nb(i)&&nb(o)&&e.positionals.length>=2?a.positionals=[i,o]:a.positionals=[e.positionals.join(" ")],a}if("fill"===r){let e=eh(r,n);if(Object.assign(a.flags,e.flags),!(e.positionals.length>=2))return a.positionals=e.positionals,a;let[t,i,...o]=e.positionals;return t.startsWith("@")?(o.length>0?(a.positionals=[t,o.join(" ")],a.result={refLabel:i}):a.positionals=[t,i],a):(a.positionals=[t,[i,...o].join(" ")],a)}if("get"===r){let e=n[0],t=n[1];return void 0===e||void 0===t?a.positionals=n:t.startsWith("@")?(a.positionals=[e,t],n[2]&&(a.result={refLabel:n[2]})):a.positionals=[e,n.slice(1).join(" ")],a}if("swipe"===r||"type"===r){let e=eh(r,n);return Object.assign(a.flags,e.flags),a.positionals=e.positionals,a}if("record"===r){let e=[];for(let t=0;t<n.length;t+=1){let r=n[t];if("--hide-touches"===r){a.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<n.length){let e=Number(n[t+1]);Number.isFinite(e)&&(a.flags.fps=Math.floor(e)),t+=1;continue}if("--quality"===r&&t+1<n.length){let e=Number(n[t+1]);Number.isFinite(e)&&(a.flags.quality=Math.floor(e)),t+=1;continue}e.push(r)}return a.positionals=e,a}if("screenshot"===r){let e=[];for(let t=0;t<n.length;t+=1){let r=n[t],i=eY({args:n,index:t,flags:a.flags});if(i.handled){t=i.nextIndex;continue}e.push(r)}return a.positionals=e,a}return a.positionals=n,a}(i);o&&(t.push(o),r.push(e+1),a=!0)}return{actions:t,actionLines:r}}(e),metadata:ny(e)}}(e,r.flags,{sourcePath:p}),g=w.metadata,y=g.platform||g.target?{...r,flags:(m=r.flags,h=g,{...m??{},...void 0!==h.platform&&m?.platform===void 0?{platform:h.platform}:{},...void 0!==h.target&&m?.target===void 0?{target:h.target}:{}})}:r,v=w.actions,A=w.actionLines;if(r.flags?.replayUpdate===!0&&w.updateUnsupportedMessage)return R("INVALID_ARGS",w.updateUnsupportedMessage);if(r.flags?.replayUpdate===!0&&g.env&&Object.keys(g.env).length>0)return R("INVALID_ARGS","replay -u does not yet preserve env directives. Temporarily remove the env lines, run replay -u, then restore them.");if(r.flags?.replayUpdate===!0&&function(e){for(let t of e){for(let e of t.positionals??[])if("string"==typeof e&&e.includes("${"))return!0;if(iU(t.flags)||iU(t.runtime))return!0}return!1}(v))return R("INVALID_ARGS","replay -u does not yet preserve ${VAR} substitutions. Resolve or inline the variables before running with -u.");let S=function(e){let t={};if(e.builtins)for(let[r,n]of Object.entries(e.builtins))t[r]=n;for(let r of[e.fileEnv,e.shellEnv,e.cliEnv])if(r)for(let[e,n]of Object.entries(r)){if(nl(e))throw nu(e);t[e]=n}return{values:t}}({builtins:function(e){let{req:t,sessionName:r,metadata:n,resolvedPath:i}=e,o=t.flags??{},s=t.meta?.cwd??process.cwd(),l={AD_SESSION:r,AD_FILENAME:a.relative(s,i)||i},u=o.platform??n.platform;u&&(l.AD_PLATFORM=u);let c=o.target??n.target;c&&(l.AD_TARGET=c);let d=o.device;"string"==typeof d&&d.length>0&&(l.AD_DEVICE=d);let p=o.artifactsDir;return"string"==typeof p&&p.length>0&&(l.AD_ARTIFACTS=p),l}({req:y,sessionName:n,metadata:g,resolvedPath:p}),fileEnv:g.env,shellEnv:nc(nf(r.flags?.replayShellEnv)),cliEnv:nd(np(r.flags?.replayEnv))}),I=r.flags?.replayUpdate===!0,_=s??o.get(n)?.trace?.outPath,N=0;for(let e=0;e<v.length;e+=1){let t=v[e];if(!t||"replay"===t.command)continue;let r=await iL({req:y,sessionName:n,action:t,scope:S,filePath:p,line:A[e]??0,step:e+1,tracePath:_,invoke:l});if(r.ok){iV(r).forEach(e=>f.add(e));continue}if(!I)return iE(r,t,e,p,[...f]);let a=await aI({action:t,sessionName:n,logPath:i,sessionStore:o});if(!a)return iE(r,t,e,p,[...f]);if(v[e]=a,!(r=await iL({req:y,sessionName:n,action:a,scope:S,filePath:p,line:A[e]??0,step:e+1,tracePath:_,invoke:l})).ok)return iE(r,a,e,p,[...f]);iV(r).forEach(e=>f.add(e)),N+=1}return I&&N>0&&function(e,r,n){let a=[];if(n){let e=n.device.kind?` kind=${n.device.kind}`:"",t=n.device.target?` target=${n.device.target}`:"";a.push(`context platform=${n.device.platform}${t} device=${ee(n.device.name)}${e} theme=unknown`)}for(let e of r){var i;a.push((i=e,b(i,{runtimeIncludeAllPositionals:!0})))}let o=`${a.join("\n")}
|
|
29
29
|
`,s=`${e}.tmp-${process.pid}-${Date.now()}`;t.writeFileSync(s,o),t.renameSync(s,e)}(p,v,o.get(n)),{ok:!0,data:{replayed:v.length,healed:N,session:n,artifactPaths:[...f]}}}catch(t){let e=u(t);return R(e.code,e.message,f.size>0?{artifactPaths:[...f]}:void 0)}}function iE(e,t,r,n,a=[]){if(e.ok)return e;let i=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${i} (${et(t)}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:n,step:i,action:t.command,positionals:t.positionals??[],artifactPaths:a}}}}function iV(e){if(!e.ok||!e.data)return[];let r=[];if("string"==typeof e.data.path&&r.push(e.data.path),"string"==typeof e.data.outPath&&r.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let t of e.data.artifacts){if(!t||"object"!=typeof t)continue;let e="string"==typeof t.localPath?t.localPath:void 0,n="string"==typeof t.path?t.path:void 0;e?r.push(e):n&&r.push(n)}return[...new Set(r.filter(e=>(function(e){try{return t.statSync(e).isFile()}catch{return!1}})(e)))]}function iU(e){return"string"==typeof e?e.includes("${"):Array.isArray(e)?e.some(iU):!!e&&"object"==typeof e&&Object.values(e).some(iU)}async function iT(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}=e;return"replay"===t.command?await iC({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i}):"test"===t.command?await av({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,target:s,requestId:l,artifactsDir:u,artifactPaths:c,tracePath:d})=>{let p=function(e){let{parentFlags:t,platform:r,target:n,artifactsDir:a}=e;return void 0===r&&void 0===n&&void 0===a?t:{...t??{},...void 0!==r?{platform:r}:{},...void 0!==n?{target:n}:{},...void 0!==a?{artifactsDir:a}:{}}}({parentFlags:t.flags,platform:o,target:s,artifactsDir:u});return await iC({req:{...t,command:"replay",session:r,positionals:[e],flags:p,meta:l?{...t.meta??{},requestId:l}:t.meta},sessionName:r,logPath:n,sessionStore:a,tracePath:d,invoke:async e=>{var t;return t=await i(e),c&&iV(t).forEach(e=>c.add(e)),t}})},cleanupSession:async e=>{a.get(e)&&await B({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:n,sessionStore:a})}}):null}let iG=tm.inventory,ij=tm.state,iq=tm.observability,iK=tm.replay,iB={...Object.fromEntries([...iG].map(e=>[e,!0])),...Object.fromEntries([...ij].map(e=>[e,!0])),...Object.fromEntries([...iq].map(e=>[e,!0])),...Object.fromEntries([...iK].map(e=>[e,!0])),[tf.runtime]:!0,[th.clipboard]:!0,[th.keyboard]:!0,[th.install]:!0,[th.reinstall]:!0,[tf.installSource]:!0,[tf.releaseMaterializedPaths]:!0,[th.push]:!0,[th.triggerAppEvent]:!0,[th.open]:!0,[th.batch]:!0,[th.close]:!0};async function iH(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,command:i,positionals:o,recordPositionals:s,deriveNextSession:l}=e,u=a.get(r),c=t.flags??{},d=I(i,u,c);if(d)return d;let p=await g({session:u,flags:c,ensureReady:!0});if(!eA(i,p))return R("UNSUPPORTED_OPERATION",`${i} is not supported on this device`);let f=await m(p,i,o,t.flags?.out,{...Y(n,t.flags,u?.appBundleId,u?.trace?.outPath)});if(u){let e=l?await l(u,f,p):u;a.recordAction(e,{command:i,positionals:s??o,flags:t.flags??{},result:f??{}}),e!==u&&a.set(r,e)}return{ok:!0,data:f??{}}}async function iW(e){let{req:t,sessionName:r,logPath:n,sessionStore:a}=e,i=a.get(r),o=t.flags??{},s=I(th.clipboard,i,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return R("INVALID_ARGS","clipboard requires a subcommand: read or write");let u=await g({session:i,flags:o,ensureReady:!0});if(!eA(th.clipboard,u))return R("UNSUPPORTED_OPERATION","clipboard is not supported on this device");let c=await m(u,th.clipboard,t.positionals??[],t.flags?.out,{...Y(n,t.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:c??{}}),{ok:!0,data:{platform:u.platform,...c??{}}}}async function iz(e){let{req:t,sessionName:r,logPath:n,sessionStore:a,invoke:i,invokeReplayAction:o,androidAdbExecutor:s}=e;if(iG.has(t.command))return await ro({req:t,sessionName:r,sessionStore:a});if("runtime"===t.command)return await tk({req:t,sessionName:r,sessionStore:a});if(ij.has(t.command))return await rd({req:t,sessionName:r,sessionStore:a});if(t.command===th.clipboard)return await iW({req:t,sessionName:r,logPath:n,sessionStore:a});if(t.command===th.keyboard){let e=a.get(r),i=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==i&&"enter"!==i&&"return"!==i||"ios"!==eI((t.flags??{}).platform)?await iH({req:t,sessionName:r,logPath:n,sessionStore:a,command:th.keyboard,positionals:t.positionals??[]}):R("SESSION_NOT_FOUND","iOS keyboard action requires an active session so the target app stays foregrounded. Run open first.")}if(iq.has(t.command))return await r9({req:t,sessionName:r,sessionStore:a,androidAdbExecutor:s});if(t.command===th.install||t.command===th.reinstall)return await ra({req:t,command:t.command,sessionName:r,sessionStore:a,deployOps:t.command===th.install?rn:rr});if(t.command===tf.installSource)return await tb({req:t,sessionName:r,sessionStore:a});if(t.command===tf.releaseMaterializedPaths)return await tS({req:t});if(t.command===th.push){let e,i=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return i&&o?await iH({req:t,sessionName:r,logPath:n,sessionStore:a,command:th.push,positionals:[i,"file"===(e=eo(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>Q.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[i,o]}):R("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>")}return t.command===th.triggerAppEvent?await iH({req:t,sessionName:r,logPath:n,sessionStore:a,command:th.triggerAppEvent,positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,n=r?await t1(e.device,r,e.appBundleId,tQ)??e.appBundleId:e.appBundleId;return{...e,appBundleId:n}}}):t.command===th.open?await rt({req:t,sessionName:r,logPath:n,sessionStore:a}):iK.has(t.command)?await iT({req:t,sessionName:r,logPath:n,sessionStore:a,invoke:o??i}):t.command===th.batch?await ri(t,r,i):t.command===th.close?await B({req:t,sessionName:r,logPath:n,sessionStore:a}):null}export{tg as session_namespaceObject};
|