agent-device 0.17.8 → 0.17.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.8.apk → agent-device-android-multitouch-helper-0.17.9.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.9.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.8.manifest.json → agent-device-android-multitouch-helper-0.17.9.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.8.apk → agent-device-android-snapshot-helper-0.17.9.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.9.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.8.manifest.json → agent-device-android-snapshot-helper-0.17.9.manifest.json} +6 -6
- package/dist/src/1404.js +1 -0
- package/dist/src/2133.js +1 -1
- package/dist/src/2577.js +1 -1
- package/dist/src/2948.js +30 -1
- package/dist/src/4428.js +1 -1
- package/dist/src/587.js +1 -1
- package/dist/src/7394.js +5 -5
- package/dist/src/8184.js +1 -1
- package/dist/src/8358.js +1 -1
- package/dist/src/9581.js +2 -2
- package/dist/src/9722.js +36 -36
- package/dist/src/9836.js +1 -1
- package/dist/src/9919.js +5 -5
- package/dist/src/android.js +3 -3
- package/dist/src/apple.js +1 -1
- package/dist/src/apps.js +1 -1
- package/dist/src/cli-help.js +8 -1
- package/dist/src/cli-output.js +1 -4
- package/dist/src/cli.js +18 -18
- package/dist/src/command-surface.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/generic.js +5 -5
- package/dist/src/index.d.ts +12 -0
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions~1.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace-recording.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session.js +7 -7
- package/dist/src/snapshot.js +1 -1
- package/dist/src/web.js +1 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +92 -4
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +130 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +4 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +18 -0
- package/package.json +3 -3
- package/server.json +2 -2
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.8.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.8.apk.sha256 +0 -1
- package/dist/src/6311.js +0 -27
- package/dist/src/7244.js +0 -1
- package/dist/src/9873.js +0 -1
package/dist/src/snapshot.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__webpack_require__ as e}from"./rslib-runtime.js";import{promises as t}from"node:fs";import a from"node:os";import n from"node:path";import{centerOfRect as s}from"./4291.js";import{normalizeError as o,AppError as r}from"./733.js";import{withDiagnosticTimer as i,emitDiagnostic as l}from"./432.js";import{pressAndroid as d,backAndroid as p}from"./input-actions.js";import{createDaemonRuntimeSessionStore as u,captureSnapshot as c,dispatchCommand as f,resolveSnapshotScope as m,runMacOsAlertAction as h,errorResponse as w,runIosRunnerCommand as g,isCommandSupportedOnDevice as y,snapshotAndroid as _,annotateScreenshotWithRefs as v,context_contextFromFlags as S}from"./9722.js";import{SETTINGS_INVALID_ARGS_MESSAGE as b,parseTimeout as I,getUnsupportedMacOsSettingMessage as A,successText as R,isMacOsSettingSupported as C,snapshotCaptureAnnotationsFrom as N}from"./
|
|
1
|
+
import{__webpack_require__ as e}from"./rslib-runtime.js";import{promises as t}from"node:fs";import a from"node:os";import n from"node:path";import{centerOfRect as s}from"./4291.js";import{normalizeError as o,AppError as r}from"./733.js";import{withDiagnosticTimer as i,emitDiagnostic as l}from"./432.js";import{pressAndroid as d,backAndroid as p}from"./input-actions.js";import{createDaemonRuntimeSessionStore as u,captureSnapshot as c,dispatchCommand as f,resolveSnapshotScope as m,runMacOsAlertAction as h,errorResponse as w,runIosRunnerCommand as g,isCommandSupportedOnDevice as y,snapshotAndroid as _,annotateScreenshotWithRefs as v,context_contextFromFlags as S}from"./9722.js";import{SETTINGS_INVALID_ARGS_MESSAGE as b,parseTimeout as I,getUnsupportedMacOsSettingMessage as A,successText as R,isMacOsSettingSupported as C,snapshotCaptureAnnotationsFrom as N}from"./2948.js";import{sleep as D}from"./5560.js";import{buildSnapshotSession as P,dispatchWaitViaRuntime as k,createDaemonRuntimePolicy as M,recordIfSession as E,resolveSessionDevice as O,withSessionlessRunnerCleanup as K}from"./selector-runtime.js";import{createAgentDevice as U}from"./2577.js";import{summarizeSnapshotDiagnostics as x}from"./8358.js";var L={};e.r(L),e.d(L,{handleSnapshotCommands:()=>ew});let B=new Set(["com.android.permissioncontroller","com.google.android.permissioncontroller","com.google.android.packageinstaller","com.android.packageinstaller"]),$=new Set(["android","com.android.systemui"]),H=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,q=/^android:id\/button[123]$/i,F=/(?:^|:)id\/permission_/i,T=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,j=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,X=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function z(e,t){let a=t[0];if(!a)return;let n=G(e,a.index);for(let a of t.slice(1)){let t=new Set(G(e,a.index));for(let e=n.length-1;e>=0;e-=1)t.has(n[e])||n.splice(e,1)}return n[n.length-1]}function G(e,t){let a=new Map(e.map(e=>[e.index,e])),n=[],s=a.get(t);for(;s;)n.push(s.index),s=void 0===s.parentIndex?void 0:a.get(s.parentIndex);return n.reverse()}function V(e,t){let a=new Map;for(let t of e){if(void 0===t.parentIndex)continue;let e=a.get(t.parentIndex)??[];e.push(t),a.set(t.parentIndex,e)}let n=new Set([t]),s=[t];for(let e of s)for(let t of a.get(e)??[])n.has(t.index)||(n.add(t.index),s.push(t.index));return e.filter(e=>n.has(e.index))}function W(e){let t=e.type??"",a=e.identifier??"";return!!(e.hittable||/\bbutton\b/i.test(t)||q.test(a)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(a))}function J(e){if(!e)return"";let t=[e.label,e.value].filter(e=>"string"==typeof e&&e.trim().length>0);return t[0]?.trim()??""}async function Q(e,t,a={}){if("wait"===t)return await Y(e,a.timeoutMs??1e4);if("get"===t){var n;let t=await et(e);return{kind:"alertStatus",platform:"android",action:"get",alert:n=t?.alert??null,...n?R("Alert visible"):R("No alert visible")}}return await Z(e,t)}async function Y(e,t){let a=Date.now(),n=await ee(e,t);if(!n)throw new r("COMMAND_FAILED","alert wait timed out");return{kind:"alertWait",platform:"android",action:"wait",alert:n.alert,waitedMs:Date.now()-a,...R("Alert visible")}}async function Z(e,t){var a;let n,s,o=await ee(e,2e3);if(!o)throw new r("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=(a=o.buttons,n="accept"===t?"accept":"dismiss",(s=a.find(e=>e.role===n))||("dismiss"===t?a.find(e=>"neutral"===e.role)??null:1===a.length?a[0]??null:null));if(i)return await d(e,i.x,i.y),ea(t,o.alert,i.label);if("dismiss"===t)return await p(e),ea(t,o.alert,"Back");throw new r("COMMAND_FAILED","alert accept found an alert but no accept button",{alert:o.alert,hint:"Inspect alert get --json for visible buttons, then use press by visible label/ref if needed."})}async function ee(e,t){let a=Date.now();for(;Date.now()-a<t;){let t=await et(e);if(t)return t;await D(300)}return null}async function et(e){return function(e){var t,a,n,o;let r,i=function(e){let t=e.filter(e=>{var t;let a;return a=(t=e).bundleId??"",B.has(a)||F.test(t.identifier??"")});if(t.length)return{nodes:t,source:"permission"};let a=function(e){let t=e.filter(e=>{var t;let a;return a=(t=e).bundleId??"",$.has(a)&&T.test(J(t))});if(0===t.length)return[];let a=z(e,t);return void 0===a?t:V(e,a).filter(e=>e.bundleId&&$.has(e.bundleId))}(e);return a.length?{nodes:a,source:"system-dialog"}:{nodes:function(e){var t;let a,n,s=e.filter(e=>{var t;return t=e.type??"",/(?:^|[.$])[^.]*Dialog$/i.test(t)}),o=e.filter(e=>H.test(e.identifier??"")),r=s.length?[...s,...o]:(a=(t=o).some(e=>q.test(e.identifier??"")),n=t.some(e=>!q.test(e.identifier??"")),a&&n?t:[]);if(0===r.length)return[];let i=z(e,r);return void 0===i?r:V(e,i)}(e),source:"native-dialog"}}(e),l=i.nodes;if(0===l.length)return null;let d=function(e){let t=new Set,a=[];for(let n of e){let e=J(n);if(!e||!n.rect||!W(n))continue;let o=e.trim().toLowerCase();if(!o||t.has(o))continue;t.add(o);let r=s(n.rect);a.push({label:e,x:r.x,y:r.y,role:function(e,t){var a;let n=(a=e.identifier??"",/(?:^|:)id\/button1$/i.test(a)?"accept":/(?:^|:)id\/button2$/i.test(a)?"dismiss":/(?:^|:)id\/button3$/i.test(a)?"neutral":/(?:^|:)id\/permission_allow/i.test(a)?"accept":/(?:^|:)id\/permission_deny/i.test(a)?"dismiss":null);return n||(j.test(t.trim())?"accept":X.test(t.trim())?"dismiss":"neutral")}(n,e)})}return a}(l),p=l.filter(e=>J(e)&&!W(e)),u=J((t=p).find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??"")))||J(t[0]),c=(a=p,n=u,(r=a.map(e=>J(e)).filter(e=>e&&e!==n)).length?[...new Set(r)].join("\n"):void 0),f=(o=l,o.find(e=>e.bundleId)?.bundleId);return{alert:{...u?{title:u}:{},...c?{message:c}:{},buttons:d.map(e=>e.label),platform:"android",source:i.source,...f?{packageName:f}:{}},buttons:d}}((await i("snapshot_capture",async()=>await _(e,{helperWaitForIdleTimeoutMs:0,includeHiddenContentHints:!1}),{backend:"android",purpose:"alert"})).nodes)}function ea(e,t,a){return{kind:"alertHandled",platform:"android",action:e,handled:!0,alert:t,button:a,...R(`Alert ${e}ed`)}}async function en(e){var t;let{req:a,logPath:n,session:s,device:o}=e,r="accept"===(t=a.positionals?.[0])||"dismiss"===t||"wait"===t?t:"get",i=s?"frontmost-app"===s.surface?{surface:"frontmost-app"}:{bundleId:s.appBundleId,surface:s.surface}:{};if(!y("alert",o))return w("UNSUPPORTED_OPERATION","alert is not supported on this device");if("android"===o.platform){let t=I(a.positionals?.[1])??1e4;return ei(e,await Q(o,r,{timeoutMs:t}))}if("macos"===o.platform){let t=async e=>await h(e,i);return await es(e,r,t)}let l={verbose:a.flags?.verbose,logPath:n,traceLogPath:s?.trace?.outPath,requestId:a.meta?.requestId,iosXctestrunFile:a.flags?.iosXctestrunFile,iosXctestDerivedDataPath:a.flags?.iosXctestDerivedDataPath,iosXctestEnvDir:a.flags?.iosXctestEnvDir},d=async e=>await g(o,{command:"alert",action:e,appBundleId:s?.appBundleId},l);return await es(e,r,d)}async function es(e,t,a){if("wait"===t)return await eo(e,a);let n="accept"===t||"dismiss"===t?t:"get";return"accept"===n||"dismiss"===n?await er(e,n,a):ei(e,await a("get"))}async function eo(e,t){let a=I(e.req.positionals?.[1])??1e4,n=Date.now();for(;Date.now()-n<a;){try{return ei(e,await t("get"))}catch{}await D(300)}return w("COMMAND_FAILED","alert wait timed out")}async function er(e,t,a){var n,s;let o,i,l=Date.now();for(;Date.now()-l<2e3;){try{return ei(e,await a(t))}catch(t){i=t;let e=String(t?.message??"").toLowerCase();if(!e.includes("alert not found")&&!e.includes("no alert"))break}await D(300)}throw(n=i)instanceof r&&(s=n,(o=String(s?.message??"").toLowerCase()).includes("alert not found")||o.includes("no alert"))?new r(n.code,n.message,{...n.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."}):n}function ei(e,t){return E(e.sessionStore,e.session,e.req,t),{ok:!0,data:t}}async function el(e){let{req:t,logPath:a,sessionStore:n,session:s,device:o,parsed:r}=e,{setting:i,state:l,appBundleId:d,permissionTarget:p,latitude:u,longitude:c}=r;if(!y("settings",o))return w("UNSUPPORTED_OPERATION","settings is not supported on this device");if("macos"===o.platform&&!C(i))return w("INVALID_ARGS",A(i));let m=d??s?.appBundleId;if("clear-app-state"===i&&!m)return w("INVALID_ARGS","settings clear-app-state requires an app id when no app is bound to the session");let h="clear-app-state"===i?[i,l,m??""]:"permission"===i?[i,l,p??"",t.positionals?.[3]??"",m??""]:"location"===i&&"set"===l?[i,l,u??"",c??"",m??""]:[i,l,m??""],g=await f(o,"settings",h,t.flags?.out,{...S(a,t.flags,m,s?.trace?.outPath)});return E(n,s,t,g??{setting:i,state:l}),{ok:!0,data:g??{setting:i,state:l}}}async function ed(e){var t,a;let n;if("snapshot"!==e.command||"android"!==e.device.platform)return;let s=o(e.error);if("COMMAND_FAILED"===(t=s).code&&(a=t,n=`${a.message}
|
|
2
2
|
${a.hint??""}`,/Android UI hierarchy dump timed out/i.test(n)||/Stock UIAutomator fallback was skipped/i.test(n)||/Android accessibility snapshots can be blocked/i.test(n)||function(e){if(!e||"object"!=typeof e)return!1;let t=String(e.errorType??""),a=String(e.message??"");return/TimeoutException/i.test(t)||/timed out/i.test(a)}(t.details?.helper)||function(e){var t;if(!e)return!1;let a=e?.timeoutMs,n=e?.cmd,s=Array.isArray(t=e?.args)?t.map(String):"string"==typeof t?t.split(/\s+/):[];return"number"==typeof a&&"adb"===n&&s.includes("uiautomator")&&s.includes("dump")}(t.details)))return{ok:!1,error:{...s,details:{...s.details??{},androidSnapshotTimeoutScreenshot:await ep(e)}}}}async function ep(e){try{var s,r,i;let o=await t.mkdtemp(n.join(a.tmpdir(),"agent-device-android-snapshot-timeout-")),d=n.join(o,"snapshot-timeout-overlay-refs.png"),p=(s=await f(e.device,"screenshot",[d],void 0,{...S(e.logPath,{screenshotNoStabilize:!0},e.session?.appBundleId,e.session?.trace?.outPath),surface:e.session?.surface}),r=d,(i=s,"object"==typeof i&&null!==i&&"path"in i&&"string"==typeof i.path)?s.path:r);await t.access(p);let u=await eu(p,e.session);return l({level:"warn",phase:"android_snapshot_timeout_screenshot_captured",data:{path:p,overlayRefCount:"overlayRefCount"in u?u.overlayRefCount:void 0,overlayRefsAnnotated:"overlayRefsAnnotated"in u?u.overlayRefsAnnotated:void 0}}),u}catch(t){let e=o(t);return l({level:"warn",phase:"android_snapshot_timeout_screenshot_failed",data:{error:e.message}}),{captureFailed:!0,error:e.message}}}async function eu(e,t){if(!t?.snapshot)return{path:e,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:"unavailable",overlayRefCount:0};try{let a=await v({screenshotPath:e,snapshot:t.snapshot});return{path:e,overlayRefsRequested:!0,overlayRefsAnnotated:a.length>0,overlayRefCount:a.length,overlayRefSource:"session-snapshot",overlayRefs:a}}catch(a){let t=o(a);return l({level:"warn",phase:"android_snapshot_timeout_screenshot_overlay_failed",data:{path:e,error:t.message}}),{path:e,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:"session-snapshot",overlayRefCount:0,overlayAnnotationError:t.message}}}async function ec(e){return await em({...e,command:"snapshot",unsupportedMessage:"snapshot is not supported on this device",execute:async({runtime:e,sessionName:t,req:a,snapshotScope:n})=>{let s=await e.capture.snapshot({session:t,interactiveOnly:a.flags?.snapshotInteractiveOnly,depth:a.flags?.snapshotDepth,scope:n,raw:a.flags?.snapshotRaw,forceFull:a.flags?.snapshotForceFull});return{data:s,record:{kind:"snapshot",nodes:s.nodes.length,truncated:s.truncated}}}})}async function ef(e){return await em({...e,command:"diff",unsupportedMessage:"diff is not supported on this device",execute:async({runtime:e,sessionName:t,req:a,snapshotScope:n})=>{let s=await e.capture.diffSnapshot({session:t,interactiveOnly:a.flags?.snapshotInteractiveOnly,depth:a.flags?.snapshotDepth,scope:n,raw:a.flags?.snapshotRaw});return{data:s,record:{kind:"diff",mode:"snapshot",baselineInitialized:s.baselineInitialized,summary:s.summary}}}})}async function em(e){var t,a;let{req:n,sessionName:s,logPath:o,sessionStore:i}=e,{session:l,device:d}=await O(i,s,n.flags);if(!y(e.command,d))return w("UNSUPPORTED_OPERATION",e.unsupportedMessage);let p=m(n.flags?.snapshotScope,l);if(!p.ok)return p;let f=(t=e.command,a=l,"ios"!==d.platform||a?.appBundleId?null:w("SESSION_NOT_FOUND",`iOS ${t} requires an active app session on the target device. Run open first (for example: open --session ${a?.name??"sim"} --platform ios --device "<name>" <app>).`));return f||await K(l,d,async()=>{var t,a;let f,m,h=function(e){let{req:t,sessionName:a,logPath:n,sessionStore:s,session:o,device:i,snapshotScope:l}=e;return U({backend:function(e){let{req:t,logPath:a,session:n,device:s,snapshotScope:o}=e;return{platform:s.platform,captureSnapshot:async(e,r)=>{let i=await c({device:s,session:n,flags:t.flags,outPath:r?.outPath??t.flags?.out,logPath:a,snapshotScope:o}),l=x(n);return{snapshot:i.snapshot,...N(i),...l?{snapshotDiagnostics:l}:{},appName:n?.appBundleId?n.appName??n.appBundleId:void 0,appBundleId:n?.appBundleId}}}}({req:t,logPath:n,session:o,device:i,snapshotScope:l}),...M("snapshot"),sessions:u({sessionName:a,getSession:()=>s.get(a),recordOptions:{includeSnapshot:!0},setRecord:e=>{var n;let o=function(e){if(!e.snapshot)throw new r("UNKNOWN","snapshot runtime did not produce session state");return e}(e),l=s.get(a);s.set(a,function(e){var t,a;let{current:n,sessionName:s,device:o,record:r,refScopedSnapshot:i}=e,l=(t=n,a=r,i&&a.snapshot?.nodes.length===0&&t?.snapshot!==void 0),d=l?n.snapshot:r.snapshot,p=P({session:n,sessionName:s,device:o,snapshot:d,appBundleId:r.appBundleId});return p.snapshotScopeSource=function(e){let{current:t,keepCurrentSnapshot:a,refScopedSnapshot:n}=e;if(n)return a?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}({current:n,keepCurrentSnapshot:l,refScopedSnapshot:i}),r.appName&&(p.appName=r.appName),p}({current:l,sessionName:a,device:i,record:o,refScopedSnapshot:(n=t,n.flags?.snapshotScope?.trim().startsWith("@")===!0)}))}})})}({req:n,sessionName:s,logPath:o,sessionStore:i,session:l,device:d,snapshotScope:p.scope});try{m=await e.execute({runtime:h,sessionName:s,req:n,snapshotScope:p.scope})}catch(a){let t=await ed({error:a,command:e.command,logPath:o,session:l,device:d});if(!t)throw a;return t}return(f=(t={req:n,sessionName:s,sessionStore:i,result:m.record}).sessionStore.get(t.sessionName))&&t.sessionStore.recordAction(f,{command:t.req.command,positionals:t.req.positionals??[],flags:t.req.flags??{},result:"snapshot"===(a=t.result).kind?{nodes:a.nodes,truncated:a.truncated}:{mode:a.mode,baselineInitialized:a.baselineInitialized,summary:a.summary}}),{ok:!0,data:m.data}})}let eh={snapshot:async({req:e,sessionName:t,logPath:a,sessionStore:n})=>await ec({req:e,sessionName:t,logPath:a,sessionStore:n}),diff:async({req:e,sessionName:t,logPath:a,sessionStore:n})=>e.positionals?.[0]!=="snapshot"?w("INVALID_ARGS","diff currently supports only: diff snapshot"):await ef({req:e,sessionName:t,logPath:a,sessionStore:n}),wait:async({req:e,sessionName:t,logPath:a,sessionStore:n})=>await k({req:e,sessionName:t,logPath:a,sessionStore:n}),alert:async({req:e,sessionName:t,logPath:a,sessionStore:n})=>{let{session:s,device:o}=await O(n,t,e.flags);return await K(s,o,async()=>await en({req:e,logPath:a,sessionStore:n,session:s,device:o}))},settings:async({req:e,sessionName:t,logPath:a,sessionStore:n})=>{let s,o,r,i=(s=e.positionals?.[0]?.toLowerCase(),o=e.positionals?.[1]?.toLowerCase(),r=e.positionals?.[2]?.toLowerCase(),"clear-app-state"===s?{ok:!0,parsed:{setting:s,state:"clear",appBundleId:"clear"===o?e.positionals?.[2]:e.positionals?.[1]}}:s&&o&&("permission"!==s||r)&&("location"!==s||"set"!==o||e.positionals?.[2]&&e.positionals?.[3])?{ok:!0,parsed:{setting:s,state:o,permissionTarget:r,latitude:e.positionals?.[2],longitude:e.positionals?.[3]}}:w("INVALID_ARGS",b));if(!i.ok)return i;let{session:l,device:d}=await O(n,t,e.flags);return await K(l,d,async()=>await el({req:e,logPath:a,sessionStore:n,session:l,device:d,parsed:i.parsed}))}};async function ew(e){let t=eh[e.req.command];return t?await t(e):null}export{L as snapshot_namespaceObject};
|
package/dist/src/web.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AppError as e}from"./733.js";import{withDiagnosticTimer as t}from"./432.js";import{resolveWebProvider as r}from"./provider.js";function o(){return{open:(e,t)=>r().open(t?.url??e,{url:t?.url}),openDevice:()=>r().open("about:blank"),close:e=>r().close(e),tap:(e,t)=>r().click(e,t),doubleTap:()=>n("doubleTap"),swipe:()=>n("swipe"),pan:()=>n("pan"),fling:()=>n("fling"),longPress:()=>n("longPress"),focus:(e,t)=>r().click(e,t),type:(e,t)=>r().typeText(e,{delayMs:t}),fill:(e,t,o,n)=>r().fill(e,t,o,{delayMs:n}),scroll:(e,t)=>r().scroll(e,t),pinch:()=>n("pinch"),screenshot:(e,t)=>r().screenshot(e,t),snapshot:async e=>{let o=await t("snapshot_capture",async()=>await r().snapshot(e),{backend:"web"});return{nodes:o.nodes,truncated:o.truncated??!1,backend:"web"}},back:()=>n("back"),home:()=>n("home"),rotate:()=>n("rotate"),rotateGesture:()=>n("rotateGesture"),transformGesture:()=>n("transformGesture"),appSwitcher:()=>n("appSwitcher"),readClipboard:()=>n("readClipboard"),writeClipboard:()=>n("writeClipboard"),setSetting:()=>n("setSetting")}}async function n(t){throw new e("UNSUPPORTED_OPERATION",`${t} is not supported on web`)}export{o as createWebInteractor};
|
|
1
|
+
import{AppError as e}from"./733.js";import{withDiagnosticTimer as t}from"./432.js";import{resolveWebProvider as r}from"./provider.js";function o(){return{open:(e,t)=>r().open(t?.url??e,{url:t?.url}),openDevice:()=>r().open("about:blank"),close:e=>r().close(e),tap:(e,t)=>r().click(e,t),doubleTap:()=>n("doubleTap"),swipe:()=>n("swipe"),pan:()=>n("pan"),fling:()=>n("fling"),longPress:()=>n("longPress"),focus:(e,t)=>r().click(e,t),type:(e,t)=>r().typeText(e,{delayMs:t}),fill:(e,t,o,n)=>r().fill(e,t,o,{delayMs:n}),scroll:(e,t)=>r().scroll(e,t),pinch:()=>n("pinch"),screenshot:(e,t)=>r().screenshot(e,t),setViewport:(e,t)=>r().setViewport(e,t),snapshot:async e=>{let o=await t("snapshot_capture",async()=>await r().snapshot(e),{backend:"web"});return{nodes:o.nodes,truncated:o.truncated??!1,backend:"web"}},back:()=>n("back"),home:()=>n("home"),rotate:()=>n("rotate"),rotateGesture:()=>n("rotateGesture"),transformGesture:()=>n("transformGesture"),appSwitcher:()=>n("appSwitcher"),readClipboard:()=>n("readClipboard"),writeClipboard:()=>n("writeClipboard"),setSetting:()=>n("setSetting")}}async function n(t){throw new e("UNSUPPORTED_OPERATION",`${t} is not supported on web`)}export{o as createWebInteractor};
|
package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift
CHANGED
|
@@ -625,16 +625,105 @@ extension RunnerTests {
|
|
|
625
625
|
)
|
|
626
626
|
)
|
|
627
627
|
}
|
|
628
|
+
if let durationMs = command.durationMs,
|
|
629
|
+
durationMs.isFinite == false || durationMs < 0 || durationMs > 10000
|
|
630
|
+
{
|
|
631
|
+
return Response(
|
|
632
|
+
ok: false,
|
|
633
|
+
error: ErrorPayload(
|
|
634
|
+
code: "INVALID_ARGS",
|
|
635
|
+
message: "scroll durationMs must be between 0 and 10000"
|
|
636
|
+
)
|
|
637
|
+
)
|
|
638
|
+
}
|
|
628
639
|
return executeDragGesture(
|
|
629
640
|
activeApp: activeApp,
|
|
630
641
|
x: frame.minX + plan.x1,
|
|
631
642
|
y: frame.minY + plan.y1,
|
|
632
643
|
x2: frame.minX + plan.x2,
|
|
633
644
|
y2: frame.minY + plan.y2,
|
|
634
|
-
durationMs:
|
|
635
|
-
synthesized:
|
|
645
|
+
durationMs: command.durationMs,
|
|
646
|
+
synthesized: command.durationMs != nil,
|
|
636
647
|
message: "scrolled"
|
|
637
648
|
)
|
|
649
|
+
case .desktopScroll:
|
|
650
|
+
guard let direction = command.direction,
|
|
651
|
+
direction == "up" || direction == "down" || direction == "left" || direction == "right"
|
|
652
|
+
else {
|
|
653
|
+
return Response(
|
|
654
|
+
ok: false,
|
|
655
|
+
error: ErrorPayload(
|
|
656
|
+
code: "INVALID_ARGS",
|
|
657
|
+
message: "desktopScroll requires direction up|down|left|right"
|
|
658
|
+
)
|
|
659
|
+
)
|
|
660
|
+
}
|
|
661
|
+
let appFrame = activeApp.frame
|
|
662
|
+
let frame = resolvedTouchReferenceFrame(app: activeApp, appFrame: appFrame)
|
|
663
|
+
guard frame.width > 0, frame.height > 0 else {
|
|
664
|
+
return Response(
|
|
665
|
+
ok: false,
|
|
666
|
+
error: ErrorPayload(message: "desktopScroll could not resolve a usable interaction frame")
|
|
667
|
+
)
|
|
668
|
+
}
|
|
669
|
+
guard let plan = runnerScrollGesturePlan(
|
|
670
|
+
direction: direction,
|
|
671
|
+
amount: command.amount,
|
|
672
|
+
pixels: command.pixels,
|
|
673
|
+
referenceWidth: frame.width,
|
|
674
|
+
referenceHeight: frame.height
|
|
675
|
+
) else {
|
|
676
|
+
return Response(
|
|
677
|
+
ok: false,
|
|
678
|
+
error: ErrorPayload(
|
|
679
|
+
code: "INVALID_ARGS",
|
|
680
|
+
message: "desktopScroll could not compute a wheel plan"
|
|
681
|
+
)
|
|
682
|
+
)
|
|
683
|
+
}
|
|
684
|
+
let x = frame.midX
|
|
685
|
+
let y = frame.midY
|
|
686
|
+
let localX = x - (appFrame.isEmpty ? frame.minX : appFrame.minX)
|
|
687
|
+
let localY = y - (appFrame.isEmpty ? frame.minY : appFrame.minY)
|
|
688
|
+
if let durationMs = command.durationMs,
|
|
689
|
+
durationMs.isFinite == false || durationMs < 0 || durationMs > 10000
|
|
690
|
+
{
|
|
691
|
+
return Response(
|
|
692
|
+
ok: false,
|
|
693
|
+
error: ErrorPayload(
|
|
694
|
+
code: "INVALID_ARGS",
|
|
695
|
+
message: "desktopScroll durationMs must be between 0 and 10000"
|
|
696
|
+
)
|
|
697
|
+
)
|
|
698
|
+
}
|
|
699
|
+
let touchFrame = resolvedTouchVisualizationFrame(
|
|
700
|
+
app: activeApp,
|
|
701
|
+
x: localX,
|
|
702
|
+
y: localY
|
|
703
|
+
)
|
|
704
|
+
do {
|
|
705
|
+
var scrollError: Error?
|
|
706
|
+
let timing = measureGesture {
|
|
707
|
+
do {
|
|
708
|
+
try desktopScrollAt(
|
|
709
|
+
app: activeApp,
|
|
710
|
+
x: x,
|
|
711
|
+
y: y,
|
|
712
|
+
direction: direction,
|
|
713
|
+
pixels: plan.travelPixels,
|
|
714
|
+
durationMs: command.durationMs
|
|
715
|
+
)
|
|
716
|
+
} catch {
|
|
717
|
+
scrollError = error
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
if let scrollError {
|
|
721
|
+
throw scrollError
|
|
722
|
+
}
|
|
723
|
+
return gestureResponse(message: "scrolled", timing: timing, frame: .touch(touchFrame))
|
|
724
|
+
} catch {
|
|
725
|
+
return Response(ok: false, error: ErrorPayload(message: error.localizedDescription))
|
|
726
|
+
}
|
|
638
727
|
case .remotePress:
|
|
639
728
|
guard let button = tvRemoteButton(from: command.remoteButton) else {
|
|
640
729
|
return Response(ok: false, error: ErrorPayload(message: "remotePress requires remoteButton"))
|
|
@@ -910,8 +999,7 @@ extension RunnerTests {
|
|
|
910
999
|
/// Shared drag execution for `.drag` and the fused `.scroll`. Mirrors the original `.drag` body
|
|
911
1000
|
/// exactly: keyboardAvoidingDragPoints -> resolvedDragVisualizationFrame -> synthesized branch
|
|
912
1001
|
/// (16-10000ms clamp) or non-synthesized dragAt with coordinateDragHoldDuration ->
|
|
913
|
-
/// gestureResponse(.drag). `.scroll`
|
|
914
|
-
/// non-synthesized drag path scroll's drag used today.
|
|
1002
|
+
/// gestureResponse(.drag). `.scroll` uses the synthesized path only when a duration is requested.
|
|
915
1003
|
private func executeDragGesture(
|
|
916
1004
|
activeApp: XCUIApplication,
|
|
917
1005
|
x: Double,
|
package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift
CHANGED
|
@@ -144,7 +144,7 @@ final class RunnerCommandJournal {
|
|
|
144
144
|
case .snapshot, .screenshot:
|
|
145
145
|
return false
|
|
146
146
|
case .tap, .mouseClick, .longPress, .drag,
|
|
147
|
-
.remotePress, .type, .swipe, .scroll, .findText, .querySelector, .readText, .back,
|
|
147
|
+
.remotePress, .type, .swipe, .scroll, .desktopScroll, .findText, .querySelector, .readText, .back,
|
|
148
148
|
.backInApp, .backSystem, .home, .rotate, .appSwitcher, .keyboardDismiss, .keyboardReturn,
|
|
149
149
|
.alert, .pinch, .sequence, .rotateGesture, .transformGesture, .recordStart, .recordStop,
|
|
150
150
|
.status, .uptime, .shutdown:
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import XCTest
|
|
2
2
|
|
|
3
|
+
#if os(macOS)
|
|
4
|
+
import CoreGraphics
|
|
5
|
+
#endif
|
|
6
|
+
|
|
3
7
|
private enum RunnerInterfaceOrientation {
|
|
4
8
|
static let unknown = 0
|
|
5
9
|
static let portrait = 1
|
|
@@ -605,6 +609,110 @@ extension RunnerTests {
|
|
|
605
609
|
#endif
|
|
606
610
|
}
|
|
607
611
|
|
|
612
|
+
func desktopScrollAt(
|
|
613
|
+
app: XCUIApplication,
|
|
614
|
+
x: Double,
|
|
615
|
+
y: Double,
|
|
616
|
+
direction: String,
|
|
617
|
+
pixels: Double,
|
|
618
|
+
durationMs: Double?
|
|
619
|
+
) throws {
|
|
620
|
+
#if os(macOS)
|
|
621
|
+
guard let events = desktopScrollWheelDeltaEvents(
|
|
622
|
+
direction: direction,
|
|
623
|
+
pixels: pixels,
|
|
624
|
+
durationMs: durationMs
|
|
625
|
+
) else {
|
|
626
|
+
throw NSError(
|
|
627
|
+
domain: "AgentDeviceRunner",
|
|
628
|
+
code: 1,
|
|
629
|
+
userInfo: [NSLocalizedDescriptionKey: "unsupported desktop scroll direction: \(direction)"]
|
|
630
|
+
)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
let coordinate = interactionCoordinate(app: app, x: x, y: y)
|
|
634
|
+
let interval = desktopScrollEventIntervalSeconds(durationMs: durationMs, eventCount: events.count)
|
|
635
|
+
for (index, deltas) in events.enumerated() {
|
|
636
|
+
// Keep desktop scrolling on XCTest's coordinate API so macOS owns wheel synthesis, natural
|
|
637
|
+
// scrolling preference handling, and cursor placement instead of posting raw CGEvents.
|
|
638
|
+
coordinate.scroll(
|
|
639
|
+
byDeltaX: CGFloat(deltas.horizontal),
|
|
640
|
+
deltaY: CGFloat(deltas.vertical)
|
|
641
|
+
)
|
|
642
|
+
if interval > 0 && index < events.count - 1 {
|
|
643
|
+
Thread.sleep(forTimeInterval: interval)
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
#elseif os(tvOS)
|
|
647
|
+
throw NSError(
|
|
648
|
+
domain: "AgentDeviceRunner",
|
|
649
|
+
code: 1,
|
|
650
|
+
userInfo: [NSLocalizedDescriptionKey: "desktopScroll is not supported on tvOS"]
|
|
651
|
+
)
|
|
652
|
+
#else
|
|
653
|
+
throw NSError(
|
|
654
|
+
domain: "AgentDeviceRunner",
|
|
655
|
+
code: 1,
|
|
656
|
+
userInfo: [NSLocalizedDescriptionKey: "desktopScroll is only supported on macOS"]
|
|
657
|
+
)
|
|
658
|
+
#endif
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
func desktopScrollWheelDeltas(direction: String, pixels: Double) -> (vertical: Int32, horizontal: Int32)? {
|
|
662
|
+
let magnitude = Int32(max(1, min(Double(Int32.max), pixels.rounded())))
|
|
663
|
+
switch direction {
|
|
664
|
+
case "up":
|
|
665
|
+
return (vertical: magnitude, horizontal: 0)
|
|
666
|
+
case "down":
|
|
667
|
+
return (vertical: -magnitude, horizontal: 0)
|
|
668
|
+
case "left":
|
|
669
|
+
return (vertical: 0, horizontal: magnitude)
|
|
670
|
+
case "right":
|
|
671
|
+
return (vertical: 0, horizontal: -magnitude)
|
|
672
|
+
default:
|
|
673
|
+
return nil
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
func desktopScrollWheelDeltaEvents(
|
|
678
|
+
direction: String,
|
|
679
|
+
pixels: Double,
|
|
680
|
+
durationMs: Double?
|
|
681
|
+
) -> [(vertical: Int32, horizontal: Int32)]? {
|
|
682
|
+
guard let totalDeltas = desktopScrollWheelDeltas(direction: direction, pixels: pixels) else {
|
|
683
|
+
return nil
|
|
684
|
+
}
|
|
685
|
+
let magnitude = max(abs(Int(totalDeltas.vertical)), abs(Int(totalDeltas.horizontal)))
|
|
686
|
+
let duration = max(0, durationMs ?? 0)
|
|
687
|
+
let requestedEventCount = duration > 0 ? Int(ceil(duration / 16.0)) : 1
|
|
688
|
+
let eventCount = max(1, min(magnitude, requestedEventCount))
|
|
689
|
+
guard eventCount > 1 else {
|
|
690
|
+
return [totalDeltas]
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if totalDeltas.vertical != 0 {
|
|
694
|
+
return distributeDesktopScrollDelta(totalDeltas.vertical, eventCount: eventCount)
|
|
695
|
+
.map { (vertical: $0, horizontal: 0) }
|
|
696
|
+
}
|
|
697
|
+
return distributeDesktopScrollDelta(totalDeltas.horizontal, eventCount: eventCount)
|
|
698
|
+
.map { (vertical: 0, horizontal: $0) }
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
func desktopScrollEventIntervalSeconds(durationMs: Double?, eventCount: Int) -> TimeInterval {
|
|
702
|
+
guard let durationMs, durationMs > 0, eventCount > 1 else { return 0 }
|
|
703
|
+
return (durationMs / 1000.0) / Double(eventCount - 1)
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
private func distributeDesktopScrollDelta(_ delta: Int32, eventCount: Int) -> [Int32] {
|
|
707
|
+
let sign: Int32 = delta < 0 ? -1 : 1
|
|
708
|
+
let magnitude = abs(Int(delta))
|
|
709
|
+
let base = magnitude / eventCount
|
|
710
|
+
let remainder = magnitude % eventCount
|
|
711
|
+
return (0..<eventCount).map { index in
|
|
712
|
+
sign * Int32(base + (index < remainder ? 1 : 0))
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
608
716
|
func doubleTapAt(app: XCUIApplication, x: Double, y: Double) -> RunnerInteractionOutcome {
|
|
609
717
|
if let outcome = selectFocusedTvElement(app: app, point: CGPoint(x: x, y: y), action: "double tap") {
|
|
610
718
|
guard case .performed = outcome else { return outcome }
|
|
@@ -1199,4 +1307,26 @@ extension RunnerTests {
|
|
|
1199
1307
|
XCTAssertEqual(vector.dy, expected.dy, "dy interfaceOrientation \(orientation)")
|
|
1200
1308
|
}
|
|
1201
1309
|
}
|
|
1310
|
+
|
|
1311
|
+
func testDesktopScrollWheelDeltasMapDirections() throws {
|
|
1312
|
+
XCTAssertEqual(try XCTUnwrap(desktopScrollWheelDeltas(direction: "up", pixels: 120)).vertical, 120)
|
|
1313
|
+
XCTAssertEqual(try XCTUnwrap(desktopScrollWheelDeltas(direction: "down", pixels: 120)).vertical, -120)
|
|
1314
|
+
XCTAssertEqual(try XCTUnwrap(desktopScrollWheelDeltas(direction: "left", pixels: 120)).horizontal, 120)
|
|
1315
|
+
XCTAssertEqual(try XCTUnwrap(desktopScrollWheelDeltas(direction: "right", pixels: 120)).horizontal, -120)
|
|
1316
|
+
XCTAssertNil(desktopScrollWheelDeltas(direction: "diagonal", pixels: 120))
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
func testDesktopScrollWheelDeltaEventsHonorDurationAndPreservePixels() throws {
|
|
1320
|
+
let events = try XCTUnwrap(desktopScrollWheelDeltaEvents(direction: "down", pixels: 200, durationMs: 50))
|
|
1321
|
+
XCTAssertEqual(events.count, 4)
|
|
1322
|
+
XCTAssertEqual(events.map(\.vertical).reduce(0, +), -200)
|
|
1323
|
+
XCTAssertEqual(events.map(\.horizontal).reduce(0, +), 0)
|
|
1324
|
+
XCTAssertEqual(desktopScrollEventIntervalSeconds(durationMs: 50, eventCount: events.count), 0.05 / 3.0)
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
func testDesktopScrollWheelDeltaEventsKeepInstantScrollSingleEvent() throws {
|
|
1328
|
+
let events = try XCTUnwrap(desktopScrollWheelDeltaEvents(direction: "down", pixels: 200, durationMs: 0))
|
|
1329
|
+
XCTAssertEqual(events.count, 1)
|
|
1330
|
+
XCTAssertEqual(events.first?.vertical, -200)
|
|
1331
|
+
}
|
|
1202
1332
|
}
|
|
@@ -9,6 +9,7 @@ enum CommandType: String, Codable {
|
|
|
9
9
|
case type
|
|
10
10
|
case swipe
|
|
11
11
|
case scroll
|
|
12
|
+
case desktopScroll
|
|
12
13
|
case findText
|
|
13
14
|
case querySelector
|
|
14
15
|
case readText
|
|
@@ -69,8 +70,9 @@ extension CommandType {
|
|
|
69
70
|
// Interaction commands: require the foreground-guard + stabilization preflight.
|
|
70
71
|
// keyboardReturn is the sibling of keyboardDismiss (missing from the historical switch —
|
|
71
72
|
// drift the table now prevents). .scroll is the fused frame-resolve + drag scroll; same
|
|
72
|
-
// classification as .drag. .
|
|
73
|
-
|
|
73
|
+
// classification as .drag. .desktopScroll is the macOS frame-resolve + wheel event sibling.
|
|
74
|
+
// .sequence is the fused multi-step gesture batch.
|
|
75
|
+
case .tap, .longPress, .drag, .remotePress, .type, .swipe, .scroll, .desktopScroll,
|
|
74
76
|
.back, .backInApp, .backSystem, .rotate, .appSwitcher,
|
|
75
77
|
.keyboardDismiss, .keyboardReturn, .pinch, .sequence, .rotateGesture, .transformGesture:
|
|
76
78
|
return CommandTraits(isInteraction: true, readOnly: .never, isLifecycle: false)
|
package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift
CHANGED
|
@@ -119,6 +119,24 @@ extension RunnerTests {
|
|
|
119
119
|
XCTAssertEqual(plan.travelPixels, 720)
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
func testRunnerScrollGesturePlanClampsExplicitPixelsVertically() throws {
|
|
123
|
+
// 400x800, down, pixels 1000 clamps travel to the safe band (720): (200,760)->(200,40).
|
|
124
|
+
let plan = try XCTUnwrap(
|
|
125
|
+
runnerScrollGesturePlan(
|
|
126
|
+
direction: "down",
|
|
127
|
+
amount: nil,
|
|
128
|
+
pixels: 1000,
|
|
129
|
+
referenceWidth: 400,
|
|
130
|
+
referenceHeight: 800
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
XCTAssertEqual(plan.x1, 200)
|
|
134
|
+
XCTAssertEqual(plan.y1, 760)
|
|
135
|
+
XCTAssertEqual(plan.x2, 200)
|
|
136
|
+
XCTAssertEqual(plan.y2, 40)
|
|
137
|
+
XCTAssertEqual(plan.travelPixels, 720)
|
|
138
|
+
}
|
|
139
|
+
|
|
122
140
|
func testRunnerScrollGesturePlanFloorsTinyFrames() throws {
|
|
123
141
|
// 2x2, down, pixels 10 engages every max(1, ...) floor and the .5 rounding cases the two
|
|
124
142
|
// ports must agree on (halfTravel 0.5 -> 1, center 1 from 2/2): (1,2)->(1,0), travel 1.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.9",
|
|
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,8 +103,8 @@
|
|
|
103
103
|
"perf:ios": "node --experimental-strip-types scripts/perf/run.ts --platform ios",
|
|
104
104
|
"perf:android": "node --experimental-strip-types scripts/perf/run.ts --platform android",
|
|
105
105
|
"lint": "oxlint . --deny-warnings",
|
|
106
|
-
"format": "oxfmt --write src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
|
|
107
|
-
"format:check": "oxfmt --check src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
|
|
106
|
+
"format": "node ./node_modules/oxfmt/bin/oxfmt --write src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
|
|
107
|
+
"format:check": "node ./node_modules/oxfmt/bin/oxfmt --check src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
|
|
108
108
|
"fallow": "fallow audit --base origin/main",
|
|
109
109
|
"fallow:all": "fallow --summary",
|
|
110
110
|
"fallow:baseline": "(fallow dead-code --save-baseline fallow-baselines/dead-code.json --summary || true) && (fallow health --save-baseline fallow-baselines/health.json --summary || true)",
|
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.17.
|
|
10
|
+
"version": "0.17.9",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "agent-device",
|
|
15
|
-
"version": "0.17.
|
|
15
|
+
"version": "0.17.9",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|
package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.8.apk.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
7babb1a8cfdc9ea488cb6d419067a5345cf287581532de6a388b3c0f6bb9f72f agent-device-android-multitouch-helper-0.17.8.apk
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
95eff5dda23179abb7da5bcf1650fb4e9ebcf40ae08871936683233aee152914 agent-device-android-snapshot-helper-0.17.8.apk
|
package/dist/src/6311.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import e from"node:path";import{styleText as t}from"node:util";import{buildMobileSnapshotPresentation as n,displayNodeLabel as r}from"./9873.js";import{normalizeError as i,AppError as o}from"./733.js";import{isSnapshotBackend as l,usesMobileSnapshotPresentation as s}from"./4291.js";import{buildSnapshotDisplayLines as a,formatSnapshotLine as u}from"./7244.js";function d(e){return e.width>0&&e.height>0}function f(e,t){return!!e&&!!t&&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 c(e){return"number"!=typeof e.parentIndex}function h(e){let t=(e.type??"").toLowerCase(),n=(e.identifier??"").trim().toLowerCase();return t.includes("edittext")||t.includes("textfield")||"composer"===n}function p(e){let t=(e.type??"").toLowerCase();return t.includes("scroll")||t.includes("list")||t.includes("recyclerview")}function g(e){var t;let n=r(e);if(!n||n!==e.identifier?.trim()||(t=n,!/^[\w.]+:id\/[\w.-]+$/i.test(t)))return n;let i=(e.type??"").toLowerCase();return i.includes("view")||i.includes("layout")||i.includes("image")||i.includes("list")||i.includes("recyclerview")||i.includes("collection")?"":n}function $(e){let t=e.trim().replace(/\s+/g," ").toLowerCase();return!t||/^(true|false|\d+)$/.test(t)?null:t}function x(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 m(e,t,n){let r=[t];for(;r.length>0;){let t=r.pop();if(!n.has(t))for(let i of(n.add(t),e))i.parentIndex!==t||n.has(i.index)||r.push(i.index)}}let y=["button","switch","checkbox","radio"],v=["button","image","textview","view"];function b(e){if(!0===e.hittable||h(e))return!1;let t=(e.type??"").toLowerCase();return t.includes("text")||t.includes("image")||t.includes("icon")}function C(e){if(!e.rect||!d(e.rect)||c(e)||h(e))return!1;let t=(e.type??"").toLowerCase();return"text"===t||M(t,v)}function w(e,t){let n=S(e);return S(t)>n?t:e}function S(e){let t=(e.type??"").toLowerCase(),n=0;return M(t,y)?n+=100:t.includes("image")?n+=30:t.includes("textview")||"text"===t?n+=20:t.includes("view")&&(n+=10),!0===e.hittable&&(n+=20),!1!==e.enabled&&(n+=5),n}function M(e,t){return t.some(t=>e.includes(t))}function N(e){process.stdout.write(`${JSON.stringify(e,null,2)}
|
|
2
|
-
`)}function I(e,t={}){let n=e instanceof o?i(e):e;process.stderr.write(`Error (${n.code}): ${n.message}
|
|
3
|
-
`),n.hint&&process.stderr.write(`Hint: ${n.hint}
|
|
4
|
-
`),n.diagnosticId&&process.stderr.write(`Diagnostic ID: ${n.diagnosticId}
|
|
5
|
-
`),n.logPath&&process.stderr.write(`Diagnostics Log: ${n.logPath}
|
|
6
|
-
`),t.showDetails&&n.details&&process.stderr.write(`${JSON.stringify(n.details,null,2)}
|
|
7
|
-
`)}function A(e,t={}){var i,o,y,v;let S,M,N,I,O,_=e.nodes,k=Array.isArray(_)?_:[],L=s(l(e.backend)?e.backend:void 0),j=function(e,t,n){let r;if(n.raw||!((r=e.androidSnapshot)&&"object"==typeof r&&"android-helper"===r.backend))return{nodes:t,filteredCount:0};let i=function(e){var t,n;if(0===e.length)return e;let r=new Set,i=new Map,o=new Map(e.map(e=>[e.index,e]));(function(e,t){for(let n of e)!n.rect||d(n.rect)||c(n)||m(e,n.index,t)})(e,r),function(e,t,n,r){for(let i of e){if(n.has(i.index)||i.rect||c(i))continue;let o=function(e,t,n){let r=e;for(;"number"==typeof r.parentIndex;){let e=t.get(r.parentIndex);if(!e)break;if(n(e))return e;r=e}return null}(i,t,p);o&&function(e,t,n){if(!n)return;let r=e.get(t.index)??t;e.set(t.index,{...r,hiddenContentAbove:!0===r.hiddenContentAbove||"above"===n||void 0,hiddenContentBelow:!0===r.hiddenContentBelow||"below"===n||void 0})}(r,o,function(e,t){let n=t.filter(t=>t.parentIndex===e.parentIndex&&t.rect&&d(t.rect)).map(e=>e.index);return 0===n.length?null:e.index<Math.min(...n)?"above":e.index>Math.max(...n)?"below":null}(i,e)),m(e,i.index,n)}}(e,o,r,i);for(let n of e){if(r.has(n.index)||!(!0===(t=n).hittable&&!h(t)&&t.rect&&d(t.rect)&&0===g(t).trim().length))continue;let o=function(e,t,n){let r=[],i=[],o=new Set;for(let l of e){if(n.has(l.index)||!b(l)||!f(l.rect,t.rect))continue;let e=g(l).trim().replace(/\s+/g," "),s=$(e);i.push(l.index),!e||!s||o.has(s)||(o.add(s),r.push(e))}return{label:r.join(", "),removableIndexes:i}}(x(e,n.index),n,r);if(o.label)for(let t of(i.set(n.index,{...n,...i.get(n.index),label:o.label}),o.removableIndexes))m(e,t,r)}for(let t of e){if(r.has(t.index)||!(!0===(n=t).hittable&&!h(n)&&n.rect&&d(n.rect)&&$(g(n))))continue;let i=$(g(t));if(!i)continue;let o=x(e,t.index).filter(e=>!r.has(e.index)&&function(e,t,n){if(!C(t)||!f(t.rect,e.rect))return!1;let r=$(g(t));return!!(r&&n!==r&&n.includes(r))}(t,e,i));for(let t of o.filter(b))m(e,t.index,r);let l=o.filter(e=>!b(e)),s=new Set(l.map(e=>$(g(e))).filter(e=>!!e));if(!(l.length<2)&&!(s.size<2))for(let t of l)m(e,t.index,r)}let l=new Map;for(let t of e){if(r.has(t.index)||!C(t))continue;let n=$(g(t));if(!n)continue;let o=l.get(n);if(o&&function(e,t,n){var r,i,o,l;return!n.has(e.index)&&(r=e.rect,i=t.rect,!r||!i||Math.abs(r.y+r.height/2-(i.y+i.height/2))<=Math.max(r.height,i.height,1))&&(o=e,l=t,(o.parentIndex===l.parentIndex?3>=Math.abs(o.index-l.index):o.parentIndex!==l.index&&l.parentIndex!==o.index&&1>=Math.abs((o.depth??0)-(l.depth??0))&&2>=Math.abs(o.index-l.index))||function(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&&w(n,r).index===n.index}(e,t))}(o,t,r)){let s=function(e,t,n,r,i){var o,l,s;let a=w(t,n),u=a.index===t.index?n:t,d=(u.type??"").toLowerCase().includes("image")?"has image":null,f=i.get(a.index)??a,c=i.get(u.index)?.presentationHints??u.presentationHints;return i.set(a.index,{...f,presentationHints:(o=f.presentationHints,l=c,s=d,[...new Set([...Array.isArray(o)?o:[],...Array.isArray(l)?l:[],...s?[s]:[]])])}),m(e,u.index,r),i.get(a.index)??a}(e,o,t,r,i);l.set(n,s);continue}l.set(n,t)}return e.filter(e=>!r.has(e.index)).map(e=>i.get(e.index)??e)}(t);return{nodes:i,filteredCount:t.length-i.length}}(e,k,t),H=(S="string"==typeof(i=e).appName?i.appName:void 0,M="string"==typeof i.appBundleId?i.appBundleId:void 0,N=[],S&&N.push(`Page: ${S}`),M&&N.push(`App: ${M}`),N.length>0?`${N.join("\n")}
|
|
8
|
-
`:""),T=function(e,t,n,i={nodes:t,filteredCount:0}){var o;let l=K(e);if(!(o=e).snapshotQuality&&!function(e){let t=e.snapshotDiagnostics;if(!t||"object"!=typeof t)return!1;let n=t.stats;return!!(n&&"object"==typeof n&&"web"===n.platform)}(o)){let e=function(e,t){if(!0===t.scoped||!0===t.depthLimited||e.length>3)return null;let n=1===e.length?"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.`}(t,n);e&&l.push(e)}!n.raw&&i.filteredCount>0&&l.push(`Collapsed ${i.filteredCount} Android helper node${1===i.filteredCount?"":"s"} from the agent-facing text snapshot; use --raw or --json for the full hierarchy.`);let s=i.filteredCount>0?i.nodes:t;return!n.raw&&function(e){if(e.length<20)return!1;let t=new Map;for(let n of e){let e=(n.type??"").toLowerCase(),i=function(e){var t;let n=e.trim().replace(/\s+/g," ").toLowerCase();return!n||(t=n,/\S+@\S+\.\S+/.test(t))?null:n}(r(n));if(!i)continue;let o=`${e}|${i}`,l=t.get(o)??[];l.push(n),t.set(o,l)}let n=0;for(let e of t.values())!(e.length<=1)&&function(e){for(let r=0;r<e.length;r+=1)for(let i=r+1;i<e.length;i+=1){var t,n;if(t=e[r]?.rect,n=e[i]?.rect,!t||!n||!(t.x+t.width<=n.x+.5||n.x+n.width<=t.x+.5||t.y+t.height<=n.y+.5||n.y+n.height<=t.y+.5))return!0}return!1}(e)&&(n+=e.length);return n>=8}(s)&&l.push("Warning: possible repeated nav subtree detected."),l}(e,k,t,j),B=T.length>0?`${T.join("\n")}
|
|
9
|
-
`:"",D=t.raw?null:(I=e.unchanged)&&"object"==typeof I?"number"!=typeof I.ageMs||"number"!=typeof I.nodeCount?null:{ageMs:I.ageMs,nodeCount:I.nodeCount,interactiveOnly:!0===I.interactiveOnly||void 0,scope:"string"==typeof I.scope?I.scope:void 0}:null;if(D){let e;return`${H}${B}${e=function(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;return t<60?`${(Math.round(10*t)/10).toFixed(1)}m`:`${(Math.round(t/60*10)/10).toFixed(1)}h`}((o=D).ageMs),o.scope?`Scoped snapshot unchanged for scope "${o.scope}" since previous read ${e} ago.
|
|
10
|
-
Previous refs in this scope remain valid. Use find/get/is for a targeted query, or --force-full to re-emit.`:o.interactiveOnly?`Interactive snapshot unchanged since previous read ${e} ago.
|
|
11
|
-
${o.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.`:`Snapshot unchanged since previous read ${e} ago.
|
|
12
|
-
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.`}
|
|
13
|
-
`}let R=t.raw||!L?null:n(j.nodes),z=!!e.truncated,U=R?.nodes??k,E=t.raw||!L?null:function(e,t,n,r,i=0){let o,l=(o=e.visibility)&&"object"==typeof o&&"boolean"==typeof o.partial&&"number"==typeof o.visibleNodeCount&&"number"==typeof o.totalNodeCount&&Array.isArray(o.reasons)?{partial:o.partial,visibleNodeCount:o.visibleNodeCount,totalNodeCount:o.totalNodeCount,reasons:o.reasons.filter(e=>"string"==typeof e)}:null;if(0===i&&l)return l;let s=(t?.hiddenCount??0)+i,a=!!t&&t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow);return s>0?{partial:!0,visibleNodeCount:n,totalNodeCount:Math.max(r,l?.totalNodeCount??r),reasons:[...new Set([...l?.reasons??[],"offscreen-nodes"])]}:l||(a?{partial:!0,visibleNodeCount:n,totalNodeCount:n,reasons:[]}:null)}(e,R,U.length,k.length,j.filteredCount),F=(y=k.length,v=E,O=z?" (truncated)":"",v?.partial?v.totalNodeCount>v.visibleNodeCount?`Snapshot: ${v.visibleNodeCount} visible nodes (${v.totalNodeCount} total)${O}`:`Snapshot: ${v.visibleNodeCount} visible nodes${O}`:`Snapshot: ${y} nodes${O}`);return 0===k.length?`${H}${F}
|
|
14
|
-
${B}`:t.raw?`${H}${F}
|
|
15
|
-
${B}${k.map(e=>JSON.stringify(e)).join("\n")}
|
|
16
|
-
`:t.flatten?`${H}${F}
|
|
17
|
-
${B}${a(U,{summarizeTextSurfaces:!0}).flatMap(e=>[u(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...J({...e,depth:0})]).join("\n")}${P(R)}
|
|
18
|
-
`:`${H}${F}
|
|
19
|
-
${B}${(function(e){let t=[],n=[],r=new Map(e.map(e=>[e.node.index,e.node])),i=e=>{for(var i,o,l;n.length>0&&(!e||(i=e,o=n[n.length-1],l=r,!function(e,t,n){let r=e;for(;"number"==typeof r.parentIndex;){if(r.parentIndex===t.index)return!0;let e=n.get(r.parentIndex);if(!e)break;r=e}return!1}(i.node,o.node,l)&&i.depth<=o.depth));)t.push(...J(n.pop(),"below"))};for(let r of e)i(r),t.push(r.text),t.push(...J(r,"above")),r.node.hiddenContentBelow&&n.push(r);return i(),t})(a(U,{summarizeTextSurfaces:!0})).join("\n")}${P(R)}
|
|
20
|
-
`}function P(e){return e&&e.summaryLines.length>0?`
|
|
21
|
-
${e.summaryLines.join("\n")}`:""}function O(e){let t=!0===e.baselineInitialized,n=e.summary??{},r=B(n.additions),i=B(n.removals),o=B(n.unchanged),l=D(),s=K(e),a=s.length>0?`${s.join("\n")}
|
|
22
|
-
`:"";if(t)return`${a}Baseline initialized (${o} lines).
|
|
23
|
-
`;let u=(function(e){if(0===e.length)return e;let t=e.map((e,t)=>({index:t,kind:e.kind})).filter(e=>"added"===e.kind||"removed"===e.kind).map(e=>e.index);if(0===t.length)return e;let n=Array(e.length).fill(!1);for(let r of t){let t=Math.max(0,r-1),i=Math.min(e.length-1,r+1);for(let e=t;e<=i;e+=1)n[e]=!0}return e.filter((e,t)=>n[t])})(Array.isArray(e.lines)?e.lines:[]).map(e=>{let t="string"==typeof e.text?e.text:"";if("added"===e.kind){let e=t.startsWith(" ")?`+${t}`:`+ ${t}`;return l?R(e,"green"):e}if("removed"===e.kind){let e=t.startsWith(" ")?`-${t}`:`- ${t}`;return l?R(e,"red"):e}return l?R(t,"dim"):t}),d=u.length>0?`${u.join("\n")}
|
|
24
|
-
`:"";if(!l)return`${a}${d}${r} additions, ${i} removals, ${o} unchanged
|
|
25
|
-
`;let f=`${R(String(r),"green")} additions, ${R(String(i),"red")} removals, ${R(String(o),"dim")} unchanged`;return`${a}${d}${f}
|
|
26
|
-
`}function _(e){var t,n,r,i;let o,l,s,a,u=D(),d=!0===e.match,f=e.dimensionMismatch,c=[];return c.push(...function(e,t){if(!0===e.match){let e=t?R("✓","green"):"✓";return[`${e} Screenshots match.`]}let n=e.dimensionMismatch,r=t?R("✗","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=B(e.differentPixels),o=B(e.mismatchPercentage),l=0===o&&i>0?"<0.01":String(o),s=`${l}% pixels differ`;return[`${r} ${t?R(s,"red"):s}`]}(e,u)),c.push(...function(e,t,n){if(t)return[];let r=[];if(e.diffPath){let t=T(e.diffPath),i=n?R("Diff image:","dim"):"Diff image:",o=n?R(t,"green"):t;r.push(` ${i} ${o}`)}if(e.currentOverlayPath){let t=T(e.currentOverlayPath),i=n?R("Current overlay:","dim"):"Current overlay:",o=n?R(t,"green"):t,l=B(e.currentOverlayRefCount),s=l>0?` (${l} refs)`:"";r.push(` ${i} ${o}${s}`)}return r}(e,d,u)),d||f||(c.push(...(t=e,n=u,o=B(t.differentPixels),l=B(t.totalPixels),s=n?R(String(o),"red"):String(o),[` ${s} different / ${l} total pixels`])),c.push(...(r=e,i=u,0===(a=function(e){let t=[];for(let n of(e.ocr?.movementClusters??[]).slice(0,2))t.push(`text movement cluster: ${function(e){let t=e.slice(0,4).map(e=>JSON.stringify(e)),n=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${n}`}(n.texts)} dx=${H(n.xRange)}px dy=${H(n.yRange)}px`);let n=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);n.length>0&&t.push(`non-text controls: ${n.map(j).join("; ")}`);let r=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return r.length>0&&t.push(`non-text boundaries: ${r.map(j).join("; ")}`),t.slice(0,6)}(r)).length?[]:[` ${z("Hints:",i)}`,...a.map(e=>` - ${e}`)])),c.push(...function(e,t){let n=Array.isArray(e.regions)?e.regions:[];if(0===n.length)return[];let r=[` ${z("Changed regions:",t)}`];for(let e of n.slice(0,5))r.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),n=e.rect,r=[` ${e.index}. ${e.location} x=${n.x} y=${n.y} ${n.width}x${n.height}, ${t}% of diff, change=${e.dominantChange}`],i=function(e){let t=[e.size?`size=${e.size}`:null,e.shape?`shape=${e.shape}`:null,"number"==typeof e.densityPercentage?`density=${e.densityPercentage}%`:null,e.averageBaselineColorHex&&e.averageCurrentColorHex?`avgColor=${e.averageBaselineColorHex}->${e.averageCurrentColorHex}`:null,"number"==typeof e.baselineLuminance&&"number"==typeof e.currentLuminance?`luminance=${e.baselineLuminance}->${e.currentLuminance}`:null].filter(e=>null!==e);return t.length>0?t.join(" "):null}(e);i&&r.push(` ${i}`);let o=e.currentOverlayMatches?.[0];if(o){let e=o.label?` "${o.label}"`:"";r.push(` overlaps @${o.ref}${e}, ${o.regionCoveragePercentage}% of region`)}return r}(e));return r}(e,u)),c.push(...function(e,t){let n=e.ocr?.matches??[];if(0===n.length)return[];let r=n.slice(0,8),i=[` ${z(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${r.length}/${n.length}; px):`,t)}`,` ${z("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of r.entries()){let n=t.delta;i.push(` ${e+1} | ${JSON.stringify(t.text)} | ${L(n.x)},${L(n.y)} | ${L(n.width)},${L(n.height)} | ${k(t.baselineRect)} | ${k(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return i}(e,u)),c.push(...function(e,t){let n=e.nonTextDeltas??[];if(0===n.length)return[];let r=n.slice(0,8),i=[` ${z(`Non-text visual deltas (showing ${r.length}/${n.length}; px):`,t)}`,` ${z("item | region | slot | kind | bboxCurrent | nearestText",t)}`];for(let e of r)i.push(` ${e.index} | ${e.regionIndex?`r${e.regionIndex}`:"-"} | ${e.slot} | ${e.likelyKind} | ${k(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return i}(e,u))),`${c.join("\n")}
|
|
27
|
-
`}function k(e){return`x=${e.x},y=${e.y},w=${e.width},h=${e.height}`}function L(e){return e>0?`+${e}`:String(e)}function j(e){let t=e.nearestText?` near ${JSON.stringify(e.nearestText)}`:"",n=e.regionIndex?` r${e.regionIndex}`:"";return`${e.likelyKind}${t}${n}`}function H(e){return e.min===e.max?L(e.min):`${L(e.min)}..${L(e.max)}`}function T(t){let n=process.cwd(),r=e.relative(n,t);return""!==r&&(r.startsWith("..")||e.isAbsolute(r))?t:""===r?".":`.${e.sep}${r}`}function B(e){return"number"==typeof e&&Number.isFinite(e)?e:0}function D(e=process.stdout){let t=process.env.FORCE_COLOR;return"string"==typeof t?"0"!==t:"string"!=typeof process.env.NO_COLOR&&!!e.isTTY}function R(e,n,r){return t(n,e,r)}function z(e,t){return t?R(e,"dim"):e}function K(e){let t=e.warnings;return Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.length>0):[]}function J(e,t){var n;let r="scroll-area"===(n=e.type)||"list"===n||"collection"===n||"table"===n?n:null;if(!r)return[];let i=[];if(e.node.hiddenContentAbove&&"below"!==t&&i.push(`[content above ${r} hidden]`),e.node.hiddenContentBelow&&"above"!==t&&i.push(`[content below ${r} hidden]`),0===i.length)return[];let o=" ".repeat(e.depth+1);return i.map(e=>`${o}${e}`)}export{R as colorize,_ as formatScreenshotDiffText,O as formatSnapshotDiffText,A as formatSnapshotText,I as printHumanError,N as printJson,D as supportsColor};
|
package/dist/src/7244.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import e from"node:fs";import t from"node:path";import{fileURLToPath as r}from"node:url";import{buildTextPreview as i,trimText as l,describeTextSurface as o}from"./9836.js";import{isSystemScrollIndicatorLabel as n}from"./9873.js";function a(){try{let r=c();return JSON.parse(e.readFileSync(t.join(r,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}function c(){let i=t.dirname(r(import.meta.url)),l=i;for(let r=0;r<6;r+=1){let r=t.join(l,"package.json");if(e.existsSync(r))return l;l=t.dirname(l)}return i}let u={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",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 s(e,t={}){let r=[],i=[];for(let l of e){let e=l.depth??0,o=l.label?.trim()||l.value?.trim()||l.identifier?.trim()||"",n=f(l.type??"Element");if("group"===n&&!o)continue;for(;r.length>0&&e<=r[r.length-1];)r.pop();let a=r.length;r.push(e),i.push({node:l,depth:a,type:n,text:d(l,a,!1,n,t)})}return i}function d(e,t,r,n,a={}){var c,u,s,x,b,g,v,y;let $,S=n??f(e.type??"Element"),_=o(e,S),k=(c=e,u=S,s=a,x=_,s.summarizeTextSurfaces&&x.shouldSummarize&&function(e,t,r){let i=l(e.label);if(i&&i!==r)return i;let o=l(e.identifier);if(o&&!w(o)&&o!==r)return o;switch(t){case"text":case"text-view":return"Text view";case"text-field":return"Text field";case"search":return"Search field";default:return""}}(c,u,x.text)||p(c,u)),C=" ".repeat(t),j=e.ref?`@${e.ref}`:"",E=(b=e,g=S,v=a,y=_,$=[],!1===b.enabled&&$.push("disabled"),$.push(...b.presentationHints??[]),v.summarizeTextSurfaces&&(!0===b.selected&&$.push("selected"),!0===b.focused&&$.push("focused"),m(g)&&$.push("editable"),function(e,t){if("scroll-area"===t)return!0;let r=(e.type??"").toLowerCase(),i=`${e.role??""} ${e.subrole??""}`.toLowerCase();return r.includes("scroll")||i.includes("scroll")}(b,g)&&$.push("scrollable"),y.shouldSummarize&&($.push(`preview:"${i(y.text).replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`),$.push("truncated"))),h($)).map(e=>` [${e}]`).join(""),L=k?` "${k}"`:"";return r?`${C}${j} [${S}]${E}`.trimEnd():`${C}${j} [${S}]${L}${E}`.trimEnd()}function p(e,t){var r,i;let l=e.label?.trim();if(l&&(r=t,i=l,("scroll-area"===r||"list"===r||"collection"===r||"table"===r)&&n(i)))return"";let o=e.value?.trim();if(m(t)){if(o)return o;if(l)return l}else if(l)return l;if(o)return o;let a=e.identifier?.trim();return!a||w(a)&&("group"===t||"image"===t||"list"===t||"collection"===t)?"":a}function f(e){var t;let r=e.replace(/XCUIElementType/gi,"").toLowerCase(),i=e.includes(".")&&(e.startsWith("android.")||e.startsWith("androidx.")||e.startsWith("com."));return(r.includes(".")&&(r=r.replace(/^android\.widget\./,"").replace(/^android\.view\./,"").replace(/^android\.webkit\./,"").replace(/^androidx\./,"").replace(/^com\.google\.android\./,"").replace(/^com\.android\./,""),i&&r.includes(".")&&(r=r.slice(r.lastIndexOf(".")+1))),"textview"===r)?i?"text":"text-view":(t=r,(Object.prototype.hasOwnProperty.call(u,t)?u[t]:void 0)||r||"element")}function m(e){return"text-field"===e||"text-view"===e||"search"===e}function w(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function h(e){return[...new Set(e)]}export{s as buildSnapshotDisplayLines,p as displayLabel,c as findProjectRoot,f as formatRole,d as formatSnapshotLine,a as readVersion};
|