agent-device 0.19.3 → 0.20.1
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 +62 -70
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.1.apk +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.1.apk.sha256 +1 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.1.manifest.json +10 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.1.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.1.apk.sha256 +1 -0
- package/{android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.3.manifest.json → android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.1.manifest.json} +6 -6
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +2 -0
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +5 -0
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +5 -10
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +74 -174
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +113 -19
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +82 -0
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +325 -123
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +2 -2
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +149 -105
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +56 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +73 -0
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +51 -26
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +2 -2
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +2 -107
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +130 -13
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +51 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +24 -0
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +1 -1
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +43 -35
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -1
- package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +16 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +3 -0
- package/dist/src/android-adb.d.ts +1 -1
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-method-overlays.js +1 -0
- package/dist/src/android-input-ownership.js +1 -6
- package/dist/src/android-system-chrome.js +1 -0
- package/dist/src/android.js +1 -1
- package/dist/src/app-lifecycle.js +5 -5
- package/dist/src/app-log-request-scope.js +1 -0
- package/dist/src/app-resolution.js +1 -0
- package/dist/src/apple-multitouch-support.js +1 -0
- package/dist/src/apps.js +5 -5
- package/dist/src/boot-diagnostics.js +2 -0
- package/dist/src/cli-config.js +1 -0
- package/dist/src/cli-help.js +131 -40
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +15 -11
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/compatibility-policy.js +1 -0
- package/dist/src/context.js +1 -0
- package/dist/src/contracts.d.ts +2 -2
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/devices2.js +1 -1
- package/dist/src/devices4.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/helper.js +1 -1
- package/dist/src/index.d.ts +533 -279
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +4 -3
- package/dist/src/install-artifact.js +1 -0
- package/dist/src/install-source.d.ts +5 -1
- package/dist/src/install-source.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.d.ts +230 -0
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -0
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +42 -20
- package/dist/src/internal/png-worker.d.ts +22 -0
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/launch-console.js +1 -0
- package/dist/src/lease-context.js +1 -0
- package/dist/src/lease.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/logcat.js +5 -0
- package/dist/src/method-scope.js +1 -0
- package/dist/src/metro-types.d.ts +52 -0
- package/dist/src/metro.d.ts +3 -3
- package/dist/src/notifications.js +1 -1
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-lock.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-export-quality.js +15 -0
- package/dist/src/register-builtins.js +1 -0
- package/dist/src/registry.js +24 -24
- package/dist/src/remote-config.d.ts +1 -1
- package/dist/src/reporting.js +8 -7
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +2 -0
- package/dist/src/runner-lease.js +1 -0
- package/dist/src/runner-provider.js +1 -1
- package/dist/src/runner-sequence.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +1 -0
- package/dist/src/sdk-android-adb.d.ts +97 -33
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.d.ts +2 -1
- package/dist/src/sdk-batch-runner.js +3 -2
- package/dist/src/sdk-contracts.d.ts +70 -149
- package/dist/src/sdk-contracts.js +1 -1
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +5 -4
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.d.ts +1 -1
- package/dist/src/sdk-remote-config.d.ts +19 -96
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -0
- package/dist/src/selectors.d.ts +12 -3
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-target-evidence.js +1 -0
- package/dist/src/session.js +8 -10
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-diagnostics.js +5 -2
- package/dist/src/snapshot-quality.js +1 -1
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -2
- package/dist/src/tool-provider3.js +1 -0
- package/dist/src/unsupported-interactor.js +1 -0
- package/dist/src/url.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +34 -27
- package/server.json +2 -2
- package/skills/agent-device/SKILL.md +5 -3
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.3.apk +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.3.apk.sha256 +0 -1
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.3.manifest.json +0 -10
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.3.apk +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.3.apk.sha256 +0 -1
- package/dist/src/apple-runner-options.js +0 -1
- package/dist/src/cli-output.js +0 -1
- package/dist/src/client.js +0 -3
- package/dist/src/handler-utils.js +0 -1
- package/dist/src/output-path.js +0 -1
- package/dist/src/points.js +0 -4
- package/dist/src/provider.js +0 -1
- package/dist/src/providers.js +0 -1
- package/dist/src/record-trace-recording.js +0 -23
- package/dist/src/recording-provider.js +0 -1
- package/dist/src/sdk-batch.js +0 -2
- package/dist/src/selectors2.js +0 -1
- package/dist/src/ttl-memo.js +0 -1
- package/dist/src/tv-remote.js +0 -14
- package/dist/src/xml.js +0 -2
- /package/{macos-helper → apple/macos-helper}/Package.swift +0 -0
- /package/{macos-helper → apple/macos-helper}/Sources/AgentDeviceMacOSHelper/AudioProbe.swift +0 -0
- /package/{macos-helper → apple/macos-helper}/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +0 -0
- /package/{macos-helper → apple/macos-helper}/Sources/AgentDeviceMacOSHelper/main.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/xcshareddata/xcschemes/AgentDeviceRunner.xcscheme +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests.entitlements +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerObjCExceptionCatcher.h +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerObjCExceptionCatcher.m +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests.xctestplan +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -0
- /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/RecordingScripts/recording-trim.swift +0 -0
- /package/{src/platforms/linux → linux}/atspi-dump.py +0 -0
package/dist/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e,b as t,u as n,x as r}from"./sdk-contracts.js";import{n as i}from"./client.js";import{t as a}from"./sdk-io.js";export{e as AppError,n as centerOfRect,i as createAgentDeviceClient,a as createLocalArtifactAdapter,t as isAgentDeviceError,r as normalizeAgentDeviceError};
|
|
1
|
+
import{_ as e,b as t,u as n,x as r}from"./sdk-contracts.js";import{n as i}from"./agent-device-client.js";import{t as a}from"./sdk-io.js";export{e as AppError,n as centerOfRect,i as createAgentDeviceClient,a as createLocalArtifactAdapter,t as isAgentDeviceError,r as normalizeAgentDeviceError};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{j as n,u as r}from"./sdk-android-adb.js";import{i,st as a}from"./tv-remote.js";import{t as o}from"./timeouts.js";import{p as s,r as c}from"./android-input-ownership.js";import{r as l}from"./device-input-state.js";import{Et as u,Mt as d}from"./internal/daemon.js";function ee(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=h(t),r={failureReason:t.reason??`text_mismatch`,targetInput:m(t.targetInput),actualInput:m(t.actualInput)};return n?{...r,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??``).length}:{...r,expected:e,actual:t.actual}}function f(e){return e?e.password?!0:p(e.text):!1}function p(e){return e?Array.from(e).every(te):!1}function m(e){if(!e)return null;let t=f(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function te(e){return e===`•`||e===`*`||e===`●`}function h(e){return e.masked===!0||f(e.targetInput)||f(e.actualInput)}async function g(e,t,n,r){let i=[0,150,350],a=null,s=null,c=await ae(e);for(let l of i){l>0&&await o(l);let i=await S(e,t,n,r,c);if(a=i,i.reason===`ime_capture`)return i;s=i.ok?i:null}return s??a??{ok:!1,actual:null,reason:`text_mismatch`,targetInput:null,actualInput:null}}async function _(e,t,n){return y(await u(e),t,n)}function v(e,t,n,r,i={}){let a=C(e,t,n,i);return w(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:T(a,r)??E(a,r)}function y(e,t,n){return C(e,t,n).actualInput?.text??null}function b(e){return 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`}function x(e,t){let n=ee(e,t);return t?.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 S(e,t,n,r,i){return v(await u(e),t,n,r,i)}function C(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of d(e)){let e=ie(a,r);e&&oe(i,e,t,n)}return ce(i)}function w(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function T(e,t){let n=e.actualInput;if(!n||!A(n))return null;let r=n.text??null,i=Array.from(r??``).length,a=Array.from(t).length,o=r!==null&&i>0&&a>0&&i===a;return{ok:o,actual:r,reason:o?void 0:`masked_unverified`,masked:!0,targetInput:e.targetInput,actualInput:n}}function E(e,t){let n=e.actualInput?.text??null;return{ok:ne(n,t),actual:n,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:e.actualInput}}function ne(e,t){if(e===t)return!0;let n=D(e),r=D(t);return!n||!r?!1:!!(n===r||re(n,r))}function D(e){return(e??``).replace(/\s+/g,` `).trim()}function re(e,t){if(e.length!==t.length||e.length===0||e.slice(1)!==t.slice(1))return!1;let n=e[0],r=t[0];return!n||!r?!1:r.toLowerCase()===r&&n===r.toUpperCase()}function ie(e,t){if(!e.rect)return null;let n=e.text??``,r=Math.max(1,e.rect.width*e.rect.height);return{text:n||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:e.password===!0,inputMethodOwned:c({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:k(e.className??``)}}async function ae(e){try{return{activeInputMethodPackage:(await l(e)).inputMethodPackage}}catch(e){return n({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function oe(e,t,n,r){let i=se(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=O(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=O(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=O(e.anyAtPoint,t))}function se(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function O(e,t){return e&&e.area<t.area?e:t}function ce(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function k(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function A(e){return f(e)}var j=e({appSwitcherAndroid:()=>z,backAndroid:()=>F,fillAndroid:()=>U,focusAndroid:()=>H,getAndroidScreenSize:()=>q,homeAndroid:()=>I,longPressAndroid:()=>B,pressAndroid:()=>M,pressAndroidEnter:()=>L,pressAndroidTvRemote:()=>N,readAndroidTextAtPoint:()=>_,rotateAndroid:()=>R,scrollAndroid:()=>G,swipeAndroid:()=>P,typeAndroid:()=>V});async function M(e,t,n){await s(e,[`shell`,`input`,`tap`,String(t),String(n)])}async function N(e,t,n){let r=i(t);await s(e,[`shell`,`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function P(e,t,n,r,i,a=250){await s(e,[`shell`,`input`,`swipe`,String(t),String(n),String(r),String(i),String(a)])}async function F(e){await s(e,[`shell`,`input`,`keyevent`,`4`])}async function I(e){await s(e,[`shell`,`input`,`keyevent`,`3`])}async function L(e){await s(e,[`shell`,`input`,`keyevent`,`ENTER`])}async function R(e,t){let n=le(t);await s(e,[`shell`,`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await s(e,[`shell`,`settings`,`put`,`system`,`user_rotation`,n])}async function z(e){await s(e,[`shell`,`input`,`keyevent`,`187`])}async function B(e,t,n,r=800){await s(e,[`shell`,`input`,`swipe`,String(t),String(n),String(t),String(n),String(r)])}async function V(e,t,n=0){let i=r(e);if(i){await i({action:`type`,text:t,delayMs:n}),$(`type`,`provider-native`,t);return}if(X(t),await K(e,`type`),n>0&&Array.from(t).length>1){await Y(e,{action:`type`,text:t,chunkSize:1,delayMs:n});return}await Y(e,{action:`type`,text:t,chunkSize:J,delayMs:0})}async function H(e,t,n){await M(e,t,n)}async function U(e,t,n,i,a=0){let o=r(e);if(o){await o({action:`fill`,target:{x:t,y:n},text:i,delayMs:a}),$(`fill`,`provider-native`,i);let r=await g(e,t,n,i);if(r.ok)return;W(i,r)}X(i);let s=Array.from(i).length,c=[{clearPadding:12,minClear:8,maxClear:48,chunkSize:a>0?1:J,inputDelayMs:a},{clearPadding:24,minClear:16,maxClear:96,chunkSize:a>0?1:4,inputDelayMs:a>0?a:15}],l=null;for(let r of c){await H(e,t,n),await K(e,`fill`),await me(e,he(s+r.clearPadding,r.minClear,r.maxClear)),await Y(e,{action:`fill`,text:i,chunkSize:r.chunkSize,delayMs:r.inputDelayMs});let a=await g(e,t,n,i);if(l=a,a.ok)return;a.reason===`ime_capture`&&W(i,a)}W(i,l)}function W(e,n){throw new t(`COMMAND_FAILED`,b(n),x(e,n))}async function G(e,t,n){let r=await q(e),i=a({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:r.width,referenceHeight:r.height}),o=n?.durationMs??300;return await s(e,[`shell`,`input`,`swipe`,String(i.x1),String(i.y1),String(i.x2),String(i.y2),String(o)]),{...i,...n?.durationMs===void 0?{}:{durationMs:n.durationMs}}}function le(e){switch(e){case`portrait`:return`0`;case`landscape-left`:return`1`;case`portrait-upside-down`:return`2`;case`landscape-right`:return`3`;default:throw new t(`INVALID_ARGS`,`Unsupported Android rotation: ${e}`)}}async function K(e,r){let i;try{i=await l(e)}catch(e){n({level:`warn`,phase:`android_input_ownership_probe_failed`,data:{action:r,error:e instanceof Error?e.message:String(e)}});return}if(i.inputOwner===`ime`)throw new t(`COMMAND_FAILED`,`KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.`,{failureReason:`ime_capture`,action:r,inputOwner:i.inputOwner,inputType:i.inputType,type:i.type,inputMethodPackage:i.inputMethodPackage,focusedPackage:i.focusedPackage,focusedResourceId:i.focusedResourceId,nextAction:`Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.`})}async function q(e){let n=(await s(e,[`shell`,`wm`,`size`])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new t(`COMMAND_FAILED`,`Unable to read screen size`);return{width:Number(n[1]),height:Number(n[2])}}const J=8;async function Y(e,t){let n=t.text.split(`
|
|
2
|
-
`);for(let[
|
|
3
|
-
|
|
1
|
+
import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{I as n,c as r,j as i,l as a,p as o,s,u as c}from"./sdk-android-adb.js";import{Bn as l,Cn as ee}from"./recording-export-quality.js";import{t as u}from"./timeouts.js";import{r as te}from"./android-input-ownership.js";import{s as d}from"./logcat.js";import{r as f}from"./device-input-state.js";import{s as ne}from"./selector-vocabulary.js";import{Bt as re,D as ie,E as ae,Gt as oe,Ht as se,It as p,Jt as m,Kt as ce,O as h,Ut as g,Vt as le,Wt as _,Yt as ue,qt as de,w as v}from"./internal/daemon.js";function fe(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=he(t),r={failureReason:t.reason??`text_mismatch`,targetInput:b(t.targetInput),actualInput:b(t.actualInput)};return n?{...r,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??``).length}:{...r,expected:e,actual:t.actual}}function y(e){return e?e.password?!0:pe(e.text):!1}function pe(e){return e?Array.from(e).every(me):!1}function b(e){if(!e)return null;let t=y(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function me(e){return e===`•`||e===`*`||e===`●`}function he(e){return e.masked===!0||y(e.targetInput)||y(e.actualInput)}async function x(e,t,n,r){let i=[0,150,350],a=null,o=null,s=await Oe(e);for(let c of i){c>0&&await u(c);let i=await xe(e,t,n,r,s);if(a=i,i.reason===`ime_capture`)return i;o=i.ok?i:null}return o??a??{ok:!1,actual:null,reason:`text_mismatch`,targetInput:null,actualInput:null}}async function ge(e,t,n){return ve(await p(e),t,n)}function _e(e,t,n,r,i={}){let a=S(e,t,n,i);return Se(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:Ce(a,r)??we(a,r)}function ve(e,t,n){return S(e,t,n).actualInput?.text??null}function ye(e){return 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`}function be(e,t){let n=fe(e,t);return t?.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 xe(e,t,n,r,i){return _e(await p(e),t,n,r,i)}function S(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of ue(e)){let e=De(a,r);e&&ke(i,e,t,n)}return je(i)}function Se(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function Ce(e,t){let n=e.actualInput;if(!n||!Ne(n))return null;let r=n.text??null,i=Array.from(r??``).length,a=Array.from(t).length,o=r!==null&&i>0&&a>0&&i===a;return{ok:o,actual:r,reason:o?void 0:`masked_unverified`,masked:!0,targetInput:e.targetInput,actualInput:n}}function we(e,t){let n=e.actualInput?.text??null;return{ok:Te(n,t),actual:n,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:e.actualInput}}function Te(e,t){if(e===t)return!0;let n=C(e),r=C(t);return!n||!r?!1:!!(n===r||Ee(n,r))}function C(e){return(e??``).replace(/\s+/g,` `).trim()}function Ee(e,t){if(e.length!==t.length||e.length===0||e.slice(1)!==t.slice(1))return!1;let n=e[0],r=t[0];return!n||!r?!1:r.toLowerCase()===r&&n===r.toUpperCase()}function De(e,t){if(!e.rect)return null;let n=e.text??``,r=Math.max(1,e.rect.width*e.rect.height);return{text:n||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:e.password===!0,inputMethodOwned:te({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:Me(e.className??``)}}async function Oe(e){try{return{activeInputMethodPackage:(await f(e)).inputMethodPackage}}catch(e){return i({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function ke(e,t,n,r){let i=Ae(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=w(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=w(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=w(e.anyAtPoint,t))}function Ae(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function w(e,t){return e&&e.area<t.area?e:t}function je(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function Me(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function Ne(e){return y(e)}function T(e){if(!Number.isFinite(e.x)||!Number.isFinite(e.y)||!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return e}const E=45e3,D=`ANDROID_TOUCH_HELPER_NO_FINAL_RESULT`,O=`ANDROID_TOUCH_HELPER_REPORTED_FAILURE`;async function Pe(e,t){let r=await A(e),i=Le(t),a=Math.max(45e3,i.durationMs+15e3),o=Buffer.from(JSON.stringify({protocol:`android-touch-plan-v1`,...i})).toString(`base64`),s=await n(`android_touch_helper_gesture`,async()=>{let e=await g({deviceKey:r.deviceKey,action:`gesture`,helper:k(r.artifact),payloadBase64:o,timeoutMs:a});return e?{...M(e),helperTransport:`persistent-session`}:{...await j({adb:r.adb,runner:r.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`gesture`,`-e`,`payloadBase64`,o],timeoutMs:a,readResult:M}),helperTransport:`instrumentation`}},{packageName:r.artifact.manifest.packageName,version:r.artifact.manifest.version});return{backend:`android-helper`,helperVersion:r.artifact.manifest.version,installReason:r.install.reason,...s}}async function Fe(e){let t=await A(e);try{let e=await g({deviceKey:t.deviceKey,action:`viewport`,helper:k(t.artifact),timeoutMs:E});if(e)return N(e)}catch(e){await _(t.deviceKey),i({level:`warn`,phase:`android_touch_helper_viewport_session_fallback`,data:{reason:e instanceof Error?e.message:String(e)}})}return await j({adb:t.adb,runner:t.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`viewport`],timeoutMs:E,readResult:N})}function k(e){return{packageName:e.manifest.packageName,runner:e.manifest.instrumentationRunner,helperVersion:e.manifest.version,helperVersionCode:e.manifest.versionCode,sha256:e.manifest.sha256}}async function A(e){let t=r(e),a=t.snapshotHelperArtifact??await Ie(),o=se(e),s=await n(`android_touch_helper_install`,async()=>await re({adb:t.exec,adbProvider:t,artifact:a,deviceKey:o,timeoutMs:3e4}),{packageName:a.manifest.packageName,versionCode:a.manifest.versionCode});return i({phase:`android_touch_helper_install_decision`,data:s}),s.installed&&await _(o),{adb:t.exec,artifact:a,install:s,deviceKey:o}}async function Ie(){return await le({helperDirName:`snapshot-helper`,manifestFileName:e=>`agent-device-android-snapshot-helper-${e}.manifest.json`,parseManifest:e=>{let t=oe(e);return{...t,assetName:t.assetName??`agent-device-android-snapshot-helper-${t.version}.apk`}},unavailableMessage:`Android touch gestures require the bundled Android automation helper artifact, but it was not found or could not be read`})}function Le(e){return{kind:e.topology===`single`?`swipe`:`transform`,durationMs:e.durationMs,pointers:e.pointers.map(Re)}}function Re(e){return{pointerId:e.pointerId,samples:e.samples.map(({offsetMs:e,point:t})=>({offsetMs:e,x:t.x,y:t.y}))}}async function j(e){let n=await e.adb([`shell`,`am`,`instrument`,`-w`,...e.extraArgs,e.runner],{allowFailure:!0,timeoutMs:e.timeoutMs}),r;try{r=ze(`${n.stdout}\n${n.stderr}`)}catch(e){if(e instanceof t){if(e.code===O)throw new t(`COMMAND_FAILED`,e.message,e.details,e);if(e.code!==D)throw e}throw new t(`COMMAND_FAILED`,n.exitCode===0?`Android automation helper output could not be parsed`:`Android automation helper failed before returning parseable output`,o(n),e)}if(n.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android automation helper failed`,o(n,{helper:r}));return e.readResult(r)}function ze(e){let n=de(e).results.find(e=>e.agentDeviceProtocol===ce);if(!n)throw new t(D,`Android automation helper did not return a final result`);if(n.ok!==`true`)throw new t(O,n.message&&n.message!==`null`?n.message:n.errorType||`Android automation helper returned an error`,{errorType:n.errorType,helper:n});return n}function M(e){return{helperKind:e.kind,helperApiVersion:e.helperApiVersion,injectedEvents:m(e.injectedEvents),elapsedMs:m(e.elapsedMs)}}function N(e){let n=m(e.x),r=m(e.y),i=m(e.width),a=m(e.height);if(n===void 0||r===void 0||i===void 0||a===void 0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return T({x:n,y:r,width:i,height:a})}async function P(e,t){let n=c(e);if(n){let e=t.intent===`longPress`?{...t,viewport:T(await n.gestureViewport())}:t;return{backend:`provider-native-touch`,...await n.touch(e)??{}}}return await Pe(e,t)}async function F(e){let t=c(e);return t?T(await t.gestureViewport()):await Fe(e)}var Be=e({appSwitcherAndroid:()=>V,backAndroid:()=>R,fillAndroid:()=>G,focusAndroid:()=>W,getAndroidScreenSize:()=>Y,homeAndroid:()=>z,longPressAndroid:()=>H,pressAndroid:()=>I,pressAndroidEnter:()=>Ve,pressAndroidTvRemote:()=>L,readAndroidTextAtPoint:()=>ge,scrollAndroid:()=>q,setAndroidOrientation:()=>B,typeAndroid:()=>U});async function I(e,t,n){await d(e,[`shell`,`input`,`tap`,String(t),String(n)])}async function L(e,t,n){let r=ee(t);await d(e,[`shell`,`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function R(e){await d(e,[`shell`,`input`,`keyevent`,`4`])}async function z(e){await d(e,[`shell`,`input`,`keyevent`,`3`])}async function Ve(e){await d(e,[`shell`,`input`,`keyevent`,`ENTER`])}async function B(e,t){let n=We(t);await d(e,[`shell`,`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await d(e,[`shell`,`settings`,`put`,`system`,`user_rotation`,n])}async function V(e){await d(e,[`shell`,`input`,`keyevent`,`187`])}async function H(e,t,n,r=800){let i={x:t,y:n};return await P(e,{topology:`single`,intent:`longPress`,durationMs:r,pointers:[{pointerId:0,samples:[{offsetMs:0,point:i},{offsetMs:r,point:i}]}]})}async function U(e,t,n=0){let r=a(e);if(r){await r({action:`type`,text:t,delayMs:n}),$(`type`,`provider-native`,t);return}if(v(e)){await He(e,t,n);return}if(Q(t),await J(e,`type`),n>0&&Array.from(t).length>1){await Z(e,{action:`type`,text:t,chunkSize:1,delayMs:n});return}await Z(e,{action:`type`,text:t,chunkSize:X,delayMs:0})}async function W(e,t,n){await I(e,t,n)}async function G(e,t,n,r,i=0){let o=a(e);if(o){await o({action:`fill`,target:{x:t,y:n},text:r,delayMs:i}),$(`fill`,`provider-native`,r);let a=await x(e,t,n,r);if(a.ok)return;K(r,a)}if(v(e)){let i=await Ue(e,t,n,r);if(i.ok)return;K(r,i)}Q(r);let s=Array.from(r).length,c=[{clearPadding:12,minClear:8,maxClear:48,chunkSize:i>0?1:X,inputDelayMs:i},{clearPadding:24,minClear:16,maxClear:96,chunkSize:i>0?1:4,inputDelayMs:i>0?i:15}],l=null;for(let i of c){await W(e,t,n),await J(e,`fill`),await Ze(e,Qe(s+i.clearPadding,i.minClear,i.maxClear)),await Z(e,{action:`fill`,text:r,chunkSize:i.chunkSize,delayMs:i.inputDelayMs});let a=await x(e,t,n,r);if(l=a,a.ok)return;a.reason===`ime_capture`&&K(r,a)}K(r,l)}async function He(e,t,n){let r=s(e),i=(await ie()).manifest.packageName,a=t.split(`
|
|
2
|
+
`);for(let[t,o]of a.entries()){let s=n>0?Xe(o,1):[o];for(let[e,o]of s.entries())o&&await h(r,i,o),n>0&&(e+1<s.length||t+1<a.length)&&await u(n);t+1<a.length&&await d(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(`type`,`test-ime`,t)}async function Ue(e,t,n,r){let i=s(e),a=(await ie()).manifest.packageName,o=null;for(let s=0;s<2;s+=1){await W(e,t,n),await ae(i,a),r&&await h(i,a,r);let s=await x(e,t,n,r);if(o=s,s.ok)break}return $(`fill`,`test-ime`,r),o}function K(e,n){throw new t(`COMMAND_FAILED`,ye(n),be(e,n))}async function q(e,t,n){let r=await F(e),i=l({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:r.width,referenceHeight:r.height}),a={...i,referenceWidth:r.x+r.width,referenceHeight:r.y+r.height,x1:r.x+i.x1,y1:r.y+i.y1,x2:r.x+i.x2,y2:r.y+i.y2},o=Math.max(n?.durationMs??300,16),s=await P(e,ne({intent:`pan`,origin:{x:a.x1,y:a.y1},delta:{x:a.x2-a.x1,y:a.y2-a.y1},durationMs:o},r,`android`));return{...a,...n?.durationMs===void 0?{}:{durationMs:o},...s}}function We(e){switch(e){case`portrait`:return`0`;case`landscape-left`:return`1`;case`portrait-upside-down`:return`2`;case`landscape-right`:return`3`;default:throw new t(`INVALID_ARGS`,`Unsupported Android rotation: ${e}`)}}async function J(e,n){let r;try{r=await f(e)}catch(e){i({level:`warn`,phase:`android_input_ownership_probe_failed`,data:{action:n,error:e instanceof Error?e.message:String(e)}});return}if(r.inputOwner===`ime`)throw new t(`COMMAND_FAILED`,`KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.`,{failureReason:`ime_capture`,action:n,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 Y(e){let n=(await d(e,[`shell`,`wm`,`size`])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new t(`COMMAND_FAILED`,`Unable to read screen size`);return{width:Number(n[1]),height:Number(n[2])}}const X=8;async function Z(e,t){let n=t.text.split(`
|
|
3
|
+
`);for(let[r,i]of n.entries()){let a=Xe(i,t.chunkSize);for(let[i,o]of a.entries())await Ge(e,o),t.delayMs>0&&(i+1<a.length||r+1<n.length)&&await u(t.delayMs);r+1<n.length&&await d(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(t.action,`adb-shell`,t.text)}async function Ge(e,t){if(t)try{await d(e,[`shell`,`input`,`text`,qe(t)])}catch(e){throw Je(e)?Ye(t,e):e}}function Q(e){if(!Ke(e))throw Ye(e)}function Ke(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&t!==`
|
|
4
|
+
`&&(e<32||e>126))return!1}return!0}function qe(e){return e.replace(/ /g,`%s`)}function Je(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details?.stderr,r=(typeof n==`string`?n:``).toLowerCase();return!!(r.includes(`exception occurred while executing 'text'`)||r.includes(`nullpointerexception`)&&r.includes(`inputshellcommand.sendtext`))}function Ye(e,n){return new t(`COMMAND_FAILED`,"Android text input requires provider-native text injection or the bundled test IME helper for non-ASCII/control characters; the adb-shell fallback supports ASCII text only. On emulators the test IME activates automatically; on real devices pass `open --test-ime` to enable it (see `agent-device doctor` for the current IME state).",{backend:`adb-shell`,textLength:Array.from(e).length,textPreview:e.slice(0,32)},n instanceof Error?n:void 0)}function Xe(e,t){let n=Math.max(1,Math.floor(t)),r=[],i=Array.from(e);for(let e=0;e<i.length;e+=n)r.push(i.slice(e,e+n).join(``));return r.length>0?r:[``]}function $(e,t,n){i({phase:`android_text_injection`,data:{action:e,backend:t,textLength:Array.from(n).length}})}async function Ze(e,t){let n=Math.max(0,t);await d(e,[`shell`,`input`,`keyevent`,`KEYCODE_MOVE_END`],{allowFailure:!0});for(let t=0;t<n;t+=24){let r=Math.min(24,n-t);await d(e,[`shell`,`input`,`keyevent`,...Array(r).fill(`KEYCODE_DEL`)],{allowFailure:!0})}}function Qe(e,t,n){return Math.max(t,Math.min(n,e))}export{Y as a,H as c,q as d,B as f,F as h,W as i,I as l,P as m,R as n,z as o,U as p,G as r,Be as s,V as t,L as u};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{v as n}from"./sdk-android-adb.js";import{n as r,r as i}from"./install-source2.js";import{it as a}from"./internal/daemon.js";import{promises as o}from"node:fs";import s from"node:os";import c from"node:path";var l=e({prepareIosInstallArtifact:()=>u,readIosBundleInfo:()=>d});async function u(e,n){if(e.kind===`url`&&!r(e.url))throw new t(`INVALID_ARGS`,`iOS install_from_source URL sources are only supported for trusted artifact services such as GitHub Actions and EAS. Use a path source for other hosts.`);let a=await i({source:e,isInstallablePath:(e,t)=>t.isDirectory()&&e.toLowerCase().endsWith(`.app`)||t.isFile()&&e.toLowerCase().endsWith(`.ipa`),installableLabel:`iOS installable (.app or .ipa)`,allowArchiveExtraction:e.kind!==`url`||r(e.url),signal:n?.signal}),o;try{o=await f(a.installablePath,n);let e=o,t=await d(e.installPath);return{archivePath:a.archivePath??(a.installablePath.toLowerCase().endsWith(`.ipa`)?a.installablePath:void 0),installablePath:e.installPath,bundleId:t.bundleId,appName:t.appName,cleanup:async()=>{await e.cleanup(),await a.cleanup()}}}catch(e){try{await o?.cleanup()}finally{await a.cleanup()}throw e}}async function d(e){let t=c.join(e,`Info.plist`),[n,r,i]=await Promise.all([a(t,`CFBundleIdentifier`),a(t,`CFBundleDisplayName`),a(t,`CFBundleName`)]);return{bundleId:n,appName:r??i}}async function f(e,r){if(!e.toLowerCase().endsWith(`.ipa`))return{installPath:e,cleanup:async()=>{}};let i=await o.mkdtemp(c.join(s.tmpdir(),`agent-device-ios-ipa-`)),a=async()=>{await o.rm(i,{recursive:!0,force:!0})};try{await n(`unzip`,[`-q`,e,`-d`,i]);let s=c.join(i,`Payload`),l=(await o.readdir(s,{withFileTypes:!0}).catch(()=>{throw new t(`INVALID_ARGS`,`Invalid IPA: missing Payload directory`)})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(`.app`)).map(e=>({installPath:c.join(s,e.name),bundleName:e.name.replace(/\.app$/i,``)})),u=l[0];if(u!==void 0&&l.length===1)return{installPath:u.installPath,cleanup:a};if(l.length===0)throw new t(`INVALID_ARGS`,`Invalid IPA: expected at least one .app under Payload, found 0`);await p(l);let d=r?.appIdentifierHint?.trim();if(d){let e=m(l,d);if(e)return{installPath:e.installPath,cleanup:a};throw new t(`INVALID_ARGS`,`Invalid IPA: found ${l.length} .app bundles under Payload and none matched "${d}". Available bundles: ${l.map(h).join(`, `)}`)}throw new t(`INVALID_ARGS`,`Invalid IPA: found ${l.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${l.map(h).join(`, `)}`)}catch(e){throw await a(),e}}async function p(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await d(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function m(e,n){let r=n.toLowerCase(),i=e.filter(e=>e.bundleName.toLowerCase()===r);if(i.length===1)return i[0];if(i.length>1)throw new t(`INVALID_ARGS`,`Invalid IPA: multiple app bundles matched "${n}" by name. Use a bundle id hint instead.`);if(n.includes(`.`)){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(t.length===1)return t[0]}}function h(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}export{u as n,l as t};
|
|
@@ -7,7 +7,11 @@ type MaterializeInstallSource = {
|
|
|
7
7
|
kind: 'path';
|
|
8
8
|
path: string;
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* @public Archive extensions accepted by install-source resolution.
|
|
12
|
+
*/
|
|
13
|
+
declare const ARCHIVE_EXTENSIONS: readonly [".zip", ".tar", ".tar.gz", ".tgz"];
|
|
10
14
|
declare function validateDownloadSourceUrl(parsedUrl: URL): Promise<void>;
|
|
11
15
|
declare function isTrustedInstallSourceUrl(sourceUrl: string | URL): boolean;
|
|
12
16
|
//#endregion
|
|
13
|
-
export { type MaterializeInstallSource, isTrustedInstallSourceUrl, validateDownloadSourceUrl };
|
|
17
|
+
export { ARCHIVE_EXTENSIONS, type MaterializeInstallSource, isTrustedInstallSourceUrl, validateDownloadSourceUrl };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{i as e,n as t,t as n}from"./install-source2.js";export{n as ARCHIVE_EXTENSIONS,t as isTrustedInstallSourceUrl,e as validateDownloadSourceUrl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{v as t}from"./sdk-android-adb.js";import{t as n}from"./path-resolution.js";import{createWriteStream as r,promises as i}from"node:fs";import a from"node:os";import o from"node:path";import{pipeline as s}from"node:stream/promises";import{Readable as c}from"node:stream";import l from"node:net";import u from"node:dns/promises";const d=[`.zip`,`.tar`,`.tar.gz`,`.tgz`]
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{v as t}from"./sdk-android-adb.js";import{t as n}from"./path-resolution.js";import{createWriteStream as r,promises as i}from"node:fs";import a from"node:os";import o from"node:path";import{pipeline as s}from"node:stream/promises";import{Readable as c}from"node:stream";import l from"node:net";import u from"node:dns/promises";const d=[`.zip`,`.tar`,`.tar.gz`,`.tgz`],f=Object.freeze([...d]);async function p(e){let t=[];try{let n=await h(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(n.cleanup);let r=await E(n.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:e.allowArchiveExtraction!==!1,registerCleanup:e=>{t.push(e)}});return{archivePath:r.archivePath,installablePath:r.installablePath,cleanup:async()=>{await j(t)}}}catch(e){throw await j(t),e}}function m(e){return n(e)}async function h(e,t){if(e.kind===`path`)return{localPath:m(e.path),cleanup:async()=>{}};let n=await i.mkdtemp(o.join(a.tmpdir(),`agent-device-source-`));try{return{localPath:await g(n,e.url,e.headers,t),cleanup:async()=>{await i.rm(n,{recursive:!0,force:!0})}}}catch(e){throw await i.rm(n,{recursive:!0,force:!0}),e}}async function g(t,n,i,a){let l;try{l=new URL(n)}catch{throw new e(`INVALID_ARGS`,`Invalid source URL: ${n}`)}await _(l);let u=a?.signal;if(u?.aborted)throw new e(`COMMAND_FAILED`,`request canceled`,{reason:`request_canceled`});let d=a?.downloadTimeoutMs??12e4,f=AbortSignal.timeout(d),p=u?AbortSignal.any([u,f]):f;try{let n=await fetch(l,{headers:i,redirect:`follow`,signal:p});if(!n.ok)throw new e(`COMMAND_FAILED`,`Failed to download app source: ${n.status} ${n.statusText}`,{status:n.status,statusText:n.statusText,url:l.toString()});let a=x(n,l),u=o.join(t,a),d=n.body;if(!d)throw new e(`COMMAND_FAILED`,`Download response body was empty`,{url:l.toString()});return await s(c.fromWeb(d),r(u)),u}catch(t){throw u?.aborted?new e(`COMMAND_FAILED`,`request canceled`,{reason:`request_canceled`},t):f.aborted?new e(`COMMAND_FAILED`,`App source download timed out after ${d}ms`,{timeoutMs:d,url:l.toString()},t):t}}async function _(t){if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new e(`INVALID_ARGS`,`Unsupported source URL protocol: ${t.protocol}`);if(S(t.hostname.toLowerCase()))throw new e(`INVALID_ARGS`,`Source URL host is not allowed: ${t.hostname}`,{hint:`Use a public artifact URL.`});if((await u.lookup(t.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>C(e.address)))throw new e(`INVALID_ARGS`,`Source URL host resolved to a private or loopback address: ${t.hostname}`,{hint:`Use a public artifact URL.`})}function v(e){let t=e instanceof URL?e:new URL(e),n=t.hostname.toLowerCase();if(!n)return!1;let r=t.pathname;return y(n,r)||b(n,r)}function y(e,t){return e===`api.github.com`?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(t):e===`github.com`?/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(t):!1}function b(e,t){return e!==`expo.dev`&&!e.endsWith(`.expo.dev`)?!1:/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(t)}function x(e,t){let n=(e.headers.get(`content-disposition`)?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i))?.[1]?.trim();return n?o.basename(n):o.basename(t.pathname)||`downloaded-artifact.bin`}function S(e){return!e||e===`localhost`||e.endsWith(`.localhost`)?!0:C(e)}function C(e){let t=l.isIP(e);return t===4?w(e):t===6?T(e):!1}function w(e){let t=e.split(`.`).map(e=>Number.parseInt(e,10));if(t.length!==4||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let n=t[0],r=t[1];return n===void 0||r===void 0?!1:n===10||n===127||n===169&&r===254||n===172&&r>=16&&r<=31||n===192&&r===168}function T(e){let t=e.toLowerCase();return!!(t===`::1`||t.startsWith(`fc`)||t.startsWith(`fd`)||t.startsWith(`fe80:`))}async function E(t,n){let r=await i.stat(t).catch(()=>null);if(!r)throw new e(`INVALID_ARGS`,`App source not found: ${t}`);if(n.isInstallablePath(t,r))return{archivePath:n.archivePath,installablePath:t};if(r.isFile()&&A(t)){if(!n.allowArchiveExtraction)throw new e(`INVALID_ARGS`,`URL sources must point directly to a ${n.installableLabel}; archive extraction is not allowed`,{path:t});let r=await O(t);return n.registerCleanup(r.cleanup),await E(r.outputPath,{...n,archivePath:n.archivePath??t})}if(r.isDirectory()){let r=await D(t,n.isInstallablePath),i=r[0];if(i!==void 0&&r.length===1)return{archivePath:n.archivePath,installablePath:i};if(r.length>1)throw new e(`INVALID_ARGS`,`Found multiple ${n.installableLabel} candidates under ${t}`,{matches:r});let a=await D(t,(e,t)=>t.isFile()&&A(e)),o=a[0];if(o!==void 0&&a.length===1){if(!n.allowArchiveExtraction)throw new e(`INVALID_ARGS`,`URL sources must point directly to a ${n.installableLabel}; nested archives are not allowed`,{path:o});let t=await O(o);return n.registerCleanup(t.cleanup),await E(t.outputPath,{...n,archivePath:n.archivePath??o})}if(a.length>1)throw new e(`INVALID_ARGS`,`Found multiple nested archives under ${t}; expected one ${n.installableLabel} source`,{matches:a})}throw new e(`INVALID_ARGS`,`Expected ${n.installableLabel} source, but got ${t}`)}async function D(e,t){let n=[],r=[{path:e,depth:0}];for(;r.length>0;){let e=r.shift();if(!e)continue;let a=await i.readdir(e.path,{withFileTypes:!0});a.sort((e,t)=>e.name.localeCompare(t.name));for(let i of a){let a=o.join(e.path,i.name);if(t(a,i)){n.push(a);continue}i.isDirectory()&&e.depth<5&&r.push({path:a,depth:e.depth+1})}}return n}async function O(e){let n=await i.mkdtemp(o.join(a.tmpdir(),`agent-device-archive-`));try{return e.toLowerCase().endsWith(`.zip`)?await k(e,n):e.toLowerCase().endsWith(`.tar.gz`)||e.toLowerCase().endsWith(`.tgz`)?await t(`tar`,[`-xzf`,e,`-C`,n]):await t(`tar`,[`-xf`,e,`-C`,n]),{outputPath:n,cleanup:async()=>{await i.rm(n,{recursive:!0,force:!0})}}}catch(e){throw await i.rm(n,{recursive:!0,force:!0}),e}}async function k(e,n){await t(`unzip`,[`-q`,e,`-d`,n])}function A(e){let t=e.toLowerCase();return d.some(e=>t.endsWith(e))}async function j(e){for(let t of[...e].reverse())await t()}export{_ as i,v as n,p as r,f as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./sdk-android-adb.js";import{t}from"./snapshot-quality.js";import{
|
|
1
|
+
import{j as e}from"./sdk-android-adb.js";import{J as t,X as n,ot as r}from"./snapshot-diagnostics.js";import{t as i}from"./snapshot-quality.js";import{$t as a,Mt as o,_n as s,fn as c,gn as l,jt as u,mn as d,on as f,pn as p}from"./internal/daemon.js";import{a as m}from"./input-actions.js";import{i as h}from"./session-target-evidence.js";function g(e){let{session:t,sessionStore:n,command:r,positionals:i,actionCommand:a=r,retryPositionals:o,flags:f,result:m,responseData:g,recordedTarget:v,actionStartedAt:y,actionFinishedAt:b,androidFreshnessBaseline:x}=e,S=d(f),[C,w]=_({command:r,positionals:i,flags:S,result:m,responseData:g}),T=t.recordSession&&v?h(v):void 0;return n.recordAction(t,{command:r,positionals:i,flags:S??{},result:C,...T?{targetEvidence:T}:{}}),p({session:t,command:r,positionals:o??i,flags:f,preSnapshot:t.snapshot}),l(a)&&s(t,a,x??t.snapshot),c(t,a,o??i,f),u(t,a,i,C,S??{},y,b),{ok:!0,data:w}}function _(e){if(e.command!==`fill`||typeof e.flags?.recordAs!=`string`)return[e.result,e.responseData];let i=r({ts:0,command:`fill`,positionals:e.positionals,flags:e.flags,result:e.result}),a=n(e.flags.recordAs);return[t(e.result,i,a),t(e.responseData,i,a)]}async function v(e){let{session:t,flags:n,sessionStore:r,contextFromFlags:i,captureSnapshotForSession:a}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if(t.device.platform===`android`){let e=await m(t.device),n={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=n),n}let s=o(t.snapshot);if(s)return t.recording&&(t.recording.touchReferenceFrame=s),s;if(!t.recording)return;let c=o(await a(t,n,r,i,{interactiveOnly:!0}));return c&&t.recording&&(t.recording.touchReferenceFrame=c),c}async function y(t){try{return await v(t)}catch(n){e({level:`warn`,phase:`touch_reference_frame_resolve_failed`,data:{platform:t.session.device.platform,error:n instanceof Error?n.message:String(n)}});return}}function b(e){return o({nodes:e,createdAt:0})}async function x(e,t,n,r,o){let s={...t??{},snapshotInteractiveOnly:o.interactiveOnly},c=r(s,e.appBundleId,e.trace?.outPath),{snapshot:l}=await f({device:e.device,session:e,flags:s,outPath:s.out,logPath:c.logPath??``,includeRects:o.includeRects,androidFreshnessMode:o.androidFreshnessMode});return i(l.snapshotQuality)||(a(e,l),n.set(e.name,e)),l}export{g as i,b as n,y as r,x as t};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { O as SnapshotNode, h as ResponseCost } from "./sdk-contracts.js";
|
|
2
|
+
//#region src/contracts/click-button.d.ts
|
|
3
|
+
declare const CLICK_BUTTONS: readonly ['primary', 'secondary', 'middle'];
|
|
4
|
+
type ClickButton = (typeof CLICK_BUTTONS)[number];
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/contracts/interaction.d.ts
|
|
7
|
+
/** The decisive criterion separating a resolveSelectorChain winner from its strongest runner-up (ADR 0012). */
|
|
8
|
+
type DisambiguationTiebreak = 'visible' | 'deepest' | 'smallest-area';
|
|
9
|
+
/**
|
|
10
|
+
* A disambiguation winner or losing alternative. `diagnosticRef` is an opaque,
|
|
11
|
+
* non-`@` token — never a snapshot ref, never issued via `refsGeneration`,
|
|
12
|
+
* never pinnable or usable as an `@ref` target. Strings are UTF-8 truncated
|
|
13
|
+
* to 256 bytes.
|
|
14
|
+
*/
|
|
15
|
+
type ResolutionDiagnosticEntry = {
|
|
16
|
+
diagnosticRef: string;
|
|
17
|
+
role?: string;
|
|
18
|
+
label?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* ADR 0012 decision 2: pre-action disclosure of how the acting path resolved
|
|
22
|
+
* its target, on every press/click/fill/longpress response. Never ref-issuing.
|
|
23
|
+
* `direct-ios`/`not-observed` = the XCTest fast path has no daemon tree to
|
|
24
|
+
* report from; `ref`/`label-fallback` = a stale `@ref` recovered via
|
|
25
|
+
* first-match label lookup, never exact ref provenance; `alternatives` holds
|
|
26
|
+
* at most 5 losing candidates, winner excluded.
|
|
27
|
+
*/
|
|
28
|
+
type ResolutionDisclosure = {
|
|
29
|
+
source: 'runtime';
|
|
30
|
+
phase: 'pre-action';
|
|
31
|
+
kind: 'unique';
|
|
32
|
+
} | {
|
|
33
|
+
source: 'runtime';
|
|
34
|
+
phase: 'pre-action';
|
|
35
|
+
kind: 'disambiguated';
|
|
36
|
+
matchCount: number;
|
|
37
|
+
winnerDiagnostic: ResolutionDiagnosticEntry;
|
|
38
|
+
tiebreak: DisambiguationTiebreak;
|
|
39
|
+
alternatives: ResolutionDiagnosticEntry[];
|
|
40
|
+
} | {
|
|
41
|
+
source: 'ref';
|
|
42
|
+
phase: 'pre-action';
|
|
43
|
+
kind: 'exact';
|
|
44
|
+
} | {
|
|
45
|
+
source: 'ref';
|
|
46
|
+
phase: 'pre-action';
|
|
47
|
+
kind: 'label-fallback';
|
|
48
|
+
} | {
|
|
49
|
+
source: 'direct-ios';
|
|
50
|
+
kind: 'not-observed';
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Opt-in (`--verify`) cheap post-condition evidence for mutating interaction
|
|
54
|
+
* commands (#1047). `digest`/`nodeCount`/`interactiveNodeCount` describe a single
|
|
55
|
+
* interactive-only capture taken right after the action; `changedFromBefore`
|
|
56
|
+
* compares that digest against the pre-action capture the resolution path already
|
|
57
|
+
* held, so no extra device round trip is spent beyond the one verify capture.
|
|
58
|
+
* `changedFromBefore: false` is evidence, not failure — the command still
|
|
59
|
+
* succeeded.
|
|
60
|
+
*/
|
|
61
|
+
type InteractionEvidence = {
|
|
62
|
+
foregroundApp?: string;
|
|
63
|
+
nodeCount: number;
|
|
64
|
+
interactiveNodeCount: number;
|
|
65
|
+
digest: string;
|
|
66
|
+
changedFromBefore: boolean;
|
|
67
|
+
};
|
|
68
|
+
type SettleDiffLine = {
|
|
69
|
+
kind: 'added' | 'removed';
|
|
70
|
+
text: string;
|
|
71
|
+
/**
|
|
72
|
+
* Plain ref body (`e12`) for ADDED lines: minted from the settled tree that
|
|
73
|
+
* became the stored session snapshot, so it is immediately actionable and
|
|
74
|
+
* lets the MCP layer pin it at `refsGeneration`. Removed lines never carry
|
|
75
|
+
* one — their refs name nodes of the replaced tree.
|
|
76
|
+
*/
|
|
77
|
+
ref?: string;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* One still-present, actionable element on the settled tree, surfaced by the
|
|
81
|
+
* unchanged-interactive tail (see `SettleObservation.tail`).
|
|
82
|
+
*/
|
|
83
|
+
type SettleTailEntry = {
|
|
84
|
+
ref: string;
|
|
85
|
+
role: string;
|
|
86
|
+
label?: string;
|
|
87
|
+
};
|
|
88
|
+
type SettleObservation = {
|
|
89
|
+
settled: boolean;
|
|
90
|
+
waitedMs: number;
|
|
91
|
+
captures: number;
|
|
92
|
+
quietMs: number;
|
|
93
|
+
timeoutMs: number;
|
|
94
|
+
/**
|
|
95
|
+
* The session's snapshot generation after the settled tree became the stored
|
|
96
|
+
* snapshot (#1076 versioned refs). Attached by the daemon response layer
|
|
97
|
+
* when `diff` is present: added lines carry refs minted from that tree, so
|
|
98
|
+
* the response is ref-issuing — the MCP layer merges per-ref pins from it
|
|
99
|
+
* exactly like snapshot/find responses.
|
|
100
|
+
*/
|
|
101
|
+
refsGeneration?: number;
|
|
102
|
+
/**
|
|
103
|
+
* Digest response view only: capped added-line refs preserved without the
|
|
104
|
+
* verbose diff line text, so MCP can still pin refs when `diff.lines` is
|
|
105
|
+
* intentionally omitted.
|
|
106
|
+
*/
|
|
107
|
+
refs?: Array<{
|
|
108
|
+
ref: string;
|
|
109
|
+
}>;
|
|
110
|
+
/** Present only for `settled: true` observations that stored the settled tree. */
|
|
111
|
+
diff?: {
|
|
112
|
+
summary: {
|
|
113
|
+
additions: number;
|
|
114
|
+
removals: number;
|
|
115
|
+
unchanged: number;
|
|
116
|
+
};
|
|
117
|
+
lines: SettleDiffLine[];
|
|
118
|
+
/** Present (true) when lines were capped to the response bound. */
|
|
119
|
+
truncated?: boolean;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Unchanged interactive refs tail: benchmarks (July 2026) showed 27% of
|
|
123
|
+
* `--settle` actions were followed by a fallback `snapshot -i` because a
|
|
124
|
+
* change-only diff omits refs for elements that did not change — after a
|
|
125
|
+
* modal dismiss the diff shows only removals, and the next button to press
|
|
126
|
+
* (already on screen, untouched) is absent from the response. `tail` lists
|
|
127
|
+
* the settled tree's remaining uncovered interactive elements (excluding
|
|
128
|
+
* structural application/window chrome and the keyboard window's chrome)
|
|
129
|
+
* so the response stays actionable without that extra round trip. Attached
|
|
130
|
+
* ONLY when `diff` carries zero added-line refs naming a NEW target (the
|
|
131
|
+
* modal-dismiss/toast-only/fill signature) — a diff whose added refs hand
|
|
132
|
+
* the next target already pays its way, so the tail would be pure byte
|
|
133
|
+
* cost. Keyboard-chrome refs and self-echo refs (added lines whose node
|
|
134
|
+
* contains the action point: the acted-on element re-describing itself,
|
|
135
|
+
* e.g. a filled field re-labeled with its new value) do not count as new
|
|
136
|
+
* targets. Refs already present on `diff`'s added lines are excluded.
|
|
137
|
+
* Capped; `tailTruncated` marks when candidates exceeded the cap.
|
|
138
|
+
*/
|
|
139
|
+
tail?: SettleTailEntry[];
|
|
140
|
+
tailTruncated?: true;
|
|
141
|
+
hint?: string;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Public daemon response data shared by press/click/fill/longpress.
|
|
145
|
+
* `buildInteractionResponseData` emits this shape (ADR 0011 Layer 2):
|
|
146
|
+
* `targetKind` discriminates the resolved target, identity fields are FLAT
|
|
147
|
+
* (`ref`, `selector`, `x`, `y`), and per-command extras ride alongside.
|
|
148
|
+
*/
|
|
149
|
+
type TouchResponseDataBase = {
|
|
150
|
+
message?: string;
|
|
151
|
+
warning?: string;
|
|
152
|
+
x?: number;
|
|
153
|
+
y?: number;
|
|
154
|
+
referenceWidth?: number;
|
|
155
|
+
referenceHeight?: number;
|
|
156
|
+
evidence?: InteractionEvidence;
|
|
157
|
+
settle?: SettleObservation;
|
|
158
|
+
resolution?: ResolutionDisclosure;
|
|
159
|
+
cost?: ResponseCost;
|
|
160
|
+
/** Direct iOS Maestro coordinate-fallback signals. */
|
|
161
|
+
maestroNonHittableCoordinateFallbackAllowed?: boolean;
|
|
162
|
+
maestroNonHittableCoordinateFallbackUsed?: boolean;
|
|
163
|
+
maestroFallbackReason?: 'non-hittable-coordinate';
|
|
164
|
+
};
|
|
165
|
+
type TouchResponsePoint = TouchResponseDataBase & {
|
|
166
|
+
targetKind: 'point';
|
|
167
|
+
x: number;
|
|
168
|
+
y: number;
|
|
169
|
+
};
|
|
170
|
+
type TouchResponseRef = TouchResponseDataBase & {
|
|
171
|
+
targetKind: 'ref';
|
|
172
|
+
ref: string;
|
|
173
|
+
refLabel?: string;
|
|
174
|
+
selectorChain?: string[];
|
|
175
|
+
targetHittable?: boolean;
|
|
176
|
+
hint?: string;
|
|
177
|
+
};
|
|
178
|
+
type TouchResponseSelector = TouchResponseDataBase & {
|
|
179
|
+
targetKind: 'selector';
|
|
180
|
+
selector: string;
|
|
181
|
+
selectorChain?: string[];
|
|
182
|
+
refLabel?: string;
|
|
183
|
+
targetHittable?: boolean;
|
|
184
|
+
hint?: string;
|
|
185
|
+
};
|
|
186
|
+
type TouchPressExtras = {
|
|
187
|
+
button?: ClickButton;
|
|
188
|
+
count?: number;
|
|
189
|
+
intervalMs?: number;
|
|
190
|
+
holdMs?: number;
|
|
191
|
+
jitterPx?: number;
|
|
192
|
+
doubleTap?: boolean;
|
|
193
|
+
};
|
|
194
|
+
type PressCommandResponseData = (TouchResponsePoint & TouchPressExtras) | (TouchResponseRef & TouchPressExtras) | (TouchResponseSelector & TouchPressExtras);
|
|
195
|
+
type ClickCommandResponseData = PressCommandResponseData;
|
|
196
|
+
type TouchFillExtras = {
|
|
197
|
+
text: string;
|
|
198
|
+
delayMs?: number;
|
|
199
|
+
};
|
|
200
|
+
type FillCommandResponseData = (TouchResponsePoint & TouchFillExtras) | (TouchResponseRef & TouchFillExtras) | (TouchResponseSelector & TouchFillExtras);
|
|
201
|
+
type TouchLongPressExtras = {
|
|
202
|
+
durationMs?: number;
|
|
203
|
+
gesture: 'longpress';
|
|
204
|
+
};
|
|
205
|
+
type LongPressCommandResponseData = (TouchResponsePoint & TouchLongPressExtras) | (TouchResponseRef & TouchLongPressExtras) | (TouchResponseSelector & TouchLongPressExtras);
|
|
206
|
+
/**
|
|
207
|
+
* Daemon response data for the `find` command. Read-only actions (`exists`,
|
|
208
|
+
* `wait`, `get_text`, `get_attrs`) may issue a pinnable ref with
|
|
209
|
+
* `refsGeneration`; mutating actions (`click`, `fill`, `focus`, `type`) carry
|
|
210
|
+
* `ref` as diagnostic pre-action identity and intentionally omit `refsGeneration`
|
|
211
|
+
* (ADR 0014). The shape is intentionally a flat, optional-field record because
|
|
212
|
+
* the action positional changes which fields are present.
|
|
213
|
+
*/
|
|
214
|
+
type FindCommandResponseData = {
|
|
215
|
+
ref?: string;
|
|
216
|
+
refsGeneration?: number;
|
|
217
|
+
found?: true;
|
|
218
|
+
waitedMs?: number;
|
|
219
|
+
text?: string;
|
|
220
|
+
node?: SnapshotNode;
|
|
221
|
+
locator?: string;
|
|
222
|
+
query?: string;
|
|
223
|
+
x?: number;
|
|
224
|
+
y?: number;
|
|
225
|
+
message?: string;
|
|
226
|
+
settle?: SettleObservation;
|
|
227
|
+
cost?: ResponseCost;
|
|
228
|
+
};
|
|
229
|
+
//#endregion
|
|
230
|
+
export { LongPressCommandResponseData as a, FindCommandResponseData as i, DisambiguationTiebreak as n, PressCommandResponseData as o, FillCommandResponseData as r, ClickButton as s, ClickCommandResponseData as t };
|
package/dist/src/interaction.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{S as e,_ as t,v as n}from"./sdk-contracts.js";import{j as r}from"./sdk-android-adb.js";import{d as i,f as a,h as o,u as s}from"./sdk-batch.js";import{Sn as c,Xn as l,bt as u,xt as d,yt as ee}from"./tv-remote.js";import{c as f,m as p,o as m}from"./sdk-device.js";import{t as h}from"./runtime.js";import{It as g,Lt as _,Nt as v,Pt as y,Qt as b,Tt as x,Xt as S,an as C,in as w,on as T,qt as te,rn as ne,wt as E}from"./internal/daemon.js";import{n as re}from"./provider.js";import{_ as D,c as O,d as ie,f as ae,g as k,h as oe,l as se,m as ce,n as le,o as ue,p as de,r as fe,s as pe,u as me,v as he,y as A}from"./selector-runtime.js";import{i as j,n as M,r as N,t as P}from"./interaction-snapshot.js";const F=new Set(a());function I(e){return R({fields:L(e.command),input:e.input??{},data:e.data,controlledFields:F})}function L(e){let t=o(e);if(!t)throw Error(`Missing response data transform descriptor for ${e}`);return t.fields}function R(e){let t=Object.fromEntries(Object.entries(e.data??{}).filter(([t])=>!e.controlledFields.has(t)));for(let[n,r]of Object.entries(e.fields)){let i=e.input[n]===void 0?r.defaultValue:e.input[n];if(i===void 0||r.omitDefault===!0&&i===r.defaultValue){delete t[n];continue}t[n]=i}return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}const ge=new Set([`currentUptimeMs`,`gestureEndUptimeMs`,`gestureStartUptimeMs`,`sequenceResults`]);function _e(e){if(e)return Object.fromEntries(Object.entries(e).filter(([e])=>!ge.has(e)))}function z(e){let{source:t,referenceFrame:n,extra:r}=e;if(t.kind===`runner-payload`){let e={targetKind:t.targetKind,...r??{}};return{result:B({data:t.data,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e}),responseData:B({data:t.publicData,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e})}}let{result:i}=t,a=ae(i),o={targetKind:i.kind,...a,...ve(i.settle,e.settleRefsGeneration),...r??{}},s=B({data:i.backendResult,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),c=B({data:t.publicData,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),l=ye(`warning`in i?i.warning:void 0,e.staleRefsWarning);return l&&(s.warning=l,c.warning=l),{result:s,responseData:c}}function ve(e,t){return!e?.diff||t===void 0?{}:{settle:{...e,refsGeneration:t}}}function ye(e,t){return t?e?`${e} ${t}`:t:e}function B(e){let{data:t,fallbackX:n,fallbackY:r,referenceFrame:i,extra:a}=e,o=xe(a,n,r)??(typeof t?.message==`string`?t.message:void 0);return be({...t??{},...n===void 0||r===void 0?{}:{x:n,y:r},...i??{},...a??{},...c(o)})}function be(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function xe(e,t,n){let r=V(e,`text`);if(r!==void 0)return`Filled ${Array.from(r).length} chars`;let i=Se(t,n),a=Ce(e);if(a)return Te(a,e??{},i);if(i)return we(e,i)}function V(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}function Se(e,t){return e===void 0||t===void 0?``:` (${e}, ${t})`}function Ce(e){let t=V(e,`ref`);return t===void 0?V(e,`selector`):`@${t}`}function we(e,t){return e?.gesture===`longpress`?`Long pressed${t}`:`Tapped${t}`}function Te(e,t,n){let r=typeof t.button==`string`?t.button:void 0;return t.gesture===`longpress`?`Long pressed ${e}${n}`:r&&r!==`primary`?`Clicked ${r} ${e}${n}`:`Tapped ${e}${n}`}function H(e,t){return!f(e.device)||e.surface!==`desktop`&&e.surface!==`menubar`||e.surface===`menubar`&&(t===`click`||t===`press`)?null:w(`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){let n=e.sessionStore.get(e.sessionName);if(!n)throw new t(`SESSION_NOT_FOUND`,ne);return h({backend:Ee({...e,session:n}),...ue(`interaction commands`,{plural:!0}),sessions:v({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0},setRecord:t=>{t.snapshot&&(_(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function Ee(e){let{req:t,session:n}=e,r=De(n);return{platform:p(n.device),captureSnapshot:async(r,i)=>({snapshot:await e.captureSnapshotForSession(n,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:i?.interactiveOnly===!0,includeRects:i?.includeRects===!0})}),tap:async(r,i)=>W(await S(n.device,`press`,[String(i.x),String(i.y)],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),tapTarget:r?.clickRef?async(e,t)=>(await r.clickRef?.(t.ref),{ref:k(t.ref)}):void 0,fill:async(r,i,a)=>W(await S(n.device,`fill`,[String(i.x),String(i.y),a],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),fillTarget:r?.fillRef?async(e,t,n,i)=>(await r.fillRef?.(t.ref,n,i),{ref:k(t.ref),text:n,delayMs:i?.delayMs??0}):void 0,longPress:async(r,i,a)=>W(await S(n.device,`longpress`,[String(i.x),String(i.y),...a?.durationMs===void 0?[]:[String(a.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),typeText:async(r,i)=>W(await S(n.device,`type`,[i],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))}}function De(e){if(e.device.platform!==`web`)return;let t=re();return t.clickRef||t.fillRef?t:void 0}function W(e){return e&&typeof e==`object`?e:void 0}async function Oe(e){switch(e.req.command){case`press`:return await G(e,`press`);case`click`:return await G(e,`click`);case`longpress`:return await G(e,`longpress`);case`fill`:return await ze(e);default:return null}}async function G(e,t){let{req:n,sessionName:r,sessionStore:i}=e,a=i.get(r);if(!a)return C();let o=t===`click`?`click`:t,s=t===`longpress`?`longpress`:`press`,c=H(a,o);if(c)return c;let l=T(s,a.device);if(l)return l;let f=A(t,n.flags);if(f)return f;let m=d(n.flags),h=ee(m);if(t!==`longpress`&&m!==`primary`){let e=u({commandLabel:o,platform:p(a.device),button:m,count:n.flags?.count,intervalMs:n.flags?.intervalMs,holdMs:n.flags?.holdMs,jitterPx:n.flags?.jitterPx,doubleTap:n.flags?.doubleTap});if(e)return w(e.code,e.message,e.details)}let _=t===`longpress`?ce(n.positionals??[]):oe(n.positionals??[],o);if(!_.ok)return _.response;let v=_.target.kind===`ref`?g({session:a,ref:_.target.ref,mintedGeneration:_.refGeneration}):void 0,y;if(_.target.kind===`ref`){let r=e.refSnapshotFlagGuardResponse(t===`longpress`?`longpress`:`press`,n.flags);if(r)return r;y=await Z(e,a)}let b=Me({session:a,commandLabel:o,target:_.target,flags:n.flags});if(b){let t=await Pe(e,a,b);if(t)return t}let x=t===`longpress`?_.durationMs:void 0;return await X(e,{androidFreshnessBaseline:y,run:async e=>await ke({runtime:e,command:t,target:_.target,sessionName:r,requestId:n.meta?.requestId,clickButton:m,flags:n.flags,durationMs:x}),afterRun:async e=>{a.lease?.leaseProvider||await se(a,ie(_.target,e))},buildPayloads:async r=>{let i=je(r);return await Ae({params:e,session:a,result:r,staleRefsWarning:v,publicData:Y({session:a,command:t===`longpress`?void 0:t,flags:n.flags,data:r.backendResult}),extra:t===`longpress`?{...i===void 0?{}:{durationMs:i},gesture:`longpress`}:h})}})}async function ke(e){let{runtime:t,command:n,target:r,sessionName:i,requestId:a,flags:o}=e,s=D(o);if(n===`longpress`)return await t.interactions.longPress(r,{session:i,requestId:a,durationMs:e.durationMs,settle:s});let c={session:i,requestId:a,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap,verify:o?.verify,settle:s};return n===`click`?await t.interactions.click(r,c):await t.interactions.press(r,c)}async function Ae(e){let{params:t,session:n,result:r,publicData:i,extra:a}=e,o=r.kind===`point`?await N({session:n,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):M(n.snapshot?.nodes??[]);return z({source:{kind:`runtime`,result:r,publicData:i},referenceFrame:o,extra:a,staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:K(n,r)})}function K(e,t){if(t.settle?.diff)return y(e),e.snapshotGeneration}function je(e){return`durationMs`in e?e.durationMs:void 0}function Me(e){let{session:t,commandLabel:n,target:r,flags:a}=e;return n!==`click`||r.kind!==`selector`||Ne(a)||i(n)&&a?.verify===!0||s(n)&&a?.settle===!0?null:q(t,r.selector,a)}function q(e,t,n){let r=O({session:e,selectorExpression:t});return r?{...r,...n?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}function Ne(e){return e?.count!==void 0||e?.intervalMs!==void 0||e?.holdMs!==void 0||e?.jitterPx!==void 0||e?.doubleTap!==void 0||e?.clickButton!==void 0&&e.clickButton!==`primary`}async function Pe(e,t,n){return await J({params:e,session:t,selector:n,command:`press`,positionals:[],extra:{selector:n.raw},fallbackPhase:`ios_direct_selector_tap_fallback`})}async function J(t){let{params:n,session:i,selector:a,command:o,positionals:s,extra:c,fallbackPhase:l}=t,u=Date.now();try{let e=await S(i.device,o,s,n.req.flags?.out,{...n.contextFromFlags(n.req.flags,i.appBundleId,i.trace?.outPath),directElementSelector:a,surface:i.surface})??{},t=Date.now(),r=Le(e),{result:l,responseData:d}=z({source:{kind:`runner-payload`,targetKind:`selector`,data:e,publicData:Y({session:i,command:Fe(n.req.command,o),flags:n.req.flags,data:e}),point:r},referenceFrame:Re(e),extra:{...c,...Ie(a,e)}});return j({session:i,sessionStore:n.sessionStore,command:n.req.command,positionals:n.req.positionals??[],retryPositionals:$(r),flags:n.req.flags,result:l,responseData:d,actionStartedAt:u,actionFinishedAt:t})}catch(t){return pe(t,{delegateSemanticFailures:a.allowNonHittableCoordinateFallback!==!0})?(r({level:`debug`,phase:l,data:{selector:a.raw,error:t instanceof Error?t.message:String(t)}}),null):{ok:!1,error:e(t)}}}function Y(e){let t=m(e.session.device.platform)?_e(e.data):e.data;return e.command?I({command:e.command,input:e.flags,data:t}):t}function Fe(e,t){return e===`click`||e===`press`||e===`fill`?e:t}function Ie(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let n=t.message===b;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:n,...n?{maestroFallbackReason:`non-hittable-coordinate`}:{}}}function Le(e){let t=typeof e.x==`number`?e.x:void 0,n=typeof e.y==`number`?e.y:void 0;return t!==void 0&&n!==void 0?{x:t,y:n}:{x:0,y:0}}function Re(e){return typeof e.referenceWidth==`number`&&typeof e.referenceHeight==`number`?{referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight}:void 0}async function ze(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n);if(i){let e=H(i,`fill`);if(e)return e;let t=T(`fill`,i.device);if(t)return t}if(!i)return C();let a=A(`fill`,t.flags);if(a)return a;let o=de(t.positionals??[]);if(!o.ok)return o.response;let s=await Be(e,i,o.target,o.refGeneration);if(s.response)return s.response;let{staleRefsWarning:c}=s;return await Ve(e,i,o.target,o.text)||await X(e,{run:async e=>await e.interactions.fill(o.target,o.text,{session:n,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs,verify:t.flags?.verify,settle:D(t.flags)}),buildPayloads:e=>He({session:i,result:e,text:o.text,flags:t.flags,staleRefsWarning:c})})}async function Be(e,t,n,r){if(n.kind!==`ref`)return{};let i=g({session:t,ref:n.ref,mintedGeneration:r}),a=e.refSnapshotFlagGuardResponse(`fill`,e.req.flags);return a?{response:a,staleRefsWarning:i}:(await Z(e,t),{staleRefsWarning:i})}async function Ve(e,t,n,r){let i=Ue({session:t,target:n,flags:e.req.flags});return i?await We(e,t,i,r):null}function He(e){let{session:t,result:n}=e,r=n.kind===`point`?void 0:M(t.snapshot?.nodes??[]);return z({source:{kind:`runtime`,result:n,publicData:Y({session:t,command:`fill`,flags:e.flags,data:n.backendResult})},referenceFrame:r,extra:{text:e.text},staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:K(t,n)})}function Ue(e){let{session:t,target:n,flags:r}=e;return n.kind!==`selector`||i(`fill`)&&r?.verify===!0||s(`fill`)&&r?.settle===!0?null:q(t,n.selector,r)}async function We(e,t,n,r){return await J({params:e,session:t,selector:n,command:`fill`,positionals:[r],extra:{selector:n.raw,text:r},fallbackPhase:`ios_direct_selector_fill_fallback`})}async function X(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return C();let i=U(e),a=Date.now();try{let{readiness:n,runtimeResult:o}=await Ge(r,e.req.command,async()=>{let e=await t.run(i);return await t.afterRun?.(e),e}),s=Date.now(),{result:c,responseData:l}=await t.buildPayloads(o);if(n.status===`recovered`){let e=typeof l.warning==`string`?`${l.warning} ${n.warning}`:n.warning;c.warning=e,l.warning=e}return j({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:Ke(e.req.command,o),flags:e.req.flags,result:c,responseData:l,actionStartedAt:a,actionFinishedAt:s,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(e){let t=n(e);if(me(t))throw t;return Q(e)}}async function Ge(e,t,n){if(e.lease?.leaseProvider)return{readiness:{status:`clear`},runtimeResult:await n()};let r=await E({session:e,command:t,phase:`before-command`}),i=await n();return await E({session:e,command:t,phase:`after-command`}),{readiness:r,runtimeResult:i}}async function Z(e,t){if(!te(t))return;let n=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){r({level:`warn`,phase:`android_ref_snapshot_refresh_failed`,data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return n}function Q(t){return{ok:!1,error:e(t)}}function Ke(e,t){if(!(t.kind===`ref`&&!t.node)&&(e===`click`||e===`press`))return t.point?$(t.point):void 0}function $(e){return[String(e.x),String(e.y)]}async function qe(e){let t=await Oe({...e,captureSnapshotForSession:P,refSnapshotFlagGuardResponse:he});if(t)return t;switch(e.req.command){case l.type:return await Je({...e,captureSnapshotForSession:P});case`get`:return await le(e);case`is`:return await fe(e);default:return null}}async function Je(e){let{sessionName:t,sessionStore:n}=e,r=n.get(t);return r?T(l.type,r.device)||await Ye(r)||await Xe(e,r):C()}async function Ye(e){return e.device.platform===`android`&&e.recording&&(await x({session:e})).status===`failed`?w(`COMMAND_FAILED`,`Android system dialog blocked the recording session`):null}async function Xe(t,n){let{req:r,sessionName:i,sessionStore:a}=t,o=(r.positionals??[]).join(` `),s=U(t),l=Date.now();try{let e=await E({session:n,command:r.command,phase:`before-command`}),t=await s.interactions.typeText(o,{session:i,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await E({session:n,command:r.command,phase:`after-command`});let u=Date.now(),d={...t.backendResult??{},text:t.text,delayMs:t.delayMs,...c(t.message??`Typed ${Array.from(t.text).length} chars`)};return e.status===`recovered`&&(d.warning=e.warning),j({session:n,sessionStore:a,command:r.command,positionals:r.positionals??[],flags:r.flags,result:d,responseData:d,actionStartedAt:l,actionFinishedAt:u})}catch(t){return{ok:!1,error:e(t)}}}export{qe as handleInteractionCommands};
|
|
1
|
+
import{S as e,_ as t,v as n}from"./sdk-contracts.js";import{j as r}from"./sdk-android-adb.js";import{D as i,O as a,P as o,k as s}from"./sdk-batch-runner.js";import{An as c,Fn as l,Gt as u,Ln as d,Mn as f,Qn as p,c as m,cr as h,d as g,f as _,g as v,jn as ee,p as y}from"./recording-export-quality.js";import{Z as b}from"./snapshot-diagnostics.js";import{c as te,h as x,o as ne}from"./sdk-device.js";import{t as re}from"./timeouts.js";import{t as ie}from"./runtime.js";import"./selector-vocabulary.js";import{C as ae,c as S,f as oe,i as se,l as C,n as w,o as ce,r as le,s as T}from"./context.js";import{$t as ue,Ft as de,Pt as E,Qt as D,Xt as fe,Zt as pe,an as me,hn as he,in as ge,m as _e,nn as ve,rn as O}from"./internal/daemon.js";import{_ as k,c as ye,d as be,f as xe,g as A,h as Se,l as Ce,m as we,n as Te,o as Ee,p as De,r as Oe,s as ke,u as Ae,v as je,y as j}from"./selector-runtime.js";import{i as M,n as N,r as Me,t as P}from"./interaction-snapshot.js";const Ne=new Set(s());function Pe(e){return Ie({fields:Fe(e.command),input:e.input??{},data:e.data,controlledFields:Ne})}function Fe(e){let t=o(e);if(!t)throw Error(`Missing response data transform descriptor for ${e}`);return t.fields}function Ie(e){let t=Object.fromEntries(Object.entries(e.data??{}).filter(([t])=>!e.controlledFields.has(t)));for(let[n,r]of Object.entries(e.fields)){let i=e.input[n]===void 0?r.defaultValue:e.input[n];if(i===void 0||r.omitDefault===!0&&i===r.defaultValue){delete t[n];continue}t[n]=i}return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}const Le=new Set([`currentUptimeMs`,`gestureEndUptimeMs`,`gestureStartUptimeMs`,`sequenceResults`]);function Re(e){if(e)return Object.fromEntries(Object.entries(e).filter(([e])=>!Le.has(e)))}const ze={source:`direct-ios`,kind:`not-observed`};function F(e){let{source:t,referenceFrame:n,extra:r}=e;if(t.kind===`runner-payload`){let e={targetKind:t.targetKind,...t.maestroFallbackUsed?{}:{resolution:ze},...r??{}};return{result:L({data:t.data,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e}),responseData:L({data:t.publicData,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e})}}let{result:i}=t,a=xe(i),o={targetKind:i.kind,...a,...He(i.settle,e.settleRefsGeneration),...r??{}},s=L({data:i.backendResult,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:{...o,...Ve(i)}}),c=L({data:t.publicData,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),l=Ue(`warning`in i?i.warning:void 0,e.staleRefsWarning);return l&&(s.warning=l,c.warning=l),{result:s,responseData:c,...Be(i)}}function Be(e){let t=I(e)?.node??(`node`in e?e.node:void 0),n=`preActionNodes`in e?e.preActionNodes:void 0;return t&&n?{recordedTarget:{node:t,preActionNodes:n}}:{}}function Ve(e){let t=I(e);return t?{selectorChain:t.selectorChain,refLabel:t.refLabel}:{}}function I(e){return`recordingTarget`in e?e.recordingTarget:void 0}function He(e,t){return!e?.diff||t===void 0?{}:{settle:{...e,refsGeneration:t}}}function Ue(e,t){return t?e?`${e} ${t}`:t:e}function L(e){let{data:t,fallbackX:n,fallbackY:r,referenceFrame:i,extra:a}=e,o=Ge(a,n,r)??(typeof t?.message==`string`?t.message:void 0);return We({...t??{},...n===void 0||r===void 0?{}:{x:n,y:r},...i??{},...a??{},...p(o)})}function We(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function Ge(e,t,n){let r=R(e,`text`);if(r!==void 0)return`Filled ${Array.from(r).length} chars`;let i=Ke(t,n),a=qe(e);if(a)return Ye(a,e??{},i);if(i)return Je(e,i)}function R(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}function Ke(e,t){return e===void 0||t===void 0?``:` (${e}, ${t})`}function qe(e){let t=R(e,`ref`);return t===void 0?R(e,`selector`):`@${t}`}function Je(e,t){return e?.gesture===`longpress`?`Long pressed${t}`:`Tapped${t}`}function Ye(e,t,n){let r=typeof t.button==`string`?t.button:void 0;return t.gesture===`longpress`?`Long pressed ${e}${n}`:r&&r!==`primary`?`Clicked ${r} ${e}${n}`:`Tapped ${e}${n}`}function z(e,t){return!te(e.device)||e.surface!==`desktop`&&e.surface!==`menubar`||e.surface===`menubar`&&(t===`click`||t===`press`)?null:T(`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 B(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new t(`SESSION_NOT_FOUND`,ce);return ie({backend:Xe({...e,session:n}),...Ee(`interaction commands`,{plural:!0}),sessions:fe({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0,omitRefFrameSnapshot:e.req.internal?.findResolvedTarget===!0},setRecord:t=>{t.snapshot&&(ue(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function Xe(e){let{req:t,session:n}=e,r=Ze(n);return{platform:x(n.device),captureSnapshot:async(r,i)=>({snapshot:await e.captureSnapshotForSession(n,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:i?.interactiveOnly===!0,includeRects:i?.includeRects===!0})}),resolveGestureViewport:async()=>e.pairedGestureViewport??await se(n.device,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)),tap:async(r,i)=>(O(n),V(await w(n.device,`press`,[String(i.x),String(i.y)],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))),tapTarget:r?.clickRef?async(e,t)=>(O(n),await r.clickRef?.(t.ref),{ref:A(t.ref)}):void 0,fill:async(r,i,a)=>(O(n),V(await w(n.device,`fill`,[String(i.x),String(i.y),a],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))),fillTarget:r?.fillRef?async(e,t,i,a)=>(O(n),await r.fillRef?.(t.ref,i,a),{ref:A(t.ref),text:i,delayMs:a?.delayMs??0}):void 0,longPress:async(r,i,a)=>(O(n),V(await w(n.device,`longpress`,[String(i.x),String(i.y),...a?.durationMs===void 0?[]:[String(a.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))),performGesture:async(r,i)=>(O(n),V(await le(n.device,i,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))),typeText:async(r,i)=>(O(n),V(await w(n.device,`type`,[i],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))))}}function Ze(e){if(e.device.platform!==`web`)return;let t=_e();return t.clickRef||t.fillRef?t:void 0}function V(e){return e&&typeof e==`object`?e:void 0}function H(e){let t=e.ref.startsWith(`@`)?e.ref.slice(1):e.ref,n=ve({session:e.session,refBody:t,mintedGeneration:e.mintedGeneration});if(n.admitted)return null;let r=me(e.session);return T(`COMMAND_FAILED`,$e(n.reason,e.ref),{reason:n.reason,ref:e.ref,currentGeneration:ge(e.session),scope:r===`all`?`all`:Array.from(r),...e.mintedGeneration===void 0?{}:{mintedGeneration:e.mintedGeneration},hint:e.staleRefsWarning??Qe})}const Qe=`Capture a fresh interactive snapshot (snapshot -i) or use a stable selector, then retry.`;function $e(e,t){switch(e){case`ref_frame_expired`:return`Ref ${t} belongs to an expired ref frame — a device action since the snapshot invalidated it`;case`ref_generation_mismatch`:return`Ref ${t} was minted from a superseded snapshot generation`;case`plain_ref_requires_complete_frame`:return`Ref ${t} needs a complete snapshot — the current frame only authorizes its emitted refs`;case`ref_not_issued`:return`Ref ${t} was not issued by the current ref frame`}}function et(e){let n=e.flags?.recordAs;if(n!==void 0){if(b(n),e.flags?.noRecord)throw new t(`INVALID_ARGS`,`fill --record-as cannot be combined with --no-record because no script step would be published.`);if(!e.session.recordSession&&!e.replayPlanStep)throw new t(`INVALID_ARGS`,`fill --record-as requires an armed script recording. Start a fresh session with open --save-script, then retry the fill.`)}}async function tt(e){switch(e.req.command){case`press`:return await U(e,`press`);case`click`:return await U(e,`click`);case`longpress`:return await U(e,`longpress`);case`fill`:return await pt(e);default:return null}}async function U(e,t){let{req:n,sessionName:r,sessionStore:i}=e,a=i.get(r);if(!a)return S();let o=t===`click`?`click`:t,s=t===`longpress`?`longpress`:`press`,l=z(a,o);if(l)return l;let u=C(s,a.device);if(u)return u;let d=j(t,n.flags);if(d)return d;let p=f(n.flags),m=c(p);if(t!==`longpress`&&p!==`primary`){let e=ee({commandLabel:o,platform:x(a.device),button:p,count:n.flags?.count,intervalMs:n.flags?.intervalMs,holdMs:n.flags?.holdMs,jitterPx:n.flags?.jitterPx,doubleTap:n.flags?.doubleTap});if(e)return T(e.code,e.message,e.details)}let h=t===`longpress`?we(n.positionals??[]):Se(n.positionals??[],o);if(!h.ok)return h.response;let g=h.target.kind===`ref`&&n.internal?.findResolvedTarget!==!0?D({session:a,ref:h.target.ref,mintedGeneration:h.refGeneration}):void 0,_;if(h.target.kind===`ref`){let r=e.refSnapshotFlagGuardResponse(t===`longpress`?`longpress`:`press`,n.flags);if(r)return r;let i=n.internal?.findResolvedTarget?null:H({session:a,ref:h.target.ref,mintedGeneration:h.refGeneration,staleRefsWarning:g});if(i)return i;_=await Y(e,a)}let v=n.internal?.replayTargetGuard,y=v?null:ot({session:a,commandLabel:o,target:h.target,flags:n.flags});if(y){let t=await ct(e,a,y);if(t)return t}let b=t===`longpress`?h.durationMs:void 0;return await J(e,{androidFreshnessBaseline:_,refContext:h.target.kind===`ref`&&n.internal?.findResolvedTarget!==!0?{ref:h.target.ref,mintedGeneration:h.refGeneration,staleRefsWarning:g}:void 0,run:async e=>await nt({runtime:e,command:t,target:h.target,sessionName:r,requestId:n.meta?.requestId,clickButton:p,flags:n.flags,durationMs:b,expectedResolvedTarget:v}),afterRun:async e=>{a.lease?.leaseProvider||await Ce(a,be(h.target,e))},buildPayloads:async r=>{let i=at(r);return await rt({params:e,session:a,result:r,staleRefsWarning:g,publicData:q({session:a,command:t===`longpress`?void 0:t,flags:n.flags,data:r.backendResult}),extra:t===`longpress`?{...i===void 0?{}:{durationMs:i},gesture:`longpress`}:m})}})}async function nt(e){let{runtime:t,command:n,target:r,sessionName:i,requestId:a,flags:o,expectedResolvedTarget:s}=e,c=k(o);if(n===`longpress`)return await t.interactions.longPress(r,{session:i,requestId:a,durationMs:e.durationMs,settle:c,expectedResolvedTarget:s});let l={session:i,requestId:a,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap,verify:o?.verify,settle:c,expectedResolvedTarget:s};return n===`click`?await t.interactions.click(r,l):await t.interactions.press(r,l)}async function rt(e){let{params:t,session:n,result:r,publicData:i,extra:a}=e,o=r.kind===`point`?await Me({session:n,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):N(n.snapshot?.nodes??[]);return F({source:{kind:`runtime`,result:r,publicData:i},referenceFrame:o,extra:a,staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:W(n,r)})}function W(e,t){if(t.settle?.diff)return pe(e,it(t.settle)),e.snapshotGeneration}function it(e){let t=[];for(let n of e.diff?.lines??[])n.ref&&t.push(n.ref);for(let n of e.refs??[])t.push(n.ref);for(let n of e.tail??[])t.push(n.ref);return t}function at(e){return`durationMs`in e?e.durationMs:void 0}function ot(e){let{session:t,commandLabel:n,target:r,flags:o}=e;return n!==`click`||r.kind!==`selector`||t.recordSession||st(o)||a(n)&&o?.verify===!0||i(n)&&o?.settle===!0?null:G(t,r.selector,o)}function G(e,t,n){let r=ye({session:e,selectorExpression:t});return r?{...r,...n?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{},...n?.maestro?.expectedTapPoint?{expectedPoint:n.maestro.expectedTapPoint}:{}}:null}function st(e){return e?.count!==void 0||e?.intervalMs!==void 0||e?.holdMs!==void 0||e?.jitterPx!==void 0||e?.doubleTap!==void 0||e?.clickButton!==void 0&&e.clickButton!==`primary`}async function ct(e,t,n){return await K({params:e,session:t,selector:n,command:`press`,positionals:[],extra:{selector:n.raw},fallbackPhase:`ios_direct_selector_tap_fallback`})}async function K(t){let{params:n,session:i,selector:a,command:o,positionals:s,extra:c,fallbackPhase:l}=t,u=Date.now();O(i);try{let e=await w(i.device,o,s,n.req.flags?.out,{...n.contextFromFlags(n.req.flags,i.appBundleId,i.trace?.outPath),directElementSelector:a,surface:i.surface})??{},t=Date.now(),r=dt(e),l=q({session:i,command:lt(n.req.command,o),flags:n.req.flags,data:e}),d=ut(a,e),{result:f,responseData:p}=F({source:{kind:`runner-payload`,targetKind:`selector`,data:e,publicData:l,point:r,maestroFallbackUsed:d.maestroNonHittableCoordinateFallbackUsed===!0},referenceFrame:ft(e),extra:{...c,...d}});return M({session:i,sessionStore:n.sessionStore,command:n.req.command,positionals:n.req.positionals??[],retryPositionals:X(r),flags:n.req.flags,result:f,responseData:p,actionStartedAt:u,actionFinishedAt:t})}catch(t){return ke(t,{delegateSemanticFailures:a.allowNonHittableCoordinateFallback!==!0})?(r({level:`debug`,phase:l,data:{selector:a.raw,error:t instanceof Error?t.message:String(t)}}),null):{ok:!1,error:e(t)}}}function q(e){let t=ne(e.session.device.platform)?Re(e.data):e.data;return e.command?Pe({command:e.command,input:e.flags,data:t}):t}function lt(e,t){return e===`click`||e===`press`||e===`fill`?e:t}function ut(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let n=t.maestroNonHittableCoordinateFallbackUsed===!0;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:n,...n?{maestroFallbackReason:`non-hittable-coordinate`}:{}}}function dt(e){let t=typeof e.x==`number`?e.x:void 0,n=typeof e.y==`number`?e.y:void 0;return t!==void 0&&n!==void 0?{x:t,y:n}:{x:0,y:0}}function ft(e){return typeof e.referenceWidth==`number`&&typeof e.referenceHeight==`number`?{referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight}:void 0}async function pt(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n);if(i){let e=z(i,`fill`);if(e)return e;let t=C(`fill`,i.device);if(t)return t}if(!i)return S();et({session:i,flags:t.flags,replayPlanStep:t.internal?.replayPlanStep===!0});let a=j(`fill`,t.flags);if(a)return a;let o=De(t.positionals??[]);if(!o.ok)return o.response;let s=await mt(e,i,o.target,o.refGeneration);if(s.response)return s.response;let{staleRefsWarning:c}=s,l=t.internal?.replayTargetGuard;return(l?null:await ht(e,i,o.target,o.text))||await J(e,{refContext:o.target.kind===`ref`&&t.internal?.findResolvedTarget!==!0?{ref:o.target.ref,mintedGeneration:o.refGeneration,staleRefsWarning:c}:void 0,run:async e=>await e.interactions.fill(o.target,o.text,{session:n,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs,verify:t.flags?.verify,settle:k(t.flags),expectedResolvedTarget:l}),buildPayloads:e=>gt({session:i,result:e,text:o.text,flags:t.flags,staleRefsWarning:c})})}async function mt(e,t,n,r){if(n.kind!==`ref`)return{};let i=e.req.internal?.findResolvedTarget===!0?void 0:D({session:t,ref:n.ref,mintedGeneration:r}),a=e.refSnapshotFlagGuardResponse(`fill`,e.req.flags);if(a)return{response:a,staleRefsWarning:i};let o=e.req.internal?.findResolvedTarget?null:H({session:t,ref:n.ref,mintedGeneration:r,staleRefsWarning:i});return o?{response:o,staleRefsWarning:i}:(await Y(e,t),{staleRefsWarning:i})}async function ht(e,t,n,r){let i=_t({session:t,target:n,flags:e.req.flags});return i?await vt(e,t,i,r):null}function gt(e){let{session:t,result:n}=e,r=n.kind===`point`?void 0:N(t.snapshot?.nodes??[]);return F({source:{kind:`runtime`,result:n,publicData:q({session:t,command:`fill`,flags:e.flags,data:n.backendResult})},referenceFrame:r,extra:{text:e.text},staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:W(t,n)})}function _t(e){let{session:t,target:n,flags:r}=e;return n.kind!==`selector`||t.recordSession||a(`fill`)&&r?.verify===!0||i(`fill`)&&r?.settle===!0?null:G(t,n.selector,r)}async function vt(e,t,n,r){return await K({params:e,session:t,selector:n,command:`fill`,positionals:[r],extra:{selector:n.raw,text:r},fallbackPhase:`ios_direct_selector_fill_fallback`})}async function J(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return S();let i=B(e),a=Date.now();try{let n=await yt(r,e.req.command,{refContext:t.refContext},async()=>{let e=await t.run(i);return await t.afterRun?.(e),e});if(n.aborted)return n.response;let{readiness:o,runtimeResult:s}=n,c=Date.now(),{result:l,responseData:u,recordedTarget:d}=await t.buildPayloads(s);if(o.status===`recovered`){let e=typeof u.warning==`string`?`${u.warning} ${o.warning}`:o.warning;l.warning=e,u.warning=e}return M({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:xt(e.req.command,s),flags:e.req.flags,result:l,responseData:u,recordedTarget:d,actionStartedAt:a,actionFinishedAt:c,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(e){let t=n(e);if(Ae(t))throw t;return bt(e)}}async function yt(e,t,n,r){if(e.lease?.leaseProvider)return{aborted:!1,readiness:{status:`clear`},runtimeResult:await r()};let i=await E({session:e,command:t,phase:`before-command`});if(n.refContext&&i.status===`recovered`){let t=H({session:e,ref:n.refContext.ref,mintedGeneration:n.refContext.mintedGeneration,staleRefsWarning:n.refContext.staleRefsWarning});if(t)return{aborted:!0,response:t}}let a=await r();return await E({session:e,command:t,phase:`after-command`}),{aborted:!1,readiness:i,runtimeResult:a}}async function Y(e,t){if(!he(t))return;let n=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){r({level:`warn`,phase:`android_ref_snapshot_refresh_failed`,data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return n}function bt(t){return{ok:!1,error:e(t)}}function xt(e,t){if(!(t.kind===`ref`&&!t.node)&&(e===`click`||e===`press`))return t.point?X(t.point):void 0}function X(e){return[String(e.x),String(e.y)]}async function St(e){return await Q(e,`gesture`,async t=>{let n=v(e.req.input),r=_(n);r.gesture.intent===`pan`&&e.req.internal?.gestureExecutionProfile&&(r.gesture.executionProfile=e.req.internal.gestureExecutionProfile),oe(r.gesture,t.device);let i=await Z(e).interactions.gesture({session:e.sessionName,requestId:e.req.meta?.requestId,gesture:r.gesture});return{positionals:g(n),flags:jt(n,e.req.flags),responseData:$(i,{executionProfile:wt(r.gesture)}),...n.kind===`pinch`?{recordingResultExtra:{scale:n.scale}}:{}}})}async function Ct(e){return await Q(e,`swipe`,async t=>{let n=Tt(e.req.input);oe(y(n).gesture,t.device);let r=n.count??1,i=n.pauseMs??0,a=n.pattern??`one-way`,o=await kt(Z(e),e,n,r,i,a);return{positionals:Ot(n),flags:e.req.flags,responseData:$(o,{from:n.from,to:n.to,x1:n.from.x,y1:n.from.y,x2:n.to.x,y2:n.to.y,effectiveDurationMs:o.durationMs,timingMode:`direct`,executionProfile:`endpoint-hold`,count:r,pauseMs:i,pattern:a})}})}function Z(e){return B({...e,pairedGestureViewport:e.req.internal?.gestureViewport})}async function Q(t,n,r){let i=t.sessionStore.get(t.sessionName);if(!i)return S();let a=Date.now();try{let e=ae(i.device),o=e?{status:`clear`}:await E({session:i,command:n,phase:`before-command`}),s=await r(i);e||await E({session:i,command:n,phase:`after-command`});let c={...s.responseData};return o.status===`recovered`&&(c.warning=`${typeof c.warning==`string`?`${c.warning} `:``}${o.warning}`),M({session:i,sessionStore:t.sessionStore,command:n,actionCommand:n,positionals:s.positionals,flags:s.flags,result:{...c,...s.recordingResultExtra??{}},responseData:c,actionStartedAt:a,actionFinishedAt:Date.now()})}catch(t){return{ok:!1,error:e(t)}}}function wt(e){if(e.intent===`fling`)return`endpoint-hold`;if(e.intent===`pan`)return e.executionProfile??`timed-pan`}function $(e,t={}){let n=typeof t.executionProfile==`string`?t.executionProfile:void 0;return{kind:e.kind,durationMs:e.durationMs,pointerCount:e.pointerCount,from:e.from,to:e.to,...e.backendResult??{},...t,...n?{timing:{executionProfile:n,gestureDurationMs:e.durationMs}}:{},message:e.message}}function Tt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`swipe requires structured object input`);m(e);let n=e,r=n.pattern;if(r!==void 0&&r!==`one-way`&&r!==`ping-pong`)throw new t(`INVALID_ARGS`,`swipe pattern must be one-way or ping-pong`);let i={from:Dt(n.from,`swipe from`),to:Dt(n.to,`swipe to`),count:u(n,`count`,{min:1,max:200}),pauseMs:u(n,`pauseMs`,{min:0,max:l}),pattern:r};return Et(i),i}function Et(e){let n=e.count??1,r=e.pauseMs??0,i=n*100+Math.max(0,n-1)*r;if(!(i<=6e4))throw new t(`INVALID_ARGS`,`Swipe series must fit within ${d}ms.`,{count:n,pauseMs:r,gestureDurationMs:100,scheduledDurationMs:i,hint:`Reduce --count or --pause-ms.`})}function Dt(e,n){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`${n} must be a point`);let r=e;if(typeof r.x!=`number`||!Number.isFinite(r.x))throw new t(`INVALID_ARGS`,`${n} x must be finite`);if(typeof r.y!=`number`||!Number.isFinite(r.y))throw new t(`INVALID_ARGS`,`${n} y must be finite`);return{x:r.x,y:r.y}}function Ot(e){return[String(e.from.x),String(e.from.y),String(e.to.x),String(e.to.y)]}async function kt(e,t,n,r,i,a){let o;for(let s=0;s<r;s+=1){let c=y(At(n,a,s));o=await e.interactions.gesture({session:t.sessionName,requestId:t.req.meta?.requestId,gesture:c.gesture}),i>0&&s+1<r&&await re(i)}if(!o)throw Error(`Swipe orchestration did not execute a gesture.`);return o}function At(e,t,n){return t===`ping-pong`&&n%2==1?{...e,from:e.to,to:e.from}:e}function jt(e,t){return e.kind!==`pan`||e.pointerCount===void 0?t:{...t,pointerCount:e.pointerCount}}async function Mt(e){let t=await tt({...e,captureSnapshotForSession:P,refSnapshotFlagGuardResponse:je});if(t)return t;switch(e.req.command){case h.gesture:return await St({...e,captureSnapshotForSession:P});case h.swipe:return await Ct({...e,captureSnapshotForSession:P});case h.type:return await Nt({...e,captureSnapshotForSession:P});case`get`:return await Te(e);case`is`:return await Oe(e);default:return null}}async function Nt(e){let{sessionName:t,sessionStore:n}=e,r=n.get(t);return r?C(h.type,r.device)||await Pt(r)||await Ft(e,r):S()}async function Pt(e){return e.device.platform===`android`&&e.recording&&(await de({session:e})).status===`failed`?T(`COMMAND_FAILED`,`Android system dialog blocked the recording session`):null}async function Ft(t,n){let{req:r,sessionName:i,sessionStore:a}=t,o=(r.positionals??[]).join(` `),s=B(t),c=Date.now();try{let e=await E({session:n,command:r.command,phase:`before-command`}),t=await s.interactions.typeText(o,{session:i,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await E({session:n,command:r.command,phase:`after-command`});let l=Date.now(),u={...t.backendResult??{},text:t.text,delayMs:t.delayMs,...p(t.message??`Typed ${Array.from(t.text).length} chars`)};return e.status===`recovered`&&(u.warning=e.warning),M({session:n,sessionStore:a,command:r.command,positionals:r.positionals??[],flags:r.flags,result:u,responseData:u,actionStartedAt:c,actionFinishedAt:l})}catch(t){return{ok:!1,error:e(t)}}}export{Mt as handleInteractionCommands};
|
package/dist/src/interactor.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
2
|
-
`?void 0:`append`,appBundleId:t.appBundleId},n)},fillElementSelector:async(r,i,a)=>await
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{I as t}from"./sdk-android-adb.js";import{Bn as n,Dn as r,Rn as i,it as a,st as o,wn as s}from"./recording-export-quality.js";import{c,f as l,s as u}from"./sdk-device.js";import{r as d}from"./snapshot-quality.js";import{c as f}from"./selector-vocabulary.js";import{t as p}from"./apple-multitouch-support.js";import{o as m}from"./helper.js";import{a as h}from"./runner-client.js";import{i as g}from"./runner-provider.js";import{t as _}from"./method-scope.js";import{a as v,c as y,i as b,l as x,n as S,o as C,r as w,s as T}from"./apps.js";import{n as E,t as D}from"./runner-sequence.js";function O(e,t,n){return{command:`remotePress`,remoteButton:e,...n===void 0?{}:{durationMs:n},...t===void 0?{}:{appBundleId:t}}}function k(e,t,r,i={includeDuration:!0}){let a=j(e.referenceWidth),o=j(e.referenceHeight);if(a===void 0||o===void 0)return M(e,{amount:r?.amount});let s=n({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a,referenceHeight:o});return M(e,{amount:r?.amount,pixels:s.pixels,durationMs:i?.includeDuration?r?.durationMs:void 0,preferProvidedPixels:!0})}function A(e,t={includeDuration:!0}){return{...e?.amount===void 0?{}:{amount:e.amount},...e?.pixels===void 0?{}:{pixels:e.pixels},...t?.includeDuration&&e?.durationMs!==void 0?{durationMs:e.durationMs}:{}}}function j(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function M(e,t){let{x1:n,y1:r,x2:i,y2:a}=P(e),o=j(e.referenceWidth),s=j(e.referenceHeight),c=N(t,n!==void 0&&i!==void 0?Math.round(Math.abs(i-n)):void 0,r!==void 0&&a!==void 0?Math.round(Math.abs(a-r)):void 0);return{...n===void 0?{}:{x1:n},...r===void 0?{}:{y1:r},...i===void 0?{}:{x2:i},...a===void 0?{}:{y2:a},...o===void 0?{}:{referenceWidth:o},...s===void 0?{}:{referenceHeight:s},...t?.amount===void 0?{}:{amount:t.amount},...c===void 0?{}:{pixels:c},...t?.durationMs===void 0?{}:{durationMs:t.durationMs}}}function N(e,t,n){if(e?.preferProvidedPixels&&e.pixels!==void 0)return e.pixels;if(t!==void 0&&t>0)return t;if(n!==void 0&&n>0)return n}function P(e){let t=j(e.x),n=j(e.y),r=j(e.x2),i=j(e.y2);return{...t===void 0?{}:{x1:t},...n===void 0?{}:{y1:n},...r===void 0?{}:{x2:r},...i===void 0?{}:{y2:i}}}async function F(e,t,n,r,i,a){return k(await e(t,{command:`desktopScroll`,direction:i,...A(a,{includeDuration:!0}),appBundleId:n.appBundleId},r),i,a,{includeDuration:!0})}function I(e){return e===`system`?`backSystem`:`backInApp`}function L(e,t){let n={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId,iosXctestrunFile:t.iosXctestrunFile,iosXctestDerivedDataPath:t.iosXctestDerivedDataPath,iosXctestEnvDir:t.iosXctestEnvDir,runnerLeaseContext:t.runnerLeaseContext};return{runnerOpts:n,overrides:{tap:async(r,i)=>await h(e,H(e,t,r,i),n),tapElementSelector:async r=>await h(e,{command:`tap`,selectorKey:r.key,selectorValue:r.value,allowNonHittableCoordinateFallback:r.allowNonHittableCoordinateFallback,...r.expectedPoint?{x:r.expectedPoint.x,y:r.expectedPoint.y}:{},appBundleId:t.appBundleId},n),doubleTap:async(r,i)=>{let a=await h(e,D([{kind:`doubleTap`,x:r,y:i}],t.appBundleId),n);return E(a),a},longPress:async(r,i,a)=>await h(e,{command:`longPress`,x:r,y:i,durationMs:a,appBundleId:t.appBundleId},n),focus:async(r,i)=>await h(e,H(e,t,r,i),n),type:async(r,i)=>{await h(e,{command:`type`,text:r,delayMs:i,textEntryMode:r===`
|
|
2
|
+
`?void 0:`append`,appBundleId:t.appBundleId},n)},fillElementSelector:async(r,i,a)=>await h(e,{command:`type`,selectorKey:r.key,selectorValue:r.value,allowNonHittableCoordinateFallback:r.allowNonHittableCoordinateFallback,text:i,delayMs:a,textEntryMode:`replace`,appBundleId:t.appBundleId},n),fill:async(r,i,a,o)=>await h(e,{command:`type`,x:r,y:i,text:a,delayMs:o,textEntryMode:`replace`,appBundleId:t.appBundleId},n),scroll:async(r,i)=>await W(h,e,t,n,r,i),performGesture:async r=>await B(e,t,n,r),gestureViewport:async()=>R(await h(e,{command:`gestureViewport`,appBundleId:t.appBundleId},n))}}}function R(t){let n=z(t.x),r=z(t.y),i=z(t.x2),a=z(t.y2);if(n===void 0||r===void 0||i===void 0||a===void 0||i<=0||a<=0)throw new e(`COMMAND_FAILED`,`Apple runner returned an invalid gesture viewport`);return{x:n,y:r,width:i,height:a}}function z(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}async function B(e,t,n,r){if(r.topology===`two`&&p(e,r.intent),r.topology===`single`&&c(e)){let{start:i,end:a}=f(r);return await h(e,{command:`drag`,x:i.x,y:i.y,x2:a.x,y2:a.y,durationMs:r.durationMs,appBundleId:t.appBundleId},n)}if(r.topology===`single`&&l(e)){let{start:i,end:a}=f(r);return await h(e,{command:`swipe`,direction:V(i,a),appBundleId:t.appBundleId},n)}return await h(e,{command:`gesture`,gesturePlan:r,appBundleId:t.appBundleId},n)}function V(e,t){let n=t.x-e.x,r=t.y-e.y;return Math.abs(n)>=Math.abs(r)?n>=0?`right`:`left`:r>=0?`down`:`up`}function H(e,t,n,r){return{command:`tap`,x:n,y:r,...U(e)?{synthesized:!0}:{},appBundleId:t.appBundleId}}function U(e){return u(e)&&!l(e)}async function W(e,t,n,r,s,u){return o(u?.durationMs,{invalidMessage:`scroll durationMs must be a non-negative integer at most ${a}`}),l(t)?M(await e(t,O(s,n.appBundleId,u?.durationMs),r),{amount:u?.amount,durationMs:u?.durationMs}):(i(u??{}),c(t)?await F(e,t,n,r,s,u):k(await e(t,{command:`scroll`,direction:s,...A(u),appBundleId:n.appBundleId},r),s,u))}function G(n,r,i){if(n.appleOs===`watchos`)throw new e(`UNSUPPORTED_PLATFORM`,`watchOS is not supported: XCUITest cannot drive watchOS UI, so this device has no runner backend.`);let{overrides:a,runnerOpts:o}=L(n,r),c={open:(e,t)=>C(n,e,{appBundleId:t?.appBundleId,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,terminateRunningApp:t?.terminateRunningApp,url:t?.url,runnerOptions:o}),openDevice:()=>T(n),close:e=>v(n,e,o),screenshot:(e,t)=>Y(n,e,t,o),snapshot:async r=>{let i=Z(await t(`snapshot_capture`,async()=>await h(n,{command:`snapshot`,appBundleId:r?.appBundleId,interactiveOnly:r?.interactiveOnly,depth:r?.depth,scope:r?.scope,raw:r?.raw},o),{backend:`xctest`})),a=i.nodes??[];if(a.length===0&&n.kind===`simulator`)throw new e(`COMMAND_FAILED`,`XCTest snapshot returned 0 nodes on iOS simulator.`);return{nodes:a,truncated:i.truncated??!1,backend:`xctest`,...i.quality?{quality:i.quality}:{},...!i.quality&&i.message?{warnings:[i.message]}:{}}},back:async e=>{if(l(n)){await h(n,O(`menu`,r.appBundleId),o);return}await h(n,{command:I(e),appBundleId:r.appBundleId},o)},home:async()=>{if(l(n)){await h(n,O(`home`,r.appBundleId),o);return}await h(n,{command:`home`,appBundleId:r.appBundleId},o)},setOrientation:async t=>{let i=K(await h(n,{command:`rotate`,orientation:t,appBundleId:r.appBundleId},o));if(i!==t)throw new e(`COMMAND_FAILED`,`iOS runner observed ${i} after requesting ${t}`,{requestedOrientation:t,observedOrientation:i});return{orientation:i}},appSwitcher:async()=>{await h(n,{command:`appSwitcher`,appBundleId:r.appBundleId},o)},tvRemote:async(e,t)=>{await h(n,O(s(e),r.appBundleId,t),o)},readClipboard:()=>w(n),writeClipboard:e=>b(n,e),setSetting:(e,t,r,i)=>S(n,e,t,r,i),...a};return i?q(n,r,c,i):c}function K(t){let n=t.orientation;if(typeof n==`string`&&r.includes(n))return n;throw new e(`COMMAND_FAILED`,`iOS runner returned an invalid orientation result`,{orientation:n})}function q(e,t,n,r){return _({...n,open:async()=>J(`open`),openDevice:async()=>J(`openDevice`),close:async()=>J(`close`),screenshot:async()=>J(`screenshot`),readClipboard:async()=>J(`readClipboard`),writeClipboard:async()=>J(`writeClipboard`),setSetting:async()=>J(`setSetting`)},n=>g(r,{deviceId:e.id,requestId:t.requestId},n))}function J(t){throw new e(`UNSUPPORTED_OPERATION`,`${t} uses local Apple tooling (simctl/devicectl), which an injected runner transport cannot reach; the provider session must supply its own ${t} implementation.`)}async function Y(e,t,n={},r){if(X(e,n.surface)){await m(t,{surface:n.surface,fullscreen:n.fullscreen});return}if(n.captureBackend===`runner`){await y(e,t,n.appBundleId,n.fullscreen,r);return}await x(e,t,{appBundleId:n.appBundleId,pixelDensity:n.pixelDensity,fullscreen:n.fullscreen,runnerOptions:r,normalizeStatusBar:n.normalizeStatusBar,skipIosSimulatorBootCheck:n.skipIosSimulatorBootCheck})}function X(e,t){return c(e)&&t!==void 0&&t!==`app`}function Z(e){return{nodes:Array.isArray(e.nodes)?e.nodes:void 0,truncated:typeof e.truncated==`boolean`?e.truncated:void 0,quality:d(e.snapshotQuality),message:typeof e.message==`string`&&e.message.trim().length>0?e.message:void 0}}export{G as createAppleInteractor};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{h as t}from"./sdk-android-adb.js";import{Tn as n}from"./recording-export-quality.js";import{d as r}from"./logcat.js";import{t as i}from"./unsupported-interactor.js";import{t as a}from"./tool-provider3.js";const o={allowFailure:!0,timeoutMs:3e4};async function s(e,n){t(await a().launchApp(e.id,n,o),`Failed to launch Vega app ${n}`,{appName:n,deviceId:e.id})}async function c(e){t(await a().checkConnected(e.id,o),`Vega device is not connected`,{deviceId:e.id})}async function l(e,n){t(await a().terminateApp(e.id,n,o),`Failed to terminate Vega app ${n}`,{appName:n,deviceId:e.id})}async function u(e,r,i){let o=n(r);t(await a().pressRemote(e.id,o,i,{allowFailure:!0,timeoutMs:1e4+(i??0)}),`Failed to press Vega TV remote ${r}`,{button:r,deviceId:e.id})}const d=[{matches:(e,t)=>r(e)||!!t?.url,message:`Vega open does not support URLs or deep links.`,hint:`Use open <component-id> with an installed Vega app component ID.`},{matches:(e,t)=>!!t?.activity,message:`Vega open does not support Android activity selection.`,hint:`Remove --activity and use the Vega component ID as the open target.`},{matches:(e,t)=>!!t?.launchConsole,message:`Vega open does not support launch-console output.`,hint:`Remove --launch-console and open the Vega component ID directly.`},{matches:(e,t)=>!!t?.terminateRunningApp,message:`Vega open does not support terminating the running app before launch.`,hint:`Close the Vega component explicitly before opening it again.`},{matches:(e,t)=>!!t?.launchArgs?.length,message:`Vega open does not support launch arguments.`,hint:`Remove --launch-arg values and open the Vega component ID directly.`}];function f(e,t){return{...i(`Vega OS`),open:async(t,n)=>{p(t,n),await s(e,t)},openDevice:()=>c(e),close:t=>l(e,t),back:()=>u(e,`back`),home:()=>u(e,`home`),tvRemote:(t,n)=>u(e,t,n)}}function p(t,n){let r=d.find(({matches:e})=>e(t,n));if(r)throw new e(`UNSUPPORTED_OPERATION`,r.message,{hint:r.hint})}export{f as createVegaInteractor};
|
package/dist/src/internal/bin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=process.argv.slice(2);t(e)||(e[0]===`mcp`&&!e.includes(`--help`)&&!e.includes(`-h`)?import(`../server.js`).then(({runAgentDeviceMcpServer:e})=>e()).catch(m):p(e));function t(e){return n(e)||r(e)||i(e)}function n(e){return e.length!==1||!f(e[0])?!1:(process.stdout.write(`0.
|
|
1
|
+
const e=process.argv.slice(2);t(e)||(e[0]===`mcp`&&!e.includes(`--help`)&&!e.includes(`-h`)?import(`../server.js`).then(({runAgentDeviceMcpServer:e})=>e()).catch(m):p(e));function t(e){return n(e)||r(e)||i(e)}function n(e){return e.length!==1||!f(e[0])?!1:(process.stdout.write(`0.20.1
|
|
2
2
|
`),!0)}function r(e){return e.length===0?(import(`../cli-help.js`).then(({buildUsageText:e})=>{process.stdout.write(`${e()}\n`),process.exit(1)}).catch(m),!0):!1}function i(e){let t=a(e);return t===void 0?!1:(import(`../cli-help.js`).then(({buildCommandUsageText:n,buildUsageText:r})=>{if(t===null){process.stdout.write(`${r()}\n`);return}let i=n(l(t));if(i){process.stdout.write(i);return}p(e)}).catch(m),!0)}function a(e){switch(e.length){case 1:return o(e[0]);case 2:return s(e[0],e[1]);default:return}}function o(e){return e===`help`||d(e)?null:void 0}function s(e,t){return u(e)?t:c(e,t)}function c(e,t){return d(t)?e:void 0}function l(e){return e===`long-press`?`longpress`:e===`metrics`?`perf`:e}function u(e){return e===`help`}function d(e){return e===`--help`||e===`-h`}function f(e){return e===`--version`||e===`-V`}function p(e){import(`../cli.js`).then(({runCli:t})=>t(e)).catch(m)}function m(e){process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exit(1)}export{};
|