agent-device 0.20.3 → 0.20.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.3.apk → agent-device-android-ime-helper-0.20.5.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.5.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.3.manifest.json → agent-device-android-ime-helper-0.20.5.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.5.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.5.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.3.manifest.json → agent-device-android-snapshot-helper-0.20.5.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +57 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +45 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +73 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +3 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +8 -2
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android-adb.d.ts +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-inventory.d.ts +4 -0
- package/dist/src/app-lifecycle.js +7 -7
- package/dist/src/app-resolution.js +1 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +27 -19
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +15 -14
- package/dist/src/client-metro.js +1 -1
- package/dist/src/{tv-remote.d.ts → cloud-artifacts.d.ts} +109 -126
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-surface.js +1 -1
- package/dist/src/context.js +1 -1
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/debug-symbols.js +4 -4
- package/dist/src/device-input-state.d.ts +2 -2
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/device.js +1 -9
- package/dist/src/devices2.js +1 -1
- package/dist/src/entities.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.d.ts +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/ime-lifecycle.js +9 -0
- package/dist/src/index.d.ts +592 -555
- package/dist/src/input-actions.js +4 -4
- package/dist/src/install-artifact.js +4 -4
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.d.ts +7 -4
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +14 -14
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +103 -198
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/metro.d.ts +1 -1
- package/dist/src/parser.js +2 -0
- package/dist/src/path-resolution.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/plist-xml.js +1 -0
- package/dist/src/plist.js +1 -1
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-lock.js +1 -1
- package/dist/src/provider-limrun-runtime.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +22 -22
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/reporting.js +7 -7
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runner-provider.js +1 -1
- package/dist/src/runner-sequence.js +1 -1
- package/dist/src/runtime-transport.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/screenshot-geometry.js +1 -0
- package/dist/src/screenshot-result.js +6 -0
- package/dist/src/sdk-android-adb.d.ts +5 -6
- package/dist/src/sdk-android-adb.js +3 -3
- package/dist/src/sdk-batch-runner.d.ts +2 -2
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +21 -25
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.d.ts +19 -4
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.d.ts +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +9 -8
- package/dist/src/setting-state.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/src.js +1 -0
- package/dist/src/tool-provider.js +3 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/viewport-dimension.js +14 -0
- package/package.json +21 -9
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.3.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.3.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.3.apk.sha256 +0 -1
- package/dist/src/android-input-method-overlays.js +0 -1
- package/dist/src/android-input-ownership.js +0 -1
- package/dist/src/apple-multitouch-support.js +0 -1
- package/dist/src/click-button.d.ts +0 -5
- package/dist/src/compatibility-policy.js +0 -1
- package/dist/src/gesture-plan-types.js +0 -1
- package/dist/src/gesture-plan.js +0 -1
- package/dist/src/launch-console.js +0 -1
- package/dist/src/recording-export-quality.js +0 -14
- package/dist/src/rolldown-runtime.js +0 -1
- package/dist/src/runtime2.js +0 -1
- package/dist/src/sdk-app-inventory.d.ts +0 -4
- package/dist/src/sdk-app-inventory.js +0 -1
- package/dist/src/snapshot-diagnostics.js +0 -6
- package/dist/src/xml.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";function t(e){return e.map(e=>({args:e.args.join(` `),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}))}
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";function t(e){return e.map(e=>({args:e.args.join(` `),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}))}function n(t){let n=t.trim().toLowerCase();if(n===`light`)return`light`;if(n===`dark`)return`dark`;if(n===`toggle`)return`toggle`;throw new e(`INVALID_ARGS`,`Invalid appearance state: ${t}. Use light|dark|toggle.`)}function r(t){let n=t.toLowerCase();if(n===`on`||n===`true`||n===`1`)return!0;if(n===`off`||n===`false`||n===`0`)return!1;throw new e(`INVALID_ARGS`,`Invalid setting state: ${t}`)}export{n,t as r,r as t};
|
package/dist/src/simulator.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{h as n,p as r}from"./sdk-android-adb.js";import{l as i,n as a,s as o,t as s}from"./boot-diagnostics.js";import{a as c,i as l}from"./tool-provider.js";import{I as u,L as d,M as f,f as p,u as m}from"./physical-device-control.js";var h=e({SIMULATOR_BOOTED_MEMO_TTL_MS:()=>v,ensureBootedSimulator:()=>E,getSimulatorState:()=>O,markSimulatorBooted:()=>S,openIosSimulatorApp:()=>T,requireSimulatorDevice:()=>w,shutdownSimulator:()=>D});const g=[`Simulator`],_=[`Device Hub`,`Simulator`],v=5e3,y=f({ttlMs:v});function b(e){return`${e.id}|${e.simulatorSetPath??``}`}function x(e){return y.get(b(e))===!0}function S(e){y.set(b(e),!0)}function C(e){y.delete(b(e))}function w(e,n){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`${n} is only supported on iOS simulators`)}async function T(e={}){let t=e.deviceHub?_:g,n=e.background?[`-g`,`-a`]:[`-a`];for(let e of t)if((await l(`open`,[...n,e],{allowFailure:!0,timeoutMs:1e4})).exitCode===0)return}async function E(e,l={}){if(e.kind!==`simulator`)return;if((x(e)?`Booted`:await O(e))===`Booted`){S(e),l.focusExisting&&await T({background:l.deviceHub,deviceHub:l.deviceHub});return}l.onColdBootStart?.(e);let u=o.fromTimeoutMs(m),f,p;try{await i(async({deadline:i})=>{if(i?.isExpired())throw new t(`COMMAND_FAILED`,`iOS simulator boot deadline exceeded`,{timeoutMs:m});let a=Math.max(1e3,i?.remainingMs()??18e4);f=await c(d(e,[`boot`,e.id]),{allowFailure:!0,timeoutMs:a});let o=`${f.stdout}\n${f.stderr}`.toLowerCase(),s=o.includes(`already booted`)||o.includes(`current state: booted`);if(f.exitCode!==0&&!s)throw new t(`COMMAND_FAILED`,`simctl boot failed`,r(f));p=await c(d(e,[`bootstatus`,e.id,`-b`]),{allowFailure:!0,timeoutMs:a}),n(p,`simctl bootstatus failed`);let l=await O(e);if(l!==`Booted`)throw new t(`COMMAND_FAILED`,`Simulator is still booting`,{state:l})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let t=a({error:e,stdout:p?.stdout??f?.stdout,stderr:p?.stderr??f?.stderr,context:{platform:`ios`,phase:`boot`}});return t!==`IOS_BOOT_TIMEOUT`&&t!==`CI_RESOURCE_STARVATION_SUSPECTED`}},{deadline:u,phase:`boot`,classifyReason:e=>a({error:e,stdout:p?.stdout??f?.stdout,stderr:p?.stderr??f?.stderr,context:{platform:`ios`,phase:`boot`}})})}catch(n){let r=a({error:n,stdout:p?.stdout??f?.stdout,stderr:p?.stderr??f?.stderr,context:{platform:`ios`,phase:`boot`}});throw new t(`COMMAND_FAILED`,`iOS simulator failed to boot`,{platform:`ios`,deviceId:e.id,timeoutMs:m,elapsedMs:u.elapsedMs(),reason:r,hint:s(r),boot:f,bootstatus:p})}S(e),await T({deviceHub:l.deviceHub})}async function D(e){C(e);let t=await c(d(e,[`shutdown`,e.id]),{allowFailure:!0,timeoutMs:15e3});return{success:t.exitCode===0,exitCode:t.exitCode,stdout:t.stdout,stderr:t.stderr}}async function O(e){let t=typeof e==`string`?e:e.id,n=await c(typeof e==`string`?u([`list`,`devices`,`-j`]):d(e,[`list`,`devices`,`-j`]),{allowFailure:!0,timeoutMs:p});if(n.exitCode!==0)return null;try{let e=JSON.parse(n.stdout);for(let n of Object.values(e.devices??{})){let e=n.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}export{D as a,w as i,O as n,h as o,S as r,E as t};
|
package/dist/src/snapshot.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{j as n}from"./sdk-android-adb.js";import{n as r,t as i}from"./tool-provider2.js";import a from"node:path";import o from"node:fs";import{fileURLToPath as s}from"node:url";const c={"push button":`Button`,"toggle button":`Button`,"push button menu":`Button`,label:`StaticText`,static:`StaticText`,caption:`StaticText`,text:`TextField`,entry:`TextField`,"password text":`TextField`,"spin button":`TextField`,terminal:`TextArea`,"document text":`TextArea`,paragraph:`TextArea`,frame:`Window`,window:`Window`,dialog:`Dialog`,alert:`Alert`,"file chooser":`Dialog`,"color chooser":`Dialog`,"font chooser":`Dialog`,panel:`Group`,filler:`Group`,section:`Group`,form:`Group`,grouping:`Group`,"layered pane":`Group`,"glass pane":`Group`,"root pane":`Group`,"option pane":`Group`,"internal frame":`Group`,"desktop frame":`Group`,"block quote":`Group`,article:`Group`,comment:`Group`,landmark:`Group`,log:`Group`,marquee:`Group`,math:`Group`,notification:`Group`,"content deletion":`Group`,"content insertion":`Group`,mark:`Group`,suggestion:`Group`,"scroll pane":`ScrollArea`,"scroll bar":`ScrollBar`,"menu bar":`MenuBar`,menu:`Menu`,"popup menu":`Menu`,"menu item":`MenuItem`,"check menu item":`MenuItem`,"radio menu item":`MenuItem`,"tearoff menu item":`MenuItem`,"check box":`CheckBox`,"radio button":`RadioButton`,switch:`Switch`,"combo box":`ComboBox`,"page tab":`Tab`,"page tab list":`TabList`,table:`Table`,"tree table":`Table`,"table cell":`Cell`,"table row":`Row`,"table column header":`Cell`,"table row header":`Cell`,"column header":`Cell`,"row header":`Cell`,list:`List`,"list item":`ListItem`,"list box":`List`,tree:`Tree`,"tree item":`TreeItem`,"description list":`List`,"description term":`ListItem`,"description value":`ListItem`,"tool bar":`Toolbar`,"status bar":`StatusBar`,"info bar":`StatusBar`,slider:`Slider`,"progress bar":`ProgressBar`,"level bar":`ProgressBar`,image:`Image`,icon:`Image`,animation:`Image`,canvas:`Image`,"drawing area":`Image`,video:`Video`,audio:`Audio`,link:`Link`,hyperlink:`Link`,separator:`Separator`,application:`Application`,"tool tip":`Tooltip`,timer:`Timer`,heading:`Heading`,footnote:`Footnote`,"title bar":`TitleBar`,"date editor":`DateEditor`,rating:`Slider`};function l(e){let t=e.toLowerCase().trim();return c[t]||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)}const u=`atspi-dump.py`;let d=null;function f(){if(d)return d;let e=a.dirname(s(import.meta.url));for(let t=0;t<6;t++){let t=a.join(e,`linux`,u);if(o.existsSync(t))return d=t,t;e=a.dirname(e)}throw new t(`TOOL_MISSING`,`Cannot find ${u}. Ensure the agent-device package is installed correctly.`)}async function p(e,n={}){let a=i().accessibility;if(a)return await a.captureTree(e,n);if(process.platform!==`linux`)throw new t(`UNSUPPORTED_PLATFORM`,`AT-SPI2 bridge is only available on Linux`);if(!await i().whichCommand(`python3`))throw new t(`TOOL_MISSING`,`python3 is required for AT-SPI2 accessibility snapshots on Linux.`);let o=n.maxNodes??1500,s=n.maxDepth??12,c=n.maxApps??24,u=await r(`python3`,[f(),`--surface`,e,`--max-nodes`,String(o),`--max-depth`,String(s),`--max-apps`,String(c)],{allowFailure:!0,timeoutMs:3e4,signal:n.signal});if(u.exitCode!==0){let e=u.stderr.trim();throw e.includes(`No module named`)||e.includes(`gi.require_version`)?new t(`TOOL_MISSING`,`AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.`,{cause:e}):new t(`COMMAND_FAILED`,`AT-SPI2 snapshot failed (exit ${u.exitCode}): ${e||u.stdout}`)}let d;try{d=JSON.parse(u.stdout)}catch{throw new t(`COMMAND_FAILED`,`AT-SPI2 snapshot returned invalid JSON: ${u.stdout.slice(0,200)}`)}if(d.error)throw new t(`COMMAND_FAILED`,`AT-SPI2: ${d.error}`);return{nodes:(d.nodes??[]).map(e=>({index:e.index,type:l(e.role),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0})),truncated:d.truncated,surface:e}}var m=e({readLinuxTextAtPoint:()=>_,snapshotLinux:()=>g});function h(e){return e===`desktop`?`desktop`:e===`frontmost-app`||e===`app`?`frontmost-app`:(e===`menubar`&&n({level:`warn`,phase:`linux_snapshot`,data:{message:`menubar surface is not supported on Linux, falling back to desktop`}}),`desktop`)}async function g(e,t){let n=await p(h(e),{signal:t});return{nodes:n.nodes,truncated:n.truncated}}async function _(e,t,n){let{nodes:r}=await g(n),i=r.filter(n=>{let r=n.rect;return r?e>=r.x&&t>=r.y&&e<=r.x+r.width&&t<=r.y+r.height:!1}).sort((e,t)=>{let n=e.depth??0,r=t.depth??0;return n===r?v(e.rect)-v(t.rect):r-n});for(let e of i){let t=y(e);if(t.trim())return t}return``}function v(e){return(e?.width??0)*(e?.height??0)}function y(e){for(let t of[e.value,e.label,e.identifier])if(typeof t==`string`&&t.length>0)return t;return``}export{m as n,g as t};
|
package/dist/src/snapshot2.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{S as e,_ as t}from"./sdk-contracts.js";import{I as n,j as r}from"./sdk-android-adb.js";import{z as i}from"./sdk-batch-runner.js";import{ft as a,gt as o,ht as s,pt as c,ut as l,vn as u}from"./recording-export-quality.js";import{i as d,q as f}from"./snapshot-diagnostics.js";import{c as p,h as m,s as h}from"./sdk-device.js";import{a as g,g as _}from"./gesture-plan-types.js";import{t as v}from"./timeouts.js";import{t as y}from"./runtime.js";import{l as b,n as x}from"./input-actions.js";import{_ as S,g as C,v as ee}from"./device.js";import{l as w,n as T,s as E,t as D}from"./context.js";import{i as O}from"./helper.js";import{a as k}from"./runner-client.js";import{Bt as A,Ft as j,Mt as te,Nt as ne,Ot as re,Tt as ie,en as ae,u as oe,zt as M}from"./internal/daemon.js";import{C as N,S as P,b as F,i as I,o as L,x as R}from"./selector-runtime.js";import{promises as z}from"node:fs";import B from"node:os";import V from"node:path";async function H(e,t,n={}){return t===`wait`?await U(e,n.timeoutMs??1e4):t===`get`?q((await K(e))?.alert??null):await W(e,t)}async function U(e,n){let r=Date.now(),i=await G(e,n);if(!i)throw new t(`COMMAND_FAILED`,`alert wait timed out`);return{kind:`alertWait`,platform:`android`,action:`wait`,alert:i.alert,waitedMs:Date.now()-r,...u(`Alert visible`)}}async function W(e,n){let r=await G(e,s);if(!r)throw new t(`COMMAND_FAILED`,`alert not found`,{hint:`If a sheet is visible in snapshot but alert reports no alert, it is likely app-owned UI. Use snapshot -i and press the visible label/ref.`});let i=S(r.buttons,n);if(i)return await b(e,i.x,i.y),J(n,r.alert,i.label);if(n===`dismiss`)return await x(e),J(n,r.alert,`Back`);throw new t(`COMMAND_FAILED`,`alert accept found an alert but no accept button`,{alert:r.alert,hint:`Inspect alert get --json for visible buttons, then use press by visible label/ref if needed.`})}async function G(e,t){let n=Date.now();for(;Date.now()-n<t;){let t=await K(e);if(t)return t;await v(300)}return null}async function K(e){return ee((await n(`snapshot_capture`,async()=>await C(e,{helperWaitForIdleTimeoutMs:0,includeHiddenContentHints:!1}),{backend:`android`,purpose:`alert`})).nodes)}function q(e){return{kind:`alertStatus`,platform:`android`,action:`get`,alert:e,...u(e?`Alert visible`:`No alert visible`)}}function J(e,t,n){return{kind:`alertHandled`,platform:`android`,action:e,handled:!0,alert:t,button:n,...u(`Alert ${e}ed`)}}async function se(e){let{req:t,logPath:n,session:r,device:a}=e,o=ce(t.positionals?.[0]),s=r?r.surface===`frontmost-app`?{surface:`frontmost-app`}:{bundleId:r.appBundleId,surface:r.surface}:{},c=w(`alert`,a);if(c)return c;if(r&&ae(t)===`may-invalidate`&&j(r),a.platform===`android`)return Z(e,await H(a,o,{timeoutMs:i(t.positionals?.[1])??1e4}));if(p(a))return await Y(e,o,async e=>await O(e,s));let l=oe({req:t,logPath:n,traceLogPath:r?.trace?.outPath});return await Y(e,o,async(e,t)=>await k(a,{command:`alert`,action:e,appBundleId:r?.appBundleId,timeoutMs:t},l))}async function Y(e,t,n){if(t===`wait`)return await le(e,n);let r=t===`accept`||t===`dismiss`?t:`get`;return r===`accept`||r===`dismiss`?await ue(e,r,n):Z(e,await n(`get`,o))}function ce(e){return e===`accept`||e===`dismiss`||e===`wait`?e:`get`}async function le(e,t){let n=i(e.req.positionals?.[1])??1e4,r=Date.now(),a=!0;for(;Date.now()-r<n;){try{let i=a?n:X(r,n);return a=!1,Z(e,await t(`get`,i))}catch{}await v(300)}return E(`COMMAND_FAILED`,`alert wait timed out`)}async function ue(e,t,n){let r=h(e.device)?o:s,i=Date.now(),a,c=!0;for(;Date.now()-i<s;){try{let a=c?r:X(i,s);return c=!1,Z(e,await n(t,a))}catch(e){a=e;let t=String(e?.message??``).toLowerCase();if(!t.includes(`alert not found`)&&!t.includes(`no alert`))break}await v(300)}throw de(a)}function X(e,t){return Math.max(1,t-(Date.now()-e))}function Z(e,t){let n=t;return R(e.sessionStore,e.session,e.req,n),{ok:!0,data:n}}function de(e){return!(e instanceof t)||!fe(e)?e:new t(e.code,e.message,{...e.details??{},hint:`If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref.`})}function fe(e){let t=String(e?.message??``).toLowerCase();return t.includes(`alert not found`)||t.includes(`no alert`)}function pe(e){let t=e.positionals?.[0]?.toLowerCase(),n=e.positionals?.[1]?.toLowerCase(),r=e.positionals?.[2]?.toLowerCase();return t===`clear-app-state`?{ok:!0,parsed:{setting:t,state:`clear`,appBundleId:n===`clear`?e.positionals?.[2]:e.positionals?.[1]}}:!t||!n||t===`permission`&&!r||t===`location`&&n===`set`&&(!e.positionals?.[2]||!e.positionals?.[3])?E(`INVALID_ARGS`,l):{ok:!0,parsed:{setting:t,state:n,permissionTarget:r,latitude:e.positionals?.[2],longitude:e.positionals?.[3]}}}async function me(e){let{req:t,logPath:n,sessionStore:r,session:i,device:o,parsed:s}=e,{setting:l,state:u,appBundleId:d,permissionTarget:f,latitude:m,longitude:h}=s,g=w(`settings`,o);if(g)return g;if(p(o)&&!c(l))return E(`INVALID_ARGS`,a(l));let _=d??i?.appBundleId;if(l===`clear-app-state`&&!_)return E(`INVALID_ARGS`,`settings clear-app-state requires an app id when no app is bound to the session`);let v=l===`clear-app-state`?[l,u,_??``]:l===`permission`?[l,u,f??``,t.positionals?.[3]??``,_??``]:l===`location`&&u===`set`?[l,u,m??``,h??``,_??``]:[l,u,_??``];i&&j(i);let y=await T(o,`settings`,v,t.flags?.out,{...D(n,t.flags,_,i?.trace?.outPath)});return R(r,i,t,y??{setting:l,state:u}),{ok:!0,data:y??{setting:l,state:u}}}async function he(t){if(t.command!==`snapshot`||t.device.platform!==`android`)return;let n=e(t.error);if(be(n))return{ok:!1,error:{...n,details:{...n.details??{},androidSnapshotTimeoutScreenshot:await ge(t)}}}}async function ge(t){try{let e=await z.mkdtemp(V.join(B.tmpdir(),`agent-device-android-snapshot-timeout-`)),n=V.join(e,`snapshot-timeout-overlay-refs.png`),i=ve(await T(t.device,`screenshot`,[n],void 0,{...D(t.logPath,{screenshotNoStabilize:!0},t.session?.appBundleId,t.session?.trace?.outPath),surface:t.session?.surface}),n);await z.access(i);let a=await _e(i,t.session);return r({level:`warn`,phase:`android_snapshot_timeout_screenshot_captured`,data:{path:i,overlayRefCount:`overlayRefCount`in a?a.overlayRefCount:void 0,overlayRefsAnnotated:`overlayRefsAnnotated`in a?a.overlayRefsAnnotated:void 0}}),a}catch(t){let n=e(t);return r({level:`warn`,phase:`android_snapshot_timeout_screenshot_failed`,data:{error:n.message}}),{captureFailed:!0,error:n.message}}}async function _e(t,n){if(!n?.snapshot)return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`unavailable`,overlayRefCount:0};try{let e=await ie({screenshotPath:t,snapshot:n.snapshot});return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:e.length>0,overlayRefCount:e.length,overlayRefSource:`session-snapshot`,overlayRefs:e}}catch(n){let i=e(n);return r({level:`warn`,phase:`android_snapshot_timeout_screenshot_overlay_failed`,data:{path:t,error:i.message}}),{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`session-snapshot`,overlayRefCount:0,overlayAnnotationError:i.message}}}function ve(e,t){return ye(e)?e.path:t}function ye(e){return typeof e==`object`&&!!e&&`path`in e&&typeof e.path==`string`}function be(e){return e.code===`COMMAND_FAILED`?xe(e)||Se(e.details?.helper):!1}function xe(e){let t=`${e.message}\n${e.hint??``}`;return/Android accessibility snapshots can be blocked/i.test(t)}function Se(e){if(!e||typeof e!=`object`)return!1;let t=e,n=String(t.errorType??``),r=String(t.message??``);return/TimeoutException/i.test(n)||/timed out/i.test(r)}async function Ce(e){return await Q({...e,command:`snapshot`,unsupportedMessage:`snapshot is not supported on this device`,execute:async({runtime:t,sessionName:n,req:r,snapshotScope:i})=>{let a=await t.capture.snapshot({session:n,interactiveOnly:r.flags?.snapshotInteractiveOnly,depth:r.flags?.snapshotDepth,scope:i,raw:r.flags?.snapshotRaw,forceFull:r.flags?.snapshotForceFull}),o=we(r,e.sessionStore.get(n)),s=g(a.nodes),c=s===a.nodes?a:{...a,nodes:s};return{data:o===void 0?c:{...c,refsGeneration:o},record:{kind:`snapshot`,nodes:a.nodes.length,truncated:a.truncated}}}})}function we(e,t){return e.internal?.observationOnly===!0?void 0:t?.snapshotGeneration}async function Te(e){return await Q({...e,command:`diff`,unsupportedMessage:`diff is not supported on this device`,execute:async({runtime:e,sessionName:t,req:n,snapshotScope:r})=>{let i=await e.capture.diffSnapshot({session:t,interactiveOnly:n.flags?.snapshotInteractiveOnly,depth:n.flags?.snapshotDepth,scope:r,raw:n.flags?.snapshotRaw});return{data:i,record:{kind:`diff`,mode:`snapshot`,baselineInitialized:i.baselineInitialized,summary:i.summary}}}})}async function Q(e){let{req:t,sessionName:n,logPath:r,sessionStore:i}=e,{session:a,device:o}=await P(i,n,t.flags),s=w(e.command,o,{message:e.unsupportedMessage});if(s)return s;let c=A(t.flags?.snapshotScope,a);return c.ok?Ee(e.command,a,o)||await N(a,o,async()=>{let s=De({req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:c.scope}),l;try{l=await e.execute({runtime:s,sessionName:n,req:t,snapshotScope:c.scope})}catch(t){let n=await he({error:t,command:e.command,logPath:r,session:a,device:o});if(!n)throw t;return n}return Ne({req:t,sessionName:n,sessionStore:i,result:l.record}),{ok:!0,data:l.data}}):c}function Ee(e,t,n){return!h(n)||t?.appBundleId?null:E(`SESSION_NOT_FOUND`,`iOS ${e} requires an active app session on the target device. Run open first (for example: open --session ${t?.name??`sim`} --platform ios --device "<name>" <app>).`)}function De(e){let{req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:s}=e;return y({backend:Me({req:t,logPath:r,session:a,device:o,snapshotScope:s}),...L(`snapshot`),sessions:re({sessionName:n,getSession:()=>i.get(n),recordOptions:{includeSnapshot:!0},setRecord:e=>{let r=Pe(e),a=i.get(n);i.set(n,$({current:a,sessionName:n,device:o,record:r,refScopedSnapshot:Oe(t),issuesRefsToClient:t.command===`snapshot`&&t.internal?.observationOnly!==!0}))}})})}function $(e){let{current:t,sessionName:n,device:r,record:i,refScopedSnapshot:a}=e,o=ke(t,i,a),s=F({session:t,sessionName:n,device:r,snapshot:o?t.snapshot:i.snapshot,appBundleId:i.appBundleId});return te(s,{scopeSource:je({current:t,keepCurrentSnapshot:o,refScopedSnapshot:a}),keptCurrentSnapshot:o,previousGeneration:t?.snapshotGeneration}),Ae(s,o,e.issuesRefsToClient),i.appName&&(s.appName=i.appName),s}function Oe(e){return e.flags?.snapshotScope?.trim().startsWith(`@`)===!0}function ke(e,t,n){return n&&t.snapshot?.nodes.length===0&&e?.snapshot!==void 0}function Ae(e,t,n){!t&&n&&ne(e)}function je(e){let{current:t,keepCurrentSnapshot:n,refScopedSnapshot:r}=e;if(r)return n?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}function Me(e){let{req:t,logPath:n,session:r,device:i,snapshotScope:a}=e;return{platform:m(i),captureSnapshot:async(e,o)=>{let s=await M({device:i,session:r,flags:t.flags,outPath:o?.outPath??t.flags?.out,logPath:n,snapshotScope:a}),c=d(r);return{snapshot:s.snapshot,..._(s),...c?{snapshotDiagnostics:c}:{},appName:r?.appBundleId?r.appName??r.appBundleId:void 0,appBundleId:r?.appBundleId}}}}function Ne(e){let t=e.sessionStore.get(e.sessionName);t&&e.sessionStore.recordAction(t,{command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags??{},result:Fe(e.result),interactiveObservation:f(e.req)})}function Pe(e){if(!e.snapshot)throw new t(`UNKNOWN`,`snapshot runtime did not produce session state`);return e}function Fe(e){return e.kind===`snapshot`?{nodes:e.nodes,truncated:e.truncated}:{mode:e.mode,baselineInitialized:e.baselineInitialized,summary:e.summary}}const Ie={snapshot:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>await Ce({req:e,sessionName:t,logPath:n,sessionStore:r}),diff:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>e.positionals?.[0]===`snapshot`?await Te({req:e,sessionName:t,logPath:n,sessionStore:r}):E(`INVALID_ARGS`,`diff currently supports only: diff snapshot`),wait:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>await I({req:e,sessionName:t,logPath:n,sessionStore:r}),alert:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let{session:i,device:a}=await P(r,t,e.flags);return await N(i,a,async()=>await se({req:e,logPath:n,sessionStore:r,session:i,device:a}))},settings:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let i=pe(e);if(!i.ok)return i;let{session:a,device:o}=await P(r,t,e.flags);return await N(a,o,async()=>await me({req:e,logPath:n,sessionStore:r,session:a,device:o,parsed:i.parsed}))}};async function Le(e){let t=e.req.command,n=Ie[t];return n?await n(e):null}export{Le as handleSnapshotCommands};
|
|
1
|
+
import{S as e,_ as t}from"./sdk-contracts.js";import{in as n}from"./viewport-dimension.js";import{Q as r,Z as i,a,c as o,nt as s,s as c}from"./screenshot-geometry.js";import{k as l}from"./sdk-batch-runner.js";import{N as u,kt as d}from"./screenshot-result.js";import{c as f,h as p,s as m}from"./sdk-device.js";import{x as h}from"./device.js";import{t as g}from"./runtime.js";import{I as _,j as v}from"./sdk-android-adb.js";import{t as y}from"./timeouts.js";import{l as b,n as x}from"./input-actions.js";import{f as S,m as C,p as ee}from"./ime-lifecycle.js";import{l as w,n as T,s as E,t as D}from"./context.js";import{i as O}from"./helper.js";import{a as k}from"./runner-client.js";import{Bt as A,Gt as te,Lt as ne,Qt as re,Wt as ie,Zt as ae,qt as j,u as oe,un as M}from"./internal/daemon.js";import{C as N,E as P,T as F,i as I,s as L,w as R}from"./selector-runtime.js";import z from"node:path";import{promises as B}from"node:fs";import V from"node:os";async function H(e,t,n={}){return t===`wait`?await U(e,n.timeoutMs??1e4):t===`get`?q((await K(e))?.alert??null):await W(e,t)}async function U(e,r){let i=Date.now(),a=await G(e,r);if(!a)throw new t(`COMMAND_FAILED`,`alert wait timed out`);return{kind:`alertWait`,platform:`android`,action:`wait`,alert:a.alert,waitedMs:Date.now()-i,...n(`Alert visible`)}}async function W(e,n){let r=await G(e,i);if(!r)throw new t(`COMMAND_FAILED`,`alert not found`,{hint:`If a sheet is visible in snapshot but alert reports no alert, it is likely app-owned UI. Use snapshot -i and press the visible label/ref.`});let a=ee(r.buttons,n);if(a)return await b(e,a.x,a.y),J(n,r.alert,a.label);if(n===`dismiss`)return await x(e),J(n,r.alert,`Back`);throw new t(`COMMAND_FAILED`,`alert accept found an alert but no accept button`,{alert:r.alert,hint:`Inspect alert get --json for visible buttons, then use press by visible label/ref if needed.`})}async function G(e,t){let n=Date.now();for(;Date.now()-n<t;){let t=await K(e);if(t)return t;await y(300)}return null}async function K(e){return C((await _(`snapshot_capture`,async()=>await S(e,{includeHiddenContentHints:!1}),{backend:`android`,purpose:`alert`})).nodes)}function q(e){return{kind:`alertStatus`,platform:`android`,action:`get`,alert:e,...n(e?`Alert visible`:`No alert visible`)}}function J(e,t,r){return{kind:`alertHandled`,platform:`android`,action:e,handled:!0,alert:t,button:r,...n(`Alert ${e}ed`)}}async function se(e){let{req:t,logPath:n,session:r,device:i}=e,a=ce(t.positionals?.[0]),o=r?r.surface===`frontmost-app`?{surface:`frontmost-app`}:{bundleId:r.appBundleId,surface:r.surface}:{},s=w(`alert`,i);if(s)return s;if(r&&M(t)===`may-invalidate`&&j(r),i.platform===`android`)return Z(e,await H(i,a,{timeoutMs:l(t.positionals?.[1])??1e4}));if(f(i))return await Y(e,a,async e=>await O(e,o));let c=oe({req:t,logPath:n,traceLogPath:r?.trace?.outPath});return await Y(e,a,async(e,t)=>await k(i,{command:`alert`,action:e,appBundleId:r?.appBundleId,timeoutMs:t},c))}async function Y(e,t,n){if(t===`wait`)return await le(e,n);let i=t===`accept`||t===`dismiss`?t:`get`;return i===`accept`||i===`dismiss`?await ue(e,i,n):Z(e,await n(`get`,r))}function ce(e){return e===`accept`||e===`dismiss`||e===`wait`?e:`get`}async function le(e,t){let n=l(e.req.positionals?.[1])??1e4,r=Date.now(),i=!0;for(;Date.now()-r<n;){try{let a=i?n:X(r,n);return i=!1,Z(e,await t(`get`,a))}catch{}await y(300)}return E(`COMMAND_FAILED`,`alert wait timed out`)}async function ue(e,t,n){let a=m(e.device)?r:i,o=Date.now(),s,c=!0;for(;Date.now()-o<i;){try{let r=c?a:X(o,i);return c=!1,Z(e,await n(t,r))}catch(e){s=e;let t=String(e?.message??``).toLowerCase();if(!t.includes(`alert not found`)&&!t.includes(`no alert`))break}await y(300)}throw de(s)}function X(e,t){return Math.max(1,t-(Date.now()-e))}function Z(e,t){let n=t;return R(e.sessionStore,e.session,e.req,n),{ok:!0,data:n}}function de(e){return!(e instanceof t)||!fe(e)?e:new t(e.code,e.message,{...e.details??{},hint:`If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref.`})}function fe(e){let t=String(e?.message??``).toLowerCase();return t.includes(`alert not found`)||t.includes(`no alert`)}function pe(e){let t=e.positionals?.[0]?.toLowerCase(),n=e.positionals?.[1]?.toLowerCase(),r=e.positionals?.[2]?.toLowerCase();return t===`clear-app-state`?{ok:!0,parsed:{setting:t,state:`clear`,appBundleId:n===`clear`?e.positionals?.[2]:e.positionals?.[1]}}:!t||!n||t===`permission`&&!r||t===`location`&&n===`set`&&(!e.positionals?.[2]||!e.positionals?.[3])?E(`INVALID_ARGS`,a):{ok:!0,parsed:{setting:t,state:n,permissionTarget:r,latitude:e.positionals?.[2],longitude:e.positionals?.[3]}}}async function me(e){let{req:t,logPath:n,sessionStore:r,session:i,device:a,parsed:s}=e,{setting:l,state:u,appBundleId:d,permissionTarget:p,latitude:m,longitude:h}=s,g=w(`settings`,a);if(g)return g;if(f(a)&&!o(l))return E(`INVALID_ARGS`,c(l));let _=d??i?.appBundleId;if(l===`clear-app-state`&&!_)return E(`INVALID_ARGS`,`settings clear-app-state requires an app id when no app is bound to the session`);let v=l===`clear-app-state`?[l,u,_??``]:l===`permission`?[l,u,p??``,t.positionals?.[3]??``,_??``]:l===`location`&&u===`set`?[l,u,m??``,h??``,_??``]:[l,u,_??``];i&&j(i);let y=await T(a,`settings`,v,t.flags?.out,{...D(n,t.flags,_,i?.trace?.outPath)});return R(r,i,t,y??{setting:l,state:u}),{ok:!0,data:y??{setting:l,state:u}}}async function he(t){if(t.command!==`snapshot`||t.device.platform!==`android`)return;let n=e(t.error);if(be(n))return{ok:!1,error:{...n,details:{...n.details??{},androidSnapshotTimeoutScreenshot:await ge(t)}}}}async function ge(t){try{let e=await B.mkdtemp(z.join(V.tmpdir(),`agent-device-android-snapshot-timeout-`)),n=z.join(e,`snapshot-timeout-overlay-refs.png`),r=ve(await T(t.device,`screenshot`,[n],void 0,{...D(t.logPath,{screenshotNoStabilize:!0},t.session?.appBundleId,t.session?.trace?.outPath),surface:t.session?.surface}),n);await B.access(r);let i=await _e(r,t.session);return v({level:`warn`,phase:`android_snapshot_timeout_screenshot_captured`,data:{path:r,overlayRefCount:`overlayRefCount`in i?i.overlayRefCount:void 0,overlayRefsAnnotated:`overlayRefsAnnotated`in i?i.overlayRefsAnnotated:void 0}}),i}catch(t){let n=e(t);return v({level:`warn`,phase:`android_snapshot_timeout_screenshot_failed`,data:{error:n.message}}),{captureFailed:!0,error:n.message}}}async function _e(t,n){if(!n?.snapshot)return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`unavailable`,overlayRefCount:0};try{let e=await ne({screenshotPath:t,snapshot:n.snapshot});return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:e.length>0,overlayRefCount:e.length,overlayRefSource:`session-snapshot`,overlayRefs:e}}catch(n){let r=e(n);return v({level:`warn`,phase:`android_snapshot_timeout_screenshot_overlay_failed`,data:{path:t,error:r.message}}),{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`session-snapshot`,overlayRefCount:0,overlayAnnotationError:r.message}}}function ve(e,t){return ye(e)?e.path:t}function ye(e){return typeof e==`object`&&!!e&&`path`in e&&typeof e.path==`string`}function be(e){return e.code===`COMMAND_FAILED`?xe(e)||Se(e.details?.helper):!1}function xe(e){let t=`${e.message}\n${e.hint??``}`;return/Android accessibility snapshots can be blocked/i.test(t)}function Se(e){if(!e||typeof e!=`object`)return!1;let t=e,n=String(t.errorType??``),r=String(t.message??``);return/TimeoutException/i.test(n)||/timed out/i.test(r)}async function Ce(e){return await Q({...e,command:`snapshot`,unsupportedMessage:`snapshot is not supported on this device`,execute:async({runtime:t,sessionName:n,req:r,snapshotScope:i})=>{let a=await t.capture.snapshot({session:n,interactiveOnly:r.flags?.snapshotInteractiveOnly,depth:r.flags?.snapshotDepth,scope:i,raw:r.flags?.snapshotRaw,forceFull:r.flags?.snapshotForceFull}),o=we(r,e.sessionStore.get(n)),s=h(a.nodes),c=s===a.nodes?a:{...a,nodes:s};return{data:o===void 0?c:{...c,refsGeneration:o},record:{kind:`snapshot`,nodes:a.nodes.length,truncated:a.truncated}}}})}function we(e,t){return e.internal?.observationOnly===!0?void 0:t?.snapshotGeneration}async function Te(e){return await Q({...e,command:`diff`,unsupportedMessage:`diff is not supported on this device`,execute:async({runtime:e,sessionName:t,req:n,snapshotScope:r})=>{let i=await e.capture.diffSnapshot({session:t,interactiveOnly:n.flags?.snapshotInteractiveOnly,depth:n.flags?.snapshotDepth,scope:r,raw:n.flags?.snapshotRaw});return{data:i,record:{kind:`diff`,mode:`snapshot`,baselineInitialized:i.baselineInitialized,summary:i.summary}}}})}async function Q(e){let{req:t,sessionName:n,logPath:r,sessionStore:i}=e,{session:a,device:o}=await F(i,n,t.flags),s=w(e.command,o,{message:e.unsupportedMessage});if(s)return s;let c=re(t.flags?.snapshotScope,a);return c.ok?Ee(e.command,a,o)||await P(a,o,async()=>{let s=De({req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:c.scope}),l;try{l=await e.execute({runtime:s,sessionName:n,req:t,snapshotScope:c.scope})}catch(t){let n=await he({error:t,command:e.command,logPath:r,session:a,device:o});if(!n)throw t;return n}return Ne({req:t,sessionName:n,sessionStore:i,result:l.record}),{ok:!0,data:l.data}}):c}function Ee(e,t,n){return!m(n)||t?.appBundleId?null:E(`SESSION_NOT_FOUND`,`iOS ${e} requires an active app session on the target device. Run open first (for example: open --session ${t?.name??`sim`} --platform ios --device "<name>" <app>).`)}function De(e){let{req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:s}=e;return g({backend:Me({req:t,logPath:r,session:a,device:o,snapshotScope:s}),...L(`snapshot`),sessions:A({sessionName:n,getSession:()=>i.get(n),recordOptions:{includeSnapshot:!0},setRecord:e=>{let r=Pe(e),a=i.get(n);i.set(n,$({current:a,sessionName:n,device:o,record:r,refScopedSnapshot:Oe(t),issuesRefsToClient:t.command===`snapshot`&&t.internal?.observationOnly!==!0}))}})})}function $(e){let{current:t,sessionName:n,device:r,record:i,refScopedSnapshot:a}=e,o=ke(t,i,a),s=N({session:t,sessionName:n,device:r,snapshot:o?t.snapshot:i.snapshot,appBundleId:i.appBundleId});return ie(s,{scopeSource:je({current:t,keepCurrentSnapshot:o,refScopedSnapshot:a}),keptCurrentSnapshot:o,previousGeneration:t?.snapshotGeneration}),Ae(s,o,e.issuesRefsToClient),i.appName&&(s.appName=i.appName),s}function Oe(e){return e.flags?.snapshotScope?.trim().startsWith(`@`)===!0}function ke(e,t,n){return n&&t.snapshot?.nodes.length===0&&e?.snapshot!==void 0}function Ae(e,t,n){!t&&n&&te(e)}function je(e){let{current:t,keepCurrentSnapshot:n,refScopedSnapshot:r}=e;if(r)return n?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}function Me(e){let{req:t,logPath:n,session:r,device:i,snapshotScope:a}=e;return{platform:p(i),captureSnapshot:async(e,o)=>{let c=await ae({device:i,session:r,flags:t.flags,outPath:o?.outPath??t.flags?.out,logPath:n,snapshotScope:a}),l=d(r);return{snapshot:c.snapshot,...s(c),...l?{snapshotDiagnostics:l}:{},appName:r?.appBundleId?r.appName??r.appBundleId:void 0,appBundleId:r?.appBundleId}}}}function Ne(e){let t=e.sessionStore.get(e.sessionName);t&&e.sessionStore.recordAction(t,{command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags??{},result:Fe(e.result),interactiveObservation:u(e.req)})}function Pe(e){if(!e.snapshot)throw new t(`UNKNOWN`,`snapshot runtime did not produce session state`);return e}function Fe(e){return e.kind===`snapshot`?{nodes:e.nodes,truncated:e.truncated}:{mode:e.mode,baselineInitialized:e.baselineInitialized,summary:e.summary}}const Ie={snapshot:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>await Ce({req:e,sessionName:t,logPath:n,sessionStore:r}),diff:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>e.positionals?.[0]===`snapshot`?await Te({req:e,sessionName:t,logPath:n,sessionStore:r}):E(`INVALID_ARGS`,`diff currently supports only: diff snapshot`),wait:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>await I({req:e,sessionName:t,logPath:n,sessionStore:r}),alert:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let{session:i,device:a}=await F(r,t,e.flags);return await P(i,a,async()=>await se({req:e,logPath:n,sessionStore:r,session:i,device:a}))},settings:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let i=pe(e);if(!i.ok)return i;let{session:a,device:o}=await F(r,t,e.flags);return await P(a,o,async()=>await me({req:e,logPath:n,sessionStore:r,session:a,device:o,parsed:i.parsed}))}};async function Le(e){let t=e.req.command,n=Ie[t];return n?await n(e):null}export{Le as handleSnapshotCommands};
|
package/dist/src/src.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{s as t}from"./sdk-batch-runner.js";import{f as n}from"./device.js";import r from"node:path";import i from"node:fs";import a from"node:os";import o from"@limrun/api";import{createInstanceClient as s}from"@limrun/api/instance-client";import{createInstanceClient as ee}from"@limrun/api/ios-client";import{setTimeout as c}from"node:timers/promises";const l=`limrun`,u=l;function d(e){if(e===`ios-instance`)return`ios`;if(e===`android-instance`)return`android`}function f(e,t,n){return{platform:e===`ios`?`apple`:`android`,...e===`ios`?{appleOs:`ios`}:{},id:m(e,t.leaseId),name:`Limrun ${e} ${n.slice(0,8)}`,kind:e===`ios`?`simulator`:`emulator`,target:`mobile`,booted:!0}}function p(e){let[t,n,r]=e.split(`:`);if(t===u&&!(n!==`ios`&&n!==`android`)&&r)return{platform:n,leaseId:r}}function m(e,t){return`${u}:${e}:${t}`}function h(e){return e?.trim()||void 0}async function g(e,t){let n=await s({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t},i={exec:async(e,t)=>await S(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return i.reverse=await t.android.createPortReverse(i.exec),Object.assign(r,{adbProvider:i})}function _(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function v(e,t,n,r){let i=h(r?.packageNameHint);r?.relaunch&&i&&await S(t,[`shell`,`am`,`force-stop`,i],{allowFailure:!0});let a=await e.assets.getOrUpload({path:n,name:E(i,n)});await t.client.sendAsset(a.signedDownloadUrl);let o=i?await t.dependencies.android.inferAppName(i):void 0;return{...i?{packageName:i,launchTarget:i}:{},...o?{appName:o}:{}}}async function y(e,t){await e.adbProvider.reverse?.ensure({local:T(t.devicePort),remote:T(t.hostPort),ownerId:t.name})}async function b(e){await e.adbTunnelPromise?.catch(()=>{});let t=e.adbSerial;t&&(await x(e),await e.dependencies.host.runAdb([`disconnect`,t],{allowFailure:!0,timeoutMs:1e4}).catch(()=>{})),e.adbTunnel?.close(),e.adbTunnel=void 0,e.adbSerial=void 0,e.adbTunnelPromise=void 0}async function x(e){let t=e.adbProvider.reverse;if(!t?.list)return;let n=await t.list().catch(()=>[]),r=new Set,i=[];for(let e of n)e.ownerId?r.add(e.ownerId):i.push(e.local);await Promise.allSettled([...[...r].map(async e=>await t.removeAllOwned(e)),...i.map(async e=>await t.remove(e))])}async function S(e,t,n){let{adbArgs:r,result:i}=await C(e,t,n);return await w(r,i,n?.allowFailure,e.dependencies)}async function C(e,t,n){let r=[`-s`,await te(e),...t];return{adbArgs:r,result:await e.dependencies.host.runAdb(r,{allowFailure:n?.allowFailure,binaryStdout:n?.binaryStdout,stdin:n?.stdin,timeoutMs:n?.timeoutMs??3e4,signal:n?.signal})}}async function w(e,t,n,r){if(t.exitCode!==0&&n!==!0)throw await r.android.adbError(`Limrun Android ADB command failed`,t,{command:[`adb`,...e].join(` `)});return t}async function te(e){if(e.adbSerial)return e.adbSerial;let t=e.adbTunnelPromise??ne(e);e.adbTunnelPromise=t;try{return await t}catch(n){throw e.adbTunnelPromise===t&&(e.adbTunnelPromise=void 0),n}}async function ne(e){let t=await e.client.startAdbTunnel(),n=`${t.address.address}:${t.address.port}`;return e.adbTunnel=t,e.adbSerial=n,n}function T(t){if(!Number.isInteger(t)||t<1||t>65535)throw new e(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${t}`);return`tcp:${t}`}function E(e,t){let n=r.extname(t)||`.apk`;return`${e?.replace(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}function D(e){let t=Array.isArray(e)?e:[e],n=[],r=(e,t,i)=>{let a=n.length;n.push(O(e,{index:a,depth:t,parentIndex:i}));for(let n of F(e))r(n,t+1,a)};for(let e of t)r(e,0);return n}function O(e,t){return{index:t.index,type:k(e),role:A(e),label:j(e),value:M(e),identifier:N(e),rect:P(e),enabled:e.enabled,selected:e.selected,hittable:e.hittable,depth:t.depth,parentIndex:t.parentIndex}}function k(e){return e.elementType??e.type}function A(e){return e.role??k(e)}function j(e){return e.label??e.AXLabel??void 0}function M(e){return e.value??e.AXValue??void 0}function N(e){return e.identifier??e.AXUniqueId??void 0}function P(e){let t=e.rect??e.frame;if(!(!t||typeof t.x!=`number`||typeof t.y!=`number`||typeof t.width!=`number`||typeof t.height!=`number`))return{x:t.x,y:t.y,width:t.width,height:t.height}}function F(e){return e.children??e.nodes??e.elements??[]}function I(e){return e.key===`id`?{accessibilityId:e.value}:e.key===`value`?{value:e.value}:{label:e.value}}async function L(e,t){i.mkdirSync(r.dirname(e),{recursive:!0}),await i.promises.writeFile(e,Buffer.from(t,`base64`))}async function R(e,t){let n=await ee({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t}}async function z(e,t,n,r){let i=await H(n,t.dependencies);try{let n=await e.assets.getOrUpload({path:i.uploadPath,name:i.assetName}),a=(await B(t,n.signedDownloadUrl,{md5:n.md5,relaunch:r?.relaunch,appIdentifierHint:r?.appIdentifierHint})).appId;return{...a?{bundleId:a,launchTarget:a}:{},...i.appName?{appName:i.appName}:{}}}finally{await i.cleanup()}}async function B(t,n,r){let i=await t.client.listApps().catch(()=>void 0),a=h((await t.client.installApp(n,{md5:r?.md5,launchMode:r?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`})).bundleId),o=h(r?.appIdentifierHint),s=[];for(let e of W){e>0&&await c(e),s=await t.client.listApps();let n=G({resultBundleId:a,requestedBundleId:o,beforeInstallApps:i,afterInstallApps:s});if(n)return{appId:n}}throw new e(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:a,requestedBundleId:o,installedUserApps:s.filter(q).map(e=>e.bundleId).sort()})}function V(e){return new re(e)}var re=class{session;constructor(e){this.session=e}async open(e,n){if(n?.url){await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e)),await this.session.client.openUrl(n.url);return}if(t(e)){await this.session.client.openUrl(e);return}await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e))}async openDevice(){}async close(e){e&&await this.session.client.terminateApp(await this.session.dependencies.ios.resolveAppAlias(e)).catch(()=>{})}async tap(e,t){await this.session.client.tap(e,t)}async tapElementSelector(e){await this.session.client.tapElement(I(e))}async doubleTap(e,t){await this.tap(e,t),await this.tap(e,t)}async longPress(){throw J(`longpress`,`Limrun iOS direct sessions do not expose long press yet.`)}async focus(e,t){await this.tap(e,t)}async type(e,t){if(t&&t>0){for(let n of Array.from(e))await this.session.client.typeText(n),await c(t);return}await this.session.client.typeText(e)}async fill(e,t,n){await this.tap(e,t),await this.session.client.typeText(n)}async fillElementSelector(e,t){await this.session.client.setElementValue(t,I(e))}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){await L(e,(await this.session.client.screenshot()).base64)}async snapshot(e){let t=await this.session.client.elementTree();return{nodes:D(JSON.parse(t)),backend:`xctest`}}async back(){await this.session.client.pressKey(`escape`)}async home(){throw J(`home`,`Limrun iOS direct sessions do not expose home yet.`)}async setOrientation(e){if(e===`portrait-upside-down`)throw J(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async performGesture(){throw J(`gesture`,`Limrun iOS direct sessions do not expose portable gesture execution yet.`)}async appSwitcher(){throw J(`app-switcher`,`Limrun iOS direct sessions do not expose app switcher yet.`)}async tvRemote(){throw J(`tv-remote`,`Limrun iOS direct sessions do not expose tv remote control.`)}async readClipboard(){throw J(`clipboard`,`Limrun iOS direct sessions do not expose clipboard read yet.`)}async writeClipboard(){throw J(`clipboard`,`Limrun iOS direct sessions do not expose clipboard write yet.`)}async setSetting(){throw J(`settings`,`Limrun iOS direct sessions do not expose settings changes yet.`)}};async function H(e,t){if(!(await i.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:r.basename(e),appName:U(e),cleanup:async()=>{}};let n=await i.promises.mkdtemp(r.join(a.tmpdir(),`agent-device-limrun-ios-app-`)),o=r.join(n,`${r.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:r.dirname(e),entryName:r.basename(e),archivePath:o})}catch(e){throw await i.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:o,assetName:r.basename(o),appName:await t.ios.readBundleAppName(e)??U(e),cleanup:async()=>{await i.promises.rm(n,{recursive:!0,force:!0})}}}function U(e){return r.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const W=[0,250];function G(e){let t=new Set(e.afterInstallApps.map(e=>e.bundleId));return(e.resultBundleId&&t.has(e.resultBundleId)?e.resultBundleId:void 0)??(e.requestedBundleId&&t.has(e.requestedBundleId)?e.requestedBundleId:void 0)??K(e.beforeInstallApps,e.afterInstallApps)}function K(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>q(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function q(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}function J(t,n){throw new e(`UNSUPPORTED_OPERATION`,n,{command:t})}function Y(e){return e.platform===`android`?X(e):ie(e)}function X(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:_(e),adb:e.adbProvider,listApps:async r=>await e.dependencies.android.listApps(t,n(r)),getForegroundApp:async()=>await e.dependencies.android.getForegroundApp(t),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},getKeyboardState:async()=>await e.dependencies.android.getKeyboardState(t),dismissKeyboard:async()=>await e.dependencies.android.dismissKeyboard(t),readLogs:async n=>await e.dependencies.android.readLogs(t,n),...Z(e.client),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function ie(e){return{platform:`ios`,device:e.device,interactor:V(e),viewport:{width:e.client.deviceInfo.screenWidth,height:e.client.deviceInfo.screenHeight},listApps:async t=>(await e.client.listApps()).filter(e=>n(t)===`all`||q(e)).map(e=>({id:e.bundleId,name:e.name,installType:e.installType})).sort((e,t)=>e.id.localeCompare(t.id)),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},readLogs:async(t,n)=>await e.client.appLogTail(t,n),...Z(e.client),installRemoteApp:async(t,n)=>await B(e,t,n),runSimctl:t=>e.client.simctl(t)}}function Z(e){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async({outPath:t})=>await e.stopRecording({localPath:t})}}const Q=`agent-device-cli`;function $(e){return{apiKey:e.apiKey,defaultHeaders:{"x-agent-device-client":Q,"x-agent-device-version":e.clientVersion}}}function ae(e,t){return new oe(e,t)}var oe=class{limrun;sessions=new Map;options;dependencies;provider=l;leaseLifecycle={allocate:async e=>await this.allocate(e),release:async e=>await this.release(e)};recoverExpiredLease=async t=>{if(t.leaseProvider!==this.provider||!d(t.backend))throw new e(`UNSUPPORTED_OPERATION`,`Limrun cannot recover this expired lease.`,{leaseId:t.leaseId,leaseProvider:t.leaseProvider,leaseBackend:t.backend});await this.release(t)};deviceInventoryProvider=async e=>{if(e.leaseProvider!==this.provider||!e.leaseId)return null;let t=this.sessions.get(e.leaseId);return t?e.platform&&e.platform!==t.platform?[]:[t.device]:null};constructor(e,t){this.options=e,this.dependencies=t,this.limrun=new o($({apiKey:e.apiKey,clientVersion:t.clientVersion}))}ownsDevice(e){return p(e.id)!==void 0}getInteractor(e){let t=this.getSessionForDevice(e);if(t)return t.platform===`ios`?V(t):_(t)}getDeviceSession(e){let t=this.getSessionForDevice(e);return t?Y(t):void 0}async installApp(e,t,n,r){return await this.installInstallablePath(e,n,{...r,appIdentifierHint:r?.appIdentifierHint??t,packageNameHint:r?.packageNameHint??t})}async installInstallablePath(e,t,n){let r=this.getSessionForDevice(e);if(r)return r.platform===`ios`?await z(this.limrun,r,t,n):await v(this.limrun,r,t,n)}async configurePortReverse(e){let t=this.requireAndroidPortReverseSession(e.leaseId);if(t)return await y(t,e),se(e)}async shutdown(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(async e=>await this.terminateSession(e))),this.sessions.clear()}async allocate(e){if(e.leaseProvider!==this.provider)return;let t=d(e.backend);if(!t)return;let n=this.sessions.get(e.leaseId);if(n)return{limrunInstanceId:n.instanceId,device:n.device};let r=t===`ios`?await this.createIosSession(e):await this.createAndroidSession(e);return this.sessions.set(e.leaseId,r),{limrunInstanceId:r.instanceId,device:r.device}}async createIosSession(t){let n=await this.limrun.iosInstances.create({wait:!0,metadata:this.buildInstanceMetadata(t),spec:this.options.region?{region:this.options.region}:{}});try{if(!n.status.apiUrl)throw new e(`COMMAND_FAILED`,`Limrun iOS instance did not expose apiUrl`);return await R({lease:t,instanceId:n.metadata.id,device:f(`ios`,t,n.metadata.id),apiUrl:n.status.apiUrl,token:n.status.token},this.dependencies)}catch(e){throw await this.limrun.iosInstances.delete(n.metadata.id).catch(()=>{}),e}}async createAndroidSession(t){let n=await this.limrun.androidInstances.create({wait:!0,metadata:this.buildInstanceMetadata(t),spec:this.options.region?{region:this.options.region}:{}});try{if(!n.status.apiUrl||!n.status.adbWebSocketUrl)throw new e(`COMMAND_FAILED`,`Limrun Android instance did not expose API and ADB websocket endpoints`);return await g({lease:t,instanceId:n.metadata.id,device:f(`android`,t,n.metadata.id),apiUrl:n.status.apiUrl,adbUrl:n.status.adbWebSocketUrl,token:n.status.token},this.dependencies)}catch(e){throw await this.limrun.androidInstances.delete(n.metadata.id).catch(()=>{}),e}}buildInstanceMetadata(e){return{displayName:`agent-device-${e.tenantId}-${e.runId}`,labels:{tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId,provider:e.leaseProvider??`limrun`,source:Q}}}async release(e){let t=this.sessions.get(e.leaseId);return t?(await this.terminateSession(t),this.sessions.delete(e.leaseId),{limrunInstanceId:t.instanceId}):await this.releaseRecoveredSession(e)}async releaseRecoveredSession(e){let t=d(e.backend);if(!t)return;let n=`provider=${l},leaseId=${e.leaseId}`,r=(t===`ios`?await this.limrun.iosInstances.list({labelSelector:n}):await this.limrun.androidInstances.list({labelSelector:n})).getPaginatedItems().map(e=>e.metadata.id);for(let e of r)t===`ios`?await this.limrun.iosInstances.delete(e):await this.limrun.androidInstances.delete(e);if(r.length!==0)return{limrunInstanceId:r[0],limrunInstanceCount:r.length}}async terminateSession(e){if(e.client.disconnect(),e.platform===`ios`){await this.limrun.iosInstances.delete(e.instanceId);return}await b(e),await this.limrun.androidInstances.delete(e.instanceId)}getSessionForDevice(e){let t=p(e.id);if(!t)return;let n=this.sessions.get(t.leaseId);return n?.platform===t.platform?n:void 0}requireAndroidPortReverseSession(e){let t=this.sessions.get(e);if(!t||t.platform===`android`)return t;throw ce(`port reverse`,`Direct Limrun iOS sessions cannot reach local host ports; use a bridge public URL.`)}};function se(e){return{leaseId:e.leaseId,devicePort:e.devicePort,hostPort:e.hostPort,name:e.name}}function ce(t,n){throw new e(`UNSUPPORTED_OPERATION`,n,{command:t})}async function le(t){let n=new o({...$(t),timeout:15e3,maxRetries:0}),r={limit:1,...t.region?{region:t.region}:{}};try{t.platform===`android`?await n.androidInstances.list(r):await n.iosInstances.list(r)}catch(t){let n=ue(t);throw n===401||n===403?new e(`UNAUTHORIZED`,`Limrun rejected connection verification.`,{status:n,hint:`Check LIMRUN_API_KEY and its organization access.`}):new e(`COMMAND_FAILED`,`Limrun connection verification failed.`,{hint:`Check Limrun service access, LIMRUN_REGION, and network connectivity, then retry.`},t)}let i=t.platform===`android`?`Android`:`iOS`,a=t.platform===`android`?`emulator`:`simulator`;return{provider:`limrun`,service:`Limrun`,verificationMessage:`Credentials and ${i} instance access verified.`,device:{status:`deferred`,name:`Provider-selected ${i} ${a}`,platform:t.platform},app:{status:`missing`,message:`A new Limrun instance does not have your app yet.`}}}function ue(e){if(!e||typeof e!=`object`)return;let t=e.status;return typeof t==`number`?t:void 0}export{ae as n,l as r,le as t};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`).replace(/\n$/,``),writeClipboard:async t=>{r(await e(`pbcopy`,[],{allowFailure:!0,stdin:t}),`Failed to write macOS clipboard`)},readDarkMode:async()=>{let n=r(await e(`osascript`,[`-e`,`tell application "System Events" to tell appearance preferences to get dark mode`],{allowFailure:!0}),`Failed to read macOS appearance`),i=n.stdout.trim().toLowerCase();if(i===`true`)return!0;if(i===`false`)return!1;throw new t(`COMMAND_FAILED`,`Unable to determine current macOS appearance from osascript output: ${n.stdout.trim()}`)},setDarkMode:async t=>{r(await e(`osascript`,[`-e`,`tell application "System Events" to tell appearance preferences to set dark mode to ${t?`true`:`false`}`],{allowFailure:!0}),`Failed to set macOS appearance`)},listApps:async t=>await m(e,n,t)}}function p(e,t){let n=[`-b`,e];return t&&n.push(t),n}async function m(e,t,n){let r=[`/Applications`,`/System/Applications`,
|
|
3
|
-
`)){let t=e.trim();t&&i.add(t)}}return d((await Promise.all(Array.from(i).map(async e=>{let n=await h(e,t).catch(()=>({})),r=n.bundleId;return r?{bundleId:r,name:n.appName??
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{f as n,h as r,v as i,w as a}from"./sdk-android-adb.js";import o from"node:path";import{AsyncLocalStorage as s}from"node:async_hooks";import{promises as c}from"node:fs";import l from"node:os";function u(e,t=e=>e){let n=new s;return{resolve(r){return r?t(r):n.getStore()??e},async run(e,r){return e?await n.run(t(e),r):await r()},hasScope(){return!!n.getStore()}}}function d(e,t){return t===`user-installed`?e.filter(e=>!e.bundleId.startsWith(`com.apple.`)):e}function f(e,n){return{openBundle:async(t,n)=>{await e(`open`,p(t,n))},openTarget:async t=>{await e(`open`,[t])},readClipboard:async()=>r(await e(`pbpaste`,[],{allowFailure:!0}),`Failed to read macOS clipboard`).stdout.replace(/\r\n/g,`
|
|
2
|
+
`).replace(/\n$/,``),writeClipboard:async t=>{r(await e(`pbcopy`,[],{allowFailure:!0,stdin:t}),`Failed to write macOS clipboard`)},readDarkMode:async()=>{let n=r(await e(`osascript`,[`-e`,`tell application "System Events" to tell appearance preferences to get dark mode`],{allowFailure:!0}),`Failed to read macOS appearance`),i=n.stdout.trim().toLowerCase();if(i===`true`)return!0;if(i===`false`)return!1;throw new t(`COMMAND_FAILED`,`Unable to determine current macOS appearance from osascript output: ${n.stdout.trim()}`)},setDarkMode:async t=>{r(await e(`osascript`,[`-e`,`tell application "System Events" to tell appearance preferences to set dark mode to ${t?`true`:`false`}`],{allowFailure:!0}),`Failed to set macOS appearance`)},listApps:async t=>await m(e,n,t)}}function p(e,t){let n=[`-b`,e];return t&&n.push(t),n}async function m(e,t,n){let r=[`/Applications`,`/System/Applications`,o.join(l.homedir(),`Applications`)],i=new Set;for(let t of r){if(!(await c.stat(t).catch(()=>null))?.isDirectory())continue;let n=await e(`find`,[t,`-maxdepth`,`4`,`-type`,`d`,`-name`,`*.app`],{allowFailure:!0});if(n.exitCode===0)for(let e of n.stdout.split(`
|
|
3
|
+
`)){let t=e.trim();t&&i.add(t)}}return d((await Promise.all(Array.from(i).map(async e=>{let n=await h(e,t).catch(()=>({})),r=n.bundleId;return r?{bundleId:r,name:n.appName??o.basename(e,`.app`)}:null}))).filter(e=>e!==null).sort((e,t)=>e.name.localeCompare(t.name)),n)}async function h(e,t){for(let n of[o.join(e,`Contents`,`Info.plist`),o.join(e,`Info.plist`)]){let e=await t(n),r=g(e,`CFBundleIdentifier`),i=g(e,`CFBundleDisplayName`),a=g(e,`CFBundleName`);if(r||i||a)return{bundleId:r,appName:i??a}}return{}}function g(e,t){let n=e?.[t];return typeof n==`string`&&n.trim()?n.trim():void 0}var _=e({createLocalAppleToolProvider:()=>b,hasScopedAppleToolProvider:()=>C,readApplePlistJson:()=>E,resolveAppleToolProvider:()=>x,runAppleToolCommand:()=>w,runXcrun:()=>T,withAppleToolProvider:()=>S});const v={runCommand:i,simctl:{run:async(e,t)=>await i(`xcrun`,[`simctl`,...e],t)},devicectl:{run:async(e,t)=>await i(`xcrun`,[`devicectl`,...e],t)},plist:{readJson:async e=>await A(i,e)},macosHost:f(i,async e=>await A(i,e)),whichCommand:a},y=u(v,D);function b(e={}){let t={...v,...e},n=e.plist??{readJson:async e=>await A(t.runCommand,e)};return{...t,simctl:e.simctl??{run:async(e,n)=>await t.runCommand(`xcrun`,[`simctl`,...e],n)},devicectl:e.devicectl??{run:async(e,n)=>await t.runCommand(`xcrun`,[`devicectl`,...e],n)},plist:n,macosHost:e.macosHost??f(t.runCommand,async e=>await n.readJson(e))}}function x(e){return y.resolve(e)}async function S(e,t){return await y.run(e,t)}function C(){return y.hasScope()}async function w(e,t,n){return await x().runCommand(e,t,n)}async function T(e,t){let n=x(),[r,...i]=e;return r===`simctl`?await(n.simctl?.run(i,t)??n.runCommand(`xcrun`,e,t)):r===`devicectl`?await(n.devicectl?.run(i,t)??n.runCommand(`xcrun`,e,t)):await w(`xcrun`,e,t)}async function E(e){return await x().plist?.readJson(e)??null}function D(e){return b(typeof e==`function`?{runCommand:O(e)}:{...e,runCommand:O(e.runCommand),...e.simctl?{simctl:{run:k(e.simctl.run)}}:{},...e.devicectl?{devicectl:{run:k(e.devicectl.run)}}:{},...e.macosHelper?{macosHelper:{run:k(e.macosHelper.run)}}:{}})}function O(e){return async(t,r,i)=>n(await e(t,r,i))}function k(e){return async(t,r)=>n(await e(t,r))}async function A(e,t){try{let n=await e(`plutil`,[`-convert`,`json`,`-o`,`-`,t],{allowFailure:!0});return n.exitCode!==0||!n.stdout.trim()?null:JSON.parse(n.stdout)}catch{return null}}export{T as a,u as c,w as i,E as n,_ as o,x as r,d as s,C as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{j as n,v as r,w as i}from"./sdk-android-adb.js";import{t as a}from"./timeouts.js";import{c as o}from"./tool-provider.js";var s=e({createLocalLinuxToolProvider:()=>u,resolveLinuxToolProvider:()=>d,runLinuxToolCommand:()=>p,withLinuxToolProvider:()=>f});const c={runCommand:r,whichCommand:i,desktop:m(r,i),clipboard:h(r,i),screenshot:g(r,i)},l=o(c,u);function u(e={}){let t={...c,...e};return{...t,desktop:e.desktop??m(t.runCommand,t.whichCommand),clipboard:e.clipboard??h(t.runCommand,t.whichCommand),screenshot:e.screenshot??g(t.runCommand,t.whichCommand)}}function d(e){return l.resolve(e)}async function f(e,t){return await l.run(e,t)}async function p(e,t,n){return await d().runCommand(e,t,n)}function m(e,t){return{async openTarget(r){if(r.includes(`://`)||r.startsWith(`/`)){await e(`xdg-open`,[r]);return}if(await t(r)){e(r,[],{allowFailure:!0}).catch(e=>{n({level:`warn`,phase:`linux_app_launch`,data:{app:r,error:String(e)}})}),await a(500);return}await e(`xdg-open`,[r],{allowFailure:!0})},async closeApp(n){if(await t(`wmctrl`)){await e(`wmctrl`,[`-c`,n],{allowFailure:!0});return}await e(`pkill`,[`-x`,n],{allowFailure:!0})}}}function h(e,t){return{async readText(){let n=await C(t,v),r=b[n];return(await e(r.cmd,r.args,r.options)).stdout},async writeText(n){let r=await C(t,v),i=x[r](n);await e(i.cmd,i.args,i.options)}}}function g(e,t){return{async capture(n){let r=await C(t,y),i=S[r](n);await e(i.cmd,i.args,i.options)}}}const _=5e3,v={wayland:[{tool:`wl-clipboard`,command:`wl-paste`}],x11:[{tool:`xclip`,command:`xclip`},{tool:`xsel`,command:`xsel`}],waylandError:`wl-paste (wl-clipboard) is required for clipboard access on Wayland. Install via your package manager.`,x11Error:`xclip or xsel is required for clipboard access on X11. Install via your package manager.`},y={wayland:[{tool:`grim`,command:`grim`},{tool:`gnome-screenshot`,command:`gnome-screenshot`}],x11:[{tool:`scrot`,command:`scrot`},{tool:`import`,command:`import`},{tool:`gnome-screenshot`,command:`gnome-screenshot`}],waylandError:`grim or gnome-screenshot is required for screenshots on Wayland. Install via your package manager.`,x11Error:`scrot, import (ImageMagick), or gnome-screenshot is required for screenshots on X11. Install via your package manager.`},b={"wl-clipboard":{cmd:`wl-paste`,args:[`--no-newline`],options:{allowFailure:!0,timeoutMs:_}},xclip:{cmd:`xclip`,args:[`-selection`,`clipboard`,`-o`],options:{allowFailure:!0,timeoutMs:_}},xsel:{cmd:`xsel`,args:[`--clipboard`,`--output`],options:{allowFailure:!0,timeoutMs:_}}},x={"wl-clipboard":e=>({cmd:`wl-copy`,args:[`--`,e],options:{allowFailure:!1,timeoutMs:_}}),xclip:e=>({cmd:`xclip`,args:[`-selection`,`clipboard`],options:{allowFailure:!1,timeoutMs:_,stdin:e}}),xsel:e=>({cmd:`xsel`,args:[`--clipboard`,`--input`],options:{allowFailure:!1,timeoutMs:_,stdin:e}})},S={grim:e=>({cmd:`grim`,args:[e]}),scrot:e=>({cmd:`scrot`,args:[e]}),import:e=>({cmd:`import`,args:[`-window`,`root`,e]}),"gnome-screenshot":e=>({cmd:`gnome-screenshot`,args:[`-f`,e]})};async function C(e,n){let r=w()?`wayland`:`x11`;for(let t of n[r])if(await e(t.command))return t.tool;throw new t(`TOOL_MISSING`,r===`wayland`?n.waylandError:n.x11Error)}function w(){return!!process.env.WAYLAND_DISPLAY||process.env.XDG_SESSION_TYPE===`wayland`}export{p as n,s as r,d as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{v as t,w as n}from"./sdk-android-adb.js";import{c as r}from"./tool-provider.js";import i from"node:path";import{constants as a}from"node:fs";import o from"node:os";import{access as s}from"node:fs/promises";var c=e({createLocalVegaToolProvider:()=>d,resolveVegaToolProvider:()=>f,withVegaToolProvider:()=>p});const l={run:async(e,n)=>await t(await h()??`vega`,e,n),isAvailable:async()=>!!await h()},u=r(d());function d(e=l){return{isAvailable:async()=>await e.isAvailable(),version:async t=>await e.run([`--version`],t),listDevices:async t=>await e.run([`device`,`list`],t),checkConnected:async(t,n)=>await e.run([`device`,`is-connected`,`--device`,t],n),launchApp:async(t,n,r)=>await e.run([`device`,`launch-app`,`--device`,t,`--appName`,n],r),terminateApp:async(t,n,r)=>await e.run([`device`,`terminate-app`,`--device`,t,`--appName`,n],r),pressRemote:async(t,n,r,i)=>await e.run([`device`,`run-cmd`,`--device`,t,`--command`,[`inputd-cli`,`button_press`,n,...r===void 0?[]:[`--holdDuration`,String(r)]].join(` `)],i)}}function f(e){return u.resolve(e)}async function p(e,t){return await u.run(e,t)}let m;async function h(){if(m)return m;if(await n(`vega`))return m=`vega`,m;let e=i.join(o.homedir(),`vega`,`bin`,`vega`);try{await s(e,a.X_OK),m=e}catch{return}return m}export{c as n,f as t};
|
package/dist/src/update-check.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as e}from"./sdk-android-adb.js";import t from"node:
|
|
1
|
+
import{b as e}from"./sdk-android-adb.js";import t from"node:path";import n from"node:fs";import{fileURLToPath as r}from"node:url";const i=`agent-device`,a=`--agent-device-run-update-check`;function o(e){if(!c(e))return;let n=Date.now(),r=t.join(e.stateDir,`update-check.json`),a=d(r);l(a,e.currentVersion)&&(process.stderr.write(`Update available: ${i} ${e.currentVersion} -> ${a.latestVersion}. Run \`npm install -g ${i}@latest\` to upgrade the CLI and bundled skills.\n`),f(r,{...a,prompted:!0})),u(a,n)&&m(r,e.currentVersion)}async function s(e){let t=Date.now(),n=d(e.cachePath);try{let r=await h()??void 0;if(!r||_(r,e.currentVersion)<=0){f(e.cachePath,{checkedAt:new Date(t).toISOString()});return}f(e.cachePath,{checkedAt:new Date(t).toISOString(),latestVersion:r,prompted:n.latestVersion===r?n.prompted===!0:!1})}catch{f(e.cachePath,{...n,checkedAt:new Date(t).toISOString()})}}function c(e){return!e.command||e.command===`help`||e.command===`test`||e.flags.help||e.flags.version||e.flags.json||process.env.CI?.trim()||process.env.NODE_ENV===`test`||process.env.AGENT_DEVICE_NO_UPDATE_NOTIFIER?.trim()?!1:!!process.stderr.isTTY}function l(e,t){return!e.latestVersion||_(e.latestVersion,t)<=0?!1:e.prompted!==!0}function u(e,t){let n=g(e.checkedAt);return n===void 0||t-n>=12096e5}function d(e){try{let t=JSON.parse(n.readFileSync(e,`utf8`));return{checkedAt:typeof t.checkedAt==`string`?t.checkedAt:void 0,latestVersion:typeof t.latestVersion==`string`?t.latestVersion:void 0,prompted:t.prompted===!0}}catch{return{}}}function f(e,r){try{n.mkdirSync(t.dirname(e),{recursive:!0}),n.writeFileSync(e,`${JSON.stringify(r,null,2)}\n`,`utf8`)}catch{}}function p(){let e=r(import.meta.url),i=t.extname(e)||`.js`,a=[t.join(t.dirname(e),`update-check-entry${i}`),t.join(t.dirname(e),`internal`,`update-check-entry${i}`)].find(e=>n.existsSync(e));if(!a)throw Error(`Update check entrypoint not found. Rebuild the package to include the update-check worker entry.`);return a}function m(t,n){let r=p(),i=r.endsWith(`.ts`)?[`--experimental-strip-types`]:[];e(process.execPath,[...i,r,a,t,n])}async function h(){let e=await fetch(`https://registry.npmjs.org/${i}/latest`,{signal:AbortSignal.timeout(3500),headers:{accept:`application/json`}});if(!e.ok)return;let t=await e.json();return typeof t.version==`string`&&t.version.trim().length>0?t.version.trim():void 0}function g(e){if(!e)return;let t=Date.parse(e);return Number.isNaN(t)?void 0:t}function _(e,t){return e.localeCompare(t,void 0,{numeric:!0})}function v(e){if(e[0]!==a)return null;let t=e[1]?.trim(),n=e[2]?.trim();return!t||!n?null:{cachePath:t,currentVersion:n}}export{v as n,s as r,o as t};
|
package/dist/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"node:
|
|
1
|
+
import e from"node:path";import t from"node:fs";import{fileURLToPath as n}from"node:url";function r(n=i()){try{let r=JSON.parse(t.readFileSync(e.join(n,`package.json`),`utf8`));return typeof r.version==`string`?r.version:`0.0.0`}catch{return`0.0.0`}}function i(){let r=e.dirname(n(import.meta.url)),i=r;for(let n=0;n<6;n+=1){let n=e.join(i,`package.json`);if(t.existsSync(n))return i;i=e.dirname(i)}return r}export{r as n,i as t};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import{E as e,S as t,_ as n,d as r,f as i,g as a,p as o,u as s}from"./sdk-contracts.js";import{$ as c,b as l,et as u,t as d,x as f,y as p}from"./screenshot-geometry.js";import{B as m,H as h,R as g,U as _,V as ee,b as te,it as v,z as ne}from"./sdk-batch-runner.js";import{d as re}from"./sdk-device.js";import{$ as ie,G as ae,H as oe,J as se,K as y,R as ce,U as le,W as ue,X as de,Y as fe,Z as pe,a as me,at as he,b,c as ge,ct as _e,dt as ve,et as ye,g as be,lt as x,n as xe,nt as Se,o as Ce,r as we,s as S,t as Te,tt as Ee,u as De,ut as Oe,v as ke,x as Ae,z as je}from"./sdk-selectors.js";import{b as Me,w as Ne,y as Pe}from"./device.js";import Fe from"node:path";import{styleText as Ie}from"node:util";import{createHash as Le}from"node:crypto";const Re=[`out`,`overlayRefs`,`screenshotPixelDensity`,`screenshotFullscreen`,`screenshotMaxSize`,`screenshotNoStabilize`,`screenshotNormalizeStatusBar`],ze=[`screenshotPixelDensity`,`screenshotFullscreen`,`screenshotMaxSize`,`screenshotNoStabilize`,`screenshotNormalizeStatusBar`],Be=[{key:`screenshotPixelDensity`,names:[`--pixel-density`],type:`int`,min:1,usageLabel:`--pixel-density <n>`,usageDescription:`Screenshot: output PNG pixel density in pixels per logical point (currently supported on iOS simulators)`},{key:`screenshotFullscreen`,names:[`--fullscreen`,`--full`,`-f`],type:`boolean`,usageLabel:`--fullscreen, --full, -f`,usageDescription:`Screenshot: on web capture the full page; on macOS app sessions capture the full desktop instead of the app window`},{key:`screenshotMaxSize`,names:[`--max-size`],type:`int`,min:1,usageLabel:`--max-size <px>`,usageDescription:`Screenshot/record: downscale so the longest edge is at most <px>`},{key:`screenshotNoStabilize`,names:[`--no-stabilize`],type:`boolean`,usageLabel:`--no-stabilize`,usageDescription:`Screenshot: skip Android demo-mode/status-bar stabilization and settle delay for low-latency capture loops`},{key:`screenshotNormalizeStatusBar`,names:[`--normalize-status-bar`],type:`boolean`,usageLabel:`--normalize-status-bar`,usageDescription:`Screenshot: on iOS simulators temporarily normalize status-bar chrome for deterministic screenshot diffs`}],Ve=[{tokens:[`--fullscreen`,`--full`,`-f`],key:`screenshotFullscreen`},{tokens:[`--no-stabilize`],key:`screenshotNoStabilize`},{tokens:[`--normalize-status-bar`],key:`screenshotNormalizeStatusBar`}],He=[{token:`--pixel-density`,key:`screenshotPixelDensity`,label:`screenshot --pixel-density`},{token:`--max-size`,key:`screenshotMaxSize`,label:`screenshot --max-size`}];function Ue(e){return qe({overlayRefs:e?.overlayRefs,pixelDensity:e?.screenshotPixelDensity,fullscreen:e?.screenshotFullscreen,maxSize:e?.screenshotMaxSize,stabilize:e?.screenshotNoStabilize?!1:void 0,normalizeStatusBar:e?.screenshotNormalizeStatusBar})}function We(e={}){return qe({overlayRefs:e.overlayRefs,screenshotPixelDensity:e.screenshotPixelDensity??e.pixelDensity,screenshotFullscreen:e.screenshotFullscreen??e.fullscreen,screenshotMaxSize:e.screenshotMaxSize??e.maxSize,screenshotNoStabilize:e.screenshotNoStabilize??(e.stabilize===!1?!0:void 0),screenshotNormalizeStatusBar:e.screenshotNormalizeStatusBar??e.normalizeStatusBar})}function Ge(e,t){typeof t?.screenshotPixelDensity==`number`&&e.push(`--pixel-density`,String(t.screenshotPixelDensity)),t?.screenshotFullscreen&&e.push(`--fullscreen`),typeof t?.screenshotMaxSize==`number`&&e.push(`--max-size`,String(t.screenshotMaxSize)),t?.screenshotNoStabilize&&e.push(`--no-stabilize`),t?.screenshotNormalizeStatusBar&&e.push(`--normalize-status-bar`)}function Ke(e){let{args:t,flags:n,index:r}=e,i=t[r];return Je(i,n,r)??Ye({args:t,index:r,flags:n,token:i})??{handled:!1}}function qe(e){return Object.fromEntries(Object.entries(e).filter(e=>e[1]!==void 0))}function Je(e,t,n){let r=Ve.find(t=>t.tokens.some(t=>t===e));if(r)return t[r.key]=!0,{handled:!0,nextIndex:n}}function Ye(e){let t=He.find(t=>t.token===e.token);if(!t)return;let r=e.args[e.index+1],i=r===void 0?NaN:Number(r);if(!Number.isInteger(i)||i<1)throw new n(`INVALID_ARGS`,`${t.label} requires a positive integer`);return e.flags[t.key]=i,{handled:!0,nextIndex:e.index+1}}const Xe=3e5,Ze=[`leaseId`,`tenantId`,`runId`,`clientId`,`deviceKey`];function Qe(e){return v({tenantId:e.meta?.tenantId??C(e.flags,`tenant`),runId:e.meta?.runId??C(e.flags,`runId`),leaseId:e.meta?.leaseId??C(e.flags,`leaseId`),leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend,leaseProvider:e.meta?.leaseProvider??C(e.flags,`leaseProvider`)??C(e.flags,`provider`),deviceKey:e.meta?.deviceKey??C(e.flags,`deviceKey`),clientId:e.meta?.clientId??C(e.flags,`clientId`)})}function $e(e){return v({tenantId:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseTtlMs:e.leaseTtlMs??e.ttlMs,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider??e.provider,deviceKey:e.deviceKey,clientId:e.clientId})}function et(e){return v({tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId,leaseTtlMs:e.leaseTtlMs,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId})}function tt(e){return v({tenant:e.tenantId,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId})}function nt(e){return v({tenantId:e.tenantId??``,runId:e.runId??``,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId,ttlMs:e.leaseTtlMs})}function rt(e){return lt(e)}function it(e){let{ttlMs:t,...n}=lt(e);return n}function at(e,t,n){let r=v({...n.includeTokenParam?{token:n.token}:{},session:n.session,tenantId:e.tenantId,runId:e.runId,leaseProvider:e.leaseProvider,clientId:e.clientId,deviceKey:e.deviceKey});switch(t){case`lease_allocate`:return{...r,...v({ttlMs:e.leaseTtlMs,backend:e.leaseBackend})};case`lease_heartbeat`:return{...r,...v({leaseId:e.leaseId,ttlMs:e.leaseTtlMs})};case`lease_release`:return{...r,...v({leaseId:e.leaseId})}}}function ot(e){let t=v({leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId});return Object.keys(t).length>0?t:void 0}function st(e){return e.leaseProvider===`proxy`}function ct(e){return st(e)?Ze.filter(t=>!e[t]):[]}function lt(e){return v({leaseId:e.leaseId??``,tenantId:e.tenantId,runId:e.runId,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId,ttlMs:e.leaseTtlMs})}function C(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}function w(e){return e?{message:e}:{}}function T(e,t){return t?{...e,message:t}:e}function ut(e){return typeof e?.message==`string`&&e.message.length>0?e.message:null}function dt(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function ft(e,t,n){return{deviceId:t,deviceName:n,...re(e)?{serial:t}:e===`ios`?{udid:t}:{}}}function pt(e,t={}){let n=t.includeSerial??!0,r=mt(e);return{platform:e.platform,target:e.target,device:e.name,id:e.id,...e.platform===`ios`?{device_udid:e.ios?.udid??e.id,ios_simulator_device_set:e.ios?.simulatorSetPath??null}:{},...n&&r?{serial:r}:{}}}function mt(e){return re(e.platform)?e.identifiers.serial??e.id:void 0}function ht(e){return{name:e.name,...e.sessionStateDir?{sessionStateDir:e.sessionStateDir}:{},...e.runnerLogPath?{runnerLogPath:e.runnerLogPath}:{},...pt(e.device,{includeSerial:!1}),createdAt:e.createdAt}}function gt(e){return{platform:e.platform,...e.appleOs?{appleOs:e.appleOs}:{},id:e.id,name:e.name,kind:e.kind,target:e.target,...typeof e.booted==`boolean`?{booted:e.booted}:{}}}function _t(e){return e.bundleId??e.package??e.app}function vt(e){return T({app:e.app,appPath:e.appPath,platform:e.platform,...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.package?{package:e.package}:{}},`Installed: ${_t(e)}`)}function yt(e){return e.appName??e.bundleId??e.packageName??e.launchTarget}function bt(e){return T({launchTarget:e.launchTarget,...e.appName?{appName:e.appName}:{},...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.packageName?{package:e.packageName}:{},...e.installablePath?{installablePath:e.installablePath}:{},...e.archivePath?{archivePath:e.archivePath}:{},...e.materializationId?{materializationId:e.materializationId}:{},...e.materializationExpiresAt?{materializationExpiresAt:e.materializationExpiresAt}:{}},`Installed: ${yt(e)}`)}function xt(e){let t=e.appName??e.appBundleId??e.session;return T({session:e.session,...e.warnings?.length?{warnings:e.warnings}:{},...e.sessionStateDir?{sessionStateDir:e.sessionStateDir}:{},...e.runnerLogPath?{runnerLogPath:e.runnerLogPath}:{},...e.requestLogPath?{requestLogPath:e.requestLogPath}:{},...e.eventLogPath?{eventLogPath:e.eventLogPath}:{},...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.startup?{startup:e.startup}:{},...e.runtime?{runtime:e.runtime}:{},...e.device?pt(e.device):{}},t?`Opened: ${t}`:`Opened`)}function St(e){return{session:e.session,...e.shutdown?{shutdown:e.shutdown}:{},...`provider`in e&&e.provider?{provider:e.provider}:{},...w(e.session?`Closed: ${e.session}`:`Closed`)}}function Ct(e){return{nodes:e.nodes,truncated:e.truncated,...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.visibility?{visibility:e.visibility}:{},...u(wt(e)),...e.unchanged?{unchanged:e.unchanged}:{},...e.snapshotDiagnostics?{snapshotDiagnostics:e.snapshotDiagnostics}:{},...e.refsGeneration===void 0?{}:{refsGeneration:e.refsGeneration}}}function wt(e){return{...e,...e.snapshotQuality?{quality:e.snapshotQuality}:{}}}const Tt=jt(`public`),Et=jt(`internal`),Dt=jt(`local-cli`),Ot={help:`help`};function kt(){return[...Object.values(Tt),...Object.values(Dt)].sort()}function At(e){return Object.values(Ot).includes(e)||Object.values(Et).includes(e)?!0:kt().includes(e)}function jt(e){let t={};for(let[n,r]of te(e))t[n]=r;return t}const Mt=[`medium`,`high`],Nt=`medium`;function Pt(e){return Mt.includes(e)}function Ft(e){let t=typeof e==`number`?e:It(e);return t!==void 0&&Number.isInteger(t)&&t>=5&&t<=10?t:void 0}function It(e){return typeof e==`string`&&/^\d+$/.test(e)?Number(e):void 0}function Lt(e){if(Pt(e))return e;let t=Ft(e);if(t!==void 0)return t<=7?`medium`:`high`}const Rt=[`app`,`device`,`system`];function zt(e){return e===`device`||e===`system`}const Bt=[`app`,`frontmost-app`,`desktop`,`menubar`],Vt=c(Bt,{normalize:e=>e.trim().toLowerCase(),message:e=>`Invalid surface: ${e}. Use ${Bt.join(`|`)}.`});function Ht(e){return Vt.parse(e)}const Ut=`--launch-console is supported only for iOS simulator app launches`,Wt=`--launch-console requires a direct app launch and cannot be used with URL opens`,Gt=[`path`,`start`,`stop`,`doctor`,`mark`,`clear`],Kt=[`metrics`,`frames`,`memory`,`cpu`,`trace`],qt=[`sample`,`snapshot`,`start`,`stop`,`report`],Jt=[`profile`],Yt=[`xctrace`,`simpleperf`,`perfetto`,`android-hprof`,`memgraph`],Xt=[`android-hprof`,`memgraph`],Zt=c(Kt),Qt=c(qt),$t=c(Jt),en=c(Yt),tn=c(Xt),nn=`perf area must be metrics, frames, memory, cpu, or trace`,rn=`perf action must be sample, snapshot, start, stop, or report`,an=`perf cpu requires profile`,on=`perf --kind must be xctrace, simpleperf, perfetto, android-hprof, or memgraph`,sn=`perf memory snapshot --kind must be android-hprof or memgraph`,cn=Zt.is,ln=Qt.is,un=$t.is,dn=en.is,fn=tn.is;function E(e){return e.width>0&&e.height>0}function pn(e,t){return!e||!t?!1:e.x>=t.x-2&&e.y>=t.y-2&&e.x+e.width<=t.x+t.width+2&&e.y+e.height<=t.y+t.height+2}function mn(e,t){if(!e||!t)return!0;let n=e.y+e.height/2,r=t.y+t.height/2;return Math.abs(n-r)<=Math.max(e.height,t.height,1)}function hn(e){return typeof e.parentIndex!=`number`}function D(e){let t=(e.type??``).toLowerCase(),n=(e.identifier??``).trim().toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)||n===`composer`}function gn(e){let t=(e.type??``).toLowerCase();return t.includes(`scroll`)||t.includes(`list`)||t.includes(`recyclerview`)}function O(e){let t=he(e);if(!t||t!==e.identifier?.trim()||!_n(t))return t;let n=(e.type??``).toLowerCase();return n.includes(`view`)||n.includes(`layout`)||n.includes(`image`)||n.includes(`list`)||n.includes(`recyclerview`)||n.includes(`collection`)?``:t}function k(e){let t=e.trim().replace(/\s+/g,` `).toLowerCase();return!t||/^(true|false|\d+)$/.test(t)?null:t}function _n(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function vn(e,t,n){let r=e;for(;typeof r.parentIndex==`number`;){let e=t.get(r.parentIndex);if(!e)return null;if(n(e))return e;r=e}return null}function yn(e,t){let n=[],r=[t];for(;r.length>0;){let t=r.pop();for(let i of e)i.parentIndex===t&&(n.push(i),r.push(i.index))}return n}function A(e,t,n){let r=[t];for(;r.length>0;){let t=r.pop();if(!n.has(t)){n.add(t);for(let i of e)i.parentIndex!==t||n.has(i.index)||r.push(i.index)}}}const bn=[`button`,`switch`,`checkbox`,`radio`],xn=[`button`,`image`,`textview`,`view`];function Sn(e,t,n){for(let r of e){if(t.has(r.index)||!Tn(r))continue;let i=En(yn(e,r.index),r,t);if(i.label){n.set(r.index,{...r,...n.get(r.index),label:i.label});for(let n of i.removableIndexes)A(e,n,t)}}}function Cn(e,t,n){let r=new Map;for(let i of e){if(t.has(i.index)||!Nn(i))continue;let a=k(O(i));if(!a)continue;let o=r.get(a);if(o&&An(o,i,t)){let s=jn(e,o,i,t,n);r.set(a,s);continue}r.set(a,i)}}function wn(e,t){for(let n of e){if(t.has(n.index)||!On(n))continue;let r=k(O(n));if(!r)continue;let i=yn(e,n.index).filter(e=>!t.has(e.index)&&kn(n,e,r));for(let n of i.filter(Dn))A(e,n.index,t);let a=i.filter(e=>!Dn(e)),o=new Set(a.map(e=>k(O(e))).filter(e=>!!e));if(!(a.length<2||o.size<2))for(let n of a)A(e,n.index,t)}}function Tn(e){return e.hittable===!0&&!D(e)&&!!(e.rect&&E(e.rect))&&O(e).trim().length===0}function En(e,t,n){let r=[],i=[],a=new Set;for(let o of e){if(n.has(o.index)||!Dn(o)||!pn(o.rect,t.rect))continue;let e=O(o).trim().replace(/\s+/g,` `),s=k(e);i.push(o.index),!(!e||!s||a.has(s))&&(a.add(s),r.push(e))}return{label:r.join(`, `),removableIndexes:i}}function Dn(e){if(e.hittable===!0||D(e))return!1;let t=(e.type??``).toLowerCase();return t.includes(`text`)||t.includes(`image`)||t.includes(`icon`)}function On(e){return e.hittable===!0&&!D(e)&&!!(e.rect&&E(e.rect))&&!!k(O(e))}function kn(e,t,n){if(!Nn(t)||!pn(t.rect,e.rect))return!1;let r=k(O(t));return!!(r&&n!==r&&n.includes(r))}function An(e,t,n){return!n.has(e.index)&&mn(e.rect,t.rect)&&(Rn(e,t)||Ln(e,t))}function jn(e,t,n,r,i){let a=Pn(t,n),o=a.index===t.index?n:t,s=(o.type??``).toLowerCase().includes(`image`)?`has image`:null,c=i.get(a.index)??a,l=i.get(o.index)?.presentationHints??o.presentationHints;return i.set(a.index,{...c,presentationHints:Mn(c.presentationHints,l,s)}),A(e,o.index,r),i.get(a.index)??a}function Mn(e,t,n){return[...new Set([...Array.isArray(e)?e:[],...Array.isArray(t)?t:[],...n?[n]:[]])]}function Nn(e){if(!e.rect||!E(e.rect)||hn(e)||D(e))return!1;let t=(e.type??``).toLowerCase();return t===`text`||In(t,xn)}function Pn(e,t){let n=Fn(e);return Fn(t)>n?t:e}function Fn(e){let t=(e.type??``).toLowerCase(),n=0;return In(t,bn)?n+=100:t.includes(`image`)?n+=30:t.includes(`textview`)||t===`text`?n+=20:t.includes(`view`)&&(n+=10),e.hittable===!0&&(n+=20),e.enabled!==!1&&(n+=5),n}function In(e,t){return t.some(t=>e.includes(t))}function Ln(e,t){let n=e.parentIndex===t.index?t:t.parentIndex===e.index?e:null,r=n?.index===e.index?t:n?.index===t.index?e:null;return!n||!r?!1:Pn(n,r).index===n.index}function Rn(e,t){return e.parentIndex===t.parentIndex?Math.abs(e.index-t.index)<=3:e.parentIndex===t.index||t.parentIndex===e.index?!1:Math.abs((e.depth??0)-(t.depth??0))<=1&&Math.abs(e.index-t.index)<=2}function zn(e,t,n){if(n.raw||!Bn(e))return{nodes:t,filteredCount:0};let r=Vn(t);return{nodes:r,filteredCount:t.length-r.length}}function Bn(e){let t=e.androidSnapshot;return!t||typeof t!=`object`?!1:t.backend===`android-helper`}function Vn(e){if(e.length===0)return e;let t=new Set,n=new Map,r=new Map(e.map(e=>[e.index,e]));return Hn(e,t),Un(e,r,t,n),Sn(e,t,n),wn(e,t),Cn(e,t,n),e.filter(e=>!t.has(e.index)).map(e=>n.get(e.index)??e)}function Hn(e,t){for(let n of e)!n.rect||E(n.rect)||hn(n)||A(e,n.index,t)}function Un(e,t,n,r){for(let i of e){if(n.has(i.index)||i.rect||hn(i))continue;let a=vn(i,t,gn);a&&Gn(r,a,Wn(i,e)),A(e,i.index,n)}}function Wn(e,t){let n=t.filter(t=>t.parentIndex===e.parentIndex&&t.rect&&E(t.rect)).map(e=>e.index);return n.length===0?null:e.index<Math.min(...n)?`above`:e.index>Math.max(...n)?`below`:null}function Gn(e,t,n){if(!n)return;let r=e.get(t.index)??t;e.set(t.index,{...r,hiddenContentAbove:r.hiddenContentAbove===!0||n===`above`?!0:void 0,hiddenContentBelow:r.hiddenContentBelow===!0||n===`below`?!0:void 0})}function Kn(e){let t=e.trim().replace(/\s+/g,` `).toLowerCase();return!t||qn(t)?null:t}function qn(e){return/\S+@\S+\.\S+/.test(e)}function Jn(e){if(e.length<20)return!1;let t=new Map;for(let n of e){let e=(n.type??``).toLowerCase(),r=Kn(he(n));if(!r)continue;let i=`${e}|${r}`,a=t.get(i)??[];a.push(n),t.set(i,a)}let n=0;for(let e of t.values())e.length<=1||!Yn(e)||(n+=e.length);return n>=8}function Yn(e){for(let t=0;t<e.length;t+=1)for(let n=t+1;n<e.length;n+=1)if(Xn(e[t]?.rect,e[n]?.rect))return!0;return!1}function Xn(e,t){if(!e||!t)return!0;let n=.5;return!(e.x+e.width<=t.x+n||t.x+t.width<=e.x+n||e.y+e.height<=t.y+n||t.y+t.height<=e.y+n)}const Zn={digest:8*1024,default:24*1024,full:64*1024};function Qn(e){return e===`digest`||e===`full`?e:`default`}function $n(e,t=256){let n=Buffer.from(e,`utf8`);if(n.length<=t)return e;let r=`…<truncated>`,i=Buffer.byteLength(r,`utf8`),a=Math.max(0,t-i);for(;a>0&&(n[a]&192)==128;)--a;return`${n.subarray(0,a).toString(`utf8`)}${r}`}function j(t,n=256){return $n(e(t),n)}function er(e,t){let n=e;for(let e of t)e.value&&(n=n.split(e.value).join(`<var:${e.name}>`));return n}function tr(e){return(t,n)=>j(er(t,e),n)}function nr(e,t){return e.state!==`available`||e.refs.length<=t?e:{...e,refs:e.refs.slice(0,t),truncated:!0}}function rr(e,t){let n=Qn(t),r=n===`digest`?8:20,i=nr(e.screen,r),a=n===`digest`?[]:e.suggestions.slice(0,5);return{...e,screen:i,suggestions:a}}function ir(e){return Buffer.byteLength(JSON.stringify(e),`utf8`)}function ar(e){let{divergence:t,level:n,writeOverflowArtifact:r}=e,i=Qn(n),a=Zn[i],o=rr(t,n),s=ir(o);if(s<=a)return o;let c=s-a,l=r(rr(t,`full`)),u=or(o);return`artifactPath`in l?{...u,overflow:{omittedBytes:c,artifactPath:l.artifactPath}}:{...u,artifactUnavailable:!0}}function or(e){return{version:e.version,kind:e.kind,step:{index:e.step.index,source:{path:j(e.step.source.path),line:e.step.source.line}},action:j(e.action),cause:{code:e.cause.code,message:j(e.cause.message),...e.cause.hint?{hint:j(e.cause.hint)}:{}},screen:{state:`unavailable`,reason:`omitted-for-size`,hint:`The screen digest and suggestions were omitted to stay within the response byte budget. See overflow.artifactPath (or retry at --level full) for the complete report.`},suggestions:[],suggestionCount:e.suggestionCount,resume:e.resume,repairHint:e.repairHint,...e.targetBinding?{targetBinding:e.targetBinding}:{}}}function sr(e){let t=e?.divergence;if(!t||typeof t!=`object`)return null;let n=t,r=[...yr(n.step),...hr(n.kind,n.targetBinding),...cr(n.repairHint,n.resume),...br(n.screen),...wr(n.suggestions,n.suggestionCount),...Er(n.overflow,n.artifactUnavailable)];return r.length>0?r.join(`
|
|
2
|
+
`):null}function cr(e,t){if(typeof e!=`string`)return[];let n=dr(e,t);return[`Repair hint: ${e}${n?` — ${n}`:``}`]}function lr(e){let t=e;if(!t||typeof t.allowed!=`boolean`)return;if(!t.allowed)return{allowed:!1,reason:typeof t.reason==`string`?t.reason:void 0};let{from:n,planDigest:r,alternateFrom:i}=t;if(!(typeof n!=`number`||typeof r!=`string`||r.length===0))return{allowed:!0,from:n,planDigest:r,alternateFrom:typeof i==`number`?i:void 0}}function M(e,t){return`replay --from ${e} --plan-digest ${t}`}function ur(e){return e?.repairSessionHeld===!0}function dr(e,t){let n=fr(e,lr(t));if(n!==void 0)return ur(t)?`${n} Read-only inspection while armed (snapshot -i, get attrs, find, is) is excluded from the healed script by default — no --no-record needed. If the step you are repairing is itself a read, add --record to that command so it lands in the heal.`:n}function fr(e,t){switch(e){case`record-and-heal`:return t?.allowed?`press the correct control via a blessed @ref from screen.refs (recorded), then ${M(t.from,t.planDigest)}.`:`press the correct control via a blessed @ref from screen.refs (recorded). ${mr(t)}`;case`state-repair`:return t?.allowed?`fix app state with --no-record actions, then ${M(t.from,t.planDigest)} to re-run it.`:`fix app state with --no-record actions. ${mr(t)}`;case`caution`:return pr({lead:`something already matches the recorded selector; a blind re-press may repeat the mistake.`,guidance:t});case`manual`:return pr({lead:`no safe automated repair could be proven; inspect the screen and repair by hand.`,guidance:t});default:return}}function pr(e){let{lead:t,guidance:n}=e;if(!n?.allowed)return`${t} ${mr(n)}`;let r=`if you fixed app state with --no-record actions: ${M(n.from,n.planDigest)}`;return n.alternateFrom===void 0?`${t} ${r}.`:`${t} ${r}; ${`if you performed the step's intent as a recorded action: ${M(n.alternateFrom,n.planDigest)}`}.`}function mr(e){return e&&!e.allowed&&e.reason?`This step cannot currently be resumed automatically (${e.reason}) — run a fresh full replay instead.`:`This step cannot currently be resumed automatically — run a fresh full replay instead.`}function hr(e,t){if(typeof e!=`string`||e===`action-failure`)return[];let n=t;return n?[gr(e,n.matchCount),..._r(n.mismatches),...vr(n.candidates)]:[]}function gr(e,t){return`Target binding: ${e}${typeof t==`number`?` (matchCount ${t})`:``} — recorded target evidence did not verify.`}function _r(e){return!Array.isArray(e)||e.length===0?[]:[` mismatches: ${e.slice(0,5).join(`; `)}`]}function vr(e){return!Array.isArray(e)||e.length===0?[]:[` ${e.length} candidate(s) shared the recorded identity:`,...e.slice(0,5).map(e=>` ${Cr(e)}`)]}function yr(e){let t=e;if(typeof t?.index!=`number`)return[];let n=t.source,r=typeof n?.path==`string`&&typeof n.line==`number`?` (${n.path}:${n.line})`:``;return[`Divergence at step ${t.index}${r}`]}function br(e){let t=e;return t?.state===`available`&&Array.isArray(t.refs)?xr(t.refs,t.refsGeneration):t?.state===`unavailable`?[Sr(t)]:[]}function xr(e,t){let n=e.slice(0,8).map(Cr),r=e.length-n.length;return[`Screen: ${e.length} actionable ref(s) captured (refsGeneration ${t}).`,...n,...r>0?[` ... ${r} more`]:[]]}function Sr(e){let t=typeof e.hint==`string`&&e.hint.length>0?` ${e.hint}`:``;return`Screen: unavailable (${String(e.reason??`unknown`)}).${t}`}function Cr(e){let t=e,n=typeof t.label==`string`?` "${t.label}"`:``;return` @${String(t.ref)} [${String(t.role)}]${n}`}function wr(e,t){return Array.isArray(e)&&e.length>0?[`Suggestions:`,...e.slice(0,5).map(Tr)]:typeof t==`number`&&t>0?[`Suggestions: ${t} available (omitted at this response level; rerun with --json for the full report).`]:[]}function Tr(e){let t=e,n=typeof t.label==`string`?` "${t.label}"`:``;return` - [${String(t.basis)}]${n} ${String(t.selector)}`}function Er(e,t){return e&&typeof e==`object`?[`Full report written to ${String(e.artifactPath)}.`]:t===!0?[`Full report exceeded the response budget and the overflow artifact could not be written.`]:[]}const Dr={application:`application`,navigationbar:`navigation-bar`,tabbar:`tab-bar`,button:`button`,imagebutton:`button`,link:`link`,cell:`cell`,statictext:`text`,checkedtextview:`text`,textbox:`text-field`,textfield:`text-field`,edittext:`text-field`,textarea:`text-view`,switch:`switch`,slider:`slider`,image:`image`,imageview:`image`,webview:`webview`,framelayout:`group`,linearlayout:`group`,relativelayout:`group`,constraintlayout:`group`,viewgroup:`group`,view:`group`,listview:`list`,recyclerview:`list`,collectionview:`collection`,searchfield:`search`,heading:`heading`,activityindicator:`activity-indicator`,progressindicator:`progress-indicator`,segmentedcontrol:`segmented-control`,group:`group`,window:`window`,checkbox:`checkbox`,radio:`radio`,menuitem:`menu-item`,toolbar:`toolbar`,scrollarea:`scroll-area`,scrollview:`scroll-area`,nestedscrollview:`scroll-area`,table:`table`};function Or(e,t={}){let n=[],r=[];for(let i of e){let e=i.depth??0,a=i.label?.trim()||i.value?.trim()||i.identifier?.trim()||``,o=P(i.type??`Element`),s=i.inheritsLabel===!0||i.inheritsIdentifier===!0;if(o===`group`&&!a&&!s)continue;for(;n.length>0&&e<=n[n.length-1];)n.pop();let c=n.length;n.push(e),r.push({node:i,depth:c,type:o,text:kr(i,c,!1,o,t)})}return r}function kr(e,t,n,r,i={}){let a=r??P(e.type??`Element`),o=ue(e,a),s=Pr(e,a,i,o),c=` `.repeat(t),l=e.ref?`@${e.ref}`:``,u=Fr(e,a,i,o);!s&&(e.inheritsLabel===!0||e.inheritsIdentifier===!0)&&u.push(`same label as parent`);let d=u.map(e=>` [${e}]`).join(``),f=s?` "${s}"`:``;return n?`${c}${l} [${a}]${d}`.trimEnd():`${c}${l} [${a}]${f}${d}`.trimEnd()}function N(e,t){let n=e.label?.trim();if(n&&Mr(t,n))return``;let r=e.value?.trim();if(jr(t)){if(r)return r;if(n)return n}else if(n)return n;if(r)return r;let i=e.identifier?.trim();return!i||Nr(i)&&(t===`group`||t===`image`||t===`list`||t===`collection`)?``:i}function P(e){let t=e,n=e.replace(/XCUIElementType/gi,``).toLowerCase(),r=t.includes(`.`)&&(t.startsWith(`android.`)||t.startsWith(`androidx.`)||t.startsWith(`com.`));return n.includes(`.`)&&(n=n.replace(/^android\.widget\./,``).replace(/^android\.view\./,``).replace(/^android\.webkit\./,``).replace(/^androidx\./,``).replace(/^com\.google\.android\./,``).replace(/^com\.android\./,``),r&&n.includes(`.`)&&(n=n.slice(n.lastIndexOf(`.`)+1))),n===`textview`?r?`text`:`text-view`:Ar(n)||n||`element`}function Ar(e){return Object.prototype.hasOwnProperty.call(Dr,e)?Dr[e]:void 0}function jr(e){return e===`text-field`||e===`text-view`||e===`search`}function Mr(e,t){return e!==`scroll-area`&&e!==`list`&&e!==`collection`&&e!==`table`?!1:_e(t)}function Nr(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function Pr(e,t,n,r){return!n.summarizeTextSurfaces||!r.shouldSummarize?N(e,t):Ir(e,t,r.text)||N(e,t)}function Fr(e,t,n,r){let i=[];return e.enabled===!1&&i.push(`disabled`),i.push(...e.presentationHints??[]),!n.summarizeTextSurfaces||(e.selected===!0&&i.push(`selected`),e.focused===!0&&i.push(`focused`),jr(t)&&i.push(`editable`),Lr(e,t)&&i.push(`scrollable`),!r.shouldSummarize)?zr(i):(i.push(`preview:"${Rr(le(r.text))}"`),i.push(`truncated`),zr(i))}function Ir(e,t,n){let r=se(e.label);if(r&&r!==n)return r;let i=se(e.identifier);if(i&&!Nr(i)&&i!==n)return i;switch(t){case`text`:case`text-view`:return`Text view`;case`text-field`:return`Text field`;case`search`:return`Search field`;default:return``}}function Lr(e,t){if(t===`scroll-area`)return!0;let n=(e.type??``).toLowerCase(),r=`${e.role??``} ${e.subrole??``}`.toLowerCase();return n.includes(`scroll`)||r.includes(`scroll`)}function Rr(e){return e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}function zr(e){return[...new Set(e)]}function Br(e){process.stdout.write(`${JSON.stringify(e,null,2)}\n`)}function Vr(e,r={}){let i=e instanceof n?t(e):e;process.stderr.write(`Error (${i.code}): ${i.message}\n`),i.hint&&process.stderr.write(`Hint: ${i.hint}\n`),i.diagnosticId&&process.stderr.write(`Diagnostic ID: ${i.diagnosticId}\n`),i.logPath&&process.stderr.write(`Diagnostics Log: ${i.logPath}\n`);let a=sr(i.details);a&&process.stderr.write(`${a}\n`),r.showDetails&&i.details&&process.stderr.write(`${JSON.stringify(i.details,null,2)}\n`)}function Hr(e,t={}){let n=e.nodes,r=Array.isArray(n)?n:[],o=a(i(e.backend)?e.backend:void 0),s=zn(e,r,t),c=Kr(e),l=di(e,r,t,s),u=l.length>0?`${l.join(`
|
|
3
|
+
`)}\n`:``,d=t.raw?null:Ur(e);if(d)return`${c}${u}${Wr(d)}\n`;let f=t.raw||!o?null:fe(s.nodes),p=!!e.truncated,m=f?.nodes??r,h=t.raw||!o?null:Qr(e,f,m.length,r.length,s.filteredCount),g=qr(r.length,h,p);return r.length===0?`${c}${g}\n${u}`:t.raw?`${c}${g}\n${u}${Jr(r)}\n`:t.flatten?`${c}${g}\n${u}${Yr(m)}${Zr(f)}\n`:`${c}${g}\n${u}${Xr(m)}${Zr(f)}\n`}function Ur(e){let t=e.unchanged;if(!t||typeof t!=`object`)return null;let n=t;return typeof n.ageMs!=`number`||typeof n.nodeCount!=`number`?null:{ageMs:n.ageMs,nodeCount:n.nodeCount,interactiveOnly:n.interactiveOnly===!0?!0:void 0,scope:typeof n.scope==`string`?n.scope:void 0}}function Wr(e){let t=Gr(e.ageMs);return e.scope?[`Scoped snapshot unchanged for scope "${e.scope}" since previous read ${t} ago.`,`Previous refs in this scope remain valid. Use find/get/is for a targeted query, or --force-full to re-emit.`].join(`
|
|
4
|
+
`):e.interactiveOnly?[`Interactive snapshot unchanged since previous read ${t} ago.`,`${e.nodeCount} visible nodes are unchanged. Previous @e refs are still valid. Use find/get/is for a targeted query, or --force-full to re-emit.`].join(`
|
|
5
|
+
`):[`Snapshot unchanged since previous read ${t} ago.`,`Refs from the previous snapshot are still valid. Use --force-full to re-emit the tree, or use find/get/is for a targeted query.`].join(`
|
|
6
|
+
`)}function Gr(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(Math.round(e/100)/10).toFixed(1)}s`;let t=e/6e4;if(t<60)return`${(Math.round(t*10)/10).toFixed(1)}m`;let n=t/60;return`${(Math.round(n*10)/10).toFixed(1)}h`}function Kr(e){let t=typeof e.appName==`string`?e.appName:void 0,n=typeof e.appBundleId==`string`?e.appBundleId:void 0,r=[];return t&&r.push(`Page: ${t}`),n&&r.push(`App: ${n}`),r.length>0?`${r.join(`
|
|
7
|
+
`)}\n`:``}function qr(e,t,n){let r=n?` (truncated)`:``;return t?.partial?t.totalNodeCount>t.visibleNodeCount?`Snapshot: ${t.visibleNodeCount} visible nodes (${t.totalNodeCount} total)${r}`:`Snapshot: ${t.visibleNodeCount} visible nodes${r}`:`Snapshot: ${e} nodes${r}`}function Jr(e){return e.map(e=>JSON.stringify(e)).join(`
|
|
8
|
+
`)}function Yr(e){return yi(e).join(`
|
|
9
|
+
`)}function Xr(e){return gi(Or(e,{summarizeTextSurfaces:!0})).join(`
|
|
10
|
+
`)}function Zr(e){return e&&e.summaryLines.length>0?`\n${e.summaryLines.join(`
|
|
11
|
+
`)}`:``}function Qr(e,t,n,r,i=0){let a=$r(e);if(i===0&&a)return a;let o=(t?.hiddenCount??0)+i,s=t?t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow):!1;return o>0?{partial:!0,visibleNodeCount:n,totalNodeCount:Math.max(r,a?.totalNodeCount??r),reasons:ei([...a?.reasons??[],`offscreen-nodes`])}:a||(s?{partial:!0,visibleNodeCount:n,totalNodeCount:n,reasons:[]}:null)}function $r(e){let t=e.visibility;if(!t||typeof t!=`object`)return null;let n=t;return typeof n.partial!=`boolean`||typeof n.visibleNodeCount!=`number`||typeof n.totalNodeCount!=`number`||!Array.isArray(n.reasons)?null:{partial:n.partial,visibleNodeCount:n.visibleNodeCount,totalNodeCount:n.totalNodeCount,reasons:n.reasons.filter(e=>typeof e==`string`)}}function ei(e){return[...new Set(e)]}function ti(e){let t=e.baselineInitialized===!0,n=e.summary??{},r=F(n.additions),i=F(n.removals),a=F(n.unchanged),o=I(),s=hi(e),c=s.length>0?`${s.join(`
|
|
12
|
+
`)}\n`:``;if(t)return`${c}Baseline initialized (${a} lines).\n`;let l=li(Array.isArray(e.lines)?e.lines:[],1).map(e=>{let t=typeof e.text==`string`?e.text:``;if(e.kind===`added`){let e=t.startsWith(` `)?`+${t}`:`+ ${t}`;return o?L(e,`green`):e}if(e.kind===`removed`){let e=t.startsWith(` `)?`-${t}`:`- ${t}`;return o?L(e,`red`):e}return o?L(t,`dim`):t}),u=l.length>0?`${l.join(`
|
|
13
|
+
`)}\n`:``;return o?`${c}${u}${[`${L(String(r),`green`)} additions`,`${L(String(i),`red`)} removals`,`${L(String(a),`dim`)} unchanged`].join(`, `)}\n`:`${c}${u}${r} additions, ${i} removals, ${a} unchanged\n`}function ni(e){let t=I(),n=e.match===!0,r=e.dimensionMismatch,i=[];return i.push(...ri(e,t)),i.push(...ii(e,n,t)),!n&&!r&&(i.push(...ai(e,t)),i.push(...oi(e,t))),`${i.join(`
|
|
14
|
+
`)}\n`}function ri(e,t){if(e.match===!0)return[`${t?L(`✓`,`green`):`✓`} Screenshots match.`];let n=e.dimensionMismatch,r=t?L(`✗`,`red`):`✗`;if(n){let e=n.expected,t=n.actual;return[`${r} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let i=F(e.differentPixels),a=F(e.mismatchPercentage),o=`${a===0&&i>0?`<0.01`:String(a)}% pixels differ`;return[`${r} ${t?L(o,`red`):o}`]}function ii(e,t,n){if(t)return[];let r=[];if(e.diffPath){let t=ci(e.diffPath),i=n?L(`Diff image:`,`dim`):`Diff image:`,a=n?L(t,`green`):t;r.push(` ${i} ${a}`)}if(e.currentOverlayPath){let t=ci(e.currentOverlayPath),i=n?L(`Current overlay:`,`dim`):`Current overlay:`,a=n?L(t,`green`):t,o=F(e.currentOverlayRefCount),s=o>0?` (${o} refs)`:``;r.push(` ${i} ${a}${s}`)}return r}function ai(e,t){let n=F(e.differentPixels),r=F(e.totalPixels);return[` ${t?L(String(n),`red`):String(n)} different / ${r} total pixels`]}function oi(e,t){let n=Array.isArray(e.regions)?e.regions:[];if(n.length===0)return[];let r=[` ${ui(`Changed regions:`,t)}`];for(let e of n.slice(0,5))r.push(...si(e));return r}function si(e){let t=e.shareOfDiffPercentage===0&&e.differentPixels>0?`<0.01`:String(e.shareOfDiffPercentage),n=e.rect,r=[` ${e.index}. x=${n.x} y=${n.y} ${n.width}x${n.height}, ${t}% of diff`],i=e.currentOverlayMatches?.[0];if(i){let e=i.label?` "${i.label}"`:``;r.push(` overlaps @${i.ref}${e}, ${i.regionCoveragePercentage}% of region`)}return r}function ci(e){let t=process.cwd(),n=Fe.relative(t,e);return n===``||!n.startsWith(`..`)&&!Fe.isAbsolute(n)?n===``?`.`:`.${Fe.sep}${n}`:e}function F(e){return typeof e==`number`&&Number.isFinite(e)?e:0}function li(e,t){if(e.length===0)return e;let n=e.map((e,t)=>({index:t,kind:e.kind})).filter(e=>e.kind===`added`||e.kind===`removed`).map(e=>e.index);if(n.length===0)return e;let r=Array(e.length).fill(!1);for(let i of n){let n=Math.max(0,i-t),a=Math.min(e.length-1,i+t);for(let e=n;e<=a;e+=1)r[e]=!0}return e.filter((e,t)=>r[t])}function I(e=process.stdout){let t=process.env.FORCE_COLOR;return typeof t==`string`?t!==`0`:typeof process.env.NO_COLOR==`string`?!1:!!e.isTTY}function L(e,t,n){return Ie(t,e,n)}function ui(e,t){return t?L(e,`dim`):e}function di(e,t,n,r={nodes:t,filteredCount:0}){let i=hi(e);if(fi(e)){let e=mi(t,n);e&&i.push(e)}!n.raw&&r.filteredCount>0&&i.push(`Collapsed ${r.filteredCount} Android helper node${r.filteredCount===1?``:`s`} from the agent-facing text snapshot; use --raw or --json for the full hierarchy.`);let a=r.filteredCount>0?r.nodes:t;return!n.raw&&Jn(a)&&i.push(`Warning: possible repeated nav subtree detected.`),i}function fi(e){return!e.snapshotQuality&&!pi(e)}function pi(e){let t=e.snapshotDiagnostics;if(!t||typeof t!=`object`)return!1;let n=t.stats;return!!(n&&typeof n==`object`&&n.platform===`web`)}function mi(e,t){if(t.scoped===!0||t.depthLimited===!0||e.length>3)return null;let n=e.length===1?`node`:`nodes`;return`Hint: sparse accessibility snapshot returned ${e.length} ${n}; snapshot state is invalid or unavailable for this screen. Use plain screenshot, not screenshot --overlay-refs, as visual truth. If screenshot shows the Home Screen or another app, run open for this app again first. Then navigate away with coordinates if needed and retry snapshot -i on the next screen.`}function hi(e){let t=e.warnings;return Array.isArray(t)?t.filter(e=>typeof e==`string`&&e.length>0):[]}function gi(e){let t=[],n=[],r=new Map(e.map(e=>[e.node.index,e.node])),i=e=>{for(;n.length>0&&(!e||_i(e,n[n.length-1],r));)t.push(...bi(n.pop(),`below`))};for(let r of e)i(r),t.push(r.text),t.push(...bi(r,`above`)),r.node.hiddenContentBelow&&n.push(r);return i(),t}function _i(e,t,n){return vi(e.node,t.node,n)?!1:e.depth<=t.depth}function vi(e,t,n){let r=e;for(;typeof r.parentIndex==`number`;){if(r.parentIndex===t.index)return!0;let e=n.get(r.parentIndex);if(!e)return!1;r=e}return!1}function yi(e){return Or(e,{summarizeTextSurfaces:!0}).flatMap(e=>[kr(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...bi({...e,depth:0})])}function bi(e,t){let n=xi(e.type);if(!n)return[];let r=[];if(e.node.hiddenContentAbove&&t!==`below`&&r.push(`[content above ${n} hidden]`),e.node.hiddenContentBelow&&t!==`above`&&r.push(`[content below ${n} hidden]`),r.length===0)return[];let i=` `.repeat(e.depth+1);return r.map(e=>`${i}${e}`)}function xi(e){return e===`scroll-area`||e===`list`||e===`collection`||e===`table`?e:null}function Si(e,t,n={}){let r=Di(e);if(r.length===0)return{canScroll:!1,emptySnapshot:!0};let i=pe(r),a=Oi(r,i,t,n);return a?{canScroll:Ai(a,i.get(a.index),t),emptySnapshot:!1,scope:ji(a,r)}:{canScroll:!1,emptySnapshot:!1}}async function Ci(e){let{edge:t,target:n={},scope:r,captureNodes:i}=e;try{let e=Si(await i(r),t,n);return r&&e.emptySnapshot?await Ci({edge:t,target:n,captureNodes:i}):e}catch(e){throw Ei(t,r,e)}}async function wi(e){let{edge:t,captureState:r,scroll:i}=e,a=await r();a.scope&&(a=await r(a.scope));let o=0,s;for(;a.canScroll;){if(o>=40)throw new n(`COMMAND_FAILED`,`scroll ${t} reached the safety limit before the snapshot showed the edge`,{hint:`The scoped scroll container still reports hidden content. Use a smaller manual scroll + snapshot loop to inspect the current state.`});s=await i(),o+=1,a=await r(a.scope)}return{passes:o,result:s}}function Ti(e,t,n,r,i){return t&&n===0?`Already at ${t}; no hidden content ${t===`bottom`?`below`:`above`} detected`:t?`Scrolled to ${t} with ${n} ${e} passes`:i===void 0?r===void 0?`Scrolled ${e}`:`Scrolled ${e} by ${r}`:`Scrolled ${e} by ${i}px`}function Ei(e,t,r){return t?new n(`COMMAND_FAILED`,`Failed to verify scroll ${e} state for scoped container`,{scope:t,hint:`scroll ${e} could not verify the scoped scroll container. Run snapshot -i for the current screen and retry with a visible scroll target.`},r):new n(`COMMAND_FAILED`,`Failed to verify scroll ${e} state`,{hint:`scroll ${e} needs a snapshot showing hidden content ${e===`bottom`?`below`:`above`} before it will move.`},r)}function Di(e){return e.map((e,t)=>({...e,ref:`ref`in e&&e.ref?e.ref:`e${t+1}`}))}function Oi(e,t,n,r){let i=new Map(e.map(e=>[e.index,e])),a=e.filter(e=>Se(e)&&Li(e.rect));if(a.length===0)return null;let o=ki(r.nodeIndex,i);if(o)return o;let s=r.point;if(s){let e=a.filter(e=>e.rect&&Ii(e.rect,s)).sort(Pi);if(e.length>0)return e.find(e=>Ai(e,t.get(e.index),n))??e[0]??null}let c=a.filter(e=>Ai(e,t.get(e.index),n)).sort(Fi);return c.length>0?c[0]??null:a.filter(t=>ie(t,e)).sort(Fi)[0]??a.sort(Fi)[0]??null}function ki(e,t){if(e===void 0)return null;let n=t.get(e);for(;n;){if(Se(n)&&Li(n.rect))return n;n=n.parentIndex===void 0?void 0:t.get(n.parentIndex)}return null}function Ai(e,t,n){return n===`bottom`?e.hiddenContentBelow===!0||t?.hiddenContentBelow===!0:e.hiddenContentAbove===!0||t?.hiddenContentAbove===!0}function ji(e,t){return[e.identifier,e.label].filter(e=>typeof e==`string`).map(e=>e.trim()).find(n=>Ni(n)&&Mi(n,e,t))}function Mi(e,t,n){let r=e.toLowerCase(),i=n.filter(e=>[e.identifier,e.label,e.value].some(e=>typeof e==`string`&&e.trim().toLowerCase().includes(r)));return i.length===1&&i[0]?.index===t.index}function Ni(e){return e.length>0&&e.length<=80&&!/^(true|false)$/i.test(e)&&!/^\d+$/.test(e)&&!/^\d+%$/.test(e)}function Pi(e,t){return R(e.rect)-R(t.rect)}function Fi(e,t){return R(t.rect)-R(e.rect)}function R(e){return e?e.width*e.height:0}function Ii(e,t){return t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height}function Li(e){return!!(e&&e.width>0&&e.height>0)}function Ri(e,t,r,i){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>i)throw new n(`INVALID_ARGS`,`${t} must be an integer between ${r} and ${i}`);return e}function z(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}function B(e){return e.clock?.now()??Date.now()}async function zi(e,t){e.clock?await e.clock.sleep(t):await new Promise(e=>setTimeout(e,t))}function Bi(e,t){return Object.fromEntries(Object.entries(e).map(([e,n])=>[e,e=>n(t,e)]))}function V(e){return e&&typeof e==`object`?e:void 0}function Vi(e){let t=Buffer.alloc(16);for(let n of e)Ui(t,Hi(n));return{digest:`ax1:${Le(`sha256`).update(t).update(`\0`).update(String(e.length)).digest(`hex`).slice(0,16)}`,nodeCount:e.length}}function Hi(e){return Le(`sha256`).update(e.type??``).update(`\0`).update(e.label??``).update(`\0`).update(e.identifier??``).digest().subarray(0,16)}function Ui(e,t){for(let n=0;n<e.length;n+=1)e[n]=(e[n]??0)^(t[n]??0)}function H(e){let{digest:t,nodeCount:n}=Vi(e),r=e.reduce((e,t)=>t.hittable===!1?e:e+1,0),i=Wi(e);return{digest:t,nodeCount:n,interactiveNodeCount:r,...i?{foregroundApp:i}:{}}}function Wi(e){for(let t of e)if(t.bundleId)return t.bundleId;for(let t of e)if(t.appName)return t.appName}const Gi=[`x`,`y`,`width`,`height`];function U(e){let t=W(e);if(!t)return null;let n=s(t);return!Number.isFinite(n.x)||!Number.isFinite(n.y)?null:n}function W(e){if(!e)return null;let t=Number(e.x),n=Number(e.y),r=Number(e.width),i=Number(e.height);return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(i)||r<0||i<0?null:{x:t,y:n,width:r,height:i}}function G(e,t){return!e||!t?!1:Gi.every(n=>Math.abs(e[n]-t[n])<=.5)}function Ki(e){return{x:qi(e.x,e.width),y:qi(e.y,e.height)}}function qi(e,t){if(t<=1)return Math.floor(e);let n=Math.ceil(e),r=Math.floor(e+t-1);return Math.round(Math.min(r,Math.max(n,e+t/2)))}function Ji(e){return{...e.id===void 0?{}:{id:e.id},role:e.role,...e.label===void 0?{}:{label:e.label}}}function Yi(e,t){return t.id===void 0?e.role===t.role&&e.label===t.label:e.id===t.id}function Xi(e,t){if(e.length<t.length)return!1;for(let[n,r]of t.entries()){let t=e[n];if(!t||t.role!==r.role||r.label!==void 0&&t.label!==r.label)return!1}return!0}function Zi(e,t){let n=[];return e.id!==t.id&&n.push(`id: recorded=${e.id??`(none)`} observed=${t.id??`(none)`}`),e.role!==t.role&&n.push(`role: recorded=${e.role} observed=${t.role}`),e.label!==t.label&&n.push(`label: recorded=${e.label??`(none)`} observed=${t.label??`(none)`}`),n}function Qi(e){return e?`${e.role}${e.label?`/${e.label}`:``}`:`(missing)`}function $i(e,t){return!t||t.role!==e.role?!0:e.label!==void 0&&t.label!==e.label}function ea(e,t){for(let[n,r]of e.entries()){let e=t[n];if($i(r,e))return[`ancestry[${n}]: recorded=${Qi(r)} observed=${Qi(e)}`]}return[]}function ta(e){let t=new Map;for(let n of e)t.set(n.index,n);return t}function na(e,t,n){let r=[],i=new Set([e.index]),a=e;for(;r.length<n;){if(typeof a.parentIndex!=`number`)return{chain:r,broken:!1};let e=t.get(a.parentIndex);if(!e||i.has(e.index))return{chain:r,broken:!0};i.add(e.index);let n=S(e);r.push({role:n.role,...n.label===void 0?{}:{label:n.label}}),a=e}return{chain:r,broken:!1}}function ra(e,t,n,r){return e.filter(e=>{if(!Yi(S(e),n))return!1;let i=na(e,t,Math.max(r.length,1));return!i.broken&&Xi(i.chain,r)})}const ia=[`tabbar`,`toolbar`,`navigationbar`,`bottomnavigation`,`bottomnavigationview`,`sheet`,`dialog`,`alert`,`popover`,`menu`],aa=[`button`,`link`,`menuitem`,`tabitem`,`textfield`,`searchfield`,`edittext`,`checkbox`,`radio`,`switch`,`cell`];function oa(e,t={}){if(e.length<2)return e;let n=new Map(e.map(e=>[e.index,e])),r={nodes:e,byIndex:n,overlayPositions:e.flatMap((e,r)=>fa(e,n,t)?[r]:[]),coverCache:new Map},i=[];for(let[n,a]of e.entries())da(a)&&sa(r,n,a,t)&&i.push(n);if(i.length===0)return e;let a=[...e];for(let t of i){let n=e[t];a[t]={...n,hittable:!1,interactionBlocked:`covered`,presentationHints:Sa(n.presentationHints)}}return a}function K(e){return e.interactionBlocked!==void 0}function sa(e,t,n,r){let i=e.coverCache.get(t);if(i!==void 0)return i;e.coverCache.set(t,null);let a=q(n.rect);if(!a)return ca(e,t,null);let o=s(a);for(let i of e.overlayPositions){if(i<=t)continue;let s=e.nodes[i];if(s&&la(e,i,n,a,o,r))return ca(e,t,s)}return ca(e,t,null)}function ca(e,t,n){return e.coverCache.set(t,n),n}function la(e,t,n,r,i,a){if(!e.nodes[t])return!1;let o=ua(e,t,n,r,a);return!!(o&&x(o,i.x,i.y))}function ua(e,t,n,r,i){let a=e.nodes[t];if(!a||!fa(a,e.byIndex,i)||ba(n,a,e.byIndex))return null;let o=q(a.rect);return!o||G(r,o)||sa(e,t,a,i)?null:o}function da(e){return q(e.rect)?e.hittable===!0||ga(e)?!0:!!(e.label?.trim()||e.value?.trim()||e.identifier?.trim()):!1}function fa(e,t,n){return!q(e.rect)||ya(e)?!1:_a(e,ia)||pa(e,t,n)}function pa(e,t,n){return n.isAdditionalOverlayNode?.(e)===!0?!ma(e,t,n):!1}function ma(e,t,n){let r=typeof e.parentIndex==`number`?t.get(e.parentIndex):void 0,i=new Set;for(;r&&!i.has(r.index);){if(ha(r,n))return!0;i.add(r.index),r=typeof r.parentIndex==`number`?t.get(r.parentIndex):void 0}return!1}function ha(e,t){return t.isAdditionalOverlayNode?.(e)===!0&&q(e.rect)!==null&&!ya(e)}function ga(e){return _a(e,aa)}function _a(e,t){let n=va(e);return t.some(e=>n.includes(e))}function va(e){return[e.type,e.role,e.subrole].map(e=>y(e??``)).join(` `)}function ya(e){let t=va(e);return t.includes(`application`)||t.includes(`window`)}function ba(e,t,n){return xa(e,t,n)||xa(t,e,n)}function xa(e,t,n){let r=typeof t.parentIndex==`number`?n.get(t.parentIndex):void 0,i=new Set;for(;r&&!i.has(r.index);){if(r.index===e.index)return!0;i.add(r.index),r=typeof r.parentIndex==`number`?n.get(r.parentIndex):void 0}return!1}function q(e){let t=W(e);return t&&t.width>0&&t.height>0?t:null}function Sa(e){return Array.from(new Set([...e??[],`covered`]))}const Ca=[`button`,`link`,`menuitem`,`tabitem`,`textfield`,`searchfield`,`securetextfield`,`checkbox`,`radio`,`switch`,`cell`];function wa(e,t){return Ta(e,t).node}function Ta(e,t){if(K(t))return{node:t,reason:`covered`};let n=Ea(e,t);if(n?.rect&&U(n.rect))return{node:n,reason:`same-rect-descendant`};if(Da(t)&&t.rect&&U(t.rect))return{node:t,reason:`semantic-target`};let r=ce(e,t);return r?.rect&&!K(r)&&U(r.rect)?ka(t,r,e)?{node:t,reason:`overly-broad-ancestor`}:{node:r,reason:`hittable-ancestor`}:{node:t,reason:`original`}}function Ea(e,t){let n=W(t.rect);if(!n)return null;let r=t,i=new Set;for(;!i.has(r.ref);){i.add(r.ref);let t=e.filter(e=>{if(e.parentIndex!==r.index||!e.hittable||K(e))return!1;let t=W(e.rect);return t?G(t,n):!1});if(t.length!==1)break;r=t[0]}return r===t?null:r}function Da(e){return[e.type,e.role,e.subrole].map(e=>y(e??``)).some(Oa)}function Oa(e){return e===`tab`||Ca.some(t=>e.includes(t))}function ka(e,t,n){let r=W(e.rect),i=W(t.rect);if(!r||!i)return!1;let a=Aa(n,r);return!a||!ja(i,a)?!1:!G(r,i)}function Aa(e,t){let n=s(t),r=e.filter(e=>{let t=(e.type??``).toLowerCase();return t.includes(`application`)||t.includes(`window`)}).map(e=>W(e.rect)).filter(e=>e!==null);if(r.length===0)return null;let i=r.filter(e=>x(e,n.x,n.y));return Oe(i.length>0?i:r)}function ja(e,t){let n=d(e,t),r=e.width*e.height,i=t.width*t.height;if(n<=0||r<=0||i<=0)return!1;let a=n/i,o=n/r;return a>=.9&&o>=.8}function Ma(e){return e.hittable===!0||Da(e)}function Na(e,t){let n=me(S(e),t);return n.id!==void 0||n.label!==void 0?!1:xe(e.value)===null}function Pa(e,t,n){let r=new Set,i=e;for(;typeof i.parentIndex==`number`;){if(r.has(i.index))return!1;if(r.add(i.index),i.parentIndex===t.index)return!0;let e=n.get(i.parentIndex);if(!e)return!1;i=e}return!1}function Fa(e,t){let n=ta(t);return t.filter(t=>t.index!==e.index&&Pa(t,e,n)).sort((e,t)=>e.index-t.index)}function Ia(e,t){let n=U(e.rect);return!n||!t.rect?!1:x(t.rect,n.x,n.y)}function La(e,t){if(!Na(e,t))return e;let n=Fa(e,t);if(n.some(Ma))return e;let r=n.find(e=>S(e).label!==void 0);return!r||!Ia(r,e)?e:r}const Ra=new Set([`healthy`,`recovered`,`sparse`]),za=new Set([`tree`,`queries`,`private-ax`]),Ba=new Set([`ax-rejected`,`sparse-tree`,`budget`,`no-nodes`,`capture-failed`]);function Va(e){if(!e||typeof e!=`object`)return;let t=e;if(!(typeof t.state!=`string`||!Ra.has(t.state))&&!(typeof t.backend!=`string`||!za.has(t.backend)))return{state:t.state,backend:t.backend,reason:typeof t.reason==`string`?t.reason:void 0,reasonCode:typeof t.reasonCode==`string`&&Ba.has(t.reasonCode)?t.reasonCode:void 0,effectiveDepth:typeof t.effectiveDepth==`number`?t.effectiveDepth:void 0,collapsedLeafIndexes:Array.isArray(t.collapsedLeafIndexes)?t.collapsedLeafIndexes.filter(e=>typeof e==`number`):void 0}}function Ha(e){return e?.state===`sparse`}function Ua(e,t){return[...Wa(e),...Ga(e),...Ka(e,t)]}function Wa(e){return e.state===`recovered`?[`Detected an overly complex or slow accessibility tree. Fell back to the ${e.backend} snapshot backend. It is OK to continue; use --json to inspect snapshotQuality.reason if you need recovery details.`]:e.state===`sparse`?[`No snapshot backend could read this screen`+(e.reason?` (${e.reason})`:``)+`. Use screenshot as visual truth and coordinate taps; retry snapshot after navigating.`]:[]}function Ga(e){return e.effectiveDepth===void 0?[]:[`Some deeper accessibility nodes were omitted; this tree is capped at depth ${e.effectiveDepth}. Re-run with --depth ${e.effectiveDepth} --scope <container> only if you need deeper content.`]}function Ka(e,t){let n=[];for(let r of e.collapsedLeafIndexes??[]){let e=t.find(e=>e.index===r);if(!e)continue;let i=e.identifier?` (${e.identifier})`:``;n.push(`@${e.ref} [${e.type??`element`}]${i} merges many labels into a single accessibility element. The app likely marks a container as accessible, which hides every descendant from assistive tech and automation — the children cannot be addressed individually. Fix the app's accessibility (mark the rows, not the container); until then use screenshot as visual truth and coordinate taps.`)}return n}const qa=new Set([`empty-helper-output`,`system-window-only`,`content-poor-app-window`]);function Ja(e){if(!e||typeof e!=`object`)return!1;let t=e.details?.androidSnapshotHelperFailureReason;return typeof t==`string`&&qa.has(t)}function Ya(e){return e===`text`||e===`label`||e===`any`}function Xa(e,t,n,r){if(!(r||e===`web`))return Ya(t)?n:void 0}function Za(e){return new n(`COMMAND_FAILED`,`find could not read the current accessibility tree`,{reason:e.reason,hint:`The snapshot quality verdict is sparse. Use screenshot as visual truth, navigate with coordinates if needed, then retry find after reaching a readable screen.`})}async function Qa(e,t){let r=t??`default`,i=await e.sessions.get(r);if(!i)throw new n(`SESSION_NOT_FOUND`,`No active session. Run open first.`);let a=i.refFrameSnapshot??i.snapshot;if(!a)throw new n(`INVALID_ARGS`,`No snapshot in session. Run snapshot first.`);return{sessionName:r,session:i,snapshot:a}}async function $a(e,t,r={updateSession:!0}){let i=e.backend.captureSnapshot;if(!i)throw new n(`UNSUPPORTED_OPERATION`,`snapshot is not supported by this backend`);let a=t.session??`default`,o=await e.sessions.get(a),s=await i(z(e,t),{interactiveOnly:r.interactiveOnly??!1,depth:t.depth,scope:r.scope??t.scope,raw:t.raw,includeRects:r.includeRects,...r.includeHiddenContentHints===void 0?{}:{includeHiddenContentHints:r.includeHiddenContentHints}}),c=s.snapshot??{nodes:s.nodes??[],truncated:s.truncated,backend:s.backend,...s.quality?{snapshotQuality:s.quality}:{},createdAt:B(e)};return(t.signal??e.signal)?.throwIfAborted(),r.updateSession&&o&&!Ha(c.snapshotQuality)&&await e.sessions.set({...o,snapshot:c}),{sessionName:a,session:o,snapshot:c}}async function eo(e,t,n){if(e.backend.readText){let r=await e.backend.readText(z(e,{session:t.sessionName}),n);if(r.text.trim())return r.text}return ae(n)}function to(e,t,i){let a=o(t);if(!a)throw new n(`INVALID_ARGS`,i.invalidRefMessage);let s=r(e,a)??(i.fallbackLabel.length>0?je(e,i.fallbackLabel):null);if(!s)throw new n(`COMMAND_FAILED`,i.notFoundMessage);return{ref:a,node:s}}function no(e,t){if(Buffer.byteLength(e,`utf8`)<=t)return e;let n=Buffer.byteLength(`…`,`utf8`),r=Math.max(0,t-n),i=Buffer.from(e,`utf8`),a=Math.min(r,i.length);for(;a>0&&(i[a]&192)==128;)--a;return i.subarray(0,a).toString(`utf8`)+`…`}function ro(e,t,r,i){if(!r)return;let a=S(e),o=ge(e,t);if(!(Ce(a,r.identity)&&De(o,r.structural)))throw new n(`COMMAND_FAILED`,`${i} resolved to a different element than replay verification isolated; the action was not sent`,{reason:we,observed:a,observedStructural:o,expected:r.identity,expectedStructural:r.structural})}async function J(e,t,n){return await X(e,t,n.action),t.target.kind===`point`?await ao(e,t,t.target,n):t.target.kind===`ref`?await so(e,t,t.target,n):await co(e,t,t.target,n)}async function io(e,t,n){let r=t.session??`default`,i=await e.sessions.get(r);if(!i?.snapshot)return;let a={x:n.x,y:n.y,width:0,height:0},o=ve(i.snapshot.nodes,a);if(!o)return;let s={x:n.x,y:n.y};if(!x(o,s.x,s.y))return`Coordinates (${s.x}, ${s.y}) are outside the last-known viewport (${o.width}x${o.height}). The tap will be forwarded anyway; take a fresh snapshot if the screen changed.`}async function ao(e,t,n,r){let i=await io(e,t,n);if(!r.captureEvidenceBaseline)return{kind:`point`,point:{x:n.x,y:n.y},...i?{warning:i}:{}};let a=await oo(e,t);return{kind:`point`,point:{x:n.x,y:n.y},...a?{preActionNodes:a}:{},...i?{warning:i}:{}}}async function oo(e,t){try{return(await Y(e,t,!0)).snapshot.nodes}catch{return}}async function so(e,t,n,r){let i=await wo(e,t,n),a=i.resolved;ro(a.node,i.snapshot.nodes,r.expectedResolvedTarget,r.action);let o=r.promoteToHittableAncestor?yo(i.snapshot.nodes,a.node,{action:r.action,label:`Ref ${n.ref}`}):a.node;bo(o,`Ref ${n.ref}`,r.action);let s=await Ao(e,t,o,i.snapshot.nodes,n.ref,r.action);return{kind:`ref`,point:Do(s,`Ref ${n.ref} not found or has invalid bounds`),target:{kind:`ref`,ref:`@${a.ref}`},...ho(e,s,i.snapshot.nodes,r.action,a.resolution)}}async function co(e,t,r,i){let a=h(r.selector),o=await Y(e,t,i.requireInteractive),s=b(vo(o.snapshot.nodes),a,{platform:e.backend.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if((!s||!s.node.rect)&&i.requireInteractive&&(o=await Y(e,t,!1),s=b(vo(o.snapshot.nodes),a,{platform:e.backend.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0})),!s||!s.node.rect){let t=b(o.snapshot.nodes,a,{platform:e.backend.platform,requireRect:!0,requireUnique:!1});throw t?.node&&K(t.node)?xo({label:`Selector ${t.selector.raw}`,node:t.node,action:i.action,selector:t.selector.raw}):new n(`COMMAND_FAILED`,ke(a,s?.diagnostics??[],{unique:!0}),{hint:Ae(s?.diagnostics??[])})}ro(s.node,o.snapshot.nodes,i.expectedResolvedTarget,i.action);let c=i.promoteToHittableAncestor?yo(o.snapshot.nodes,s.node,{action:i.action,label:`Selector ${s.selector.raw}`}):s.node;bo(c,`Selector ${s.selector.raw}`,i.action);let l=await ko(e,t,c,o.snapshot.nodes,s.selector.raw,i.action);return{kind:`selector`,point:Do(l,`Selector ${s.selector.raw} resolved to invalid bounds`),target:{kind:`selector`,selector:s.selector.raw},...ho(e,l,o.snapshot.nodes,i.action,po(s,o.snapshot.nodes))}}const lo={source:`ref`,phase:`pre-action`,kind:`exact`},uo={source:`ref`,phase:`pre-action`,kind:`label-fallback`},fo={source:`runtime`,phase:`pre-action`,kind:`unique`};function po(e,t){return e.disambiguation?{source:`runtime`,phase:`pre-action`,kind:`disambiguated`,matchCount:e.disambiguation.matchCount,winnerDiagnostic:mo(e.node,t),tiebreak:e.disambiguation.tiebreak,alternatives:e.disambiguation.alternatives.slice(0,5).map(e=>mo(e,t))}:fo}function mo(e,t){let n=y(e.type??``),r=oe(e,t);return{diagnosticRef:`diag-${e.ref}`,...n?{role:no(n,256)}:{},...r===void 0?{}:{label:no(r,256)}}}function ho(e,t,n,r,i){return{node:t,selectorChain:Te(t,e.backend.platform,{action:r===`fill`?`fill`:`click`,nodes:n}),refLabel:oe(t,n),..._o(t,r),preActionNodes:n,resolution:i,...go(e,t,n,r)}}function go(e,t,n,r){if(r!==`click`&&r!==`press`)return{};let i=La(t,n);return i===t?{}:{recordingTarget:{node:i,selectorChain:Te(i,e.backend.platform,{action:`click`,nodes:n}),refLabel:oe(i,n)}}}function _o(e,t){return e.hittable===!1?{targetHittable:!1,hint:`The resolved element reports hittable: false, so this ${t} may have had no visible effect. Verify with a snapshot, or prefer a @ref or a longer/more specific selector to target the intended element.`}:{}}function vo(e){return e.filter(e=>!K(e))}function yo(e,t,n){let r=Ta(e,t);if(r.reason===`covered`)throw xo({label:n.label,node:t,action:n.action});return r.node}function bo(e,t,n){if(K(e))throw xo({label:t,node:e,action:n})}function xo(e){return new n(`COMMAND_FAILED`,`${e.label} is covered by another visible element and cannot ${So(e.action)} safely`,{hint:`Use a different visible target, scroll it clear of the overlay, or inspect with snapshot/screenshot before retrying.`,...e.selector?{selector:e.selector}:{},ref:`@${e.node.ref}`,interactionBlocked:e.node.interactionBlocked})}function So(e){switch(e){case`fill`:return`be filled`;case`focus`:return`be focused`;case`longPress`:return`be long-pressed`;default:return`be tapped`}}async function Y(e,t,r){if(!e.backend.captureSnapshot)throw new n(`UNSUPPORTED_OPERATION`,`snapshot is not supported by this backend`);let i=t.session??`default`,a=await e.sessions.get(i);if(!a)throw new n(`SESSION_NOT_FOUND`,`No active session. Run open first.`);let o=await e.backend.captureSnapshot(z(e,t),{interactiveOnly:r,includeRects:!0}),s=o.snapshot??{nodes:o.nodes??[],truncated:o.truncated,backend:o.backend,createdAt:B(e)};return await e.sessions.set({...a,snapshot:s}),{snapshot:s}}async function X(e,t,r){if(e.backend.platform!==`macos`)return;let i=await Co(e,t);if(!(i!==`desktop`&&i!==`menubar`)&&!(i===`menubar`&&(r===`click`||r===`press`)))throw new n(`UNSUPPORTED_OPERATION`,`${r} is not supported on macOS ${i} sessions yet. Open an app session to act, or use the ${i} surface to inspect.`)}async function Co(e,t){return(await e.sessions.get(t.session??`default`))?.metadata?.surface}async function wo(e,t,r){let{session:i,snapshot:a}=await Qa(e,t.session),o=r.fallbackLabel??``,s=Eo(a.nodes,r.ref,{fallbackLabel:o});if(!s)throw new n(`COMMAND_FAILED`,`Ref ${r.ref} not found or has no bounds`,{hint:be});return To({session:i,frameTree:a,target:r,fallbackLabel:o,authorized:s})}function To(e){let{session:t,frameTree:n,target:r,fallbackLabel:i,authorized:a}=e,o=t.snapshot;if(!o||o===n)return{snapshot:n,resolved:a};let s=Eo(o.nodes,r.ref,{fallbackLabel:i});return s&&Ce(S(a.node),S(s.node))?{snapshot:o,resolved:s}:{snapshot:n,resolved:a}}function Eo(e,t,i){let a=o(t);if(!a)throw new n(`INVALID_ARGS`,`Invalid ref: ${t}`);let s=r(e,a);if(Oo(s))return{ref:a,node:s,resolution:lo};let c=i.fallbackLabel.length>0?je(e,i.fallbackLabel):null;return Oo(c)?{ref:a,node:c,resolution:uo}:null}function Do(e,t){let r=U(e.rect);if(!r)throw new n(`COMMAND_FAILED`,t);return r}function Oo(e){return e?U(e.rect)!==null:!1}async function ko(e,t,n,r,i,a){return await No(e,t,n,r,{message:`Selector ${i} resolved to an off-screen element and is not safe to ${a}`,details:{reason:`offscreen_selector`,selector:i},hint:e=>`${jo(e)} in small steps, retrying ${a} with the same selector after each (it re-resolves against a fresh snapshot). A single large scroll can overshoot the target; a short bounded gesture pan lands it more reliably. If it is inside a closed drawer or another tab, open that container first.`})}async function Ao(e,t,n,r,i,a){return await No(e,t,n,r,{message:`Ref ${i} is off-screen and not safe to ${a}`,details:{reason:`offscreen_ref`,ref:o(i)},hint:e=>`${jo(e)} in small steps (a single large scroll can overshoot; a short bounded gesture pan lands it more reliably), then retry ${a} with a selector (e.g. text=/id=) rather than this @ref — the scroll expires the ref frame, so re-run snapshot -i before reusing any @ref.`})}function jo(e){return e?`Scroll ${e} toward it`:`Scroll toward it`}async function Mo(e,t,n,r){let i=(await e.sessions.get(t.session??`default`))?.snapshot?.nodes;if(!i||o(n.ref)===null)return{};let a=Eo(i,n.ref,{fallbackLabel:n.fallbackLabel??``});if(!a)return{};bo(a.node,`Ref ${n.ref}`,r);let s=await Ao(e,t,a.node,i,n.ref,r);return{..._o(s,r),node:s,preActionNodes:i}}async function No(e,t,r,i,a){let o=r.rect?Ee(r,i):null;if(!r.rect||!o||ye(r,i))return r;let s=ve(i,r.rect),c=await e.backend.confirmOffscreenTargetVisible?.(z(e,t),r,s);if(c)return{...r,rect:c};let l=de(r,i);throw new n(`COMMAND_FAILED`,a.message,{...a.details,rect:r.rect,viewport:o,...l?{scrollDirection:l}:{},hint:a.hint(l)})}function Po(e,t){let n=P(e.type??`Element`),r=N(e,n),i=e.enabled===!1?`disabled`:`enabled`,a=e.selected===!0?`selected`:`unselected`,o=e.hittable===!0?`hittable`:`not-hittable`;return[String(t??e.depth??0),n,r,i,a,o].join(`|`)}function Fo(e,t,n={}){let r=Ro(Lo(e,n),Lo(t,n)),i={additions:0,removals:0,unchanged:0};for(let e of r)e.kind===`added`&&(i.additions+=1),e.kind===`removed`&&(i.removals+=1),e.kind===`unchanged`&&(i.unchanged+=1);return{summary:i,lines:r}}function Io(e,t={}){return Lo(e,t).length}function Lo(e,t){return t.flatten?e.map(e=>({text:kr(e,0,!1),comparable:Po(e,0),...t.withRefs&&e.ref?{ref:e.ref}:{}})):Or(e).map(e=>({text:e.text,comparable:Po(e.node,e.depth),...t.withRefs&&e.node.ref?{ref:e.node.ref}:{}}))}function Ro(e,t){let n=e.length,r=t.length,i=n+r,a=new Map,o=[];a.set(1,0);for(let s=0;s<=i;s+=1){o.push(new Map(a));for(let i=-s;i<=s;i+=2){let c=Bo(a,i,s)?Z(a,i+1):Z(a,i-1)+1,l=c-i;for(;c<n&&l<r&&e[c].comparable===t[l].comparable;)c+=1,l+=1;if(a.set(i,c),c>=n&&l>=r)return zo(o,e,t,n,r)}}return[]}function zo(e,t,n,r,i){let a=[],o=r,s=i;for(let r=e.length-1;r>=0;--r){let i=e[r],c=o-s,l=Bo(i,c,r)?c+1:c-1,u=Z(i,l),d=u-l;for(;o>u&&s>d;)a.push({kind:`unchanged`,text:n[s-1].text}),--o,--s;if(r===0)break;if(o===u){let e=n[d];a.push({kind:`added`,text:e.text,...e.ref?{ref:e.ref}:{}}),s=d}else a.push({kind:`removed`,text:t[u].text}),o=u}return a.reverse(),a}function Bo(e,t,n){return t===-n||t!==n&&Z(e,t-1)<Z(e,t+1)}function Z(e,t){return e.get(t)??0}function Vo(e){return e?Ne({packageName:e.bundleId,resourceId:e.identifier}).inputMethodOwned:!1}const Ho=new Set([`textfield`,`securetextfield`,`textview`,`textarea`,`searchfield`,`edittext`]),Uo={strippedIndexes:new Set,refs:new Set};function Wo(e){let t=new Set(e.filter(e=>y(e.type??``)===`keyboard`).map(e=>e.index));if(t.size===0)return Uo;let n=new Map(e.map(e=>[e.index,e])),r=Yo(e,n,t),i=new Set(r),a=rs(e,n,r);for(let t of Yo(e,n,a))i.add(t);for(let o of Go(e,n,a,t,r))i.delete(o);let o=new Set(e.filter(e=>e.ref&&i.has(e.index)).map(e=>e.ref));return{strippedIndexes:new Set([...i].filter(e=>!t.has(e))),refs:o}}function Go(e,t,n,r,i){let a=new Set;if(n.size===0)return a;let o=qo(t,n,r);if(o.size===0)return a;let s=Jo(t,r);for(let n of e)!i.has(n.index)&&!s.has(n.index)&&n.rect&&Ko(n,t,o)&&a.add(n.index);return a}function Ko(e,t,n){if(!e.rect)return!1;let r=is(e,t);if(r===void 0)return!1;let i=n.get(r);return i!==void 0&&e.rect.y+e.rect.height/2<i}function qo(e,t,n){let r=new Map;for(let i of n){let n=e.get(i);if(!n?.rect)continue;let a=is(n,e);if(a===void 0||!t.has(a))continue;let o=r.get(a);(o===void 0||n.rect.y<o)&&r.set(a,n.rect.y)}return r}function Jo(e,t){let n=new Set;for(let r of t){let t=e.get(r),i=t&&typeof t.parentIndex==`number`?e.get(t.parentIndex):void 0;for(;i;)n.add(i.index),i=typeof i.parentIndex==`number`?e.get(i.parentIndex):void 0}return n}function Yo(e,t,n){let r=new Set(n);if(n.size===0)return r;for(let i of e)as(i,t,n)&&r.add(i.index);return r}function Xo(e,t){if(e.bundleId!==`com.android.systemui`)return!1;if(Pe(e))return!0;let n=new Set,r=e;for(;r?.bundleId===`com.android.systemui`&&!n.has(r.index);){if(Me(r.identifier))return!0;n.add(r.index),r=r.parentIndex===void 0?void 0:t.get(r.parentIndex)}return!1}function Zo(e,t){let n=new Map(e.map(e=>[e.index,e])),r=new Set(e.filter(e=>Vo(e)).map(e=>e.index)),i=new Set([...r].filter(e=>{let t=n.get(e)?.parentIndex,i=t===void 0?void 0:n.get(t);return!i||!r.has(i.index)})),a=t===`com.android.systemui`?new Set:Qo(e,n,r),o=new Set([...r].filter(e=>!i.has(e)));for(let e of a)o.add(e);let s=new Set(e.filter(e=>e.ref&&(r.has(e.index)||a.has(e.index))).map(e=>e.ref));return o.size===0&&s.size===0?Uo:{strippedIndexes:o,refs:s}}function Qo(e,t,n){return new Set(e.filter(e=>!n.has(e.index)&&Xo(e,t)).map(e=>e.index))}function $o(e,t){let n=Wo(e),r=Zo(e,t);return n.strippedIndexes.size===0&&n.refs.size===0?r:r.strippedIndexes.size===0&&r.refs.size===0?n:{strippedIndexes:new Set([...n.strippedIndexes,...r.strippedIndexes]),refs:new Set([...n.refs,...r.refs])}}function es(e,t){let{strippedIndexes:n}=$o(e,t);return n.size===0?e:e.filter(e=>!n.has(e.index))}function ts(e,t){return $o(e,t).refs}function ns(e){return Wo(e).refs}function rs(e,t,n){let r=new Set;for(let e of n){let n=t.get(e);if(!n||y(n.type??``)!==`keyboard`)continue;let i=is(n,t);i!==void 0&&r.add(i)}for(let i of r){let a=new Set([i]);e.some(e=>Ho.has(y(e.type??``))&&!n.has(e.index)&&as(e,t,a))&&r.delete(i)}return r}function is(e,t){let n=typeof e.parentIndex==`number`?t.get(e.parentIndex):void 0;for(;n;){if(y(n.type??``)===`window`)return n.index;n=typeof n.parentIndex==`number`?t.get(n.parentIndex):void 0}}function as(e,t,n){let r=typeof e.parentIndex==`number`?t.get(e.parentIndex):void 0;for(;r;){if(n.has(r.index))return!0;r=typeof r.parentIndex==`number`?t.get(r.parentIndex):void 0}return!1}async function os(e,t,n,r){let i=new AbortController,a=[t.signal,e.signal].filter(e=>e!==void 0),o=AbortSignal.any([...a,i.signal]),s=!1,c=setTimeout(()=>{s=!0,i.abort(new DOMException(`Wait deadline exceeded`,`TimeoutError`))},Math.max(0,n));c.unref();try{let e=await r(o);return s&&!a.some(e=>e.aborted)?{timedOut:!0}:(o.throwIfAborted(),{timedOut:!1,value:e})}catch(e){if(s&&!a.some(e=>e.aborted))return{timedOut:!0};throw e}finally{clearTimeout(c)}}const ss=`Settled on a nearly-empty tree — the app may still be loading. Wait for specific content (wait text ...) before interacting.`;async function cs(e,t,n){let{quietMs:r,timeoutMs:i}=n,a=B(e),o=a+i,s=!1,c=Math.min(300,Math.max(25,r)),l=0,u,d=0,f,p=a;for(;B(e)<o;){let m=await ds(e,t,o-B(e));if(!m)return{settled:!1,stalled:!0,waitedMs:B(e)-a,captures:l,nodeCount:d,lastCapture:f};l+=1,f=m;let h=fs(m.snapshot.nodes),g=B(e);if(n.resetBudgetOnPrivateAxRecovery===!0&&!s&&ls(m.snapshot.snapshotQuality)){s=!0,o=Math.max(o,g+i),p=g,u=h,d=m.snapshot.nodes.length;let t=us({nowMs:g,quietSinceMs:p,quietMs:r,pollMs:c,deadlineMs:o});if(t<=0)break;await zi(e,t);continue}if(h!==u)u=h,d=m.snapshot.nodes.length,p=g;else if(l>=2&&g-p>=r)return{settled:!0,stalled:!1,waitedMs:g-a,captures:l,nodeCount:d,lastCapture:f};let _=us({nowMs:g,quietSinceMs:p,quietMs:r,pollMs:c,deadlineMs:o});if(_<=0)break;await zi(e,_)}return{settled:!1,stalled:!1,waitedMs:B(e)-a,captures:l,nodeCount:d,lastCapture:f}}function ls(e){return e?.state===`recovered`&&e.backend===`private-ax`}function us(e){let t=e.quietSinceMs+e.quietMs-e.nowMs,n=t>e.pollMs?e.pollMs:Math.max(25,t+2),r=e.deadlineMs-e.nowMs,i=r-1;return i<2?r>=2?r:0:Math.min(n,i)}async function ds(e,t,n){let r=await os(e,t,n,async n=>await $a(e,{...t,signal:n},{updateSession:!1,interactiveOnly:!0}));return r.timedOut?void 0:r.value}function fs(e){return e.map(ps).join(`|`)}function ps(e){let t=e.rect?`${Math.round(e.rect.x)},${Math.round(e.rect.y)},${Math.round(e.rect.width)},${Math.round(e.rect.height)}`:``;return`${e.type??``}#${e.label??``}#${e.identifier??``}#${t}`}const ms=`The UI kept changing for the whole settle budget (animation, carousel, or ticker?), so no settled diff is shown. Raise --timeout, wait for specific content, or take a fresh snapshot.`,hs=`A snapshot capture stalled past the settle budget, so no settled diff is shown. The action itself succeeded; observe with wait stable or snapshot.`;async function gs(e,t,n){let r=n.quietMs??500,i=n.timeoutMs??1e4,a={settled:!1,waitedMs:0,captures:0,quietMs:r,timeoutMs:i};try{let o=await cs(e,t,{quietMs:r,timeoutMs:i,resetBudgetOnPrivateAxRecovery:!0}),s={...a,settled:o.settled,waitedMs:o.waitedMs,captures:o.captures};if(!o.lastCapture)return{observation:{...s,hint:o.stalled?hs:ms}};let{stored:c,session:l}=await Ds(e,t,o.lastCapture),u=o.lastCapture.snapshot.nodes;return{observation:{...s,...o.settled&&c?bs(vs(n.resolved),u,n.resolved.point,l?.appBundleId):{},...Es(o,c,u.length)},settledNodes:u}}catch(e){return{observation:{...a,hint:`Settle observation unavailable (${e instanceof Error?e.message:String(e)}). The action itself succeeded; take a snapshot to observe the result.`}}}}function _s(e,t){if(!e)return;let n=H(e),r=t!==void 0&&n.digest!==H(t).digest;return{...n,changedFromBefore:r}}function vs(e){return`preActionNodes`in e&&e.preActionNodes?e.preActionNodes:[]}function ys(e,t,n){let r=Fo(es(e,n),es(t,n),{flatten:!0,withRefs:!0}),i=r.lines.filter(e=>e.kind!==`unchanged`),a=Ts(i).map(e=>({kind:e.kind,text:e.text,...e.ref?{ref:e.ref}:{}}));return{summary:r.summary,lines:a,...i.length>a.length?{truncated:!0}:{}}}function bs(e,t,n,r){let i=ys(e,t,r);return{diff:i,...xs(i,t,n,r)}}function xs(e,t,n,r){let i=new Set(e.lines.filter(e=>e.kind===`added`&&e.ref).map(e=>e.ref)),a=ts(t,r),o=new Map(t.filter(e=>e.ref).map(e=>[e.ref,e]));return[...i].some(e=>e!==void 0&&!a.has(e)&&!Ss(o.get(e),n))?{}:ws(t,i,r)}function Ss(e,t){if(!e?.rect||!t)return!1;let{x:n,y:r,width:i,height:a}=e.rect;return t.x>=n&&t.x<=n+i&&t.y>=r&&t.y<=r+a}const Cs=new Set([`application`,`window`]);function ws(e,t,n){let r=ts(e,n),i=e.filter(e=>e.ref&&e.interactionBlocked!==`covered`&&!t.has(e.ref)&&!r.has(e.ref)&&!Cs.has(P(e.type??`Element`)));if(i.length===0)return{};let a=i.slice(0,20).map(e=>{let t=P(e.type??`Element`),n=N(e,t);return{ref:e.ref,role:t,...n?{label:n}:{}}});return{tail:a,...i.length>a.length?{tailTruncated:!0}:{}}}function Ts(e){if(e.length<=80)return e;let t=e.filter(e=>e.kind===`added`),n=new Set(t.slice(0,80)),r=80-n.size,i=[];for(let t of e)n.has(t)?i.push(t):t.kind===`removed`&&r>0&&(i.push(t),--r);return i}function Es(e,t,n){return e.stalled?{hint:hs}:e.settled?t?n<5?{hint:ss}:{}:{hint:`Settled on a sparse, unreadable tree — the diff is omitted. Use screenshot as visual truth before interacting further.`}:{hint:ms}}async function Ds(e,t,n){if(Ha(n.snapshot.snapshotQuality))return{stored:!1};let r=await e.sessions.get(t.session??`default`);return r?(await e.sessions.set({...r,snapshot:n.snapshot}),{stored:!0,session:r}):{stored:!1}}function Os(e){let t=e.verify===!0;return{verify:t,needsPreActionBaseline:t||e.settle!==void 0,...e.settle===void 0?{}:{settle:e.settle}}}async function ks(e,t,n,r,i){let a=await As(e,t,n,i);return Ms({...r,...a})}async function As(e,t,n,r){if(r.settle!==void 0){let i=await gs(e,t,{...r.settle,resolved:n}),a=r.verify?_s(i.settledNodes,`preActionNodes`in n?n.preActionNodes:void 0):void 0;return{settle:i.observation,...a?{evidence:a}:{}}}if(!r.verify)return{};let i=await js(e,t,n);return i?{evidence:i}:{}}async function js(e,t,n){let r=`preActionNodes`in n?n.preActionNodes:void 0;try{let n=H((await Y(e,t,!0)).snapshot.nodes),i=r!==void 0&&n.digest!==H(r).digest;return{...n,changedFromBefore:i}}catch{return}}function Ms(e){let t=e;if(t.targetHittable!==!1||!Ns(t)||t.hint===void 0)return e;let{hint:n,...r}=t;return r}function Ns(e){if(e.evidence?.changedFromBefore===!0)return!0;let t=e.settle?.diff?.summary;return!!t&&(t.additions>0||t.removals>0)}const Ps=async(e,t)=>{let r=await J(e,t,{action:`focus`,requireInteractive:!0,promoteToHittableAncestor:!1});if(!e.backend.focus)throw new n(`UNSUPPORTED_OPERATION`,`focus is not supported by this backend`);let i=Bs(r),a=V(await e.backend.focus(z(e,t),i));return{...r,...a?{backendResult:a}:{},...w(`Focused (${i.x}, ${i.y})`)}},Fs=async(e,t)=>{let r=Os(t),i=await J(e,t,{action:`longPress`,requireInteractive:!0,promoteToHittableAncestor:!0,captureEvidenceBaseline:r.needsPreActionBaseline,expectedResolvedTarget:t.expectedResolvedTarget});if(!e.backend.longPress)throw new n(`UNSUPPORTED_OPERATION`,`longPress is not supported by this backend`);let a=t.durationMs===void 0?void 0:Ri(t.durationMs,`durationMs`,0,12e4),o=Bs(i),s=V(await e.backend.longPress(z(e,t),o,{durationMs:a}));return await ks(e,t,i,{...i,...a===void 0?{}:{durationMs:a},...s?{backendResult:s}:{},...w(`Long pressed (${o.x}, ${o.y})`)},r)},Is=async(e,t)=>{if(!e.backend.scroll)throw new n(`UNSUPPORTED_OPERATION`,`scroll is not supported by this backend`);let r=Rs(t.direction),i=Us(t.amount,`scroll amount`),a=Gs(t.pixels,`scroll pixels`),o=f(t.durationMs);p({amount:i,pixels:a},`scroll accepts either amount or pixels, not both`);let s=await Ls(e,t),c=s.kind===`viewport`?{kind:`viewport`}:{kind:`point`,point:Bs(s)},u=e.backend.scroll,d=async()=>await u(z(e,t),c,{direction:r.direction,...i===void 0?{}:{amount:i},...a===void 0?{}:{pixels:a},...o===void 0?{}:{durationMs:o}}),m,h=0;if(r.edge){let n=r.edge,i=zs(s),a=await wi({edge:n,captureState:async r=>await Vs(e,t,n,i,r),scroll:d});m=a.result,h=a.passes}else m=await d(),h=1;let g=V(m),_=l(g);return{...s,direction:r.direction,...r.edge?{edge:r.edge,passes:h}:{},...i===void 0?{}:{amount:i},...a===void 0?{}:{pixels:a},..._===void 0?{}:{durationMs:_},...g?{backendResult:g}:{},...w(Ti(r.direction,r.edge,h,i,a))}};async function Ls(e,t){let n=t.target??{kind:`viewport`};return n.kind===`viewport`?(await X(e,t,`scroll`),{kind:`viewport`}):await J(e,{...t,target:n},{action:`scroll`,requireInteractive:!1,promoteToHittableAncestor:!1})}function Rs(e){return e===`bottom`?{direction:`down`,edge:`bottom`}:e===`top`?{direction:`up`,edge:`top`}:{direction:Hs(e,`scroll direction`)}}function zs(e){return e.kind===`viewport`?{}:{point:e.point,nodeIndex:`node`in e?e.node?.index:void 0}}function Bs(e){if(!e.point)throw new n(`COMMAND_FAILED`,`Interaction target resolved without coordinates`);return e.point}async function Vs(e,t,r,i,a){if(!e.backend.captureSnapshot)throw new n(`UNSUPPORTED_OPERATION`,`scroll ${r} requires snapshot support to verify hidden content before scrolling`);let{captureSnapshot:o}=e.backend;return await Ci({edge:r,target:i,scope:a,captureNodes:async n=>{let r=await o(z(e,t),{scope:n});return r.snapshot?.nodes??r.nodes??[]}})}function Hs(e,t){switch(e){case`up`:case`down`:case`left`:case`right`:return e;default:throw new n(`INVALID_ARGS`,`${t} must be up, down, left, or right`)}}function Us(e,t){return e===void 0?void 0:Ws(e,t)}function Ws(e,t){if(!Number.isFinite(e)||e<=0)throw new n(`INVALID_ARGS`,`${t} must be a positive number`);return e}function Gs(e,t){if(e!==void 0){if(!Number.isFinite(e)||!Number.isInteger(e)||e<=0)throw new n(`INVALID_ARGS`,`${t} must be a positive integer`);return e}}const Ks=/^e\d+$/;function qs(e){if(e[0]?.startsWith(`@`)){let t=tc(e.slice(1));return{ref:e[0],...t===void 0?{}:{label:t}}}if(Ks.test(e[0]??``))throw new n(`INVALID_ARGS`,`Did you mean "@${e[0]}"? Snapshot refs need the @ prefix.`);let t=_(e);if(t){if(t.rest.length>0)throw new n(`INVALID_ARGS`,$s(e,t));return{selector:t.selectorExpression}}return Ys(e)}function Js(e){let t=e[0];if(t?.startsWith(`@`)){let n=e.length>=3?e.slice(2).join(` `):e.slice(1).join(` `);return{kind:`ref`,target:{ref:t,label:e.length>=3?tc(e.slice(1,2)):void 0},text:n}}if(Ks.test(t??``))throw new n(`INVALID_ARGS`,`Did you mean "@${t}"? Snapshot refs need the @ prefix.`);let r=_(e,{preferTrailingValue:!0});return r?{kind:`selector`,target:{selector:r.selectorExpression},text:r.rest.join(` `)}:{kind:`point`,target:Ys(e.slice(0,2)),text:e.slice(2).join(` `)}}function Ys(e){let t=e[0]??``,r=ne(t);if(r){let i=Xs(t)?r.value:[r.value,...e.slice(1)].join(` `).trim();throw new n(`INVALID_ARGS`,Zs({key:r.key,value:i}))}let i=Number(e[0]),a=Number(e[1]);if(Number.isFinite(i)&&Number.isFinite(a))return{x:i,y:a};throw new n(`INVALID_ARGS`,Qs(e))}function Xs(e){let t=e.slice(e.indexOf(`=`)+1).trim();if(t.length<2)return!1;let n=t[0];return(n===`"`||n===`'`)&&t.endsWith(n)}function Zs(e){let{key:t,value:n}=e;return`Unknown selector key "${t}". Supported: ${g.join(`, `)}. ${m(t)?`Did you mean role=${t} label=${Q(n)}?`:`Did you mean label=${Q(n)}?`}`}function Qs(e){let t=e.filter(e=>e!==void 0).join(` `);if(!t.trim())return`Missing target. Pass an @ref from snapshot, a selector like text="Sign in", or "x y" coordinates.`;let n=`Target "${t}" is not a @ref, selector, or "x y" point.`;return e.some(e=>ee(e??``))?`${n} Selector values with spaces need quotes, e.g. text="Sign in".`:`${n} To match by visible text, use text=${Q(t)} (or label=/id=/role=), or pass an @ref from snapshot.`}function $s(e,t){return`${`Selector ${t.selectorExpression} is followed by unexpected extra arguments: "${t.rest.join(` `)}".`} Selector values with spaces need quotes, e.g. ${ec(e,t)??`text="Sign in"`}.`}function ec(e,t){let n=e.length-t.rest.length,r=e[n-1];if(r===void 0)return;let i=r.indexOf(`=`);if(i<=0)return;let a=[r.slice(i+1),...t.rest].join(` `),o=`${r.slice(0,i+1)}${Q(a)}`;return[...e.slice(0,n-1),o].join(` `)}function Q(e){return`"${e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`)}"`}function tc(e){return e.join(` `).trim()||void 0}function nc(e,t={}){let n=I(process.stderr);if(e===`pass`){let e=t.passFormat??`green`;return n?$(`✓`,e):`✓`}return e===`fail`?n?$(`⨯`,`red`):`⨯`:e===`warn`?n?$(`!`,`yellow`):`!`:n?$(`-`,`dim`):`-`}function $(e,t){return L(e,t,{validateStream:!1})}function rc(e){return`${nc(ac(e.status))} ${oc(e)}`}function ic(e){return e.status!==`fail`&&e.status!==`warn`?[]:typeof e.command==`string`?[` run: ${e.command}`]:typeof e.hint==`string`?[` hint: ${e.hint}`]:[]}function ac(e){return e===`pass`?`pass`:e===`fail`?`fail`:e===`warn`?`warn`:`skip`}function oc(e){let t=typeof e.id==`string`&&e.id.length>0?e.id:`check`,n=typeof e.summary==`string`&&e.summary.length>0?e.summary:t;return n===t?t:`${t}: ${n}`}function sc(e,t){let r=e===void 0?NaN:Number(e);if(!Number.isInteger(r)||r<1)throw new n(`INVALID_ARGS`,`viewport ${t} must be a positive integer`);return r}export{B as $,bt as $t,Xa as A,fn as At,na as B,Mt as Bt,Y as C,We as Cn,Yt as Ct,eo as D,ln as Dt,$a as E,Jt as Et,Ua as F,Bt as Ft,Zi as G,kt as Gt,ra as H,Et as Ht,wa as I,Ht as It,G as J,_t as Jt,Xi as K,dt as Kt,Ta as L,Rt as Lt,Ha as M,Gt as Mt,Ja as N,Wt as Nt,Qa as O,cn as Ot,Va as P,Ut as Pt,V as Q,gt as Qt,oa as R,zt as Rt,X as S,Ke as Sn,on as St,J as T,an as Tt,Ji as U,Tt as Ut,ta as V,Lt as Vt,ea as W,At as Wt,U as X,St as Xt,Ki as Y,yt as Yt,Bi as Z,vt as Zt,Vo as _,et as _n,er as _t,Js as a,T as an,L as at,lo as b,Be as bn,nn as bt,Fs as c,st as cn,Hr as ct,Os as d,nt as dn,I as dt,xt as en,z as et,ss as f,tt as fn,N as ft,ts as g,it as gn,sr as gt,ns as h,at as hn,tr as ht,nc as i,w as in,wi as it,Za as j,un as jt,to as k,dn as kt,Is as l,$e as ln,Vr as lt,os as m,rt as mn,ar as mt,ic as n,Ct as nn,Ci as nt,qs as o,Xe as on,ni as ot,cs as p,ot as pn,P as pt,Yi as q,ft as qt,rc as r,ut as rn,Ti as rt,Ps as s,ct as sn,ti as st,sc as t,ht as tn,Ri as tt,ks as u,Qe as un,Br as ut,Fo as v,ze as vn,rn as vt,Mo as w,Ue as wn,sn as wt,ro as x,Ge as xn,Kt as xt,Io as y,Re as yn,qt as yt,K as z,Nt as zt};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.5",
|
|
4
4
|
"description": "Agent-native CLI for AI app automation across iOS, Android, tvOS, Android TV, macOS, Linux, and web.",
|
|
5
5
|
"mcpName": "io.github.callstackincubator/agent-device",
|
|
6
6
|
"license": "MIT",
|
|
@@ -103,12 +103,12 @@
|
|
|
103
103
|
"package:android-ime-helper:npm": "rm -rf android/ime-helper/dist && AGENT_DEVICE_ANDROID_HELPER=ime sh ./scripts/package-android-helper.sh $(node -p \"require('./package.json').version\") android/ime-helper/dist",
|
|
104
104
|
"build:macos-helper": "swift build -c release --package-path apple/macos-helper",
|
|
105
105
|
"build:macos-helper:clean": "swift package --package-path apple/macos-helper clean && pnpm build:macos-helper",
|
|
106
|
-
"package:npm": "pnpm build && pnpm build:xcuitest:ios && pnpm build:xcuitest:macos && pnpm build:xcuitest:tvos && pnpm build:xcuitest:visionos && pnpm build:macos-helper:clean && pnpm package:apple-runner:npm && pnpm build:android",
|
|
106
|
+
"package:npm": "pnpm build && pnpm check:bundle-dependencies && pnpm build:xcuitest:ios && pnpm build:xcuitest:macos && pnpm build:xcuitest:tvos && pnpm build:xcuitest:visionos && pnpm build:macos-helper:clean && pnpm package:apple-runner:npm && pnpm build:android",
|
|
107
107
|
"ad": "node bin/agent-device.mjs",
|
|
108
108
|
"bench:help-conformance": "node scripts/help-conformance-bench.mjs",
|
|
109
|
-
"maestro:conformance": "node --experimental-strip-types --test
|
|
110
|
-
"maestro:conformance:regenerate": "node scripts/maestro-conformance/regenerate.mjs",
|
|
111
|
-
"maestro:conformance:differential": "node --experimental-strip-types
|
|
109
|
+
"maestro:conformance": "node --experimental-strip-types --test packages/maestro/test/conformance/verify.test.ts packages/maestro/test/conformance/differential/run.test.ts packages/maestro/test/conformance/differential/invariants.test.ts",
|
|
110
|
+
"maestro:conformance:regenerate": "node --experimental-strip-types scripts/maestro-conformance/regenerate.mjs",
|
|
111
|
+
"maestro:conformance:differential": "node --experimental-strip-types packages/maestro/test/conformance/differential/run.ts",
|
|
112
112
|
"prototype:program-boundary": "node --experimental-strip-types scripts/prototypes/daemon-boundaries/program-boundary.ts",
|
|
113
113
|
"prototype:session-boundary": "node --experimental-strip-types scripts/prototypes/daemon-boundaries/session-boundary.ts",
|
|
114
114
|
"size": "node scripts/size-report.mjs",
|
|
@@ -129,11 +129,12 @@
|
|
|
129
129
|
"check:affected:test": "node --experimental-strip-types --test scripts/check-affected/model.test.ts scripts/check-affected/run.test.ts",
|
|
130
130
|
"check:coverage-changed": "node --experimental-strip-types scripts/coverage-changed/run.ts",
|
|
131
131
|
"check:coverage-changed:test": "node --experimental-strip-types --test scripts/coverage-changed/model.test.ts scripts/coverage-changed/run.test.ts",
|
|
132
|
-
"check:layering": "node --experimental-strip-types --test scripts/layering/model.test.ts scripts/layering/zone-policy.test.ts scripts/layering/daemon-modularity.test.ts && node --experimental-strip-types scripts/layering/check.ts",
|
|
132
|
+
"check:layering": "node --experimental-strip-types --test scripts/layering/model.test.ts scripts/layering/zone-policy.test.ts scripts/layering/daemon-modularity.test.ts scripts/layering/package-boundaries.test.ts && node --experimental-strip-types scripts/layering/check.ts",
|
|
133
133
|
"depgraph": "node --experimental-strip-types scripts/depgraph/build.ts",
|
|
134
134
|
"depgraph:test": "node --experimental-strip-types --test scripts/depgraph/model.test.ts scripts/depgraph/affected.test.ts",
|
|
135
135
|
"check:production-exports": "fallow dead-code --config fallow-production-exports.json --production --unused-exports --fail-on-issues",
|
|
136
136
|
"check:bundle-owner-files": "node --experimental-strip-types scripts/check-bundle-owner-files.ts",
|
|
137
|
+
"check:bundle-dependencies": "node --experimental-strip-types scripts/check-bundle-dependencies.ts",
|
|
137
138
|
"check:command-docs": "vitest run --project unit-core src/__tests__/command-doc-coverage.test.ts",
|
|
138
139
|
"check:replay-compat": "node --experimental-strip-types scripts/check-replay-compat-provenance.ts",
|
|
139
140
|
"check:freerange": "fr",
|
|
@@ -141,11 +142,11 @@
|
|
|
141
142
|
"sync:mcp-metadata": "node scripts/sync-mcp-metadata.mjs",
|
|
142
143
|
"check:mcp-metadata": "node scripts/sync-mcp-metadata.mjs --check",
|
|
143
144
|
"version": "pnpm sync:mcp-metadata && git add server.json",
|
|
144
|
-
"check:tooling": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm check:layering && pnpm depgraph:test && pnpm check:production-exports && pnpm check:mcp-metadata && pnpm build && pnpm check:bundle-owner-files",
|
|
145
|
+
"check:tooling": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm check:layering && pnpm depgraph:test && pnpm check:production-exports && pnpm check:mcp-metadata && pnpm build && pnpm check:bundle-owner-files && pnpm check:bundle-dependencies",
|
|
145
146
|
"check:unit": "pnpm check:contention-retry && pnpm test:unit && pnpm test:smoke",
|
|
146
147
|
"check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit",
|
|
147
148
|
"prepack": "pnpm check:mcp-metadata && pnpm package:npm",
|
|
148
|
-
"typecheck": "tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json",
|
|
149
|
+
"typecheck": "tsc -b packages/xml packages/kernel packages/contracts packages/ad-script packages/ad-replay packages/maestro packages/replay-test packages/provider-webdriver packages/provider-limrun && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json",
|
|
149
150
|
"test-app:install": "pnpm install --dir examples/test-app",
|
|
150
151
|
"test-app:start": "pnpm --dir examples/test-app start",
|
|
151
152
|
"test-app:ios": "pnpm --dir examples/test-app ios",
|
|
@@ -158,7 +159,7 @@
|
|
|
158
159
|
"test-app:maestro:android": "pnpm test-app:maestro --platform android",
|
|
159
160
|
"test": "pnpm test:unit",
|
|
160
161
|
"test:unit": "vitest run --project unit-core --project subprocess-stub",
|
|
161
|
-
"test:maestro-compat": "vitest run --project unit-core src/
|
|
162
|
+
"test:maestro-compat": "vitest run --project unit-core packages/maestro src/daemon/adapters/maestro src/compat/__tests__/replay-input.test.ts",
|
|
162
163
|
"test:coverage": "vitest run --coverage",
|
|
163
164
|
"test:coverage:ci": "node --experimental-strip-types scripts/lib/contention-retry-run.ts --coverage",
|
|
164
165
|
"check:contention-retry": "node --experimental-strip-types --test scripts/lib/contention-retry-policy.test.ts",
|
|
@@ -241,13 +242,24 @@
|
|
|
241
242
|
],
|
|
242
243
|
"dependencies": {
|
|
243
244
|
"@limrun/api": "^0.24.5",
|
|
245
|
+
"pngjs": "^7.0.0",
|
|
244
246
|
"yaml": "^2.9.0"
|
|
245
247
|
},
|
|
246
248
|
"devDependencies": {
|
|
249
|
+
"@agent-device/ad-replay": "workspace:*",
|
|
250
|
+
"@agent-device/ad-script": "workspace:*",
|
|
251
|
+
"@agent-device/contracts": "workspace:*",
|
|
252
|
+
"@agent-device/kernel": "workspace:*",
|
|
253
|
+
"@agent-device/maestro": "workspace:*",
|
|
254
|
+
"@agent-device/provider-limrun": "workspace:*",
|
|
255
|
+
"@agent-device/provider-webdriver": "workspace:*",
|
|
256
|
+
"@agent-device/replay-test": "workspace:*",
|
|
257
|
+
"@agent-device/xml": "workspace:*",
|
|
247
258
|
"@chenglou/freerange": "^0.0.1",
|
|
248
259
|
"@stryker-mutator/core": "9.6.1",
|
|
249
260
|
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
250
261
|
"@types/node": "^22.19.21",
|
|
262
|
+
"@types/pngjs": "^6.0.5",
|
|
251
263
|
"@vitest/coverage-v8": "4.1.8",
|
|
252
264
|
"fallow": "^2.95.0",
|
|
253
265
|
"fast-check": "^4.9.0",
|
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/callstack/agent-device",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.20.
|
|
10
|
+
"version": "0.20.5",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "agent-device",
|
|
15
|
-
"version": "0.20.
|
|
15
|
+
"version": "0.20.5",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
02777b8c7e55044210eafa255ac92e627977679d75ba4a97f563f3e23dea3267 agent-device-android-ime-helper-0.20.3.apk
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
de7ecffc80d54dd1c173d3bf445ff8c9a02de2d124bcf39abeafeb5a6a08c95e agent-device-android-snapshot-helper-0.20.3.apk
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as e}from"./sdk-contracts.js";import{Z as t,gt as n,ht as r,rt as i,s as a}from"./sdk-selectors.js";import{n as o}from"./android-input-ownership.js";const s=[`x`,`y`,`width`,`height`];function c(t){let n=l(t);if(!n)return null;let r=e(n);return!Number.isFinite(r.x)||!Number.isFinite(r.y)?null:r}function l(e){if(!e)return null;let t=Number(e.x),n=Number(e.y),r=Number(e.width),i=Number(e.height);return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(i)||r<0||i<0?null:{x:t,y:n,width:r,height:i}}function u(e,t){return!e||!t?!1:s.every(n=>Math.abs(e[n]-t[n])<=.5)}function d(e){return{x:f(e.x,e.width),y:f(e.y,e.height)}}function f(e,t){if(t<=1)return Math.floor(e);let n=Math.ceil(e),r=Math.floor(e+t-1);return Math.round(Math.min(r,Math.max(n,e+t/2)))}function p(e){let t=new Map;for(let n of e)t.set(n.index,n);return t}function m(e,t,n){let r=[],i=new Set([e.index]),o=e;for(;r.length<n;){if(typeof o.parentIndex!=`number`)return{chain:r,broken:!1};let e=t.get(o.parentIndex);if(!e||i.has(e.index))return{chain:r,broken:!0};i.add(e.index);let n=a(e);r.push({role:n.role,...n.label===void 0?{}:{label:n.label}}),o=e}return{chain:r,broken:!1}}function h(e,t,i,o){return e.filter(e=>{if(!n(a(e),i))return!1;let s=m(e,t,Math.max(o.length,1));return!s.broken&&r(s.chain,o)})}const g=[`tabbar`,`toolbar`,`navigationbar`,`bottomnavigation`,`bottomnavigationview`,`sheet`,`dialog`,`alert`,`popover`,`menu`],_=[`button`,`link`,`menuitem`,`tabitem`,`textfield`,`searchfield`,`edittext`,`checkbox`,`radio`,`switch`,`cell`];function v(e,t={}){if(e.length<2)return e;let n=[...e],r=new Map(n.map(e=>[e.index,e])),i={nodes:n,byIndex:r,overlayPositions:n.flatMap((e,n)=>w(e,r,t)?[n]:[])},a=!1;for(let[e,r]of n.entries()){if(!C(r)||!b(i,e,r,t))continue;a=!0;let o={...r,hittable:!1,interactionBlocked:`covered`,presentationHints:F(r.presentationHints)};n[e]=o,i.byIndex.set(o.index,o)}return a?n:e}function y(e){return e.interactionBlocked!==void 0}function b(t,n,r,i){let a=P(r.rect);if(!a)return null;let o=e(a);for(let e of t.overlayPositions){if(e<=n)continue;let s=t.nodes[e];if(s&&x(t,e,r,a,o,i))return s}return null}function x(e,n,r,i,a,o){if(!e.nodes[n])return!1;let s=S(e,n,r,i,o);return!!(s&&t(s,a.x,a.y))}function S(e,t,n,r,i){let a=e.nodes[t];if(!a||!w(a,e.byIndex,i)||M(n,a,e.byIndex))return null;let o=P(a.rect);return!o||u(r,o)||b(e,t,a,i)?null:o}function C(e){return P(e.rect)?e.hittable===!0||O(e)?!0:!!(e.label?.trim()||e.value?.trim()||e.identifier?.trim()):!1}function w(e,t,n){return!P(e.rect)||j(e)?!1:k(e,g)||T(e,t,n)}function T(e,t,n){return n.isAdditionalOverlayNode?.(e)===!0?!E(e,t,n):!1}function E(e,t,n){let r=typeof e.parentIndex==`number`?t.get(e.parentIndex):void 0,i=new Set;for(;r&&!i.has(r.index);){if(D(r,n))return!0;i.add(r.index),r=typeof r.parentIndex==`number`?t.get(r.parentIndex):void 0}return!1}function D(e,t){return t.isAdditionalOverlayNode?.(e)===!0&&P(e.rect)!==null&&!j(e)}function O(e){return k(e,_)}function k(e,t){let n=A(e);return t.some(e=>n.includes(e))}function A(e){return[e.type,e.role,e.subrole].map(e=>i(e??``)).join(` `)}function j(e){let t=A(e);return t.includes(`application`)||t.includes(`window`)}function M(e,t,n){return N(e,t,n)||N(t,e,n)}function N(e,t,n){let r=typeof t.parentIndex==`number`?n.get(t.parentIndex):void 0,i=new Set;for(;r&&!i.has(r.index);){if(r.index===e.index)return!0;i.add(r.index),r=typeof r.parentIndex==`number`?n.get(r.parentIndex):void 0}return!1}function P(e){let t=l(e);return t&&t.width>0&&t.height>0?t:null}function F(e){return Array.from(new Set([...e??[],`covered`]))}function I(e){return e?o({packageName:e.bundleId,resourceId:e.identifier}).inputMethodOwned:!1}export{p as a,l as c,m as i,d as l,v as n,h as o,y as r,u as s,I as t,c as u};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e=new Set([`com.google.android.inputmethod.latin`,`com.samsung.android.honeyboard`,`com.touchtype.swiftkey`,`com.microsoft.swiftkey`]);function t(t){let n=l(t.packageName),r=(t.resourceId??``).toLowerCase(),i=l(t.activeInputMethodPackage);if(n&&i&&n===i)return{inputMethodOwned:!0,source:`active-input-method`};if(i&&r.startsWith(`${i}:id/`))return{inputMethodOwned:!0,source:`active-input-method-resource`};if(n&&e.has(n))return{inputMethodOwned:!0,source:`known-ime-package`};for(let t of e)if(r.startsWith(`${t}:id/`))return{inputMethodOwned:!0,source:`known-ime-resource`};return{inputMethodOwned:!1,source:`app`}}function n(e,n,r){return t({packageName:e,resourceId:n,activeInputMethodPackage:r}).inputMethodOwned}function r(e){return t(e).inputMethodOwned}function i(t){let n=l(t);return!!(n&&e.has(n))}function a(t){let n=(t??``).toLowerCase();for(let t of e)if(n.startsWith(`${t}:id/`))return!0;return!1}function o(e,t,r){return!e&&!t?`unknown`:n(e,t,r)?`ime`:`app`}function s(e){for(let t of[/\bmCurMethodId=([^\s]+)/i,/\bmCurId=([^\s]+)/i,/\bmCurrentInputMethodId=([^\s]+)/i,/\bcurMethodId=([^\s]+)/i]){let n=c(e.match(t)?.[1]);if(n)return n}}function c(e){let t=(e??``).trim();if(t)return l((t.split(`/`)[0]??``).match(/[a-zA-Z0-9_.]+/)?.[0])}function l(e){return(e??``).trim().toLowerCase()||void 0}export{a,i,t as n,s as o,r,o as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{o as t,y as n}from"./sdk-device.js";const r={ios:`iOS`,ipados:`iPadOS`,tvos:`tvOS`,watchos:`watchOS`,visionos:`visionOS`,macos:`macOS`},i={visionos:`visionOS uses spatial input and does not support two-finger touch synthesis.`,tvos:`tvOS has no touch input — this gesture is supported on Android and the iOS simulator only.`,macos:`macOS automation has no multi-touch input — this gesture is supported on Android and the iOS simulator only.`};function a(a,s){if(!t(a.platform))throw o(s,a.platform);let c=n(a);if(!((c===`ios`||c===`ipados`)&&a.kind===`simulator`))throw c===`ios`||c===`ipados`?new e(`UNSUPPORTED_OPERATION`,`gesture ${s} is not supported on physical iOS devices`,{hint:`Two-finger gesture synthesis is iOS-simulator only — not available on physical iOS devices.`}):o(s,r[c],i[c])}function o(t,n,r){return new e(`UNSUPPORTED_OPERATION`,`gesture ${t} is not supported on ${n}`,r===void 0?void 0:{hint:r})}export{a as t};
|