agent-device 0.16.7 → 0.16.8
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/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.7.apk → agent-device-android-multitouch-helper-0.16.8.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.8.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.7.manifest.json → agent-device-android-multitouch-helper-0.16.8.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.7.apk → agent-device-android-snapshot-helper-0.16.8.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.8.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.7.manifest.json → agent-device-android-snapshot-helper-0.16.8.manifest.json} +6 -6
- package/dist/src/1352.js +1 -1
- package/dist/src/2415.js +29 -29
- package/dist/src/2805.js +1 -1
- package/dist/src/6232.js +1 -0
- package/dist/src/7455.js +1 -0
- package/dist/src/8699.js +1 -1
- package/dist/src/940.js +1 -1
- package/dist/src/9471.js +1 -1
- package/dist/src/9533.js +1 -1
- package/dist/src/9542.js +1 -1
- package/dist/src/9818.js +1 -1
- package/dist/src/android-adb.d.ts +2 -0
- package/dist/src/android-snapshot-helper.d.ts +2 -0
- package/dist/src/args.js +5 -4
- package/dist/src/cli.js +6 -6
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/generic.js +10 -7
- package/dist/src/interaction.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +3 -3
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/session.js +9 -9
- package/dist/src/snapshot.js +2 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +20 -6
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +178 -74
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +8 -33
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +71 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +80 -10
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +34 -6
- package/package.json +4 -6
- package/server.json +2 -2
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.7.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.7.apk.sha256 +0 -1
- package/dist/src/5186.js +0 -1
package/dist/src/find.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{setSessionSnapshot as t,captureSnapshot as e,dispatchCommand as r,errorResponse as n,ensureDeviceReady as o,
|
|
1
|
+
import{setSessionSnapshot as t,captureSnapshot as e,dispatchCommand as r,errorResponse as n,ensureDeviceReady as o,stripInternalInteractionOutcomeFlags as a,getActiveAndroidSnapshotFreshness as i,resolveTargetDevice as s,context_contextFromFlags as l}from"./2415.js";import{findBestMatchesByLocator as c,parseFindArgs as f}from"./7556.js";import{dispatchFindReadOnlyViaRuntime as u,readTextForNode as d}from"./selector-runtime.js";import{PUBLIC_COMMANDS as _}from"./5792.js";import{centerOfRect as p}from"./4057.js";import{resolveActionableTouchResolution as g,resolveActionableTouchNode as m}from"./9533.js";import{sleep as h}from"./4829.js";import{extractNodeText as A}from"./940.js";let w={[_.find]:!0};async function S(r){var l,d;let{req:_,sessionName:h,logPath:w,sessionStore:S,invoke:F}=r,E=_.command;if("find"!==E)return null;let P=_.positionals??[];if(0===P.length)return n("INVALID_ARGS","find requires a locator or text");let{locator:U,query:L,action:v,value:H,timeoutMs:O}=f(P);if(!L)return n("INVALID_ARGS","find requires a value");if(_.flags?.findFirst&&_.flags?.findLast)return n("INVALID_ARGS","find accepts only one of --first or --last");let b=await u({req:_,sessionName:h,logPath:w,sessionStore:S});if(b)return b;let $=S.get(h),q="exists"===(l=v)||"wait"===l||"get_text"===l||"get_attrs"===l;if(!$&&!q)return n("SESSION_NOT_FOUND","No active session. Run open first.");let G=$?.device??await s(_.flags??{});$||await o(G);let B="click"===(d=v)||"focus"===d||"fill"===d||"type"===d,V="role"===U||B?void 0:L,T=0,j=null,z=async()=>{let r=Date.now();if(j&&r-T<750&&!i($))return{nodes:j};let{snapshot:n}=await e({device:G,session:$,flags:{..._.flags,snapshotInteractiveOnly:B,snapshotCompact:B},outPath:_.flags?.out,logPath:w,snapshotScope:V}),o=n.nodes;return T=r,j=o,$&&(t($,n),S.set(h,$)),{nodes:o,truncated:n.truncated,backend:n.backend}},J={req:_,sessionName:h,logPath:w,sessionStore:S,invoke:F,session:$,device:G,command:E,locator:U,query:L,publicFlags:{...a(_.flags)??{}}};if("wait"===v)return N(J,z,U,L,O);let{nodes:Q}=await z(),W=function(t){let{nodes:e,locator:r,query:o,requiresRect:a,flags:i}=t,s=c(e,r,o,{requireRect:a});if(a&&(s.matches=function(t,e){var r,n;let o=e[0]?.rect;if(!o)return t;let a=t.filter(t=>{if(!t.rect)return!1;let e=p(t.rect);return e.x>=o.x&&e.x<=o.x+o.width&&e.y>=o.y&&e.y<=o.y+o.height});return r=a.length>0?a:t,n=e,r.length<2?r:r.map((t,e)=>{var r,o;let a;return{node:t,index:e,score:(r=t,"semantic-target"===(a=g(o=n,r)).reason&&a.node.rect||"same-rect-descendant"===a.reason&&a.node.rect?4:"hittable-ancestor"===a.reason&&a.node.rect&&!C(a.node,o[0])?2:r.hittable&&r.rect&&!C(r,o[0])?3:+!!r.rect)}}).sort((t,e)=>e.score!==t.score?e.score-t.score:y(t.node)-y(e.node)||t.index-e.index).map(t=>t.node)}(s.matches,e)),a&&s.matches.length>1)if(i?.findFirst)s.matches=[s.matches[0]];else{if(!i?.findLast){var l,f,u;let t;return{ok:!1,response:(l=s.matches,f=r,u=o,t=l.slice(0,8).map(t=>{let e=A(t)||t.label||t.identifier||t.type||"";return`@${t.ref}${e?`(${e})`:""}`}),n("AMBIGUOUS_MATCH",`find matched ${l.length} elements for ${f} "${u}". Use a more specific locator or selector.`,{locator:f,query:u,matches:l.length,candidates:t}))}}s.matches=[s.matches[s.matches.length-1]]}let d=s.matches[0]??null;return d?{ok:!0,node:d}:{ok:!1,response:n("COMMAND_FAILED","find did not match any element")}}({nodes:Q,locator:U,query:L,requiresRect:B,flags:_.flags});if(!W.ok)return W.response;let X=W.node,Y=B?m(Q,X):X,Z=`@${Y.ref}`,tt={node:X,resolvedNode:Y,ref:Z,nodes:Q,actionFlags:{..._.flags??{},noRecord:!0}},te={exists:()=>k(J),get_text:()=>x(J,tt),get_attrs:()=>I(J,tt),click:()=>M(J,tt),fill:()=>D(J,tt,H),focus:()=>R(J,tt),type:()=>K(J,tt,H)}[v];return te?te():null}function y(t){return t.rect?t.rect.width*t.rect.height:1/0}function C(t,e){if(!e?.rect||!t.rect)return!1;let r=t.type?.toLowerCase()??"";return(!!r.includes("application")||!!r.includes("window"))&&t.rect.x===e.rect.x&&t.rect.y===e.rect.y&&t.rect.width===e.rect.width&&t.rect.height===e.rect.height}async function N(t,e,r,o,a){let{req:i,sessionStore:s,session:l,command:f,publicFlags:u}=t,d=a??1e4,_=Date.now();for(;Date.now()-_<d;){let{nodes:t}=await e();if(c(t,r,o,{requireRect:!1}).matches[0])return l&&s.recordAction(l,{command:f,positionals:i.positionals??[],flags:u,result:{found:!0,waitedMs:Date.now()-_}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-_}};await h(300)}return n("COMMAND_FAILED","find wait timed out")}async function k(t){let{req:e,sessionStore:r,session:n,command:o,publicFlags:a}=t;return n&&r.recordAction(n,{command:o,positionals:e.positionals??[],flags:a,result:{found:!0}}),{ok:!0,data:{found:!0}}}async function x(t,e){let{req:r,sessionStore:n,session:o,command:a,device:i,logPath:s,publicFlags:c}=t,f=await d({device:i,node:e.node,flags:r.flags,appBundleId:o?.appBundleId,traceOutPath:o?.trace?.outPath,surface:o?.surface,contextFromFlags:(t,e,r)=>l(s,t,e,r)});return o&&n.recordAction(o,{command:a,positionals:r.positionals??[],flags:c,result:{ref:e.ref,action:"get text",text:f}}),{ok:!0,data:{ref:e.ref,text:f,node:e.node}}}async function I(t,e){let{req:r,sessionStore:n,session:o,command:a,publicFlags:i}=t;return o&&n.recordAction(o,{command:a,positionals:r.positionals??[],flags:i,result:{ref:e.ref,action:"get attrs"}}),{ok:!0,data:{ref:e.ref,node:e.node}}}async function M(t,e){let{req:r,sessionName:n,sessionStore:o,session:a,invoke:i,command:s,locator:l,query:c,publicFlags:f}=t,u=await i({token:r.token,session:n,command:"click",positionals:[e.ref],flags:e.actionFlags});if(!u.ok)return u;let d=e.resolvedNode.rect?p(e.resolvedNode.rect):e.node.rect?p(e.node.rect):null,_={ref:e.ref,locator:l,query:c};return d&&(_.x=d.x,_.y=d.y),a&&o.recordAction(a,{command:s,positionals:r.positionals??[],flags:f,result:{ref:e.ref,action:"click",locator:l,query:c}}),{ok:!0,data:_}}async function D(t,e,r){let{req:o,sessionName:a,sessionStore:i,session:s,invoke:l,command:c,publicFlags:f}=t;if(!r)return n("INVALID_ARGS","find fill requires text");let u=await l({token:o.token,session:a,command:"fill",positionals:[e.ref,r],flags:e.actionFlags});return u.ok&&s&&i.recordAction(s,{command:c,positionals:o.positionals??[],flags:f,result:{ref:e.ref,action:"fill"}}),u}async function R(t,e){let r=await F(t,e);return r.ok&&E(t,e,"focus"),r}async function K(t,e,o){let{req:a,device:i,logPath:s,session:c}=t;if(!o)return n("INVALID_ARGS","find type requires text");let f=await F(t,e);if(!f.ok)return f;let u=await r(i,"type",[o],a.flags?.out,{...l(s,a.flags,c?.appBundleId,c?.trace?.outPath)});return E(t,e,"type"),{ok:!0,data:u??{ref:e.ref}}}async function F(t,e){let{req:o,device:a,logPath:i,session:s}=t,c=e.node.rect?p(e.node.rect):null;return c?{ok:!0,data:await r(a,"focus",[String(c.x),String(c.y)],o.flags?.out,{...l(i,o.flags,s?.appBundleId,s?.trace?.outPath)})??{ref:e.ref}}:n("COMMAND_FAILED","matched element has no bounds")}function E(t,e,r){let{req:n,sessionStore:o,session:a,command:i,publicFlags:s}=t;a&&o.recordAction(a,{command:i,positionals:n.positionals??[],flags:s,result:{ref:e.ref,action:r}})}export{parseFindArgs}from"./7556.js";export{w as FIND_COMMAND_HANDLERS,S as handleFindCommands};
|
package/dist/src/generic.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import t from"node:fs";import e from"node:path";import{AppError as
|
|
1
|
+
import t from"node:fs";import e from"node:path";import{AppError as r}from"./9152.js";import{runCliCommandWithOutput as s,printJson as i,writeCommandOutput as n}from"./cli.js";import{readCommandMessage as o}from"./1998.js";function a(t){var r,s;let i,n,o=t.attempts>1?` after ${t.attempts} attempts`:"",a=h(t);for(let u of(process.stdout.write(`FAIL ${(i=g(r=t),n=e.basename(r.file),i&&i.length>0?`${JSON.stringify(i)} in ${n}`:n)}${o}${a}
|
|
2
2
|
`),process.stdout.write(` ${t.error?.message??"Unknown test failure"}
|
|
3
|
-
`),
|
|
4
|
-
`)
|
|
5
|
-
`}(
|
|
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
|
+
`);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?[]:[`steps (attempt ${r.attempts}):`,...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?"[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 k({command:l,positionals:f,flags:p,client:d}){var c,D,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,D=N,!c.json&&D.stderr&&process.stderr.write(D.stderr),n(c,c.json?D.jsonData??D.data:D.data,()=>D.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
|
+
`}(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}
|
|
6
7
|
`),"skipped"===t.status&&process.stdout.write(` ${t.message??"skipped"}
|
|
7
|
-
`)
|
|
8
|
-
`)}(t)
|
|
9
|
-
`)
|
|
8
|
+
`),u(t)))process.stdout.write(` ${s}
|
|
9
|
+
`)}(e);else for(let e of t.failures)a(e);let s="number"==typeof t.durationMs?t.durationMs:void 0,i=r.length>0?`, ${r.length} flaky`:"",n=void 0!==s?` in ${A(s)}`:"";return process.stdout.write(`Test summary: ${t.passed} passed, ${t.failed} failed${i}${n}
|
|
10
|
+
`),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
|
+
`),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{k as runGenericClientBackedCommand};
|
package/dist/src/interaction.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__webpack_require__ as e}from"./rslib-runtime.js";import{createDaemonRuntimeSessionStore as t,setSessionSnapshot as r,dispatchCommand as a,getClickButtonValidationError as n,ensureAndroidBlockingSystemDialogReady as s,isCommandSupportedOnDevice as o,buttonTag as i,resolveClickButton as l,errorResponse as c,recoverAndroidBlockingSystemDialog as u,getActiveAndroidSnapshotFreshness as f}from"./2415.js";import{createAgentDevice as d}from"./9533.js";import{asAppError as p,normalizeError as g,AppError as m}from"./9152.js";import{dispatchGetViaRuntime as S,isAndroidEscapeError as _,createDaemonRuntimePolicy as k,assertAndroidPressStayedInApp as h,dispatchIsViaRuntime as y,isDirectIosSelectorFallbackError as w,refSnapshotFlagGuardResponse as b,readSimpleIosSelectorTarget as N}from"./selector-runtime.js";import{readInteractionTargetFromPositionals as v,readFillTargetFromPositionals as x}from"./8502.js";import{interaction_snapshot_captureSnapshotForSession as F,readSnapshotNodesReferenceFrame as P,resolveDirectTouchReferenceFrameSafely as R,buildTouchVisualizationResult as M,finalizeTouchInteraction as O}from"./9471.js";import{emitDiagnostic as C}from"./7599.js";import{PUBLIC_COMMANDS as I}from"./5792.js";import{successText as A}from"./1998.js";var E={};function q(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:c("UNSUPPORTED_OPERATION",`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function D(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new m("SESSION_NOT_FOUND","No active session. Run open first.");return d({backend:function(e){let{req:t,session:r}=e;return{platform:r.device.platform,captureSnapshot:async(a,n)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:n?.interactiveOnly===!0})}),tap:async(n,s)=>U(await a(r.device,"press",[String(s.x),String(s.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fill:async(n,s,o)=>U(await a(r.device,"fill",[String(s.x),String(s.y),o],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),longPress:async(n,s,o)=>U(await a(r.device,"longpress",[String(s.x),String(s.y),...o?.durationMs===void 0?[]:[String(o.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(n,s)=>U(await a(r.device,"type",[s],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:n}),...k("interaction commands",{plural:!0}),sessions:t({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0},setRecord:t=>{t.snapshot&&(r(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function U(e){return e&&"object"==typeof e?e:void 0}function T(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}function H(e,t){let r=T(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let a=e[0]??"";if(a.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:a,fallbackLabel:v(e).label??""}};let n=e.join(" ").trim();return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:c("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}function K(e){return"ref"===e.kind?{ref:L(e.target?.kind==="ref"?e.target.ref:void 0),refLabel:e.refLabel,selectorChain:e.selectorChain}:"selector"===e.kind?{selector:e.target?.kind==="selector"?e.target.selector:void 0,selectorChain:e.selectorChain,refLabel:e.refLabel}:{}}function L(e){return e?.startsWith("@")?e.slice(1):e}async function j(e){switch(e.req.command){case"press":return await B(e,"press");case"click":return await B(e,"click");case"longpress":return await B(e,"longpress");case"fill":return await X(e);default:return null}}async function B(e,t){let r,{req:a,sessionName:s,sessionStore:u}=e,f=u.get(s);if(!f)return c("SESSION_NOT_FOUND","No active session. Run open first.");let d="click"===t?"click":t,p="longpress"===t?"longpress":"press",g=q(f,d);if(g)return g;if(!o(p,f.device))return c("UNSUPPORTED_OPERATION",`${p} is not supported on this device`);let m=l(a.flags),S=i(m);if("longpress"!==t&&"primary"!==m){let e=n({commandLabel:d,platform:f.device.platform,button:m,count:a.flags?.count,intervalMs:a.flags?.intervalMs,holdMs:a.flags?.holdMs,jitterPx:a.flags?.jitterPx,doubleTap:a.flags?.doubleTap});if(e)return c(e.code,e.message,e.details)}let _="longpress"===t?function(e){var t,r,a;let n,s=T(e);if(s){return{ok:!0,target:{kind:"point",x:s.x,y:s.y},...void 0===(t=e[2])?{}:{durationMs:Number(t)}}}let o=(n=(r=e).at(-1),r.length>1&&void 0!==(a=n)&&""!==a.trim()&&Number.isFinite(Number(a))?{targetPositionals:r.slice(0,-1),duration:{durationMs:Number(n)}}:{targetPositionals:r,duration:{}}),i=H(o.targetPositionals,"longpress");return i.ok?{ok:!0,target:i.target,...o.duration}:i}(a.positionals??[]):H(a.positionals??[],d);if(!_.ok)return _.response;if("ref"===_.target.kind){let n=e.refSnapshotFlagGuardResponse("longpress"===t?"longpress":"press",a.flags);if(n)return n;r=await J(e,f)}let k=function(e){var t;let{session:r,commandLabel:a,target:n,flags:s}=e;if("click"!==a||"selector"!==n.kind||(t=s,t?.count!==void 0||t?.intervalMs!==void 0||t?.holdMs!==void 0||t?.jitterPx!==void 0||t?.doubleTap!==void 0||t?.clickButton!==void 0&&"primary"!==t.clickButton))return null;let o=N({session:r,selectorExpression:n.selector});return o?{...o,...s?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:f,commandLabel:d,target:_.target,flags:a.flags});if(k){let t=await $(e,f,k);if(t)return t}let y="longpress"===t?_.durationMs:void 0;return await z(e,{androidFreshnessBaseline:r,run:async e=>await G({runtime:e,command:t,target:_.target,sessionName:s,requestId:a.meta?.requestId,clickButton:m,flags:a.flags,durationMs:y}),afterRun:async e=>{var t;await h(f,(t=_.target,"point"===t.kind?"coordinate tap":"ref"===e.kind&&e.target?.kind==="ref"?e.target.ref:"selector"===e.kind&&e.target?.kind==="selector"?e.target.selector:"target"))},buildPayloads:async r=>{var a;let n="durationMs"in(a=r)?a.durationMs:void 0,s=await W({params:e,session:f,result:r,extra:"longpress"===t?{...void 0!==n?{durationMs:n}:{},gesture:"longpress"}:S});return{result:s,responseData:s}}})}async function G(e){let{runtime:t,command:r,target:a,sessionName:n,requestId:s,flags:o}=e;if("longpress"===r)return await t.interactions.longPress(a,{session:n,requestId:s,durationMs:e.durationMs});let i={session:n,requestId:s,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap};return"click"===r?await t.interactions.click(a,i):await t.interactions.press(a,i)}async function W(e){let{params:t,session:r,result:a,extra:n}=e,s="point"===a.kind?await R({session:r,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):P(r.snapshot?.nodes??[]);return M({data:a.backendResult,fallbackX:a.point.x,fallbackY:a.point.y,referenceFrame:s,extra:{...K(a),...n}})}async function $(e,t,r){return await V({params:e,session:t,selector:r,command:"press",positionals:[],extra:{selector:r.raw},fallbackPhase:"ios_direct_selector_tap_fallback"})}async function V(e){let{params:t,session:r,selector:n,command:s,positionals:o,extra:i,fallbackPhase:l}=e,c=Date.now();try{var u,f;let e,l,d=await a(r.device,s,o,t.req.flags?.out,{...t.contextFromFlags(t.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:n,surface:r.surface})??{},p=Date.now(),g=(u=d,e="number"==typeof u.x?u.x:void 0,l="number"==typeof u.y?u.y:void 0,void 0!==e&&void 0!==l?{x:e,y:l}:{x:0,y:0}),m=M({data:d,fallbackX:g.x,fallbackY:g.y,referenceFrame:(f=d,"number"==typeof f.referenceWidth&&"number"==typeof f.referenceHeight?{referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight}:void 0),extra:{...i,...function(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let r="tapped via non-hittable coordinate fallback"===t.message;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:r,...r?{maestroFallbackReason:"non-hittable-coordinate"}:{}}}(n,d)}});return O({session:r,sessionStore:t.sessionStore,command:t.req.command,positionals:t.req.positionals??[],flags:t.req.flags,result:m,responseData:m,actionStartedAt:c,actionFinishedAt:p})}catch(e){if(!w(e))return{ok:!1,error:g(e)};return C({level:"debug",phase:l,data:{selector:n.raw,error:e instanceof Error?e.message:String(e)}}),null}}async function X(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(n){let e=q(n,"fill");if(e)return e}if(n&&!o("fill",n.device))return c("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!n)return c("SESSION_NOT_FOUND","No active session. Run open first.");let s=function(e){let t=e[0]??"";if(t.startsWith("@")){var r;let a=x(e).text;return a?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:(r=e).length>=3&&r[1]?.trim()||""},text:a}:{ok:!1,response:c("INVALID_ARGS","fill requires text after ref")}}let a=T(e);if(a){let t=e.slice(2).join(" ");return t?{ok:!0,target:{kind:"point",x:a.x,y:a.y},text:t}:{ok:!1,response:c("INVALID_ARGS","fill requires text after coordinates")}}let n=x(e);return"selector"!==n.kind?{ok:!1,response:c("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}:n.text.trim()?{ok:!0,target:{kind:"selector",selector:n.target.selector},text:n.text}:{ok:!1,response:c("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!s.ok)return s.response;if("ref"===s.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await J(e,n)}let i=function(e){let{session:t,target:r,flags:a}=e;if("selector"!==r.kind)return null;let n=N({session:t,selectorExpression:r.selector});return n?{...n,...a?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:n,target:s.target,flags:t.flags});if(i){let t=await Y(e,n,i,s.text);if(t)return t}return await z(e,{run:async e=>await e.interactions.fill(s.target,s.text,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),buildPayloads:e=>{let t="point"===e.kind?void 0:P(n.snapshot?.nodes??[]),r=M({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...K(e),text:s.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:L(e.target?.kind==="ref"?e.target.ref:void 0),x:e.point.x,y:e.point.y}}:r;return e.warning&&(a.warning=e.warning),{result:r,responseData:a}}})}async function Y(e,t,r,a){return await V({params:e,session:t,selector:r,command:"fill",positionals:[a],extra:{selector:r.raw,text:a},fallbackPhase:"ios_direct_selector_fill_fallback"})}async function z(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return c("SESSION_NOT_FOUND","No active session. Run open first.");let a=D(e),n=Date.now();try{let o=await s({session:r,command:e.req.command,phase:"before-command"}),i=await t.run(a);await t.afterRun?.(i),await s({session:r,command:e.req.command,phase:"after-command"});let l=Date.now(),{result:c,responseData:u}=await t.buildPayloads(i);return"recovered"===o.status&&(c.warning=o.warning,u.warning=o.warning),O({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags,result:c,responseData:u,actionStartedAt:n,actionFinishedAt:l,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=p(t);if(_(e))throw e;return{ok:!1,error:g(t)}}}async function J(e,t){if(!f(t))return;let r=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:"ref-refresh"})}catch(t){C({level:"warn",phase:"android_ref_snapshot_refresh_failed",data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return r}e.r(E),e.d(E,{INTERACTION_COMMAND_HANDLERS:()=>Q,handleInteractionCommands:()=>Z});let Q={[I.click]:!0,[I.fill]:!0,[I.get]:!0,[I.is]:!0,[I.longPress]:!0,[I.press]:!0,[I.type]:!0};async function Z(e){let t=await j({...e,captureSnapshotForSession:F,refSnapshotFlagGuardResponse:b});if(t)return t;switch(e.req.command){case I.type:return await ee({...e,captureSnapshotForSession:F});case"get":return await S(e);case"is":return await y(e);default:return null}}async function ee(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return c("SESSION_NOT_FOUND","No active session. Run open first.");if(!o(I.type,a.device))return c("UNSUPPORTED_OPERATION","type is not supported on this device");let n=await et(a);return n||await er(e,a)}async function et(e){return"android"===e.device.platform&&e.recording&&"failed"===await u({session:e})?c("COMMAND_FAILED","Android system dialog blocked the recording session"):null}async function er(e,t){let{req:r,sessionName:a,sessionStore:n}=e,o=(r.positionals??[]).join(" "),i=D(e),l=Date.now();try{let e=await s({session:t,command:r.command,phase:"before-command"}),c=await i.interactions.typeText(o,{session:a,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await s({session:t,command:r.command,phase:"after-command"});let u=Date.now(),f={...c.backendResult??{},text:c.text,delayMs:c.delayMs,...A(c.message??`Typed ${Array.from(c.text).length} chars`)};return"recovered"===e.status&&(f.warning=e.warning),O({session:t,sessionStore:n,command:r.command,positionals:r.positionals??[],flags:r.flags,result:f,responseData:f,actionStartedAt:l,actionFinishedAt:u})}catch(e){return{ok:!1,error:g(e)}}}export{E as interaction_namespaceObject};
|
|
1
|
+
import{__webpack_require__ as e}from"./rslib-runtime.js";import{createDaemonRuntimeSessionStore as t,setSessionSnapshot as r,dispatchCommand as a,getClickButtonValidationError as n,ensureAndroidBlockingSystemDialogReady as s,isCommandSupportedOnDevice as o,buttonTag as i,resolveClickButton as l,errorResponse as c,recoverAndroidBlockingSystemDialog as u,getActiveAndroidSnapshotFreshness as f}from"./2415.js";import{createAgentDevice as d}from"./9533.js";import{asAppError as p,normalizeError as g,AppError as m}from"./9152.js";import{dispatchGetViaRuntime as S,isAndroidEscapeError as k,createDaemonRuntimePolicy as _,assertAndroidPressStayedInApp as y,dispatchIsViaRuntime as h,isDirectIosSelectorFallbackError as w,refSnapshotFlagGuardResponse as b,readSimpleIosSelectorTarget as N}from"./selector-runtime.js";import{readInteractionTargetFromPositionals as v,readFillTargetFromPositionals as x}from"./8502.js";import{interaction_snapshot_captureSnapshotForSession as F,readSnapshotNodesReferenceFrame as P,resolveDirectTouchReferenceFrameSafely as R,buildTouchVisualizationResult as M,finalizeTouchInteraction as O}from"./9471.js";import{emitDiagnostic as C}from"./7599.js";import{PUBLIC_COMMANDS as I}from"./5792.js";import{successText as A}from"./1998.js";var E={};function q(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:c("UNSUPPORTED_OPERATION",`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function D(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new m("SESSION_NOT_FOUND","No active session. Run open first.");return d({backend:function(e){let{req:t,session:r}=e;return{platform:r.device.platform,captureSnapshot:async(a,n)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:n?.interactiveOnly===!0})}),tap:async(n,s)=>U(await a(r.device,"press",[String(s.x),String(s.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fill:async(n,s,o)=>U(await a(r.device,"fill",[String(s.x),String(s.y),o],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),longPress:async(n,s,o)=>U(await a(r.device,"longpress",[String(s.x),String(s.y),...o?.durationMs===void 0?[]:[String(o.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(n,s)=>U(await a(r.device,"type",[s],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:n}),..._("interaction commands",{plural:!0}),sessions:t({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0},setRecord:t=>{t.snapshot&&(r(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function U(e){return e&&"object"==typeof e?e:void 0}function T(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}function H(e,t){let r=T(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let a=e[0]??"";if(a.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:a,fallbackLabel:v(e).label??""}};let n=e.join(" ").trim();return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:c("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}function K(e){return"ref"===e.kind?{ref:L(e.target?.kind==="ref"?e.target.ref:void 0),refLabel:e.refLabel,selectorChain:e.selectorChain}:"selector"===e.kind?{selector:e.target?.kind==="selector"?e.target.selector:void 0,selectorChain:e.selectorChain,refLabel:e.refLabel}:{}}function L(e){return e?.startsWith("@")?e.slice(1):e}async function j(e){switch(e.req.command){case"press":return await B(e,"press");case"click":return await B(e,"click");case"longpress":return await B(e,"longpress");case"fill":return await X(e);default:return null}}async function B(e,t){let r,{req:a,sessionName:s,sessionStore:u}=e,f=u.get(s);if(!f)return c("SESSION_NOT_FOUND","No active session. Run open first.");let d="click"===t?"click":t,p="longpress"===t?"longpress":"press",g=q(f,d);if(g)return g;if(!o(p,f.device))return c("UNSUPPORTED_OPERATION",`${p} is not supported on this device`);let m=l(a.flags),S=i(m);if("longpress"!==t&&"primary"!==m){let e=n({commandLabel:d,platform:f.device.platform,button:m,count:a.flags?.count,intervalMs:a.flags?.intervalMs,holdMs:a.flags?.holdMs,jitterPx:a.flags?.jitterPx,doubleTap:a.flags?.doubleTap});if(e)return c(e.code,e.message,e.details)}let k="longpress"===t?function(e){var t,r,a;let n,s=T(e);if(s){return{ok:!0,target:{kind:"point",x:s.x,y:s.y},...void 0===(t=e[2])?{}:{durationMs:Number(t)}}}let o=(n=(r=e).at(-1),r.length>1&&void 0!==(a=n)&&""!==a.trim()&&Number.isFinite(Number(a))?{targetPositionals:r.slice(0,-1),duration:{durationMs:Number(n)}}:{targetPositionals:r,duration:{}}),i=H(o.targetPositionals,"longpress");return i.ok?{ok:!0,target:i.target,...o.duration}:i}(a.positionals??[]):H(a.positionals??[],d);if(!k.ok)return k.response;if("ref"===k.target.kind){let n=e.refSnapshotFlagGuardResponse("longpress"===t?"longpress":"press",a.flags);if(n)return n;r=await J(e,f)}let _=function(e){var t;let{session:r,commandLabel:a,target:n,flags:s}=e;if("click"!==a||"selector"!==n.kind||(t=s,t?.count!==void 0||t?.intervalMs!==void 0||t?.holdMs!==void 0||t?.jitterPx!==void 0||t?.doubleTap!==void 0||t?.clickButton!==void 0&&"primary"!==t.clickButton))return null;let o=N({session:r,selectorExpression:n.selector});return o?{...o,...s?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:f,commandLabel:d,target:k.target,flags:a.flags});if(_){let t=await $(e,f,_);if(t)return t}let h="longpress"===t?k.durationMs:void 0;return await z(e,{androidFreshnessBaseline:r,run:async e=>await G({runtime:e,command:t,target:k.target,sessionName:s,requestId:a.meta?.requestId,clickButton:m,flags:a.flags,durationMs:h}),afterRun:async e=>{var t;await y(f,(t=k.target,"point"===t.kind?"coordinate tap":"ref"===e.kind&&e.target?.kind==="ref"?e.target.ref:"selector"===e.kind&&e.target?.kind==="selector"?e.target.selector:"target"))},buildPayloads:async r=>{var a;let n="durationMs"in(a=r)?a.durationMs:void 0,s=await W({params:e,session:f,result:r,extra:"longpress"===t?{...void 0!==n?{durationMs:n}:{},gesture:"longpress"}:S});return{result:s,responseData:s}}})}async function G(e){let{runtime:t,command:r,target:a,sessionName:n,requestId:s,flags:o}=e;if("longpress"===r)return await t.interactions.longPress(a,{session:n,requestId:s,durationMs:e.durationMs});let i={session:n,requestId:s,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap};return"click"===r?await t.interactions.click(a,i):await t.interactions.press(a,i)}async function W(e){let{params:t,session:r,result:a,extra:n}=e,s="point"===a.kind?await R({session:r,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):P(r.snapshot?.nodes??[]);return M({data:a.backendResult,fallbackX:a.point.x,fallbackY:a.point.y,referenceFrame:s,extra:{...K(a),...n}})}async function $(e,t,r){return await V({params:e,session:t,selector:r,command:"press",positionals:[],extra:{selector:r.raw},fallbackPhase:"ios_direct_selector_tap_fallback"})}async function V(e){let{params:t,session:r,selector:n,command:s,positionals:o,extra:i,fallbackPhase:l}=e,c=Date.now();try{var u,f;let e,l,d=await a(r.device,s,o,t.req.flags?.out,{...t.contextFromFlags(t.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:n,surface:r.surface})??{},p=Date.now(),g=(u=d,e="number"==typeof u.x?u.x:void 0,l="number"==typeof u.y?u.y:void 0,void 0!==e&&void 0!==l?{x:e,y:l}:{x:0,y:0}),m=M({data:d,fallbackX:g.x,fallbackY:g.y,referenceFrame:(f=d,"number"==typeof f.referenceWidth&&"number"==typeof f.referenceHeight?{referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight}:void 0),extra:{...i,...function(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let r="tapped via non-hittable coordinate fallback"===t.message;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:r,...r?{maestroFallbackReason:"non-hittable-coordinate"}:{}}}(n,d)}});return O({session:r,sessionStore:t.sessionStore,command:t.req.command,positionals:t.req.positionals??[],retryPositionals:Q(g),flags:t.req.flags,result:m,responseData:m,actionStartedAt:c,actionFinishedAt:p})}catch(e){if(!w(e))return{ok:!1,error:g(e)};return C({level:"debug",phase:l,data:{selector:n.raw,error:e instanceof Error?e.message:String(e)}}),null}}async function X(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(n){let e=q(n,"fill");if(e)return e}if(n&&!o("fill",n.device))return c("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!n)return c("SESSION_NOT_FOUND","No active session. Run open first.");let s=function(e){let t=e[0]??"";if(t.startsWith("@")){var r;let a=x(e).text;return a?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:(r=e).length>=3&&r[1]?.trim()||""},text:a}:{ok:!1,response:c("INVALID_ARGS","fill requires text after ref")}}let a=T(e);if(a){let t=e.slice(2).join(" ");return t?{ok:!0,target:{kind:"point",x:a.x,y:a.y},text:t}:{ok:!1,response:c("INVALID_ARGS","fill requires text after coordinates")}}let n=x(e);return"selector"!==n.kind?{ok:!1,response:c("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}:n.text.trim()?{ok:!0,target:{kind:"selector",selector:n.target.selector},text:n.text}:{ok:!1,response:c("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!s.ok)return s.response;if("ref"===s.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await J(e,n)}let i=function(e){let{session:t,target:r,flags:a}=e;if("selector"!==r.kind)return null;let n=N({session:t,selectorExpression:r.selector});return n?{...n,...a?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:n,target:s.target,flags:t.flags});if(i){let t=await Y(e,n,i,s.text);if(t)return t}return await z(e,{run:async e=>await e.interactions.fill(s.target,s.text,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),buildPayloads:e=>{let t="point"===e.kind?void 0:P(n.snapshot?.nodes??[]),r=M({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...K(e),text:s.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:L(e.target?.kind==="ref"?e.target.ref:void 0),x:e.point.x,y:e.point.y}}:r;return e.warning&&(a.warning=e.warning),{result:r,responseData:a}}})}async function Y(e,t,r,a){return await V({params:e,session:t,selector:r,command:"fill",positionals:[a],extra:{selector:r.raw,text:a},fallbackPhase:"ios_direct_selector_fill_fallback"})}async function z(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return c("SESSION_NOT_FOUND","No active session. Run open first.");let a=D(e),n=Date.now();try{let o=await s({session:r,command:e.req.command,phase:"before-command"}),i=await t.run(a);await t.afterRun?.(i),await s({session:r,command:e.req.command,phase:"after-command"});let l=Date.now(),{result:c,responseData:u}=await t.buildPayloads(i);return"recovered"===o.status&&(c.warning=o.warning,u.warning=o.warning),O({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:function(e,t){if("click"===e||"press"===e)return Q(t.point)}(e.req.command,i),flags:e.req.flags,result:c,responseData:u,actionStartedAt:n,actionFinishedAt:l,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=p(t);if(k(e))throw e;return{ok:!1,error:g(t)}}}async function J(e,t){if(!f(t))return;let r=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:"ref-refresh"})}catch(t){C({level:"warn",phase:"android_ref_snapshot_refresh_failed",data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return r}function Q(e){return[String(e.x),String(e.y)]}e.r(E),e.d(E,{INTERACTION_COMMAND_HANDLERS:()=>Z,handleInteractionCommands:()=>ee});let Z={[I.click]:!0,[I.fill]:!0,[I.get]:!0,[I.is]:!0,[I.longPress]:!0,[I.press]:!0,[I.type]:!0};async function ee(e){let t=await j({...e,captureSnapshotForSession:F,refSnapshotFlagGuardResponse:b});if(t)return t;switch(e.req.command){case I.type:return await et({...e,captureSnapshotForSession:F});case"get":return await S(e);case"is":return await h(e);default:return null}}async function et(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return c("SESSION_NOT_FOUND","No active session. Run open first.");if(!o(I.type,a.device))return c("UNSUPPORTED_OPERATION","type is not supported on this device");let n=await er(a);return n||await ea(e,a)}async function er(e){return"android"===e.device.platform&&e.recording&&"failed"===await u({session:e})?c("COMMAND_FAILED","Android system dialog blocked the recording session"):null}async function ea(e,t){let{req:r,sessionName:a,sessionStore:n}=e,o=(r.positionals??[]).join(" "),i=D(e),l=Date.now();try{let e=await s({session:t,command:r.command,phase:"before-command"}),c=await i.interactions.typeText(o,{session:a,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await s({session:t,command:r.command,phase:"after-command"});let u=Date.now(),f={...c.backendResult??{},text:c.text,delayMs:c.delayMs,...A(c.message??`Typed ${Array.from(c.text).length} chars`)};return"recovered"===e.status&&(f.warning=e.warning),O({session:t,sessionStore:n,command:r.command,positionals:r.positionals??[],flags:r.flags,result:f,responseData:f,actionStartedAt:l,actionFinishedAt:u})}catch(e){return{ok:!1,error:g(e)}}}export{E as interaction_namespaceObject};
|
package/dist/src/react-native.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dispatchCommand as e,errorResponse as t,isCommandSupportedOnDevice as i}from"./2415.js";import{PUBLIC_COMMANDS as
|
|
1
|
+
import{dispatchCommand as e,errorResponse as t,isCommandSupportedOnDevice as i}from"./2415.js";import{PUBLIC_COMMANDS as a}from"./5792.js";import{analyzeReactNativeOverlay as r}from"./9533.js";import{normalizeError as n}from"./9152.js";import{stripUndefined as o}from"./7455.js";import{interaction_snapshot_captureSnapshotForSession as s,readSnapshotNodesReferenceFrame as d,finalizeTouchInteraction as c}from"./9471.js";import{successText as l}from"./1998.js";let v={[a.reactNative]:!0};async function f(e){var o;let{req:d,sessionName:c,sessionStore:v}=e;if(d.command!==a.reactNative)return null;let f=1===(o=d.positionals??[]).length&&"dismiss-overlay"===o[0]?{ok:!0}:{ok:!1,response:t("INVALID_ARGS","react-native supports only: dismiss-overlay")};if(!f.ok)return f.response;let _=v.get(c);if(!_)return t("SESSION_NOT_FOUND","No active session. Run open first.");if(!i(a.reactNative,_.device))return t("UNSUPPORTED_OPERATION","react-native dismiss-overlay is not supported on this device");try{let i=await s(_,d.flags,v,e.contextFromFlags,{interactiveOnly:!0}),a=r(i.nodes),n=a.primaryAction;if(!n)return a.detected?t("COMMAND_FAILED","React Native overlay detected, but no safe dismiss target was found",{hint:"Use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing the warning body."}):{ok:!0,data:{action:"dismiss-overlay",detected:!1,dismissed:!1,...l("No React Native overlay detected")}};return await m(e,_,i,n)}catch(e){return{ok:!1,error:n(e)}}}async function m(t,i,a,r){let{req:n,sessionStore:s}=t,v=Date.now(),f=await e(i.device,"press",[String(r.point.x),String(r.point.y)],n.flags?.out,t.contextFromFlags(n.flags,i.appBundleId,i.trace?.outPath))??{},m=Date.now(),p=await _(t,i),y=o({...d(a.nodes),...f,action:"dismiss-overlay",overlayAction:r.action,x:r.point.x,y:r.point.y,ref:r.ref,label:r.label,warning:r.warning,dismissed:!0,verified:p.verified,verificationRequired:!p.verified,verificationWarning:p.verificationWarning,nextCommand:p.nextCommand,...l(p.verified?"React Native overlay dismiss action sent and verified gone":"React Native overlay dismiss action sent, but verification still detects an overlay")});return c({session:i,sessionStore:s,command:n.command,positionals:n.positionals??[],flags:n.flags,result:y,responseData:y,actionStartedAt:v,actionFinishedAt:m})}async function _(e,t){let{req:i,sessionStore:a}=e;return r((await s(t,i.flags,a,e.contextFromFlags,{interactiveOnly:!0})).nodes).detected?{verified:!1,verificationWarning:"React Native overlay is still detected after dismissal. Use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing the warning body.",nextCommand:"agent-device screenshot --overlay-refs"}:{verified:!0}}export{v as REACT_NATIVE_COMMAND_HANDLERS,f as handleReactNativeCommands};
|
package/dist/src/record-trace.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let e,t,r,a;import{__webpack_require__ as i}from"./rslib-runtime.js";import o from"node:fs";import n from"node:path";import{createHash as s}from"node:crypto";import c from"node:os";import{setTimeout as d}from"node:timers/promises";import{fileURLToPath as l}from"node:url";import{AppError as u}from"./9152.js";import{runCmd as m}from"./9818.js";import{sleep as f}from"./4829.js";import{withDiagnosticTimer as p,emitDiagnostic as h}from"./7599.js";import{androidDeviceForSerial as w,runAndroidAdb as g}from"./8806.js";import{pullAndroidAdbFile as y}from"./9639.js";import{runXcrun as _,SessionStore as v,runIosRunnerCommand as P,errorResponse as S,isCommandSupportedOnDevice as A,ensureDeviceReady as C,resolveTargetDevice as b,IOS_RUNNER_CONTAINER_BUNDLE_IDS as M}from"./2415.js";import{resolveRecordingProvider as I}from"./recording-provider.js";import{PUBLIC_COMMANDS as x}from"./5792.js";var D={};function R(e=process.env){let t
|
|
1
|
+
let e,t,r,a;import{__webpack_require__ as i}from"./rslib-runtime.js";import o from"node:fs";import n from"node:path";import{createHash as s}from"node:crypto";import c from"node:os";import{setTimeout as d}from"node:timers/promises";import{fileURLToPath as l}from"node:url";import{AppError as u}from"./9152.js";import{runCmd as m}from"./9818.js";import{sleep as f}from"./4829.js";import{withDiagnosticTimer as p,emitDiagnostic as h}from"./7599.js";import{androidDeviceForSerial as w,runAndroidAdb as g}from"./8806.js";import{pullAndroidAdbFile as y}from"./9639.js";import{runXcrun as _,SessionStore as v,runIosRunnerCommand as P,errorResponse as S,isCommandSupportedOnDevice as A,ensureDeviceReady as C,resolveTargetDevice as b,IOS_RUNNER_CONTAINER_BUNDLE_IDS as M}from"./2415.js";import{resolveRecordingProvider as I}from"./recording-provider.js";import{PUBLIC_COMMANDS as x}from"./5792.js";var D={};function R(e=process.env){let t=E(),r=n.join(t,"home"),a=n.join(t,"module-cache");return o.mkdirSync(r,{recursive:!0}),o.mkdirSync(a,{recursive:!0}),{...e,HOME:r,CLANG_MODULE_CACHE_PATH:a}}async function N(e){let t=o.statSync(e.sourcePath),r=o.readFileSync(e.sourcePath),a=T(e.cacheName??n.basename(e.sourcePath,n.extname(e.sourcePath))),i=L(["2",process.platform,process.arch,n.resolve(e.sourcePath),t.size,r]),s=n.join(E(),"bin",`${a}-${i}`);return await k({sourcePath:e.sourcePath,executablePath:s,timeoutMs:e.timeoutMs}),s}async function $(e){let t=T(e.cacheName),r=L(["2",process.platform,process.arch,e.source]),a=n.join(E(),"sources",`${t}-${r}.swift`),i=n.join(E(),"bin",`${t}-${r}`);return await k({sourcePath:a,executablePath:i,sourceText:e.source,timeoutMs:e.timeoutMs}),i}function E(){let e=process.env.AGENT_DEVICE_SWIFT_CACHE_DIR?.trim();return e?n.resolve(e):n.join(c.tmpdir(),"agent-device-swift-cache")}async function k(e){if(O(e.executablePath))return;let t=n.dirname(e.executablePath);o.mkdirSync(t,{recursive:!0});let r=`${e.executablePath}.lock`;if(!await F(r,e.executablePath,e.timeoutMs??12e4))return;let a=o.mkdtempSync(n.join(t,`.${n.basename(e.executablePath)}.${process.pid}.`)),i=n.join(a,n.basename(e.executablePath));try{if(O(e.executablePath))return;void 0===e.sourceText||o.existsSync(e.sourcePath)||(o.mkdirSync(n.dirname(e.sourcePath),{recursive:!0}),o.writeFileSync(e.sourcePath,e.sourceText)),await m("xcrun",["swiftc",e.sourcePath,"-o",i],{timeoutMs:e.timeoutMs??12e4,env:R()}),o.renameSync(i,e.executablePath)}finally{o.rmSync(a,{recursive:!0,force:!0}),o.rmSync(r,{recursive:!0,force:!0})}}async function F(e,t,r){let a=Date.now()+r;for(;;){if(O(t))return!1;try{return o.mkdirSync(e),!0}catch(t){if("EEXIST"!==t.code)throw t;if(function(e,t){try{return Date.now()-o.statSync(e).mtimeMs>=t}catch{return!1}}(e,r)){o.rmSync(e,{recursive:!0,force:!0});continue}if(Date.now()>=a)throw new u("COMMAND_FAILED",`Timed out waiting for Swift cache lock: ${e} (${r}ms)`,{lockDir:e,timeoutMs:r,hint:`Another agent-device process may still be compiling this Swift helper. Retry shortly; if no agent-device process is active, remove "${e}" and retry.`});await d(25)}}}function O(e){try{return o.accessSync(e,o.constants.X_OK),o.statSync(e).isFile()}catch{return!1}}function T(e){return e.replaceAll(/[^A-Za-z0-9._-]/g,"-").replaceAll(/^-+|-+$/g,"")||"swift-helper"}function L(e){let t=s("sha256");for(let r of e)t.update(Buffer.isBuffer(r)?r:String(r)),t.update("\0");return t.digest("hex").slice(0,16)}i.r(D),i.d(D,{RECORD_TRACE_COMMAND_HANDLERS:()=>eY,handleRecordTraceCommands:()=>e0});let U=`
|
|
2
2
|
import Foundation
|
|
3
3
|
import AVFoundation
|
|
4
4
|
|
|
@@ -22,5 +22,5 @@ Task {
|
|
|
22
22
|
|
|
23
23
|
semaphore.wait()
|
|
24
24
|
exit(exitCode)
|
|
25
|
-
`.trim();async function
|
|
26
|
-
${t}`;return/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swiftc?["']|xcrun: error: unable to find utility ["']swiftc?["'])\b/i.test(r)}function H(e){try{let t=o.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=o.openSync(e,"r");try{let e=o.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>o.readSync(t,e,0,8,r))break;let i=e.readUInt32BE(0),n=e.toString("latin1",4,8);if(a.push(n),1===i){let e=Buffer.alloc(8);if(8>o.readSync(t,e,0,8,r+8))break;i=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(i)||i<=0)break;r+=i}return a}finally{o.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function j(e){let t=n.parse(e);return n.join(t.dir,`${t.name}.gesture-telemetry.json`)}function B(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function W(e){var t,r,a;let i,n,{recording:s,trimStartMs:c}=e,d=(i=j((t={videoPath:s.outPath,events:s.gestureEvents,trimStartMs:c}).videoPath),n={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?B(r.flatMap(e=>{let t=e.tMs-a,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):B(r))},o.writeFileSync(i,JSON.stringify(n,null,2)),i);return s.telemetryPath=d,d}function X(e){let t=n.dirname(l(import.meta.url)),r=[l(new URL(`./${e}`,import.meta.url)),n.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(o.existsSync(e))return e;throw new u("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}async function J(e){var t;let r,a,{videoPath:i,scriptPath:s,scriptArgs:c,commandDescription:d}=e;await K(i),await V(i);let l=(t=i,r=n.parse(t),a=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,n.join(r.dir,`.${r.name}.agent-device-${a}${r.ext||".mp4"}`));try{let e=await N({sourcePath:s});await m(e,["--input",i,"--output",l,...c],{timeoutMs:12e4,env:R()}),await V(l),o.renameSync(l,i)}catch(t){let e=t instanceof u?t:new u("COMMAND_FAILED",String(t),void 0,t instanceof Error?t:void 0);throw new u("COMMAND_FAILED",d,{...e.details,videoPath:i,script:s},e)}finally{o.rmSync(l,{force:!0})}}async function Z(e){let{videoPath:t,trimStartMs:a}=e;a>0&&await J({videoPath:t,scriptPath:r??=X("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function Q(e){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=e;await J({videoPath:r,scriptPath:t??=X("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function Y(e){let{videoPath:t,quality:r,targetLabel:i="recording"}=e;await J({videoPath:t,scriptPath:a??=X("recording-resize.swift"),scriptArgs:["--quality",String(r)],commandDescription:`Failed to resize the ${i}`})}function ee(e){return e instanceof Error?e.message:String(e)}function et(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function er(e){let{recording:t,deps:r,trimStartMs:a,targetLabel:i}=e,o=W({recording:t,trimStartMs:a});if(!t.showTouches)return void h({level:"debug",phase:"record_stop_overlay_skipped",data:{reason:"hide_touches"}});if(0===t.gestureEvents.length)return void h({level:"debug",phase:"record_stop_overlay_skipped",data:{reason:"no_gesture_events"}});let n=function(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}();if(n){t.overlayWarning??=n;return}try{await p("record_stop_overlay_export",()=>r.overlayRecordingTouches({videoPath:t.outPath,telemetryPath:o,targetLabel:i}),{targetLabel:i,gestureEventCount:t.gestureEvents.length})}catch(e){t.overlayWarning??=`failed to overlay recording touches: ${ee(e)}`}}function ea(e,t){if(1===t)return e;let r=n.parse(e),a=r.ext||".mp4";return n.join(r.dir,`${r.name}.part-${String(t).padStart(3,"0")}${a}`)}function ei(e){return e.chunks??=[{index:1,path:e.outPath,remotePath:e.remotePath}],e.chunks}async function eo(e){let{recording:t,startNextChunk:r,finishCurrentChunk:a}=e;if(t.stopping)return;let i=await a();if(i)throw Error(i);if(t.stopping)return;let o=ei(t),s=o.length+1,c=await r(n.posix.dirname(t.remotePath));t.remotePath=c.remotePath,t.remotePid=c.remotePid,o.push({index:s,path:ea(t.outPath,s),remotePath:c.remotePath}),t.warning??="Android adb screenrecord is capped at 180s, so this recording was split into multiple MP4 chunks."}async function en(e){let{recording:t,deps:r}=e;ei(t).length<=1?await er({recording:t,deps:r,targetLabel:"Android recording"}):(W({recording:t}),t.showTouches&&t.gestureEvents.length>0&&(t.overlayWarning??="touch overlay burn-in is skipped for chunked Android recordings; returning raw chunks plus gesture telemetry"))}async function es(e){for(let t of e.chunks){let r=await ec({deps:e.deps,deviceId:e.deviceId,remotePath:t.remotePath,outPath:t.path});if(r)return`failed to copy recording chunk ${t.index}: ${r}`}}async function ec(e){let t,{deps:r,deviceId:a,remotePath:i,outPath:n}=e;for(let e=0;e<2;e+=1){try{o.rmSync(n,{force:!0})}catch{}let s=w(a),c=await y(i,n,{allowFailure:!0,device:s});if(0!==c.exitCode)t=et(c,"adb pull");else{await r.waitForStableFile(n,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(n);if(h({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1,fileSize:function(e){try{return o.statSync(e).size}catch{return 0}}(n),playable:t}}),t)return;h({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1}})}e<1&&await f(750)}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function ed(e,t,r){return await g(w(e),t,r)}async function el(e,t){let r=await ed(e,["shell","ps","-o","pid=","-p",t],{allowFailure:!0});return 0===r.exitCode&&r.stdout.split(/\s+/).map(e=>e.trim()).includes(t)}async function eu(e,t){for(let r=0;r<40;r+=1){if(!await el(e,t))return!0;await f(250)}return!await el(e,t)}async function em(e,t){let r,a=0;for(let i=0;i<20;i+=1){let i=await ed(e,["shell","stat","-c","%s",t],{allowFailure:!0}),o=0===i.exitCode?i.stdout.trim():"";if(o.length>0&&o===r){if((a+=1)>=4)return}else a=0;r=o,await f(250)}}async function ef(e,t,r){for(let a=0;a<8;a+=1){let i=await ed(e,["shell","stat","-c","%s",t],{allowFailure:!0}),o=0===i.exitCode?Number(i.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await el(e,r))break;if(a+1>=2)return!0;await f(250)}return!1}async function ep(e){let{deviceId:t,quality:r}=e;if(void 0===r||r>=10)return;let a=await ed(t,["shell","wm","size"],{allowFailure:!0}),i=a.stdout.match(/Override size:\s*(\d+)x(\d+)/)??a.stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(0!==a.exitCode||!i)throw Error(`failed to resolve Android screen size for recording quality: ${et(a,"adb shell wm size")}`);return{width:eh(Number(i[1]),r),height:eh(Number(i[2]),r)}}function eh(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function ew(e,t){await ed(e,["shell","rm","-f",t],{allowFailure:!0})}async function eg(e,t){let r=await ed(e,["shell","kill","-9",t],{allowFailure:!0});return h({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:e,remotePid:t,exitCode:r.exitCode,stdout:r.stdout.trim(),stderr:r.stderr.trim()}}),!(0!==r.exitCode&&await el(e,t))&&await eu(e,t)}async function ey(e){var t;let r,a,{device:i,recordingSize:o,preferredRemoteDir:n}=e,s="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,a=["/sdcard","/data/local/tmp"],(n&&a.includes(n)?[n,...a.filter(e=>e!==n)]:a).map(e=>`${e}/${r}`))){let t=await ed(i.id,["shell",function(e,t){let r=["screenrecord"];return t&&r.push("--size",`${t.width}x${t.height}`),r.push(e),`${r.join(" ")} >/dev/null 2>&1 & echo $!`}(e,o)],{allowFailure:!0});if(0!==t.exitCode){s=`failed to start recording: ${et(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){s="failed to start recording: adb did not return a valid Android screenrecord pid",await ew(i.id,e);continue}if(h({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await ef(i.id,e,r))return{remotePath:e,remotePid:r,startedAt:Date.now()};s="failed to start recording: Android screenrecord did not begin producing frames",await eg(i.id,r),await ew(i.id,e)}return{error:S("COMMAND_FAILED",s)}}async function e_(e){let t,{device:r,recordingBase:a}=e;try{t=await ep({deviceId:r.id,quality:a.quality})}catch(e){return S("COMMAND_FAILED",e instanceof Error?e.message:String(e))}let i=await ey({device:r,recordingSize:t});if("error"in i)return i.error;let o={platform:"android",remotePath:i.remotePath,remotePid:i.remotePid,chunks:[{index:1,path:a.outPath,remotePath:i.remotePath}],...a,startedAt:i.startedAt};return!function e(t){let{recording:r,startNextChunk:a,finishCurrentChunk:i}=t,o=setTimeout(()=>{r.rotationPromise=eo({recording:r,startNextChunk:a,finishCurrentChunk:i}).catch(e=>{r.rotationFailedReason=e instanceof Error?e.message:String(e)}).finally(()=>{r.rotationPromise=void 0,r.stopping||r.rotationFailedReason||e({recording:r,startNextChunk:a,finishCurrentChunk:i})})},17e4);o.unref?.(),r.rotationTimer=o}({recording:o,finishCurrentChunk:async()=>await ev({device:r,recording:o,waitForRemoteFileStability:!1}),startNextChunk:async e=>{let a=await ey({device:r,recordingSize:t,preferredRemoteDir:e});if("error"in a)throw Error(a.error.ok?"failed to start next Android recording chunk":a.error.error.message);return a}}),o}async function ev(e){let{device:t,recording:r,waitForRemoteFileStability:a=!0}=e;await el(t.id,r.remotePid)||(r.warning??=function(e){if(!(Date.now()-e.startedAt<178e3))return"Android adb screenrecord stopped before record stop, likely after reaching the 180s platform limit. The MP4 may be truncated; final interactions after the limit are not in the video."}(r));let i=await ed(t.id,["shell","kill","-2",r.remotePid],{allowFailure:!0});if(h({level:"debug",phase:"record_stop_android_signal",data:{deviceId:t.id,remotePath:r.remotePath,remotePid:r.remotePid,exitCode:i.exitCode,stdout:i.stdout.trim(),stderr:i.stderr.trim()}}),0!==i.exitCode)return await eP(t.id,r.remotePid,i);let o=await eS(t.id,r.remotePid);if(o)return o;a&&await em(t.id,r.remotePath)}async function eP(e,t,r){if(await el(e,t)&&!await eg(e,t))return`failed to stop recording: ${et(r,"adb shell kill")}`}async function eS(e,t){if(!await eu(e,t)&&!await eg(e,t))return`failed to stop recording: Android screenrecord pid ${t} did not exit`}async function eA(e){let t,{deps:r,device:a,recording:i}=e;h({level:"debug",phase:"record_stop_android_enter",data:{deviceId:a.id,remotePath:i.remotePath,remotePid:i.remotePid}}),i.stopping=!0,i.rotationTimer&&(clearTimeout(i.rotationTimer),i.rotationTimer=void 0),await i.rotationPromise;let o=await ev({device:a,recording:i});if(i.rotationFailedReason&&!o&&(i.warning??=`Android recording chunk rotation failed: ${i.rotationFailedReason}`),!o){let e=await es({deps:r,deviceId:a.id,chunks:ei(i)});if(e)return await n(),S("COMMAND_FAILED",e);await en({recording:i,deps:r})}if(await n(),o)return S("COMMAND_FAILED",o);if(t)return S("COMMAND_FAILED",t);return null;async function n(){for(let e of ei(i)){let r=await ed(a.id,["shell","rm","-f",e.remotePath],{allowFailure:!0});h({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:a.id,remotePath:e.remotePath,exitCode:r.exitCode,stdout:r.stdout.trim(),stderr:r.stderr.trim()}}),0===r.exitCode||o||(t=`failed to clean up remote recording: ${et(r,"adb shell rm")}`)}}}function eC(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function eb(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath,requestId:e.meta?.requestId}}async function eM(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o}=e,n=eC(r);try{await o.runIosRunnerCommand(a,{command:"recordStop",appBundleId:n},eb(t,i,r))}catch(e){h({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:ee(e)}})}}async function eI(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o}=e,n=eC(r);if(n)try{await o.runIosRunnerCommand(a,{command:"snapshot",appBundleId:n,interactiveOnly:!0,compact:!0,depth:1},eb(t,i,r))}catch(e){h({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:n,error:ee(e)}})}}async function ex(e){let t,r,{req:a,activeSession:i,sessionStore:o,device:n,logPath:s,deps:c,fpsFlag:d,recordingBase:l,appBundleId:u}=e,m=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${m}`,p=eb(a,s,i),w=async()=>c.runIosRunnerCommand(n,{command:"recordStart",outPath:m,fps:d,quality:l.quality,appBundleId:u},p);try{let e=await w();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var g,y;if(!ee(a).toLowerCase().includes("recording already in progress"))return S("COMMAND_FAILED",`failed to start recording: ${ee(a)}`);h({level:"warn",phase:"record_start_runner_desynced",data:{platform:n.platform,kind:n.kind,deviceId:n.id,session:i.name,error:ee(a)}});let e=(g=n.id,y=i.name,o.toArray().find(e=>e.name!==y&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===g&&e.recording?.platform==="ios-device-runner"));if(e)return S("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await c.runIosRunnerCommand(n,{command:"recordStop",appBundleId:u},p)}catch{}try{let e=await w();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return S("COMMAND_FAILED",`failed to start recording: ${ee(e)}`)}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...l}}async function eD(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o,fpsFlag:n,recordingBase:s,appBundleId:c}=e;try{await o.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:n,quality:s.quality,appBundleId:c},eb(t,i,r))}catch(e){return S("COMMAND_FAILED",`failed to start recording: ${ee(e)}`)}return{platform:"macos-runner",...s}}async function eR(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o,recording:n}=e;await eM({req:t,activeSession:r,device:a,logPath:i,deps:o});let s={stdout:"",stderr:"",exitCode:1};for(let e of M)if(0===(s=await o.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",n.remotePath,"--destination",n.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==s.exitCode){let e=s.stderr.trim()||s.stdout.trim()||`devicectl exited with code ${s.exitCode}`;return S("COMMAND_FAILED",`failed to copy recording from device: ${e}`)}let c="number"!=typeof n.runnerStartedAtUptimeMs||"number"!=typeof n.targetAppReadyUptimeMs?0:Math.max(0,n.targetAppReadyUptimeMs-n.runnerStartedAtUptimeMs);return c>0&&await o.trimRecordingStart({videoPath:n.outPath,trimStartMs:c}),await er({recording:n,deps:o,trimStartMs:c,targetLabel:"iOS recording"}),null}async function eN(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o,recording:n}=e;return await eM({req:t,activeSession:r,device:a,logPath:i,deps:o}),await er({recording:n,deps:o,targetLabel:"macOS recording"}),null}async function eE(e){let{deps:t,recording:r}=e;r.child.kill("SIGINT");let a=await e$(r.wait,5e3);return a||(await eF(t,r,"SIGINT"),(a=await e$(r.wait,2e3))||(r.child.kill("SIGTERM"),await eF(t,r,"SIGTERM"),a=await e$(r.wait,2e3)))?a:(r.child.kill("SIGKILL"),await eF(t,r,"SIGKILL"),await e$(r.wait,2e3))}async function e$(e,t){return await Promise.race([e,f(t).then(()=>null)])}async function eF(e,t,r){await eO(e,t,r)||await ek(e,t.outPath,r)}async function ek(e,t,r){let a,i=`simctl.*recordVideo.*${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}`;try{a=await e.runCmd("pgrep",["-f",i],{allowFailure:!0})}catch(e){h({level:"warn",phase:"record_stop_ios_simulator_pgrep_failed",data:{outPath:t,signal:r,error:ee(e)}});return}let o=eT(eK(a.stdout)),n=eU(o,r);h({level:n>0?"warn":"debug",phase:"record_stop_ios_simulator_signal_recorders",data:{outPath:t,signal:r,matchedPidCount:o.length,signaled:n,pgrepExitCode:a.exitCode}})}async function eO(e,t,r){let a=t.recorderPid??t.child.pid;if("number"!=typeof a||!Number.isInteger(a)||a<=0)return h({level:"debug",phase:"record_stop_ios_simulator_owned_recorder_unavailable",data:{outPath:t.outPath,signal:r,reason:"missing_recorder_pid"}}),!1;let i=await eL(e,a,t.outPath,r),o=eT([a,...i.pids]),n=eU(o,r);return h({level:n>0?"warn":"debug",phase:"record_stop_ios_simulator_signal_owned_recorder",data:{outPath:t.outPath,signal:r,recorderPid:a,childPidCount:i.pids.length,matchedPidCount:o.length,signaled:n,pgrepExitCode:i.exitCode}}),n>0}async function eL(e,t,r,a){let i;try{i=await e.runCmd("pgrep",["-P",String(t)],{allowFailure:!0})}catch(e){return h({level:"warn",phase:"record_stop_ios_simulator_owned_pgrep_failed",data:{outPath:r,signal:a,parentPid:t,error:ee(e)}}),{pids:[]}}return{pids:eK(i.stdout),exitCode:i.exitCode}}function eT(e){return Array.from(new Set(e)).filter(e=>Number.isInteger(e)&&e>0&&e!==process.pid)}function eU(e,t){let r=0;for(let a of e)try{process.kill(a,t),r+=1}catch{}return r}function eK(e){return e.split(/\s+/).map(e=>Number(e)).filter(e=>Number.isInteger(e)&&e>0)}async function ez(e){"ios"!==e.platform||0!==e.gestureEvents.length&&await f(350)}async function eq(e){for(let t=0;t<2;t+=1){try{if(o.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await f(250)}return Date.now()}async function eV(e){let t,r,{req:a,activeSession:i,device:o,logPath:n,deps:s,recordingBase:c,resolvedOut:d}=e;c.showTouches&&await eI({req:a,activeSession:i,device:o,logPath:n,deps:s});let{child:l,wait:u}=s.startIosSimulatorRecording({device:o,outPath:d}),m=await eq(d);if(c.showTouches)try{let e=Date.now(),c=await s.runIosRunnerCommand(o,{command:"uptime",appBundleId:eC(i)},eb(a,n,i)),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof c.currentUptimeMs?c.currentUptimeMs:void 0}catch{}return{platform:"ios",child:l,wait:u,...c,recorderPid:l.pid,startedAt:m,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function eG(e){let t,{req:r,sessionName:a,sessionStore:i,activeSession:s,device:c,logPath:d,deps:l}=e;if(s.recording)return S("INVALID_ARGS","recording already in progress");let u=r.flags?.fps,m=r.flags?.quality;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return S("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==m&&(!Number.isInteger(m)||m<5||m>10))return S("INVALID_ARGS","quality must be an integer between 5 and 10");if(!A("record",c))return S("UNSUPPORTED_OPERATION","record is not supported on this device");let f=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,p=v.expandHome(f,r.meta?.cwd),h={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),quality:r.flags?.quality,showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(o.mkdirSync(n.dirname(p),{recursive:!0}),o.rmSync(p,{force:!0}),"ios"===c.platform&&"device"===c.kind){let e=eC(s);if(!e)return S("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await ex({req:r,activeSession:s,sessionStore:i,device:c,logPath:d,deps:l,fpsFlag:u,recordingBase:h,appBundleId:e})}else if("macos"===c.platform){let e=eC(s);if(!e)return S("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await eD({req:r,activeSession:s,device:c,logPath:d,deps:l,fpsFlag:u,recordingBase:h,appBundleId:e})}else t="ios"===c.platform?await eV({req:r,activeSession:s,device:c,logPath:d,deps:l,recordingBase:h,resolvedOut:p}):await e_({device:c,recordingBase:h});return"ok"in t?t:(s.recording=t,i.set(a,s),i.recordAction(s,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??f,showTouches:t.showTouches}})}async function eH(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await eA({deps:t,device:r,recording:a});await p("record_stop_tail_settle",()=>t.waitForRecordingTail(a),{platform:a.platform,gestureEventCount:a.gestureEvents.length});let i=await p("record_stop_ios_simulator_process",()=>eE({deps:t,recording:a}),{outPath:a.outPath});if(!i)return S("COMMAND_FAILED","failed to stop recording: simctl recordVideo did not exit after 5000ms and forced cleanup");if(0!==i.exitCode)return S("COMMAND_FAILED",`failed to stop recording: ${et(i,"simctl recordVideo")}`);if(await p("record_stop_video_stable",()=>t.waitForStableFile(a.outPath,{pollMs:150,attempts:12}),{outPath:a.outPath}),!await p("record_stop_video_playable_check",()=>t.isPlayableVideo(a.outPath),{outPath:a.outPath}))return S("COMMAND_FAILED",`failed to stop recording: ${a.outPath} was not finalized into a playable video`);if(void 0!==a.quality&&a.quality<10){let e=a.quality;try{await p("record_stop_resize",()=>t.resizeRecording({videoPath:a.outPath,quality:e,targetLabel:"iOS recording"}),{outPath:a.outPath,quality:e})}catch(e){a.overlayWarning=`failed to resize recording: ${ee(e)}`}}return await p("record_stop_finalize_overlay",()=>er({recording:a,deps:t,targetLabel:"iOS recording"}),{outPath:a.outPath,showTouches:a.showTouches,gestureEventCount:a.gestureEvents.length}),null}async function ej(e){var t;let r,a,{req:i,activeSession:o,device:s,logPath:c,deps:d}=e;if(!o.recording)return S("INVALID_ARGS","no active recording");let l=o.recording,u=l.invalidatedReason;o.recording=void 0;let m="ios-device-runner"===l.platform?await eR({req:i,activeSession:o,device:s,logPath:c,deps:d,recording:l}):"macos-runner"===l.platform?await eN({req:i,activeSession:o,device:s,logPath:c,deps:d,recording:l}):await eH({deps:d,device:s,recording:l});if(m)return m;if(u&&"ios"===l.platform&&l.showTouches)l.overlayWarning??=`overlay unavailable: ${u}`;else if(u)return S("COMMAND_FAILED",u);return r="android"===(t=l).platform?t.chunks:void 0,a=[{field:"outPath",path:t.outPath,localPath:t.clientOutPath,fileName:n.basename(t.clientOutPath??t.outPath)}],r&&r.length>1&&a.push(...r.slice(1).map(e=>({field:"chunkPath",path:e.path,localPath:eB(t,e.index),fileName:n.basename(eB(t,e.index)??e.path)}))),t.telemetryPath&&a.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return j(e.clientOutPath)}(t),fileName:n.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:a,showTouches:t.showTouches,warning:t.warning,overlayWarning:t.overlayWarning,chunks:r?.map(e=>({index:e.index,path:eB(t,e.index)??e.path}))}}}function eB(e,t){if("android"===e.platform&&e.clientOutPath)return ea(e.clientOutPath,t)}async function eW(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,o={runCmd:async(e,t,r)=>"xcrun"===e?await _(t,r):await m(e,t,r),startIosSimulatorRecording:e=>I().startIosSimulatorRecording(e),runIosRunnerCommand:P,waitForRecordingTail:ez,waitForStableFile:K,isPlayableVideo:z,trimRecordingStart:Z,resizeRecording:Y,overlayRecordingTouches:Q},n=a.get(r),s=n?.device??await b(t.flags??{});n||await C(s);let c=n??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return S("INVALID_ARGS","record requires start|stop");if("start"===d)return eG({req:t,sessionName:r,sessionStore:a,activeSession:c,device:s,logPath:i,deps:o});let l=await ej({req:t,activeSession:c,device:s,logPath:i,deps:o});return l.ok&&a.recordAction(c,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l.data?.outPath,showTouches:l.data?.showTouches}}),l}let eX={[x.record]:!0,[x.trace]:!0};async function eJ(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,s=t.command;if("record"===s)return eW({req:t,sessionName:r,sessionStore:a,logPath:i});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return S("INVALID_ARGS","trace requires start|stop");let i=a.get(r);if(!i)return S("SESSION_NOT_FOUND","No active session");if("start"===e){if(i.trace)return S("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(i),r=v.expandHome(e);return o.mkdirSync(n.dirname(r),{recursive:!0}),o.appendFileSync(r,""),i.trace={outPath:r,startedAt:Date.now()},a.recordAction(i,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!i.trace)return S("INVALID_ARGS","no active trace");let c=i.trace.outPath;if(t.positionals?.[1]){let e=v.expandHome(t.positionals[1]);o.mkdirSync(n.dirname(e),{recursive:!0}),o.existsSync(c)?o.renameSync(c,e):o.appendFileSync(e,""),c=e}return i.trace=void 0,a.recordAction(i,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:c}}),{ok:!0,data:{trace:"stopped",outPath:c}}}return null}export{D as record_trace_namespaceObject};
|
|
25
|
+
`.trim();async function z(e,t={}){let r,a=t.pollMs??150,i=t.attempts??12,n=0;for(let t=0;t<i;t+=1){let t=0;try{t=o.statSync(e).size}catch{t=0}if(t>0&&t===r){if((n+=1)>=2)return}else n=0;r=t,await f(a)}}async function K(e){try{let t=await q(),r=await m(t,[e],{allowFailure:!0,timeoutMs:1e4,env:R()});if(0===r.exitCode)return!0;if(G(r.stderr,r.stdout))return H(e);return!1}catch(r){var t;if((t=r)instanceof u&&("TOOL_MISSING"===t.code||G(String(t.details?.stderr??""),String(t.details?.stdout??""))))return H(e);throw r}}async function q(){e??=$({source:U,cacheName:"video-validator",timeoutMs:3e4});try{return await e}catch(t){throw e=void 0,t}}async function V(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await K(e))return;await f(r)}}function G(e,t){let r=`${e}
|
|
26
|
+
${t}`;return/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swiftc?["']|xcrun: error: unable to find utility ["']swiftc?["'])\b/i.test(r)}function H(e){try{let t=o.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=o.openSync(e,"r");try{let e=o.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>o.readSync(t,e,0,8,r))break;let i=e.readUInt32BE(0),n=e.toString("latin1",4,8);if(a.push(n),1===i){let e=Buffer.alloc(8);if(8>o.readSync(t,e,0,8,r+8))break;i=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(i)||i<=0)break;r+=i}return a}finally{o.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function j(e){let t=n.parse(e);return n.join(t.dir,`${t.name}.gesture-telemetry.json`)}function B(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function W(e){var t,r,a;let i,n,{recording:s,trimStartMs:c}=e,d=(i=j((t={videoPath:s.outPath,events:s.gestureEvents,trimStartMs:c}).videoPath),n={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?B(r.flatMap(e=>{let t=e.tMs-a,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):B(r))},o.writeFileSync(i,JSON.stringify(n,null,2)),i);return s.telemetryPath=d,d}function X(e){let t=n.dirname(l(import.meta.url)),r=[l(new URL(`./${e}`,import.meta.url)),n.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),n.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(o.existsSync(e))return e;throw new u("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}async function J(e){var t;let r,a,{videoPath:i,scriptPath:s,scriptArgs:c,commandDescription:d}=e;await z(i),await V(i);let l=(t=i,r=n.parse(t),a=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,n.join(r.dir,`.${r.name}.agent-device-${a}${r.ext||".mp4"}`));try{let e=await N({sourcePath:s});await m(e,["--input",i,"--output",l,...c],{timeoutMs:12e4,env:R()}),await V(l),o.renameSync(l,i)}catch(t){let e=t instanceof u?t:new u("COMMAND_FAILED",String(t),void 0,t instanceof Error?t:void 0);throw new u("COMMAND_FAILED",d,{...e.details,videoPath:i,script:s},e)}finally{o.rmSync(l,{force:!0})}}async function Z(e){let{videoPath:t,trimStartMs:a}=e;a>0&&await J({videoPath:t,scriptPath:r??=X("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(a)],commandDescription:"Failed to trim the start of the iOS recording"})}async function Q(e){let{videoPath:r,telemetryPath:a,targetLabel:i="recording"}=e;await J({videoPath:r,scriptPath:t??=X("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}async function Y(e){let{videoPath:t,quality:r,targetLabel:i="recording"}=e;await J({videoPath:t,scriptPath:a??=X("recording-resize.swift"),scriptArgs:["--quality",String(r)],commandDescription:`Failed to resize the ${i}`})}function ee(e){return e instanceof Error?e.message:String(e)}function et(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}function er(e,t,r=Date.now()){let a=Math.max(0,r-t.startedAt);return a>=1e3?{message:e,tooShort:!1}:{message:`${e}. Recording stopped after ${Math.round(a)}ms; wait at least 1000ms between record start and record stop so the recorder can finalize a playable MP4`,tooShort:!0}}async function ea(e){let{recording:t,deps:r,trimStartMs:a,targetLabel:i}=e,o=W({recording:t,trimStartMs:a});if(!t.showTouches)return void h({level:"debug",phase:"record_stop_overlay_skipped",data:{reason:"hide_touches"}});if(0===t.gestureEvents.length)return void h({level:"debug",phase:"record_stop_overlay_skipped",data:{reason:"no_gesture_events"}});let n=function(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}();if(n){t.overlayWarning??=n;return}try{await p("record_stop_overlay_export",()=>r.overlayRecordingTouches({videoPath:t.outPath,telemetryPath:o,targetLabel:i}),{targetLabel:i,gestureEventCount:t.gestureEvents.length})}catch(e){t.overlayWarning??=`failed to overlay recording touches: ${ee(e)}`}}function ei(e,t){if(1===t)return e;let r=n.parse(e),a=r.ext||".mp4";return n.join(r.dir,`${r.name}.part-${String(t).padStart(3,"0")}${a}`)}function eo(e){return e.chunks??=[{index:1,path:e.outPath,remotePath:e.remotePath}],e.chunks}async function en(e){let{recording:t,startNextChunk:r,finishCurrentChunk:a}=e;if(t.stopping)return;let i=await a();if(i)throw Error(i);if(t.stopping)return;let o=eo(t),s=o.length+1,c=await r(n.posix.dirname(t.remotePath));t.remotePath=c.remotePath,t.remotePid=c.remotePid,o.push({index:s,path:ei(t.outPath,s),remotePath:c.remotePath}),t.warning??="Android adb screenrecord is capped at 180s, so this recording was split into multiple MP4 chunks."}async function es(e){let{recording:t,deps:r}=e;eo(t).length<=1?await ea({recording:t,deps:r,targetLabel:"Android recording"}):(W({recording:t}),t.showTouches&&t.gestureEvents.length>0&&(t.overlayWarning??="touch overlay burn-in is skipped for chunked Android recordings; returning raw chunks plus gesture telemetry"))}async function ec(e){for(let t of e.chunks){let r=await ed({deps:e.deps,deviceId:e.deviceId,remotePath:t.remotePath,outPath:t.path});if(r)return`failed to copy recording chunk ${t.index}: ${r}`}}async function ed(e){let t,{deps:r,deviceId:a,remotePath:i,outPath:n}=e;for(let e=0;e<2;e+=1){el(n);let s=w(a),c=await y(i,n,{allowFailure:!0,device:s});if(0!==c.exitCode)t=et(c,"adb pull");else{await r.waitForStableFile(n,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(n);if(h({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1,fileSize:function(e){try{return o.statSync(e).size}catch{return 0}}(n),playable:t}}),t)return;h({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1}})}e<1&&await f(750)}return t?`failed to copy recording from device: ${t}`:(el(n),"failed to copy recording from device: pulled file is not a playable MP4")}function el(e){try{o.rmSync(e,{force:!0})}catch{}}async function eu(e,t,r){return await g(w(e),t,r)}async function em(e,t){let r=await eu(e,["shell","ps","-o","pid=","-p",t],{allowFailure:!0});return 0===r.exitCode&&r.stdout.split(/\s+/).map(e=>e.trim()).includes(t)}async function ef(e,t){for(let r=0;r<40;r+=1){if(!await em(e,t))return!0;await f(250)}return!await em(e,t)}async function ep(e,t){let r,a=0;for(let i=0;i<20;i+=1){let i=await eu(e,["shell","stat","-c","%s",t],{allowFailure:!0}),o=0===i.exitCode?i.stdout.trim():"";if(o.length>0&&o===r){if((a+=1)>=4)return}else a=0;r=o,await f(250)}}async function eh(e,t,r){for(let a=0;a<8;a+=1){let i=await eu(e,["shell","stat","-c","%s",t],{allowFailure:!0}),o=0===i.exitCode?Number(i.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await em(e,r))break;if(a+1>=2)return!0;await f(250)}return!1}async function ew(e){let{deviceId:t,quality:r}=e;if(void 0===r||r>=10)return;let a=await eu(t,["shell","wm","size"],{allowFailure:!0}),i=a.stdout.match(/Override size:\s*(\d+)x(\d+)/)??a.stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(0!==a.exitCode||!i)throw Error(`failed to resolve Android screen size for recording quality: ${et(a,"adb shell wm size")}`);return{width:eg(Number(i[1]),r),height:eg(Number(i[2]),r)}}function eg(e,t){return Math.max(2,2*Math.round(e*t/10/2))}async function ey(e,t){await eu(e,["shell","rm","-f",t],{allowFailure:!0})}async function e_(e,t){let r=await eu(e,["shell","kill","-9",t],{allowFailure:!0});return h({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:e,remotePid:t,exitCode:r.exitCode,stdout:r.stdout.trim(),stderr:r.stderr.trim()}}),!(0!==r.exitCode&&await em(e,t))&&await ef(e,t)}async function ev(e){var t;let r,a,{device:i,recordingSize:o,preferredRemoteDir:n}=e,s="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,a=["/sdcard","/data/local/tmp"],(n&&a.includes(n)?[n,...a.filter(e=>e!==n)]:a).map(e=>`${e}/${r}`))){let t=await eu(i.id,["shell",function(e,t){let r=["screenrecord"];return t&&r.push("--size",`${t.width}x${t.height}`),r.push(e),`${r.join(" ")} >/dev/null 2>&1 & echo $!`}(e,o)],{allowFailure:!0});if(0!==t.exitCode){s=`failed to start recording: ${et(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){s="failed to start recording: adb did not return a valid Android screenrecord pid",await ey(i.id,e);continue}if(h({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await eh(i.id,e,r))return{remotePath:e,remotePid:r,startedAt:Date.now()};s="failed to start recording: Android screenrecord did not begin producing frames",await e_(i.id,r),await ey(i.id,e)}return{error:S("COMMAND_FAILED",s)}}async function eP(e){let t,{device:r,recordingBase:a}=e;try{t=await ew({deviceId:r.id,quality:a.quality})}catch(e){return S("COMMAND_FAILED",e instanceof Error?e.message:String(e))}let i=await ev({device:r,recordingSize:t});if("error"in i)return i.error;let o={platform:"android",remotePath:i.remotePath,remotePid:i.remotePid,chunks:[{index:1,path:a.outPath,remotePath:i.remotePath}],...a,startedAt:i.startedAt};return!function e(t){let{recording:r,startNextChunk:a,finishCurrentChunk:i}=t,o=setTimeout(()=>{r.rotationPromise=en({recording:r,startNextChunk:a,finishCurrentChunk:i}).catch(e=>{r.rotationFailedReason=e instanceof Error?e.message:String(e)}).finally(()=>{r.rotationPromise=void 0,r.stopping||r.rotationFailedReason||e({recording:r,startNextChunk:a,finishCurrentChunk:i})})},17e4);o.unref?.(),r.rotationTimer=o}({recording:o,finishCurrentChunk:async()=>await eS({device:r,recording:o,waitForRemoteFileStability:!1}),startNextChunk:async e=>{let a=await ev({device:r,recordingSize:t,preferredRemoteDir:e});if("error"in a)throw Error(a.error.ok?"failed to start next Android recording chunk":a.error.error.message);return a}}),o}async function eS(e){let{device:t,recording:r,waitForRemoteFileStability:a=!0}=e;await em(t.id,r.remotePid)||(r.warning??=function(e){if(!(Date.now()-e.startedAt<178e3))return"Android adb screenrecord stopped before record stop, likely after reaching the 180s platform limit. The MP4 may be truncated; final interactions after the limit are not in the video."}(r));let i=await eu(t.id,["shell","kill","-2",r.remotePid],{allowFailure:!0});if(h({level:"debug",phase:"record_stop_android_signal",data:{deviceId:t.id,remotePath:r.remotePath,remotePid:r.remotePid,exitCode:i.exitCode,stdout:i.stdout.trim(),stderr:i.stderr.trim()}}),0!==i.exitCode)return await eA(t.id,r.remotePid,i);let o=await eC(t.id,r.remotePid);if(o)return o;a&&await ep(t.id,r.remotePath)}async function eA(e,t,r){if(await em(e,t)&&!await e_(e,t))return`failed to stop recording: ${et(r,"adb shell kill")}`}async function eC(e,t){if(!await ef(e,t)&&!await e_(e,t))return`failed to stop recording: Android screenrecord pid ${t} did not exit`}async function eb(e){let t,{deps:r,device:a,recording:i,stopRequestedAt:o}=e;h({level:"debug",phase:"record_stop_android_enter",data:{deviceId:a.id,remotePath:i.remotePath,remotePid:i.remotePid}}),i.stopping=!0,i.rotationTimer&&(clearTimeout(i.rotationTimer),i.rotationTimer=void 0),await i.rotationPromise;let n=await eS({device:a,recording:i});if(i.rotationFailedReason&&!n&&(i.warning??=`Android recording chunk rotation failed: ${i.rotationFailedReason}`),!n){let e=await ec({deps:r,deviceId:a.id,chunks:eo(i)});if(e)return await s(),S("COMMAND_FAILED",eM(e,i,o));await es({recording:i,deps:r})}if(await s(),n)return S("COMMAND_FAILED",eM(n,i,o));if(t)return S("COMMAND_FAILED",t);return null;async function s(){for(let e of eo(i)){let r=await eu(a.id,["shell","rm","-f",e.remotePath],{allowFailure:!0});h({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:a.id,remotePath:e.remotePath,exitCode:r.exitCode,stdout:r.stdout.trim(),stderr:r.stderr.trim()}}),0===r.exitCode||n||(t=`failed to clean up remote recording: ${et(r,"adb shell rm")}`)}}}function eM(e,t,r){return er(e,t,r).message}function eI(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function ex(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath,requestId:e.meta?.requestId}}async function eD(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o}=e,n=eI(r);try{await o.runIosRunnerCommand(a,{command:"recordStop",appBundleId:n},ex(t,i,r))}catch(e){h({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:ee(e)}})}}async function eR(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o}=e,n=eI(r);if(n)try{await o.runIosRunnerCommand(a,{command:"snapshot",appBundleId:n,interactiveOnly:!0,compact:!0,depth:1},ex(t,i,r))}catch(e){h({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:n,error:ee(e)}})}}async function eN(e){let t,r,{req:a,activeSession:i,sessionStore:o,device:n,logPath:s,deps:c,fpsFlag:d,recordingBase:l,appBundleId:u}=e,m=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${m}`,p=ex(a,s,i),w=async()=>c.runIosRunnerCommand(n,{command:"recordStart",outPath:m,fps:d,quality:l.quality,appBundleId:u},p);try{let e=await w();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var g,y;if(!ee(a).toLowerCase().includes("recording already in progress"))return S("COMMAND_FAILED",`failed to start recording: ${ee(a)}`);h({level:"warn",phase:"record_start_runner_desynced",data:{platform:n.platform,kind:n.kind,deviceId:n.id,session:i.name,error:ee(a)}});let e=(g=n.id,y=i.name,o.toArray().find(e=>e.name!==y&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===g&&e.recording?.platform==="ios-device-runner"));if(e)return S("COMMAND_FAILED",`failed to start recording: recording already in progress in session '${e.name}'`);try{await c.runIosRunnerCommand(n,{command:"recordStop",appBundleId:u},p)}catch{}try{let e=await w();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return S("COMMAND_FAILED",`failed to start recording: ${ee(e)}`)}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...l}}async function e$(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o,fpsFlag:n,recordingBase:s,appBundleId:c}=e;try{await o.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:n,quality:s.quality,appBundleId:c},ex(t,i,r))}catch(e){return S("COMMAND_FAILED",`failed to start recording: ${ee(e)}`)}return{platform:"macos-runner",...s}}async function eE(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o,recording:n}=e;await eD({req:t,activeSession:r,device:a,logPath:i,deps:o});let s={stdout:"",stderr:"",exitCode:1};for(let e of M)if(0===(s=await o.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",n.remotePath,"--destination",n.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==s.exitCode){let e=s.stderr.trim()||s.stdout.trim()||`devicectl exited with code ${s.exitCode}`;return S("COMMAND_FAILED",`failed to copy recording from device: ${e}`)}let c="number"!=typeof n.runnerStartedAtUptimeMs||"number"!=typeof n.targetAppReadyUptimeMs?0:Math.max(0,n.targetAppReadyUptimeMs-n.runnerStartedAtUptimeMs);return c>0&&await o.trimRecordingStart({videoPath:n.outPath,trimStartMs:c}),await ea({recording:n,deps:o,trimStartMs:c,targetLabel:"iOS recording"}),null}async function ek(e){let{req:t,activeSession:r,device:a,logPath:i,deps:o,recording:n}=e;return await eD({req:t,activeSession:r,device:a,logPath:i,deps:o}),await ea({recording:n,deps:o,targetLabel:"macOS recording"}),null}async function eF(e){let{deps:t,recording:r}=e;r.child.kill("SIGINT");let a=await eO(r.wait,5e3);return a||(await eT(t,r,"SIGINT"),(a=await eO(r.wait,2e3))||(r.child.kill("SIGTERM"),await eT(t,r,"SIGTERM"),a=await eO(r.wait,2e3)))?a:(r.child.kill("SIGKILL"),await eT(t,r,"SIGKILL"),await eO(r.wait,2e3))}async function eO(e,t){return await Promise.race([e,f(t).then(()=>null)])}async function eT(e,t,r){await eU(e,t,r)||await eL(e,t.outPath,r)}async function eL(e,t,r){let a,i=`simctl.*recordVideo.*${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}`;try{a=await e.runCmd("pgrep",["-f",i],{allowFailure:!0})}catch(e){h({level:"warn",phase:"record_stop_ios_simulator_pgrep_failed",data:{outPath:t,signal:r,error:ee(e)}});return}let o=eK(eV(a.stdout)),n=eq(o,r);h({level:n>0?"warn":"debug",phase:"record_stop_ios_simulator_signal_recorders",data:{outPath:t,signal:r,matchedPidCount:o.length,signaled:n,pgrepExitCode:a.exitCode}})}async function eU(e,t,r){let a=t.recorderPid??t.child.pid;if("number"!=typeof a||!Number.isInteger(a)||a<=0)return h({level:"debug",phase:"record_stop_ios_simulator_owned_recorder_unavailable",data:{outPath:t.outPath,signal:r,reason:"missing_recorder_pid"}}),!1;let i=await ez(e,a,t.outPath,r),o=eK([a,...i.pids]),n=eq(o,r);return h({level:n>0?"warn":"debug",phase:"record_stop_ios_simulator_signal_owned_recorder",data:{outPath:t.outPath,signal:r,recorderPid:a,childPidCount:i.pids.length,matchedPidCount:o.length,signaled:n,pgrepExitCode:i.exitCode}}),n>0}async function ez(e,t,r,a){let i;try{i=await e.runCmd("pgrep",["-P",String(t)],{allowFailure:!0})}catch(e){return h({level:"warn",phase:"record_stop_ios_simulator_owned_pgrep_failed",data:{outPath:r,signal:a,parentPid:t,error:ee(e)}}),{pids:[]}}return{pids:eV(i.stdout),exitCode:i.exitCode}}function eK(e){return Array.from(new Set(e)).filter(e=>Number.isInteger(e)&&e>0&&e!==process.pid)}function eq(e,t){let r=0;for(let a of e)try{process.kill(a,t),r+=1}catch{}return r}function eV(e){return e.split(/\s+/).map(e=>Number(e)).filter(e=>Number.isInteger(e)&&e>0)}async function eG(e){"ios"!==e.platform||0!==e.gestureEvents.length&&await f(350)}async function eH(e){for(let t=0;t<2;t+=1){try{if(o.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await f(250)}return Date.now()}async function ej(e){let t,r,{req:a,activeSession:i,device:o,logPath:n,deps:s,recordingBase:c,resolvedOut:d}=e;c.showTouches&&await eR({req:a,activeSession:i,device:o,logPath:n,deps:s});let{child:l,wait:u}=s.startIosSimulatorRecording({device:o,outPath:d}),m=await eH(d);if(c.showTouches)try{let e=Date.now(),c=await s.runIosRunnerCommand(o,{command:"uptime",appBundleId:eI(i)},ex(a,n,i)),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof c.currentUptimeMs?c.currentUptimeMs:void 0}catch{}return{platform:"ios",child:l,wait:u,...c,recorderPid:l.pid,startedAt:m,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function eB(e){let t,{req:r,sessionName:a,sessionStore:i,activeSession:s,device:c,logPath:d,deps:l}=e;if(s.recording)return S("INVALID_ARGS","recording already in progress");let u=r.flags?.fps,m=r.flags?.quality;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return S("INVALID_ARGS","fps must be an integer between 1 and 120");if(void 0!==m&&(!Number.isInteger(m)||m<5||m>10))return S("INVALID_ARGS","quality must be an integer between 5 and 10");if(!A("record",c))return S("UNSUPPORTED_OPERATION","record is not supported on this device");let f=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,p=v.expandHome(f,r.meta?.cwd),h={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),quality:r.flags?.quality,showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(o.mkdirSync(n.dirname(p),{recursive:!0}),o.rmSync(p,{force:!0}),"ios"===c.platform&&"device"===c.kind){let e=eI(s);if(!e)return S("INVALID_ARGS","record on physical iOS devices requires an active app session; run open <app> first");t=await eN({req:r,activeSession:s,sessionStore:i,device:c,logPath:d,deps:l,fpsFlag:u,recordingBase:h,appBundleId:e})}else if("macos"===c.platform){let e=eI(s);if(!e)return S("INVALID_ARGS","record on macOS requires an active app session; run open <app> first");t=await e$({req:r,activeSession:s,device:c,logPath:d,deps:l,fpsFlag:u,recordingBase:h,appBundleId:e})}else t="ios"===c.platform?await ej({req:r,activeSession:s,device:c,logPath:d,deps:l,recordingBase:h,resolvedOut:p}):await eP({device:c,recordingBase:h});return"ok"in t?t:(s.recording=t,i.set(a,s),i.recordAction(s,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??f,showTouches:t.showTouches}})}async function eW(e){let{deps:t,device:r,recording:a,stopRequestedAt:i}=e;if("android"===a.platform)return await eb({deps:t,device:r,recording:a,stopRequestedAt:i});await p("record_stop_tail_settle",()=>t.waitForRecordingTail(a),{platform:a.platform,gestureEventCount:a.gestureEvents.length});let o=await p("record_stop_ios_simulator_process",()=>eF({deps:t,recording:a}),{outPath:a.outPath});if(!o)return eX("failed to stop recording: simctl recordVideo did not exit after 5000ms and forced cleanup",a,i);if(0!==o.exitCode)return eX(`failed to stop recording: ${et(o,"simctl recordVideo")}`,a,i);if(await p("record_stop_video_stable",()=>t.waitForStableFile(a.outPath,{pollMs:150,attempts:12}),{outPath:a.outPath}),!await p("record_stop_video_playable_check",()=>t.isPlayableVideo(a.outPath),{outPath:a.outPath}))return eX(`failed to stop recording: ${a.outPath} was not finalized into a playable video`,a,i);if(void 0!==a.quality&&a.quality<10){let e=a.quality;try{await p("record_stop_resize",()=>t.resizeRecording({videoPath:a.outPath,quality:e,targetLabel:"iOS recording"}),{outPath:a.outPath,quality:e})}catch(e){a.overlayWarning=`failed to resize recording: ${ee(e)}`}}return await p("record_stop_finalize_overlay",()=>ea({recording:a,deps:t,targetLabel:"iOS recording"}),{outPath:a.outPath,showTouches:a.showTouches,gestureEventCount:a.gestureEvents.length}),null}function eX(e,t,r){let a=er(e,t,r);return function(e){try{o.rmSync(e,{force:!0})}catch{}}(t.outPath),S("COMMAND_FAILED",a.message)}async function eJ(e){var t;let r,a,{req:i,activeSession:o,device:s,logPath:c,deps:d}=e;if(!o.recording)return S("INVALID_ARGS","no active recording");let l=o.recording,u=Date.now(),m=l.invalidatedReason;o.recording=void 0;let f="ios-device-runner"===l.platform?await eE({req:i,activeSession:o,device:s,logPath:c,deps:d,recording:l}):"macos-runner"===l.platform?await ek({req:i,activeSession:o,device:s,logPath:c,deps:d,recording:l}):await eW({deps:d,device:s,recording:l,stopRequestedAt:u});if(f)return f;if(m&&"ios"===l.platform&&l.showTouches)l.overlayWarning??=`overlay unavailable: ${m}`;else if(m)return S("COMMAND_FAILED",m);return r="android"===(t=l).platform?t.chunks:void 0,a=[{field:"outPath",path:t.outPath,localPath:t.clientOutPath,fileName:n.basename(t.clientOutPath??t.outPath)}],r&&r.length>1&&a.push(...r.slice(1).map(e=>({field:"chunkPath",path:e.path,localPath:eZ(t,e.index),fileName:n.basename(eZ(t,e.index)??e.path)}))),t.telemetryPath&&a.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return j(e.clientOutPath)}(t),fileName:n.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:a,showTouches:t.showTouches,warning:t.warning,overlayWarning:t.overlayWarning,chunks:r?.map(e=>({index:e.index,path:eZ(t,e.index)??e.path}))}}}function eZ(e,t){if("android"===e.platform&&e.clientOutPath)return ei(e.clientOutPath,t)}async function eQ(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,o={runCmd:async(e,t,r)=>"xcrun"===e?await _(t,r):await m(e,t,r),startIosSimulatorRecording:e=>I().startIosSimulatorRecording(e),runIosRunnerCommand:P,waitForRecordingTail:eG,waitForStableFile:z,isPlayableVideo:K,trimRecordingStart:Z,resizeRecording:Y,overlayRecordingTouches:Q},n=a.get(r),s=n?.device??await b(t.flags??{});n||await C(s);let c=n??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return S("INVALID_ARGS","record requires start|stop");if("start"===d)return eB({req:t,sessionName:r,sessionStore:a,activeSession:c,device:s,logPath:i,deps:o});let l=await eJ({req:t,activeSession:c,device:s,logPath:i,deps:o});return l.ok&&a.recordAction(c,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:l.data?.outPath,showTouches:l.data?.showTouches}}),l}let eY={[x.record]:!0,[x.trace]:!0};async function e0(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,s=t.command;if("record"===s)return eQ({req:t,sessionName:r,sessionStore:a,logPath:i});if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return S("INVALID_ARGS","trace requires start|stop");let i=a.get(r);if(!i)return S("SESSION_NOT_FOUND","No active session");if("start"===e){if(i.trace)return S("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(i),r=v.expandHome(e);return o.mkdirSync(n.dirname(r),{recursive:!0}),o.appendFileSync(r,""),i.trace={outPath:r,startedAt:Date.now()},a.recordAction(i,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!i.trace)return S("INVALID_ARGS","no active trace");let c=i.trace.outPath;if(t.positionals?.[1]){let e=v.expandHome(t.positionals[1]);o.mkdirSync(n.dirname(e),{recursive:!0}),o.existsSync(c)?o.renameSync(c,e):o.appendFileSync(e,""),c=e}return i.trace=void 0,a.recordAction(i,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:c}}),{ok:!0,data:{trace:"stopped",outPath:c}}}return null}export{D as record_trace_namespaceObject};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDaemonRuntimeSessionStore as e,setSessionSnapshot as t,captureSnapshot as r,dispatchCommand as n,runIosRunnerCommand as s,isCommandSupportedOnDevice as o,errorResponse as i,ensureDeviceReady as a,isApplePlatform as l,stopIosRunnerSession as u,getActiveAndroidSnapshotFreshness as c,resolveTargetDevice as d,context_contextFromFlags as f}from"./2415.js";import{asAppError as p,normalizeError as m,AppError as g}from"./9152.js";import{evaluateIsPredicate as h,isSupportedPredicate as y,localCommandPolicy as w,resolveRectCenter as _,createAgentDevice as S}from"./9533.js";import{emitDiagnostic as x}from"./7599.js";import{tryParseSelectorChain as k,normalizeType as I,extractNodeReadText as v,findNodeByLabel as A,splitIsSelectorArgs as N}from"./940.js";import{getAndroidAppState as P}from"./8806.js";import{parseWaitPositionals as R}from"./6085.js";import{parseFindArgs as b}from"./7556.js";import{buildSnapshotPresentationKey as q,snapshotPresentationOptionsFromFlags as C}from"./4057.js";async function M(e,t,r){let n=e.get(t),s=n?.device??await d(r??{});return n||await a(s),{session:n,device:s}}async function D(e,t,r){let n=!e&&"ios"===t.platform;try{return await r()}finally{n&&await u(t.id)}}function E(e,t,r,n){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function O(e){let{session:t,sessionName:r,device:n,snapshot:s,appBundleId:o}=e;return t?{...t,snapshot:s}:{name:r,device:n,createdAt:Date.now(),appBundleId:o,snapshot:s,actions:[]}}function $(e,t={}){return{artifacts:function(e,t={}){let r=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new g("UNSUPPORTED_OPERATION",`${e} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new g("UNSUPPORTED_OPERATION",`${e} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new g("UNSUPPORTED_OPERATION",`${e} ${r} not create temporary files`)}}}(e,t),policy:w()}}async function L(e){let{device:t,node:r,flags:s,appBundleId:o,traceOutPath:i,surface:a,contextFromFlags:l}=e,u=v(r),c=_(r.rect);if(!c)return u;try{let e=await n(t,"read",[String(c.x),String(c.y)],void 0,{...l(s,o,i),surface:a}),d=e&&"object"==typeof e?e:void 0,f="string"==typeof d?.text?d.text:"";if(f.trim())return f;return x({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:a,platform:t.platform}}),u}catch(e){return x({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:a,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),u}}let U=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function K(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,n]of U)void 0!==e[r]&&t.push(n);return t}(t);return 0===r.length?null:i("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function T(e,t){let r=await G(e);if(r)throw new g("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${r.foregroundPackage}. The tap likely escaped the app.`,r)}async function G(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let r=await P(e.device),n=r.package?.trim();return n&&n!==e.appBundleId&&("com.android.settings"===(t=n)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:n,activity:r.activity,hint:"com.google.android.permissioncontroller"===n?"Dismiss or allow the permission prompt, then retry the smoke assertion.":"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."}:null}function V(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function F(e,t){let r=Array.isArray(e.selectorChain)?e.selectorChain:void 0,n=W(e),s=n?.kind==="ref"?z(n.ref):void 0,o=n?.kind==="selector"?n.selector:void 0,i={...s?{ref:s}:{},...o?{selector:o}:{},...r?{selectorChain:r}:{}};if("attrs"===t)return i;let a="string"==typeof e.text?e.text:"";return{...i,text:a,refLabel:function(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}(a)}}function B(e){let t=W(e);return{...t?.kind==="ref"?{ref:z(t.ref)}:{},...t?.kind==="selector"?{selector:t.selector}:{},..."string"==typeof e.text?{text:e.text}:{},...e.node&&"object"==typeof e.node?{node:e.node}:{}}}function j(e){let{selectorChain:t,...r}=e;return r}function H(e,t,r,n){let s=e.get(t);s&&e.recordAction(s,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function W(e){let t=e.target;return t&&"object"==typeof t?"ref"===t.kind&&"string"==typeof t.ref?{kind:"ref",ref:t.ref}:"selector"===t.kind&&"string"==typeof t.selector?{kind:"selector",selector:t.selector}:void 0:void 0}function z(e){return e.startsWith("@")?e.slice(1):e}let J=["application","window","tabbar","scrollbar","image"],Q=new Set(["tab bar"]);async function X(e,t){var r;if(t.ok||(r=t.error.message,!/^wait timed out for (?:selector|text): /i.test(r)))return t;let n=await Y(e).catch(()=>null);return n?i(t.error.code,`${t.error.message}. Current surface: ${n.summary}.`,{...t.error.details??{},currentSurface:n.details}):t}async function Y(e){let t=[...(await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!0,snapshotCompact:!0},logPath:e.logPath??""})).snapshot.nodes].sort(ee),n=Z(t,6,{includeIdentifiers:!0});if(0===n.length)return null;let s=Z(t.filter(e=>!en(e)),4,{includeIdentifiers:!1}),o=Z(t.filter(es),4,{includeIdentifiers:!0});return{summary:(s.length>0?s:n.slice(0,4)).join(", "),details:{labels:n,...o.length>0?{buttons:o}:{}}}}function Z(e,t,r){let n=new Set,s=[];for(let o of e){let e=er(o,r);if(!(!e||n.has(e))&&(n.add(e),s.push(e),s.length>=t))break}return s}function ee(e,t){var r,n;return et(e)-et(t)||(r=e,n=t,r.rect&&n.rect?r.rect.y-n.rect.y||r.rect.x-n.rect.x:r.rect?-1:n.rect?1:(r.depth??0)-(n.depth??0)||r.index-n.index)}function et(e){let t=!!er(e,{includeIdentifiers:!1});return 2*!!en(e)+ +!t}function er(e,t){let r=(t.includeIdentifiers?[e.label,e.value,e.identifier]:[e.label,e.value]).map(e=>"string"==typeof e?e.trim():"").find(e=>e.length>0);return r?r.replace(/\s+/g," ").slice(0,80):""}function en(e){let t=I(`${e.type??""} ${e.role??""} ${e.subrole??""}`),r=`${e.label??""} ${e.value??""}`.trim().toLowerCase();return J.some(e=>t.includes(e))||Q.has(r)||r.endsWith(".fill")}function es(e){return I(`${e.type??""} ${e.role??""} ${e.subrole??""}`).includes("button")}function eo(e){var t;let{session:r,selectorExpression:n}=e;if(!r||"ios"!==r.device.platform||r.postGestureStabilization)return null;let s=k(n);if(!s||1!==s.selectors.length)return null;let o=s.selectors[0];if(!o||1!==o.terms.length)return null;let i=o.terms[0];return i&&"string"==typeof i.value&&("id"===(t=i.key)||"label"===t||"text"===t||"value"===t)?{key:i.key,value:i.value,raw:o.raw}:null}function ei(e){let t=p(e);if("COMMAND_FAILED"!==t.code)return!1;let r=t.message.toLowerCase();return r.includes("fetch failed")||r.includes("timed out")||r.includes("timeout")||r.includes("runner did not accept connection")||r.includes("invalid runner response")}async function ea(e){var t;let{req:r}=e;if("find"!==r.command)return null;let n=r.positionals??[];if(0===n.length)return i("INVALID_ARGS","find requires a locator or text");let s=b(n);if(!s.query)return i("INVALID_ARGS","find requires a value");if(r.flags?.findFirst&&r.flags?.findLast)return i("INVALID_ARGS","find accepts only one of --first or --last");let o=s.action;if("exists"!==(t=o)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let a=await e_(e,{requireSession:!1,capability:"find"});return a.ok?await ek(async()=>{let t=await a.runtime.selectors.find({session:e.sessionName,requestId:r.meta?.requestId,locator:s.locator,query:s.query,action:o,timeoutMs:s.timeoutMs});return H(e.sessionStore,e.sessionName,r,function(e,t){if("exists"===t)return{found:!0};if("wait"===t)return{found:!0,waitedMs:e.waitedMs};let r="string"==typeof e.ref?e.ref:void 0;return"get_attrs"===t?{ref:r,action:"get attrs"}:{ref:r,action:"get text",text:"string"==typeof e.text?e.text:""}}(t,o)),"found"===t.kind?{found:!0,..."number"==typeof t.waitedMs?{waitedMs:t.waitedMs}:{}}:{..."string"==typeof t.ref?{ref:t.ref}:{},..."string"==typeof t.text?{text:t.text}:{},...t.node&&"object"==typeof t.node?{node:t.node}:{}}}):a.response}async function el(e){let{req:t}=e;if("get"!==t.command)return null;let r=t.positionals?.[0];if("text"!==r&&"attrs"!==r)return i("INVALID_ARGS","get only supports text or attrs");let n=function(e){let t=e.positionals?.[1]??"";if(t.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:e.positionals.length>2?e.positionals.slice(2).join(" ").trim():""}};let r=e.positionals?.slice(1).join(" ").trim()??"";return r?{ok:!0,target:{kind:"selector",selector:r}}:{ok:!1,response:i("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!n.ok)return n.response;if("ref"===n.target.kind){let e=K("get",t.flags);if(e)return e}if("selector"===n.target.kind){let t=await ed(e,r,n.target.selector);if(t)return t}let s=await e_(e,{requireSession:!0,capability:"get"});return s.ok?await ek(async()=>{let o=await s.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:r,target:n.target});return H(e.sessionStore,e.sessionName,t,F(o,r)),B(o)}):s.response}async function eu(e){let{req:t}=e;if("is"!==t.command)return null;let r=(t.positionals?.[0]??"").toLowerCase();if(!y(r))return i("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:n}=N(t.positionals??[]);if(!n)return i("INVALID_ARGS","is requires a selector expression");let s=n.rest.join(" ").trim();if("text"===r&&!s)return i("INVALID_ARGS","is text requires expected text value");if("text"!==r&&n.rest.length>0)return i("INVALID_ARGS",`is ${r} does not accept trailing values`);let o=await ef(e,r,n.selectorExpression,s);if(o)return o;let a=await e_(e,{requireSession:!0,capability:"is"});if(!a.ok)return a.response;let l=await ek(async()=>{let o=await a.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:r,selector:n.selectorExpression,expectedText:s});return H(e.sessionStore,e.sessionName,t,o),j(o)});return await eI(e,l,`is ${r}`)}async function ec(e){let{req:t,sessionName:r,sessionStore:n}=e,s=R(t.positionals??[]);if(!s)return i("INVALID_ARGS","wait requires a duration or text");let{session:a,device:l}=await M(n,r,t.flags);if("sleep"!==s.kind&&!o("wait",l))return i("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===s.kind){let t=await ep({...e,session:a,device:l,selectorExpression:s.selectorExpression,timeoutMs:s.timeoutMs});if(t)return t}let u=async()=>{let o=ew({...e,session:a,device:l}),i=await ek(async()=>{let e=await o.selectors.wait({session:r,requestId:t.meta?.requestId,target:function(e,t){if("sleep"===e.kind)return{kind:"sleep",durationMs:e.durationMs};if("selector"===e.kind)return{kind:"selector",selector:e.selectorExpression,timeoutMs:e.timeoutMs};if("ref"===e.kind){if(!t?.snapshot)throw new g("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new g("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(s,a)});return H(n,r,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}}),u=await X({req:t,logPath:e.logPath,session:a,device:l},i);return await eI(e,u,"wait")};return"sleep"===s.kind?await u():await D(a,l,u)}async function ed(e,t,r){let n=await em(e,r);if(ey(n))return n.response;if(!n)return null;let s=function(e,t,r){if(!r.found||!r.node)return null;let n={target:{kind:"selector",selector:t},node:r.node,selectorChain:[t]};return"attrs"===e?{kind:"attrs",...n}:"string"!=typeof r.text?null:{kind:"text",...n,text:r.text}}(t,n.selector.raw,n.result);return s?(H(e.sessionStore,e.sessionName,e.req,F(s,t)),{ok:!0,data:B(s)}):null}async function ef(e,t,r,n){var s,o,i,a,l;let u;if("hidden"===t)return null;let c=await em(e,r);if(ey(c))return c.response;if(!c?.result.found||!c.result.node)return null;let d="exists"===t?{predicate:t,pass:!0,selector:c.selector.raw,matches:1,selectorChain:[c.selector.raw]}:(s=t,o=n,i=c.selector.raw,a=c.session,u=h({predicate:s,node:l=c.result.node,nodes:[l],expectedText:o,platform:a.device.platform}),{predicate:s,pass:u.pass,selector:i,..."text"===s?{text:u.actualText}:{},selectorChain:[i]});return d?(H(e.sessionStore,e.sessionName,e.req,d),{ok:!0,data:j(d)}):null}async function ep(e){let t=eo({session:e.session,selectorExpression:e.selectorExpression});if(!e.session||!t)return null;let r=Date.now(),n=await eh(e,e.session,t);if(ey(n))return n.response;if(!n?.found)return null;let s={kind:"selector",selector:t.raw,waitedMs:Date.now()-r,selectorChain:[t.raw]};return H(e.sessionStore,e.sessionName,e.req,s),await X({req:e.req,logPath:e.logPath,session:e.session,device:e.device},{ok:!0,data:s})}async function em(e,t){let r=e.sessionStore.get(e.sessionName),n=eo({session:r,selectorExpression:t});if(!r||!n)return null;let s=await eh(e,r,n);return ey(s)?s:s?{session:r,selector:n,result:s}:null}async function eg(e,t,r){let n=await s(t.device,{command:"querySelector",selectorKey:r.key,selectorValue:r.value,appBundleId:t.appBundleId},{verbose:!!e.req.flags?.verbose,logPath:e.logPath,traceLogPath:t.trace?.outPath,requestId:e.req.meta?.requestId}),o=!0===n.found,i=function(e){let t=e.nodes;if(!Array.isArray(t))return;let r=t[0];if(r&&"object"==typeof r)return r}(n);return{found:o,..."string"==typeof n.text?{text:n.text}:{},...i?{node:i}:{}}}async function eh(e,t,r){try{return await eg(e,t,r)}catch(e){if(ei(e))return null;return{kind:"error",response:{ok:!1,error:m(e)}}}}function ey(e){return null!==e&&"kind"in e&&"error"===e.kind}function ew(n){return S({backend:function(e){let n,{req:s,session:o,device:i,logPath:a,sessionName:l,sessionStore:u}=e,d=0;return{platform:i.platform,captureSnapshot:async(e,f)=>{var p;let m,g={...s.flags,...(p=f,m={},p?.interactiveOnly!==void 0&&(m.snapshotInteractiveOnly=p.interactiveOnly),p?.compact!==void 0&&(m.snapshotCompact=p.compact),p?.scope!==void 0&&(m.snapshotScope=p.scope),p?.depth!==void 0&&(m.snapshotDepth=p.depth),p?.raw!==void 0&&(m.snapshotRaw=p.raw),m)},h=f?.scope??s.flags?.snapshotScope,y=Date.now(),w=q(C(g)),_="wait"===s.command||"find"===s.command;if(!_&&n&&y-d<750&&!c(o)&&!o?.postGestureStabilization)return n;if(!_&&o?.snapshot&&y-o.snapshot.createdAt<750&&o.snapshot.presentationKey===w&&!c(o)&&!o.postGestureStabilization)return d=o.snapshot.createdAt,n={snapshot:o.snapshot};let S=await r({device:i,session:o,flags:g,outPath:s.flags?.out,logPath:a??"",snapshotScope:h});return o&&(t(o,S.snapshot),u.set(l,o)),d=y,n={snapshot:S.snapshot}},readText:async(t,r)=>({text:await L({device:i,node:r,flags:s.flags,appBundleId:o?.appBundleId,traceOutPath:o?.trace?.outPath,surface:o?.surface,contextFromFlags:e.contextFromFlags??((e,t,r)=>f(a??"",e,t,r))})}),findText:async(t,r)=>({found:await eS(e,r)})}}(n),...$("selector commands",{plural:!0}),sessions:e({sessionName:n.sessionName,getSession:()=>n.session,recordOptions:{includeSnapshot:!0},setRecord:e=>{n.session&&e.snapshot&&(t(n.session,e.snapshot),n.sessionStore.set(n.sessionName,n.session))}})})}async function e_(e,t){let r=e.sessionStore.get(e.sessionName);if(!r&&t.requireSession)return{ok:!1,response:i("SESSION_NOT_FOUND","No active session. Run open first.")};let n=r?.device??await d(e.req.flags??{});return(r||await a(n),o(t.capability,n))?{ok:!0,runtime:ew({...e,session:r,device:n})}:{ok:!1,response:i("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function eS(e,t){let{device:r,session:n,req:o,logPath:i}=e;if("macos"===r.platform&&n?.surface&&"app"!==n.surface)return!!A((await ex(e)).nodes,t);if(l(r.platform)&&n?.appBundleId){let e=await s(r,{command:"findText",text:t,appBundleId:n?.appBundleId},{verbose:o.flags?.verbose,logPath:i,traceLogPath:n?.trace?.outPath,requestId:o.meta?.requestId});return e?.found===!0}return!!A((await ex(e)).nodes,t)}async function ex(e){let n=await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&(t(e.session,n.snapshot),e.sessionStore.set(e.sessionName,e.session)),n.snapshot}async function ek(e){try{return{ok:!0,data:await e()}}catch(t){let e=p(t);return i(e.code,e.message,e.details)}}async function eI(e,t,r){var n;let s;if(t.ok)return t;let o=e.sessionStore.get(e.sessionName);if(!o)return t;try{s=await G(o)}catch{return t}return s?i(t.error.code,`${r} failed because ${"com.google.android.permissioncontroller"===(n=s).foregroundPackage?`Android permission dialog is blocking ${n.expectedPackage}`:`${n.foregroundPackage} is foreground instead of ${n.expectedPackage}`}.`,{...t.error.details??{},...s,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}export{T as assertAndroidPressStayedInApp,O as buildSnapshotSession,$ as createDaemonRuntimePolicy,ea as dispatchFindReadOnlyViaRuntime,el as dispatchGetViaRuntime,eu as dispatchIsViaRuntime,ec as dispatchWaitViaRuntime,V as isAndroidEscapeError,ei as isDirectIosSelectorFallbackError,eo as readSimpleIosSelectorTarget,L as readTextForNode,E as recordIfSession,K as refSnapshotFlagGuardResponse,M as resolveSessionDevice,D as withSessionlessRunnerCleanup};
|
|
1
|
+
import{createDaemonRuntimeSessionStore as e,setSessionSnapshot as t,captureSnapshot as r,dispatchCommand as n,runIosRunnerCommand as s,isCommandSupportedOnDevice as o,errorResponse as i,ensureDeviceReady as a,isApplePlatform as l,stopIosRunnerSession as u,getActiveAndroidSnapshotFreshness as c,resolveTargetDevice as d,context_contextFromFlags as f}from"./2415.js";import{asAppError as p,normalizeError as m,AppError as g}from"./9152.js";import{evaluateIsPredicate as h,isSupportedPredicate as y,localCommandPolicy as w,resolveRectCenter as _,createAgentDevice as S}from"./9533.js";import{emitDiagnostic as x}from"./7599.js";import{tryParseSelectorChain as k,extractNodeReadText as I,prefersValueForReadableText as v,findNodeByLabel as N,normalizeType as A,splitIsSelectorArgs as P}from"./940.js";import{getAndroidAppState as R}from"./8806.js";import{parseWaitPositionals as b}from"./6085.js";import{parseFindArgs as q}from"./7556.js";import{buildSnapshotPresentationKey as E,snapshotPresentationOptionsFromFlags as C}from"./4057.js";async function M(e,t,r){let n=e.get(t),s=n?.device??await d(r??{});return n||await a(s),{session:n,device:s}}async function D(e,t,r){let n=!e&&"ios"===t.platform;try{return await r()}finally{n&&await u(t.id)}}function O(e,t,r,n){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function $(e){let{session:t,sessionName:r,device:n,snapshot:s,appBundleId:o}=e;return t?{...t,snapshot:s}:{name:r,device:n,createdAt:Date.now(),appBundleId:o,snapshot:s,actions:[]}}function L(e,t={}){return{artifacts:function(e,t={}){let r=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new g("UNSUPPORTED_OPERATION",`${e} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new g("UNSUPPORTED_OPERATION",`${e} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new g("UNSUPPORTED_OPERATION",`${e} ${r} not create temporary files`)}}}(e,t),policy:w()}}async function U(e){let{device:t,node:r,flags:s,appBundleId:o,traceOutPath:i,surface:a,contextFromFlags:l}=e,u=I(r),c=_(r.rect);if(!c||"ios"===t.platform&&u&&!v(r.type??""))return u;try{let e=await n(t,"read",[String(c.x),String(c.y)],void 0,{...l(s,o,i),surface:a}),d=e&&"object"==typeof e?e:void 0,f="string"==typeof d?.text?d.text:"";if(f.trim())return f;return x({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:a,platform:t.platform}}),u}catch(e){return x({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:a,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),u}}let T=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function K(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,n]of T)void 0!==e[r]&&t.push(n);return t}(t);return 0===r.length?null:i("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function G(e,t){let r=await V(e);if(r)throw new g("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${r.foregroundPackage}. The tap likely escaped the app.`,r)}async function V(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let r=await R(e.device),n=r.package?.trim();return n&&n!==e.appBundleId&&("com.android.settings"===(t=n)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:n,activity:r.activity,hint:"com.google.android.permissioncontroller"===n?"Dismiss or allow the permission prompt, then retry the smoke assertion.":"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."}:null}function F(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function B(e,t){let r=Array.isArray(e.selectorChain)?e.selectorChain:void 0,n=z(e),s=n?.kind==="ref"?J(n.ref):void 0,o=n?.kind==="selector"?n.selector:void 0,i={...s?{ref:s}:{},...o?{selector:o}:{},...r?{selectorChain:r}:{}};if("attrs"===t)return i;let a="string"==typeof e.text?e.text:"";return{...i,text:a,refLabel:function(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}(a)}}function j(e){let t=z(e);return{...t?.kind==="ref"?{ref:J(t.ref)}:{},...t?.kind==="selector"?{selector:t.selector}:{},..."string"==typeof e.text?{text:e.text}:{},...e.node&&"object"==typeof e.node?{node:e.node}:{}}}function H(e){let{selectorChain:t,...r}=e;return r}function W(e,t,r,n){let s=e.get(t);s&&e.recordAction(s,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function z(e){let t=e.target;return t&&"object"==typeof t?"ref"===t.kind&&"string"==typeof t.ref?{kind:"ref",ref:t.ref}:"selector"===t.kind&&"string"==typeof t.selector?{kind:"selector",selector:t.selector}:void 0:void 0}function J(e){return e.startsWith("@")?e.slice(1):e}let Q=["application","window","tabbar","scrollbar","image"],X=new Set(["tab bar"]);async function Y(e,t){var r;if(t.ok||(r=t.error.message,!/^wait timed out for (?:selector|text): /i.test(r)))return t;let n=await Z(e).catch(()=>null);return n?i(t.error.code,`${t.error.message}. Current surface: ${n.summary}.`,{...t.error.details??{},currentSurface:n.details}):t}async function Z(e){let t=[...(await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!0,snapshotCompact:!0},logPath:e.logPath??""})).snapshot.nodes].sort(et),n=ee(t,6,{includeIdentifiers:!0});if(0===n.length)return null;let s=ee(t.filter(e=>!es(e)),4,{includeIdentifiers:!1}),o=ee(t.filter(eo),4,{includeIdentifiers:!0});return{summary:(s.length>0?s:n.slice(0,4)).join(", "),details:{labels:n,...o.length>0?{buttons:o}:{}}}}function ee(e,t,r){let n=new Set,s=[];for(let o of e){let e=en(o,r);if(!(!e||n.has(e))&&(n.add(e),s.push(e),s.length>=t))break}return s}function et(e,t){var r,n;return er(e)-er(t)||(r=e,n=t,r.rect&&n.rect?r.rect.y-n.rect.y||r.rect.x-n.rect.x:r.rect?-1:n.rect?1:(r.depth??0)-(n.depth??0)||r.index-n.index)}function er(e){let t=!!en(e,{includeIdentifiers:!1});return 2*!!es(e)+ +!t}function en(e,t){let r=(t.includeIdentifiers?[e.label,e.value,e.identifier]:[e.label,e.value]).map(e=>"string"==typeof e?e.trim():"").find(e=>e.length>0);return r?r.replace(/\s+/g," ").slice(0,80):""}function es(e){let t=A(`${e.type??""} ${e.role??""} ${e.subrole??""}`),r=`${e.label??""} ${e.value??""}`.trim().toLowerCase();return Q.some(e=>t.includes(e))||X.has(r)||r.endsWith(".fill")}function eo(e){return A(`${e.type??""} ${e.role??""} ${e.subrole??""}`).includes("button")}function ei(e){var t;let{session:r,selectorExpression:n}=e;if(!r||"ios"!==r.device.platform||r.postGestureStabilization)return null;let s=k(n);if(!s||1!==s.selectors.length)return null;let o=s.selectors[0];if(!o||1!==o.terms.length)return null;let i=o.terms[0];return i&&"string"==typeof i.value&&("id"===(t=i.key)||"label"===t||"text"===t||"value"===t)?{key:i.key,value:i.value,raw:o.raw}:null}function ea(e,t={}){let r=p(e);if("ELEMENT_NOT_FOUND"===r.code)return!0===t.allowElementNotFound;if("COMMAND_FAILED"!==r.code)return!1;let n=r.message.toLowerCase();return n.includes("fetch failed")||n.includes("timed out")||n.includes("timeout")||n.includes("runner did not accept connection")||n.includes("invalid runner response")}async function el(e){var t;let{req:r}=e;if("find"!==r.command)return null;let n=r.positionals??[];if(0===n.length)return i("INVALID_ARGS","find requires a locator or text");let s=q(n);if(!s.query)return i("INVALID_ARGS","find requires a value");if(r.flags?.findFirst&&r.flags?.findLast)return i("INVALID_ARGS","find accepts only one of --first or --last");let o=s.action;if("exists"!==(t=o)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let a=await eS(e,{requireSession:!1,capability:"find"});return a.ok?await eI(async()=>{let t=await a.runtime.selectors.find({session:e.sessionName,requestId:r.meta?.requestId,locator:s.locator,query:s.query,action:o,timeoutMs:s.timeoutMs});return W(e.sessionStore,e.sessionName,r,function(e,t){if("exists"===t)return{found:!0};if("wait"===t)return{found:!0,waitedMs:e.waitedMs};let r="string"==typeof e.ref?e.ref:void 0;return"get_attrs"===t?{ref:r,action:"get attrs"}:{ref:r,action:"get text",text:"string"==typeof e.text?e.text:""}}(t,o)),"found"===t.kind?{found:!0,..."number"==typeof t.waitedMs?{waitedMs:t.waitedMs}:{}}:{..."string"==typeof t.ref?{ref:t.ref}:{},..."string"==typeof t.text?{text:t.text}:{},...t.node&&"object"==typeof t.node?{node:t.node}:{}}}):a.response}async function eu(e){let{req:t}=e;if("get"!==t.command)return null;let r=t.positionals?.[0];if("text"!==r&&"attrs"!==r)return i("INVALID_ARGS","get only supports text or attrs");let n=function(e){let t=e.positionals?.[1]??"";if(t.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:e.positionals.length>2?e.positionals.slice(2).join(" ").trim():""}};let r=e.positionals?.slice(1).join(" ").trim()??"";return r?{ok:!0,target:{kind:"selector",selector:r}}:{ok:!1,response:i("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!n.ok)return n.response;if("ref"===n.target.kind){let e=K("get",t.flags);if(e)return e}if("selector"===n.target.kind){let t=await ef(e,r,n.target.selector);if(t)return t}let s=await eS(e,{requireSession:!0,capability:"get"});return s.ok?await eI(async()=>{let o=await s.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:r,target:n.target});return W(e.sessionStore,e.sessionName,t,B(o,r)),j(o)}):s.response}async function ec(e){let{req:t}=e;if("is"!==t.command)return null;let r=(t.positionals?.[0]??"").toLowerCase();if(!y(r))return i("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:n}=P(t.positionals??[]);if(!n)return i("INVALID_ARGS","is requires a selector expression");let s=n.rest.join(" ").trim();if("text"===r&&!s)return i("INVALID_ARGS","is text requires expected text value");if("text"!==r&&n.rest.length>0)return i("INVALID_ARGS",`is ${r} does not accept trailing values`);let o=await ep(e,r,n.selectorExpression,s);if(o)return o;let a=await eS(e,{requireSession:!0,capability:"is"});if(!a.ok)return a.response;let l=await eI(async()=>{let o=await a.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:r,selector:n.selectorExpression,expectedText:s});return W(e.sessionStore,e.sessionName,t,o),H(o)});return await ev(e,l,`is ${r}`)}async function ed(e){let{req:t,sessionName:r,sessionStore:n}=e,s=b(t.positionals??[]);if(!s)return i("INVALID_ARGS","wait requires a duration or text");let{session:a,device:l}=await M(n,r,t.flags);if("sleep"!==s.kind&&!o("wait",l))return i("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===s.kind){let t=await em({...e,session:a,device:l,selectorExpression:s.selectorExpression,timeoutMs:s.timeoutMs});if(t)return t}let u=async()=>{let o=e_({...e,session:a,device:l}),i=await eI(async()=>{let e=await o.selectors.wait({session:r,requestId:t.meta?.requestId,target:function(e,t){if("sleep"===e.kind)return{kind:"sleep",durationMs:e.durationMs};if("selector"===e.kind)return{kind:"selector",selector:e.selectorExpression,timeoutMs:e.timeoutMs};if("ref"===e.kind){if(!t?.snapshot)throw new g("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new g("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(s,a)});return W(n,r,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}}),u=await Y({req:t,logPath:e.logPath,session:a,device:l},i);return await ev(e,u,"wait")};return"sleep"===s.kind?await u():await D(a,l,u)}async function ef(e,t,r){let n=e.sessionStore.get(e.sessionName),s=ei({session:n,selectorExpression:r});if(!n||!s||"text"===t&&"id"!==s.key)return null;let o=await ey(e,n,s);if(ew(o))return o.response;if(!o)return null;let i=function(e,t,r){if(!r.found||!r.node)return null;let n={target:{kind:"selector",selector:t},node:r.node,selectorChain:[t]};return"attrs"===e?{kind:"attrs",...n}:"string"!=typeof r.text?null:{kind:"text",...n,text:r.text}}(t,s.raw,o);return i?(W(e.sessionStore,e.sessionName,e.req,B(i,t)),{ok:!0,data:j(i)}):null}async function ep(e,t,r,n){var s,o,i,a,l;let u;if("hidden"===t)return null;let c=await eg(e,r);if(ew(c))return c.response;if(!c?.result.found||!c.result.node)return null;let d="exists"===t?{predicate:t,pass:!0,selector:c.selector.raw,matches:1,selectorChain:[c.selector.raw]}:(s=t,o=n,i=c.selector.raw,a=c.session,u=h({predicate:s,node:l=c.result.node,nodes:[l],expectedText:o,platform:a.device.platform}),{predicate:s,pass:u.pass,selector:i,..."text"===s?{text:u.actualText}:{},selectorChain:[i]});return d?(W(e.sessionStore,e.sessionName,e.req,d),{ok:!0,data:H(d)}):null}async function em(e){let t=ei({session:e.session,selectorExpression:e.selectorExpression});if(!e.session||!t)return null;let r=Date.now(),n=await ey(e,e.session,t);if(ew(n))return n.response;if(!n?.found)return null;let s={kind:"selector",selector:t.raw,waitedMs:Date.now()-r,selectorChain:[t.raw]};return W(e.sessionStore,e.sessionName,e.req,s),await Y({req:e.req,logPath:e.logPath,session:e.session,device:e.device},{ok:!0,data:s})}async function eg(e,t){let r=e.sessionStore.get(e.sessionName),n=ei({session:r,selectorExpression:t});if(!r||!n)return null;let s=await ey(e,r,n);return ew(s)?s:s?{session:r,selector:n,result:s}:null}async function eh(e,t,r){let n=await s(t.device,{command:"querySelector",selectorKey:r.key,selectorValue:r.value,appBundleId:t.appBundleId},{verbose:!!e.req.flags?.verbose,logPath:e.logPath,traceLogPath:t.trace?.outPath,requestId:e.req.meta?.requestId}),o=!0===n.found,i=function(e){let t=e.nodes;if(!Array.isArray(t))return;let r=t[0];if(r&&"object"==typeof r)return r}(n);return{found:o,..."string"==typeof n.text?{text:n.text}:{},...i?{node:i}:{}}}async function ey(e,t,r){try{return await eh(e,t,r)}catch(e){if(ea(e,{allowElementNotFound:!0}))return null;return{kind:"error",response:{ok:!1,error:m(e)}}}}function ew(e){return null!==e&&"kind"in e&&"error"===e.kind}function e_(n){return S({backend:function(e){let n,{req:s,session:o,device:i,logPath:a,sessionName:l,sessionStore:u}=e,d=0;return{platform:i.platform,captureSnapshot:async(e,f)=>{var p;let m,g={...s.flags,...(p=f,m={},p?.interactiveOnly!==void 0&&(m.snapshotInteractiveOnly=p.interactiveOnly),p?.compact!==void 0&&(m.snapshotCompact=p.compact),p?.scope!==void 0&&(m.snapshotScope=p.scope),p?.depth!==void 0&&(m.snapshotDepth=p.depth),p?.raw!==void 0&&(m.snapshotRaw=p.raw),m)},h=f?.scope??s.flags?.snapshotScope,y=Date.now(),w=E(C(g)),_="wait"===s.command||"find"===s.command;if(!_&&n&&y-d<750&&!c(o)&&!o?.postGestureStabilization)return n;if(!_&&o?.snapshot&&y-o.snapshot.createdAt<750&&o.snapshot.presentationKey===w&&!c(o)&&!o.postGestureStabilization)return d=o.snapshot.createdAt,n={snapshot:o.snapshot};let S=await r({device:i,session:o,flags:g,outPath:s.flags?.out,logPath:a??"",snapshotScope:h});return o&&(t(o,S.snapshot),u.set(l,o)),d=y,n={snapshot:S.snapshot}},readText:async(t,r)=>({text:await U({device:i,node:r,flags:s.flags,appBundleId:o?.appBundleId,traceOutPath:o?.trace?.outPath,surface:o?.surface,contextFromFlags:e.contextFromFlags??((e,t,r)=>f(a??"",e,t,r))})}),findText:async(t,r)=>({found:await ex(e,r)})}}(n),...L("selector commands",{plural:!0}),sessions:e({sessionName:n.sessionName,getSession:()=>n.session,recordOptions:{includeSnapshot:!0},setRecord:e=>{n.session&&e.snapshot&&(t(n.session,e.snapshot),n.sessionStore.set(n.sessionName,n.session))}})})}async function eS(e,t){let r=e.sessionStore.get(e.sessionName);if(!r&&t.requireSession)return{ok:!1,response:i("SESSION_NOT_FOUND","No active session. Run open first.")};let n=r?.device??await d(e.req.flags??{});return(r||await a(n),o(t.capability,n))?{ok:!0,runtime:e_({...e,session:r,device:n})}:{ok:!1,response:i("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function ex(e,t){let{device:r,session:n,req:o,logPath:i}=e;if("macos"===r.platform&&n?.surface&&"app"!==n.surface)return!!N((await ek(e)).nodes,t);if(l(r.platform)&&n?.appBundleId){let e=await s(r,{command:"findText",text:t,appBundleId:n?.appBundleId},{verbose:o.flags?.verbose,logPath:i,traceLogPath:n?.trace?.outPath,requestId:o.meta?.requestId});return e?.found===!0}return!!N((await ek(e)).nodes,t)}async function ek(e){let n=await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&(t(e.session,n.snapshot),e.sessionStore.set(e.sessionName,e.session)),n.snapshot}async function eI(e){try{return{ok:!0,data:await e()}}catch(t){let e=p(t);return i(e.code,e.message,e.details)}}async function ev(e,t,r){var n;let s;if(t.ok)return t;let o=e.sessionStore.get(e.sessionName);if(!o)return t;try{s=await V(o)}catch{return t}return s?i(t.error.code,`${r} failed because ${"com.google.android.permissioncontroller"===(n=s).foregroundPackage?`Android permission dialog is blocking ${n.expectedPackage}`:`${n.foregroundPackage} is foreground instead of ${n.expectedPackage}`}.`,{...t.error.details??{},...s,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}export{G as assertAndroidPressStayedInApp,$ as buildSnapshotSession,L as createDaemonRuntimePolicy,el as dispatchFindReadOnlyViaRuntime,eu as dispatchGetViaRuntime,ec as dispatchIsViaRuntime,ed as dispatchWaitViaRuntime,F as isAndroidEscapeError,ea as isDirectIosSelectorFallbackError,ei as readSimpleIosSelectorTarget,U as readTextForNode,O as recordIfSession,K as refSnapshotFlagGuardResponse,M as resolveSessionDevice,D as withSessionlessRunnerCleanup};
|