agent-device 0.20.2 → 0.20.3
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.2.apk → agent-device-android-ime-helper-0.20.3.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.3.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.2.manifest.json → agent-device-android-ime-helper-0.20.3.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.2.apk → 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 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.2.manifest.json → agent-device-android-snapshot-helper-0.20.3.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -176
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +184 -0
- package/dist/src/android-adb.d.ts +3 -26
- package/dist/src/android-adb.js +1 -1
- package/dist/src/app-helpers.js +1 -0
- package/dist/src/apps.js +5 -5
- package/dist/src/context.js +1 -1
- package/dist/src/device-input-state.d.ts +26 -0
- package/dist/src/find.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +14 -14
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +78 -2
- package/dist/src/logcat.js +1 -1
- package/dist/src/recording-export-quality.js +2 -3
- package/dist/src/runtime2.js +1 -1
- package/dist/src/sdk-android-adb.d.ts +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +8 -8
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/tv-remote.d.ts +1 -1
- package/package.json +14 -15
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.2.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.2.apk.sha256 +0 -1
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{$t as A,Ft as j,Mt as te,Nt as ne,Ot as re,Rt as ie,Tt 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&&A(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 ae({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=e.sessionStore.get(n)?.snapshotGeneration,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}}}})}async function we(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=M(t.flags?.snapshotScope,a);return c.ok?Te(e.command,a,o)||await N(a,o,async()=>{let s=Ee({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 Me({req:t,sessionName:n,sessionStore:i,result:l.record}),{ok:!0,data:l.data}}):c}function Te(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 Ee(e){let{req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:s}=e;return y({backend:je({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=Ne(e),a=i.get(n);i.set(n,De({current:a,sessionName:n,device:o,record:r,refScopedSnapshot:Oe(t),issuesRefsToClient:t.command===`snapshot`}))}})})}function De(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:$({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 $(e){let{current:t,keepCurrentSnapshot:n,refScopedSnapshot:r}=e;if(r)return n?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}function je(e){let{req:t,logPath:n,session:r,device:i,snapshotScope:a}=e;return{platform:m(i),captureSnapshot:async(e,o)=>{let s=await ie({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 Me(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:Pe(e.result),interactiveObservation:f(e.req)})}function Ne(e){if(!e.snapshot)throw new t(`UNKNOWN`,`snapshot runtime did not produce session state`);return e}function Pe(e){return e.kind===`snapshot`?{nodes:e.nodes,truncated:e.truncated}:{mode:e.mode,baselineInitialized:e.baselineInitialized,summary:e.summary}}const Fe={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 we({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 Ie(e){let t=e.req.command,n=Fe[t];return n?await n(e):null}export{Ie as handleSnapshotCommands};
|
|
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};
|
package/dist/src/tv-remote.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { M as SnapshotQualityVerdict, O as ScreenshotOverlayRef, U as PublicPlatform, n as DaemonArtifactType } from "./sdk-contracts.js";
|
|
2
|
-
import {
|
|
2
|
+
import { h as AndroidSnapshotHelperTransport, m as AndroidSnapshotHelperInstallReason, p as AndroidSnapshotCaptureMode } from "./sdk-android-adb.js";
|
|
3
3
|
//#region src/contracts/json.d.ts
|
|
4
4
|
type JsonPrimitive = string | number | boolean | null;
|
|
5
5
|
type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.3",
|
|
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",
|
|
@@ -83,11 +83,12 @@
|
|
|
83
83
|
"clean:xcuitest:macos": "node scripts/clean-xcuitest-derived.mjs macos",
|
|
84
84
|
"clean:xcuitest:tvos": "node scripts/clean-xcuitest-derived.mjs tvos",
|
|
85
85
|
"clean:xcuitest:visionos": "node scripts/clean-xcuitest-derived.mjs visionos",
|
|
86
|
-
"
|
|
86
|
+
"rebuild:cli": "pnpm build && pnpm clean:daemon",
|
|
87
87
|
"build:xcuitest": "pnpm build:xcuitest:ios && pnpm build:xcuitest:macos",
|
|
88
88
|
"build:xcuitest:ios": "AGENT_DEVICE_XCUITEST_PLATFORM=ios sh ./scripts/build-xcuitest-apple.sh",
|
|
89
89
|
"build:xcuitest:ios:clean": "pnpm clean:xcuitest:ios && pnpm build:xcuitest:ios",
|
|
90
90
|
"build:xcuitest:macos": "AGENT_DEVICE_XCUITEST_PLATFORM=macos sh ./scripts/build-xcuitest-apple.sh",
|
|
91
|
+
"build:xcuitest:macos:clean": "pnpm clean:xcuitest:macos && pnpm build:xcuitest:macos",
|
|
91
92
|
"build:xcuitest:tvos": "AGENT_DEVICE_XCUITEST_PLATFORM=tvos sh ./scripts/build-xcuitest-apple.sh",
|
|
92
93
|
"build:xcuitest:tvos:clean": "pnpm clean:xcuitest:tvos && pnpm build:xcuitest:tvos",
|
|
93
94
|
"build:xcuitest:visionos": "AGENT_DEVICE_XCUITEST_PLATFORM=visionos sh ./scripts/build-xcuitest-apple.sh",
|
|
@@ -101,7 +102,8 @@
|
|
|
101
102
|
"package:android-ime-helper": "AGENT_DEVICE_ANDROID_HELPER=ime sh ./scripts/package-android-helper.sh $(node -p \"require('./package.json').version\") .tmp/android-ime-helper",
|
|
102
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",
|
|
103
104
|
"build:macos-helper": "swift build -c release --package-path apple/macos-helper",
|
|
104
|
-
"build:
|
|
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",
|
|
105
107
|
"ad": "node bin/agent-device.mjs",
|
|
106
108
|
"bench:help-conformance": "node scripts/help-conformance-bench.mjs",
|
|
107
109
|
"maestro:conformance": "node --experimental-strip-types --test scripts/maestro-conformance/verify.test.ts scripts/maestro-conformance/differential/run.test.ts scripts/maestro-conformance/differential/invariants.test.ts",
|
|
@@ -110,10 +112,7 @@
|
|
|
110
112
|
"prototype:program-boundary": "node --experimental-strip-types scripts/prototypes/daemon-boundaries/program-boundary.ts",
|
|
111
113
|
"prototype:session-boundary": "node --experimental-strip-types scripts/prototypes/daemon-boundaries/session-boundary.ts",
|
|
112
114
|
"size": "node scripts/size-report.mjs",
|
|
113
|
-
"size:markdown": "node scripts/size-report.mjs --json .tmp/size-report.json --markdown .tmp/size-report.md",
|
|
114
115
|
"perf": "node --experimental-strip-types scripts/perf/run.ts",
|
|
115
|
-
"perf:ios": "node --experimental-strip-types scripts/perf/run.ts --platform ios",
|
|
116
|
-
"perf:android": "node --experimental-strip-types scripts/perf/run.ts --platform android",
|
|
117
116
|
"mutation:run": "node --experimental-strip-types scripts/mutation/run.ts",
|
|
118
117
|
"mutation:baseline": "node --experimental-strip-types scripts/mutation/run.ts --update",
|
|
119
118
|
"mutation:check": "node --experimental-strip-types scripts/mutation/run.ts --no-run",
|
|
@@ -123,15 +122,14 @@
|
|
|
123
122
|
"format": "node ./node_modules/oxfmt/bin/oxfmt --write",
|
|
124
123
|
"format:check": "node ./node_modules/oxfmt/bin/oxfmt --check",
|
|
125
124
|
"fuzz:parsers": "node --experimental-strip-types scripts/fuzz/run.ts",
|
|
126
|
-
"fallow": "fallow audit --base origin/main",
|
|
127
125
|
"fallow:all": "fallow --summary",
|
|
128
|
-
"fallow:baseline": "
|
|
126
|
+
"fallow:baseline": "fallow dead-code --save-baseline fallow-baselines/dead-code.json --summary && fallow health --report-only --save-baseline fallow-baselines/health.json --summary",
|
|
129
127
|
"check:fallow": "fallow audit",
|
|
130
128
|
"check:affected": "node --experimental-strip-types scripts/check-affected/run.ts",
|
|
131
129
|
"check:affected:test": "node --experimental-strip-types --test scripts/check-affected/model.test.ts scripts/check-affected/run.test.ts",
|
|
132
130
|
"check:coverage-changed": "node --experimental-strip-types scripts/coverage-changed/run.ts",
|
|
133
131
|
"check:coverage-changed:test": "node --experimental-strip-types --test scripts/coverage-changed/model.test.ts scripts/coverage-changed/run.test.ts",
|
|
134
|
-
"check:layering": "node --experimental-strip-types --test scripts/layering/model.test.ts scripts/layering/zone-policy.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 && node --experimental-strip-types scripts/layering/check.ts",
|
|
135
133
|
"depgraph": "node --experimental-strip-types scripts/depgraph/build.ts",
|
|
136
134
|
"depgraph:test": "node --experimental-strip-types --test scripts/depgraph/model.test.ts scripts/depgraph/affected.test.ts",
|
|
137
135
|
"check:production-exports": "fallow dead-code --config fallow-production-exports.json --production --unused-exports --fail-on-issues",
|
|
@@ -142,11 +140,11 @@
|
|
|
142
140
|
"check:quick": "pnpm lint && pnpm typecheck",
|
|
143
141
|
"sync:mcp-metadata": "node scripts/sync-mcp-metadata.mjs",
|
|
144
142
|
"check:mcp-metadata": "node scripts/sync-mcp-metadata.mjs --check",
|
|
145
|
-
"version": "
|
|
146
|
-
"check:tooling": "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",
|
|
143
|
+
"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",
|
|
147
145
|
"check:unit": "pnpm check:contention-retry && pnpm test:unit && pnpm test:smoke",
|
|
148
146
|
"check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit",
|
|
149
|
-
"prepack": "pnpm check:mcp-metadata && pnpm
|
|
147
|
+
"prepack": "pnpm check:mcp-metadata && pnpm package:npm",
|
|
150
148
|
"typecheck": "tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json",
|
|
151
149
|
"test-app:install": "pnpm install --dir examples/test-app",
|
|
152
150
|
"test-app:start": "pnpm --dir examples/test-app start",
|
|
@@ -156,10 +154,11 @@
|
|
|
156
154
|
"test-app:replay:ios": "pnpm ad test examples/test-app/replays --platform ios --artifacts-dir .tmp/test-app-replay/ios",
|
|
157
155
|
"test-app:replay:android": "pnpm ad test examples/test-app/replays --platform android --artifacts-dir .tmp/test-app-replay/android",
|
|
158
156
|
"test-app:maestro": "node scripts/run-test-app-maestro-suite.mjs",
|
|
159
|
-
"test-app:maestro:ios": "
|
|
160
|
-
"test-app:maestro:android": "
|
|
161
|
-
"test": "
|
|
157
|
+
"test-app:maestro:ios": "pnpm test-app:maestro --platform ios",
|
|
158
|
+
"test-app:maestro:android": "pnpm test-app:maestro --platform android",
|
|
159
|
+
"test": "pnpm test:unit",
|
|
162
160
|
"test:unit": "vitest run --project unit-core --project subprocess-stub",
|
|
161
|
+
"test:maestro-compat": "vitest run --project unit-core src/compat/maestro src/compat/__tests__/replay-input.test.ts",
|
|
163
162
|
"test:coverage": "vitest run --coverage",
|
|
164
163
|
"test:coverage:ci": "node --experimental-strip-types scripts/lib/contention-retry-run.ts --coverage",
|
|
165
164
|
"check:contention-retry": "node --experimental-strip-types --test scripts/lib/contention-retry-policy.test.ts",
|
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.3",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "agent-device",
|
|
15
|
-
"version": "0.20.
|
|
15
|
+
"version": "0.20.3",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
941f2997c4315e753fb2f5411562a2907b3a188370c3d52e762692843be1b50f agent-device-android-ime-helper-0.20.2.apk
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
003859ea5dc5d1ed8ddc5daf786eacb790ff471bbb0c3b0e1239712f73f37684 agent-device-android-snapshot-helper-0.20.2.apk
|