agent-device 0.17.8 → 0.17.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.8.apk → agent-device-android-multitouch-helper-0.17.10.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.10.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.8.manifest.json → agent-device-android-multitouch-helper-0.17.10.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.8.apk → agent-device-android-snapshot-helper-0.17.10.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.10.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.8.manifest.json → agent-device-android-snapshot-helper-0.17.10.manifest.json} +6 -6
- package/dist/src/1404.js +1 -0
- package/dist/src/2133.js +1 -1
- package/dist/src/2577.js +1 -1
- package/dist/src/2948.js +30 -1
- package/dist/src/4428.js +1 -1
- package/dist/src/587.js +1 -1
- package/dist/src/7394.js +5 -5
- package/dist/src/8184.js +1 -1
- package/dist/src/8358.js +1 -1
- package/dist/src/9581.js +2 -2
- package/dist/src/9722.js +36 -36
- package/dist/src/9836.js +1 -1
- package/dist/src/9919.js +5 -5
- package/dist/src/android.js +3 -3
- package/dist/src/apple.js +1 -1
- package/dist/src/apps.js +1 -1
- package/dist/src/cli-help.js +93 -27
- package/dist/src/cli-output.js +1 -4
- package/dist/src/cli.js +18 -18
- package/dist/src/command-surface.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/generic.js +5 -5
- package/dist/src/index.d.ts +12 -0
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions~1.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace-recording.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session.js +7 -7
- package/dist/src/snapshot.js +1 -1
- package/dist/src/web.js +1 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +92 -4
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +130 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +4 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +18 -0
- package/package.json +3 -3
- package/server.json +2 -2
- package/skills/agent-device/SKILL.md +1 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.8.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.8.apk.sha256 +0 -1
- package/dist/src/6311.js +0 -27
- package/dist/src/7244.js +0 -1
- package/dist/src/9873.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{emitDiagnostic as t}from"./432.js";import{runAndroidAdb as e}from"./3340.js";import{getAndroidKeyboardState as n,isAndroidInputMethodOwnedNode as a}from"./9624.js";import{captureAndroidUiHierarchyXml as r}from"./9722.js";import{androidUiNodes as i}from"./7394.js";import{AppError as o}from"./733.js";import{buildScrollGesturePlan as u}from"./
|
|
1
|
+
import{emitDiagnostic as t}from"./432.js";import{runAndroidAdb as e}from"./3340.js";import{getAndroidKeyboardState as n,isAndroidInputMethodOwnedNode as a}from"./9624.js";import{captureAndroidUiHierarchyXml as r}from"./9722.js";import{androidUiNodes as i}from"./7394.js";import{AppError as o}from"./733.js";import{buildScrollGesturePlan as u}from"./2948.js";import{resolveAndroidTextInjector as l}from"./2954.js";import{sleep as c}from"./5560.js";function s(t){var e;return!!t&&(!!t.password||!!(e=t.text)&&Array.from(e).every(f))}function d(t){if(!t)return null;let e=s(t);return{...t,text:e?null:t.text,...e?{textRedacted:!0}:{}}}function f(t){return"•"===t||"*"===t||"●"===t}async function p(t,e,n,a){let r=null,i=null,o=await y(t);for(let u of[0,150,350]){u>0&&await c(u);let l=await g(t,e,n,a,o);if(r=l,"ime_capture"===l.reason)return l;i=l.ok?l:null}return i??r??{ok:!1,actual:null,reason:"text_mismatch",targetInput:null,actualInput:null}}async function h(t,e,n){var a,i,o;return a=await r(t),i=e,o=n,m(a,i,o).actualInput?.text??null}async function g(t,e,n,a,i){return function(t,e,n,a,r={}){var i,o;let u,l=m(t,e,n,r);return!function(t){let{targetInput:e,actualInput:n}=t;return!!e&&!!n&&n!==e&&n.inputMethodOwned&&!e.inputMethodOwned}(l)?function(t,e){let n=t.actualInput;if(!n||!s(n))return null;let a=n.text??null,r=Array.from(a??"").length,i=Array.from(e).length,o=null!==a&&r>0&&i>0&&r===i;return{ok:o,actual:a,reason:o?void 0:"masked_unverified",masked:!0,targetInput:t.targetInput,actualInput:n}}(l,a)??(i=l,o=a,{ok:function(t,e){if(t===e)return!0;let n=w(t),a=w(e);return!!n&&!!a&&!!(n===a||function(t,e){if(t.length!==e.length||0===t.length||t.slice(1)!==e.slice(1))return!1;let n=t[0],a=e[0];return!!n&&!!a&&a.toLowerCase()===a&&n===a.toUpperCase()}(n,a))}(u=i.actualInput?.text??null,o),actual:u,reason:"text_mismatch",targetInput:i.targetInput,actualInput:i.actualInput}):{ok:!1,actual:l.actualInput?.text??null,reason:"ime_capture",targetInput:l.targetInput,actualInput:l.actualInput}}(await r(t),e,n,a,i)}function m(t,e,n,r={}){var o;let u,l={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let o of i(t)){let t=function(t,e){if(!t.rect)return null;let n=t.text??"",r=Math.max(1,t.rect.width*t.rect.height);return{text:n||null,className:t.className,resourceId:t.resourceId,packageName:t.packageName,rect:t.rect,focused:t.focused??!1,password:!0===t.password,inputMethodOwned:a({packageName:t.packageName,resourceId:t.resourceId,activeInputMethodPackage:e.activeInputMethodPackage}),area:r,editText:function(t){let e=t.toLowerCase();return e.includes("edittext")||e.includes("textfield")}(t.className??"")}}(o,r);t&&function(t,e,n,a){var r,i,o;let u=(r=e.rect,i=n,o=a,i>=r.x&&i<=r.x+r.width&&o>=r.y&&o<=r.y+r.height);if(u&&e.editText&&(t.editAtPoint=_(t.editAtPoint,e)),e.focused&&e.editText){t.focusedEdit=_(t.focusedEdit,e);return}u&&e.text&&(t.anyAtPoint=_(t.anyAtPoint,e))}(l,t,e,n)}return{targetInput:u=(o=l).editAtPoint??o.anyAtPoint,actualInput:(o.focusedEdit?.text?o.focusedEdit:null)??u}}function w(t){return(t??"").replace(/\s+/g," ").trim()}async function y(e){try{return{activeInputMethodPackage:(await n(e)).inputMethodPackage}}catch(e){return t({level:"warn",phase:"android_fill_verification_input_method_probe_failed",data:{error:e instanceof Error?e.message:String(e)}}),{}}}function _(t,e){return t&&t.area<e.area?t:e}async function A(t,n,a){await e(t,["shell","input","tap",String(n),String(a)])}async function x(t,n,a,r,i,o=250){await e(t,["shell","input","swipe",String(n),String(a),String(r),String(i),String(o)])}async function I(t){await e(t,["shell","input","keyevent","4"])}async function M(t){await e(t,["shell","input","keyevent","3"])}async function S(t){await e(t,["shell","input","keyevent","ENTER"])}async function k(t,n){let a=function(t){switch(t){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new o("INVALID_ARGS",`Unsupported Android rotation: ${t}`)}}(n);await e(t,["shell","settings","put","system","accelerometer_rotation","0"]),await e(t,["shell","settings","put","system","user_rotation",a])}async function E(t){await e(t,["shell","input","keyevent","187"])}async function v(t,n,a,r=800){await e(t,["shell","input","swipe",String(n),String(a),String(n),String(a),String(r)])}async function C(t,e,n=0){let a=l(t);if(a){await a({action:"type",text:e,delayMs:n}),T("type","provider-native",e);return}(z(e),await D(t,"type"),n>0&&Array.from(e).length>1)?await L(t,{action:"type",text:e,chunkSize:1,delayMs:n}):await L(t,{action:"type",text:e,chunkSize:O,delayMs:0})}async function P(t,e,n){await A(t,e,n)}async function N(t,e,n,a,r=0){let i=l(t);if(i){await i({action:"fill",target:{x:e,y:n},text:a,delayMs:r}),T("fill","provider-native",a);let o=await p(t,e,n,a);if(o.ok)return;b(a,o)}z(a);let o=Array.from(a).length,u=null;for(let i of[{clearPadding:12,minClear:8,maxClear:48,chunkSize:r>0?1:O,inputDelayMs:r},{clearPadding:24,minClear:16,maxClear:96,chunkSize:r>0?1:4,inputDelayMs:r>0?r:15}]){var c,s;await P(t,e,n),await D(t,"fill");let r=(c=o+i.clearPadding,s=i.minClear,Math.max(s,Math.min(i.maxClear,c)));await F(t,r),await L(t,{action:"fill",text:a,chunkSize:i.chunkSize,delayMs:i.inputDelayMs});let l=await p(t,e,n,a);if(u=l,l.ok)return;"ime_capture"===l.reason&&b(a,l)}b(a,u)}function b(t,e){let n;throw new o("COMMAND_FAILED",e?.reason==="ime_capture"?"Android fill input was captured by the active keyboard instead of the app field":e?.reason==="masked_unverified"?"Android fill verification could not confirm masked text value":"Android fill verification failed",(n=function(t,e){var n;if(!e)return{expected:t,actual:null,failureReason:"text_mismatch",targetInput:null,actualInput:null};let a=!0===(n=e).masked||s(n.targetInput)||s(n.actualInput),r={failureReason:e.reason??"text_mismatch",targetInput:d(e.targetInput),actualInput:d(e.actualInput)};return a?{...r,expectedLength:Array.from(t).length,actual:null,masked:!0,actualLength:Array.from(e.actual??"").length}:{...r,expected:t,actual:e.actual}}(t,e),e?.reason==="ime_capture"&&(n.hint="The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill."),n))}async function K(t,n,a){let r=await R(t),i=u({direction:n,amount:a?.amount,pixels:a?.pixels,referenceWidth:r.width,referenceHeight:r.height}),o=a?.durationMs??300;return await e(t,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),String(o)]),{...i,...a?.durationMs!==void 0?{durationMs:a.durationMs}:{}}}async function D(e,a){let r;try{r=await n(e)}catch(e){t({level:"warn",phase:"android_input_ownership_probe_failed",data:{action:a,error:e instanceof Error?e.message:String(e)}});return}if("ime"===r.inputOwner)throw new o("COMMAND_FAILED","KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.",{failureReason:"ime_capture",action:a,inputOwner:r.inputOwner,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,nextAction:"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry."})}async function R(t){let n=(await e(t,["shell","wm","size"])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new o("COMMAND_FAILED","Unable to read screen size");return{width:Number(n[1]),height:Number(n[2])}}let O=8;async function L(t,n){let a=n.text.split("\n");for(let[r,i]of a.entries()){let o=function(t,e){let n=Math.max(1,Math.floor(e)),a=[],r=Array.from(t);for(let t=0;t<r.length;t+=n)a.push(r.slice(t,t+n).join(""));return a.length>0?a:[""]}(i,n.chunkSize);for(let[e,i]of o.entries())await U(t,i),n.delayMs>0&&(e+1<o.length||r+1<a.length)&&await c(n.delayMs);r+1<a.length&&await e(t,["shell","input","keyevent","ENTER"])}T(n.action,"adb-shell",n.text)}async function U(t,n){if(n)try{await e(t,["shell","input","text",n.replace(/ /g,"%s")])}catch(t){if(function(t){if(!(t instanceof o)||"COMMAND_FAILED"!==t.code)return!1;let e=t.details?.stderr,n=("string"==typeof e?e:"").toLowerCase();return!!(n.includes("exception occurred while executing 'text'")||n.includes("nullpointerexception")&&n.includes("inputshellcommand.sendtext"))}(t))throw H(n,t);throw t}}function z(t){if(!function(t){for(let e of t){let t=e.codePointAt(0);if(void 0!==t&&"\n"!==e&&(t<32||t>126))return!1}return!0}(t))throw H(t)}function H(t,e){return new o("COMMAND_FAILED","Android text input requires provider-native text injection for non-ASCII/control characters; the current adb-shell fallback supports ASCII text only.",{backend:"adb-shell",textLength:Array.from(t).length,textPreview:t.slice(0,32)},e instanceof Error?e:void 0)}function T(e,n,a){t({phase:"android_text_injection",data:{action:e,backend:n,textLength:Array.from(a).length}})}async function F(t,n){let a=Math.max(0,n);await e(t,["shell","input","keyevent","KEYCODE_MOVE_END"],{allowFailure:!0});for(let n=0;n<a;n+=24){let r=Math.min(24,a-n);await e(t,["shell","input","keyevent",...Array(r).fill("KEYCODE_DEL")],{allowFailure:!0})}}export{E as appSwitcherAndroid,I as backAndroid,N as fillAndroid,P as focusAndroid,R as getAndroidScreenSize,M as homeAndroid,v as longPressAndroid,A as pressAndroid,S as pressAndroidEnter,h as readAndroidTextAtPoint,k as rotateAndroid,K as scrollAndroid,x as swipeAndroid,C as typeAndroid};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AppError as a}from"./733.js";import{resolveLinuxToolProvider as t}from"./9722.js";import{sleep as i}from"./5560.js";let o=null;async function n(){let i=t();if(o?.provider===i)return o;let n=process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11";if("wayland"===n){if(await i.whichCommand("ydotool"))return o={tool:"ydotool",display:n,provider:i};throw new a("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await i.whichCommand("xdotool"))return o={tool:"xdotool",display:n,provider:i};throw new a("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function e(...a){await t().runCommand("xdotool",a,{allowFailure:!1,timeoutMs:1e4})}async function l(...a){await t().runCommand("ydotool",a,{allowFailure:!1,timeoutMs:1e4})}function
|
|
1
|
+
import{AppError as a}from"./733.js";import{resolveLinuxToolProvider as t}from"./9722.js";import{sleep as i}from"./5560.js";let o=null;async function n(){let i=t();if(o?.provider===i)return o;let n=process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11";if("wayland"===n){if(await i.whichCommand("ydotool"))return o={tool:"ydotool",display:n,provider:i};throw new a("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await i.whichCommand("xdotool"))return o={tool:"xdotool",display:n,provider:i};throw new a("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function e(...a){await t().runCommand("xdotool",a,{allowFailure:!1,timeoutMs:1e4})}async function l(...a){await t().runCommand("ydotool",a,{allowFailure:!1,timeoutMs:1e4})}function r(){return t().input}async function u(a,t){let{tool:i}=await n();"xdotool"===i?await e("mousemove","--sync",String(a),String(t)):await l("mousemove","--absolute","-x",String(a),"-y",String(t))}async function w(a,t){let i=r();if(i)return void await i.key(a,t);let{tool:o}=await n();"xdotool"===o?await e("key","--clearmodifiers",a):await l("key",...t)}async function c(a,t,i,o){await u(a,t);let{tool:r}=await n();"xdotool"===r?await e("click",i):await l("click",o)}async function s(a,t,i,o,n){let e=r();e?await e.click(a,t,i):await c(a,t,o,n)}async function d(a,t){await s(a,t,"primary","1","0xC0")}async function y(a,t){await s(a,t,"secondary","3","0xC1")}async function x(a,t){await s(a,t,"middle","2","0xC2")}async function f(a,t){let i=r();if(i)return void await i.doubleClick(a,t);let{tool:o}=await n();await u(a,t),"xdotool"===o?await e("click","--repeat","2","1"):(await l("click","0xC0"),await l("click","0xC0"))}async function m(a,t,o=800){let w=r();if(w)return void await w.longPress(a,t,o);let{tool:c}=await n();await u(a,t),"xdotool"===c?(await e("mousedown","1"),await i(o),await e("mouseup","1")):(await l("click","--down","0xC0"),await i(o),await l("click","--up","0xC0"))}async function p(a,t){await d(a,t)}async function S(a,t,o,w,c=300){let s=r();if(s)return void await s.drag(a,t,o,w,c);let{tool:d}=await n();await u(a,t),"xdotool"===d?(await e("mousedown","1"),await e("mousemove","--sync",String(o),String(w)),await i(c),await e("mouseup","1")):(await l("click","--down","0xC0"),await l("mousemove","--absolute","-x",String(o),"-y",String(w)),await i(c),await l("click","--up","0xC0"))}async function C(a,t){let i=r();if(i)return await i.scroll(a,t),k(t);let{tool:o}=await n(),u=5;if(t?.pixels!=null?u="xdotool"===o?Math.max(1,Math.round(t.pixels/15)):Math.max(1,Math.round(t.pixels/40)):t?.amount!=null&&(u=Math.max(1,Math.round(5*(t.amount/.6)))),"xdotool"===o){let i="up"===a?"4":"down"===a?"5":"left"===a?"6":"7";await g(u,t?.durationMs,async a=>{await e("click","--repeat",String(a),i)})}else"up"===a||"down"===a?await g(u,t?.durationMs,async t=>{let i="up"===a?String(-t):String(t);await l("mousemove","--wheel","-y",i)}):await g(u,t?.durationMs,async t=>{let i="left"===a?String(-t):String(t);await l("mousemove","--wheel","-x",i)});return k(t)}async function g(a,t,o){if(void 0===t||t<=0||a<=1)return void await o(a);let n=t/Math.max(1,a-1);for(let t=0;t<a;t+=1)await o(1),t<a-1&&await i(n)}function k(a){return a?.durationMs!==void 0?{durationMs:a.durationMs}:{}}async function h(a,t=0){let i=r();if(i)return void await i.typeText(a,{delayMs:t});let{tool:o}=await n();if("xdotool"===o){let i=["type"];t>0&&i.push("--delay",String(t)),i.push("--clearmodifiers","--",a),await e(...i)}else await l("type","--",a)}async function M(a,t,o,n=0){await d(a,t),await i(100),await w("ctrl+a",["29:1","30:1","30:0","29:0"]),await i(50),await h(o,n)}export{f as doubleClickLinux,M as fillLinux,p as focusLinux,m as longPressLinux,x as middleClickLinux,d as pressLinux,y as rightClickLinux,C as scrollLinux,w as sendKey,S as swipeLinux,h as typeLinux};
|
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,ensureAndroidBlockingSystemDialogReady as n,isCommandSupportedOnDevice as o,errorResponse as s,recoverAndroidBlockingSystemDialog as i,getActiveAndroidSnapshotFreshness as l}from"./9722.js";import{buttonTag as c,resolveClickButton as f,readFillTargetFromPositionals as u,getClickButtonValidationError as d,successText as p}from"./9873.js";import{createAgentDevice as g}from"./2577.js";import{asAppError as m,normalizeError as k,AppError as S}from"./733.js";import{dispatchGetViaRuntime as _,isAndroidEscapeError as y,createDaemonRuntimePolicy as w,assertAndroidPressStayedInApp as h,dispatchIsViaRuntime as b,isDirectIosSelectorFallbackError as v,refSnapshotFlagGuardResponse as N,readSimpleIosSelectorTarget as x}from"./selector-runtime.js";import{resolveWebProvider as F}from"./provider.js";import{interaction_snapshot_captureSnapshotForSession as R,readSnapshotNodesReferenceFrame as P,resolveDirectTouchReferenceFrameSafely as M,buildTouchVisualizationResult as O,finalizeTouchInteraction as C}from"./8184.js";import{emitDiagnostic as I}from"./432.js";import{PUBLIC_COMMANDS as A}from"./2133.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:s("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 U(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 T(e,t){let r=U(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let a=e[0]??"";if(a.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:a,fallbackLabel:e.slice(1).join(" ").trim()}};let n=e.join(" ").trim();return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:s("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}function D(e){return"ref"===e.kind?{ref:H(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 H(e){return e?.startsWith("@")?e.slice(1):e}function K(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new S("SESSION_NOT_FOUND","No active session. Run open first.");return g({backend:function(e){let{req:t,session:r}=e,n=function(e){if("web"!==e.device.platform)return;let t=F();return t.clickRef||t.fillRef?t:void 0}(r);return{platform:r.device.platform,captureSnapshot:async(a,n)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:n?.interactiveOnly===!0,includeRects:n?.includeRects===!0})}),tap:async(n,o)=>L(await a(r.device,"press",[String(o.x),String(o.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),tapTarget:n?.clickRef?async(e,t)=>(await n.clickRef?.(t.ref),{ref:H(t.ref)}):void 0,fill:async(n,o,s)=>L(await a(r.device,"fill",[String(o.x),String(o.y),s],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fillTarget:n?.fillRef?async(e,t,r,a)=>(await n.fillRef?.(t.ref,r,a),{ref:H(t.ref),text:r,delayMs:a?.delayMs??0}):void 0,longPress:async(n,o,s)=>L(await a(r.device,"longpress",[String(o.x),String(o.y),...s?.durationMs===void 0?[]:[String(s.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(n,o)=>L(await a(r.device,"type",[o],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:n}),...w("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 L(e){return e&&"object"==typeof e?e:void 0}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:n,sessionStore:i}=e,l=i.get(n);if(!l)return s("SESSION_NOT_FOUND","No active session. Run open first.");let u="click"===t?"click":t,p="longpress"===t?"longpress":"press",g=q(l,u);if(g)return g;if(!o(p,l.device))return s("UNSUPPORTED_OPERATION",`${p} is not supported on this device`);let m=f(a.flags),k=c(m);if("longpress"!==t&&"primary"!==m){let e=d({commandLabel:u,platform:l.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 s(e.code,e.message,e.details)}let S="longpress"===t?function(e){var t,r,a;let n,o=U(e);if(o){return{ok:!0,target:{kind:"point",x:o.x,y:o.y},...void 0===(t=e[2])?{}:{durationMs:Number(t)}}}let s=(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=T(s.targetPositionals,"longpress");return i.ok?{ok:!0,target:i.target,...s.duration}:i}(a.positionals??[]):T(a.positionals??[],u);if(!S.ok)return S.response;if("ref"===S.target.kind){let n=e.refSnapshotFlagGuardResponse("longpress"===t?"longpress":"press",a.flags);if(n)return n;r=await J(e,l)}let _=function(e){var t;let{session:r,commandLabel:a,target:n,flags:o}=e;if("click"!==a||"selector"!==n.kind||(t=o,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 s=x({session:r,selectorExpression:n.selector});return s?{...s,...o?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:l,commandLabel:u,target:S.target,flags:a.flags});if(_){let t=await $(e,l,_);if(t)return t}let y="longpress"===t?S.durationMs:void 0;return await z(e,{androidFreshnessBaseline:r,run:async e=>await G({runtime:e,command:t,target:S.target,sessionName:n,requestId:a.meta?.requestId,clickButton:m,flags:a.flags,durationMs:y}),afterRun:async e=>{var t;await h(l,(t=S.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,o=await W({params:e,session:l,result:r,extra:"longpress"===t?{...void 0!==n?{durationMs:n}:{},gesture:"longpress"}:k});return{result:o,responseData:o}}})}async function G(e){let{runtime:t,command:r,target:a,sessionName:n,requestId:o,flags:s}=e;if("longpress"===r)return await t.interactions.longPress(a,{session:n,requestId:o,durationMs:e.durationMs});let i={session:n,requestId:o,button:e.clickButton,count:s?.count,intervalMs:s?.intervalMs,holdMs:s?.holdMs,jitterPx:s?.jitterPx,doubleTap:s?.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,o="point"===a.kind?await M({session:r,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):P(r.snapshot?.nodes??[]);return O({data:a.backendResult,fallbackX:a.point?.x,fallbackY:a.point?.y,referenceFrame:o,extra:{...D(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:o,positionals:s,extra:i,fallbackPhase:l}=e,c=Date.now();try{var f,u;let e,l,d=await a(r.device,o,s,t.req.flags?.out,{...t.contextFromFlags(t.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:n,surface:r.surface})??{},p=Date.now(),g=(f=d,e="number"==typeof f.x?f.x:void 0,l="number"==typeof f.y?f.y:void 0,void 0!==e&&void 0!==l?{x:e,y:l}:{x:0,y:0}),m=O({data:d,fallbackX:g.x,fallbackY:g.y,referenceFrame:(u=d,"number"==typeof u.referenceWidth&&"number"==typeof u.referenceHeight?{referenceWidth:u.referenceWidth,referenceHeight:u.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 C({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(!v(e))return{ok:!1,error:k(e)};return I({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 s("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!n)return s("SESSION_NOT_FOUND","No active session. Run open first.");let i=function(e){let t=e[0]??"";if(t.startsWith("@")){var r;let a=u(e).text;return a?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:(r=e).length>=3&&r[1]?.trim()||""},text:a}:{ok:!1,response:s("INVALID_ARGS","fill requires text after ref")}}let a=U(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:s("INVALID_ARGS","fill requires text after coordinates")}}let n=u(e);return"selector"!==n.kind?{ok:!1,response:s("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:s("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!i.ok)return i.response;if("ref"===i.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await J(e,n)}let l=function(e){let{session:t,target:r,flags:a}=e;if("selector"!==r.kind)return null;let n=x({session:t,selectorExpression:r.selector});return n?{...n,...a?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:n,target:i.target,flags:t.flags});if(l){let t=await Y(e,n,l,i.text);if(t)return t}return await z(e,{run:async e=>await e.interactions.fill(i.target,i.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=O({data:e.backendResult,fallbackX:e.point?.x,fallbackY:e.point?.y,referenceFrame:t,extra:{...D(e),text:i.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:H(e.target?.kind==="ref"?e.target.ref:void 0),...e.point?{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 s("SESSION_NOT_FOUND","No active session. Run open first.");let a=K(e),o=Date.now();try{let s=await n({session:r,command:e.req.command,phase:"before-command"}),i=await t.run(a);await t.afterRun?.(i),await n({session:r,command:e.req.command,phase:"after-command"});let l=Date.now(),{result:c,responseData:f}=await t.buildPayloads(i);return"recovered"===s.status&&(c.warning=s.warning,f.warning=s.warning),C({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:function(e,t){if(("ref"!==t.kind||t.node)&&("click"===e||"press"===e)&&t.point)return Q(t.point)}(e.req.command,i),flags:e.req.flags,result:c,responseData:f,actionStartedAt:o,actionFinishedAt:l,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=m(t);if(y(e))throw e;return{ok:!1,error:k(t)}}}async function J(e,t){if(!l(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){I({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)]}async function Z(e){let t=await j({...e,captureSnapshotForSession:R,refSnapshotFlagGuardResponse:N});if(t)return t;switch(e.req.command){case A.type:return await ee({...e,captureSnapshotForSession:R});case"get":return await _(e);case"is":return await b(e);default:return null}}async function ee(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return s("SESSION_NOT_FOUND","No active session. Run open first.");if(!o(A.type,a.device))return s("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 i({session:e})).status?s("COMMAND_FAILED","Android system dialog blocked the recording session"):null}async function er(e,t){let{req:r,sessionName:a,sessionStore:o}=e,s=(r.positionals??[]).join(" "),i=K(e),l=Date.now();try{let e=await n({session:t,command:r.command,phase:"before-command"}),c=await i.interactions.typeText(s,{session:a,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await n({session:t,command:r.command,phase:"after-command"});let f=Date.now(),u={...c.backendResult??{},text:c.text,delayMs:c.delayMs,...p(c.message??`Typed ${Array.from(c.text).length} chars`)};return"recovered"===e.status&&(u.warning=e.warning),C({session:t,sessionStore:o,command:r.command,positionals:r.positionals??[],flags:r.flags,result:u,responseData:u,actionStartedAt:l,actionFinishedAt:f})}catch(e){return{ok:!1,error:k(e)}}}e.r(E),e.d(E,{handleInteractionCommands:()=>Z});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,ensureAndroidBlockingSystemDialogReady as n,isCommandSupportedOnDevice as o,errorResponse as s,recoverAndroidBlockingSystemDialog as i,getActiveAndroidSnapshotFreshness as l}from"./9722.js";import{buttonTag as c,resolveClickButton as f,readFillTargetFromPositionals as u,getClickButtonValidationError as d,successText as p}from"./2948.js";import{createAgentDevice as g}from"./2577.js";import{asAppError as m,normalizeError as k,AppError as S}from"./733.js";import{dispatchGetViaRuntime as _,isAndroidEscapeError as y,createDaemonRuntimePolicy as w,assertAndroidPressStayedInApp as h,dispatchIsViaRuntime as b,isDirectIosSelectorFallbackError as v,refSnapshotFlagGuardResponse as N,readSimpleIosSelectorTarget as x}from"./selector-runtime.js";import{resolveWebProvider as F}from"./provider.js";import{interaction_snapshot_captureSnapshotForSession as R,readSnapshotNodesReferenceFrame as P,resolveDirectTouchReferenceFrameSafely as M,buildTouchVisualizationResult as O,finalizeTouchInteraction as C}from"./8184.js";import{emitDiagnostic as I}from"./432.js";import{PUBLIC_COMMANDS as A}from"./2133.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:s("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 U(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 T(e,t){let r=U(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let a=e[0]??"";if(a.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:a,fallbackLabel:e.slice(1).join(" ").trim()}};let n=e.join(" ").trim();return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:s("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}function D(e){return"ref"===e.kind?{ref:H(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 H(e){return e?.startsWith("@")?e.slice(1):e}function K(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new S("SESSION_NOT_FOUND","No active session. Run open first.");return g({backend:function(e){let{req:t,session:r}=e,n=function(e){if("web"!==e.device.platform)return;let t=F();return t.clickRef||t.fillRef?t:void 0}(r);return{platform:r.device.platform,captureSnapshot:async(a,n)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:n?.interactiveOnly===!0,includeRects:n?.includeRects===!0})}),tap:async(n,o)=>L(await a(r.device,"press",[String(o.x),String(o.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),tapTarget:n?.clickRef?async(e,t)=>(await n.clickRef?.(t.ref),{ref:H(t.ref)}):void 0,fill:async(n,o,s)=>L(await a(r.device,"fill",[String(o.x),String(o.y),s],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fillTarget:n?.fillRef?async(e,t,r,a)=>(await n.fillRef?.(t.ref,r,a),{ref:H(t.ref),text:r,delayMs:a?.delayMs??0}):void 0,longPress:async(n,o,s)=>L(await a(r.device,"longpress",[String(o.x),String(o.y),...s?.durationMs===void 0?[]:[String(s.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(n,o)=>L(await a(r.device,"type",[o],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:n}),...w("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 L(e){return e&&"object"==typeof e?e:void 0}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:n,sessionStore:i}=e,l=i.get(n);if(!l)return s("SESSION_NOT_FOUND","No active session. Run open first.");let u="click"===t?"click":t,p="longpress"===t?"longpress":"press",g=q(l,u);if(g)return g;if(!o(p,l.device))return s("UNSUPPORTED_OPERATION",`${p} is not supported on this device`);let m=f(a.flags),k=c(m);if("longpress"!==t&&"primary"!==m){let e=d({commandLabel:u,platform:l.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 s(e.code,e.message,e.details)}let S="longpress"===t?function(e){var t,r,a;let n,o=U(e);if(o){return{ok:!0,target:{kind:"point",x:o.x,y:o.y},...void 0===(t=e[2])?{}:{durationMs:Number(t)}}}let s=(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=T(s.targetPositionals,"longpress");return i.ok?{ok:!0,target:i.target,...s.duration}:i}(a.positionals??[]):T(a.positionals??[],u);if(!S.ok)return S.response;if("ref"===S.target.kind){let n=e.refSnapshotFlagGuardResponse("longpress"===t?"longpress":"press",a.flags);if(n)return n;r=await J(e,l)}let _=function(e){var t;let{session:r,commandLabel:a,target:n,flags:o}=e;if("click"!==a||"selector"!==n.kind||(t=o,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 s=x({session:r,selectorExpression:n.selector});return s?{...s,...o?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:l,commandLabel:u,target:S.target,flags:a.flags});if(_){let t=await $(e,l,_);if(t)return t}let y="longpress"===t?S.durationMs:void 0;return await z(e,{androidFreshnessBaseline:r,run:async e=>await G({runtime:e,command:t,target:S.target,sessionName:n,requestId:a.meta?.requestId,clickButton:m,flags:a.flags,durationMs:y}),afterRun:async e=>{var t;await h(l,(t=S.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,o=await W({params:e,session:l,result:r,extra:"longpress"===t?{...void 0!==n?{durationMs:n}:{},gesture:"longpress"}:k});return{result:o,responseData:o}}})}async function G(e){let{runtime:t,command:r,target:a,sessionName:n,requestId:o,flags:s}=e;if("longpress"===r)return await t.interactions.longPress(a,{session:n,requestId:o,durationMs:e.durationMs});let i={session:n,requestId:o,button:e.clickButton,count:s?.count,intervalMs:s?.intervalMs,holdMs:s?.holdMs,jitterPx:s?.jitterPx,doubleTap:s?.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,o="point"===a.kind?await M({session:r,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):P(r.snapshot?.nodes??[]);return O({data:a.backendResult,fallbackX:a.point?.x,fallbackY:a.point?.y,referenceFrame:o,extra:{...D(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:o,positionals:s,extra:i,fallbackPhase:l}=e,c=Date.now();try{var f,u;let e,l,d=await a(r.device,o,s,t.req.flags?.out,{...t.contextFromFlags(t.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:n,surface:r.surface})??{},p=Date.now(),g=(f=d,e="number"==typeof f.x?f.x:void 0,l="number"==typeof f.y?f.y:void 0,void 0!==e&&void 0!==l?{x:e,y:l}:{x:0,y:0}),m=O({data:d,fallbackX:g.x,fallbackY:g.y,referenceFrame:(u=d,"number"==typeof u.referenceWidth&&"number"==typeof u.referenceHeight?{referenceWidth:u.referenceWidth,referenceHeight:u.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 C({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(!v(e))return{ok:!1,error:k(e)};return I({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 s("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!n)return s("SESSION_NOT_FOUND","No active session. Run open first.");let i=function(e){let t=e[0]??"";if(t.startsWith("@")){var r;let a=u(e).text;return a?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:(r=e).length>=3&&r[1]?.trim()||""},text:a}:{ok:!1,response:s("INVALID_ARGS","fill requires text after ref")}}let a=U(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:s("INVALID_ARGS","fill requires text after coordinates")}}let n=u(e);return"selector"!==n.kind?{ok:!1,response:s("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:s("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!i.ok)return i.response;if("ref"===i.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await J(e,n)}let l=function(e){let{session:t,target:r,flags:a}=e;if("selector"!==r.kind)return null;let n=x({session:t,selectorExpression:r.selector});return n?{...n,...a?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:n,target:i.target,flags:t.flags});if(l){let t=await Y(e,n,l,i.text);if(t)return t}return await z(e,{run:async e=>await e.interactions.fill(i.target,i.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=O({data:e.backendResult,fallbackX:e.point?.x,fallbackY:e.point?.y,referenceFrame:t,extra:{...D(e),text:i.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:H(e.target?.kind==="ref"?e.target.ref:void 0),...e.point?{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 s("SESSION_NOT_FOUND","No active session. Run open first.");let a=K(e),o=Date.now();try{let s=await n({session:r,command:e.req.command,phase:"before-command"}),i=await t.run(a);await t.afterRun?.(i),await n({session:r,command:e.req.command,phase:"after-command"});let l=Date.now(),{result:c,responseData:f}=await t.buildPayloads(i);return"recovered"===s.status&&(c.warning=s.warning,f.warning=s.warning),C({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:function(e,t){if(("ref"!==t.kind||t.node)&&("click"===e||"press"===e)&&t.point)return Q(t.point)}(e.req.command,i),flags:e.req.flags,result:c,responseData:f,actionStartedAt:o,actionFinishedAt:l,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=m(t);if(y(e))throw e;return{ok:!1,error:k(t)}}}async function J(e,t){if(!l(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){I({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)]}async function Z(e){let t=await j({...e,captureSnapshotForSession:R,refSnapshotFlagGuardResponse:N});if(t)return t;switch(e.req.command){case A.type:return await ee({...e,captureSnapshotForSession:R});case"get":return await _(e);case"is":return await b(e);default:return null}}async function ee(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return s("SESSION_NOT_FOUND","No active session. Run open first.");if(!o(A.type,a.device))return s("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 i({session:e})).status?s("COMMAND_FAILED","Android system dialog blocked the recording session"):null}async function er(e,t){let{req:r,sessionName:a,sessionStore:o}=e,s=(r.positionals??[]).join(" "),i=K(e),l=Date.now();try{let e=await n({session:t,command:r.command,phase:"before-command"}),c=await i.interactions.typeText(s,{session:a,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await n({session:t,command:r.command,phase:"after-command"});let f=Date.now(),u={...c.backendResult??{},text:c.text,delayMs:c.delayMs,...p(c.message??`Typed ${Array.from(c.text).length} chars`)};return"recovered"===e.status&&(u.warning=e.warning),C({session:t,sessionStore:o,command:r.command,positionals:r.positionals??[],flags:r.flags,result:u,responseData:u,actionStartedAt:l,actionFinishedAt:f})}catch(e){return{ok:!1,error:k(e)}}}e.r(E),e.d(E,{handleInteractionCommands:()=>Z});export{E as interaction_namespaceObject};
|
package/dist/src/internal/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var e,t,r,s;let n,o=process.argv.slice(2);function c(e){return"--help"===e||"-h"===e}function i(e){import("../cli.js").then(({runCli:t})=>t(e)).catch(p)}function p(e){process.stderr.write(`${e instanceof Error?e.message:String(e)}
|
|
2
|
-
`),process.exit(1)}1===(t=e=o).length&&("--version"===(r=t[0])||"-V"===r)&&(process.stdout.write(`0.17.
|
|
2
|
+
`),process.exit(1)}1===(t=e=o).length&&("--version"===(r=t[0])||"-V"===r)&&(process.stdout.write(`0.17.10
|
|
3
3
|
`),1)||0===e.length&&(import("../cli-help.js").then(({buildUsageText:e})=>{process.stdout.write(`${e()}
|
|
4
4
|
`),process.exit(1)}).catch(p),1)||void 0!==(n=function(e){var t,r,s,n;switch(e.length){case 1:return"help"===(t=e[0])||c(t)?null:void 0;case 2:return r=e[0],s=e[1],"help"===r?s:(n=r,c(s)?n:void 0);default:return}}(s=e))&&(import("../cli-help.js").then(({buildCommandUsageText:e,buildUsageText:t})=>{var r;if(null===n)return void process.stdout.write(`${t()}
|
|
5
5
|
`);let o=e("long-press"===(r=n)?"longpress":"metrics"===r?"perf":r);o?process.stdout.write(o):i(s)}).catch(p),1)||("mcp"!==o[0]||o.includes("--help")||o.includes("-h")?i(o):import("../server.js").then(({runAgentDeviceMcpServer:e})=>e()).catch(p));export{};
|
package/dist/src/react-native.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dispatchCommand as e,errorResponse as t,isCommandSupportedOnDevice as i}from"./9722.js";import{PUBLIC_COMMANDS as a}from"./2133.js";import{isSparseSnapshotQualityVerdict as s,analyzeReactNativeOverlay as r,successText as n,parsing_stripUndefined as o}from"./
|
|
1
|
+
import{dispatchCommand as e,errorResponse as t,isCommandSupportedOnDevice as i}from"./9722.js";import{PUBLIC_COMMANDS as a}from"./2133.js";import{isSparseSnapshotQualityVerdict as s,analyzeReactNativeOverlay as r,successText as n,parsing_stripUndefined as o}from"./2948.js";import{normalizeError as d}from"./733.js";import{interaction_snapshot_captureSnapshotForSession as l,readSnapshotNodesReferenceFrame as c,finalizeTouchInteraction as v}from"./8184.js";async function f(e){var o,c;let{req:v,sessionName:f,sessionStore:u}=e;if(v.command!==a.reactNative)return null;let y=1===(o=v.positionals??[]).length&&"dismiss-overlay"===o[0]?{ok:!0}:{ok:!1,response:t("INVALID_ARGS","react-native supports only: dismiss-overlay")};if(!y.ok)return y.response;let p=u.get(f);if(!p)return t("SESSION_NOT_FOUND","No active session. Run open first.");if(!i(a.reactNative,p.device))return t("UNSUPPORTED_OPERATION","react-native dismiss-overlay is not supported on this device");try{let i=await l(p,v.flags,u,e.contextFromFlags,{interactiveOnly:!0});if(s(i.snapshotQuality)){return c=i.snapshotQuality,t("COMMAND_FAILED","React Native overlay state could not be determined because the accessibility tree is unreadable",{reason:c.reason,hint:"The snapshot quality verdict is sparse. Use screenshot as visual truth; if an overlay is visible, report it or navigate with coordinates, then retry snapshot or dismiss-overlay on a readable screen."})}let a=r(i.nodes),o=a.primaryAction;if(!o)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,...n("No React Native overlay detected")}};return await m(e,p,i,o)}catch(e){return{ok:!1,error:d(e)}}}async function m(t,i,a,s){let{req:r,sessionStore:d}=t,l=Date.now(),f=await e(i.device,"press",[String(s.point.x),String(s.point.y)],r.flags?.out,t.contextFromFlags(r.flags,i.appBundleId,i.trace?.outPath))??{},m=Date.now(),y=await u(t,i),p=o({...c(a.nodes),...f,action:"dismiss-overlay",overlayAction:s.action,x:s.point.x,y:s.point.y,ref:s.ref,label:s.label,warning:s.warning,dismissed:!0,verified:y.verified,verificationRequired:!y.verified,verificationWarning:y.verificationWarning,nextCommand:y.nextCommand,...n(y.verified?"React Native overlay dismiss action sent and verified gone":"React Native overlay dismiss action sent, but verification still detects an overlay")});return v({session:i,sessionStore:d,command:r.command,positionals:r.positionals??[],flags:r.flags,result:p,responseData:p,actionStartedAt:l,actionFinishedAt:m})}async function u(e,t){let{req:i,sessionStore:a}=e,n=await l(t,i.flags,a,e.contextFromFlags,{interactiveOnly:!0});return s(n.snapshotQuality)?{verified:!1,verificationWarning:"React Native overlay dismissal could not be verified because the post-dismiss accessibility tree is unreadable. Use screenshot as visual truth.",nextCommand:"agent-device screenshot"}:r(n.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{f as handleReactNativeCommands};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let e,t,r,i;import a from"node:fs";import o from"node:path";import{createHash as n}from"node:crypto";import s from"node:os";import{fileURLToPath as c}from"node:url";import{AppError as d}from"./733.js";import{runCmd as l}from"./8875.js";import{acquireProcessLock as u}from"./2577.js";import{readProcessStartTime as m}from"./5628.js";import{sleep as f}from"./5560.js";import{withDiagnosticTimer as h,emitDiagnostic as p}from"./432.js";import{androidDeviceForSerial as w,runAndroidAdb as g}from"./3340.js";import{pullAndroidAdbFile as y}from"./2954.js";import{runXcrun as _,SessionStore as v,runIosRunnerCommand as P,errorResponse as S,isCommandSupportedOnDevice as A,ensureDeviceReady as M,resolvePublicSessionName as C,resolveImplicitSessionScope as b,resolveTargetDevice as x,IOS_RUNNER_CONTAINER_BUNDLE_IDS as I}from"./9722.js";import{resolveRecordingProvider as D}from"./recording-provider.js";import{recordingQualityInputToExportQuality as $,RECORDING_EXPORT_QUALITIES as R}from"./
|
|
1
|
+
let e,t,r,i;import a from"node:fs";import o from"node:path";import{createHash as n}from"node:crypto";import s from"node:os";import{fileURLToPath as c}from"node:url";import{AppError as d}from"./733.js";import{runCmd as l}from"./8875.js";import{acquireProcessLock as u}from"./2577.js";import{readProcessStartTime as m}from"./5628.js";import{sleep as f}from"./5560.js";import{withDiagnosticTimer as h,emitDiagnostic as p}from"./432.js";import{androidDeviceForSerial as w,runAndroidAdb as g}from"./3340.js";import{pullAndroidAdbFile as y}from"./2954.js";import{runXcrun as _,SessionStore as v,runIosRunnerCommand as P,errorResponse as S,isCommandSupportedOnDevice as A,ensureDeviceReady as M,resolvePublicSessionName as C,resolveImplicitSessionScope as b,resolveTargetDevice as x,IOS_RUNNER_CONTAINER_BUNDLE_IDS as I}from"./9722.js";import{resolveRecordingProvider as D}from"./recording-provider.js";import{recordingQualityInputToExportQuality as $,RECORDING_EXPORT_QUALITIES as R}from"./2948.js";function N(e=process.env){let t=F(),r=o.join(t,"home"),i=o.join(t,"module-cache");return a.mkdirSync(r,{recursive:!0}),a.mkdirSync(i,{recursive:!0}),{...e,HOME:r,CLANG_MODULE_CACHE_PATH:i}}async function k(e){let t=a.statSync(e.sourcePath),r=a.readFileSync(e.sourcePath),i=z(e.cacheName??o.basename(e.sourcePath,o.extname(e.sourcePath))),n=U(["2",process.platform,process.arch,o.resolve(e.sourcePath),t.size,r]),s=o.join(F(),"bin",`${i}-${n}`);return await O({sourcePath:e.sourcePath,executablePath:s,timeoutMs:e.timeoutMs}),s}async function E(e){let t=z(e.cacheName),r=U(["2",process.platform,process.arch,e.source]),i=o.join(F(),"sources",`${t}-${r}.swift`),a=o.join(F(),"bin",`${t}-${r}`);return await O({sourcePath:i,executablePath:a,sourceText:e.source,timeoutMs:e.timeoutMs}),a}function F(){let e=process.env.AGENT_DEVICE_SWIFT_CACHE_DIR?.trim();return e?o.resolve(e):o.join(s.tmpdir(),"agent-device-swift-cache")}async function O(e){if(T(e.executablePath))return;let t=o.dirname(e.executablePath);a.mkdirSync(t,{recursive:!0});let r=`${e.executablePath}.lock`,i=await L(r,e.executablePath,e.timeoutMs??12e4);if(!i)return;let n=a.mkdtempSync(o.join(t,`.${o.basename(e.executablePath)}.${process.pid}.`)),s=o.join(n,o.basename(e.executablePath));try{if(T(e.executablePath))return;void 0===e.sourceText||a.existsSync(e.sourcePath)||(a.mkdirSync(o.dirname(e.sourcePath),{recursive:!0}),a.writeFileSync(e.sourcePath,e.sourceText)),await l("xcrun",["swiftc",e.sourcePath,"-o",s],{timeoutMs:e.timeoutMs??12e4,env:N()}),a.renameSync(s,e.executablePath)}finally{a.rmSync(n,{recursive:!0,force:!0}),await i()}}async function L(e,t,r){if(T(t))return null;try{return await u({lockDirPath:e,owner:{pid:process.pid,startTime:m(process.pid),acquiredAtMs:Date.now()},timeoutMs:r,pollMs:25,ownerGraceMs:r,description:`Swift cache lock: ${e} (${r}ms)`})}catch(t){if(t instanceof d&&t.message.startsWith("Timed out waiting for Swift cache lock:"))throw new d("COMMAND_FAILED",t.message,{...t.details,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.`});throw t}}function T(e){try{return a.accessSync(e,a.constants.X_OK),a.statSync(e).isFile()}catch{return!1}}function z(e){return e.replaceAll(/[^A-Za-z0-9._-]/g,"-").replaceAll(/^-+|-+$/g,"")||"swift-helper"}function U(e){let t=n("sha256");for(let r of e)t.update(Buffer.isBuffer(r)?r:String(r)),t.update("\0");return t.digest("hex").slice(0,16)}let K=`
|
|
2
2
|
import Foundation
|
|
3
3
|
import AVFoundation
|
|
4
4
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDaemonRuntimeSessionStore as e,setSessionSnapshot as t,captureSnapshot as r,dispatchCommand as s,runIosRunnerCommand as n,isCommandSupportedOnDevice as o,errorResponse as i,ensureDeviceReady as a,stopIosRunnerSession as l,resolveRunnerAppBundleId as u,getActiveAndroidSnapshotFreshness as c,resolveTargetDevice as d,context_contextFromFlags as f}from"./9722.js";import{closeIosApp as p}from"./apps.js";import{emitDiagnostic as m}from"./432.js";import{asAppError as g,normalizeError as h,AppError as y}from"./733.js";import{evaluateIsPredicate as w,isSupportedPredicate as _,localCommandPolicy as S,createAgentDevice as v}from"./2577.js";import{tryParseSelectorChain as x,extractNodeReadText as k,prefersValueForReadableText as I,findNodeByLabel as N,normalizeType as A,splitIsSelectorArgs as P}from"./9836.js";import{resolveRectCenter as R,isSparseSnapshotQualityVerdict as b,parseWaitPositionals as D}from"./9873.js";import{getAndroidAppState as E}from"./3340.js";import{isApplePlatform as q}from"./5910.js";import{parseFindArgs as C}from"./587.js";import{buildSnapshotPresentationKey as M,snapshotPresentationOptionsFromFlags as O}from"./4291.js";async function $(e,t,r){let s=e.get(t),n=s?.device??await d(r??{});return s||await a(n),{session:s,device:n}}async function L(e,t,r){let s=!e&&"ios"===t.platform;try{return await r()}finally{s&&(await l(t.id),await K(t))}}async function K(e){let t=u();await p(e,t).catch(r=>{m({level:"debug",phase:"ios_sessionless_runner_host_close_failed",data:{deviceId:e.id,bundleId:t,error:r instanceof Error?r.message:String(r)}})})}function U(e,t,r,s){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:s})}function F(e){let{session:t,sessionName:r,device:s,snapshot:n,appBundleId:o}=e;return t?{...t,snapshot:n,lastComparisonSafeSnapshot:n?.comparisonSafe===!0?n:t.lastComparisonSafeSnapshot}:{name:r,device:s,createdAt:Date.now(),appBundleId:o,snapshot:n,...n?.comparisonSafe===!0?{lastComparisonSafeSnapshot:n}:{},actions:[]}}function T(e,t={}){return{artifacts:function(e,t={}){let r=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not create temporary files`)}}}(e,t),policy:S()}}async function G(e){let{device:t,node:r,flags:n,appBundleId:o,traceOutPath:i,surface:a,contextFromFlags:l}=e,u=k(r),c=R(r.rect);if(!c||"ios"===t.platform&&u&&!I(r.type??""))return u;try{let e=await s(t,"read",[String(c.x),String(c.y)],void 0,{...l(n,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 m({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:a,platform:t.platform}}),u}catch(e){return m({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 V=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function B(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,s]of V)void 0!==e[r]&&t.push(s);return t}(t);return 0===r.length?null:i("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function X(e,t){let r=await H(e);if(r)throw new y("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${r.foregroundPackage}. The tap likely escaped the app.`,r)}async function H(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let r=await E(e.device),s=r.package?.trim();return s&&s!==e.appBundleId&&("com.android.settings"===(t=s)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:s,activity:r.activity,hint:"com.google.android.permissioncontroller"===s?"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 j(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function W(e,t){let r=Array.isArray(e.selectorChain)?e.selectorChain:void 0,s=Y(e),n=s?.kind==="ref"?Z(s.ref):void 0,o=s?.kind==="selector"?s.selector:void 0,i={...n?{ref:n}:{},...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 z(e){let t=Y(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 Q(e){let{selectorChain:t,...r}=e;return r}function J(e,t,r,s){let n=e.get(t);n&&e.recordAction(n,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:s})}function Y(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 ee=["application","window","tabbar","scrollbar","image"],et=new Set(["tab bar"]);async function er(e,t){var r;if(t.ok||(r=t.error.message,!/^wait timed out for (?:selector|text): /i.test(r)))return t;let s=await es(e).catch(()=>null);return s?i(t.error.code,`${t.error.message}. Current surface: ${s.summary}.`,{...t.error.details??{},currentSurface:s.details}):t}async function es(e){let t=[...(await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!0},logPath:e.logPath??""})).snapshot.nodes].sort(eo),s=en(t,6,{includeIdentifiers:!0});if(0===s.length)return null;let n=en(t.filter(e=>!el(e)),4,{includeIdentifiers:!1}),o=en(t.filter(eu),4,{includeIdentifiers:!0});return{summary:(n.length>0?n:s.slice(0,4)).join(", "),details:{labels:s,...o.length>0?{buttons:o}:{}}}}function en(e,t,r){let s=new Set,n=[];for(let o of e){let e=ea(o,r);if(!(!e||s.has(e))&&(s.add(e),n.push(e),n.length>=t))break}return n}function eo(e,t){var r,s;return ei(e)-ei(t)||(r=e,s=t,r.rect&&s.rect?r.rect.y-s.rect.y||r.rect.x-s.rect.x:r.rect?-1:s.rect?1:(r.depth??0)-(s.depth??0)||r.index-s.index)}function ei(e){let t=!!ea(e,{includeIdentifiers:!1});return 2*!!el(e)+ +!t}function ea(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 el(e){let t=A(`${e.type??""} ${e.role??""} ${e.subrole??""}`),r=`${e.label??""} ${e.value??""}`.trim().toLowerCase();return ee.some(e=>t.includes(e))||et.has(r)||r.endsWith(".fill")}function eu(e){return A(`${e.type??""} ${e.role??""} ${e.subrole??""}`).includes("button")}function ec(e){var t;let{session:r,selectorExpression:s}=e;if(!r||"ios"!==r.device.platform||r.postGestureStabilization)return null;let n=x(s);if(!n||1!==n.selectors.length)return null;let o=n.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 ed(e,t={}){let r=g(e);if("ELEMENT_NOT_FOUND"===r.code)return!0===t.allowElementNotFound;if("COMMAND_FAILED"!==r.code)return!1;let s=r.message.toLowerCase();return s.includes("fetch failed")||s.includes("timed out")||s.includes("timeout")||s.includes("runner did not accept connection")||s.includes("invalid runner response")}async function ef(e){var t;let{req:r}=e;if("find"!==r.command)return null;let s=r.positionals??[];if(0===s.length)return i("INVALID_ARGS","find requires a locator or text");let n=C(s);if(!n.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=n.action;if("exists"!==(t=o)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let a=await eI(e,{requireSession:!1,capability:"find"});return a.ok?await eP(async()=>{let t=await a.runtime.selectors.find({session:e.sessionName,requestId:r.meta?.requestId,locator:n.locator,query:n.query,action:o,timeoutMs:n.timeoutMs});return J(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 ep(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 s=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(!s.ok)return s.response;if("ref"===s.target.kind){let e=B("get",t.flags);if(e)return e}if("selector"===s.target.kind){let t=await eh(e,r,s.target.selector);if(t)return t}let n=await eI(e,{requireSession:!0,capability:"get"});return n.ok?await eP(async()=>{let o=await n.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:r,target:s.target});return J(e.sessionStore,e.sessionName,t,W(o,r)),z(o)}):n.response}async function em(e){let{req:t}=e;if("is"!==t.command)return null;let r=(t.positionals?.[0]??"").toLowerCase();if(!_(r))return i("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:s}=P(t.positionals??[]);if(!s)return i("INVALID_ARGS","is requires a selector expression");let n=s.rest.join(" ").trim();if("text"===r&&!n)return i("INVALID_ARGS","is text requires expected text value");if("text"!==r&&s.rest.length>0)return i("INVALID_ARGS",`is ${r} does not accept trailing values`);let o=await ey(e,r,s.selectorExpression,n);if(o)return o;let a=await eI(e,{requireSession:!0,capability:"is"});if(!a.ok)return a.response;let l=await eP(async()=>{let o=await a.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:r,selector:s.selectorExpression,expectedText:n});return J(e.sessionStore,e.sessionName,t,o),Q(o)});return await eR(e,l,`is ${r}`)}async function eg(e){let{req:t,sessionName:r,sessionStore:s}=e,n=D(t.positionals??[]);if(!n)return i("INVALID_ARGS","wait requires a duration or text");let{session:a,device:l}=await $(s,r,t.flags);if("sleep"!==n.kind&&!o("wait",l))return i("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===n.kind){let t=await ew({...e,session:a,device:l,selectorExpression:n.selectorExpression,timeoutMs:n.timeoutMs});if(t)return t}let u=async()=>{let o=ek({...e,session:a,device:l}),i=await eP(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 y("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new y("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(n,a)});return J(s,r,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}}),u=await er({req:t,logPath:e.logPath,session:a,device:l},i);return await eR(e,u,"wait")};return"sleep"===n.kind?await u():await L(a,l,u)}async function eh(e,t,r){let s=e.sessionStore.get(e.sessionName),n=ec({session:s,selectorExpression:r});if(!s||!n||"text"===t&&"id"!==n.key)return null;let o=await ev(e,s,n);if(ex(o))return o.response;if(!o)return null;let i=function(e,t,r){if(!r.found||!r.node)return null;let s={target:{kind:"selector",selector:t},node:r.node,selectorChain:[t]};return"attrs"===e?{kind:"attrs",...s}:"string"!=typeof r.text?null:{kind:"text",...s,text:r.text}}(t,n.raw,o);return i?(J(e.sessionStore,e.sessionName,e.req,W(i,t)),{ok:!0,data:z(i)}):null}async function ey(e,t,r,s){var n,o,i,a,l;let u;if("hidden"===t)return null;let c=await e_(e,r);if(ex(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]}:(n=t,o=s,i=c.selector.raw,a=c.session,u=w({predicate:n,node:l=c.result.node,nodes:[l],expectedText:o,platform:a.device.platform}),{predicate:n,pass:u.pass,selector:i,..."text"===n?{text:u.actualText}:{},selectorChain:[i]});return d?(J(e.sessionStore,e.sessionName,e.req,d),{ok:!0,data:Q(d)}):null}async function ew(e){let t=ec({session:e.session,selectorExpression:e.selectorExpression});if(!e.session||!t)return null;let r=Date.now(),s=await ev(e,e.session,t);if(ex(s))return s.response;if(!s?.found)return null;let n={kind:"selector",selector:t.raw,waitedMs:Date.now()-r,selectorChain:[t.raw]};return J(e.sessionStore,e.sessionName,e.req,n),await er({req:e.req,logPath:e.logPath,session:e.session,device:e.device},{ok:!0,data:n})}async function e_(e,t){let r=e.sessionStore.get(e.sessionName),s=ec({session:r,selectorExpression:t});if(!r||!s)return null;let n=await ev(e,r,s);return ex(n)?n:n?{session:r,selector:s,result:n}:null}async function eS(e,t,r){let s=await n(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,iosXctestrunFile:e.req.flags?.iosXctestrunFile,iosXctestDerivedDataPath:e.req.flags?.iosXctestDerivedDataPath,iosXctestEnvDir:e.req.flags?.iosXctestEnvDir}),o=!0===s.found,i=function(e){let t=e.nodes;if(!Array.isArray(t))return;let r=t[0];if(r&&"object"==typeof r)return r}(s);return{found:o,..."string"==typeof s.text?{text:s.text}:{},...i?{node:i}:{}}}async function ev(e,t,r){try{return await eS(e,t,r)}catch(e){if(ed(e,{allowElementNotFound:!0}))return null;return{kind:"error",response:{ok:!1,error:h(e)}}}}function ex(e){return null!==e&&"kind"in e&&"error"===e.kind}function ek(s){return v({backend:function(e){let s,{req:n,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={...n.flags,...(p=f,m={},p?.interactiveOnly!==void 0&&(m.snapshotInteractiveOnly=p.interactiveOnly),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?.includeRects===!0,y=f?.scope??n.flags?.snapshotScope,w=Date.now(),_=M(O(g)),S="wait"===n.command||"find"===n.command||h&&"web"===i.platform;if(!S&&s&&w-d<750&&!c(o)&&!o?.postGestureStabilization)return s;if(!S&&o?.snapshot&&w-o.snapshot.createdAt<750&&o.snapshot.presentationKey===_&&!c(o)&&!o.postGestureStabilization)return d=o.snapshot.createdAt,s={snapshot:o.snapshot};let v=await r({device:i,session:o,flags:g,outPath:n.flags?.out,logPath:a??"",snapshotScope:y,includeRects:h});return o&&!b(v.snapshot.snapshotQuality)&&(t(o,v.snapshot),u.set(l,o)),d=w,s={snapshot:v.snapshot}},readText:async(t,r)=>({text:await G({device:i,node:r,flags:n.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 eN(e,r)})}}(s),...T("selector commands",{plural:!0}),sessions:e({sessionName:s.sessionName,getSession:()=>s.session,recordOptions:{includeSnapshot:!0},setRecord:e=>{s.session&&e.snapshot&&(t(s.session,e.snapshot),s.sessionStore.set(s.sessionName,s.session))}})})}async function eI(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 s=r?.device??await d(e.req.flags??{});return(r||await a(s),o(t.capability,s))?{ok:!0,runtime:ek({...e,session:r,device:s})}:{ok:!1,response:i("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function eN(e,t){let{device:r,session:s,req:o,logPath:i}=e;if("macos"===r.platform&&s?.surface&&"app"!==s.surface)return!!N((await eA(e)).nodes,t);if(q(r.platform)&&s?.appBundleId){let e=await n(r,{command:"findText",text:t,appBundleId:s?.appBundleId},{verbose:o.flags?.verbose,logPath:i,traceLogPath:s?.trace?.outPath,requestId:o.meta?.requestId,iosXctestrunFile:o.flags?.iosXctestrunFile,iosXctestDerivedDataPath:o.flags?.iosXctestDerivedDataPath,iosXctestEnvDir:o.flags?.iosXctestEnvDir});return e?.found===!0}return!!N((await eA(e)).nodes,t)}async function eA(e){let s=await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&!b(s.snapshot.snapshotQuality)&&(t(e.session,s.snapshot),e.sessionStore.set(e.sessionName,e.session)),s.snapshot}async function eP(e){try{return{ok:!0,data:await e()}}catch(t){let e=g(t);return i(e.code,e.message,e.details)}}async function eR(e,t,r){var s;let n;if(t.ok)return t;let o=e.sessionStore.get(e.sessionName);if(!o)return t;try{n=await H(o)}catch{return t}return n?i(t.error.code,`${r} failed because ${"com.google.android.permissioncontroller"===(s=n).foregroundPackage?`Android permission dialog is blocking ${s.expectedPackage}`:`${s.foregroundPackage} is foreground instead of ${s.expectedPackage}`}.`,{...t.error.details??{},...n,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}export{X as assertAndroidPressStayedInApp,F as buildSnapshotSession,T as createDaemonRuntimePolicy,ef as dispatchFindReadOnlyViaRuntime,ep as dispatchGetViaRuntime,em as dispatchIsViaRuntime,eg as dispatchWaitViaRuntime,j as isAndroidEscapeError,ed as isDirectIosSelectorFallbackError,ec as readSimpleIosSelectorTarget,G as readTextForNode,U as recordIfSession,B as refSnapshotFlagGuardResponse,$ as resolveSessionDevice,L as withSessionlessRunnerCleanup};
|
|
1
|
+
import{setSessionSnapshot as e,createDaemonRuntimeSessionStore as t,captureSnapshot as r,dispatchCommand as n,runIosRunnerCommand as s,errorResponse as o,isCommandSupportedOnDevice as i,ensureDeviceReady as a,stopIosRunnerSession as l,resolveRunnerAppBundleId as c,getActiveAndroidSnapshotFreshness as u,resolveTargetDevice as d,context_contextFromFlags as f}from"./9722.js";import{closeIosApp as p}from"./apps.js";import{emitDiagnostic as m}from"./432.js";import{asAppError as g,normalizeError as h,AppError as y}from"./733.js";import{evaluateIsPredicate as w,isSupportedPredicate as S,localCommandPolicy as v,createAgentDevice as _}from"./2577.js";import{getAndroidAppState as I}from"./3340.js";import{splitIsSelectorArgs as x,normalizeType as k,prefersValueForReadableText as P,findNodeByLabel as N,extractNodeReadText as A}from"./9836.js";import{resolveRectCenter as R,isSparseSnapshotQualityVerdict as b,parseWaitPositionals as q}from"./2948.js";import{buildSnapshotPresentationKey as D,snapshotPresentationOptionsFromFlags as E}from"./4291.js";import{isApplePlatform as C}from"./5910.js";import{parseFindArgs as M,tryParseSelectorChain as O}from"./587.js";async function $(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 F(e,t,r){let n=!e&&"ios"===t.platform;try{return await r()}finally{n&&(await l(t.id),await L(t))}}async function L(e){let t=c();await p(e,t).catch(r=>{m({level:"debug",phase:"ios_sessionless_runner_host_close_failed",data:{deviceId:e.id,bundleId:t,error:r instanceof Error?r.message:String(r)}})})}function K(e,t,r,n){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function U(e){let{session:t,sessionName:r,device:n,snapshot:s,appBundleId:o}=e;return t?{...t,snapshot:s,lastComparisonSafeSnapshot:s?.comparisonSafe===!0?s:t.lastComparisonSafeSnapshot}:{name:r,device:n,createdAt:Date.now(),appBundleId:o,snapshot:s,...s?.comparisonSafe===!0?{lastComparisonSafeSnapshot:s}:{},actions:[]}}function T(e,t={}){return{artifacts:function(e,t={}){let r=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not create temporary files`)}}}(e,t),policy:v()}}let G=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function V(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,n]of G)void 0!==e[r]&&t.push(n);return t}(t);return 0===r.length?null:o("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function B(e,t){let r=await X(e);if(r)throw new y("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${r.foregroundPackage}. The tap likely escaped the app.`,r)}async function X(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let r=await I(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 H(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function j(e,t){let r=Array.isArray(e.selectorChain)?e.selectorChain:void 0,n=J(e),s=n?.kind==="ref"?Y(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 z(e){let t=J(e);return{...t?.kind==="ref"?{ref:Y(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 Q(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 J(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 Y(e){return e.startsWith("@")?e.slice(1):e}let Z=["application","window","tabbar","scrollbar","image"],ee=new Set(["tab bar"]);async function et(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 er(e).catch(()=>null);return n?o(t.error.code,`${t.error.message}. Current surface: ${n.summary}.`,{...t.error.details??{},currentSurface:n.details}):t}async function er(e){let t=[...(await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!0},logPath:e.logPath??""})).snapshot.nodes].sort(es),n=en(t,6,{includeIdentifiers:!0});if(0===n.length)return null;let s=en(t.filter(e=>!ea(e)),4,{includeIdentifiers:!1}),o=en(t.filter(el),4,{includeIdentifiers:!0});return{summary:(s.length>0?s:n.slice(0,4)).join(", "),details:{labels:n,...o.length>0?{buttons:o}:{}}}}function en(e,t,r){let n=new Set,s=[];for(let o of e){let e=ei(o,r);if(!(!e||n.has(e))&&(n.add(e),s.push(e),s.length>=t))break}return s}function es(e,t){var r,n;return eo(e)-eo(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 eo(e){let t=!!ei(e,{includeIdentifiers:!1});return 2*!!ea(e)+ +!t}function ei(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 ea(e){let t=k(`${e.type??""} ${e.role??""} ${e.subrole??""}`),r=`${e.label??""} ${e.value??""}`.trim().toLowerCase();return Z.some(e=>t.includes(e))||ee.has(r)||r.endsWith(".fill")}function el(e){return k(`${e.type??""} ${e.role??""} ${e.subrole??""}`).includes("button")}function ec(e){var t;let{session:r,selectorExpression:n}=e;if(!r||"ios"!==r.device.platform||r.postGestureStabilization)return null;let s=O(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 eu(e,t={}){let r=g(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 ed(e){let{device:t,node:r,flags:s,appBundleId:o,traceOutPath:i,surface:a,contextFromFlags:l}=e,c=A(r),u=R(r.rect);if(!u||"ios"===t.platform&&c&&!P(r.type??""))return c;try{let e=await n(t,"read",[String(u.x),String(u.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 m({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:a,platform:t.platform}}),c}catch(e){return m({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)}}),c}}function ef(t){let r,n,{session:s,sessionStore:o,sessionName:i}=t,a=0;return{capture:async l=>{var c,d;let f=Date.now(),p=(c=l,d=t.req.flags?.out,JSON.stringify({presentationKey:D(E(ew(c))),includeRects:!0===c.includeRects,outPath:c.outPath??d??null})),m=function(e){let{timestamp:t,lastSnapshotAt:r,lastSnapshotResult:n,lastSnapshotCacheKey:s,session:o,request:i,cacheKey:a}=e;if(!(i.cache?.forceFresh===!0||!n||s!==a||t-r>=750||u(o))&&!ey(o,i))return n}({timestamp:f,lastSnapshotAt:a,lastSnapshotResult:r,lastSnapshotCacheKey:n,session:s,request:l,cacheKey:p});if(m)return m;let g=function(e){var t,r;let{session:n,timestamp:s,request:o}=e,i=n?.snapshot;if(i&&(t=n,r=o,!(r.cache?.forceFresh===!0||r.cache?.useSessionSnapshot!==!0||u(t)||ey(t,r)))&&s-i.createdAt<750&&i.presentationKey===function(e){return D(E(ew(e)))}(o))return i}({session:s,timestamp:f,request:l});if(g)return a=g.createdAt,r={snapshot:g},n=p,r;let h=await ep({params:t,request:l}),y={snapshot:h};return function(t){let{session:r,sessionStore:n,sessionName:s,snapshot:o}=t;!r||b(o.snapshotQuality)||(e(r,o),n.set(s,r))}({session:s,sessionStore:o,sessionName:i,snapshot:h}),a=f,r=y,n=p,y}}}async function ep(e){var t;let{params:r,request:n}=e,s=await eh(r,n,n.snapshotScope);return n.recovery?.legacyIosSparse&&!(t=s).snapshotQuality&&"xctest"===t.backend&&1===t.nodes.length&&t.nodes[0]?.type==="Application"?await em({runtimeParams:r,request:n,policy:n.recovery.legacyIosSparse}):n.recovery?.sparseVerdictQueryScope?.shouldScope&&b(s.snapshotQuality)?await eg({runtimeParams:r,request:n,policy:n.recovery.sparseVerdictQueryScope,snapshot:s}):s}async function em(e){let{runtimeParams:t,request:r,policy:n}=e;try{return await eh(t,r,n.scope,!1)}catch(e){if(!n.shouldScope)throw e;return await eh(t,r,n.query,!1)}}async function eg(e){let{runtimeParams:t,request:r,policy:n,snapshot:s}=e;try{return await eh(t,r,n.query,!1)}catch{return s}}async function eh(e,t,n,s=t.flags?.snapshotInteractiveOnly){return(await r({device:e.device,session:e.session,flags:{...t.flags,snapshotInteractiveOnly:s},outPath:t.outPath??e.req.flags?.out,logPath:e.logPath??"",snapshotScope:n,includeRects:t.includeRects})).snapshot}function ey(e,t){return t.cache?.bypassForPostGestureStabilization===!0&&!!e?.postGestureStabilization}function ew(e){return void 0===e.snapshotScope?e.flags:{...e.flags,snapshotScope:e.snapshotScope}}function eS(r){return _({backend:function(e){let{req:t,session:r,device:n,logPath:s,sessionName:o,sessionStore:i}=e,a=ef({device:n,session:r,sessionStore:i,sessionName:o,req:t,logPath:s});return{platform:n.platform,captureSnapshot:async(e,r)=>{var s;let o,i={...t.flags,...(s=r,o={},s?.interactiveOnly!==void 0&&(o.snapshotInteractiveOnly=s.interactiveOnly),s?.scope!==void 0&&(o.snapshotScope=s.scope),s?.depth!==void 0&&(o.snapshotDepth=s.depth),s?.raw!==void 0&&(o.snapshotRaw=s.raw),o)},l=r?.includeRects===!0,c=r?.scope??t.flags?.snapshotScope,u="wait"===t.command||"find"===t.command||l&&"web"===n.platform;return await a.capture({flags:i,snapshotScope:c,includeRects:l,cache:{forceFresh:u,useSessionSnapshot:!0,bypassForPostGestureStabilization:!0}})},readText:async(o,i)=>({text:await ed({device:n,node:i,flags:t.flags,appBundleId:r?.appBundleId,traceOutPath:r?.trace?.outPath,surface:r?.surface,contextFromFlags:e.contextFromFlags??((e,t,r)=>f(s??"",e,t,r))})}),findText:async(t,r)=>({found:await e_(e,r)})}}(r),...T("selector commands",{plural:!0}),sessions:t({sessionName:r.sessionName,getSession:()=>r.session,recordOptions:{includeSnapshot:!0},setRecord:t=>{r.session&&t.snapshot&&(e(r.session,t.snapshot),r.sessionStore.set(r.sessionName,r.session))}})})}async function ev(e,t){let r=e.sessionStore.get(e.sessionName);if(!r&&t.requireSession)return{ok:!1,response:o("SESSION_NOT_FOUND","No active session. Run open first.")};let n=r?.device??await d(e.req.flags??{});return(r||await a(n),i(t.capability,n))?{ok:!0,runtime:eS({...e,session:r,device:n})}:{ok:!1,response:o("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function e_(e,t){let r=await eI(e,t);if(null!==r)return r;let n=await ex(e,t);return null!==n?n:await ek(e,t)}async function eI(e,t){return"macos"===e.device.platform&&e.session?.surface&&"app"!==e.session.surface?await ek(e,t):null}async function ex(e,t){var r,n,o;let i,a,l=C((r=e).device.platform)&&r.session?.appBundleId?{device:r.device,appBundleId:r.session.appBundleId,traceLogPath:r.session.trace?.outPath}:null;if(!l)return null;let c=await s(l.device,{command:"findText",text:t,appBundleId:l.appBundleId},(n=e,o=l,i=n.req.flags??{},a=n.req.meta??{},{verbose:i.verbose,logPath:n.logPath,traceLogPath:o.traceLogPath,requestId:a.requestId,iosXctestrunFile:i.iosXctestrunFile,iosXctestDerivedDataPath:i.iosXctestDerivedDataPath,iosXctestEnvDir:i.iosXctestEnvDir}));return c?.found===!0}async function ek(e,t){return!!N((await eP(e)).nodes,t)}async function eP(e){let t=ef({device:e.device,session:e.session,sessionStore:e.sessionStore,sessionName:e.sessionName,req:e.req,logPath:e.logPath}),{snapshot:r}=await t.capture({flags:{...e.req.flags,snapshotInteractiveOnly:!1},cache:{forceFresh:!0,bypassForPostGestureStabilization:!0}});return r}async function eN(e){var t;let{req:r}=e;if("find"!==r.command)return null;let n=r.positionals??[];if(0===n.length)return o("INVALID_ARGS","find requires a locator or text");let s=M(n);if(!s.query)return o("INVALID_ARGS","find requires a value");if(r.flags?.findFirst&&r.flags?.findLast)return o("INVALID_ARGS","find accepts only one of --first or --last");let i=s.action;if("exists"!==(t=i)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let a=await ev(e,{requireSession:!1,capability:"find"});return a.ok?await eF(async()=>{let t=await a.runtime.selectors.find({session:e.sessionName,requestId:r.meta?.requestId,locator:s.locator,query:s.query,action:i,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,i)),"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 eA(e){let{req:t}=e;if("get"!==t.command)return null;let r=t.positionals?.[0];if("text"!==r&&"attrs"!==r)return o("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:o("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!n.ok)return n.response;if("ref"===n.target.kind){let e=V("get",t.flags);if(e)return e}if("selector"===n.target.kind){let t=await eq(e,r,n.target.selector);if(t)return t}let s=await ev(e,{requireSession:!0,capability:"get"});return s.ok?await eF(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,j(o,r)),z(o)}):s.response}async function eR(e){let{req:t}=e;if("is"!==t.command)return null;let r=(t.positionals?.[0]??"").toLowerCase();if(!S(r))return o("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:n}=x(t.positionals??[]);if(!n)return o("INVALID_ARGS","is requires a selector expression");let s=n.rest.join(" ").trim();if("text"===r&&!s)return o("INVALID_ARGS","is text requires expected text value");if("text"!==r&&n.rest.length>0)return o("INVALID_ARGS",`is ${r} does not accept trailing values`);let i=await eD(e,r,n.selectorExpression,s);if(i)return i;let a=await ev(e,{requireSession:!0,capability:"is"});if(!a.ok)return a.response;let l=await eF(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),Q(o)});return await eL(e,l,`is ${r}`)}async function eb(e){let{req:t,sessionName:r,sessionStore:n}=e,s=q(t.positionals??[]);if(!s)return o("INVALID_ARGS","wait requires a duration or text");let{session:a,device:l}=await $(n,r,t.flags);if("sleep"!==s.kind&&!i("wait",l))return o("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===s.kind){let t=await eE({...e,session:a,device:l,selectorExpression:s.selectorExpression,timeoutMs:s.timeoutMs});if(t)return t}let c=async()=>{let o=eS({...e,session:a,device:l}),i=await eF(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 y("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new y("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}:{}}}),c=await et({req:t,logPath:e.logPath,session:a,device:l},i);return await eL(e,c,"wait")};return"sleep"===s.kind?await c():await F(a,l,c)}async function eq(e,t,r){let n=e.sessionStore.get(e.sessionName),s=ec({session:n,selectorExpression:r});if(!n||!s||"text"===t&&"id"!==s.key)return null;let o=await eO(e,n,s);if(e$(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,j(i,t)),{ok:!0,data:z(i)}):null}async function eD(e,t,r,n){var s,o,i,a,l;let c;if("hidden"===t)return null;let u=await eC(e,r);if(e$(u))return u.response;if(!u?.result.found||!u.result.node)return null;let d="exists"===t?{predicate:t,pass:!0,selector:u.selector.raw,matches:1,selectorChain:[u.selector.raw]}:(s=t,o=n,i=u.selector.raw,a=u.session,c=w({predicate:s,node:l=u.result.node,nodes:[l],expectedText:o,platform:a.device.platform}),{predicate:s,pass:c.pass,selector:i,..."text"===s?{text:c.actualText}:{},selectorChain:[i]});return d?(W(e.sessionStore,e.sessionName,e.req,d),{ok:!0,data:Q(d)}):null}async function eE(e){let t=ec({session:e.session,selectorExpression:e.selectorExpression});if(!e.session||!t)return null;let r=Date.now(),n=await eO(e,e.session,t);if(e$(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 et({req:e.req,logPath:e.logPath,session:e.session,device:e.device},{ok:!0,data:s})}async function eC(e,t){let r=e.sessionStore.get(e.sessionName),n=ec({session:r,selectorExpression:t});if(!r||!n)return null;let s=await eO(e,r,n);return e$(s)?s:s?{session:r,selector:n,result:s}:null}async function eM(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,iosXctestrunFile:e.req.flags?.iosXctestrunFile,iosXctestDerivedDataPath:e.req.flags?.iosXctestDerivedDataPath,iosXctestEnvDir:e.req.flags?.iosXctestEnvDir}),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 eO(e,t,r){try{return await eM(e,t,r)}catch(e){if(eu(e,{allowElementNotFound:!0}))return null;return{kind:"error",response:{ok:!1,error:h(e)}}}}function e$(e){return null!==e&&"kind"in e&&"error"===e.kind}async function eF(e){try{return{ok:!0,data:await e()}}catch(t){let e=g(t);return o(e.code,e.message,e.details)}}async function eL(e,t,r){var n;let s;if(t.ok)return t;let i=e.sessionStore.get(e.sessionName);if(!i)return t;try{s=await X(i)}catch{return t}return s?o(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{B as assertAndroidPressStayedInApp,U as buildSnapshotSession,T as createDaemonRuntimePolicy,ef as createSelectorCaptureRuntime,eN as dispatchFindReadOnlyViaRuntime,eA as dispatchGetViaRuntime,eR as dispatchIsViaRuntime,eb as dispatchWaitViaRuntime,H as isAndroidEscapeError,eu as isDirectIosSelectorFallbackError,ec as readSimpleIosSelectorTarget,ed as readTextForNode,K as recordIfSession,V as refSnapshotFlagGuardResponse,$ as resolveSessionDevice,F as withSessionlessRunnerCleanup};
|
package/dist/src/selectors.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{findSelectorChainMatch,formatSelectorFailure,isNodeEditable,isNodeVisible,isSelectorToken,parseSelectorChain,
|
|
1
|
+
export{findSelectorChainMatch,formatSelectorFailure,isNodeEditable,isNodeVisible,resolveSelectorChain}from"./9836.js";export{isSelectorToken,parseSelectorChain,tryParseSelectorChain}from"./587.js";
|
package/dist/src/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{formatCliOutput as t}from"./cli-output.js";import{listMcpCommandMetadata as r,isCommandName as e}from"./2948.js";import{readVersion as n}from"./
|
|
1
|
+
import{formatCliOutput as t}from"./cli-output.js";import{listMcpCommandMetadata as r,isCommandName as e}from"./2948.js";import{readVersion as n}from"./1404.js";let i=function(r={}){return{execute:async(n,i)=>{var u;if(!e(n))throw Error(`Unknown command tool: ${n}`);let c=!(u=i)||"object"!=typeof u||Array.isArray(u)?{client:{},outputFormat:"optimized"}:{client:function(t){let r=t.stateDir,e={};if(void 0!==r&&("string"!=typeof r||0===r.length))throw Error("Expected stateDir to be a non-empty string.");return"string"==typeof r&&(e.stateDir=r),e}(u),outputFormat:function(t){if(void 0===t)return"optimized";if("optimized"!==t&&"json"!==t)throw Error('Expected mcpOutputFormat to be "optimized" or "json".');return t}(u.mcpOutputFormat)},p=function(t){if(!t||"object"!=typeof t||Array.isArray(t))return t;let{stateDir:r,mcpOutputFormat:e,...n}=t;return n}(i),f=await o(r,c.client),l=await (r.runCommand??s)(f,n,p);return{isError:!1,structuredContent:l,content:[{type:"text",text:function(r){if("json"===r.outputFormat)return a(r.result);let e=t({name:r.name,input:r.input,result:r.result});return"string"==typeof e?.text?e.text:a(e?.data??r.result)}({name:n,input:p,result:l,outputFormat:c.outputFormat})}]}}}}();async function o(t,r){if(t.createClient)return await t.createClient(r);let{createAgentDeviceClient:e}=await import("./9919.js");return e(r)}async function s(t,r,e){let n=await import("./command-surface.js");return await n.runCommand(t,r,e)}function a(t){return"string"==typeof t?t:JSON.stringify(t,null,2)}async function u(t){if("2.0"!==t.jsonrpc||"string"!=typeof t.method)return f(t.id??null,-32600,"Invalid JSON-RPC request.");if(void 0===t.id)return null;try{var r,e;return r=t.id,e=await c(t.method,t.params),{jsonrpc:"2.0",id:r,result:e}}catch(r){if(r instanceof l)return f(t.id,-32601,r.message);return f(t.id,-32602,r instanceof Error?r.message:String(r))}}async function c(t,e){switch(t){case"initialize":return{protocolVersion:"2025-11-25",capabilities:{tools:{}},serverInfo:{name:"agent-device",version:n()}};case"ping":return{};case"tools/list":return{tools:r().map(t=>{var r;return{name:t.name,description:t.description,inputSchema:{...r=t.inputSchema,properties:{...r.properties,stateDir:{type:"string",description:"Agent-device state directory."},mcpOutputFormat:{type:"string",enum:["optimized","json"],description:"MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately."}}}}})};case"tools/call":return await p(e);default:throw new l(`Unsupported MCP method: ${t}`)}}async function p(t){let r=function(t){if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Expected object parameters.");return t}(t),e=function(t,r){let e=t[r];if("string"!=typeof e||0===e.length)throw Error(`Expected ${r} to be a non-empty string.`);return e}(r,"name");try{return await i.execute(e,r.arguments)}catch(t){return function(t,r=!1){return{isError:r,content:[{type:"text",text:t}]}}(t instanceof Error?t.message:String(t),!0)}}function f(t,r,e){return{jsonrpc:"2.0",id:t,error:{code:r,message:e}}}class l extends Error{}async function m(){let t=function(t={}){let r=t.handlePayload??d,e=t.write??h,n=Promise.resolve();return{push:t=>{var i;let o=Array.isArray(i=t)?1===i.length?i[0]?.id??null:null:i.id??null;n=n.then(async()=>{let n=await r(t);n&&e(n)}).catch(t=>{e({jsonrpc:"2.0",id:o,error:{code:-32603,message:t instanceof Error?t.message:String(t)}})})},idle:async()=>{await n}}}(),r=new g(r=>{t.push(r)});process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{try{r.push(t)}catch(t){h({jsonrpc:"2.0",id:null,error:{code:-32700,message:t instanceof Error?t.message:String(t)}})}}),await new Promise(t=>{process.stdin.on("end",t),process.stdin.on("close",t),process.stdin.resume()}),await t.idle()}function d(t){return Array.isArray(t)?y(t):u(t)}async function y(t){let r=[];for(let n of t){var e;r.push(...(e=await u(n))?[e]:[])}return r.length>0?r:null}class g{buffer="";sink;constructor(t){this.sink=t}push(t){for(this.buffer+=t;;){let t=this.tryReadLineMessage();if(void 0!==t){this.emit(t);continue}break}}tryReadLineMessage(){let t=this.buffer.indexOf("\n");if(-1===t)return;let r=this.buffer.slice(0,t).trim();return this.buffer=this.buffer.slice(t+1),r.length>0?r:void 0}emit(t){let r=JSON.parse(t);Array.isArray(r),this.sink(r)}}function h(t){process.stdout.write(`${JSON.stringify(t)}
|
|
2
2
|
`)}export{m as runAgentDeviceMcpServer};
|