agent-device 0.20.3 → 0.20.4

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.
Files changed (140) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.3.apk → agent-device-android-ime-helper-0.20.4.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.4.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.3.manifest.json → agent-device-android-ime-helper-0.20.4.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.4.apk +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.4.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.3.manifest.json → agent-device-android-snapshot-helper-0.20.4.manifest.json} +6 -6
  7. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +57 -4
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +45 -9
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +73 -0
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +1 -0
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +3 -2
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +1 -1
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +8 -2
  14. package/dist/src/agent-browser-tool.js +1 -1
  15. package/dist/src/agent-device-client.js +2 -2
  16. package/dist/src/android-adb.d.ts +1 -1
  17. package/dist/src/android.js +1 -1
  18. package/dist/src/app-helpers.js +1 -1
  19. package/dist/src/app-inventory.d.ts +4 -0
  20. package/dist/src/app-lifecycle.js +7 -7
  21. package/dist/src/app-resolution.js +1 -1
  22. package/dist/src/apps.js +5 -5
  23. package/dist/src/boot-diagnostics.js +1 -1
  24. package/dist/src/cli-config.js +1 -1
  25. package/dist/src/cli-help.js +27 -19
  26. package/dist/src/cli-runner.js +1 -1
  27. package/dist/src/cli.js +15 -14
  28. package/dist/src/client-metro.js +1 -1
  29. package/dist/src/{tv-remote.d.ts → cloud-artifacts.d.ts} +109 -126
  30. package/dist/src/command-metadata.js +1 -1
  31. package/dist/src/command-schema.js +1 -1
  32. package/dist/src/command-surface.js +1 -1
  33. package/dist/src/context.js +1 -1
  34. package/dist/src/contracts.d.ts +1 -1
  35. package/dist/src/debug-symbols.js +4 -4
  36. package/dist/src/device-input-state.d.ts +2 -2
  37. package/dist/src/device-input-state.js +1 -1
  38. package/dist/src/device.js +1 -9
  39. package/dist/src/devices2.js +1 -1
  40. package/dist/src/entities.js +1 -0
  41. package/dist/src/find.js +1 -1
  42. package/dist/src/finders.d.ts +1 -1
  43. package/dist/src/finders.js +1 -1
  44. package/dist/src/generic.js +1 -1
  45. package/dist/src/helper.js +2 -2
  46. package/dist/src/ime-lifecycle.js +9 -0
  47. package/dist/src/index.d.ts +592 -555
  48. package/dist/src/input-actions.js +4 -4
  49. package/dist/src/install-artifact.js +4 -4
  50. package/dist/src/install-artifact2.js +1 -1
  51. package/dist/src/install-source2.js +1 -1
  52. package/dist/src/interaction-snapshot.js +1 -1
  53. package/dist/src/interaction.d.ts +7 -4
  54. package/dist/src/interaction.js +1 -1
  55. package/dist/src/interactor.js +2 -2
  56. package/dist/src/interactor2.js +1 -1
  57. package/dist/src/internal/bin.js +1 -1
  58. package/dist/src/internal/daemon.js +14 -14
  59. package/dist/src/internal/png-worker.js +1 -1
  60. package/dist/src/lease-context.js +1 -1
  61. package/dist/src/lease.js +1 -1
  62. package/dist/src/limrun.d.ts +103 -198
  63. package/dist/src/limrun.js +1 -1
  64. package/dist/src/linux.js +1 -1
  65. package/dist/src/logcat.js +1 -1
  66. package/dist/src/manifest.js +1 -1
  67. package/dist/src/metro.d.ts +1 -1
  68. package/dist/src/parser.js +2 -0
  69. package/dist/src/path-resolution.js +1 -1
  70. package/dist/src/physical-device-control.js +1 -1
  71. package/dist/src/plist-xml.js +1 -0
  72. package/dist/src/plist.js +1 -1
  73. package/dist/src/png-worker-contract.js +1 -1
  74. package/dist/src/process-lock.js +1 -1
  75. package/dist/src/provider-limrun-runtime.js +1 -0
  76. package/dist/src/react-native.js +1 -1
  77. package/dist/src/record-trace.js +1 -1
  78. package/dist/src/register-builtins.js +1 -1
  79. package/dist/src/registry.js +22 -22
  80. package/dist/src/remote-config2.js +1 -1
  81. package/dist/src/reporting.js +7 -7
  82. package/dist/src/runner-client.js +1 -1
  83. package/dist/src/runner-disposal.js +1 -1
  84. package/dist/src/runner-lease.js +1 -1
  85. package/dist/src/runner-provider.js +1 -1
  86. package/dist/src/runner-sequence.js +1 -1
  87. package/dist/src/runtime-transport.js +1 -1
  88. package/dist/src/runtime.js +3 -3
  89. package/dist/src/screenshot-geometry.js +1 -0
  90. package/dist/src/screenshot-result.js +6 -0
  91. package/dist/src/sdk-android-adb.d.ts +5 -6
  92. package/dist/src/sdk-android-adb.js +3 -3
  93. package/dist/src/sdk-batch-runner.d.ts +2 -2
  94. package/dist/src/sdk-batch-runner.js +3 -3
  95. package/dist/src/sdk-contracts.d.ts +21 -25
  96. package/dist/src/sdk-contracts.js +2 -2
  97. package/dist/src/sdk-finders.d.ts +1 -1
  98. package/dist/src/sdk-finders.js +1 -1
  99. package/dist/src/sdk-io.js +1 -1
  100. package/dist/src/sdk-remote-config.d.ts +19 -4
  101. package/dist/src/sdk-remote-config.js +1 -1
  102. package/dist/src/sdk-selectors.js +1 -1
  103. package/dist/src/selector-runtime.js +1 -1
  104. package/dist/src/selector-vocabulary.js +1 -1
  105. package/dist/src/selectors.d.ts +1 -1
  106. package/dist/src/selectors.js +1 -1
  107. package/dist/src/server.js +2 -2
  108. package/dist/src/session-target-evidence.js +1 -1
  109. package/dist/src/session.js +8 -8
  110. package/dist/src/setting-state.js +1 -1
  111. package/dist/src/simulator.js +1 -1
  112. package/dist/src/snapshot.js +1 -1
  113. package/dist/src/snapshot2.js +1 -1
  114. package/dist/src/src.js +1 -0
  115. package/dist/src/tool-provider.js +3 -3
  116. package/dist/src/tool-provider2.js +1 -1
  117. package/dist/src/tool-provider3.js +1 -1
  118. package/dist/src/update-check.js +1 -1
  119. package/dist/src/version.js +1 -1
  120. package/dist/src/viewport-dimension.js +14 -0
  121. package/package.json +17 -7
  122. package/server.json +2 -2
  123. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.3.apk.sha256 +0 -1
  124. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.3.apk +0 -0
  125. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.3.apk.sha256 +0 -1
  126. package/dist/src/android-input-method-overlays.js +0 -1
  127. package/dist/src/android-input-ownership.js +0 -1
  128. package/dist/src/apple-multitouch-support.js +0 -1
  129. package/dist/src/click-button.d.ts +0 -5
  130. package/dist/src/compatibility-policy.js +0 -1
  131. package/dist/src/gesture-plan-types.js +0 -1
  132. package/dist/src/gesture-plan.js +0 -1
  133. package/dist/src/launch-console.js +0 -1
  134. package/dist/src/recording-export-quality.js +0 -14
  135. package/dist/src/rolldown-runtime.js +0 -1
  136. package/dist/src/runtime2.js +0 -1
  137. package/dist/src/sdk-app-inventory.d.ts +0 -4
  138. package/dist/src/sdk-app-inventory.js +0 -1
  139. package/dist/src/snapshot-diagnostics.js +0 -6
  140. package/dist/src/xml.js +0 -2
@@ -1,4 +1,4 @@
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{E as l,R as ee}from"./gesture-plan-types.js";import{t as u}from"./timeouts.js";import{r as te}from"./android-input-ownership.js";import{a as d}from"./install-artifact.js";import{r as f}from"./device-input-state.js";import{t as ne}from"./gesture-plan.js";import{C as p,D as re,E as ie,O as m,S as h,T as ae,b as oe,f as se,h as ce,k as le,m as g,p as _,s as v,x as ue,y as de}from"./device.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 ce(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 ce(e),t,n,r,i)}function S(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of le(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 h({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 h({deviceKey:t.deviceKey,action:`viewport`,helper:k(t.artifact),timeoutMs:E});if(e)return N(e)}catch(e){await p(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=ue(e),s=await n(`android_touch_helper_install`,async()=>await de({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 p(o),{adb:t.exec,artifact:a,install:s,deviceKey:o}}async function Ie(){return await oe({helperDirName:`snapshot-helper`,manifestFileName:e=>`agent-device-android-snapshot-helper-${e}.manifest.json`,parseManifest:e=>{let t=ae(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=re(e).results.find(e=>e.agentDeviceProtocol===ie);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=l(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(Ke(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)}Ke(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 _()).manifest.packageName,a=t.split(`
2
- `);for(let[t,o]of a.entries()){let s=n>0?Q(o,1):[o];for(let[e,o]of s.entries())o&&await g(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 _()).manifest.packageName,o=null;for(let s=0;s<2;s+=1){await W(e,t,n),await se(i,a),r&&await g(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=ee({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=Q(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`,Je(t)])}catch(e){throw Ye(e)?Xe(t,e):e}}function Ke(e){if(!qe(e))throw Xe(e)}function qe(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 Je(e){return e.replace(/ /g,`%s`)}function Ye(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 Xe(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 Q(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};
1
+ import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{C as n,V as r,m as i}from"./screenshot-geometry.js";import{T as a,n as o}from"./device.js";import{I as s,c,j as l,l as u,p as d,s as f,u as p}from"./sdk-android-adb.js";import{t as m}from"./timeouts.js";import{a as h}from"./install-artifact.js";import{r as g}from"./device-input-state.js";import{C as ee,D as _,E as te,O as ne,S as re,T as ie,_ as ae,b as oe,c as se,d as v,g as ce,l as y,r as b,u as x,w as le,y as S}from"./ime-lifecycle.js";function ue(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=pe(t),r={failureReason:t.reason??`text_mismatch`,targetInput:w(t.targetInput),actualInput:w(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 C(e){return e?e.password?!0:de(e.text):!1}function de(e){return e?Array.from(e).every(fe):!1}function w(e){if(!e)return null;let t=C(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function fe(e){return e===`•`||e===`*`||e===`●`}function pe(e){return e.masked===!0||C(e.targetInput)||C(e.actualInput)}async function T(e,t,n,r){let i=[0,150,350],a=null,o=null,s=await Ee(e);for(let c of i){c>0&&await m(c);let i=await ye(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 me(e,t,n){return ge(await v(e),t,n)}function he(e,t,n,r,i={}){let a=E(e,t,n,i);return be(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:xe(a,r)??Se(a,r)}function ge(e,t,n){return E(e,t,n).targetInput?.text??null}function _e(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 ve(e,t){let n=ue(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 ye(e,t,n,r,i){return he(await v(e),t,n,r,i)}function E(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of ne(e)){let e=Te(a,r);e&&De(i,e,t,n)}return ke(i)}function be(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function xe(e,t){let n=e.actualInput;if(!n||!je(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 Se(e,t){let n=e.actualInput?.text??null;return{ok:Ce(n,t),actual:n,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:e.actualInput}}function Ce(e,t){if(e===t)return!0;let n=D(e),r=D(t);return!n||!r?!1:!!(n===r||we(n,r))}function D(e){return(e??``).replace(/\s+/g,` `).trim()}function we(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 Te(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:a({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:Ae(e.className??``)}}async function Ee(e){try{return{activeInputMethodPackage:(await g(e)).inputMethodPackage}}catch(e){return l({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function De(e,t,n,r){let i=Oe(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 Oe(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 ke(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function Ae(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function je(e){return C(e)}function k(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 A=45e3,j=`ANDROID_TOUCH_HELPER_NO_FINAL_RESULT`,M=`ANDROID_TOUCH_HELPER_REPORTED_FAILURE`;async function Me(e,t){let n=await P(e),r=Fe(t),i=Math.max(45e3,r.durationMs+15e3),a=Buffer.from(JSON.stringify({protocol:`android-touch-plan-v1`,...r})).toString(`base64`),o=await s(`android_touch_helper_gesture`,async()=>{let e=await S({deviceKey:n.deviceKey,action:`gesture`,helper:N(n.artifact),payloadBase64:a,timeoutMs:i});return e?{...I(e),helperTransport:`persistent-session`}:{...await F({adb:n.adb,runner:n.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`gesture`,`-e`,`payloadBase64`,a],timeoutMs:i,readResult:I}),helperTransport:`instrumentation`}},{packageName:n.artifact.manifest.packageName,version:n.artifact.manifest.version});return{backend:`android-helper`,helperVersion:n.artifact.manifest.version,installReason:n.install.reason,...o}}async function Ne(e){let t=await P(e);try{let e=await S({deviceKey:t.deviceKey,action:`viewport`,helper:N(t.artifact),timeoutMs:A});if(e)return L(e)}catch(e){await oe(t.deviceKey),l({level:`warn`,phase:`android_touch_helper_viewport_session_fallback`,data:{reason:e instanceof Error?e.message:String(e)}})}return await F({adb:t.adb,runner:t.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`viewport`],timeoutMs:A,readResult:L})}function N(e){return{packageName:e.manifest.packageName,runner:e.manifest.instrumentationRunner,helperVersion:e.manifest.version,helperVersionCode:e.manifest.versionCode,sha256:e.manifest.sha256}}async function P(e){let t=c(e),n=t.snapshotHelperArtifact??await Pe(),r=re(e);await ee({deviceKey:r,adb:t.exec});let i=await s(`android_touch_helper_install`,async()=>await ce({adb:t.exec,adbProvider:t,artifact:n,deviceKey:r,timeoutMs:3e4}),{packageName:n.manifest.packageName,versionCode:n.manifest.versionCode});return l({phase:`android_touch_helper_install_decision`,data:i}),i.installed&&await oe(r),{adb:t.exec,artifact:n,install:i,deviceKey:r}}async function Pe(){return await ae({helperDirName:`snapshot-helper`,manifestFileName:e=>`agent-device-android-snapshot-helper-${e}.manifest.json`,parseManifest:e=>{let t=le(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 Fe(e){return{kind:e.topology===`single`?`swipe`:`transform`,durationMs:e.durationMs,pointers:e.pointers.map(Ie)}}function Ie(e){return{pointerId:e.pointerId,samples:e.samples.map(({offsetMs:e,point:t})=>({offsetMs:e,x:t.x,y:t.y}))}}async function F(e){let n=await e.adb([`shell`,`am`,`instrument`,`-w`,...e.extraArgs,e.runner],{allowFailure:!0,timeoutMs:e.timeoutMs}),r;try{r=Le(`${n.stdout}\n${n.stderr}`)}catch(e){if(e instanceof t){if(e.code===M)throw new t(`COMMAND_FAILED`,e.message,e.details,e);if(e.code!==j)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`,d(n),e)}if(n.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android automation helper failed`,d(n,{helper:r}));return e.readResult(r)}function Le(e){let n=te(e).results.find(e=>e.agentDeviceProtocol===ie);if(!n)throw new t(j,`Android automation helper did not return a final result`);if(n.ok!==`true`)throw new t(M,n.message&&n.message!==`null`?n.message:n.errorType||`Android automation helper returned an error`,{errorType:n.errorType,helper:n});return n}function I(e){return{helperKind:e.kind,helperApiVersion:e.helperApiVersion,injectedEvents:_(e.injectedEvents),elapsedMs:_(e.elapsedMs)}}function L(e){let n=_(e.x),r=_(e.y),i=_(e.width),a=_(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 k({x:n,y:r,width:i,height:a})}async function R(e,t){let n=p(e);if(n){let e=t.intent===`longPress`?{...t,viewport:k(await n.gestureViewport())}:t;return{backend:`provider-native-touch`,...await n.touch(e)??{}}}return await Me(e,t)}async function z(e){let t=p(e);return t?k(await t.gestureViewport()):await Ne(e)}var Re=e({appSwitcherAndroid:()=>G,backAndroid:()=>H,fillAndroid:()=>Be,focusAndroid:()=>J,getAndroidScreenSize:()=>Ge,homeAndroid:()=>U,longPressAndroid:()=>K,pressAndroid:()=>B,pressAndroidEnter:()=>ze,pressAndroidTvRemote:()=>V,readAndroidTextAtPoint:()=>me,scrollAndroid:()=>Ue,setAndroidOrientation:()=>W,typeAndroid:()=>q});async function B(e,t,n){await h(e,[`shell`,`input`,`tap`,String(t),String(n)])}async function V(e,t,n){let r=i(t);await h(e,[`shell`,`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function H(e){await h(e,[`shell`,`input`,`keyevent`,`4`])}async function U(e){await h(e,[`shell`,`input`,`keyevent`,`3`])}async function ze(e){await h(e,[`shell`,`input`,`keyevent`,`ENTER`])}async function W(e,t){let n=We(t);await h(e,[`shell`,`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await h(e,[`shell`,`settings`,`put`,`system`,`user_rotation`,n])}async function G(e){await h(e,[`shell`,`input`,`keyevent`,`187`])}async function K(e,t,n,r=800){let i={x:t,y:n};return await R(e,{topology:`single`,intent:`longPress`,durationMs:r,pointers:[{pointerId:0,samples:[{offsetMs:0,point:i},{offsetMs:r,point:i}]}]})}async function q(e,t,n=0){let r=u(e);if(r){await r({action:`type`,text:t,delayMs:n}),$(`type`,`provider-native`,t);return}if(b(e)){await Ve(e,t,n);return}if(Je(t),await X(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:Ke,delayMs:0})}async function J(e,t,n){await B(e,t,n)}async function Be(e,t,n,r,i=0){let a=u(e);if(a){await a({action:`fill`,target:{x:t,y:n},text:r,delayMs:i}),$(`fill`,`provider-native`,r);let o=await T(e,t,n,r);if(o.ok)return;Y(r,o)}if(b(e)){let i=await He(e,t,n,r);if(i.ok)return;Y(r,i)}Je(r);let o=Array.from(r).length,s=[{clearPadding:12,minClear:8,maxClear:48,chunkSize:i>0?1:Ke,inputDelayMs:i},{clearPadding:24,minClear:16,maxClear:96,chunkSize:i>0?1:4,inputDelayMs:i>0?i:15}],c=null;for(let i of s){await J(e,t,n),await X(e,`fill`),await $e(e,et(o+i.clearPadding,i.minClear,i.maxClear)),await Z(e,{action:`fill`,text:r,chunkSize:i.chunkSize,delayMs:i.inputDelayMs});let a=await T(e,t,n,r);if(c=a,a.ok)return;a.reason===`ime_capture`&&Y(r,a)}Y(r,c)}async function Ve(e,t,n){let r=f(e),i=(await y()).manifest.packageName,a=t.split(`
2
+ `);for(let[t,o]of a.entries()){let s=n>0?Q(o,1):[o];for(let[e,o]of s.entries())o&&await x(r,i,o),n>0&&(e+1<s.length||t+1<a.length)&&await m(n);t+1<a.length&&await h(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(`type`,`test-ime`,t)}async function He(e,t,n,r){let i=f(e),a=(await y()).manifest.packageName,o=null;for(let s=0;s<2;s+=1){await J(e,t,n),await se(i,a),r&&await x(i,a,r);let s=await T(e,t,n,r);if(o=s,s.ok)break}return $(`fill`,`test-ime`,r),o}function Y(e,n){throw new t(`COMMAND_FAILED`,_e(n),ve(e,n))}async function Ue(e,t,i){let a=await z(e),o=r({direction:t,amount:i?.amount,pixels:i?.pixels,referenceWidth:a.width,referenceHeight:a.height}),s={...o,referenceWidth:a.x+a.width,referenceHeight:a.y+a.height,x1:a.x+o.x1,y1:a.y+o.y1,x2:a.x+o.x2,y2:a.y+o.y2},c=Math.max(i?.durationMs??300,16),l=await R(e,n({intent:`pan`,origin:{x:s.x1,y:s.y1},delta:{x:s.x2-s.x1,y:s.y2-s.y1},durationMs:c},a,`android`));return{...s,...i?.durationMs===void 0?{}:{durationMs:c},...l}}function We(e){let n=o[e];if(n===void 0)throw new t(`INVALID_ARGS`,`Unsupported Android rotation: ${e}`);return String(n)}async function X(e,n){let r;try{r=await g(e)}catch(e){l({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 Ge(e){let n=(await h(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 Ke=8;async function Z(e,t){let n=t.text.split(`
3
+ `);for(let[r,i]of n.entries()){let a=Q(i,t.chunkSize);for(let[i,o]of a.entries())await qe(e,o),t.delayMs>0&&(i+1<a.length||r+1<n.length)&&await m(t.delayMs);r+1<n.length&&await h(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(t.action,`adb-shell`,t.text)}async function qe(e,t){if(t)try{await h(e,[`shell`,`input`,`text`,Xe(t)])}catch(e){throw Ze(e)?Qe(t,e):e}}function Je(e){if(!Ye(e))throw Qe(e)}function Ye(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 Xe(e){return e.replace(/ /g,`%s`)}function Ze(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 Qe(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 Q(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){l({phase:`android_text_injection`,data:{action:e,backend:t,textLength:Array.from(n).length}})}async function $e(e,t){let n=Math.max(0,t);await h(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 h(e,[`shell`,`input`,`keyevent`,...Array(r).fill(`KEYCODE_DEL`)],{allowFailure:!0})}}function et(e,t,n){return Math.max(t,Math.min(n,e))}export{Ge as a,K as c,Ue as d,W as f,z as h,J as i,B as l,R as m,H as n,U as o,q as p,Be as r,Re as s,G as t,V as u};
@@ -1,5 +1,5 @@
1
- import{t as e}from"./rolldown-runtime.js";import{_ as t,v as n}from"./sdk-contracts.js";import{b as r,h as i,r as a,s as o,v as s,w as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{n as u,t as d}from"./manifest.js";import{n as f,r as p}from"./install-source2.js";import{a as m,l as h,n as g,s as ee,t as _}from"./boot-diagnostics.js";import v from"node:path";function y(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let n=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!n)return!1;let r=n[1]?.toLowerCase(),i=n[2]??``;return r===`http`||r===`https`||r===`ws`||r===`wss`||r===`ftp`||r===`ftps`?i.startsWith(`//`):!0}function b(e){let t=e.trim().split(`:`)[0]?.toLowerCase();return t===`http`||t===`https`}function x(e,t){let n=e?.trim();if(n)return n;if(b(t))return`com.apple.mobilesafari`}function te(e={}){let t=e.ttlMs??3e4,n=e.nowMs??Date.now,r=new Map,i=e=>{let t=C(e);for(let e of r.keys())e.startsWith(t)&&r.delete(e)};return{get(e,t){let i=S(e,t),a=r.get(i);if(a){if(a.expiresAtMs<=n()){r.delete(i);return}return a.value}},set(e,i,a){return r.set(S(e,i),{value:a,expiresAtMs:n()+t}),a},clear(e){i(e)},async invalidateWhile(e,t){i(e);try{return await t()}finally{i(e)}}}}function S(e,t){return[e.platform,e.deviceId,e.variant??``,t.trim().toLowerCase()].join(`\0`)}function C(e){return[e.platform,e.deviceId,``].join(`\0`)}var ne=e({ensureAndroidEmulatorBooted:()=>oe,listAndroidDevices:()=>H,parseAndroidAvdList:()=>G,parseAndroidEmulatorAvdNameOutput:()=>j,parseAndroidFeatureListForTv:()=>R,parseAndroidTargetFromCharacteristics:()=>L,resolveAndroidAvdName:()=>K,resolveAndroidEmulatorAvdName:()=>I,waitForAndroidBoot:()=>Z});const w=1e4,T=[`android.software.leanback`,`android.software.leanback_only`,`android.hardware.type.television`];async function E(e,t,n){let r=Array(e.length),i=0,a=Math.min(t,e.length);return await Promise.all(Array.from({length:a},async()=>{for(;i<e.length;){let t=i;i+=1,r[t]=await n(e[t])}})),r}function D(e){return`${e.stdout}\n${e.stderr}`}function O(e,t){return[`-s`,e,...t]}function k(e){return e.startsWith(`emulator-`)}function A(e){return e.toLowerCase().replace(/_/g,` `).replace(/\s+/g,` `).trim()}function j(e){let t=e.split(`
1
+ import{o as e}from"./png-worker-contract.js";import{_ as t,v as n}from"./sdk-contracts.js";import{b as r,h as i,r as a,s as o,v as s,w as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{n as u,t as d}from"./manifest.js";import{n as f,r as p}from"./install-source2.js";import{a as m,l as h,n as g,s as ee,t as _}from"./boot-diagnostics.js";import v from"node:path";function y(e={}){let t=e.ttlMs??3e4,n=e.nowMs??Date.now,r=new Map,i=e=>{let t=x(e);for(let e of r.keys())e.startsWith(t)&&r.delete(e)};return{get(e,t){let i=b(e,t),a=r.get(i);if(a){if(a.expiresAtMs<=n()){r.delete(i);return}return a.value}},set(e,i,a){return r.set(b(e,i),{value:a,expiresAtMs:n()+t}),a},clear(e){i(e)},async invalidateWhile(e,t){i(e);try{return await t()}finally{i(e)}}}}function b(e,t){return[e.platform,e.deviceId,e.variant??``,t.trim().toLowerCase()].join(`\0`)}function x(e){return[e.platform,e.deviceId,``].join(`\0`)}var S=e({ensureAndroidEmulatorBooted:()=>re,listAndroidDevices:()=>z,parseAndroidAvdList:()=>H,parseAndroidEmulatorAvdNameOutput:()=>k,parseAndroidFeatureListForTv:()=>I,parseAndroidTargetFromCharacteristics:()=>F,resolveAndroidAvdName:()=>U,resolveAndroidEmulatorAvdName:()=>P,waitForAndroidBoot:()=>Z});const C=1e4,te=[`android.software.leanback`,`android.software.leanback_only`,`android.hardware.type.television`];async function w(e,t,n){let r=Array(e.length),i=0,a=Math.min(t,e.length);return await Promise.all(Array.from({length:a},async()=>{for(;i<e.length;){let t=i;i+=1,r[t]=await n(e[t])}})),r}function T(e){return`${e.stdout}\n${e.stderr}`}function E(e,t){return[`-s`,e,...t]}function D(e){return e.startsWith(`emulator-`)}function O(e){return e.toLowerCase().replace(/_/g,` `).replace(/\s+/g,` `).trim()}function k(e){let t=e.split(`
2
2
  `).map(e=>e.trim()).filter(e=>e.length>0);if(t.length!==0)return t.at(-1)===`OK`&&t.pop(),t.join(`
3
- `).trim()||void 0}async function M(e,t=w){return s(`adb`,O(e,[`shell`,`getprop`,`sys.boot_completed`]),{allowFailure:!0,timeoutMs:t})}async function N(e,t){let n=t.replace(/_/g,` `).trim();if(!k(e))return n||e;let r=await I(e);return r?r.replace(/_/g,` `):n||e}async function P(e,t,r){try{return await r(`adb`,O(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){if(F(n(e)))return;throw e}}function F(e){return e.code===`COMMAND_FAILED`&&typeof e.details?.timeoutMs==`number`}async function I(e,t=s){for(let n of[`ro.boot.qemu.avd_name`,`persist.sys.avd_name`]){let r=await P(e,[`shell`,`getprop`,n],t);if(!r)continue;let i=r.stdout.trim();if(r.exitCode===0&&i.length>0)return i}let n=await P(e,[`emu`,`avd`,`name`],t);if(!n)return;let r=j(n.stdout);if(n.exitCode===0&&r)return r}function L(e){let t=e.toLowerCase();return t.includes(`tv`)||t.includes(`leanback`)?`tv`:null}function R(e){return/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(e)}async function z(e,t){let n=D(await s(`adb`,O(e,[`shell`,`cmd`,`package`,`has-feature`,t]),{allowFailure:!0,timeoutMs:w})).toLowerCase();return n.includes(`true`)?!0:n.includes(`false`)?!1:null}async function B(e){return(await E(T,2,async t=>await z(e,t))).some(e=>e===!0)}async function V(e){return L(D(await s(`adb`,O(e,[`shell`,`getprop`,`ro.build.characteristics`]),{allowFailure:!0,timeoutMs:w})))===`tv`||await B(e)||R(D(await s(`adb`,O(e,[`shell`,`pm`,`list`,`features`]),{allowFailure:!0,timeoutMs:w})))?`tv`:`mobile`}async function H(e={}){if(await u(),!await c(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);let n=e.serialAllowlist??m(void 0),r=await E((await W()).filter(e=>!n||n.has(e.serial)),3,async({serial:e,rawModel:t})=>{let[n,r,i]=await Promise.all([N(e,t),ae(e),V(e)]);return{platform:`android`,id:e,name:n,kind:k(e)?`emulator`:`device`,target:i,booted:r}});return[...r,...await J(r)]}function U(e){return e.split(`
4
- `).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).flatMap(e=>{let t=e[0];return t===void 0||e[1]!==`device`?[]:[{serial:t,rawModel:(e.find(e=>e.startsWith(`model:`))??``).replace(`model:`,``)}]})}async function W(){try{return U((await s(`adb`,[`devices`,`-l`],{timeoutMs:w})).stdout)}catch(e){throw a(e)}}function G(e){return e.split(`
5
- `).map(e=>e.trim()).filter(e=>e.length>0)}function K(e,t){let n=e.find(e=>e===t);if(n)return n;let r=A(t);return e.find(e=>A(e)===r)}async function q(){return G(i(await s(`emulator`,[`-list-avds`],{allowFailure:!0,timeoutMs:w}),`Failed to list Android emulator AVDs`,{hint:`Verify Android emulator tooling is installed and available in PATH.`}).stdout)}async function J(e){let t=await q().catch(()=>[]),n=new Set(e.filter(e=>e.kind===`emulator`).map(e=>A(e.name)));return t.filter(e=>!n.has(A(e))).map(e=>({platform:`android`,id:e,name:e,kind:`emulator`,target:Y(e),booted:!1}))}function Y(e){return/\b(tv|television)\b/i.test(A(e))?`tv`:`mobile`}function X(e,t,n){let r=A(t);return e.find(e=>e.platform!==`android`||e.kind!==`emulator`||n&&e.id!==n?!1:A(e.name)===r)}async function re(e){let n=Date.now(),r=Math.min(1e3,Math.max(50,Math.floor(e.timeoutMs/20)));for(;Date.now()-n<e.timeoutMs;){try{let t=await ie(e.avdName,e.serial);if(t)return{platform:`android`,id:t,name:e.avdName,kind:`emulator`,target:`mobile`,booted:!1}}catch{}await l(r)}throw new t(`COMMAND_FAILED`,`Android emulator did not appear in time`,{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:`Check emulator logs and verify the AVD can start from command line.`})}async function ie(e,t){let n=A(e),r=(await W()).filter(e=>t&&e.serial!==t?!1:k(e.serial));for(let e of r)if(A(e.rawModel)===n||A(await N(e.serial,e.rawModel))===n)return e.serial}async function ae(e){try{return(await M(e)).stdout.trim()===`1`}catch{return!1}}async function oe(e){await u();let n=e.avdName.trim();if(!n)throw new t(`INVALID_ARGS`,`Android emulator boot requires a non-empty AVD name.`);let i=e.timeoutMs??12e4;if(!await c(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);if(!await c(`emulator`))throw new t(`TOOL_MISSING`,`emulator not found in PATH`);let a=await q(),o=K(a,n);if(!o)throw new t(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:n,availableAvds:a,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let s=Date.now(),l=X(await H(),o,e.serial),d=l&&k(l.id)?l:void 0;if(!d){let t=[`-avd`,o];e.headless&&t.push(`-no-window`,`-no-audio`),r(`emulator`,t)}let f=d??await re({avdName:o,serial:e.serial,timeoutMs:i}),p=Date.now()-s,m=Math.max(1e3,i-p);await Z(f.id,m);let h=(await H()).find(e=>e.id===f.id);return h?{...h,name:o,booted:!0}:{...f,name:o,booted:!0}}async function Z(e,r=6e4){let i=r,a=ee.fromTimeoutMs(i),o=Math.min(1e3,Math.max(50,Math.floor(i/20))),s=Math.max(1,Math.ceil(i/o)),c,l=!1;try{await h(async({deadline:n})=>{if(n?.isExpired())throw l=!0,new t(`COMMAND_FAILED`,`Android boot deadline exceeded`,{serial:e,timeoutMs:r,elapsedMs:a.elapsedMs(),message:`timeout`});let o=Math.max(1e3,n?.remainingMs()??i),s=await M(e,Math.min(o,w));if(c=s,s.stdout.trim()!==`1`)throw new t(`COMMAND_FAILED`,`Android device is still booting`,{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:s,baseDelayMs:o,maxDelayMs:o,jitter:0,shouldRetry:e=>{let t=g({error:e,stdout:c?.stdout,stderr:c?.stderr,context:{platform:`android`,phase:`boot`}});return t!==`ADB_TRANSPORT_UNAVAILABLE`&&t!==`ANDROID_BOOT_TIMEOUT`}},{deadline:a,phase:`boot`,classifyReason:e=>g({error:e,stdout:c?.stdout,stderr:c?.stderr,context:{platform:`android`,phase:`boot`}})})}catch(r){let o=n(r),s=c?.stdout,u=c?.stderr,d=c?.exitCode,f=g({error:r,stdout:s,stderr:u,context:{platform:`android`,phase:`boot`}});f===`BOOT_COMMAND_FAILED`&&o.message===`Android device is still booting`&&(f=`ANDROID_BOOT_TIMEOUT`);let p={serial:e,timeoutMs:i,elapsedMs:a.elapsedMs(),reason:f,hint:_(f),stdout:s,stderr:u,exitCode:d};throw l||f===`ANDROID_BOOT_TIMEOUT`?new t(`COMMAND_FAILED`,`Android device did not finish booting in time`,p):o.code===`TOOL_MISSING`?new t(`TOOL_MISSING`,o.message,{...p,...o.details??{}}):f===`ADB_TRANSPORT_UNAVAILABLE`?new t(`COMMAND_FAILED`,o.message,{...p,...o.details??{}}):new t(o.code,o.message,{...p,...o.details??{}},o.cause)}}async function Q(e,t,n){return await o(e)(t,n)}function se(e){return{platform:`android`,id:e,name:e,kind:e.startsWith(`emulator-`)?`emulator`:`device`,booted:!0}}function ce(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`no shell command implementation`)||n.includes(`unknown command`)}var le=e({prepareAndroidInstallArtifact:()=>$});async function $(e,t){let n=e.kind===`url`&&f(e.url),r=await p({source:e,isInstallablePath:(e,t)=>t.isFile()&&ue(e),installableLabel:`Android installable (.apk or .aab)`,allowArchiveExtraction:e.kind!==`url`||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await de(r.installablePath);return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:e.packageName,cleanup:r.cleanup}}catch(e){throw await r.cleanup(),e}}function ue(e){let t=v.extname(e).toLowerCase();return t===`.apk`||t===`.aab`}async function de(e){let t=v.extname(e).toLowerCase();return t!==`.apk`&&t!==`.aab`?{}:{packageName:await d(e)}}export{Q as a,te as c,x as d,ce as i,y as l,$ as n,ne as o,se as r,Z as s,le as t,b as u};
3
+ `).trim()||void 0}async function A(e,t=C){return s(`adb`,E(e,[`shell`,`getprop`,`sys.boot_completed`]),{allowFailure:!0,timeoutMs:t})}async function j(e,t){let n=t.replace(/_/g,` `).trim();if(!D(e))return n||e;let r=await P(e);return r?r.replace(/_/g,` `):n||e}async function M(e,t,r){try{return await r(`adb`,E(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){if(N(n(e)))return;throw e}}function N(e){return e.code===`COMMAND_FAILED`&&typeof e.details?.timeoutMs==`number`}async function P(e,t=s){for(let n of[`ro.boot.qemu.avd_name`,`persist.sys.avd_name`]){let r=await M(e,[`shell`,`getprop`,n],t);if(!r)continue;let i=r.stdout.trim();if(r.exitCode===0&&i.length>0)return i}let n=await M(e,[`emu`,`avd`,`name`],t);if(!n)return;let r=k(n.stdout);if(n.exitCode===0&&r)return r}function F(e){let t=e.toLowerCase();return t.includes(`tv`)||t.includes(`leanback`)?`tv`:null}function I(e){return/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(e)}async function ne(e,t){let n=T(await s(`adb`,E(e,[`shell`,`cmd`,`package`,`has-feature`,t]),{allowFailure:!0,timeoutMs:C})).toLowerCase();return n.includes(`true`)?!0:n.includes(`false`)?!1:null}async function L(e){return(await w(te,2,async t=>await ne(e,t))).some(e=>e===!0)}async function R(e){return F(T(await s(`adb`,E(e,[`shell`,`getprop`,`ro.build.characteristics`]),{allowFailure:!0,timeoutMs:C})))===`tv`||await L(e)||I(T(await s(`adb`,E(e,[`shell`,`pm`,`list`,`features`]),{allowFailure:!0,timeoutMs:C})))?`tv`:`mobile`}async function z(e={}){if(await u(),!await c(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);let n=e.serialAllowlist??m(void 0),r=await w((await V()).filter(e=>!n||n.has(e.serial)),3,async({serial:e,rawModel:t})=>{let[n,r,i]=await Promise.all([j(e,t),X(e),R(e)]);return{platform:`android`,id:e,name:n,kind:D(e)?`emulator`:`device`,target:i,booted:r}});return[...r,...await G(r)]}function B(e){return e.split(`
4
+ `).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).flatMap(e=>{let t=e[0];return t===void 0||e[1]!==`device`?[]:[{serial:t,rawModel:(e.find(e=>e.startsWith(`model:`))??``).replace(`model:`,``)}]})}async function V(){try{return B((await s(`adb`,[`devices`,`-l`],{timeoutMs:C})).stdout)}catch(e){throw a(e)}}function H(e){return e.split(`
5
+ `).map(e=>e.trim()).filter(e=>e.length>0)}function U(e,t){let n=e.find(e=>e===t);if(n)return n;let r=O(t);return e.find(e=>O(e)===r)}async function W(){return H(i(await s(`emulator`,[`-list-avds`],{allowFailure:!0,timeoutMs:C}),`Failed to list Android emulator AVDs`,{hint:`Verify Android emulator tooling is installed and available in PATH.`}).stdout)}async function G(e){let t=await W().catch(()=>[]),n=new Set(e.filter(e=>e.kind===`emulator`).map(e=>O(e.name)));return t.filter(e=>!n.has(O(e))).map(e=>({platform:`android`,id:e,name:e,kind:`emulator`,target:K(e),booted:!1}))}function K(e){return/\b(tv|television)\b/i.test(O(e))?`tv`:`mobile`}function q(e,t,n){let r=O(t);return e.find(e=>e.platform!==`android`||e.kind!==`emulator`||n&&e.id!==n?!1:O(e.name)===r)}async function J(e){let n=Date.now(),r=Math.min(1e3,Math.max(50,Math.floor(e.timeoutMs/20)));for(;Date.now()-n<e.timeoutMs;){try{let t=await Y(e.avdName,e.serial);if(t)return{platform:`android`,id:t,name:e.avdName,kind:`emulator`,target:`mobile`,booted:!1}}catch{}await l(r)}throw new t(`COMMAND_FAILED`,`Android emulator did not appear in time`,{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:`Check emulator logs and verify the AVD can start from command line.`})}async function Y(e,t){let n=O(e),r=(await V()).filter(e=>t&&e.serial!==t?!1:D(e.serial));for(let e of r)if(O(e.rawModel)===n||O(await j(e.serial,e.rawModel))===n)return e.serial}async function X(e){try{return(await A(e)).stdout.trim()===`1`}catch{return!1}}async function re(e){await u();let n=e.avdName.trim();if(!n)throw new t(`INVALID_ARGS`,`Android emulator boot requires a non-empty AVD name.`);let i=e.timeoutMs??12e4;if(!await c(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);if(!await c(`emulator`))throw new t(`TOOL_MISSING`,`emulator not found in PATH`);let a=await W(),o=U(a,n);if(!o)throw new t(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:n,availableAvds:a,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let s=Date.now(),l=q(await z(),o,e.serial),d=l&&D(l.id)?l:void 0;if(!d){let t=[`-avd`,o];e.headless&&t.push(`-no-window`,`-no-audio`),r(`emulator`,t)}let f=d??await J({avdName:o,serial:e.serial,timeoutMs:i}),p=Date.now()-s,m=Math.max(1e3,i-p);await Z(f.id,m);let h=(await z()).find(e=>e.id===f.id);return h?{...h,name:o,booted:!0}:{...f,name:o,booted:!0}}async function Z(e,r=6e4){let i=r,a=ee.fromTimeoutMs(i),o=Math.min(1e3,Math.max(50,Math.floor(i/20))),s=Math.max(1,Math.ceil(i/o)),c,l=!1;try{await h(async({deadline:n})=>{if(n?.isExpired())throw l=!0,new t(`COMMAND_FAILED`,`Android boot deadline exceeded`,{serial:e,timeoutMs:r,elapsedMs:a.elapsedMs(),message:`timeout`});let o=Math.max(1e3,n?.remainingMs()??i),s=await A(e,Math.min(o,C));if(c=s,s.stdout.trim()!==`1`)throw new t(`COMMAND_FAILED`,`Android device is still booting`,{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:s,baseDelayMs:o,maxDelayMs:o,jitter:0,shouldRetry:e=>{let t=g({error:e,stdout:c?.stdout,stderr:c?.stderr,context:{platform:`android`,phase:`boot`}});return t!==`ADB_TRANSPORT_UNAVAILABLE`&&t!==`ANDROID_BOOT_TIMEOUT`}},{deadline:a,phase:`boot`,classifyReason:e=>g({error:e,stdout:c?.stdout,stderr:c?.stderr,context:{platform:`android`,phase:`boot`}})})}catch(r){let o=n(r),s=c?.stdout,u=c?.stderr,d=c?.exitCode,f=g({error:r,stdout:s,stderr:u,context:{platform:`android`,phase:`boot`}});f===`BOOT_COMMAND_FAILED`&&o.message===`Android device is still booting`&&(f=`ANDROID_BOOT_TIMEOUT`);let p={serial:e,timeoutMs:i,elapsedMs:a.elapsedMs(),reason:f,hint:_(f),stdout:s,stderr:u,exitCode:d};throw l||f===`ANDROID_BOOT_TIMEOUT`?new t(`COMMAND_FAILED`,`Android device did not finish booting in time`,p):o.code===`TOOL_MISSING`?new t(`TOOL_MISSING`,o.message,{...p,...o.details??{}}):f===`ADB_TRANSPORT_UNAVAILABLE`?new t(`COMMAND_FAILED`,o.message,{...p,...o.details??{}}):new t(o.code,o.message,{...p,...o.details??{}},o.cause)}}async function ie(e,t,n){return await o(e)(t,n)}function Q(e){return{platform:`android`,id:e,name:e,kind:e.startsWith(`emulator-`)?`emulator`:`device`,booted:!0}}function ae(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`no shell command implementation`)||n.includes(`unknown command`)}var oe=e({prepareAndroidInstallArtifact:()=>$});async function $(e,t){let n=e.kind===`url`&&f(e.url),r=await p({source:e,isInstallablePath:(e,t)=>t.isFile()&&se(e),installableLabel:`Android installable (.apk or .aab)`,allowArchiveExtraction:e.kind!==`url`||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await ce(r.installablePath);return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:e.packageName,cleanup:r.cleanup}}catch(e){throw await r.cleanup(),e}}function se(e){let t=v.extname(e).toLowerCase();return t===`.apk`||t===`.aab`}async function ce(e){let t=v.extname(e).toLowerCase();return t!==`.apk`&&t!==`.aab`?{}:{packageName:await d(e)}}export{ie as a,y as c,ae as i,$ as n,S as o,Q as r,Z as s,oe as t};
@@ -1 +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{t as a}from"./plist.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};
1
+ import{o as e}from"./png-worker-contract.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{t as a}from"./plist.js";import o from"node:path";import{promises as s}from"node:fs";import c from"node:os";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=o.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 s.mkdtemp(o.join(c.tmpdir(),`agent-device-ios-ipa-`)),a=async()=>{await s.rm(i,{recursive:!0,force:!0})};try{await n(`unzip`,[`-q`,e,`-d`,i]);let c=o.join(i,`Payload`),l=(await s.readdir(c,{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:o.join(c,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};
@@ -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`],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
+ 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 r from"node:path";import{createWriteStream as i,promises as a}from"node:fs";import o from"node:os";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 a.mkdtemp(r.join(o.tmpdir(),`agent-device-source-`));try{return{localPath:await g(n,e.url,e.headers,t),cleanup:async()=>{await a.rm(n,{recursive:!0,force:!0})}}}catch(e){throw await a.rm(n,{recursive:!0,force:!0}),e}}async function g(t,n,a,o){let l;try{l=new URL(n)}catch{throw new e(`INVALID_ARGS`,`Invalid source URL: ${n}`)}await _(l);let u=o?.signal;if(u?.aborted)throw new e(`COMMAND_FAILED`,`request canceled`,{reason:`request_canceled`});let d=o?.downloadTimeoutMs??12e4,f=AbortSignal.timeout(d),p=u?AbortSignal.any([u,f]):f;try{let n=await fetch(l,{headers:a,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 o=x(n,l),u=r.join(t,o),d=n.body;if(!d)throw new e(`COMMAND_FAILED`,`Download response body was empty`,{url:l.toString()});return await s(c.fromWeb(d),i(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?r.basename(n):r.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 a.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=[],i=[{path:e,depth:0}];for(;i.length>0;){let e=i.shift();if(!e)continue;let o=await a.readdir(e.path,{withFileTypes:!0});o.sort((e,t)=>e.name.localeCompare(t.name));for(let a of o){let o=r.join(e.path,a.name);if(t(o,a)){n.push(o);continue}a.isDirectory()&&e.depth<5&&i.push({path:o,depth:e.depth+1})}}return n}async function O(e){let n=await a.mkdtemp(r.join(o.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 a.rm(n,{recursive:!0,force:!0})}}}catch(e){throw await a.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{J as t,X as n,ot as r}from"./snapshot-diagnostics.js";import{_ as i}from"./gesture-plan-types.js";import{a}from"./input-actions.js";import{Ct as o,Gt as s,Kt as c,Xt as l,Yt as u,jt as d,qt as f,wt as p,zt as m}from"./internal/daemon.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:d,flags:p,result:m,responseData:g,recordedTarget:v,actionStartedAt:y,actionFinishedAt:b,androidFreshnessBaseline:x}=e,S=f(p),[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}:{}}),c({session:t,command:r,positionals:d??i,flags:p,preSnapshot:t.snapshot}),u(a)&&l(t,a,x??t.snapshot),s(t,a,d??i,p),o(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:o}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if(t.device.platform===`android`){let e=await a(t.device),n={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=n),n}let s=p(t.snapshot);if(s)return t.recording&&(t.recording.touchReferenceFrame=s),s;if(!t.recording)return;let c=p(await o(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 p({nodes:e,createdAt:0})}async function x(e,t,n,r,a){let o={...t??{},snapshotInteractiveOnly:a.interactiveOnly},s=r(o,e.appBundleId,e.trace?.outPath),{snapshot:c}=await m({device:e.device,session:e,flags:o,outPath:o.out,logPath:s.logPath??``,includeRects:a.includeRects,androidFreshnessMode:a.androidFreshnessMode});return i(c.snapshotQuality)||(d(e,c),n.set(e.name,e)),c}export{g as i,b as n,y as r,x as t};
1
+ import{M as e}from"./viewport-dimension.js";import{I as t,P as n,R as r}from"./screenshot-result.js";import{j as i}from"./sdk-android-adb.js";import{a}from"./input-actions.js";import{It as o,Lt as s,Qt as c,Wt as l,in as u,nn as d,on as f,rn as p,sn as m}from"./internal/daemon.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:s,flags:c,result:l,responseData:g,recordedTarget:v,actionStartedAt:y,actionFinishedAt:b,androidFreshnessBaseline:x}=e,S=u(c),[C,w]=_({command:r,positionals:i,flags:S,result:l,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:s??i,flags:c,preSnapshot:t.snapshot}),f(a)&&m(t,a,x??t.snapshot),d(t,a,s??i,c),o(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=t(e.flags.recordAs);return[n(e.result,i,a),n(e.responseData,i,a)]}async function v(e){let{session:t,flags:n,sessionStore:r,contextFromFlags:i,captureSnapshotForSession:o}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if(t.device.platform===`android`){let e=await a(t.device),n={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=n),n}let c=s(t.snapshot);if(c)return t.recording&&(t.recording.touchReferenceFrame=c),c;if(!t.recording)return;let l=s(await o(t,n,r,i,{interactiveOnly:!0}));return l&&t.recording&&(t.recording.touchReferenceFrame=l),l}async function y(e){try{return await v(e)}catch(t){i({level:`warn`,phase:`touch_reference_frame_resolve_failed`,data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function b(e){return s({nodes:e,createdAt:0})}async function x(t,n,r,i,a){let o={...n??{},snapshotInteractiveOnly:a.interactiveOnly},s=i(o,t.appBundleId,t.trace?.outPath),{snapshot:u}=await c({device:t.device,session:t,flags:o,outPath:o.out,logPath:s.logPath??``,includeRects:a.includeRects,androidFreshnessMode:a.androidFreshnessMode,signal:a.signal});return e(u.snapshotQuality)||(l(t,u),r.set(t.name,t)),u}export{g as i,b as n,y as r,x as t};
@@ -1,6 +1,9 @@
1
- import { A as SnapshotNode, h as ResponseCost } from "./sdk-contracts.js";
2
- import { t as ClickButton } from "./click-button.js";
3
- //#region src/contracts/interaction.d.ts
1
+ import { A as SnapshotNode, m as ResponseCost } from "./sdk-contracts.js";
2
+ //#region packages/contracts/src/click-button.d.ts
3
+ declare const CLICK_BUTTONS: readonly ['primary', 'secondary', 'middle'];
4
+ type ClickButton = (typeof CLICK_BUTTONS)[number];
5
+ //#endregion
6
+ //#region packages/contracts/src/interaction.d.ts
4
7
  /** The decisive criterion separating a resolveSelectorChain winner from its strongest runner-up (ADR 0012). */
5
8
  type DisambiguationTiebreak = 'visible' | 'deepest' | 'smallest-area';
6
9
  /**
@@ -224,4 +227,4 @@ type FindCommandResponseData = {
224
227
  cost?: ResponseCost;
225
228
  };
226
229
  //#endregion
227
- export { LongPressCommandResponseData as a, FindCommandResponseData as i, DisambiguationTiebreak as n, PressCommandResponseData as o, FillCommandResponseData as r, ClickCommandResponseData as t };
230
+ export { LongPressCommandResponseData as a, FindCommandResponseData as i, DisambiguationTiebreak as n, PressCommandResponseData as o, FillCommandResponseData as r, ClickButton as s, ClickCommandResponseData as t };
@@ -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,O as a,P as o,k as s}from"./sdk-batch-runner.js";import{On as c,c as l,d as u,dn as d,f,g as p,jt as m,ln as ee,p as h,un as te,vn as g}from"./recording-export-quality.js";import{Z as _}from"./snapshot-diagnostics.js";import{c as v,h as y,o as ne}from"./sdk-device.js";import{F as re,N as ie}from"./gesture-plan-types.js";import{t as ae}from"./timeouts.js";import{t as oe}from"./runtime.js";import"./gesture-plan.js";import{C as se,c as b,f as x,i as ce,l as S,n as C,o as le,r as ue,s as w}from"./context.js";import{At as T,Dt as de,Et as E,Ft as D,Jt as fe,Lt as pe,Ot as me,Pt as he,Rt as ge,jt as _e,kt as ve,m as ye}from"./internal/daemon.js";import{_ as O,c as be,d as xe,f as Se,g as k,h as Ce,l as we,m as Te,n as Ee,o as De,p as Oe,r as ke,s as Ae,u as je,v as Me,y as A}from"./selector-runtime.js";import{i as j,n as M,r as Ne,t as N}from"./interaction-snapshot.js";const Pe=new Set(s());function Fe(e){return Le({fields:Ie(e.command),input:e.input??{},data:e.data,controlledFields:Pe})}function Ie(e){let t=o(e);if(!t)throw Error(`Missing response data transform descriptor for ${e}`);return t.fields}function Le(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 Re=new Set([`currentUptimeMs`,`gestureEndUptimeMs`,`gestureStartUptimeMs`,`sequenceResults`]);function ze(e){if(e)return Object.fromEntries(Object.entries(e).filter(([e])=>!Re.has(e)))}const Be={source:`direct-ios`,kind:`not-observed`};function P(e){let{source:t,referenceFrame:n,extra:r}=e;if(t.kind===`runner-payload`){let e={targetKind:t.targetKind,...t.maestroFallbackUsed?{}:{resolution:Be},...r??{}};return{result:I({data:t.data,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e}),responseData:I({data:t.publicData,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e})}}let{result:i}=t,a=Se(i),o={targetKind:i.kind,...a,...Ue(i.settle,e.settleRefsGeneration),...r??{}},s=I({data:i.backendResult,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:{...o,...He(i)}}),c=I({data:t.publicData,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),l=We(`warning`in i?i.warning:void 0,e.staleRefsWarning);return l&&(s.warning=l,c.warning=l),{result:s,responseData:c,...Ve(i)}}function Ve(e){let t=F(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 He(e){let t=F(e);return t?{selectorChain:t.selectorChain,refLabel:t.refLabel}:{}}function F(e){return`recordingTarget`in e?e.recordingTarget:void 0}function Ue(e,t){return!e?.diff||t===void 0?{}:{settle:{...e,refsGeneration:t}}}function We(e,t){return t?e?`${e} ${t}`:t:e}function I(e){let{data:t,fallbackX:n,fallbackY:r,referenceFrame:i,extra:a}=e,o=Ke(a,n,r)??(typeof t?.message==`string`?t.message:void 0);return Ge({...t??{},...n===void 0||r===void 0?{}:{x:n,y:r},...i??{},...a??{},...g(o)})}function Ge(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function Ke(e,t,n){let r=L(e,`text`);if(r!==void 0)return`Filled ${Array.from(r).length} chars`;let i=qe(t,n),a=Je(e);if(a)return Xe(a,e??{},i);if(i)return Ye(e,i)}function L(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}function qe(e,t){return e===void 0||t===void 0?``:` (${e}, ${t})`}function Je(e){let t=L(e,`ref`);return t===void 0?L(e,`selector`):`@${t}`}function Ye(e,t){return e?.gesture===`longpress`?`Long pressed${t}`:`Tapped${t}`}function Xe(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 R(e,t){return!v(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 z(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new t(`SESSION_NOT_FOUND`,le);return oe({backend:Ze({...e,session:n}),...De(`interaction commands`,{plural:!0}),sessions:me({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0,omitRefFrameSnapshot:e.req.internal?.findResolvedTarget===!0},setRecord:t=>{t.snapshot&&(_e(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function Ze(e){let{req:t,session:n}=e,r=Qe(n);return{platform:y(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 ce(n.device,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)),tap:async(r,i)=>(D(n),B(await C(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)=>(D(n),await r.clickRef?.(t.ref),{ref:k(t.ref)}):void 0,fill:async(r,i,a)=>(D(n),B(await C(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)=>(D(n),await r.fillRef?.(t.ref,i,a),{ref:k(t.ref),text:i,delayMs:a?.delayMs??0}):void 0,longPress:async(r,i,a)=>(D(n),B(await C(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)=>(D(n),B(await ue(n.device,i,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))),typeText:async(r,i)=>(D(n),B(await C(n.device,`type`,[i],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))))}}function Qe(e){if(e.device.platform!==`web`)return;let t=ye();return t.clickRef||t.fillRef?t:void 0}function B(e){return e&&typeof e==`object`?e:void 0}function V(e){let t=e.ref.startsWith(`@`)?e.ref.slice(1):e.ref,n=he({session:e.session,refBody:t,mintedGeneration:e.mintedGeneration});if(n.admitted)return null;let r=ge(e.session);return w(`COMMAND_FAILED`,et(n.reason,e.ref),{reason:n.reason,ref:e.ref,currentGeneration:pe(e.session),scope:r===`all`?`all`:Array.from(r),...e.mintedGeneration===void 0?{}:{mintedGeneration:e.mintedGeneration},hint:e.staleRefsWarning??$e})}const $e=`Capture a fresh interactive snapshot (snapshot -i) or use a stable selector, then retry.`;function et(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 tt(e){let n=e.flags?.recordAs;if(n!==void 0){if(_(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 nt(e){switch(e.req.command){case`press`:return await H(e,`press`);case`click`:return await H(e,`click`);case`longpress`:return await H(e,`longpress`);case`fill`:return await mt(e);default:return null}}async function H(e,t){let{req:n,sessionName:r,sessionStore:i}=e,a=i.get(r);if(!a)return b();let o=t===`click`?`click`:t,s=t===`longpress`?`longpress`:`press`,c=R(a,o);if(c)return c;let l=S(s,a.device);if(l)return l;let u=A(t,n.flags);if(u)return u;let f=d(n.flags),p=ee(f);if(t!==`longpress`&&f!==`primary`){let e=te({commandLabel:o,platform:y(a.device),button:f,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 m=t===`longpress`?Te(n.positionals??[]):Ce(n.positionals??[],o);if(!m.ok)return m.response;let h=m.target.kind===`ref`&&n.internal?.findResolvedTarget!==!0?T({session:a,ref:m.target.ref,mintedGeneration:m.refGeneration}):void 0,g;if(m.target.kind===`ref`){let r=e.refSnapshotFlagGuardResponse(t===`longpress`?`longpress`:`press`,n.flags);if(r)return r;let i=n.internal?.findResolvedTarget?null:V({session:a,ref:m.target.ref,mintedGeneration:m.refGeneration,staleRefsWarning:h});if(i)return i;g=await J(e,a)}let _=n.internal?.replayTargetGuard,v=_?null:st({session:a,commandLabel:o,target:m.target,flags:n.flags});if(v){let t=await lt(e,a,v);if(t)return t}let ne=t===`longpress`?m.durationMs:void 0;return await q(e,{androidFreshnessBaseline:g,refContext:m.target.kind===`ref`&&n.internal?.findResolvedTarget!==!0?{ref:m.target.ref,mintedGeneration:m.refGeneration,staleRefsWarning:h}:void 0,run:async e=>await rt({runtime:e,command:t,target:m.target,sessionName:r,requestId:n.meta?.requestId,clickButton:f,flags:n.flags,durationMs:ne,expectedResolvedTarget:_}),afterRun:async e=>{a.lease?.leaseProvider||await we(a,xe(m.target,e))},buildPayloads:async r=>{let i=ot(r);return await it({params:e,session:a,result:r,staleRefsWarning:h,publicData:K({session:a,command:t===`longpress`?void 0:t,flags:n.flags,data:r.backendResult}),extra:t===`longpress`?{...i===void 0?{}:{durationMs:i},gesture:`longpress`}:p})}})}async function rt(e){let{runtime:t,command:n,target:r,sessionName:i,requestId:a,flags:o,expectedResolvedTarget:s}=e,c=O(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 it(e){let{params:t,session:n,result:r,publicData:i,extra:a}=e,o=r.kind===`point`?await Ne({session:n,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):M(n.snapshot?.nodes??[]);return P({source:{kind:`runtime`,result:r,publicData:i},referenceFrame:o,extra:a,staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:U(n,r)})}function U(e,t){if(t.settle?.diff)return ve(e,at(t.settle)),e.snapshotGeneration}function at(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 ot(e){return`durationMs`in e?e.durationMs:void 0}function st(e){let{session:t,commandLabel:n,target:r,flags:o}=e;return n!==`click`||r.kind!==`selector`||t.recordSession||ct(o)||a(n)&&o?.verify===!0||i(n)&&o?.settle===!0?null:W(t,r.selector,o)}function W(e,t,n){let r=be({session:e,selectorExpression:t});return r?{...r,...n?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{},...n?.maestro?.expectedTapPoint?{expectedPoint:n.maestro.expectedTapPoint}:{}}:null}function ct(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 lt(e,t,n){return await G({params:e,session:t,selector:n,command:`press`,positionals:[],extra:{selector:n.raw},fallbackPhase:`ios_direct_selector_tap_fallback`})}async function G(t){let{params:n,session:i,selector:a,command:o,positionals:s,extra:c,fallbackPhase:l}=t,u=Date.now();D(i);try{let e=await C(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=ft(e),l=K({session:i,command:ut(n.req.command,o),flags:n.req.flags,data:e}),d=dt(a,e),{result:f,responseData:p}=P({source:{kind:`runner-payload`,targetKind:`selector`,data:e,publicData:l,point:r,maestroFallbackUsed:d.maestroNonHittableCoordinateFallbackUsed===!0},referenceFrame:pt(e),extra:{...c,...d}});return j({session:i,sessionStore:n.sessionStore,command:n.req.command,positionals:n.req.positionals??[],retryPositionals:Y(r),flags:n.req.flags,result:f,responseData:p,actionStartedAt:u,actionFinishedAt:t})}catch(t){return Ae(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 K(e){let t=ne(e.session.device.platform)?ze(e.data):e.data;return e.command?Fe({command:e.command,input:e.flags,data:t}):t}function ut(e,t){return e===`click`||e===`press`||e===`fill`?e:t}function dt(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let n=t.maestroNonHittableCoordinateFallbackUsed===!0;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:n,...n?{maestroFallbackReason:`non-hittable-coordinate`}:{}}}function ft(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 pt(e){return typeof e.referenceWidth==`number`&&typeof e.referenceHeight==`number`?{referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight}:void 0}async function mt(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n);if(i){let e=R(i,`fill`);if(e)return e;let t=S(`fill`,i.device);if(t)return t}if(!i)return b();tt({session:i,flags:t.flags,replayPlanStep:t.internal?.replayPlanStep===!0});let a=A(`fill`,t.flags);if(a)return a;let o=Oe(t.positionals??[]);if(!o.ok)return o.response;let s=await ht(e,i,o.target,o.refGeneration);if(s.response)return s.response;let{staleRefsWarning:c}=s,l=t.internal?.replayTargetGuard;return(l?null:await gt(e,i,o.target,o.text))||await q(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:O(t.flags),expectedResolvedTarget:l}),buildPayloads:e=>_t({session:i,result:e,text:o.text,flags:t.flags,staleRefsWarning:c})})}async function ht(e,t,n,r){if(n.kind!==`ref`)return{};let i=e.req.internal?.findResolvedTarget===!0?void 0:T({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:V({session:t,ref:n.ref,mintedGeneration:r,staleRefsWarning:i});return o?{response:o,staleRefsWarning:i}:(await J(e,t),{staleRefsWarning:i})}async function gt(e,t,n,r){let i=vt({session:t,target:n,flags:e.req.flags});return i?await yt(e,t,i,r):null}function _t(e){let{session:t,result:n}=e,r=n.kind===`point`?void 0:M(t.snapshot?.nodes??[]);return P({source:{kind:`runtime`,result:n,publicData:K({session:t,command:`fill`,flags:e.flags,data:n.backendResult})},referenceFrame:r,extra:{text:e.text},staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:U(t,n)})}function vt(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:W(t,n.selector,r)}async function yt(e,t,n,r){return await G({params:e,session:t,selector:n,command:`fill`,positionals:[r],extra:{selector:n.raw,text:r},fallbackPhase:`ios_direct_selector_fill_fallback`})}async function q(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return b();let i=z(e),a=Date.now();try{let n=await bt(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 j({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:St(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(je(t))throw t;return xt(e)}}async function bt(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=V({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 J(e,t){if(!fe(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 xt(t){return{ok:!1,error:e(t)}}function St(e,t){if(!(t.kind===`ref`&&!t.node)&&(e===`click`||e===`press`))return t.point?Y(t.point):void 0}function Y(e){return[String(e.x),String(e.y)]}async function Ct(e){return await Z(e,`gesture`,async t=>{let n=p(e.req.input),r=f(n);r.gesture.intent===`pan`&&e.req.internal?.gestureExecutionProfile&&(r.gesture.executionProfile=e.req.internal.gestureExecutionProfile),x(r.gesture,t.device);let i=await X(e).interactions.gesture({session:e.sessionName,requestId:e.req.meta?.requestId,gesture:r.gesture});return{positionals:u(n),flags:jt(n,e.req.flags),responseData:Q(i,{executionProfile:Tt(r.gesture)}),...n.kind===`pinch`?{recordingResultExtra:{scale:n.scale}}:{}}})}async function wt(e){return await Z(e,`swipe`,async t=>{let n=Et(e.req.input);x(h(n).gesture,t.device);let r=n.count??1,i=n.pauseMs??0,a=n.pattern??`one-way`,o=await kt(X(e),e,n,r,i,a);return{positionals:Ot(n),flags:e.req.flags,responseData:Q(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 X(e){return z({...e,pairedGestureViewport:e.req.internal?.gestureViewport})}async function Z(t,n,r){let i=t.sessionStore.get(t.sessionName);if(!i)return b();let a=Date.now();try{let e=se(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}`),j({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 Tt(e){if(e.intent===`fling`)return`endpoint-hold`;if(e.intent===`pan`)return e.executionProfile??`timed-pan`}function Q(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 Et(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`swipe requires structured object input`);l(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:$(n.from,`swipe from`),to:$(n.to,`swipe to`),count:m(n,`count`,{min:1,max:200}),pauseMs:m(n,`pauseMs`,{min:0,max:ie}),pattern:r};return Dt(i),i}function Dt(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 ${re}ms.`,{count:n,pauseMs:r,gestureDurationMs:100,scheduledDurationMs:i,hint:`Reduce --count or --pause-ms.`})}function $(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=h(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 ae(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 nt({...e,captureSnapshotForSession:N,refSnapshotFlagGuardResponse:Me});if(t)return t;switch(e.req.command){case c.gesture:return await Ct({...e,captureSnapshotForSession:N});case c.swipe:return await wt({...e,captureSnapshotForSession:N});case c.type:return await Nt({...e,captureSnapshotForSession:N});case`get`:return await Ee(e);case`is`:return await ke(e);default:return null}}async function Nt(e){let{sessionName:t,sessionStore:n}=e,r=n.get(t);return r?S(c.type,r.device)||await Pt(r)||await Ft(e,r):b()}async function Pt(e){return e.device.platform===`android`&&e.recording&&(await de({session:e})).status===`failed`?w(`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=z(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,...g(t.message??`Typed ${Array.from(t.text).length} chars`)};return e.status===`recovered`&&(u.warning=e.warning),j({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};
1
+ import{S as e,_ as t,v as n}from"./sdk-contracts.js";import{Ht as r,rn as i}from"./viewport-dimension.js";import{D as a,G as o,I as s,K as c,M as l,O as u,R as d,T as f,k as p,q as ee}from"./screenshot-geometry.js";import{_ as m,u as h,v as g,w as _,y as v}from"./sdk-batch-runner.js";import{L as y}from"./screenshot-result.js";import{c as b,h as x,o as te}from"./sdk-device.js";import{q as ne}from"./sdk-selectors.js";import{t as re}from"./runtime.js";import{j as S}from"./sdk-android-adb.js";import{t as ie}from"./timeouts.js";import{j as ae}from"./runner-disposal.js";import{S as oe,c as C,f as w,i as se,l as T,n as E,o as ce,r as le,s as D}from"./context.js";import{Bt as ue,Ht as de,Jt as O,Ut as k,Vt as fe,Wt as pe,Xt as me,Zt as he,an as ge,m as _e,qt as ve,u as ye,zt as A}from"./internal/daemon.js";import{S as j,_ as be,a as xe,b as M,c as Se,d as Ce,f as we,g as Te,h as Ee,l as De,m as Oe,n as ke,p as Ae,r as je,s as Me,u as Ne,v as Pe,x as Fe,y as N}from"./selector-runtime.js";import{i as P,n as F,r as Ie,t as I}from"./interaction-snapshot.js";const Le=new Set(v());function Re(e){return Be({fields:ze(e.command),input:e.input??{},data:e.data,controlledFields:Le})}function ze(e){let t=_(e);if(!t)throw Error(`Missing response data transform descriptor for ${e}`);return t.fields}function Be(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 Ve=new Set([`currentUptimeMs`,`gestureEndUptimeMs`,`gestureStartUptimeMs`,`sequenceResults`]);function He(e){if(e)return Object.fromEntries(Object.entries(e).filter(([e])=>!Ve.has(e)))}function Ue(e){let n=e.flags?.recordAs;if(n!==void 0){if(y(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.`)}}function L(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=he(e.session);return D(`COMMAND_FAILED`,Ge(n.reason,e.ref),{reason:n.reason,ref:e.ref,currentGeneration:me(e.session),scope:r===`all`?`all`:Array.from(r),...e.mintedGeneration===void 0?{}:{mintedGeneration:e.mintedGeneration},hint:e.staleRefsWarning??We})}const We=`Capture a fresh interactive snapshot (snapshot -i) or use a stable selector, then retry.`;function Ge(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`}}async function Ke(e){let{session:t,node:n,rootViewport:r,requestOptions:i}=e,a=Se(n);if(!a)return null;let o;try{o=await xe(t,a,i)}catch{return null}if(!o.found||!o.node?.rect)return null;let s={rect:o.node.rect,hittable:o.node.hittable===!0};return ne(s,r)?s.rect:null}function R(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new t(`SESSION_NOT_FOUND`,ce);return re({backend:qe({...e,session:n}),...Me(`interaction commands`,{plural:!0}),sessions:fe({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0,omitRefFrameSnapshot:e.req.internal?.findResolvedTarget===!0},setRecord:t=>{t.snapshot&&(pe(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}}),signal:ae(e.req.meta?.requestId)})}function qe(e){let{req:t,session:n}=e,r=Je(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,signal:r.signal})}),resolveGestureViewport:async()=>e.pairedGestureViewport??await se(n.device,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)),confirmOffscreenTargetVisible:Ne(n,{skipPendingPostGestureStabilization:!1})?async(r,i,a)=>await Ke({session:n,node:i,rootViewport:a,requestOptions:ye({req:t,logPath:e.logPath,traceLogPath:n.trace?.outPath})}):void 0,tap:async(r,i)=>(O(n),z(await E(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:N(t.ref)}):void 0,fill:async(r,i,a)=>(O(n),z(await E(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:N(t.ref),text:i,delayMs:a?.delayMs??0}):void 0,longPress:async(r,i,a)=>(O(n),z(await E(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),z(await le(n.device,i,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))),typeText:async(r,i)=>(O(n),z(await E(n.device,`type`,[i],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))))}}function Je(e){if(e.device.platform!==`web`)return;let t=_e();return t.clickRef||t.fillRef?t:void 0}function z(e){return e&&typeof e==`object`?e:void 0}function B(e,t){return!b(e.device)||e.surface!==`desktop`&&e.surface!==`menubar`||e.surface===`menubar`&&(t===`click`||t===`press`)?null:D(`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.`)}const Ye={source:`direct-ios`,kind:`not-observed`};function V(e){let{source:t,referenceFrame:n,extra:r}=e;if(t.kind===`runner-payload`){let e={targetKind:t.targetKind,...t.maestroFallbackUsed?{}:{resolution:Ye},...r??{}};return{result:U({data:t.data,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e}),responseData:U({data:t.publicData,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e})}}let{result:i}=t,a=Ee(i),o={targetKind:i.kind,...a,...Qe(i.settle,e.settleRefsGeneration),...r??{}},s=U({data:i.backendResult,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:{...o,...Ze(i)}}),c=U({data:t.publicData,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),l=$e(`warning`in i?i.warning:void 0,e.staleRefsWarning);return l&&(s.warning=l,c.warning=l),{result:s,responseData:c,...Xe(i)}}function Xe(e){let t=H(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 Ze(e){let t=H(e);return t?{selectorChain:t.selectorChain,refLabel:t.refLabel}:{}}function H(e){return`recordingTarget`in e?e.recordingTarget:void 0}function Qe(e,t){return!e?.diff||t===void 0?{}:{settle:{...e,refsGeneration:t}}}function $e(e,t){return t?e?`${e} ${t}`:t:e}function U(e){let{data:t,fallbackX:n,fallbackY:r,referenceFrame:a,extra:o}=e,s=tt(o,n,r)??(typeof t?.message==`string`?t.message:void 0);return et({...t??{},...n===void 0||r===void 0?{}:{x:n,y:r},...a??{},...o??{},...i(s)})}function et(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function tt(e,t,n){let r=W(e,`text`);if(r!==void 0)return`Filled ${Array.from(r).length} chars`;let i=nt(t,n),a=rt(e);if(a)return at(a,e??{},i);if(i)return it(e,i)}function W(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}function nt(e,t){return e===void 0||t===void 0?``:` (${e}, ${t})`}function rt(e){let t=W(e,`ref`);return t===void 0?W(e,`selector`):`@${t}`}function it(e,t){return e?.gesture===`longpress`?`Long pressed${t}`:`Tapped${t}`}function at(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}`}async function ot(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 vt(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 s=t===`click`?`click`:t,l=t===`longpress`?`longpress`:`press`,u=B(a,s);if(u)return u;let d=T(l,a.device);if(d)return d;let f=j(t,n.flags);if(f)return f;let p=ee(n.flags),m=o(p);if(t!==`longpress`&&p!==`primary`){let e=c({commandLabel:s,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 D(e.code,e.message,e.details)}let h=t===`longpress`?be(n.positionals??[]):Pe(n.positionals??[],s);if(!h.ok)return h.response;let g=h.target.kind===`ref`&&n.internal?.findResolvedTarget!==!0?k({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:L({session:a,ref:h.target.ref,mintedGeneration:h.refGeneration,staleRefsWarning:g});if(i)return i;_=await Z(e,a)}let v=n.internal?.replayTargetGuard,y=v?null:dt({session:a,commandLabel:s,target:h.target,flags:n.flags});if(y){let t=await pt(e,a,y);if(t)return t}let b=t===`longpress`?h.durationMs:void 0;return await X(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 st({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=>{if(!a.lease?.leaseProvider)return await we(a,Oe(h.target,e))},buildPayloads:async r=>{let i=ut(r);return await ct({params:e,session:a,result:r,staleRefsWarning:g,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`}:m})}})}async function st(e){let{runtime:t,command:n,target:r,sessionName:i,requestId:a,flags:o,expectedResolvedTarget:s}=e,c=M(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 ct(e){let{params:t,session:n,result:r,publicData:i,extra:a}=e,o=r.kind===`point`?await Ie({session:n,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):F(n.snapshot?.nodes??[]);return V({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 de(e,lt(t.settle)),e.snapshotGeneration}function lt(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 ut(e){return`durationMs`in e?e.durationMs:void 0}function dt(e){let{session:t,commandLabel:n,target:r,flags:i}=e;return n!==`click`||r.kind!==`selector`||t.recordSession||ft(i)||g(n)&&i?.verify===!0||m(n)&&i?.settle===!0?null:q(t,r.selector,i)}function q(e,t,n){let r=Ce({session:e,selectorExpression:t});return r?{...r,...n?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{},...n?.maestro?.expectedTapPoint?{expectedPoint:n.maestro.expectedTapPoint}:{}}:null}function ft(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 pt(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:r,selector:i,command:a,positionals:o,extra:s,fallbackPhase:c}=t,l=Date.now();O(r);try{let e=await E(r.device,a,o,n.req.flags?.out,{...n.contextFromFlags(n.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:i,surface:r.surface})??{},t=Date.now(),c=gt(e),u=Y({session:r,command:mt(n.req.command,a),flags:n.req.flags,data:e}),d=ht(i,e),{result:f,responseData:p}=V({source:{kind:`runner-payload`,targetKind:`selector`,data:e,publicData:u,point:c,maestroFallbackUsed:d.maestroNonHittableCoordinateFallbackUsed===!0},referenceFrame:_t(e),extra:{...s,...d}});return P({session:r,sessionStore:n.sessionStore,command:n.req.command,positionals:n.req.positionals??[],retryPositionals:Q(c),flags:n.req.flags,result:f,responseData:p,actionStartedAt:l,actionFinishedAt:t})}catch(t){return De(t,{delegateSemanticFailures:i.allowNonHittableCoordinateFallback!==!0})?(S({level:`debug`,phase:c,data:{selector:i.raw,error:t instanceof Error?t.message:String(t)}}),null):{ok:!1,error:e(t)}}}function Y(e){let t=te(e.session.device.platform)?He(e.data):e.data;return e.command?Re({command:e.command,input:e.flags,data:t}):t}function mt(e,t){return e===`click`||e===`press`||e===`fill`?e:t}function ht(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let n=t.maestroNonHittableCoordinateFallbackUsed===!0;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:n,...n?{maestroFallbackReason:`non-hittable-coordinate`}:{}}}function gt(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 _t(e){return typeof e.referenceWidth==`number`&&typeof e.referenceHeight==`number`?{referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight}:void 0}async function vt(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n);if(i){let e=B(i,`fill`);if(e)return e;let t=T(`fill`,i.device);if(t)return t}if(!i)return C();Ue({session:i,flags:t.flags,replayPlanStep:t.internal?.replayPlanStep===!0});let a=j(`fill`,t.flags);if(a)return a;let o=Te(t.positionals??[]);if(!o.ok)return o.response;let s=await yt(e,i,o.target,o.refGeneration);if(s.response)return s.response;let{staleRefsWarning:c}=s,l=t.internal?.replayTargetGuard;return(l?null:await bt(e,i,o.target,o.text))||await X(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:M(t.flags),expectedResolvedTarget:l}),buildPayloads:e=>xt({session:i,result:e,text:o.text,flags:t.flags,staleRefsWarning:c})})}async function yt(e,t,n,r){if(n.kind!==`ref`)return{};let i=e.req.internal?.findResolvedTarget===!0?void 0:k({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:L({session:t,ref:n.ref,mintedGeneration:r,staleRefsWarning:i});return o?{response:o,staleRefsWarning:i}:(await Z(e,t),{staleRefsWarning:i})}async function bt(e,t,n,r){let i=St({session:t,target:n,flags:e.req.flags});return i?await Ct(e,t,i,r):null}function xt(e){let{session:t,result:n}=e,r=n.kind===`point`?void 0:F(t.snapshot?.nodes??[]);return V({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 St(e){let{session:t,target:n,flags:r}=e;return n.kind!==`selector`||t.recordSession||g(`fill`)&&r?.verify===!0||m(`fill`)&&r?.settle===!0?null:q(t,n.selector,r)}async function Ct(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=R(e),a=Date.now();try{let n,o=await wt(r,e.req.command,{refContext:t.refContext},async()=>{let e=await t.run(i);return n=await t.afterRun?.(e),e});if(o.aborted)return o.response;let{readiness:s,runtimeResult:c}=o,l=Date.now(),{result:u,responseData:d,recordedTarget:f}=await t.buildPayloads(c),p=[...s.status===`recovered`?[s.warning]:[],...n?[n]:[]];if(p.length>0){let e=[...typeof d.warning==`string`?[d.warning]:[],...p].join(` `);u.warning=e,d.warning=e}return P({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:Et(e.req.command,c),flags:e.req.flags,result:u,responseData:d,recordedTarget:f,actionStartedAt:a,actionFinishedAt:l,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(e){let t=n(e);if(Ae(t))throw t;return Tt(e)}}async function wt(e,t,n,r){if(e.lease?.leaseProvider)return{aborted:!1,readiness:{status:`clear`},runtimeResult:await r()};let i=await A({session:e,command:t,phase:`before-command`});if(n.refContext&&i.status===`recovered`){let t=L({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 A({session:e,command:t,phase:`after-command`}),{aborted:!1,readiness:i,runtimeResult:a}}async function Z(e,t){if(!ge(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){S({level:`warn`,phase:`android_ref_snapshot_refresh_failed`,data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return n}function Tt(t){return{ok:!1,error:e(t)}}function Et(e,t){if(!(t.kind===`ref`&&!t.node)&&(e===`click`||e===`press`))return t.point?Q(t.point):void 0}function Q(e){return[String(e.x),String(e.y)]}async function Dt(e){return await kt(e,`gesture`,async t=>{let n=l(e.req.input),r=u(n);r.gesture.intent===`pan`&&e.req.internal?.gestureExecutionProfile&&(r.gesture.executionProfile=e.req.internal.gestureExecutionProfile),w(r.gesture,t.device);let i=await $(e).interactions.gesture({session:e.sessionName,requestId:e.req.meta?.requestId,gesture:r.gesture});return{positionals:a(n),flags:Rt(n,e.req.flags),responseData:jt(i,{executionProfile:At(r.gesture)}),...n.kind===`pinch`?{recordingResultExtra:{scale:n.scale}}:{}}})}async function Ot(e){return await kt(e,`swipe`,async t=>{let n=Mt(e.req.input);w(p(n).gesture,t.device);let r=n.count??1,i=n.pauseMs??0,a=n.pattern??`one-way`,o=await It($(e),e,n,r,i,a);return{positionals:Ft(n),flags:e.req.flags,responseData:jt(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 $(e){return R({...e,pairedGestureViewport:e.req.internal?.gestureViewport})}async function kt(t,n,r){let i=t.sessionStore.get(t.sessionName);if(!i)return C();let a=Date.now();try{let e=oe(i.device),o=e?{status:`clear`}:await A({session:i,command:n,phase:`before-command`}),s=await r(i);e||await A({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}`),P({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 At(e){if(e.intent===`fling`)return`endpoint-hold`;if(e.intent===`pan`)return e.executionProfile??`timed-pan`}function jt(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 Mt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`swipe requires structured object input`);f(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:Pt(n.from,`swipe from`),to:Pt(n.to,`swipe to`),count:h(n,`count`,{min:1,max:200}),pauseMs:h(n,`pauseMs`,{min:0,max:s}),pattern:r};return Nt(i),i}function Nt(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 Pt(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 Ft(e){return[String(e.from.x),String(e.from.y),String(e.to.x),String(e.to.y)]}async function It(e,t,n,r,i,a){let o;for(let s=0;s<r;s+=1){let c=p(Lt(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 ie(i)}if(!o)throw Error(`Swipe orchestration did not execute a gesture.`);return o}function Lt(e,t,n){return t===`ping-pong`&&n%2==1?{...e,from:e.to,to:e.from}:e}function Rt(e,t){return e.kind!==`pan`||e.pointerCount===void 0?t:{...t,pointerCount:e.pointerCount}}async function zt(e){let t=await ot({...e,captureSnapshotForSession:I,refSnapshotFlagGuardResponse:Fe});if(t)return t;switch(e.req.command){case r.gesture:return await Dt({...e,captureSnapshotForSession:I});case r.swipe:return await Ot({...e,captureSnapshotForSession:I});case r.type:return await Bt({...e,captureSnapshotForSession:I});case`get`:return await ke(e);case`is`:return await je(e);default:return null}}async function Bt(e){let{sessionName:t,sessionStore:n}=e,i=n.get(t);return i?T(r.type,i.device)||await Vt(i)||await Ht(e,i):C()}async function Vt(e){return e.device.platform===`android`&&e.recording&&(await ue({session:e})).status===`failed`?D(`COMMAND_FAILED`,`Android system dialog blocked the recording session`):null}async function Ht(t,n){let{req:r,sessionName:a,sessionStore:o}=t,s=(r.positionals??[]).join(` `),c=R(t),l=Date.now();try{let e=await A({session:n,command:r.command,phase:`before-command`}),t=await c.interactions.typeText(s,{session:a,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await A({session:n,command:r.command,phase:`after-command`});let u=Date.now(),d={...t.backendResult??{},text:t.text,delayMs:t.delayMs,...i(t.message??`Typed ${Array.from(t.text).length} chars`)};return e.status===`recovered`&&(d.warning=e.warning),P({session:n,sessionStore:o,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{zt as handleInteractionCommands};
@@ -1,2 +1,2 @@
1
- import{_ as e}from"./sdk-contracts.js";import{I as t}from"./sdk-android-adb.js";import{Q as n,Y as r,on as i}from"./recording-export-quality.js";import{c as a,f as o,s}from"./sdk-device.js";import{D as c,I as l,R as u,y as d}from"./gesture-plan-types.js";import{n as f}from"./gesture-plan.js";import{t as p}from"./method-scope.js";import{t as m}from"./apple-multitouch-support.js";import{o as h}from"./helper.js";import{a as g}from"./runner-client.js";import{i as _}from"./runner-provider.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,n,r={includeDuration:!0}){let i=j(e.referenceWidth),a=j(e.referenceHeight);if(i===void 0||a===void 0)return M(e,{amount:n?.amount});let o=u({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:i,referenceHeight:a});return M(e,{amount:n?.amount,pixels:o.pixels,durationMs:r?.includeDuration?n?.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 g(e,H(e,t,r,i),n),tapElementSelector:async r=>await g(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 g(e,D([{kind:`doubleTap`,x:r,y:i}],t.appBundleId),n);return E(a),a},longPress:async(r,i,a)=>await g(e,{command:`longPress`,x:r,y:i,durationMs:a,appBundleId:t.appBundleId},n),focus:async(r,i)=>await g(e,H(e,t,r,i),n),type:async(r,i)=>{await g(e,{command:`type`,text:r,delayMs:i,textEntryMode:r===`
2
- `?void 0:`append`,appBundleId:t.appBundleId},n)},fillElementSelector:async(r,i,a)=>await g(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 g(e,{command:`type`,x:r,y:i,text:a,delayMs:o,textEntryMode:`replace`,appBundleId:t.appBundleId},n),scroll:async(r,i)=>await W(g,e,t,n,r,i),performGesture:async r=>await B(e,t,n,r),gestureViewport:async()=>R(await g(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`&&m(e,r.intent),r.topology===`single`&&a(e)){let{start:i,end:a}=f(r);return await g(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`&&o(e)){let{start:i,end:a}=f(r);return await g(e,{command:`swipe`,direction:V(i,a),appBundleId:t.appBundleId},n)}return await g(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 s(e)&&!o(e)}async function W(e,t,i,s,c,u){return n(u?.durationMs,{invalidMessage:`scroll durationMs must be a non-negative integer at most ${r}`}),o(t)?M(await e(t,O(c,i.appBundleId,u?.durationMs),s),{amount:u?.amount,durationMs:u?.durationMs}):(l(u??{}),a(t)?await F(e,t,i,s,c,u):k(await e(t,{command:`scroll`,direction:c,...A(u),appBundleId:i.appBundleId},s),c,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:s}=L(n,r),l={open:(e,t)=>C(n,e,{appBundleId:t?.appBundleId,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,terminateRunningApp:t?.terminateRunningApp,url:t?.url,runnerOptions:s}),openDevice:()=>T(n),close:e=>v(n,e,s),screenshot:(e,t)=>Y(n,e,t,s),snapshot:async r=>{let i=Z(await t(`snapshot_capture`,async()=>await g(n,{command:`snapshot`,appBundleId:r?.appBundleId,interactiveOnly:r?.interactiveOnly,depth:r?.depth,scope:r?.scope,raw:r?.raw},s),{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(o(n)){await g(n,O(`menu`,r.appBundleId),s);return}await g(n,{command:I(e),appBundleId:r.appBundleId},s)},home:async()=>{if(o(n)){await g(n,O(`home`,r.appBundleId),s);return}await g(n,{command:`home`,appBundleId:r.appBundleId},s)},setOrientation:async t=>{let i=K(await g(n,{command:`rotate`,orientation:t,appBundleId:r.appBundleId},s));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 g(n,{command:`appSwitcher`,appBundleId:r.appBundleId},s)},tvRemote:async(e,t)=>{await g(n,O(c(e),r.appBundleId,t),s)},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,l,i):l}function K(t){let n=t.orientation;if(typeof n==`string`&&i.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 p({...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=>_(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 h(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 a(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};
1
+ import{_ as e}from"./sdk-contracts.js";import{P as t}from"./viewport-dimension.js";import{V as n,h as r,v as i,w as a,x as o,z as s}from"./screenshot-geometry.js";import{c,f as l,s as u}from"./sdk-device.js";import{_ as d,t as f}from"./device.js";import{I as p}from"./sdk-android-adb.js";import{t as m}from"./method-scope.js";import{o as h}from"./helper.js";import{a as g}from"./runner-client.js";import{i as _}from"./runner-provider.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,r,i={includeDuration:!0}){let a=A(e.referenceWidth),o=A(e.referenceHeight);if(a===void 0||o===void 0)return j(e,{amount:r?.amount});let s=n({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a,referenceHeight:o});return j(e,{amount:r?.amount,pixels:s.pixels,durationMs:i?.includeDuration?r?.durationMs:void 0,preferProvidedPixels:!0})}function k(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 A(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function j(e,t){let{x1:n,y1:r,x2:i,y2:a}=N(e),o=A(e.referenceWidth),s=A(e.referenceHeight),c=M(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 M(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 N(e){let t=A(e.x),n=A(e.y),r=A(e.x2),i=A(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 P(e,t,n,r,i,a){return O(await e(t,{command:`desktopScroll`,direction:i,...k(a,{includeDuration:!0}),appBundleId:n.appBundleId},r),i,a,{includeDuration:!0})}function F(e,t,n){return{command:`remotePress`,remoteButton:e,...n===void 0?{}:{durationMs:n},...t===void 0?{}:{appBundleId:t}}}function I(e){return e===`system`?`backSystem`:`backInApp`}function L(e,t){let n={signal:t.signal,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 g(e,H(e,t,r,i),n),tapElementSelector:async r=>await g(e,{command:`tap`,selectorKey:r.key,selectorValue:r.value,allowNonHittableCoordinateFallback:r.allowNonHittableCoordinateFallback,...r.expectedPoint?{x:r.expectedPoint.x,y:r.expectedPoint.y}:{},...U(e)?{synthesized:!0}:{},appBundleId:t.appBundleId},n),doubleTap:async(r,i)=>{let a=await g(e,D([{kind:`doubleTap`,x:r,y:i}],t.appBundleId),n);return E(a),a},longPress:async(r,i,a)=>await g(e,{command:`longPress`,x:r,y:i,durationMs:a,appBundleId:t.appBundleId},n),focus:async(r,i)=>await g(e,H(e,t,r,i),n),type:async(r,i)=>{await g(e,{command:`type`,text:r,delayMs:i,textEntryMode:r===`
2
+ `?void 0:`append`,appBundleId:t.appBundleId},n)},fillElementSelector:async(r,i,a)=>await g(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 g(e,{command:`type`,x:r,y:i,text:a,delayMs:o,textEntryMode:`replace`,appBundleId:t.appBundleId},n),scroll:async(r,i)=>await W(g,e,t,n,r,i),performGesture:async r=>await B(e,t,n,r),gestureViewport:async()=>R(await g(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`&&d(e,r.intent),r.topology===`single`&&c(e)){let{start:i,end:o}=a(r);return await g(e,{command:`drag`,x:i.x,y:i.y,x2:o.x,y2:o.y,durationMs:r.durationMs,appBundleId:t.appBundleId},n)}if(r.topology===`single`&&l(e)){let{start:i,end:o}=a(r);return await g(e,{command:`swipe`,direction:V(i,o),appBundleId:t.appBundleId},n)}return await g(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,a,u){return o(u?.durationMs,{invalidMessage:`scroll durationMs must be a non-negative integer at most ${i}`}),l(t)?j(await e(t,F(a,n.appBundleId,u?.durationMs),r),{amount:u?.amount,durationMs:u?.durationMs}):(s(u??{}),c(t)?await P(e,t,n,r,a,u):O(await e(t,{command:`scroll`,direction:a,...k(u),appBundleId:n.appBundleId},r),a,u))}function G(t,n,i){if(t.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(t,n),s={open:(e,n)=>C(t,e,{appBundleId:n?.appBundleId,launchConsole:n?.launchConsole,launchArgs:n?.launchArgs,terminateRunningApp:n?.terminateRunningApp,url:n?.url,runnerOptions:o}),openDevice:()=>T(t),close:e=>v(t,e,o),screenshot:(e,n)=>X(t,e,n,o),snapshot:async n=>{let r=Q(await p(`snapshot_capture`,async()=>await g(t,{command:`snapshot`,appBundleId:n?.appBundleId,interactiveOnly:n?.interactiveOnly,depth:n?.depth,scope:n?.scope,raw:n?.raw},K(o,n?.signal)),{backend:`xctest`})),i=r.nodes??[];if(i.length===0&&t.kind===`simulator`)throw new e(`COMMAND_FAILED`,`XCTest snapshot returned 0 nodes on iOS simulator.`);return{nodes:i,truncated:r.truncated??!1,backend:`xctest`,...r.quality?{quality:r.quality}:{},...!r.quality&&r.message?{warnings:[r.message]}:{}}},back:async e=>{if(l(t)){await g(t,F(`menu`,n.appBundleId),o);return}await g(t,{command:I(e),appBundleId:n.appBundleId},o)},home:async()=>{if(l(t)){await g(t,F(`home`,n.appBundleId),o);return}await g(t,{command:`home`,appBundleId:n.appBundleId},o)},setOrientation:async r=>{let i=q(await g(t,{command:`rotate`,orientation:r,appBundleId:n.appBundleId},o));if(i!==r)throw new e(`COMMAND_FAILED`,`iOS runner observed ${i} after requesting ${r}`,{requestedOrientation:r,observedOrientation:i});return{orientation:i}},appSwitcher:async()=>{await g(t,{command:`appSwitcher`,appBundleId:n.appBundleId},o)},tvRemote:async(e,i)=>{await g(t,F(r(e),n.appBundleId,i),o)},readClipboard:()=>w(t),writeClipboard:e=>b(t,e),setSetting:(e,n,r,i)=>S(t,e,n,r,i),...a};return i?J(t,n,s,i):s}function K(e,t){return t?{...e,signal:e.signal?AbortSignal.any([e.signal,t]):t}:e}function q(t){let n=t.orientation;if(typeof n==`string`&&f.includes(n))return n;throw new e(`COMMAND_FAILED`,`iOS runner returned an invalid orientation result`,{orientation:n})}function J(e,t,n,r){return m({...n,open:async()=>Y(`open`),openDevice:async()=>Y(`openDevice`),close:async()=>Y(`close`),screenshot:async()=>Y(`screenshot`),readClipboard:async()=>Y(`readClipboard`),writeClipboard:async()=>Y(`writeClipboard`),setSetting:async()=>Y(`setSetting`)},n=>_(r,{deviceId:e.id,requestId:t.requestId},n))}function Y(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 X(e,t,n={},r){if(Z(e,n.surface)){await h(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 Z(e,t){return c(e)&&t!==void 0&&t!==`app`}function Q(e){return{nodes:Array.isArray(e.nodes)?e.nodes:void 0,truncated:typeof e.truncated==`boolean`?e.truncated:void 0,quality:t(e.snapshotQuality),message:typeof e.message==`string`&&e.message.trim().length>0?e.message:void 0}}export{G as createAppleInteractor};
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{h as t}from"./sdk-android-adb.js";import{O as n}from"./gesture-plan-types.js";import{l as r}from"./install-artifact.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};
1
+ import{_ as e}from"./sdk-contracts.js";import{g as t}from"./screenshot-geometry.js";import{s as n}from"./sdk-batch-runner.js";import{h as r}from"./sdk-android-adb.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,t){r(await a().launchApp(e.id,t,o),`Failed to launch Vega app ${t}`,{appName:t,deviceId:e.id})}async function c(e){r(await a().checkConnected(e.id,o),`Vega device is not connected`,{deviceId:e.id})}async function l(e,t){r(await a().terminateApp(e.id,t,o),`Failed to terminate Vega app ${t}`,{appName:t,deviceId:e.id})}async function u(e,n,i){let o=t(n);r(await a().pressRemote(e.id,o,i,{allowFailure:!0,timeoutMs:1e4+(i??0)}),`Failed to press Vega TV remote ${n}`,{button:n,deviceId:e.id})}const d=[{matches:(e,t)=>n(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};
@@ -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.20.3
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.4
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{};