agent-device 0.20.6 → 0.20.8
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 +3 -3
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.apk → agent-device-android-ime-helper-0.20.8.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.manifest.json → agent-device-android-ime-helper-0.20.8.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.apk → agent-device-android-snapshot-helper-0.20.8.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.manifest.json → agent-device-android-snapshot-helper-0.20.8.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +20 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +67 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +339 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +78 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +31 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +34 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -28
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +7 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +100 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +57 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +18 -3
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-lifecycle.js +7 -7
- package/dist/src/app-lifecycle2.js +2 -0
- package/dist/src/app-log-files.js +1 -0
- package/dist/src/app-log-reconnect.js +1 -0
- package/dist/src/app-log-runtime.js +4 -0
- package/dist/src/app-resolution.js +2 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/auth-session.js +1 -0
- package/dist/src/auth.js +2 -0
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-grammar.js +1 -0
- package/dist/src/cli-help.js +199 -259
- package/dist/src/cli-output.js +1 -0
- package/dist/src/cli-runner.js +1 -2
- package/dist/src/cli.js +6 -16
- package/dist/src/client-metro.js +1 -1
- package/dist/src/cloud-artifacts.d.ts +2 -137
- package/dist/src/command-schema.js +3 -3
- package/dist/src/connection-runtime.js +1 -0
- package/dist/src/connection.js +5 -0
- package/dist/src/daemon-shutdown-report.js +1 -0
- package/dist/src/daemon.js +2 -0
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -0
- package/dist/src/device-input-state.js +2 -2
- package/dist/src/device-ready.js +1 -0
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +2 -0
- package/dist/src/dispatch.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/handler-utils.js +1 -0
- package/dist/src/harmonyos.js +1 -0
- package/dist/src/hdc.js +1 -0
- package/dist/src/host-process.js +3 -2
- package/dist/src/ime-lifecycle.js +7 -7
- package/dist/src/index.d.ts +52 -21
- package/dist/src/input-actions.js +4 -4
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/input-actions3.js +1 -0
- package/dist/src/install-artifact.js +1 -5
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction-touch-reference-frame.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +7 -36
- package/dist/src/inventory.js +5 -0
- package/dist/src/inventory2.js +1 -0
- package/dist/src/inventory3.js +2 -0
- package/dist/src/inventory4.js +1 -0
- package/dist/src/inventory5.js +1 -0
- package/dist/src/inventory6.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -0
- package/dist/src/limrun.d.ts +10 -125
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/notifications.js +1 -1
- package/dist/src/output-path.js +1 -0
- package/dist/src/owner-identity.js +1 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -0
- package/dist/src/platform-runtime-app-log-process.js +1 -0
- package/dist/src/platform-runtime-host.js +1 -0
- package/dist/src/platform-runtime-network-web-transport.js +1 -0
- package/dist/src/platform-runtime-operation-host.js +5 -0
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-output-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -0
- package/dist/src/platform-runtime-toolchain-host.js +1 -0
- package/dist/src/platform-runtime.js +1 -0
- package/dist/src/prepare-kind.js +15 -0
- package/dist/src/process-entry.js +1 -0
- package/dist/src/process-lock.js +1 -1
- package/dist/src/provider-webdriver.js +1 -0
- package/dist/src/proxy.js +2 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -0
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-telemetry.js +1 -0
- package/dist/src/registry.js +24 -24
- package/dist/src/replay.js +3 -0
- package/dist/src/reporting.js +3 -3
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -0
- package/dist/src/runtime3.js +3 -0
- package/dist/src/runtime4.js +1 -0
- package/dist/src/runtime5.js +1 -0
- package/dist/src/runtime6.js +1 -0
- package/dist/src/runtime7.js +1 -0
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -0
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +31 -5
- package/dist/src/sdk-contracts.js +1 -1
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +285 -5
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +10 -9
- package/dist/src/shared.js +2 -0
- package/dist/src/shell-quote.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -0
- package/dist/src/snapshot-session.js +1 -0
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +2 -0
- package/dist/src/src3.js +1 -0
- package/dist/src/text-surface.js +1 -1
- package/dist/src/timing-safe-equal.js +1 -0
- package/dist/src/tool-provider.js +2 -2
- package/dist/src/update-check.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +23 -0
- package/dist/src/web.js +1 -1
- package/package.json +34 -20
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.6.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.6.apk.sha256 +0 -1
- package/dist/src/app-log-request-scope.js +0 -1
- package/dist/src/context.js +0 -1
- package/dist/src/devices.js +0 -1
- package/dist/src/devices2.js +0 -1
- package/dist/src/devices3.js +0 -1
- package/dist/src/devices4.js +0 -1
- package/dist/src/provider-limrun-runtime.js +0 -1
- package/dist/src/register-builtins.js +0 -1
- package/dist/src/runner-client.js +0 -1
- package/dist/src/runner-provider.js +0 -1
- package/dist/src/screenshot-geometry.js +0 -1
- package/dist/src/viewport-dimension.js +0 -15
- package/skills/agent-device/SKILL.md +0 -45
- package/skills/dogfood/SKILL.md +0 -27
package/dist/src/runtime.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as e,i as t,n,o as r,r as i,t as a}from"./png-worker-contract.js";import{T as o,_ as s,d as c,g as l,l as u,p as d,u as f,v as p}from"./sdk-contracts.js";import{
|
|
2
|
-
`)}function
|
|
3
|
-
`).toLowerCase(),n=E(e,Nt),r=E(e,Lt),i=E(e,jt,zt),a=E(e,Mt),o=Dt(t),s=Ot(t);return{dismissNodes:n,minimizeNodes:r,collapsedNodes:i,detected:At({text:t,hasReactNativeStackFrame:o,hasOverlayControl:kt(t,n,r),hasControllessRedBoxText:s,collapsedNodes:i,openDebuggerWarningNodes:a})}}function wt(e){let t=Ut(e.dismissNodes);if(t)return Kt(t,qt(t));let n=Jt(e.collapsedNodes.filter(Bt));return n?.rect?{action:`close-collapsed-banner`,point:$t(n),rect:n.rect,ref:n.ref,label:D(n)}:null}function Tt(e){return[e.label,e.value,e.identifier,e.type,e.role].filter(Boolean).join(` `)}function Et(e){return mt.test(e)}function Dt(e){return ht.some(t=>t.test(e))}function Ot(e){return/\buncaught\b/.test(e)&&/unable to download asset/.test(e)}function kt(e,t,n){return t.length>0||n.length>0||/\b(reload js|copy stack)\b/.test(e)}function At(e){return e.collapsedNodes.length>0||e.openDebuggerWarningNodes.length>0||e.hasControllessRedBoxText||e.hasOverlayControl&&(Et(e.text)||e.hasReactNativeStackFrame)}function jt(e){let t=e?.trim().toLowerCase();return t?_t.some(e=>t.includes(e))||gt.some(e=>e.test(t)):!1}function Mt(e){return e.includes(`open debugger to view warnings`)||/^!,\s+open debugger\b/.test(e)}function Nt(e){return Pt(e)||Ft(e)||It(e)}function Pt(e){return/^dismiss(?:\s*\([^)]*\))?$/i.test(e)}function Ft(e){return/^close(?:\s*\([^)]*\))?$/i.test(e)}function It(e){return vt.has(e)}function Lt(e){return/^minimi[sz]e(?:\b|\s|\()/i.test(e)}function Rt(e){return/^!,\s+/.test(e)}function zt(e){return!e.rect||e.rect.height<=180}function Bt(e){let t=D(e)?.trim().toLowerCase()??``;return(Mt(t)||Rt(t))&&Ht(e)}function Vt(e){return e?e.x<=1&&e.y<=1&&e.width>=300&&e.height>=600:!1}function Ht(e){return e.rect?e.rect.width>=120&&e.rect.height>=36&&e.rect.height<=180:!1}function E(e,t,n=()=>!0){let r=[];for(let i of e)i.ref&&n(i)&&[i.label,i.value,i.identifier].map(e=>e?.trim().toLowerCase()).filter(e=>!!e).some(e=>t(e))&&r.push(i);return r}function Ut(e){return Yt(e,Gt)}function Wt(e){let t=[e.type,e.role,e.subrole].join(` `).toLowerCase();return/\b(button|menuitem|link)\b/.test(t)}function Gt(e){return[Zt(Wt(e)),Zt(e.hittable),-(e.rect?he(e.rect):1/0)]}function Kt(e,t){if(!e.rect)throw Error(`React Native overlay target node must have rect`);return{action:t,point:f(e.rect),rect:e.rect,ref:e.ref,label:D(e)}}function qt(e){let t=D(e)?.trim().toLowerCase();return t&&Pt(t)?`dismiss`:`close`}function Jt(e){return Yt(e,Xt)}function Yt(e,t){let n=e.filter(e=>e.rect);return n.length===0?null:n.sort((e,n)=>Qt(t(n),t(e)))[0]??null}function Xt(e){return[Zt(e.hittable),e.rect?.width??0,e.rect?.y??0]}function Zt(e){return+(e===!0)}function Qt(e,t){for(let n=0;n<e.length;n+=1){let r=e[n]-t[n];if(r!==0)return r}return 0}function $t(e){if(!e.rect)throw Error(`Collapsed React Native warning node must have rect`);let t=Math.min(e.rect.height,52),n=Math.min(36,Math.max(18,t*.45));return{x:Math.round(en(e.rect.x+e.rect.width-n,e.rect.x+1,e.rect.x+e.rect.width-1)),y:Math.round(e.rect.y+t/2)}}function en(e,t,n){return Math.min(n,Math.max(t,e))}function D(e){return e.label??e.value??e.identifier}function tn(e){let t=e?.trim().split(/\s+/,1)[0];if(!t||!t.startsWith(`@`)||t.length<3)return null;let n=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(n)||/^(?:ref|node|element|el)[\w-]*$/i.test(n)?t:null}function nn(e,t){try{let n=ft(e),r=w.extname(n)||`.js`;return[w.join(w.dirname(n),`${t}${r}`),w.join(w.dirname(n),`internal`,`${t}${r}`)].find(e=>dt.existsSync(e))??null}catch{return null}}var O=class extends Error{};let k=null,rn=!1,an=!1,on=0;const A=new Map;function sn(e){rn=!0,!an&&(an=!0,ut({level:`warn`,phase:`png_worker_unavailable`,data:{reason:e}}),process.emitWarning(`PNG worker unavailable, falling back to in-process PNG processing: ${e}`))}function cn(e){let t=A.get(e.id);t&&(A.delete(e.id),dn(),e.ok?t.resolve(e.result):t.reject(new s(o(e.error.code),e.error.message,e.error.details)))}function ln(e,t){k===e&&(sn(t.message),k=null,e.terminate().catch(()=>{}),un(new O(`PNG worker failed: ${t.message}`)))}function un(e){let t=[...A.values()];A.clear();for(let n of t)n.reject(e)}function dn(){k&&(A.size>0?k.ref():k.unref())}function fn(){if(rn)return null;if(k)return k;let e=nn(import.meta.url,`png-worker`);if(!e)return sn(`worker entry module not found next to the current module`),null;try{let t=new pt(e,{execArgv:e.endsWith(`.ts`)?[`--experimental-strip-types`]:[]});return t.on(`message`,cn),t.on(`error`,e=>{ln(t,e)}),t.on(`exit`,e=>{ln(t,Error(`PNG worker exited with code ${e}`))}),t.unref(),k=t,t}catch(e){return sn(`failed to spawn worker: ${e instanceof Error?e.message:String(e)}`),null}}function pn(e){let t=fn();if(!t)return Promise.reject(new O(`PNG worker is unavailable`));on+=1;let n=on;return new Promise((r,i)=>{A.set(n,{resolve:r,reject:i}),dn();try{t.postMessage({...e,id:n})}catch(e){A.delete(n),dn(),i(new O(`failed to post job to PNG worker: ${e instanceof Error?e.message:String(e)}`))}})}async function j(e,t){try{return await pn(e)}catch(e){if(e instanceof O)return t();throw e}}function mn(){fn()}async function hn(){let e=k;k=null,un(new O(`PNG worker terminated`)),e&&await e.terminate()}async function M(n,r){let i=await j({kind:`decode`,png:n,label:r},()=>{let e=t(n,r);return{kind:`decode`,width:e.width,height:e.height,data:e.data}}),o=new e.PNG({width:i.width,height:i.height});return o.data=a(i.data),o}async function N(t){return a((await j({kind:`encode`,width:t.width,height:t.height,data:t.data},()=>({kind:`encode`,png:e.PNG.sync.write(t)}))).png)}async function gn(e,r,i){let{kind:a,...o}=await j({kind:`rgb-difference`,firstPng:e,secondPng:r,label:i},()=>({kind:`rgb-difference`,...n(t(e,i),t(r,i))}));return o}async function _n(e){let{kind:t,...n}=await j({kind:`diff-pixels`,...e},()=>({kind:`diff-pixels`,...i(e)}));return{...n,diffData:a(n.diffData)}}const P=[0,187,255,255];function vn(e,t){for(let n of t)n.rect.width<4||n.rect.height<4||yn(e,n.rect)}function yn(e,t){let n=bn(t);if(n==null)return;let r=I(n.x,0,e.width-1),i=I(n.y,0,e.height-1),a=I(n.right,0,e.width-1),o=I(n.bottom,0,e.height-1);for(let t=0;t<2;t+=1){for(let n=r;n<=a;n+=1)F(e,n,i+t,P),F(e,n,o-t,P);for(let n=i;n<=o;n+=1)F(e,r+t,n,P),F(e,a-t,n,P)}}function bn(e){let t=e.x+e.width-1,n=e.y+e.height-1;return[e.x,e.y,e.width,e.height,t,n].every(Number.isFinite)?{x:e.x,y:e.y,right:t,bottom:n}:null}function F(e,t,n,r){if(t<0||t>=e.width||n<0||n>=e.height)return;let i=(n*e.width+t)*4;e.data[i]=r[0],e.data[i+1]=r[1],e.data[i+2]=r[2],e.data[i+3]=r[3]}function I(e,t,n){return Number.isFinite(e)?Math.min(Math.max(e,t),n):t}const xn=[{x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:-1,y:0},{x:1,y:0},{x:-1,y:1},{x:0,y:1},{x:1,y:1}];function Sn(e){let{mask:t,width:n,height:r,hooks:i}=e,a=new Uint8Array(t.length),o=new Int32Array(t.length),s=[];for(let e=0;e<t.length;e+=1){if(!Tn(t,a,e))continue;let c=0,l=wn(o,a,0,e),u=i.create(e);for(;c<l;){let e=o[c];c+=1,i.visit(u,e),l=Cn({mask:t,visited:a,queue:o,queueEnd:l,width:n,height:r,pixelIndex:e})}s.push(u)}return s}function Cn(e){let{mask:t,visited:n,queue:r,width:i,height:a,pixelIndex:o}=e,s=o%i,c=Math.floor(o/i),l=e.queueEnd;for(let e of xn){let o=s+e.x,u=c+e.y;if(!En(o,u,i,a))continue;let d=u*i+o;Tn(t,n,d)&&(l=wn(r,n,l,d))}return l}function wn(e,t,n,r){return t[r]=1,e[n]=r,n+1}function Tn(e,t,n){return e[n]===1&&t[n]!==1}function En(e,t,n,r){return e>=0&&e<n&&t>=0&&t<r}function Dn(e,t){return e.flatMap(e=>On(e,t.baseline.width,t.baseline.height)?kn(e,t,Fn(t.baseline.height)):[e])}function On(e,t,n){let r=e.maxX-e.minX+1;return e.maxY-e.minY+1>=Pn(n)&&r>=t*.35}function kn(e,t,n){let r=Nn(e,Mn(jn(An(e,t.diffMask,t.baseline.width)),Math.max(1,Math.round((e.maxX-e.minX+1)*.08))),n);if(r.length<=1)return[e];let i=r.map(([n,r])=>In(e,n,r,t)).filter(e=>e!==null);return i.length>1?i:[e]}function An(e,t,n){let r=[];for(let i=e.minY;i<=e.maxY;i+=1){let a=0;for(let r=e.minX;r<=e.maxX;r+=1)t[i*n+r]===1&&(a+=1);r.push(a)}return r}function jn(e){return e.map((t,n)=>{let r=0,i=0,a=Math.max(0,n-3),o=Math.min(e.length-1,n+3);for(let t=a;t<=o;t+=1)r+=e[t],i+=1;return Math.round(r/i)})}function Mn(e,t){let n=[],r=null;for(let i=0;i<e.length;i+=1){if(e[i]<=t){r??=i;continue}r!==null&&(i-r>=6&&n.push([r,i-1]),r=null)}return r!==null&&e.length-r>=6&&n.push([r,e.length-1]),n}function Nn(e,t,n){let r=[],i=e.minY;for(let[a,o]of t){let t=e.minY+Math.round((a+o)/2);t-i+1<n||e.maxY-t<n||(r.push([i,t]),i=t+1)}return r.push([i,e.maxY]),r}function Pn(e){return Math.max(48,Math.round(e*.07))}function Fn(e){return Math.max(24,Math.round(e*.03))}function In(e,t,n,r){let i=null;for(let a=t;a<=n;a+=1)for(let t=e.minX;t<=e.maxX;t+=1){let e=a*r.baseline.width+t;r.diffMask[e]===1&&(i??=Ln(t,a),Rn(i,e,t,a,r.baseline,r.current))}return i}function Ln(e,t){return{minX:e,minY:t,maxX:e,maxY:t,differentPixels:0,baselineRed:0,baselineGreen:0,baselineBlue:0,currentRed:0,currentGreen:0,currentBlue:0}}function Rn(e,t,n,r,i,a){let o=t*4;e.minX=Math.min(e.minX,n),e.minY=Math.min(e.minY,r),e.maxX=Math.max(e.maxX,n),e.maxY=Math.max(e.maxY,r),e.differentPixels+=1,e.baselineRed+=i.data[o],e.baselineGreen+=i.data[o+1],e.baselineBlue+=i.data[o+2],e.currentRed+=a.data[o],e.currentGreen+=a.data[o+1],e.currentBlue+=a.data[o+2]}const zn=2.5;function Bn(e){let t=Vn(e);return Dn(t.length<=2e3?Wn(t,12):t,e).sort((e,t)=>{let n=t.differentPixels-e.differentPixels;if(n!==0)return n;let r=e.minY-t.minY;return r===0?e.minX-t.minX:r}).slice(0,8).map((t,n)=>qn(t,n+1,{width:e.baseline.width,height:e.baseline.height,totalPixels:e.totalPixels,differentPixels:e.differentPixels}))}function Vn(e){let{diffMask:t,baseline:n,current:r}=e,{width:i,height:a}=n;return Sn({mask:t,width:i,height:a,hooks:{create:e=>Hn(e,i),visit:(e,t)=>Un(e,t,i,n,r)}})}function Hn(e,t){let n=e%t,r=Math.floor(e/t);return{minX:n,minY:r,maxX:n,maxY:r,differentPixels:0,baselineRed:0,baselineGreen:0,baselineBlue:0,currentRed:0,currentGreen:0,currentBlue:0}}function Un(e,t,n,r,i){let a=t%n,o=Math.floor(t/n),s=t*4;e.minX=Math.min(e.minX,a),e.minY=Math.min(e.minY,o),e.maxX=Math.max(e.maxX,a),e.maxY=Math.max(e.maxY,o),e.differentPixels+=1,e.baselineRed+=r.data[s],e.baselineGreen+=r.data[s+1],e.baselineBlue+=r.data[s+2],e.currentRed+=i.data[s],e.currentGreen+=i.data[s+1],e.currentBlue+=i.data[s+2]}function Wn(e,t){let n=[];for(let r of e.sort((e,t)=>{let n=e.minY-t.minY;return n===0?e.minX-t.minX:n})){let e=n.find(e=>Gn(e,r,t));if(!e){n.push({...r});continue}Kn(e,r)}return n}function Gn(e,t,n){return e.minX-n<=t.maxX&&t.minX-n<=e.maxX&&e.minY-n<=t.maxY&&t.minY-n<=e.maxY}function Kn(e,t){e.minX=Math.min(e.minX,t.minX),e.minY=Math.min(e.minY,t.minY),e.maxX=Math.max(e.maxX,t.maxX),e.maxY=Math.max(e.maxY,t.maxY),e.differentPixels+=t.differentPixels,e.baselineRed+=t.baselineRed,e.baselineGreen+=t.baselineGreen,e.baselineBlue+=t.baselineBlue,e.currentRed+=t.currentRed,e.currentGreen+=t.currentGreen,e.currentBlue+=t.currentBlue}function qn(e,t,n){let r={x:e.minX,y:e.minY,width:e.maxX-e.minX+1,height:e.maxY-e.minY+1},i={x:Math.round(e.minX+r.width/2),y:Math.round(e.minY+r.height/2)},a=Jn(e.baselineRed,e.baselineGreen,e.baselineBlue,e.differentPixels),o=Jn(e.currentRed,e.currentGreen,e.currentBlue,e.differentPixels),s=r.width*r.height;return{index:t,rect:r,normalizedRect:ne({x:R(r.x/n.width),y:R(r.y/n.height),width:R(r.width/n.width),height:R(r.height/n.height)}),differentPixels:e.differentPixels,shareOfDiffPercentage:R(e.differentPixels/n.differentPixels),densityPercentage:R(e.differentPixels/s),shape:Zn(r,n.width,n.height),size:Qn(s,n.totalPixels),location:Yn(i,n.width,n.height),averageBaselineColorHex:$n(a),averageCurrentColorHex:$n(o),baselineLuminance:Math.round(L(a)),currentLuminance:Math.round(L(o)),dominantChange:Xn(a,o)}}function Jn(e,t,n,r){return{r:Math.round(e/r),g:Math.round(t/r),b:Math.round(n/r)}}function Yn(e,t,n){let r=e.x<t/3?`left`:e.x>t*2/3?`right`:`center`,i=e.y<n/3?`top`:e.y>n*2/3?`bottom`:`middle`;return r===`center`&&i===`middle`?`center`:`${i}-${r}`}function Xn(e,t){let n=L(t)-L(e);return Math.abs(n)>=12?n>0?`brighter`:`darker`:Math.max(Math.abs(t.r-e.r),Math.abs(t.g-e.g),Math.abs(t.b-e.b))>=12?`color-shift`:`mixed`}function Zn(e,t,n){return e.width>=t*.55&&e.height>=n*.12?`large-area`:e.width>=e.height*zn?`horizontal-band`:e.height>=e.width*zn?`vertical-band`:`compact`}function Qn(e,t){let n=e/t;return n>=.04?`large`:n>=.01?`medium`:`small`}function L(e){return e.r*.2126+e.g*.7152+e.b*.0722}function $n(e){return`#${er(e.r)}${er(e.g)}${er(e.b)}`}function er(e){return e.toString(16).padStart(2,`0`)}function R(e){return Math.round(e*100*100)/100}const tr=255*Math.sqrt(3);async function nr(t,n,r={}){await rr(t,`Baseline image not found`),await rr(n,`Current screenshot not found`);let i=r.outputPath,[a,o]=await Promise.all([T.readFile(t),T.readFile(n)]),[s,c]=await Promise.all([M(a,`baseline screenshot`),M(o,`current screenshot`)]);ir(s.width,s.height,`baseline screenshot`,r.maxPixels),ir(c.width,c.height,`current screenshot`,r.maxPixels);let l=r.threshold??.1;if(s.width!==c.width||s.height!==c.height){let e=s.width*s.height;return await ar(r.outputPath),{match:!1,mismatchPercentage:100,totalPixels:e,differentPixels:e,dimensionMismatch:{expected:{width:s.width,height:s.height},actual:{width:c.width,height:c.height}}}}let u=s.width*s.height,d=l*tr,{diffData:f,diffMask:p,differentPixels:m}=await _n({baselineData:s.data,currentData:c.data,width:s.width,height:s.height,maxColorDistance:d}),h=m>0?Bn({diffMask:p,baseline:s,current:c,totalPixels:u,differentPixels:m}):[];if(m>0&&i){let t=new e.PNG({width:s.width,height:s.height});t.data=f,vn(t,h),await T.mkdir(w.dirname(i),{recursive:!0}),await T.writeFile(i,await N(t))}else await ar(r.outputPath);let ee=u>0?Math.round(m/u*100*100)/100:0;return{...m>0&&i?{diffPath:i}:{},...h.length>0?{regions:h}:{},totalPixels:u,differentPixels:m,mismatchPercentage:ee,match:m===0}}async function rr(e,t){try{await T.access(e)}catch{throw new s(`INVALID_ARGS`,`${t}: ${e}`)}}function ir(e,t,n,r){if(r==null||r<=0)return;let i=e*t;if(!(i<=r))throw new s(`INVALID_ARGS`,`${n} is ${i} pixels, which exceeds the configured maxImagePixels limit of ${r}`)}async function ar(e){if(e)try{await T.unlink(e)}catch(e){if(!or(e,`ENOENT`))throw e}}function or(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}function sr(e,t){return e.map(e=>{let n=cr(e,t);return n.length>0?{...e,currentOverlayMatches:n}:e})}function cr(e,t){let n=lr(e.rect);return t.map(t=>{let r=t.overlayRect,i=ie(e.rect,r);return i<=0?null:{ref:t.ref,...t.label?{label:t.label}:{},rect:r,overlayCoveragePercentage:ur(i/lr(r)),regionCoveragePercentage:ur(i/n)}}).filter(e=>e!==null).sort((e,t)=>{let n=t.regionCoveragePercentage-e.regionCoveragePercentage;return n===0?t.overlayCoveragePercentage-e.overlayCoveragePercentage:n}).slice(0,3).map(e=>({ref:e.ref,...e.label?{label:e.label}:{},rect:e.rect,regionCoveragePercentage:e.regionCoveragePercentage}))}function lr(e){return e.width*e.height}function ur(e){return Math.round(e*100*100)/100}async function z(e,t,n){if(t.kind===`path`&&!e.policy.allowLocalInputPaths)throw new s(`INVALID_ARGS`,`Local ${n.field??`input`} paths are not allowed by command policy`);try{return await e.artifacts.resolveInput(t,n)}catch(e){throw p(e)}}async function B(e,t,n){if(t?.kind===`path`&&!e.policy.allowLocalOutputPaths)throw new s(`INVALID_ARGS`,`Local output paths are not allowed by command policy`);try{return await e.artifacts.reserveOutput(t,{...n,visibility:n.visibility??`client-visible`,requestedClientPath:t?.kind===`downloadableArtifact`?t.clientPath??n.requestedClientPath:n.requestedClientPath})}catch(e){throw p(e)}}async function dr(e,t){try{return await e.artifacts.createTempFile(t)}catch(e){throw p(e)}}const fr=async(e,t)=>{if(!t.baseline)throw new s(`INVALID_ARGS`,`diff screenshot requires a baseline image`);let n=pr(t.threshold),r=t.current??{kind:`live`};if(t.overlayRefs&&!br(r))throw new s(`INVALID_ARGS`,`diff screenshot <current.png> cannot use --overlay-refs because saved-image comparisons have no live accessibility refs`);let i=await z(e,t.baseline,{usage:`diff screenshot baseline`,field:`baseline`}),a,o,c,l=[];try{let s;br(r)?(o=await mr(e,t),s=o.path):(a=await z(e,r,{usage:`diff screenshot current`,field:`current`}),s=a.path),c=t.out?await B(e,t.out,{field:`diffPath`,ext:`.png`,artifactType:`screenshot-diff`}):void 0;let u=await nr(i.path,s,{threshold:n,outputPath:c?.path,maxPixels:e.policy.maxImagePixels});br(r)&&(u=await hr(e,t,c?.path,u,l));let d=u.diffPath?await c?.publish():void 0;return d&&l.push(d),u.diffPath||await c?.cleanup?.(),{...u,...l.length>0?{artifacts:l}:{}}}catch(e){throw await c?.cleanup?.(),e}finally{await i.cleanup?.(),await a?.cleanup?.(),await o?.cleanup?.()}};function pr(e){if(e==null||e===``)return .1;let t=Number(e);if(Number.isNaN(t)||t<0||t>1)throw new s(`INVALID_ARGS`,`--threshold must be a number between 0 and 1`);return t}async function mr(e,t){let n=await dr(e,{prefix:`agent-device-diff-current`,ext:`.png`});try{await gr(e,t,n.path,_r(t))}catch(e){throw await n.cleanup(),e}return n}async function hr(e,t,n,r,i){if(!t.overlayRefs)return r;if(r.match||r.dimensionMismatch)return n&&await yr(n),r;let a=await B(e,vr(t,n),{field:`currentOverlayPath`,ext:`.png`,artifactType:`screenshot`});try{let n=await gr(e,t,a.path,{overlayRefs:!0,..._r(t)}),o=await a.publish();return o&&i.push(o),{...r,currentOverlayPath:n.path??a.path,...n.overlayRefs?{currentOverlayRefCount:n.overlayRefs.length}:{},...r.regions&&n.overlayRefs?{regions:sr(r.regions,n.overlayRefs)}:{}}}catch(e){throw await a.cleanup?.(),e}}async function gr(e,t,n,r={}){if(!e.backend.captureScreenshot)throw new s(`UNSUPPORTED_OPERATION`,`screenshot is not supported by this backend`);return await e.backend.captureScreenshot({session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata},n,r)??{}}function _r(e){return{normalizeStatusBar:e.normalizeStatusBar??!0,...e.surface?{surface:e.surface}:{}}}function vr(e,t){if(e.currentOverlayOut)return e.currentOverlayOut;if(e.out?.kind===`path`)return{kind:`path`,path:V(t??e.out.path)};if(e.out?.kind===`downloadableArtifact`)return{kind:`downloadableArtifact`,...e.out.clientPath?{clientPath:V(e.out.clientPath)}:{},...e.out.fileName?{fileName:V(e.out.fileName)}:{}}}function V(e){let t=w.extname(e);return`${t?e.slice(0,-t.length):e}.current-overlay${t||`.png`}`}async function yr(e){try{await T.unlink(V(e))}catch(e){if(!xr(e,`ENOENT`))throw e}}function br(e){return e.kind===`live`}function xr(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}async function Sr(e,t){let{min:n,max:r}=te;if(!Number.isFinite(t)||t<n||t>r)throw new s(`INVALID_ARGS`,`Screenshot scale must be between ${n} and ${r}`);if(t===1)return;let i=await M(await T.readFile(e),`screenshot`),a=Math.max(1,Math.round(i.width*t)),o=Math.max(1,Math.round(i.height*t));await T.writeFile(e,await N(wr(i,a,o)))}async function Cr(e,t,n){if(!Number.isInteger(t)||t<1||!Number.isInteger(n)||n<1)throw new s(`INVALID_ARGS`,`Screenshot resize dimensions must be positive integers`);let r=await M(await T.readFile(e),`screenshot`);r.width===t&&r.height===n||await T.writeFile(e,await N(wr(r,t,n)))}function wr(t,n,r){let i=new e.PNG({width:n,height:r});for(let e=0;e<r;e+=1){let a=e*t.height/r,o=(e+1)*t.height/r;for(let r=0;r<n;r+=1){let s=r*t.width/n,c=(r+1)*t.width/n,l=0,u=0,d=0,f=0,p=0;for(let e=Math.floor(a);e<Math.ceil(o);e+=1){let n=Math.min(e+1,o)-Math.max(e,a);for(let r=Math.floor(s);r<Math.ceil(c);r+=1){let i=n*(Math.min(r+1,c)-Math.max(r,s)),a=(e*t.width+r)*4;l+=(t.data[a]??0)*i,u+=(t.data[a+1]??0)*i,d+=(t.data[a+2]??0)*i,f+=(t.data[a+3]??0)*i,p+=i}}let m=(e*i.width+r)*4;i.data[m]=Math.round(l/p),i.data[m+1]=Math.round(u/p),i.data[m+2]=Math.round(d/p),i.data[m+3]=Math.round(f/p)}}return i}const Tr=async(e,t)=>{if(!e.backend.captureScreenshot)throw new s(`UNSUPPORTED_OPERATION`,`screenshot is not supported by this backend`);h(t);let n=await B(e,t.out,{field:`path`,ext:`.png`,artifactType:`screenshot`}),r;try{await e.backend.captureScreenshot({session:t.session,requestId:t.requestId,appId:t.appId,appBundleId:t.appBundleId,signal:t.signal??e.signal,metadata:t.metadata},n.path,{fullscreen:t.fullscreen,overlayRefs:t.overlayRefs,pixelDensity:t.pixelDensity,stabilize:t.stabilize,normalizeStatusBar:t.normalizeStatusBar,surface:t.surface}),t.scale!==void 0&&await Sr(n.path,t.scale),r=await n.publish()}catch(e){throw await n.cleanup?.(),e}return{path:n.path,...r?{artifacts:[r]}:{},...y(`Saved screenshot: ${n.path}`)}};function Er(e){let{nodes:t,backend:n,snapshotRaw:r}=e;if(r||!l(n))return{partial:!1,visibleNodeCount:t.length,totalNodeCount:t.length,reasons:[]};let i=re(t),a=new Set;return i.hiddenCount>0&&a.add(`offscreen-nodes`),i.nodes.some(e=>e.hiddenContentAbove)&&a.add(`scroll-hidden-above`),i.nodes.some(e=>e.hiddenContentBelow)&&a.add(`scroll-hidden-below`),{partial:a.size>0,visibleNodeCount:i.nodes.length,totalNodeCount:t.length,reasons:[...a]}}const Dr=`A system surface (notification shade, quick settings, or another system overlay) covers the app, so this snapshot shows that surface. Interact with it or dismiss it (press back or swipe up) to reach app content.`;function Or(e){return e?.systemSurfaceOnly===!0?Dr:void 0}function kr(e,t){return e.presentationKey?e:{...e,presentationKey:u(t)}}function Ar(e){let{previous:t,current:n,options:r,identity:i}=e;if(r.forceFull===!0||r.raw===!0||!t||t.comparisonSafe===!1||n.comparisonSafe===!1||!jr(t,n,i)||!t.presentationKey||t.presentationKey!==n.presentationKey||!Mr(t,n))return;let a=r.scope?.trim();return{ageMs:Math.max(0,n.createdAt-t.createdAt),nodeCount:n.nodes.length,...r.interactiveOnly===!0?{interactiveOnly:!0}:{},...a?{scope:a}:{}}}function jr(e,t,n){return!(e.backend&&t.backend&&e.backend!==t.backend||n?.previousAppBundleId&&n.currentAppBundleId&&n.previousAppBundleId!==n.currentAppBundleId)}function Mr(e,t){return e.truncated===t.truncated?JSON.stringify(Nr(e.nodes))===JSON.stringify(Nr(t.nodes)):!1}function Nr(e){return e.map(e=>({index:e.index,depth:e.depth,parentIndex:e.parentIndex,type:e.type,role:e.role,subrole:e.subrole,label:e.label,value:e.value,identifier:e.identifier,enabled:e.enabled,selected:e.selected,focused:e.focused,hittable:e.hittable,rect:e.rect,bundleId:e.bundleId,appName:e.appName,windowTitle:e.windowTitle,surface:e.surface,hiddenContentAbove:e.hiddenContentAbove,hiddenContentBelow:e.hiddenContentBelow,interactionBlocked:e.interactionBlocked,presentationHints:e.presentationHints}))}const Pr=async(e,t)=>{let n=await Ir(e,t),r=Ar({previous:n.session?.snapshot,current:n.snapshot,options:t,identity:{previousAppBundleId:n.session?.appBundleId,currentAppBundleId:n.result.appBundleId??n.session?.appBundleId}});return await e.sessions.set(Rr(t.session,n)),{nodes:n.snapshot.nodes,truncated:n.snapshot.truncated??!1,visibility:Er({nodes:n.snapshot.nodes,backend:n.snapshot.backend,snapshotRaw:t.raw}),...oe({...n.annotations,warnings:n.warnings}),...r?{unchanged:r}:{},...n.result.snapshotDiagnostics?{snapshotDiagnostics:n.result.snapshotDiagnostics}:{},...zr(n)}},Fr=async(e,t)=>{let n=await Ir(e,t),r=t.interactiveOnly===!0,i=n.session?.snapshot,a=Rr(t.session,n);if(!i){let t=ze(n.snapshot.nodes,{flatten:r});return await e.sessions.set(a),{mode:`snapshot`,baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:t},lines:[],...n.warnings.length>0?{warnings:n.warnings}:{}}}let o=ot(i.nodes,n.snapshot.nodes,{flatten:r});return await e.sessions.set(a),{mode:`snapshot`,baselineInitialized:!1,summary:o.summary,lines:o.lines,...n.warnings.length>0?{warnings:n.warnings}:{}}};async function Ir(e,t){if(!e.backend.captureSnapshot)throw new s(`UNSUPPORTED_OPERATION`,`snapshot is not supported by this backend`);let n=t.session??`default`,r=await e.sessions.get(n),i=await e.backend.captureSnapshot({session:n,requestId:t.requestId,appId:r?.appId,appBundleId:r?.appBundleId,signal:t.signal??e.signal,metadata:t.metadata},{interactiveOnly:t.interactiveOnly,depth:t.depth,scope:t.scope,raw:t.raw}),a=kr(Lr(i,e),t),o=ae(i),c=Ge(e);return{snapshot:a,result:i,session:r,annotations:o,warnings:Br({result:i,annotations:o,snapshot:a,options:t,session:r,capturedAt:a.createdAt??c,runtimeNow:c})}}function Lr(e,t){return e.snapshot?e.snapshot:{nodes:e.nodes??[],truncated:e.truncated,backend:e.backend,createdAt:Ge(t)}}function Rr(e,t){let n=t.session?.name??e??`default`;return{...t.session??{name:n},name:n,snapshot:t.snapshot,appName:t.result.appName??t.session?.appName,appBundleId:t.result.appBundleId??t.session?.appBundleId}}function zr(e){let t=e.result.appName??e.session?.appName,n=e.result.appBundleId??e.session?.appBundleId;return{...t||n?{appName:t??n}:{},...n?{appBundleId:n}:{}}}function Br(e){let t=[...e.annotations.warnings??[]];e.annotations.quality&&t.push(...Oe(e.annotations.quality,e.snapshot.nodes)),t.push(...Wr(e)),e.annotations.quality||(t.push(...Hr(e)),t.push(...Ur(e.snapshot.nodes)));let n=yt(e.snapshot.nodes);n&&t.push(n);let r=Vr(e.annotations);r&&t.push(r);let i=Gr(e);return i&&t.push(i),t.push(...Yr(e.annotations.freshness,e.snapshot.backend)),Array.from(new Set(t))}function Vr(e){if(e.androidSnapshot?.systemSurfaceOnly===!0)return Dr}function Hr(e){return e.snapshot.backend!==`xctest`||e.options.interactiveOnly!==!0||e.snapshot.nodes.length!==1||e.snapshot.nodes[0]?.type!==`Application`?[]:[`iOS interactive snapshot exposed only the application root. XCTest accessibility queries can fail to enumerate some simulator UI trees even when screenshots and direct gestures still work. Use screenshot as visual truth, try a scoped/full snapshot for diagnostics, and prefer direct selectors when known.`]}function Ur(e){let t=new Set(e.map(e=>e.parentIndex).filter(e=>e!==void 0));return e.filter(e=>t.has(e.index)||(e.type?.toLowerCase()??``).includes(`text`)?!1:(e.label??``).split(`, `).length>10).map(e=>{let t=(e.label??``).split(`, `).length,n=e.identifier?` (${e.identifier})`:``;return`@${e.ref} [${e.type??`element`}]${n} merges ~${t} labels into a single accessibility element. The app likely marks a container as accessible, which hides every descendant from assistive tech and automation — the children cannot be addressed individually. Fix the app's accessibility (mark the rows, not the container); until then use screenshot as visual truth and coordinate taps.`})}function Wr(e){let t=e.annotations.analysis;if(e.snapshot.backend!==`android`||e.options.interactiveOnly!==!0||e.snapshot.nodes.length>0||!t||(t.rawNodeCount??0)<12)return[];let n=[`Interactive snapshot is empty after filtering ${t.rawNodeCount} raw Android nodes. Likely causes: the app content is not accessibility-visible yet, a transient route change, or depth/filter options hid the target.`];return typeof e.options.depth==`number`&&typeof t.maxDepth==`number`&&t.maxDepth>=e.options.depth+2&&n.push(`Interactive output is empty at depth ${e.options.depth}; retry without -d.`),n}function Gr(e){let t=e.session?.snapshot;if(!e.annotations.freshness&&t&&Kr(t,e.snapshot)&&qr(t,e.capturedAt,e.runtimeNow)&&Xr(t.nodes.length,e.snapshot.nodes.length))return Jr}function Kr(e,t){return e.presentationKey===void 0||t.presentationKey===void 0?!0:e.presentationKey===t.presentationKey}function qr(e,t,n){return[t,n].some(t=>{let n=t-e.createdAt;return n>=0&&n<=2e3})}const Jr=`Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once.`;function Yr(e,t){return!e?.staleAfterRetries||t!==`android`?[]:e.reason===`stuck-route`?[`Recent ${e.action} was followed by a nearly identical snapshot after ${e.retryCount} automatic retr${e.retryCount===1?`y`:`ies`}. If you expected navigation or submit, the tree may still be stale. Use screenshot as visual truth, wait briefly, then re-snapshot once.`]:e.reason===`sharp-drop`?[Jr]:[]}function Xr(e,t){return e<12?!1:t<=Math.floor(e*.2)}const Zr={screenshot:Tr,diffScreenshot:fr,snapshot:Pr,diffSnapshot:Fr},Qr=new WeakMap;function $r(e,t){ti(e)&&Qr.set(e,t)}function ei(e){return ti(e)?Qr.get(e):void 0}function ti(e){return typeof e==`object`&&!!e||typeof e==`function`}const ni=async(e,t)=>await oi(e,t,`press`),ri=async(e,t)=>await oi(e,t,`click`),ii=async(e,t)=>{if(!t.text)throw new s(`INVALID_ARGS`,`fill requires text`);let n=tt(t),r=n.needsPreActionBaseline?null:await li(e,t);if(r)return r;let i=await Ae(e,t,{action:`fill`,requireInteractive:!0,promoteToHittableAncestor:!1,captureEvidenceBaseline:n.needsPreActionBaseline,expectedResolvedTarget:t.expectedResolvedTarget});if(!e.backend.fill)throw new s(`UNSUPPORTED_OPERATION`,`fill is not supported by this backend`);let a=si(i),o=`node`in i?i.node?.type??``:``,c=o!==``&&se(o,e.backend.platform),l=t.allowNonHittableCoordinateFallback===!0&&`node`in i&&i.node?.hittable===!1,u=b(await e.backend.fill(x(e,t),a,t.text,{delayMs:t.delayMs,allowNonHittableCoordinateFallback:l})),d=o&&!c?`fill target ${di(i)} resolved to "${o}", attempting fill anyway.`:void 0;return await Je(e,t,i,{...i,text:t.text,...d?{warning:d}:{},...u?{backendResult:u}:{}},n)},ai=async(e,t)=>{let n=t.text;if(!n)throw new s(`INVALID_ARGS`,`type requires text`);let r=fi(n);if(r)throw new s(`INVALID_ARGS`,`type does not accept a target ref like "${r}"`,{hint:`Use fill ${r} "text" to target that field, or press ${r} then type "text" to append.`});if(!e.backend.typeText)throw new s(`UNSUPPORTED_OPERATION`,`type is not supported by this backend`);let i=C(t.delayMs??0,`delay-ms`,0,1e4),a=b(await e.backend.typeText(x(e,t),n,{delayMs:i}));return{kind:`text`,text:n,delayMs:i,...a?{backendResult:a}:{},...y(`Typed ${Array.from(n).length} chars`)}};async function oi(e,t,n){let r=tt(t),i=r.needsPreActionBaseline?null:await ci(e,t,n);if(i)return i;let a=await Ae(e,t,{action:n,requireInteractive:!0,promoteToHittableAncestor:!0,captureEvidenceBaseline:r.needsPreActionBaseline,expectedResolvedTarget:t.expectedResolvedTarget});if(!e.backend.tap)throw new s(`UNSUPPORTED_OPERATION`,`tap is not supported by this backend`);let o=si(a),c;try{c=await e.backend.tap(x(e,t),o,{button:t.button,count:t.count,intervalMs:t.intervalMs,holdMs:t.holdMs,jitterPx:t.jitterPx,doubleTap:t.doubleTap})}catch(e){throw $r(e,a),e}let l=b(c);return await Je(e,t,a,{...a,...l?{backendResult:l}:{}},r)}function si(e){if(!e.point)throw new s(`COMMAND_FAILED`,`Interaction target resolved without coordinates`);return e.point}async function ci(e,t,n){if(n!==`click`||t.target.kind!==`ref`||!e.backend.tapTarget||ui(t)||t.expectedResolvedTarget)return null;let r=await je(e,t,t.target,n),i=b(await e.backend.tapTarget(x(e,t),{kind:`ref`,ref:t.target.ref,...t.target.fallbackLabel?{fallbackLabel:t.target.fallbackLabel}:{}}));return{kind:`ref`,target:{kind:`ref`,ref:t.target.ref},resolution:ke,...r,...i?{backendResult:i}:{}}}async function li(e,t){if(t.target.kind!==`ref`||!e.backend.fillTarget||t.expectedResolvedTarget)return null;let n=await je(e,t,t.target,`fill`),r=b(await e.backend.fillTarget(x(e,t),{kind:`ref`,ref:t.target.ref,...t.target.fallbackLabel?{fallbackLabel:t.target.fallbackLabel}:{}},t.text,{delayMs:t.delayMs}));return{kind:`ref`,target:{kind:`ref`,ref:t.target.ref},text:t.text,resolution:ke,...n,...r?{backendResult:r}:{}}}function ui(e){return e.count!==void 0||e.intervalMs!==void 0||e.holdMs!==void 0||e.jitterPx!==void 0||e.doubleTap!==void 0||e.button!==void 0&&e.button!==`primary`}function di(e){return e.target?.kind===`ref`?e.target.ref:e.target?.kind===`selector`?e.target.selector:`point`}function fi(e){return tn(e)}function H(e){return{includeRects:e===`visible`||e===`hidden`,interactiveOnly:!1}}function pi(e,t,n){let r=n??1e4,i=U(e),a=vi(),o=()=>Math.max(0,r-(U(e)-i));return{capture:async n=>{let r=!1,i=await We(e,t,o(),async e=>await a.attempt(async()=>{let t=await n(e);return r=!0,t}));return i.timedOut?{timedOut:!0,deadline:a.readableCaptures()===0?`capture-stalled`:`capture-truncated`}:(r&&a.recordReadableCapture(),i)},hasTimeRemaining:()=>o()>0,failureEvidence:()=>({timeoutMs:r,readableCaptures:a.readableCaptures(),waitedMs:U(e)-i}),rethrowIfNeverReadable:a.rethrowIfNeverReadable,sleepUntilNextPoll:async()=>await yi(e,t,Math.min(300,o())),timeoutMs:r,waitedMs:()=>U(e)-i}}function mi(e,t){return new s(`COMMAND_FAILED`,e,{reason:g.captureStalled,captureStalled:!0,...t,retriable:!0,hint:`No readable snapshot capture completed before the wait timeout. Retry, or use screenshot to inspect the current surface.`})}function hi(e,t){return new s(`COMMAND_FAILED`,e,{reason:g.deadlineExceeded,captureTruncated:!0,...t})}function gi(e,t){return new s(`COMMAND_FAILED`,e,{reason:g.targetAbsent,...t})}function _i(e,t,n){let r=t.failureEvidence();return n===`capture-stalled`?mi(e,r):n===`capture-truncated`?hi(e,r):(t.rethrowIfNeverReadable(),r.readableCaptures===0?mi(e,r):gi(e,r))}function vi(){let e=0,t;return{attempt:async e=>{try{return await e()}catch(e){if(!Pe(e))throw e;t=e;return}},recordReadableCapture:()=>{e+=1},readableCaptures:()=>e,rethrowIfNeverReadable:()=>{if(e===0&&t!==void 0)throw t}}}function U(e){return e.clock?.now()??Date.now()}async function yi(e,t,n){let r=[t.signal,e.signal].filter(e=>e!==void 0);for(let e of r)e.throwIfAborted();if(n<=0)return!1;if(e.clock){await e.clock.sleep(n);for(let e of r)e.throwIfAborted();return!0}return await new Promise((e,t)=>{let i=r.length>0?AbortSignal.any(r):void 0,a=()=>i?.removeEventListener(`abort`,s),o=setTimeout(()=>{a(),e()},n),s=()=>{clearTimeout(o),a(),t(i?.reason)};i?.addEventListener(`abort`,s,{once:!0}),o.unref()}),!0}function bi(e){if(e.kind===`ambiguous`)return{selector:e.selector,selectorIndex:e.selectorIndex,matchedNodes:e.matchedNodes};if(e.kind===`resolved`)return{selector:e.resolution.selector,selectorIndex:e.resolution.selectorIndex,matchedNodes:e.matchedNodes}}function xi(e){let t=async(t,n)=>{if(n.target.kind===`sleep`)return await Oi(t,n.target.durationMs),{kind:`sleep`,waitedMs:n.target.durationMs};if(n.target.kind===`ref`){let r=await e.requireSnapshot(t,n.session),i=d(n.target.ref);if(!i)throw new s(`INVALID_ARGS`,`Invalid ref: ${n.target.ref}`);let a=c(r.snapshot.nodes,i),o=a?He(a,r.snapshot.nodes):void 0;if(!o)throw new s(`COMMAND_FAILED`,`Ref ${n.target.ref} not found or has no label`);return await wi(e,t,n,o,n.target.timeoutMs)}if(n.target.kind===`selector`)return await Si(e,t,n,n.target.selector,n.target.timeoutMs,n.target.recordedLandmark);if(n.target.kind===`stable`)return await Ei(e,t,n,n.target.quietMs,n.target.timeoutMs);let r=Ce(n.target.text);if(!r.ok)throw new s(r.code,r.message);return await wi(e,t,n,n.target.text,n.target.timeoutMs)};return{waitCommand:t,waitForTextCommand:async(e,n)=>{let r=await t(e,{...n,target:{kind:`text`,text:n.text,timeoutMs:n.timeoutMs}});if(r.kind!==`text`)throw new s(`COMMAND_FAILED`,`waitForText returned non-text result`);return r}}}async function Si(e,t,n,r,i,a){let o=pi(t,n,i),c=H(),l,u;for(;o.hasTimeRemaining();){let i=await o.capture(async r=>await e.captureSnapshot(t,{...n,signal:r},{updateSession:!0,includeHiddenContentHints:!1,...c}));if(i.timedOut){u=i.deadline;break}let s=i.value;if(s){let e=s.snapshot.nodes,n=bi(fe(e,r,_.wait,{platform:t.backend.platform}));if(n){let t=Ci(e,n,a);if(t.kind===`satisfied`)return{kind:`selector`,selector:n.selector,waitedMs:o.waitedMs(),node:t.node,preActionNodes:e};l=t.evidence}}await o.sleepUntilNextPoll()}throw u!==`capture-stalled`&&l?new s(`COMMAND_FAILED`,`wait matched selector ${r} but no candidate carried the recorded landmark identity`,{reason:Qe,...l}):_i(`wait timed out for selector: ${r}`,o,u)}function Ci(e,t,n){let r=t.matchedNodes[0];if(!n)return{kind:`satisfied`,node:r};let i=Ue(e),a=Re(t.matchedNodes,i,Se(n),n.ancestry)[0];return a?{kind:`satisfied`,node:a}:{kind:`identity-mismatch`,evidence:{matchCount:t.matchedNodes.length,observed:_e(r),observedAncestry:Ve(r,i,Math.max(n.ancestry.length,1)).chain}}}async function wi(e,t,n,r,i){let a=pi(t,n,i),o;for(;a.hasTimeRemaining();){let i=await a.capture(async i=>t.backend.findText?(await t.backend.findText(Di(t,{...n,signal:i}),r)).found:await Ti(e,t,{...n,signal:i},r));if(i.timedOut){o=i.deadline;break}if(i.value)return{kind:`text`,text:r,waitedMs:a.waitedMs()};await a.sleepUntilNextPoll()}throw _i(`wait timed out for text: ${r}`,a,o)}async function Ti(e,t,n,r){return!!nt((await e.captureSnapshot(t,n,{updateSession:!0,includeHiddenContentHints:!1})).snapshot.nodes,r)}async function Ei(e,t,n,r,i){let a=i??1e4,o=r??e.stable.defaultQuietMs,c=await e.stable.capture(t,n,{quietMs:o,timeoutMs:a});if(!c.settled)throw new s(`COMMAND_FAILED`,`wait timed out waiting for a stable UI`,{reason:g.stableTimeout,...c.stalled?{captureStalled:!0}:{},quietMs:o,timeoutMs:a,captures:c.captures,nodeCount:c.nodeCount,...c.stalled?{hint:`A snapshot capture stalled past the wait timeout, so no settle verdict is available. The UI may still be readable: retry, or use screenshot to inspect the surface.`}:{}});return{kind:`stable`,waitedMs:c.waitedMs,captures:c.captures,nodeCount:c.nodeCount,...c.nodeCount<e.stable.tinyTreeNodeCount?{hint:e.stable.tinyTreeHint}:{}}}function Di(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}async function Oi(e,t){e.clock?await e.clock.sleep(t):await new Promise(e=>setTimeout(e,t))}const ki=xi({captureSnapshot:v,requireSnapshot:Fe,stable:{defaultQuietMs:500,tinyTreeHint:Xe,tinyTreeNodeCount:5,capture:Ye}}),Ai=ki.waitCommand,ji=ki.waitForTextCommand,Mi=async(e,t)=>{let n=t.locator??`any`;if(!t.query)throw new s(`INVALID_ARGS`,me);if(t.action===`wait`)return await zi(e,t,n);if(t.action===`list`)return await Bi(e,t,n);let{capture:r,match:i}=await Vi(e,t,n);if(!i)throw new s(`COMMAND_FAILED`,`find did not match any element`);if(t.action===`exists`)return{kind:`found`,found:!0};let a=`@${i.ref}`;return t.action===`get_attrs`?{kind:`attrs`,ref:a,node:i}:{kind:`text`,ref:a,text:await Ze(e,r,i),node:i}},Ni=async(e,t)=>{if(t.target.kind===`ref`){let n=await Fe(e,t.session),r=Ie(n.snapshot.nodes,t.target.ref,{fallbackLabel:t.target.fallbackLabel??``,invalidRefMessage:`get text requires a ref like @e2`,notFoundMessage:`Ref ${t.target.ref} not found`});at(r.node,n.snapshot.nodes,t.expectedResolvedTarget,`get`);let i=de(r.node,e.backend.platform,{action:`get`,nodes:n.snapshot.nodes}),a={kind:`ref`,ref:`@${r.ref}`},o=n.snapshot.nodes;return t.property===`attrs`?{kind:`attrs`,target:a,node:r.node,selectorChain:i,preActionNodes:o}:{kind:`text`,target:a,text:await Ze(e,n,r.node),node:r.node,selectorChain:i,preActionNodes:o}}let n=await Hi(e,t,t.session??`default`,{selector:t.target.selector,policy:t.property===`text`?_.readText:_.readUnique});at(n.node,n.capture.snapshot.nodes,t.expectedResolvedTarget,`get`);let r=de(n.node,e.backend.platform,{action:`get`,nodes:n.capture.snapshot.nodes});if(t.property===`attrs`)return{kind:`attrs`,target:{kind:`selector`,selector:n.selector},node:n.node,selectorChain:r,preActionNodes:n.capture.snapshot.nodes};let i=await Ze(e,n.capture,n.node);return{kind:`text`,target:{kind:`selector`,selector:n.selector},text:i,node:n.node,selectorChain:r,preActionNodes:n.capture.snapshot.nodes}},Pi=async(e,t)=>{let n=await Ni(e,{...t,property:`text`,target:t.target});if(n.kind!==`text`)throw new s(`COMMAND_FAILED`,`getText returned non-text result`);return n},Fi=async(e,t)=>{let n=await Ni(e,{...t,property:`attrs`,target:t.target});if(n.kind!==`attrs`)throw new s(`COMMAND_FAILED`,`getAttrs returned non-attrs result`);return n},Ii=async(e,t)=>{let n=Te(t.predicate);if(!n.ok)throw new s(n.code,n.message,{hint:n.hint});let r=n.predicate;if(r===`text`&&!t.expectedText)throw new s(`INVALID_ARGS`,xe);let i=t.selector,a=await v(e,t,{updateSession:!0,...H(r)});if(r===`exists`){let t=be(a.snapshot.nodes,i,{platform:e.backend.platform});if(!t)throw new s(`COMMAND_FAILED`,we(i,[],{unique:!1}),{hint:ce([])});return{predicate:r,pass:!0,selector:t.selector,matches:t.matches,selectorChain:pe(i)}}let o=le(a.snapshot.nodes,i,{platform:e.backend.platform,...Ee(_.readUnique)});if(!o)throw new s(`COMMAND_FAILED`,we(i,[],{unique:!0}),{command:`is`,reason:`selector_not_found`,predicate:r,selector:i,hint:ce([])});at(o.node,a.snapshot.nodes,t.expectedResolvedTarget,`is`);let c=ge({predicate:r,node:o.node,nodes:a.snapshot.nodes,expectedText:t.expectedText,platform:e.backend.platform});if(!c.pass)throw new s(`COMMAND_FAILED`,`is ${r} failed for selector ${o.selector}: ${c.details}`,{command:`is`,reason:`predicate_failed`,predicate:r,selector:o.selector,predicateDetails:c.details});return{predicate:r,pass:!0,selector:o.selector,...r===`text`?{text:c.actualText}:{},selectorChain:pe(i),node:o.node,preActionNodes:a.snapshot.nodes}},Li=async(e,t)=>await Ii(e,{...t,predicate:`visible`,selector:t.target.selector}),Ri=async(e,t)=>await Ii(e,{...t,predicate:`hidden`,selector:t.target.selector});async function zi(e,t,n){let r=pi(e,t,t.timeoutMs),i;for(;r.hasTimeRemaining();){let a=await r.capture(async r=>await Vi(e,{...t,signal:r},n,{includeHiddenContentHints:!1}));if(a.timedOut){i=a.deadline;break}if(a.value?.match)return{kind:`found`,found:!0,waitedMs:r.waitedMs()};await r.sleepUntilNextPoll()}throw _i(`find wait timed out`,r,i)}async function Bi(e,t,n){let r=ue(n,t.query),i=await v(e,t,{updateSession:!0,...H()});if(Ne(i.snapshot.snapshotQuality))throw Me(i.snapshot.snapshotQuality);return{kind:`list`,matches:(r?ve(i.snapshot.nodes,r,{platform:e.backend.platform})?.matchedNodes??[]:ye(i.snapshot.nodes,n,t.query,{}).matches).map(e=>({ref:`@${e.ref}`,node:e}))}}async function Vi(e,t,n,r){let i=ue(n,t.query),a=await v(e,t,{updateSession:!0,scope:Le(e.backend.platform,n,t.query,i),includeHiddenContentHints:r?.includeHiddenContentHints,...H()});if(Ne(a.snapshot.snapshotQuality))throw Me(a.snapshot.snapshotQuality);return i?{capture:a,match:le(a.snapshot.nodes,i,{platform:e.backend.platform,...Ee(_.readAny)})?.node}:{capture:a,match:ye(a.snapshot.nodes,n,t.query,{requireRect:!1}).matches[0]}}async function Hi(e,t,n,r){let i=await v(e,{...t,session:n},{updateSession:!0,...H()}),a=le(i.snapshot.nodes,r.selector,{platform:e.backend.platform,...Ee(r.policy)});if(!a)throw new s(`COMMAND_FAILED`,we(r.selector,[],{unique:!0}),{hint:ce([])});return{capture:i,node:a.node,selector:a.selector,ref:`@${a.node.ref}`}}const Ui=async(e,t)=>{if(!e.backend.performGesture)throw new s(`UNSUPPORTED_OPERATION`,`gesture is not supported by this backend`);await Be(e,t,t.gesture.intent);let n=await it(e,t),r=m(t.gesture,n,e.backend.platform),i=b(await e.backend.performGesture(x(e,t),r)),a=Gi(r.pointers,0),o=Gi(r.pointers,-1);return{kind:t.gesture.intent,durationMs:r.durationMs,pointerCount:r.topology===`single`?1:2,from:a,to:o,...i?{backendResult:i}:{},...y(Ki(t.gesture,a,o))}},Wi=async(e,t)=>{let n=t.gesture;return n.intent===`drag`?await rt(e,{...t,gesture:n}):await Ui(e,{...t,gesture:n})};function Gi(e,t){let n=e.map(e=>t===0?e.samples[0]?.point:e.samples.at(-1)?.point);if(n.some(e=>e===void 0))throw new s(`COMMAND_FAILED`,`Gesture plan did not contain endpoint samples.`);let r=n;return{x:r.reduce((e,t)=>e+t.x,0)/r.length,y:r.reduce((e,t)=>e+t.y,0)/r.length}}function Ki(e,t,n){switch(e.intent){case`pan`:{let r=`preset`in e?t:e.origin,i=`preset`in e?{x:n.x-t.x,y:n.y-t.y}:e.delta;return`Panned (${r.x}, ${r.y}) by (${i.x}, ${i.y})`}case`fling`:return`direction`in e?`Flung ${e.direction}`:`Flung`;case`pinch`:return`Pinched to scale ${e.scale}`;case`rotate`:return`Rotated gesture ${e.degrees} degrees`;case`transform`:return`Requested transform gesture by (${e.delta.x}, ${e.delta.y}), scale ${e.scale}, rotate ${e.degrees} degrees`}}const W={find:Mi,get:Ni,getText:Pi,getAttrs:Fi,is:Ii,isVisible:Li,isHidden:Ri,wait:Ai,waitForText:ji},G={click:ri,press:ni,fill:ii,typeText:ai,focus:Ke,longPress:$e,scroll:qe,gesture:Wi,settleObservation:et};function qi(e){return{find:t=>W.find(e,t),get:t=>W.get(e,t),getText:(t,n={})=>W.getText(e,{...n,target:t}),getAttrs:(t,n={})=>W.getAttrs(e,{...n,target:t}),is:t=>W.is(e,t),isVisible:(t,n={})=>W.isVisible(e,{...n,target:t}),isHidden:(t,n={})=>W.isHidden(e,{...n,target:t}),wait:t=>W.wait(e,t),waitForText:(t,n={})=>W.waitForText(e,{...n,text:t})}}function Ji(e){return{click:(t,n={})=>G.click(e,{...n,target:t}),press:(t,n={})=>G.press(e,{...n,target:t}),fill:(t,n,r={})=>G.fill(e,{...r,target:t,text:n}),typeText:(t,n={})=>G.typeText(e,{...n,text:t}),focus:(t,n={})=>G.focus(e,{...n,target:t}),longPress:(t,n={})=>G.longPress(e,{...n,target:t}),scroll:t=>G.scroll(e,t),gesture:t=>G.gesture(e,t),settleObservation:t=>G.settleObservation(e,t)}}function K(e,t){if(e!==void 0)return q(e,t)}function q(e,t){let n=e?.trim();if(!n)throw new s(`INVALID_ARGS`,`${t} must be a non-empty string`);return n}const Yi=async(e,t={})=>{if(!e.backend.listDevices)throw new s(`UNSUPPORTED_OPERATION`,`admin.devices is not supported by this backend`);return{kind:`adminDevices`,devices:await e.backend.listDevices(x(e,t),t.filter)}},Xi=async(e,t={})=>{if(!e.backend.bootDevice)throw new s(`UNSUPPORTED_OPERATION`,`admin.boot is not supported by this backend`);let n=oa(t.target),r=b(await e.backend.bootDevice(x(e,t),n));return{kind:`deviceBooted`,...n?{target:n}:{},...r?{backendResult:r}:{},...y(`Booted device`)}},Zi=async(e,t={})=>{if(!e.backend.shutdownDevice)throw new s(`UNSUPPORTED_OPERATION`,`admin.shutdown is not supported by this backend`);let n=oa(t.target),r=b(await e.backend.shutdownDevice(x(e,t),n));return{kind:`deviceShutdown`,...n?{target:n}:{},...r?{backendResult:r}:{},...y(`Shutdown device`)}},Qi=async(e,t)=>await ta(e,t,`install`),$i=async(e,t)=>await ta(e,t,`reinstall`),ea=async(e,t)=>await ta(e,t,`installFromSource`);async function ta(e,t,n){let r=n===`reinstall`?`reinstallApp`:`installApp`,i=e.backend[r];if(!i)throw new s(`UNSUPPORTED_OPERATION`,`admin.${n} is not supported by this backend`);let a=`app`in t&&t.app!==void 0?q(t.app,`app`):void 0;if(n!==`installFromSource`&&!a)throw new s(`INVALID_ARGS`,`admin.${n} requires app`);let o=x(e,t),c=await na(e,o,t.source);try{let t=await i.call(e.backend,o,{...a?{app:a}:{},source:c.source});return sa(n,a,c.source,t)}finally{await c.cleanup?.()}}async function na(e,t,n){let r=await ra(e,ia(n));try{return{source:ia(e.backend.resolveInstallSource?await e.backend.resolveInstallSource(t,r.source):r.source),...r.cleanup?{cleanup:r.cleanup}:{}}}catch(e){if(r.cleanup)try{await r.cleanup()}catch{}throw e}}async function ra(e,t){if(t.kind===`url`)return{source:t};let n=await z(e,t,{usage:`admin.install`,field:`source`});return{source:{kind:`path`,path:n.path},...n.cleanup?{cleanup:n.cleanup}:{}}}function ia(e){if(!e||typeof e!=`object`)throw new s(`INVALID_ARGS`,`install source is required`);if(e.kind===`path`)return{kind:`path`,path:q(e.path,`source.path`)};if(e.kind===`uploadedArtifact`)return{kind:`uploadedArtifact`,id:q(e.id,`source.id`)};if(e.kind===`url`){let t=q(e.url,`source.url`);return aa(t),{kind:`url`,url:t}}throw new s(`INVALID_ARGS`,`install source kind must be path, uploadedArtifact, or url`)}function aa(e){let t;try{t=new URL(e)}catch{throw new s(`INVALID_ARGS`,`Invalid install source URL: ${e}`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new s(`INVALID_ARGS`,`Install source URL must use http or https`)}function oa(e){if(!e)return;let t=K(e.id,`target.id`),n=K(e.name,`target.name`),r={...t?{id:t}:{},...n?{name:n}:{},...e.platform?{platform:e.platform}:{},...e.target?{target:e.target}:{},...e.headless===void 0?{}:{headless:e.headless}};return Object.keys(r).length>0?r:void 0}function sa(e,t,n,r){let i=b(r),a=e===`reinstall`?`appReinstalled`:e===`installFromSource`?`appInstalledFromSource`:`appInstalled`,o=J(r,`appName`),s=J(r,`appId`),c=J(r,`bundleId`),l=J(r,`packageName`),u=J(r,`launchTarget`),d=J(r,`installablePath`),f=J(r,`archivePath`);return{kind:a,...t?{app:t}:{},source:n,...s?{appId:s}:{},...o?{appName:o}:{},...c?{bundleId:c}:{},...l?{packageName:l}:{},...u?{launchTarget:u}:{},...d?{installablePath:d}:{},...f?{archivePath:f}:{},...i?{backendResult:i}:{},...y(`${e===`reinstall`?`Reinstalled`:`Installed`}: ${o??u??t??ca(n)}`)}}function J(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function ca(e){return e.kind===`path`?e.path:e.kind===`uploadedArtifact`?e.id:e.url}const la=/^[A-Za-z0-9_.:-]{1,64}$/,ua=async(e,t)=>{if(!e.backend.openApp)throw new s(`UNSUPPORTED_OPERATION`,`apps.open is not supported by this backend`);let n=ga(t),r=b(await e.backend.openApp(Y(e,t),n,{launchArgs:t.launchArgs,relaunch:t.relaunch}));return{kind:`appOpened`,target:n,relaunch:t.relaunch===!0,...r?{backendResult:r}:{},...y(`Opened: ${va(n)}`)}},da=async(e,t={})=>{if(!e.backend.closeApp)throw new s(`UNSUPPORTED_OPERATION`,`apps.close is not supported by this backend`);let n=K(t.app,`app`),r=b(await e.backend.closeApp(Y(e,t),n));return{kind:`appClosed`,...n?{app:n}:{},...r?{backendResult:r}:{},...y(n?`Closed: ${n}`:`Closed app`)}},fa=async(e,t={})=>{if(!e.backend.listApps)throw new s(`UNSUPPORTED_OPERATION`,`apps.list is not supported by this backend`);return{kind:`appsList`,apps:await e.backend.listApps(Y(e,t),ct(t.filter))}},pa=async(e,t)=>{if(!e.backend.getAppState)throw new s(`UNSUPPORTED_OPERATION`,`apps.state is not supported by this backend`);let n=q(t.app,`app`);return{kind:`appState`,app:n,state:await e.backend.getAppState(Y(e,t),n)}},ma=async(e,t)=>{if(!e.backend.pushFile)throw new s(`UNSUPPORTED_OPERATION`,`apps.push is not supported by this backend`);let n=q(t.app,`app`),r=await ya(e,t.input);try{let i=b(await e.backend.pushFile(Y(e,t),r.backendInput,n));return{kind:`appPushed`,app:n,inputKind:r.inputKind,...i?{backendResult:i}:{},...y(`Pushed to ${n}`)}}finally{await r.cleanup?.()}},ha=async(e,t)=>{if(!e.backend.triggerAppEvent)throw new s(`UNSUPPORTED_OPERATION`,`apps.triggerEvent is not supported by this backend`);let n=ba(t.name);xa(t.payload,`apps.triggerEvent payload for "${n}"`);let r=b(await e.backend.triggerAppEvent(Y(e,t),{name:n,...t.payload?{payload:t.payload}:{}}));return{kind:`appEventTriggered`,name:n,...t.payload?{payload:t.payload}:{},...r?{backendResult:r}:{},...y(`Triggered app event: ${n}`)}};function ga(e){let t=K(e.app,`app`),n=K(e.appId,`appId`),r=K(e.bundleId,`bundleId`),i=K(e.packageName,`packageName`),a=K(e.url,`url`),o=K(e.activity,`activity`),c={...t?{app:t}:{},...n?{appId:n}:{},...r?{bundleId:r}:{},...i?{packageName:i}:{},...a?{url:a}:{},...o?{activity:o}:{}};if(!_a(c))throw new s(`INVALID_ARGS`,`apps.open requires app, appId, bundleId, packageName, url, or activity`);return c}function _a(e){return!!(e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity)}function va(e){return e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity??`app`}async function ya(e,t){if(!t||typeof t!=`object`)throw new s(`INVALID_ARGS`,`apps.push requires an input`);if(t.kind===`json`)return Sa(t.payload,`apps.push JSON payload`,8192),{backendInput:{kind:`json`,payload:t.payload},inputKind:`json`};let n=await z(e,t,{usage:`apps.push`,field:`input`});return{backendInput:{kind:`file`,path:n.path},inputKind:`file`,...n.cleanup?{cleanup:n.cleanup}:{}}}function ba(e){let t=q(e,`name`);if(!la.test(t))throw new s(`INVALID_ARGS`,`Invalid apps.triggerEvent name: ${t}`,{hint:`Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash.`});return t}function xa(e,t){e!==void 0&&Sa(e,t,8192)}function Sa(e,t,n){if(Ca(e,t),Buffer.byteLength(wa(e,t),`utf8`)>n)throw new s(`INVALID_ARGS`,`${t} exceeds ${n} bytes`)}function Ca(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new s(`INVALID_ARGS`,`${t} must be a JSON object`)}function wa(e,t){try{let n=JSON.stringify(e);if(typeof n!=`string`)throw new s(`INVALID_ARGS`,`${t} must be JSON-serializable`);return n}catch{throw new s(`INVALID_ARGS`,`${t} must be JSON-serializable`)}}function Y(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}const Ta={open:ua,close:da,list:fa,state:pa,push:ma,triggerEvent:ha},Ea={devices:Yi,boot:Xi,shutdown:Zi,install:Qi,reinstall:$i,installFromSource:ea};function Da(e){return{...S(Ta,e),list:(t={})=>Ta.list(e,{...t,filter:lt(t.filter)})}}const Oa=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i,ka=/\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/g;function Aa(e){let t=!1,n=e;return n=n.replaceAll(/(authorization|token|secret|password|passwd|api[-_]?key)=([^&\s]+)/gi,(e,n)=>(t=!0,`${String(n)}=[REDACTED]`)),n=n.replaceAll(/("(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)"\s*:\s*")([^"]*)(")/gi,(e,n,r,i)=>(t=!0,`${String(n)}[REDACTED]${String(i)}`)),n=n.replaceAll(/\b(Bearer\s+)([^\s",;]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(/((?:authorization|cookie|token|secret|password|passwd|api[-_]?key)\s*[:=]\s*)([^\s,;&]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(ka,()=>(t=!0,`[REDACTED]`)),n=Ma(n,()=>{t=!0}),{value:n,redacted:t}}function ja(e){try{let t=new URL(e),n=Na(t);return(t.username||t.password)&&(t.username=`REDACTED`,t.password=`REDACTED`,n=!0),{value:t.toString(),redacted:n}}catch{return}}function Ma(e,t){return/(https?:\/\/|token|secret|password|authorization|cookie|api[-_]?key)/i.test(e)?e.replaceAll(/https?:\/\/[^\s"'<>)]+/gi,e=>{let n=ja(e);return n?(n.redacted&&t(),n.value):e}):e}function Na(e){let t=!1;for(let n of Array.from(e.searchParams.keys()))Oa.test(n)&&(e.searchParams.set(n,`[REDACTED]`),t=!0);return t}const X=2048,Pa=4096,Fa=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i;function Ia(e){let t=e.redacted===!0;return{kind:`diagnosticsLogs`,entries:e.entries.map(e=>{let n=Q(e.message,Pa),r=Ua(e.metadata);return t||=n.redacted||r.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.level?{level:e.level}:{},message:n.value??``,...e.source?{source:e.source}:{},...r.value?{metadata:r.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function La(e,t){let n=e.redacted===!0;return{kind:`diagnosticsNetwork`,entries:e.entries.map(e=>{let r=e.url?Ba(e.url):void 0,i=t===`headers`||t===`all`?za(e.requestHeaders):void 0,a=t===`headers`||t===`all`?za(e.responseHeaders):void 0,o=t===`body`||t===`all`?Va(e.requestBody):void 0,s=t===`body`||t===`all`?Va(e.responseBody):void 0,c=Ua(e.metadata);return n||=(r?.redacted??!1)||(i?.redacted??!1)||(a?.redacted??!1)||(o?.redacted??!1)||(s?.redacted??!1)||c.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.method?{method:e.method}:{},...r?{url:r.value}:{},...e.status===void 0?{}:{status:e.status},...e.durationMs===void 0?{}:{durationMs:e.durationMs},...i?.value?{requestHeaders:i.value}:{},...a?.value?{responseHeaders:a.value}:{},...o?.value===void 0?{}:{requestBody:o.value},...s?.value===void 0?{}:{responseBody:s.value},...c.value?{metadata:c.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:n,...e.notes?{notes:e.notes}:{}}}function Ra(e){let t=e.redacted===!0;return{kind:`diagnosticsPerf`,metrics:e.metrics.map(e=>{let n=Q(e.message,Pa),r=Ua(e.metadata);return t||=n.redacted||r.redacted,{name:e.name,...e.value===void 0?{}:{value:e.value},...e.unit?{unit:e.unit}:{},...e.status?{status:e.status}:{},...n.value===void 0?{}:{message:n.value},...r.value?{metadata:r.value}:{}}}),...e.startedAt?{startedAt:e.startedAt}:{},...e.endedAt?{endedAt:e.endedAt}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function za(e){if(!e)return{redacted:!1};let t=!1,n={};for(let[r,i]of Object.entries(e))if(Fa.test(r))n[r]=`[REDACTED]`,t=!0;else{let e=Q(i,X);n[r]=e.value??``,t||=e.redacted}return{value:n,redacted:t}}function Ba(e){return ja(e)??Q(e,X)}function Va(e){return e===void 0?{redacted:!1}:Ha(e)??Q(e,X)}function Ha(e){try{let t=Z(JSON.parse(e),Aa);return Wa(JSON.stringify(t.value),X,t.redacted)}catch{return}}function Ua(e){return Z(e,e=>Q(e,X))}function Z(e,t){if(e===void 0)return{redacted:!1};if(typeof e==`string`)return t(e);if(!e||typeof e!=`object`)return{value:e,redacted:!1};if(Array.isArray(e)){let n=!1;return{value:e.map(e=>{let r=Z(e,t);return n||=r.redacted,r.value}),redacted:n}}let n=!1,r={};for(let[i,a]of Object.entries(e)){if(Fa.test(i)){r[i]=`[REDACTED]`,n=!0;continue}let e=Z(a,t);r[i]=e.value,n||=e.redacted}return{value:r,redacted:n}}function Q(e,t){if(e===void 0)return{redacted:!1};let n=Aa(e);return Wa(n.value,t,n.redacted)}function Wa(e,t,n){if(e===void 0)return{redacted:n};let r=e;return r.length>t&&(r=`${r.slice(0,t)}...[truncated]`,n=!0),{value:r,redacted:n}}const Ga=async(e,t={})=>{if(!e.backend.readLogs)throw new s(`UNSUPPORTED_OPERATION`,`diagnostics.logs is not supported by this backend`);return Ia(await e.backend.readLogs(await Ja(e,t),Ya(t)))},Ka=async(e,t={})=>{if(!e.backend.dumpNetwork)throw new s(`UNSUPPORTED_OPERATION`,`diagnostics.network is not supported by this backend`);let n=Xa(t);return La(await e.backend.dumpNetwork(await Ja(e,t),n),n.include??`summary`)},qa=async(e,t={})=>{if(!e.backend.measurePerf)throw new s(`UNSUPPORTED_OPERATION`,`diagnostics.perf is not supported by this backend`);return Ra(await e.backend.measurePerf(await Ja(e,t),Za(t)))};async function Ja(e,t){let n=x(e,t),r=t.session?await e.sessions.get(t.session):void 0;return{...n,...t.appId??r?.appId?{appId:t.appId??r?.appId}:{},...t.appBundleId??r?.appBundleId?{appBundleId:t.appBundleId??r?.appBundleId}:{}}}function Ya(e){return{...Qa(e,100,500,`logs limit`),...e.levels===void 0?{}:{levels:to(e.levels,`levels`)},...e.search===void 0?{}:{search:q(e.search,`search`)},...e.source===void 0?{}:{source:q(e.source,`source`)}}}function Xa(e){return{...Qa(e,25,200,`network limit`),include:eo(e.include)}}function Za(e){return{...$a(e),...e.sampleMs===void 0?{}:{sampleMs:C(e.sampleMs,`sampleMs`,100,6e4)},...e.metrics===void 0?{}:{metrics:to(e.metrics,`metrics`,20)}}}function Qa(e,t,n,r){return{...$a(e),...e.cursor===void 0?{}:{cursor:q(e.cursor,`cursor`)},limit:e.limit===void 0?t:C(e.limit,r,1,n)}}function $a(e){return{...e.since===void 0?{}:{since:q(e.since,`since`)},...e.until===void 0?{}:{until:q(e.until,`until`)}}}function eo(e){if(e===void 0)return`summary`;if(e===`summary`||e===`headers`||e===`body`||e===`all`)return e;throw new s(`INVALID_ARGS`,`network include must be summary, headers, body, or all`)}function to(e,t,n=50){if(!Array.isArray(e))throw new s(`INVALID_ARGS`,`${t} must be an array of strings`);if(e.length>n)throw new s(`INVALID_ARGS`,`${t} must contain at most ${n} entries`);return e.map((e,n)=>q(e,`${t}[${n}]`))}const no={logs:Ga,network:Ka,perf:qa},ro=async(e,t)=>{let n=co(t.action,`record`),r=n===`start`?e.backend.startRecording:e.backend.stopRecording;if(!r)throw new s(`UNSUPPORTED_OPERATION`,`record ${n} is not supported by this backend`);let i=t.out?await B(e,t.out,{field:`path`,ext:`.mp4`,artifactType:`screen-recording`}):void 0;try{let a=ao(t,i?.path);return lo(n,await r.call(e.backend,x(e,t),a),await i?.publish())}catch(e){throw await i?.cleanup?.(),e}},io=async(e,t)=>{let n=co(t.action,`trace`),r=n===`start`?e.backend.startTrace:e.backend.stopTrace;if(!r)throw new s(`UNSUPPORTED_OPERATION`,`trace ${n} is not supported by this backend`);let i=t.out?await B(e,t.out,{field:`outPath`,ext:`.trace`,artifactType:`trace-log`}):void 0;try{let a={...i?.path?{outPath:i.path}:{}};return uo(n,await r.call(e.backend,x(e,t),a),await i?.publish())}catch(e){throw await i?.cleanup?.(),e}};function ao(e,t){let n={};t&&(n.outPath=t);let r=oo(e.fps);r!==void 0&&(n.fps=r);let i=so(e.quality);return i!==void 0&&(n.quality=i),e.hideTouches!==void 0&&(n.showTouches=e.hideTouches!==!0),n}function oo(e){return e===void 0?void 0:C(e,`fps`,1,60)}function so(e){if(e===void 0)return;let t=De(e);if(t===void 0)throw new s(`INVALID_ARGS`,`quality must be one of: medium, high (legacy numeric values 5-10 are accepted)`);return t}function co(e,t){if(e===`start`||e===`stop`)return e;throw new s(`INVALID_ARGS`,`${t} action must be start or stop`)}function lo(e,t,n){return{...typeof t.path==`string`?{path:t.path}:{},...typeof t.telemetryPath==`string`?{telemetryPath:t.telemetryPath}:{},...typeof t.warning==`string`?{warning:t.warning}:{},...fo(e,t,n,{startKind:`recordingStarted`,stopKind:`recordingStopped`,startMessage:`Recording started`,stopMessage:`Recording stopped`})}}function uo(e,t,n){return{...typeof t.outPath==`string`?{outPath:t.outPath}:{},...fo(e,t,n,{startKind:`traceStarted`,stopKind:`traceStopped`,startMessage:`Trace started`,stopMessage:`Trace stopped`})}}function fo(e,t,n,r){return{kind:e===`start`?r.startKind:r.stopKind,action:e,...n?{artifact:n}:{},backendResult:t,...y(e===`start`?r.startMessage:r.stopMessage)}}const po={record:ro,trace:io},mo=async(e,t={})=>{if(!e.backend.pressBack)throw new s(`UNSUPPORTED_OPERATION`,`system.back is not supported by this backend`);let n=t.mode??`in-app`;if(n!==`in-app`&&n!==`system`)throw new s(`INVALID_ARGS`,`system.back mode must be in-app or system`);let r=b(await e.backend.pressBack(x(e,t),{mode:n}));return{kind:`systemBack`,mode:n,...r?{backendResult:r}:{},...y(`Back`)}},ho=async(e,t={})=>{if(!e.backend.pressHome)throw new s(`UNSUPPORTED_OPERATION`,`system.home is not supported by this backend`);let n=b(await e.backend.pressHome(x(e,t)));return{kind:`systemHome`,...n?{backendResult:n}:{},...y(`Home`)}},go=async(e,t)=>{if(!e.backend.pressTvRemote)throw new s(`UNSUPPORTED_OPERATION`,`system.tvRemote is not supported by this backend`);let n=ee(t.button),r=t.durationMs===void 0?void 0:C(t.durationMs,`durationMs`,0,1e4),i=b(await e.backend.pressTvRemote(x(e,t),{button:n,...r===void 0?{}:{durationMs:r}}));return{kind:`tvRemotePressed`,button:n,...r===void 0?{}:{durationMs:r},...i?{backendResult:i}:{},...y(`Pressed TV remote ${n}`)}},_o=async(e,t)=>{if(!e.backend.setOrientation)throw new s(`UNSUPPORTED_OPERATION`,`system.orientation is not supported by this backend`);let n=Co(t.orientation),r=b(await e.backend.setOrientation(x(e,t),n));return{kind:`systemOrientationSet`,orientation:n,...r?{backendResult:r}:{},...y(`Rotated to ${n}`)}},vo=async(e,t={})=>{if(!e.backend.setKeyboard)throw new s(`UNSUPPORTED_OPERATION`,`system.keyboard is not supported by this backend`);let n=t.action??`status`;if(!st(n))throw new s(`INVALID_ARGS`,`system.keyboard action must be status, get, dismiss, enter, or return`);let r=await e.backend.setKeyboard(x(e,t),{action:n}),i=b(r),a=Mo(r)?r:{};return n===`enter`||n===`return`?To(a,i):n===`dismiss`?Eo(n,a,i):Oo(n,a,i)},yo=async(e,t)=>{if(t.action===`read`){if(!e.backend.getClipboard)throw new s(`UNSUPPORTED_OPERATION`,`system.clipboard read is not supported by this backend`);let n=await e.backend.getClipboard(x(e,t));return{kind:`clipboardText`,action:`read`,text:typeof n==`string`?n:n.text}}if(t.action!==`write`)throw new s(`INVALID_ARGS`,`system.clipboard action must be read or write`);if(!e.backend.setClipboard)throw new s(`UNSUPPORTED_OPERATION`,`system.clipboard write is not supported by this backend`);if(typeof t.text!=`string`)throw new s(`INVALID_ARGS`,`system.clipboard write requires text`);let n=b(await e.backend.setClipboard(x(e,t),t.text));return{kind:`clipboardUpdated`,action:`write`,textLength:Array.from(t.text).length,...n?{backendResult:n}:{},...y(`Clipboard updated`)}},bo=async(e,t={})=>{if(!e.backend.openSettings)throw new s(`UNSUPPORTED_OPERATION`,`system.settings is not supported by this backend`);let n=K(t.target,`target`),r=b(await e.backend.openSettings(x(e,t),n));return{kind:`settingsOpened`,...n?{target:n}:{},...r?{backendResult:r}:{},...y(n?`Opened settings: ${n}`:`Opened settings`)}},xo=async(e,t={})=>{if(!e.backend.handleAlert)throw new s(`UNSUPPORTED_OPERATION`,`system.alert is not supported by this backend`);let n=t.action??`get`;if(n!==`get`&&n!==`accept`&&n!==`dismiss`&&n!==`wait`)throw new s(`INVALID_ARGS`,`system.alert action must be get, accept, dismiss, or wait`);let r=t.timeoutMs===void 0?void 0:C(t.timeoutMs,`timeoutMs`,0,12e4);return wo(n,await e.backend.handleAlert(x(e,t),n,{timeoutMs:r}))},So=async(e,t={})=>{if(!e.backend.openAppSwitcher)throw new s(`UNSUPPORTED_OPERATION`,`system.appSwitcher is not supported by this backend`);let n=b(await e.backend.openAppSwitcher(x(e,t)));return{kind:`appSwitcherOpened`,...n?{backendResult:n}:{},...y(`Opened app switcher`)}};function Co(e){switch(e){case`portrait`:case`portrait-upside-down`:case`landscape-left`:case`landscape-right`:return e;default:throw new s(`INVALID_ARGS`,`system.orientation must be portrait, portrait-upside-down, landscape-left, or landscape-right`)}}function wo(e,t){return e===`get`?ko(t):e===`wait`?Ao(t):jo(e,t)}function To(e,t){return{kind:`keyboardEnterPressed`,action:`enter`,state:e,...t?{backendResult:t}:{},...y(`Keyboard enter pressed`)}}function Eo(e,t,n){return{kind:`keyboardDismissed`,action:e,state:t,...n?{backendResult:n}:{},...y(Do(t))}}function Do(e){return e.dismissed===!1?`Keyboard already hidden`:e.mechanism===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`}function Oo(e,t,n){return{kind:`keyboardState`,action:e,state:t,...n?{backendResult:n}:{}}}function ko(e){if(e.kind!==`alertStatus`)throw new s(`COMMAND_FAILED`,`system.alert get returned an invalid backend result`);return{kind:`alertStatus`,action:`get`,alert:e.alert}}function Ao(e){if(e.kind!==`alertWait`)throw new s(`COMMAND_FAILED`,`system.alert wait returned an invalid backend result`);return{kind:`alertWait`,action:`wait`,alert:e.alert,...e.waitedMs===void 0?{}:{waitedMs:e.waitedMs},...e.timedOut===void 0?{}:{timedOut:e.timedOut},...y(e.alert?`Alert visible`:`Alert wait timed out`)}}function jo(e,t){if(t.kind!==`alertHandled`)throw new s(`COMMAND_FAILED`,`system.alert ${e} returned an invalid backend result`);return{kind:`alertHandled`,action:e,handled:t.handled,...t.alert?{alert:t.alert}:{},...t.button?{button:t.button}:{},...y(t.handled?`Alert ${e}ed`:`No alert handled`)}}function Mo(e){return!!(e&&typeof e==`object`)}const No={back:mo,home:ho,orientation:_o,keyboard:vo,clipboard:yo,settings:bo,alert:xo,appSwitcher:So,tvRemote:go};function Po(e){return{capture:S(Zr,e),selectors:qi(e),interactions:Ji(e),system:S(No,e),apps:Da(e),admin:S(Ea,e),recording:S(po,e),observability:S(no,e)}}var Fo=r({createAgentDevice:()=>Io,createMemorySessionStore:()=>Lo,localCommandPolicy:()=>zo,restrictedCommandPolicy:()=>Bo});function Io(e){let t={backend:e.backend,artifacts:e.artifacts,sessions:e.sessions??Lo(),policy:e.policy??Bo(),diagnostics:e.diagnostics,clock:e.clock,signal:e.signal};return{...t,...Po(t)}}function Lo(e=[]){let t=new Map(e.map(e=>[e.name,$(e)]));return{get:e=>$(t.get(e)),set:e=>{t.set(e.name,$(e))},delete:e=>{t.delete(e)},list:()=>Array.from(t.values(),e=>$(e))}}function $(e){if(e)return{...e,...e.snapshot?{snapshot:structuredClone(e.snapshot)}:{},...e.metadata?{metadata:Ro(e.metadata)}:{}}}function Ro(e){try{return structuredClone(e)}catch{return{...e}}}function zo(e={}){return{allowLocalInputPaths:!0,allowLocalOutputPaths:!0,maxImagePixels:2e7,...e}}function Bo(e={}){return{allowLocalInputPaths:!1,allowLocalOutputPaths:!1,maxImagePixels:2e7,...e}}export{Lt as _,Or as a,M as c,hn as d,tn as f,Pt as g,St as h,ei as i,N as l,xt as m,zo as n,Cr as o,bt as p,Fo as r,gn as s,Io as t,mn as u};
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,t as a}from"./png-worker-contract.js";import{T as o,_ as s,d as c,g as l,l as u,p as d,u as f,v as p}from"./sdk-contracts.js";import{L as m,Lt as h,Ot as ee,St as te,a as ne,i as re,r as ie,w as ae,wt as oe,x as g}from"./version.js";import{$t as _,Ln as se,St as ce,Wt as le,Xt as ue,Yt as de,Zt as fe,dt as pe,ht as v,in as me,jn as he,jt as ge,ln as _e,nn as ve,on as ye,pn as be,pt as xe,wt as Se}from"./sdk-batch-runner.js";import{$ as Ce,A as we,B as Te,D as Ee,E as De,F as Oe,I as ke,L as Ae,M as je,N as y,O as Me,P as Ne,Q as Pe,R as Fe,T as Ie,U as Le,X as Re,_ as ze,b as Be,ct as Ve,d as He,et as Ue,f as We,g as Ge,gn as b,h as Ke,k as qe,lt as x,m as Je,ot as S,p as Ye,rn as Xe,st as C,tt as Ze,u as Qe,ut as w,v as $e,w as et,y as tt,z as nt}from"./prepare-kind.js";import{A as rt}from"./screenshot-result.js";import{f as it,p as at}from"./device.js";import{j as ot}from"./sdk-android-adb.js";import T from"node:path";import st,{promises as E}from"node:fs";import{fileURLToPath as ct}from"node:url";import{Worker as lt}from"node:worker_threads";const ut=/\b(logbox|redbox|reload js|copy stack|component stack|call stack|runtime error|open debugger to view warnings)\b/,dt=[/\b[\w.$<>/-]+\.(?:tsx?|jsx?):\d+(?::\d+)?\b/,/\b[\w.$<>/-]+\.(?:tsx?|jsx?)\s+\(\d+:\d+\)/],ft=[/^!,\s+/,/^(warn|warning|error):\s+/,/\b(?:possible\s+)?unhandled (?:promise )?rejection\b/],pt=[`open debugger to view warnings`,`getsnapshot should be cached to avoid an infinite loop`,`unique "key" prop`,`unique 'key' prop`,`virtualizedlists should never be nested`,`failed prop type`],mt=new Set([`x`,`×`,`✕`,`✖`,`⨯`]);function ht(e){if(gt(e).detected)return[`Hint: React Native warning/error overlay detected. It overlays part of the app and should be handled before interacting.`,`Run: agent-device react-native dismiss-overlay`,`The command verifies the overlay is gone. Run agent-device snapshot -i afterward only when you need fresh refs for the next action.`].join(`
|
|
2
|
+
`)}function gt(e){let t=yt(e),n=t.detected?bt(t):null;return{detected:t.detected,dismissNodes:t.dismissNodes,minimizeNodes:t.minimizeNodes,collapsedNodes:t.collapsedNodes,primaryAction:n}}function _t(e){return Dt(e.label?.trim())&&Lt(e.rect)}function vt(e,t){let n=e.label?.trim();return!n||!_t(e)?!1:t.some(e=>e.label?.trim()===n&&Rt(e))}function yt(e){let t=e.map(xt).join(`
|
|
3
|
+
`).toLowerCase(),n=D(e,kt),r=D(e,Nt),i=D(e,Dt,Ft),a=D(e,Ot),o=Ct(t),s=wt(t);return{dismissNodes:n,minimizeNodes:r,collapsedNodes:i,detected:Et({text:t,hasReactNativeStackFrame:o,hasOverlayControl:Tt(t,n,r),hasControllessRedBoxText:s,collapsedNodes:i,openDebuggerWarningNodes:a})}}function bt(e){let t=zt(e.dismissNodes);if(t)return Ht(t,Ut(t));let n=Wt(e.collapsedNodes.filter(It));return n?.rect?{action:`close-collapsed-banner`,point:Yt(n),rect:n.rect,ref:n.ref,label:O(n)}:null}function xt(e){return[e.label,e.value,e.identifier,e.type,e.role].filter(Boolean).join(` `)}function St(e){return ut.test(e)}function Ct(e){return dt.some(t=>t.test(e))}function wt(e){return/\buncaught\b/.test(e)&&/unable to download asset/.test(e)}function Tt(e,t,n){return t.length>0||n.length>0||/\b(reload js|copy stack)\b/.test(e)}function Et(e){return e.collapsedNodes.length>0||e.openDebuggerWarningNodes.length>0||e.hasControllessRedBoxText||e.hasOverlayControl&&(St(e.text)||e.hasReactNativeStackFrame)}function Dt(e){let t=e?.trim().toLowerCase();return t?pt.some(e=>t.includes(e))||ft.some(e=>e.test(t)):!1}function Ot(e){return e.includes(`open debugger to view warnings`)||/^!,\s+open debugger\b/.test(e)}function kt(e){return At(e)||jt(e)||Mt(e)}function At(e){return/^dismiss(?:\s*\([^)]*\))?$/i.test(e)}function jt(e){return/^close(?:\s*\([^)]*\))?$/i.test(e)}function Mt(e){return mt.has(e)}function Nt(e){return/^minimi[sz]e(?:\b|\s|\()/i.test(e)}function Pt(e){return/^!,\s+/.test(e)}function Ft(e){return!e.rect||e.rect.height<=180}function It(e){let t=O(e)?.trim().toLowerCase()??``;return(Ot(t)||Pt(t))&&Rt(e)}function Lt(e){return e?e.x<=1&&e.y<=1&&e.width>=300&&e.height>=600:!1}function Rt(e){return e.rect?e.rect.width>=120&&e.rect.height>=36&&e.rect.height<=180:!1}function D(e,t,n=()=>!0){let r=[];for(let i of e)i.ref&&n(i)&&[i.label,i.value,i.identifier].map(e=>e?.trim().toLowerCase()).filter(e=>!!e).some(e=>t(e))&&r.push(i);return r}function zt(e){return Gt(e,Vt)}function Bt(e){let t=[e.type,e.role,e.subrole].join(` `).toLowerCase();return/\b(button|menuitem|link)\b/.test(t)}function Vt(e){return[qt(Bt(e)),qt(e.hittable),-(e.rect?se(e.rect):1/0)]}function Ht(e,t){if(!e.rect)throw Error(`React Native overlay target node must have rect`);return{action:t,point:f(e.rect),rect:e.rect,ref:e.ref,label:O(e)}}function Ut(e){let t=O(e)?.trim().toLowerCase();return t&&At(t)?`dismiss`:`close`}function Wt(e){return Gt(e,Kt)}function Gt(e,t){let n=e.filter(e=>e.rect);return n.length===0?null:n.sort((e,n)=>Jt(t(n),t(e)))[0]??null}function Kt(e){return[qt(e.hittable),e.rect?.width??0,e.rect?.y??0]}function qt(e){return+(e===!0)}function Jt(e,t){for(let n=0;n<e.length;n+=1){let r=e[n]-t[n];if(r!==0)return r}return 0}function Yt(e){if(!e.rect)throw Error(`Collapsed React Native warning node must have rect`);let t=Math.min(e.rect.height,52),n=Math.min(36,Math.max(18,t*.45));return{x:Math.round(Xt(e.rect.x+e.rect.width-n,e.rect.x+1,e.rect.x+e.rect.width-1)),y:Math.round(e.rect.y+t/2)}}function Xt(e,t,n){return Math.min(n,Math.max(t,e))}function O(e){return e.label??e.value??e.identifier}function Zt(e){let t=e?.trim().split(/\s+/,1)[0];if(!t||!t.startsWith(`@`)||t.length<3)return null;let n=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(n)||/^(?:ref|node|element|el)[\w-]*$/i.test(n)?t:null}function Qt(e,t){try{let n=ct(e),r=T.extname(n)||`.js`;return[T.join(T.dirname(n),`${t}${r}`),T.join(T.dirname(n),`internal`,`${t}${r}`)].find(e=>st.existsSync(e))??null}catch{return null}}var k=class extends Error{};let A=null,$t=!1,en=!1,tn=0;const j=new Map;function nn(e){$t=!0,!en&&(en=!0,ot({level:`warn`,phase:`png_worker_unavailable`,data:{reason:e}}),process.emitWarning(`PNG worker unavailable, falling back to in-process PNG processing: ${e}`))}function rn(e){let t=j.get(e.id);t&&(j.delete(e.id),sn(),e.ok?t.resolve(e.result):t.reject(new s(o(e.error.code),e.error.message,e.error.details)))}function an(e,t){A===e&&(nn(t.message),A=null,e.terminate().catch(()=>{}),on(new k(`PNG worker failed: ${t.message}`)))}function on(e){let t=[...j.values()];j.clear();for(let n of t)n.reject(e)}function sn(){A&&(j.size>0?A.ref():A.unref())}function cn(){if($t)return null;if(A)return A;let e=Qt(import.meta.url,`png-worker`);if(!e)return nn(`worker entry module not found next to the current module`),null;try{let t=new lt(e,{execArgv:e.endsWith(`.ts`)?[`--experimental-strip-types`]:[]});return t.on(`message`,rn),t.on(`error`,e=>{an(t,e)}),t.on(`exit`,e=>{an(t,Error(`PNG worker exited with code ${e}`))}),t.unref(),A=t,t}catch(e){return nn(`failed to spawn worker: ${e instanceof Error?e.message:String(e)}`),null}}function ln(e){let t=cn();if(!t)return Promise.reject(new k(`PNG worker is unavailable`));tn+=1;let n=tn;return new Promise((r,i)=>{j.set(n,{resolve:r,reject:i}),sn();try{t.postMessage({...e,id:n})}catch(e){j.delete(n),sn(),i(new k(`failed to post job to PNG worker: ${e instanceof Error?e.message:String(e)}`))}})}async function M(e,t){try{return await ln(e)}catch(e){if(e instanceof k)return t();throw e}}function un(){cn()}async function dn(){let e=A;A=null,on(new k(`PNG worker terminated`)),e&&await e.terminate()}async function N(n,r){let i=await M({kind:`decode`,png:n,label:r},()=>{let e=t(n,r);return{kind:`decode`,width:e.width,height:e.height,data:e.data}}),o=new e.PNG({width:i.width,height:i.height});return o.data=a(i.data),o}async function P(t){return a((await M({kind:`encode`,width:t.width,height:t.height,data:t.data},()=>({kind:`encode`,png:e.PNG.sync.write(t)}))).png)}async function fn(e,r,i){let{kind:a,...o}=await M({kind:`rgb-difference`,firstPng:e,secondPng:r,label:i},()=>({kind:`rgb-difference`,...n(t(e,i),t(r,i))}));return o}async function pn(e){let{kind:t,...n}=await M({kind:`diff-pixels`,...e},()=>({kind:`diff-pixels`,...i(e)}));return{...n,diffData:a(n.diffData)}}const F=[0,187,255,255];function mn(e,t){for(let n of t)n.rect.width<4||n.rect.height<4||hn(e,n.rect)}function hn(e,t){let n=gn(t);if(n==null)return;let r=L(n.x,0,e.width-1),i=L(n.y,0,e.height-1),a=L(n.right,0,e.width-1),o=L(n.bottom,0,e.height-1);for(let t=0;t<2;t+=1){for(let n=r;n<=a;n+=1)I(e,n,i+t,F),I(e,n,o-t,F);for(let n=i;n<=o;n+=1)I(e,r+t,n,F),I(e,a-t,n,F)}}function gn(e){let t=e.x+e.width-1,n=e.y+e.height-1;return[e.x,e.y,e.width,e.height,t,n].every(Number.isFinite)?{x:e.x,y:e.y,right:t,bottom:n}:null}function I(e,t,n,r){if(t<0||t>=e.width||n<0||n>=e.height)return;let i=(n*e.width+t)*4;e.data[i]=r[0],e.data[i+1]=r[1],e.data[i+2]=r[2],e.data[i+3]=r[3]}function L(e,t,n){return Number.isFinite(e)?Math.min(Math.max(e,t),n):t}const _n=[{x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:-1,y:0},{x:1,y:0},{x:-1,y:1},{x:0,y:1},{x:1,y:1}];function vn(e){let{mask:t,width:n,height:r,hooks:i}=e,a=new Uint8Array(t.length),o=new Int32Array(t.length),s=[];for(let e=0;e<t.length;e+=1){if(!xn(t,a,e))continue;let c=0,l=bn(o,a,0,e),u=i.create(e);for(;c<l;){let e=o[c];c+=1,i.visit(u,e),l=yn({mask:t,visited:a,queue:o,queueEnd:l,width:n,height:r,pixelIndex:e})}s.push(u)}return s}function yn(e){let{mask:t,visited:n,queue:r,width:i,height:a,pixelIndex:o}=e,s=o%i,c=Math.floor(o/i),l=e.queueEnd;for(let e of _n){let o=s+e.x,u=c+e.y;if(!Sn(o,u,i,a))continue;let d=u*i+o;xn(t,n,d)&&(l=bn(r,n,l,d))}return l}function bn(e,t,n,r){return t[r]=1,e[n]=r,n+1}function xn(e,t,n){return e[n]===1&&t[n]!==1}function Sn(e,t,n,r){return e>=0&&e<n&&t>=0&&t<r}function Cn(e,t){return e.flatMap(e=>wn(e,t.baseline.width,t.baseline.height)?Tn(e,t,jn(t.baseline.height)):[e])}function wn(e,t,n){let r=e.maxX-e.minX+1;return e.maxY-e.minY+1>=An(n)&&r>=t*.35}function Tn(e,t,n){let r=kn(e,On(Dn(En(e,t.diffMask,t.baseline.width)),Math.max(1,Math.round((e.maxX-e.minX+1)*.08))),n);if(r.length<=1)return[e];let i=r.map(([n,r])=>Mn(e,n,r,t)).filter(e=>e!==null);return i.length>1?i:[e]}function En(e,t,n){let r=[];for(let i=e.minY;i<=e.maxY;i+=1){let a=0;for(let r=e.minX;r<=e.maxX;r+=1)t[i*n+r]===1&&(a+=1);r.push(a)}return r}function Dn(e){return e.map((t,n)=>{let r=0,i=0,a=Math.max(0,n-3),o=Math.min(e.length-1,n+3);for(let t=a;t<=o;t+=1)r+=e[t],i+=1;return Math.round(r/i)})}function On(e,t){let n=[],r=null;for(let i=0;i<e.length;i+=1){if(e[i]<=t){r??=i;continue}r!==null&&(i-r>=6&&n.push([r,i-1]),r=null)}return r!==null&&e.length-r>=6&&n.push([r,e.length-1]),n}function kn(e,t,n){let r=[],i=e.minY;for(let[a,o]of t){let t=e.minY+Math.round((a+o)/2);t-i+1<n||e.maxY-t<n||(r.push([i,t]),i=t+1)}return r.push([i,e.maxY]),r}function An(e){return Math.max(48,Math.round(e*.07))}function jn(e){return Math.max(24,Math.round(e*.03))}function Mn(e,t,n,r){let i=null;for(let a=t;a<=n;a+=1)for(let t=e.minX;t<=e.maxX;t+=1){let e=a*r.baseline.width+t;r.diffMask[e]===1&&(i??=Nn(t,a),Pn(i,e,t,a,r.baseline,r.current))}return i}function Nn(e,t){return{minX:e,minY:t,maxX:e,maxY:t,differentPixels:0,baselineRed:0,baselineGreen:0,baselineBlue:0,currentRed:0,currentGreen:0,currentBlue:0}}function Pn(e,t,n,r,i,a){let o=t*4;e.minX=Math.min(e.minX,n),e.minY=Math.min(e.minY,r),e.maxX=Math.max(e.maxX,n),e.maxY=Math.max(e.maxY,r),e.differentPixels+=1,e.baselineRed+=i.data[o],e.baselineGreen+=i.data[o+1],e.baselineBlue+=i.data[o+2],e.currentRed+=a.data[o],e.currentGreen+=a.data[o+1],e.currentBlue+=a.data[o+2]}const Fn=2.5;function In(e){let t=Ln(e);return Cn(t.length<=2e3?Bn(t,12):t,e).sort((e,t)=>{let n=t.differentPixels-e.differentPixels;if(n!==0)return n;let r=e.minY-t.minY;return r===0?e.minX-t.minX:r}).slice(0,8).map((t,n)=>Un(t,n+1,{width:e.baseline.width,height:e.baseline.height,totalPixels:e.totalPixels,differentPixels:e.differentPixels}))}function Ln(e){let{diffMask:t,baseline:n,current:r}=e,{width:i,height:a}=n;return vn({mask:t,width:i,height:a,hooks:{create:e=>Rn(e,i),visit:(e,t)=>zn(e,t,i,n,r)}})}function Rn(e,t){let n=e%t,r=Math.floor(e/t);return{minX:n,minY:r,maxX:n,maxY:r,differentPixels:0,baselineRed:0,baselineGreen:0,baselineBlue:0,currentRed:0,currentGreen:0,currentBlue:0}}function zn(e,t,n,r,i){let a=t%n,o=Math.floor(t/n),s=t*4;e.minX=Math.min(e.minX,a),e.minY=Math.min(e.minY,o),e.maxX=Math.max(e.maxX,a),e.maxY=Math.max(e.maxY,o),e.differentPixels+=1,e.baselineRed+=r.data[s],e.baselineGreen+=r.data[s+1],e.baselineBlue+=r.data[s+2],e.currentRed+=i.data[s],e.currentGreen+=i.data[s+1],e.currentBlue+=i.data[s+2]}function Bn(e,t){let n=[];for(let r of e.sort((e,t)=>{let n=e.minY-t.minY;return n===0?e.minX-t.minX:n})){let e=n.find(e=>Vn(e,r,t));if(!e){n.push({...r});continue}Hn(e,r)}return n}function Vn(e,t,n){return e.minX-n<=t.maxX&&t.minX-n<=e.maxX&&e.minY-n<=t.maxY&&t.minY-n<=e.maxY}function Hn(e,t){e.minX=Math.min(e.minX,t.minX),e.minY=Math.min(e.minY,t.minY),e.maxX=Math.max(e.maxX,t.maxX),e.maxY=Math.max(e.maxY,t.maxY),e.differentPixels+=t.differentPixels,e.baselineRed+=t.baselineRed,e.baselineGreen+=t.baselineGreen,e.baselineBlue+=t.baselineBlue,e.currentRed+=t.currentRed,e.currentGreen+=t.currentGreen,e.currentBlue+=t.currentBlue}function Un(e,t,n){let r={x:e.minX,y:e.minY,width:e.maxX-e.minX+1,height:e.maxY-e.minY+1},i={x:Math.round(e.minX+r.width/2),y:Math.round(e.minY+r.height/2)},a=Wn(e.baselineRed,e.baselineGreen,e.baselineBlue,e.differentPixels),o=Wn(e.currentRed,e.currentGreen,e.currentBlue,e.differentPixels),s=r.width*r.height;return{index:t,rect:r,normalizedRect:re({x:z(r.x/n.width),y:z(r.y/n.height),width:z(r.width/n.width),height:z(r.height/n.height)}),differentPixels:e.differentPixels,shareOfDiffPercentage:z(e.differentPixels/n.differentPixels),densityPercentage:z(e.differentPixels/s),shape:qn(r,n.width,n.height),size:Jn(s,n.totalPixels),location:Gn(i,n.width,n.height),averageBaselineColorHex:Yn(a),averageCurrentColorHex:Yn(o),baselineLuminance:Math.round(R(a)),currentLuminance:Math.round(R(o)),dominantChange:Kn(a,o)}}function Wn(e,t,n,r){return{r:Math.round(e/r),g:Math.round(t/r),b:Math.round(n/r)}}function Gn(e,t,n){let r=e.x<t/3?`left`:e.x>t*2/3?`right`:`center`,i=e.y<n/3?`top`:e.y>n*2/3?`bottom`:`middle`;return r===`center`&&i===`middle`?`center`:`${i}-${r}`}function Kn(e,t){let n=R(t)-R(e);return Math.abs(n)>=12?n>0?`brighter`:`darker`:Math.max(Math.abs(t.r-e.r),Math.abs(t.g-e.g),Math.abs(t.b-e.b))>=12?`color-shift`:`mixed`}function qn(e,t,n){return e.width>=t*.55&&e.height>=n*.12?`large-area`:e.width>=e.height*Fn?`horizontal-band`:e.height>=e.width*Fn?`vertical-band`:`compact`}function Jn(e,t){let n=e/t;return n>=.04?`large`:n>=.01?`medium`:`small`}function R(e){return e.r*.2126+e.g*.7152+e.b*.0722}function Yn(e){return`#${Xn(e.r)}${Xn(e.g)}${Xn(e.b)}`}function Xn(e){return e.toString(16).padStart(2,`0`)}function z(e){return Math.round(e*100*100)/100}const Zn=255*Math.sqrt(3);async function Qn(t,n,r={}){await $n(t,`Baseline image not found`),await $n(n,`Current screenshot not found`);let i=r.outputPath,[a,o]=await Promise.all([E.readFile(t),E.readFile(n)]),[s,c]=await Promise.all([N(a,`baseline screenshot`),N(o,`current screenshot`)]);er(s.width,s.height,`baseline screenshot`,r.maxPixels),er(c.width,c.height,`current screenshot`,r.maxPixels);let l=r.threshold??.1;if(s.width!==c.width||s.height!==c.height){let e=s.width*s.height;return await tr(r.outputPath),{match:!1,mismatchPercentage:100,totalPixels:e,differentPixels:e,dimensionMismatch:{expected:{width:s.width,height:s.height},actual:{width:c.width,height:c.height}}}}let u=s.width*s.height,d=l*Zn,{diffData:f,diffMask:p,differentPixels:m}=await pn({baselineData:s.data,currentData:c.data,width:s.width,height:s.height,maxColorDistance:d}),h=m>0?In({diffMask:p,baseline:s,current:c,totalPixels:u,differentPixels:m}):[];if(m>0&&i){let t=new e.PNG({width:s.width,height:s.height});t.data=f,mn(t,h),await E.mkdir(T.dirname(i),{recursive:!0}),await E.writeFile(i,await P(t))}else await tr(r.outputPath);let ee=u>0?Math.round(m/u*100*100)/100:0;return{...m>0&&i?{diffPath:i}:{},...h.length>0?{regions:h}:{},totalPixels:u,differentPixels:m,mismatchPercentage:ee,match:m===0}}async function $n(e,t){try{await E.access(e)}catch{throw new s(`INVALID_ARGS`,`${t}: ${e}`)}}function er(e,t,n,r){if(r==null||r<=0)return;let i=e*t;if(!(i<=r))throw new s(`INVALID_ARGS`,`${n} is ${i} pixels, which exceeds the configured maxImagePixels limit of ${r}`)}async function tr(e){if(e)try{await E.unlink(e)}catch(e){if(!nr(e,`ENOENT`))throw e}}function nr(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}function rr(e,t){return e.map(e=>{let n=ir(e,t);return n.length>0?{...e,currentOverlayMatches:n}:e})}function ir(e,t){let n=ar(e.rect);return t.map(t=>{let r=t.overlayRect,i=ie(e.rect,r);return i<=0?null:{ref:t.ref,...t.label?{label:t.label}:{},rect:r,overlayCoveragePercentage:or(i/ar(r)),regionCoveragePercentage:or(i/n)}}).filter(e=>e!==null).sort((e,t)=>{let n=t.regionCoveragePercentage-e.regionCoveragePercentage;return n===0?t.overlayCoveragePercentage-e.overlayCoveragePercentage:n}).slice(0,3).map(e=>({ref:e.ref,...e.label?{label:e.label}:{},rect:e.rect,regionCoveragePercentage:e.regionCoveragePercentage}))}function ar(e){return e.width*e.height}function or(e){return Math.round(e*100*100)/100}async function B(e,t,n){if(t.kind===`path`&&!e.policy.allowLocalInputPaths)throw new s(`INVALID_ARGS`,`Local ${n.field??`input`} paths are not allowed by command policy`);try{return await e.artifacts.resolveInput(t,n)}catch(e){throw p(e)}}async function V(e,t,n){if(t?.kind===`path`&&!e.policy.allowLocalOutputPaths)throw new s(`INVALID_ARGS`,`Local output paths are not allowed by command policy`);try{return await e.artifacts.reserveOutput(t,{...n,visibility:n.visibility??`client-visible`,requestedClientPath:t?.kind===`downloadableArtifact`?t.clientPath??n.requestedClientPath:n.requestedClientPath})}catch(e){throw p(e)}}async function sr(e,t){try{return await e.artifacts.createTempFile(t)}catch(e){throw p(e)}}const cr=async(e,t)=>{if(!t.baseline)throw new s(`INVALID_ARGS`,`diff screenshot requires a baseline image`);let n=lr(t.threshold),r=t.current??{kind:`live`};if(t.overlayRefs&&!gr(r))throw new s(`INVALID_ARGS`,`diff screenshot <current.png> cannot use --overlay-refs because saved-image comparisons have no live accessibility refs`);let i=await B(e,t.baseline,{usage:`diff screenshot baseline`,field:`baseline`}),a,o,c,l=[];try{let s;gr(r)?(o=await ur(e,t),s=o.path):(a=await B(e,r,{usage:`diff screenshot current`,field:`current`}),s=a.path),c=t.out?await V(e,t.out,{field:`diffPath`,ext:`.png`,artifactType:`screenshot-diff`}):void 0;let u=await Qn(i.path,s,{threshold:n,outputPath:c?.path,maxPixels:e.policy.maxImagePixels});gr(r)&&(u=await dr(e,t,c?.path,u,l));let d=u.diffPath?await c?.publish():void 0;return d&&l.push(d),u.diffPath||await c?.cleanup?.(),{...u,...l.length>0?{artifacts:l}:{}}}catch(e){throw await c?.cleanup?.(),e}finally{await i.cleanup?.(),await a?.cleanup?.(),await o?.cleanup?.()}};function lr(e){if(e==null||e===``)return .1;let t=Number(e);if(Number.isNaN(t)||t<0||t>1)throw new s(`INVALID_ARGS`,`--threshold must be a number between 0 and 1`);return t}async function ur(e,t){let n=await sr(e,{prefix:`agent-device-diff-current`,ext:`.png`});try{await fr(e,t,n.path,pr(t))}catch(e){throw await n.cleanup(),e}return n}async function dr(e,t,n,r,i){if(!t.overlayRefs)return r;if(r.match||r.dimensionMismatch)return n&&await hr(n),r;let a=await V(e,mr(t,n),{field:`currentOverlayPath`,ext:`.png`,artifactType:`screenshot`});try{let n=await fr(e,t,a.path,{overlayRefs:!0,...pr(t)}),o=await a.publish();return o&&i.push(o),{...r,currentOverlayPath:n.path??a.path,...n.overlayRefs?{currentOverlayRefCount:n.overlayRefs.length}:{},...r.regions&&n.overlayRefs?{regions:rr(r.regions,n.overlayRefs)}:{}}}catch(e){throw await a.cleanup?.(),e}}async function fr(e,t,n,r={}){if(!e.backend.captureScreenshot)throw new s(`UNSUPPORTED_OPERATION`,`screenshot is not supported by this backend`);return await e.backend.captureScreenshot({session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata},n,r)??{}}function pr(e){return{normalizeStatusBar:e.normalizeStatusBar??!0,...e.surface?{surface:e.surface}:{}}}function mr(e,t){if(e.currentOverlayOut)return e.currentOverlayOut;if(e.out?.kind===`path`)return{kind:`path`,path:H(t??e.out.path)};if(e.out?.kind===`downloadableArtifact`)return{kind:`downloadableArtifact`,...e.out.clientPath?{clientPath:H(e.out.clientPath)}:{},...e.out.fileName?{fileName:H(e.out.fileName)}:{}}}function H(e){let t=T.extname(e);return`${t?e.slice(0,-t.length):e}.current-overlay${t||`.png`}`}async function hr(e){try{await E.unlink(H(e))}catch(e){if(!_r(e,`ENOENT`))throw e}}function gr(e){return e.kind===`live`}function _r(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}async function vr(e,t){let{min:n,max:r}=ee;if(!Number.isFinite(t)||t<n||t>r)throw new s(`INVALID_ARGS`,`Screenshot scale must be between ${n} and ${r}`);if(t===1)return;let i=await N(await E.readFile(e),`screenshot`),a=Math.max(1,Math.round(i.width*t)),o=Math.max(1,Math.round(i.height*t));await E.writeFile(e,await P(br(i,a,o)))}async function yr(e,t,n){if(!Number.isInteger(t)||t<1||!Number.isInteger(n)||n<1)throw new s(`INVALID_ARGS`,`Screenshot resize dimensions must be positive integers`);let r=await N(await E.readFile(e),`screenshot`);r.width===t&&r.height===n||await E.writeFile(e,await P(br(r,t,n)))}function br(t,n,r){let i=new e.PNG({width:n,height:r});for(let e=0;e<r;e+=1){let a=e*t.height/r,o=(e+1)*t.height/r;for(let r=0;r<n;r+=1){let s=r*t.width/n,c=(r+1)*t.width/n,l=0,u=0,d=0,f=0,p=0;for(let e=Math.floor(a);e<Math.ceil(o);e+=1){let n=Math.min(e+1,o)-Math.max(e,a);for(let r=Math.floor(s);r<Math.ceil(c);r+=1){let i=n*(Math.min(r+1,c)-Math.max(r,s)),a=(e*t.width+r)*4;l+=(t.data[a]??0)*i,u+=(t.data[a+1]??0)*i,d+=(t.data[a+2]??0)*i,f+=(t.data[a+3]??0)*i,p+=i}}let m=(e*i.width+r)*4;i.data[m]=Math.round(l/p),i.data[m+1]=Math.round(u/p),i.data[m+2]=Math.round(d/p),i.data[m+3]=Math.round(f/p)}}return i}const xr=async(e,t)=>{if(!e.backend.captureScreenshot)throw new s(`UNSUPPORTED_OPERATION`,`screenshot is not supported by this backend`);h(t);let n=await V(e,t.out,{field:`path`,ext:`.png`,artifactType:`screenshot`}),r;try{await e.backend.captureScreenshot({session:t.session,requestId:t.requestId,appId:t.appId,appBundleId:t.appBundleId,signal:t.signal??e.signal,metadata:t.metadata},n.path,{fullscreen:t.fullscreen,overlayRefs:t.overlayRefs,pixelDensity:t.pixelDensity,stabilize:t.stabilize,normalizeStatusBar:t.normalizeStatusBar,surface:t.surface}),t.scale!==void 0&&await vr(n.path,t.scale),r=await n.publish()}catch(e){throw await n.cleanup?.(),e}return{path:n.path,...r?{artifacts:[r]}:{},...b(`Saved screenshot: ${n.path}`)}};function Sr(e){let{nodes:t,backend:n,snapshotRaw:r}=e;if(r||!l(n))return{partial:!1,visibleNodeCount:t.length,totalNodeCount:t.length,reasons:[]};let i=ne(t),a=new Set;return i.hiddenCount>0&&a.add(`offscreen-nodes`),i.nodes.some(e=>e.hiddenContentAbove)&&a.add(`scroll-hidden-above`),i.nodes.some(e=>e.hiddenContentBelow)&&a.add(`scroll-hidden-below`),{partial:a.size>0,visibleNodeCount:i.nodes.length,totalNodeCount:t.length,reasons:[...a]}}const Cr=`A system surface (notification shade, quick settings, or another system overlay) covers the app, so this snapshot shows that surface. Interact with it or dismiss it (press back or swipe up) to reach app content.`;function wr(e){return e?.systemSurfaceOnly===!0?Cr:void 0}function Tr(e,t){return e.presentationKey?e:{...e,presentationKey:u(t)}}function Er(e){let{previous:t,current:n,options:r,identity:i}=e;if(r.forceFull===!0||r.raw===!0||!t||t.comparisonSafe===!1||n.comparisonSafe===!1||!Dr(t,n,i)||!t.presentationKey||t.presentationKey!==n.presentationKey||!Or(t,n))return;let a=r.scope?.trim();return{ageMs:Math.max(0,n.createdAt-t.createdAt),nodeCount:n.nodes.length,...r.interactiveOnly===!0?{interactiveOnly:!0}:{},...a?{scope:a}:{}}}function Dr(e,t,n){return!(e.backend&&t.backend&&e.backend!==t.backend||n?.previousAppBundleId&&n.currentAppBundleId&&n.previousAppBundleId!==n.currentAppBundleId)}function Or(e,t){return e.truncated===t.truncated?JSON.stringify(kr(e.nodes))===JSON.stringify(kr(t.nodes)):!1}function kr(e){return e.map(e=>({index:e.index,depth:e.depth,parentIndex:e.parentIndex,type:e.type,role:e.role,subrole:e.subrole,label:e.label,value:e.value,identifier:e.identifier,enabled:e.enabled,selected:e.selected,focused:e.focused,hittable:e.hittable,rect:e.rect,bundleId:e.bundleId,appName:e.appName,windowTitle:e.windowTitle,surface:e.surface,hiddenContentAbove:e.hiddenContentAbove,hiddenContentBelow:e.hiddenContentBelow,interactionBlocked:e.interactionBlocked,presentationHints:e.presentationHints,actions:e.actions}))}const Ar=async(e,t)=>{let n=await Mr(e,t),r=Er({previous:n.session?.snapshot,current:n.snapshot,options:t,identity:{previousAppBundleId:n.session?.appBundleId,currentAppBundleId:n.result.appBundleId??n.session?.appBundleId}});return await e.sessions.set(Pr(t.session,n)),{nodes:n.snapshot.nodes,truncated:n.snapshot.truncated??!1,visibility:Sr({nodes:n.snapshot.nodes,backend:n.snapshot.backend,snapshotRaw:t.raw}),...te({...n.annotations,warnings:n.warnings}),...r?{unchanged:r}:{},...n.result.snapshotDiagnostics?{snapshotDiagnostics:n.result.snapshotDiagnostics}:{},...Fr(n)}},jr=async(e,t)=>{let n=await Mr(e,t),r=t.interactiveOnly===!0,i=n.session?.snapshot,a=Pr(t.session,n);if(!i){let t=Ie(n.snapshot.nodes,{flatten:r});return await e.sessions.set(a),{mode:`snapshot`,baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:t},lines:[],...n.warnings.length>0?{warnings:n.warnings}:{}}}let o=et(i.nodes,n.snapshot.nodes,{flatten:r});return await e.sessions.set(a),{mode:`snapshot`,baselineInitialized:!1,summary:o.summary,lines:o.lines,...n.warnings.length>0?{warnings:n.warnings}:{}}};async function Mr(e,t){if(!e.backend.captureSnapshot)throw new s(`UNSUPPORTED_OPERATION`,`snapshot is not supported by this backend`);let n=t.session??`default`,r=await e.sessions.get(n),i=await e.backend.captureSnapshot({session:n,requestId:t.requestId,appId:r?.appId,appBundleId:r?.appBundleId,signal:t.signal??e.signal,metadata:t.metadata},{interactiveOnly:t.interactiveOnly,depth:t.depth,scope:t.scope,raw:t.raw,customActions:t.customActions}),a=Tr(Nr(i,e),t),o=oe(i),c=Ve(e);return{snapshot:a,result:i,session:r,annotations:o,warnings:Ir({result:i,annotations:o,snapshot:a,options:t,session:r,capturedAt:a.createdAt??c,runtimeNow:c})}}function Nr(e,t){return e.snapshot?e.snapshot:{nodes:e.nodes??[],truncated:e.truncated,backend:e.backend,createdAt:Ve(t)}}function Pr(e,t){let n=t.session?.name??e??`default`;return{...t.session??{name:n},name:n,snapshot:t.snapshot,appName:t.result.appName??t.session?.appName,appBundleId:t.result.appBundleId??t.session?.appBundleId}}function Fr(e){let t=e.result.appName??e.session?.appName,n=e.result.appBundleId??e.session?.appBundleId;return{...t||n?{appName:t??n}:{},...n?{appBundleId:n}:{}}}function Ir(e){let t=[...e.annotations.warnings??[]];e.annotations.quality&&t.push(...Le(e.annotations.quality,e.snapshot.nodes)),t.push(...Br(e)),e.annotations.quality||(t.push(...Rr(e)),t.push(...zr(e.snapshot.nodes)));let n=ht(e.snapshot.nodes);n&&t.push(n);let r=Lr(e.annotations);r&&t.push(r);let i=Vr(e);return i&&t.push(i),t.push(...Gr(e.annotations.freshness,e.snapshot.backend)),Array.from(new Set(t))}function Lr(e){if(e.androidSnapshot?.systemSurfaceOnly===!0)return Cr}function Rr(e){return e.snapshot.backend!==`xctest`||e.options.interactiveOnly!==!0||e.snapshot.nodes.length!==1||e.snapshot.nodes[0]?.type!==`Application`?[]:[`iOS interactive snapshot exposed only the application root. XCTest accessibility queries can fail to enumerate some simulator UI trees even when screenshots and direct gestures still work. Use screenshot as visual truth, try a scoped/full snapshot for diagnostics, and prefer direct selectors when known.`]}function zr(e){let t=new Set(e.map(e=>e.parentIndex).filter(e=>e!==void 0));return e.filter(e=>t.has(e.index)||(e.type?.toLowerCase()??``).includes(`text`)?!1:(e.label??``).split(`, `).length>10).map(e=>{let t=(e.label??``).split(`, `).length,n=e.identifier?` (${e.identifier})`:``;return`@${e.ref} [${e.type??`element`}]${n} merges ~${t} labels into a single accessibility element. The app likely marks a container as accessible, which hides every descendant from assistive tech and automation — the children cannot be addressed individually. Fix the app's accessibility (mark the rows, not the container); until then use screenshot as visual truth and coordinate taps.`})}function Br(e){let t=e.annotations.analysis;if(e.snapshot.backend!==`android`||e.options.interactiveOnly!==!0||e.snapshot.nodes.length>0||!t||(t.rawNodeCount??0)<12)return[];let n=[`Interactive snapshot is empty after filtering ${t.rawNodeCount} raw Android nodes. Likely causes: the app content is not accessibility-visible yet, a transient route change, or depth/filter options hid the target.`];return typeof e.options.depth==`number`&&typeof t.maxDepth==`number`&&t.maxDepth>=e.options.depth+2&&n.push(`Interactive output is empty at depth ${e.options.depth}; retry without -d.`),n}function Vr(e){let t=e.session?.snapshot;if(!e.annotations.freshness&&t&&Hr(t,e.snapshot)&&Ur(t,e.capturedAt,e.runtimeNow)&&Kr(t.nodes.length,e.snapshot.nodes.length))return Wr}function Hr(e,t){return e.presentationKey===void 0||t.presentationKey===void 0?!0:e.presentationKey===t.presentationKey}function Ur(e,t,n){return[t,n].some(t=>{let n=t-e.createdAt;return n>=0&&n<=2e3})}const Wr=`Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once.`;function Gr(e,t){return!e?.staleAfterRetries||t!==`android`?[]:e.reason===`stuck-route`?[`Recent ${e.action} was followed by a nearly identical snapshot after ${e.retryCount} automatic retr${e.retryCount===1?`y`:`ies`}. If you expected navigation or submit, the tree may still be stale. Use screenshot as visual truth, wait briefly, then re-snapshot once.`]:e.reason===`sharp-drop`?[Wr]:[]}function Kr(e,t){return e<12?!1:t<=Math.floor(e*.2)}const qr={screenshot:xr,diffScreenshot:cr,snapshot:Ar,diffSnapshot:jr},Jr=new WeakMap;function Yr(e,t){Zr(e)&&Jr.set(e,t)}function Xr(e){return Zr(e)?Jr.get(e):void 0}function Zr(e){return typeof e==`object`&&!!e||typeof e==`function`}const Qr=async(e,t)=>await ni(e,t,`press`),$r=async(e,t)=>await ni(e,t,`click`),ei=async(e,t)=>{if(!t.text)throw new s(`INVALID_ARGS`,`fill requires text`);let n=Ge(t),r=n.needsPreActionBaseline?null:await ai(e,t);if(r)return r;let i=await we(e,t,{action:`fill`,requireInteractive:!0,promoteToHittableAncestor:!1,captureEvidenceBaseline:n.needsPreActionBaseline,expectedResolvedTarget:t.expectedResolvedTarget,preresolvedTarget:t.preresolvedTarget});if(!e.backend.fill)throw new s(`UNSUPPORTED_OPERATION`,`fill is not supported by this backend`);let a=ri(i),o=`node`in i?i.node?.type??``:``,c=o!==``&&he(o,e.backend.platform),l=t.allowNonHittableCoordinateFallback===!0&&`node`in i&&i.node?.hittable===!1,u=C(await e.backend.fill(x(e,t),a,t.text,{delayMs:t.delayMs,allowNonHittableCoordinateFallback:l})),d=o&&!c?`fill target ${si(i)} resolved to "${o}", attempting fill anyway.`:void 0;return await Ke(e,t,i,{...i,text:t.text,...d?{warning:d}:{},...u?{backendResult:u}:{}},n)},ti=async(e,t)=>{let n=t.text;if(!n)throw new s(`INVALID_ARGS`,`type requires text`);let r=ci(n);if(r)throw new s(`INVALID_ARGS`,`type does not accept a target ref like "${r}"`,{hint:`Use fill ${r} "text" to target that field, or press ${r} then type "text" to append.`});if(!e.backend.typeText)throw new s(`UNSUPPORTED_OPERATION`,`type is not supported by this backend`);let i=w(t.delayMs??0,`delay-ms`,0,1e4),a=C(await e.backend.typeText(x(e,t),n,{delayMs:i}));return{kind:`text`,text:n,delayMs:i,...a?{backendResult:a}:{},...b(`Typed ${Array.from(n).length} chars`)}};async function ni(e,t,n){let r=Ge(t),i=r.needsPreActionBaseline?null:await ii(e,t,n);if(i)return i;let a=await we(e,t,{action:n,requireInteractive:!0,promoteToHittableAncestor:!0,captureEvidenceBaseline:r.needsPreActionBaseline,expectedResolvedTarget:t.expectedResolvedTarget,preresolvedTarget:t.preresolvedTarget});if(!e.backend.tap)throw new s(`UNSUPPORTED_OPERATION`,`tap is not supported by this backend`);let o=ri(a),c;try{c=await e.backend.tap(x(e,t),o,{button:t.button,count:t.count,intervalMs:t.intervalMs,holdMs:t.holdMs,jitterPx:t.jitterPx,doubleTap:t.doubleTap})}catch(e){throw Yr(e,a),e}let l=C(c);return await Ke(e,t,a,{...a,...l?{backendResult:l}:{}},r)}function ri(e){if(!e.point)throw new s(`COMMAND_FAILED`,`Interaction target resolved without coordinates`);return e.point}async function ii(e,t,n){if(n!==`click`||t.target.kind!==`ref`||!e.backend.tapTarget||oi(t)||t.expectedResolvedTarget)return null;let r=await qe(e,t,t.target,n),i=C(await e.backend.tapTarget(x(e,t),{kind:`ref`,ref:t.target.ref,...t.target.fallbackLabel?{fallbackLabel:t.target.fallbackLabel}:{}}));return{kind:`ref`,target:{kind:`ref`,ref:t.target.ref},resolution:De,...r,...i?{backendResult:i}:{}}}async function ai(e,t){if(t.target.kind!==`ref`||!e.backend.fillTarget||t.expectedResolvedTarget)return null;let n=await qe(e,t,t.target,`fill`),r=C(await e.backend.fillTarget(x(e,t),{kind:`ref`,ref:t.target.ref,...t.target.fallbackLabel?{fallbackLabel:t.target.fallbackLabel}:{}},t.text,{delayMs:t.delayMs}));return{kind:`ref`,target:{kind:`ref`,ref:t.target.ref},text:t.text,resolution:De,...n,...r?{backendResult:r}:{}}}function oi(e){return e.count!==void 0||e.intervalMs!==void 0||e.holdMs!==void 0||e.jitterPx!==void 0||e.doubleTap!==void 0||e.button!==void 0&&e.button!==`primary`}function si(e){return e.target?.kind===`ref`?e.target.ref:e.target?.kind===`selector`?e.target.selector:`point`}function ci(e){return Zt(e)}function U(e){return{includeRects:e===`visible`||e===`hidden`,interactiveOnly:!1}}function li(e,t,n){let r=n??1e4,i=W(e),a=mi(),o=()=>Math.max(0,r-(W(e)-i));return{capture:async n=>{let r=!1,i=await Be(e,t,o(),async e=>await a.attempt(async()=>{let t=await n(e);return r=!0,t}));return i.timedOut?{timedOut:!0,deadline:a.readableCaptures()===0?`capture-stalled`:`capture-truncated`}:(r&&a.recordReadableCapture(),i)},hasTimeRemaining:()=>o()>0,failureEvidence:()=>({timeoutMs:r,readableCaptures:a.readableCaptures(),waitedMs:W(e)-i}),rethrowIfNeverReadable:a.rethrowIfNeverReadable,sleepUntilNextPoll:async()=>await hi(e,t,Math.min(300,o())),timeoutMs:r,waitedMs:()=>W(e)-i}}function ui(e,t){return new s(`COMMAND_FAILED`,e,{reason:g.captureStalled,captureStalled:!0,...t,retriable:!0,hint:`No readable snapshot capture completed before the wait timeout. Retry, or use screenshot to inspect the current surface.`})}function di(e,t){return new s(`COMMAND_FAILED`,e,{reason:g.deadlineExceeded,captureTruncated:!0,...t})}function fi(e,t){return new s(`COMMAND_FAILED`,e,{reason:g.targetAbsent,...t})}function pi(e,t,n){let r=t.failureEvidence();return n===`capture-stalled`?ui(e,r):n===`capture-truncated`?di(e,r):(t.rethrowIfNeverReadable(),r.readableCaptures===0?ui(e,r):fi(e,r))}function mi(){let e=0,t;return{attempt:async e=>{try{return await e()}catch(e){if(!Te(e))throw e;t=e;return}},recordReadableCapture:()=>{e+=1},readableCaptures:()=>e,rethrowIfNeverReadable:()=>{if(e===0&&t!==void 0)throw t}}}function W(e){return e.clock?.now()??Date.now()}async function hi(e,t,n){let r=[t.signal,e.signal].filter(e=>e!==void 0);for(let e of r)e.throwIfAborted();if(n<=0)return!1;if(e.clock){await e.clock.sleep(n);for(let e of r)e.throwIfAborted();return!0}return await new Promise((e,t)=>{let i=r.length>0?AbortSignal.any(r):void 0,a=()=>i?.removeEventListener(`abort`,s),o=setTimeout(()=>{a(),e()},n),s=()=>{clearTimeout(o),a(),t(i?.reason)};i?.addEventListener(`abort`,s,{once:!0}),o.unref()}),!0}function gi(e){if(e.kind===`ambiguous`)return{selector:e.selector,selectorIndex:e.selectorIndex,matchedNodes:e.matchedNodes};if(e.kind===`resolved`)return{selector:e.resolution.selector,selectorIndex:e.resolution.selectorIndex,matchedNodes:e.matchedNodes}}function _i(e){let t=async(t,n)=>{if(n.target.kind===`sleep`)return await hi(t,n,n.target.durationMs),{kind:`sleep`,waitedMs:n.target.durationMs};if(n.target.kind===`ref`){let r=await e.requireSnapshot(t,n.session),i=d(n.target.ref);if(!i)throw new s(`INVALID_ARGS`,`Invalid ref: ${n.target.ref}`);let a=c(r.snapshot.nodes,i),o=a?Pe(a,r.snapshot.nodes):void 0;if(!o)throw new s(`COMMAND_FAILED`,`Ref ${n.target.ref} not found or has no label`);return await bi(e,t,n,o,n.target.timeoutMs)}if(n.target.kind===`selector`)return await vi(e,t,n,n.target.selector,n.target.timeoutMs,n.target.recordedLandmark);if(n.target.kind===`stable`)return await Si(e,t,n,n.target.quietMs,n.target.timeoutMs);let r=de(n.target.text);if(!r.ok)throw new s(r.code,r.message);return await bi(e,t,n,n.target.text,n.target.timeoutMs)};return{waitCommand:t,waitForTextCommand:async(e,n)=>{let r=await t(e,{...n,target:{kind:`text`,text:n.text,timeoutMs:n.timeoutMs}});if(r.kind!==`text`)throw new s(`COMMAND_FAILED`,`waitForText returned non-text result`);return r}}}async function vi(e,t,n,r,i,a){let o=li(t,n,i),c=U(),l,u;for(;o.hasTimeRemaining();){let i=await o.capture(async r=>await e.captureSnapshot(t,{...n,signal:r},{updateSession:!0,includeHiddenContentHints:!1,...c}));if(i.timedOut){u=i.deadline;break}let s=i.value;if(s){let e=s.snapshot.nodes,n=gi(v(e,r,_.wait,{platform:t.backend.platform}));if(n){let t=yi(e,n,a);if(t.kind===`satisfied`)return{kind:`selector`,selector:n.selector,waitedMs:o.waitedMs(),node:t.node,preActionNodes:e};l=t.evidence}}await o.sleepUntilNextPoll()}throw u!==`capture-stalled`&&l?new s(`COMMAND_FAILED`,`wait matched selector ${r} but no candidate carried the recorded landmark identity`,{reason:je,...l}):pi(`wait timed out for selector: ${r}`,o,u)}function yi(e,t,n){let r=t.matchedNodes[0];if(!n)return{kind:`satisfied`,node:r};let i=Ue(e),a=Ze(t.matchedNodes,i,Se(n),n.ancestry)[0];return a?{kind:`satisfied`,node:a}:{kind:`identity-mismatch`,evidence:{matchCount:t.matchedNodes.length,observed:ge(r),observedAncestry:Ce(r,i,Math.max(n.ancestry.length,1)).chain}}}async function bi(e,t,n,r,i){let a=li(t,n,i),o;for(;a.hasTimeRemaining();){let i=await a.capture(async i=>t.backend.findText?(await t.backend.findText(Ci(t,{...n,signal:i}),r)).found:await xi(e,t,{...n,signal:i},r));if(i.timedOut){o=i.deadline;break}if(i.value)return{kind:`text`,text:r,waitedMs:a.waitedMs()};await a.sleepUntilNextPoll()}throw pi(`wait timed out for text: ${r}`,a,o)}async function xi(e,t,n,r){return!!Re((await e.captureSnapshot(t,n,{updateSession:!0,includeHiddenContentHints:!1})).snapshot.nodes,r)}async function Si(e,t,n,r,i){let a=i??1e4,o=r??e.stable.defaultQuietMs,c=await e.stable.capture(t,n,{quietMs:o,timeoutMs:a});if(!c.settled)throw new s(`COMMAND_FAILED`,`wait timed out waiting for a stable UI`,{reason:g.stableTimeout,...c.stalled?{captureStalled:!0}:{},quietMs:o,timeoutMs:a,captures:c.captures,nodeCount:c.nodeCount,...c.stalled?{hint:`A snapshot capture stalled past the wait timeout, so no settle verdict is available. The UI may still be readable: retry, or use screenshot to inspect the surface.`}:{}});return{kind:`stable`,waitedMs:c.waitedMs,captures:c.captures,nodeCount:c.nodeCount,...c.nodeCount<e.stable.tinyTreeNodeCount?{hint:e.stable.tinyTreeHint}:{}}}function Ci(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}const wi=_i({captureSnapshot:y,requireSnapshot:Oe,stable:{defaultQuietMs:500,tinyTreeHint:$e,tinyTreeNodeCount:5,capture:tt}}),Ti=wi.waitCommand,Ei=wi.waitForTextCommand,Di=async(e,t)=>{let n=t.locator??`any`;if(!t.query)throw new s(`INVALID_ARGS`,ye);if(t.action===`wait`)return await Pi(e,t,n);if(t.action===`list`)return await Fi(e,t,n);let{capture:r,match:i}=await Ii(e,t,n);if(!i)throw new s(`COMMAND_FAILED`,`find did not match any element`);if(t.action===`exists`)return{kind:`found`,found:!0};let a=`@${i.ref}`;return t.action===`get_attrs`?{kind:`attrs`,ref:a,node:i}:{kind:`text`,ref:a,text:await Ne(e,r,i),node:i}},Oi=async(e,t)=>{if(t.target.kind===`ref`){let n=await Oe(e,t.session),r=ke(n.snapshot.nodes,t.target.ref,{fallbackLabel:t.target.fallbackLabel??``,invalidRefMessage:`get text requires a ref like @e2`,notFoundMessage:`Ref ${t.target.ref} not found`});Ee(r.node,n.snapshot.nodes,t.expectedResolvedTarget,`get`);let i=ce(r.node,e.backend.platform,{action:`get`,nodes:n.snapshot.nodes}),a={kind:`ref`,ref:`@${r.ref}`},o=n.snapshot.nodes;return t.property===`attrs`?{kind:`attrs`,target:a,node:r.node,selectorChain:i,preActionNodes:o}:{kind:`text`,target:a,text:await Ne(e,n,r.node),node:r.node,selectorChain:i,preActionNodes:o}}let n=await Li(e,t,t.session??`default`,{selector:t.target.selector,policy:t.property===`text`?_.readText:_.readUnique});Ee(n.node,n.capture.snapshot.nodes,t.expectedResolvedTarget,`get`);let r=ce(n.node,e.backend.platform,{action:`get`,nodes:n.capture.snapshot.nodes});if(t.property===`attrs`)return{kind:`attrs`,target:{kind:`selector`,selector:n.selector},node:n.node,selectorChain:r,preActionNodes:n.capture.snapshot.nodes};let i=await Ne(e,n.capture,n.node);return{kind:`text`,target:{kind:`selector`,selector:n.selector},text:i,node:n.node,selectorChain:r,preActionNodes:n.capture.snapshot.nodes}},ki=async(e,t)=>{let n=await Oi(e,{...t,property:`text`,target:t.target});if(n.kind!==`text`)throw new s(`COMMAND_FAILED`,`getText returned non-text result`);return n},Ai=async(e,t)=>{let n=await Oi(e,{...t,property:`attrs`,target:t.target});if(n.kind!==`attrs`)throw new s(`COMMAND_FAILED`,`getAttrs returned non-attrs result`);return n},ji=async(e,t)=>{let n=ue(t.predicate);if(!n.ok)throw new s(n.code,n.message,{hint:n.hint});let r=n.predicate;if(r===`text`&&!t.expectedText)throw new s(`INVALID_ARGS`,le);let i=t.selector,a=await y(e,t,{updateSession:!0,...U(r)});if(r===`exists`){let t=v(a.snapshot.nodes,i,_.readAny,{platform:e.backend.platform});if(t.kind!==`resolved`)throw new s(`COMMAND_FAILED`,ve(i,[],{unique:!1}),{hint:me([])});return{predicate:r,pass:!0,selector:t.resolution.selector,matches:t.resolution.matches,selectorChain:xe(i)}}let o=v(a.snapshot.nodes,i,_.readUnique,{platform:e.backend.platform});if(o.kind!==`resolved`)throw new s(`COMMAND_FAILED`,ve(i,[],{unique:!0}),{command:`is`,reason:`selector_not_found`,predicate:r,selector:i,hint:me([])});let c=o.resolution;Ee(c.node,a.snapshot.nodes,t.expectedResolvedTarget,`is`);let l=fe({predicate:r,node:c.node,nodes:a.snapshot.nodes,expectedText:t.expectedText,platform:e.backend.platform});if(!l.pass)throw new s(`COMMAND_FAILED`,`is ${r} failed for selector ${c.selector}: ${l.details}`,{command:`is`,reason:`predicate_failed`,predicate:r,selector:c.selector,predicateDetails:l.details});return{predicate:r,pass:!0,selector:c.selector,...r===`text`?{text:l.actualText}:{},selectorChain:xe(i),node:c.node,preActionNodes:a.snapshot.nodes}},Mi=async(e,t)=>await ji(e,{...t,predicate:`visible`,selector:t.target.selector}),Ni=async(e,t)=>await ji(e,{...t,predicate:`hidden`,selector:t.target.selector});async function Pi(e,t,n){let r=li(e,t,t.timeoutMs),i;for(;r.hasTimeRemaining();){let a=await r.capture(async r=>await Ii(e,{...t,signal:r},n,{includeHiddenContentHints:!1}));if(a.timedOut){i=a.deadline;break}if(a.value?.match)return{kind:`found`,found:!0,waitedMs:r.waitedMs()};await r.sleepUntilNextPoll()}throw pi(`find wait timed out`,r,i)}async function Fi(e,t,n){let r=be(n,t.query),i=await y(e,t,{updateSession:!0,...U()});if(nt(i.snapshot.snapshotQuality))throw Fe(i.snapshot.snapshotQuality);return{kind:`list`,matches:(r?pe(i.snapshot.nodes,r,{platform:e.backend.platform})?.matchedNodes??[]:_e(i.snapshot.nodes,n,t.query,{}).matches).map(e=>({ref:`@${e.ref}`,node:e}))}}async function Ii(e,t,n,r){let i=be(n,t.query),a=await y(e,t,{updateSession:!0,scope:Ae(e.backend.platform,n,t.query,i),includeHiddenContentHints:r?.includeHiddenContentHints,...U()});if(nt(a.snapshot.snapshotQuality))throw Fe(a.snapshot.snapshotQuality);if(i){let t=v(a.snapshot.nodes,i,_.readAny,{platform:e.backend.platform});return{capture:a,match:t.kind===`resolved`?t.resolution.node:void 0}}return{capture:a,match:_e(a.snapshot.nodes,n,t.query,{requireRect:!1}).matches[0]}}async function Li(e,t,n,r){let i=await y(e,{...t,session:n},{updateSession:!0,...U()}),a=v(i.snapshot.nodes,r.selector,r.policy,{platform:e.backend.platform});if(a.kind!==`resolved`)throw new s(`COMMAND_FAILED`,ve(r.selector,[],{unique:!0}),{hint:me([])});return{capture:i,node:a.resolution.node,selector:a.resolution.selector,ref:`@${a.resolution.node.ref}`}}const Ri=async(e,t)=>{if(!e.backend.performGesture)throw new s(`UNSUPPORTED_OPERATION`,`gesture is not supported by this backend`);await Me(e,t,t.gesture.intent);let n=await Ye(e,t),r=m(t.gesture,n,e.backend.platform),i=C(await e.backend.performGesture(x(e,t),r)),a=Bi(r.pointers,0),o=Bi(r.pointers,-1);return{kind:t.gesture.intent,durationMs:r.durationMs,pointerCount:r.topology===`single`?1:2,from:a,to:o,...i?{backendResult:i}:{},...b(Vi(t.gesture,a,o))}},zi=async(e,t)=>{let n=t.gesture;return n.intent===`drag`?await Qe(e,{...t,gesture:n}):await Ri(e,{...t,gesture:n})};function Bi(e,t){let n=e.map(e=>t===0?e.samples[0]?.point:e.samples.at(-1)?.point);if(n.some(e=>e===void 0))throw new s(`COMMAND_FAILED`,`Gesture plan did not contain endpoint samples.`);let r=n;return{x:r.reduce((e,t)=>e+t.x,0)/r.length,y:r.reduce((e,t)=>e+t.y,0)/r.length}}function Vi(e,t,n){switch(e.intent){case`pan`:{let r=`preset`in e?t:e.origin,i=`preset`in e?{x:n.x-t.x,y:n.y-t.y}:e.delta;return`Panned (${r.x}, ${r.y}) by (${i.x}, ${i.y})`}case`fling`:return`direction`in e?`Flung ${e.direction}`:`Flung`;case`pinch`:return`Pinched to scale ${e.scale}`;case`rotate`:return`Rotated gesture ${e.degrees} degrees`;case`transform`:return`Requested transform gesture by (${e.delta.x}, ${e.delta.y}), scale ${e.scale}, rotate ${e.degrees} degrees`}}const G={find:Di,get:Oi,getText:ki,getAttrs:Ai,is:ji,isVisible:Mi,isHidden:Ni,wait:Ti,waitForText:Ei},K={click:$r,press:Qr,fill:ei,typeText:ti,focus:He,longPress:We,scroll:Je,gesture:zi,settleObservation:ze};function Hi(e){return{find:t=>G.find(e,t),get:t=>G.get(e,t),getText:(t,n={})=>G.getText(e,{...n,target:t}),getAttrs:(t,n={})=>G.getAttrs(e,{...n,target:t}),is:t=>G.is(e,t),isVisible:(t,n={})=>G.isVisible(e,{...n,target:t}),isHidden:(t,n={})=>G.isHidden(e,{...n,target:t}),wait:t=>G.wait(e,t),waitForText:(t,n={})=>G.waitForText(e,{...n,text:t})}}function Ui(e){return{click:(t,n={})=>K.click(e,{...n,target:t}),press:(t,n={})=>K.press(e,{...n,target:t}),fill:(t,n,r={})=>K.fill(e,{...r,target:t,text:n}),typeText:(t,n={})=>K.typeText(e,{...n,text:t}),focus:(t,n={})=>K.focus(e,{...n,target:t}),longPress:(t,n={})=>K.longPress(e,{...n,target:t}),scroll:t=>K.scroll(e,t),gesture:t=>K.gesture(e,t),settleObservation:t=>K.settleObservation(e,t)}}function q(e,t){if(e!==void 0)return J(e,t)}function J(e,t){let n=e?.trim();if(!n)throw new s(`INVALID_ARGS`,`${t} must be a non-empty string`);return n}const Wi=async(e,t={})=>{if(!e.backend.listDevices)throw new s(`UNSUPPORTED_OPERATION`,`admin.devices is not supported by this backend`);return{kind:`adminDevices`,devices:await e.backend.listDevices(x(e,t),t.filter)}},Gi=async(e,t={})=>{if(!e.backend.bootDevice)throw new s(`UNSUPPORTED_OPERATION`,`admin.boot is not supported by this backend`);let n=ta(t.target),r=C(await e.backend.bootDevice(x(e,t),n));return{kind:`deviceBooted`,...n?{target:n}:{},...r?{backendResult:r}:{},...b(`Booted device`)}},Ki=async(e,t={})=>{if(!e.backend.shutdownDevice)throw new s(`UNSUPPORTED_OPERATION`,`admin.shutdown is not supported by this backend`);let n=ta(t.target),r=C(await e.backend.shutdownDevice(x(e,t),n));return{kind:`deviceShutdown`,...n?{target:n}:{},...r?{backendResult:r}:{},...b(`Shutdown device`)}},qi=async(e,t)=>await Xi(e,t,`install`),Ji=async(e,t)=>await Xi(e,t,`reinstall`),Yi=async(e,t)=>await Xi(e,t,`installFromSource`);async function Xi(e,t,n){let r=n===`reinstall`?`reinstallApp`:`installApp`,i=e.backend[r];if(!i)throw new s(`UNSUPPORTED_OPERATION`,`admin.${n} is not supported by this backend`);let a=`app`in t&&t.app!==void 0?J(t.app,`app`):void 0;if(n!==`installFromSource`&&!a)throw new s(`INVALID_ARGS`,`admin.${n} requires app`);let o=x(e,t),c=await Zi(e,o,t.source);try{let t=await i.call(e.backend,o,{...a?{app:a}:{},source:c.source});return na(n,a,c.source,t)}finally{await c.cleanup?.()}}async function Zi(e,t,n){let r=await Qi(e,$i(n));try{return{source:$i(e.backend.resolveInstallSource?await e.backend.resolveInstallSource(t,r.source):r.source),...r.cleanup?{cleanup:r.cleanup}:{}}}catch(e){if(r.cleanup)try{await r.cleanup()}catch{}throw e}}async function Qi(e,t){if(t.kind===`url`)return{source:t};let n=await B(e,t,{usage:`admin.install`,field:`source`});return{source:{kind:`path`,path:n.path},...n.cleanup?{cleanup:n.cleanup}:{}}}function $i(e){if(!e||typeof e!=`object`)throw new s(`INVALID_ARGS`,`install source is required`);if(e.kind===`path`)return{kind:`path`,path:J(e.path,`source.path`)};if(e.kind===`uploadedArtifact`)return{kind:`uploadedArtifact`,id:J(e.id,`source.id`)};if(e.kind===`url`){let t=J(e.url,`source.url`);return ea(t),{kind:`url`,url:t}}throw new s(`INVALID_ARGS`,`install source kind must be path, uploadedArtifact, or url`)}function ea(e){let t;try{t=new URL(e)}catch{throw new s(`INVALID_ARGS`,`Invalid install source URL: ${e}`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new s(`INVALID_ARGS`,`Install source URL must use http or https`)}function ta(e){if(!e)return;let t=q(e.id,`target.id`),n=q(e.name,`target.name`),r={...t?{id:t}:{},...n?{name:n}:{},...e.platform?{platform:e.platform}:{},...e.target?{target:e.target}:{},...e.headless===void 0?{}:{headless:e.headless}};return Object.keys(r).length>0?r:void 0}function na(e,t,n,r){let i=C(r),a=e===`reinstall`?`appReinstalled`:e===`installFromSource`?`appInstalledFromSource`:`appInstalled`,o=Y(r,`appName`),s=Y(r,`appId`),c=Y(r,`bundleId`),l=Y(r,`packageName`),u=Y(r,`launchTarget`),d=Y(r,`installablePath`),f=Y(r,`archivePath`);return{kind:a,...t?{app:t}:{},source:n,...s?{appId:s}:{},...o?{appName:o}:{},...c?{bundleId:c}:{},...l?{packageName:l}:{},...u?{launchTarget:u}:{},...d?{installablePath:d}:{},...f?{archivePath:f}:{},...i?{backendResult:i}:{},...b(`${e===`reinstall`?`Reinstalled`:`Installed`}: ${o??u??t??ra(n)}`)}}function Y(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function ra(e){return e.kind===`path`?e.path:e.kind===`uploadedArtifact`?e.id:e.url}const ia=/^[A-Za-z0-9_.:-]{1,64}$/,aa=async(e,t)=>{if(!e.backend.openApp)throw new s(`UNSUPPORTED_OPERATION`,`apps.open is not supported by this backend`);let n=da(t),r=C(await e.backend.openApp(X(e,t),n,{launchArgs:t.launchArgs,relaunch:t.relaunch}));return{kind:`appOpened`,target:n,relaunch:t.relaunch===!0,...r?{backendResult:r}:{},...b(`Opened: ${pa(n)}`)}},oa=async(e,t={})=>{if(!e.backend.closeApp)throw new s(`UNSUPPORTED_OPERATION`,`apps.close is not supported by this backend`);let n=q(t.app,`app`),r=C(await e.backend.closeApp(X(e,t),n));return{kind:`appClosed`,...n?{app:n}:{},...r?{backendResult:r}:{},...b(n?`Closed: ${n}`:`Closed app`)}},sa=async(e,t={})=>{if(!e.backend.listApps)throw new s(`UNSUPPORTED_OPERATION`,`apps.list is not supported by this backend`);return{kind:`appsList`,apps:await e.backend.listApps(X(e,t),it(t.filter))}},ca=async(e,t)=>{if(!e.backend.getAppState)throw new s(`UNSUPPORTED_OPERATION`,`apps.state is not supported by this backend`);let n=J(t.app,`app`);return{kind:`appState`,app:n,state:await e.backend.getAppState(X(e,t),n)}},la=async(e,t)=>{if(!e.backend.pushFile)throw new s(`UNSUPPORTED_OPERATION`,`apps.push is not supported by this backend`);let n=J(t.app,`app`),r=await ma(e,t.input);try{let i=C(await e.backend.pushFile(X(e,t),r.backendInput,n));return{kind:`appPushed`,app:n,inputKind:r.inputKind,...i?{backendResult:i}:{},...b(`Pushed to ${n}`)}}finally{await r.cleanup?.()}},ua=async(e,t)=>{if(!e.backend.triggerAppEvent)throw new s(`UNSUPPORTED_OPERATION`,`apps.triggerEvent is not supported by this backend`);let n=ha(t.name);ga(t.payload,`apps.triggerEvent payload for "${n}"`);let r=C(await e.backend.triggerAppEvent(X(e,t),{name:n,...t.payload?{payload:t.payload}:{}}));return{kind:`appEventTriggered`,name:n,...t.payload?{payload:t.payload}:{},...r?{backendResult:r}:{},...b(`Triggered app event: ${n}`)}};function da(e){let t=q(e.app,`app`),n=q(e.appId,`appId`),r=q(e.bundleId,`bundleId`),i=q(e.packageName,`packageName`),a=q(e.url,`url`),o=q(e.activity,`activity`),c={...t?{app:t}:{},...n?{appId:n}:{},...r?{bundleId:r}:{},...i?{packageName:i}:{},...a?{url:a}:{},...o?{activity:o}:{}};if(!fa(c))throw new s(`INVALID_ARGS`,`apps.open requires app, appId, bundleId, packageName, url, or activity`);return c}function fa(e){return!!(e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity)}function pa(e){return e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity??`app`}async function ma(e,t){if(!t||typeof t!=`object`)throw new s(`INVALID_ARGS`,`apps.push requires an input`);if(t.kind===`json`)return _a(t.payload,`apps.push JSON payload`,8192),{backendInput:{kind:`json`,payload:t.payload},inputKind:`json`};let n=await B(e,t,{usage:`apps.push`,field:`input`});return{backendInput:{kind:`file`,path:n.path},inputKind:`file`,...n.cleanup?{cleanup:n.cleanup}:{}}}function ha(e){let t=J(e,`name`);if(!ia.test(t))throw new s(`INVALID_ARGS`,`Invalid apps.triggerEvent name: ${t}`,{hint:`Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash.`});return t}function ga(e,t){e!==void 0&&_a(e,t,8192)}function _a(e,t,n){if(va(e,t),Buffer.byteLength(ya(e,t),`utf8`)>n)throw new s(`INVALID_ARGS`,`${t} exceeds ${n} bytes`)}function va(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new s(`INVALID_ARGS`,`${t} must be a JSON object`)}function ya(e,t){try{let n=JSON.stringify(e);if(typeof n!=`string`)throw new s(`INVALID_ARGS`,`${t} must be JSON-serializable`);return n}catch{throw new s(`INVALID_ARGS`,`${t} must be JSON-serializable`)}}function X(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}const ba={open:aa,close:oa,list:sa,state:ca,push:la,triggerEvent:ua},xa={devices:Wi,boot:Gi,shutdown:Ki,install:qi,reinstall:Ji,installFromSource:Yi};function Sa(e){return{...S(ba,e),list:(t={})=>ba.list(e,{...t,filter:at(t.filter)})}}const Ca=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i,wa=/\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/g;function Ta(e){let t=!1,n=e;return n=n.replaceAll(/(authorization|token|secret|password|passwd|api[-_]?key)=([^&\s]+)/gi,(e,n)=>(t=!0,`${String(n)}=[REDACTED]`)),n=n.replaceAll(/("(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)"\s*:\s*")([^"]*)(")/gi,(e,n,r,i)=>(t=!0,`${String(n)}[REDACTED]${String(i)}`)),n=n.replaceAll(/\b(Bearer\s+)([^\s",;]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(/((?:authorization|cookie|token|secret|password|passwd|api[-_]?key)\s*[:=]\s*)([^\s,;&]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(wa,()=>(t=!0,`[REDACTED]`)),n=Da(n,()=>{t=!0}),{value:n,redacted:t}}function Ea(e){try{let t=new URL(e),n=Oa(t);return(t.username||t.password)&&(t.username=`REDACTED`,t.password=`REDACTED`,n=!0),{value:t.toString(),redacted:n}}catch{return}}function Da(e,t){return/(https?:\/\/|token|secret|password|authorization|cookie|api[-_]?key)/i.test(e)?e.replaceAll(/https?:\/\/[^\s"'<>)]+/gi,e=>{let n=Ea(e);return n?(n.redacted&&t(),n.value):e}):e}function Oa(e){let t=!1;for(let n of Array.from(e.searchParams.keys()))Ca.test(n)&&(e.searchParams.set(n,`[REDACTED]`),t=!0);return t}const Z=2048,ka=4096,Aa=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i;function ja(e){let t=e.redacted===!0;return{kind:`diagnosticsLogs`,entries:e.entries.map(e=>{let n=$(e.message,ka),r=Ra(e.metadata);return t||=n.redacted||r.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.level?{level:e.level}:{},message:n.value??``,...e.source?{source:e.source}:{},...r.value?{metadata:r.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function Ma(e,t){let n=e.redacted===!0;return{kind:`diagnosticsNetwork`,entries:e.entries.map(e=>{let r=e.url?Fa(e.url):void 0,i=t===`headers`||t===`all`?Pa(e.requestHeaders):void 0,a=t===`headers`||t===`all`?Pa(e.responseHeaders):void 0,o=t===`body`||t===`all`?Ia(e.requestBody):void 0,s=t===`body`||t===`all`?Ia(e.responseBody):void 0,c=Ra(e.metadata);return n||=(r?.redacted??!1)||(i?.redacted??!1)||(a?.redacted??!1)||(o?.redacted??!1)||(s?.redacted??!1)||c.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.method?{method:e.method}:{},...r?{url:r.value}:{},...e.status===void 0?{}:{status:e.status},...e.durationMs===void 0?{}:{durationMs:e.durationMs},...i?.value?{requestHeaders:i.value}:{},...a?.value?{responseHeaders:a.value}:{},...o?.value===void 0?{}:{requestBody:o.value},...s?.value===void 0?{}:{responseBody:s.value},...c.value?{metadata:c.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:n,...e.notes?{notes:e.notes}:{}}}function Na(e){let t=e.redacted===!0;return{kind:`diagnosticsPerf`,metrics:e.metrics.map(e=>{let n=$(e.message,ka),r=Ra(e.metadata);return t||=n.redacted||r.redacted,{name:e.name,...e.value===void 0?{}:{value:e.value},...e.unit?{unit:e.unit}:{},...e.status?{status:e.status}:{},...n.value===void 0?{}:{message:n.value},...r.value?{metadata:r.value}:{}}}),...e.startedAt?{startedAt:e.startedAt}:{},...e.endedAt?{endedAt:e.endedAt}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function Pa(e){if(!e)return{redacted:!1};let t=!1,n={};for(let[r,i]of Object.entries(e))if(Aa.test(r))n[r]=`[REDACTED]`,t=!0;else{let e=$(i,Z);n[r]=e.value??``,t||=e.redacted}return{value:n,redacted:t}}function Fa(e){return Ea(e)??$(e,Z)}function Ia(e){return e===void 0?{redacted:!1}:La(e)??$(e,Z)}function La(e){try{let t=Q(JSON.parse(e),Ta);return za(JSON.stringify(t.value),Z,t.redacted)}catch{return}}function Ra(e){return Q(e,e=>$(e,Z))}function Q(e,t){if(e===void 0)return{redacted:!1};if(typeof e==`string`)return t(e);if(!e||typeof e!=`object`)return{value:e,redacted:!1};if(Array.isArray(e)){let n=!1;return{value:e.map(e=>{let r=Q(e,t);return n||=r.redacted,r.value}),redacted:n}}let n=!1,r={};for(let[i,a]of Object.entries(e)){if(Aa.test(i)){r[i]=`[REDACTED]`,n=!0;continue}let e=Q(a,t);r[i]=e.value,n||=e.redacted}return{value:r,redacted:n}}function $(e,t){if(e===void 0)return{redacted:!1};let n=Ta(e);return za(n.value,t,n.redacted)}function za(e,t,n){if(e===void 0)return{redacted:n};let r=e;return r.length>t&&(r=`${r.slice(0,t)}...[truncated]`,n=!0),{value:r,redacted:n}}const Ba=async(e,t={})=>{if(!e.backend.readLogs)throw new s(`UNSUPPORTED_OPERATION`,`diagnostics.logs is not supported by this backend`);return ja(await e.backend.readLogs(await Ua(e,t),Wa(t)))},Va=async(e,t={})=>{if(!e.backend.dumpNetwork)throw new s(`UNSUPPORTED_OPERATION`,`diagnostics.network is not supported by this backend`);let n=Ga(t);return Ma(await e.backend.dumpNetwork(await Ua(e,t),n),n.include??`summary`)},Ha=async(e,t={})=>{if(!e.backend.measurePerf)throw new s(`UNSUPPORTED_OPERATION`,`diagnostics.perf is not supported by this backend`);return Na(await e.backend.measurePerf(await Ua(e,t),Ka(t)))};async function Ua(e,t){let n=x(e,t),r=t.session?await e.sessions.get(t.session):void 0;return{...n,...t.appId??r?.appId?{appId:t.appId??r?.appId}:{},...t.appBundleId??r?.appBundleId?{appBundleId:t.appBundleId??r?.appBundleId}:{}}}function Wa(e){return{...qa(e,100,500,`logs limit`),...e.levels===void 0?{}:{levels:Xa(e.levels,`levels`)},...e.search===void 0?{}:{search:J(e.search,`search`)},...e.source===void 0?{}:{source:J(e.source,`source`)}}}function Ga(e){return{...qa(e,25,200,`network limit`),include:Ya(e.include)}}function Ka(e){return{...Ja(e),...e.sampleMs===void 0?{}:{sampleMs:w(e.sampleMs,`sampleMs`,100,6e4)},...e.metrics===void 0?{}:{metrics:Xa(e.metrics,`metrics`,20)}}}function qa(e,t,n,r){return{...Ja(e),...e.cursor===void 0?{}:{cursor:J(e.cursor,`cursor`)},limit:e.limit===void 0?t:w(e.limit,r,1,n)}}function Ja(e){return{...e.since===void 0?{}:{since:J(e.since,`since`)},...e.until===void 0?{}:{until:J(e.until,`until`)}}}function Ya(e){if(e===void 0)return`summary`;if(e===`summary`||e===`headers`||e===`body`||e===`all`)return e;throw new s(`INVALID_ARGS`,`network include must be summary, headers, body, or all`)}function Xa(e,t,n=50){if(!Array.isArray(e))throw new s(`INVALID_ARGS`,`${t} must be an array of strings`);if(e.length>n)throw new s(`INVALID_ARGS`,`${t} must contain at most ${n} entries`);return e.map((e,n)=>J(e,`${t}[${n}]`))}const Za={logs:Ba,network:Va,perf:Ha},Qa=async(e,t)=>{let n=ro(t.action,`record`),r=n===`start`?e.backend.startRecording:e.backend.stopRecording;if(!r)throw new s(`UNSUPPORTED_OPERATION`,`record ${n} is not supported by this backend`);let i=t.out?await V(e,t.out,{field:`path`,ext:`.mp4`,artifactType:`screen-recording`}):void 0;try{let a=eo(t,i?.path);return io(n,await r.call(e.backend,x(e,t),a),await i?.publish())}catch(e){throw await i?.cleanup?.(),e}},$a=async(e,t)=>{let n=ro(t.action,`trace`),r=n===`start`?e.backend.startTrace:e.backend.stopTrace;if(!r)throw new s(`UNSUPPORTED_OPERATION`,`trace ${n} is not supported by this backend`);let i=t.out?await V(e,t.out,{field:`outPath`,ext:`.trace`,artifactType:`trace-log`}):void 0;try{let a={...i?.path?{outPath:i.path}:{}};return ao(n,await r.call(e.backend,x(e,t),a),await i?.publish())}catch(e){throw await i?.cleanup?.(),e}};function eo(e,t){let n={};t&&(n.outPath=t);let r=to(e.fps);r!==void 0&&(n.fps=r);let i=no(e.quality);return i!==void 0&&(n.quality=i),e.hideTouches!==void 0&&(n.showTouches=e.hideTouches!==!0),n}function to(e){return e===void 0?void 0:w(e,`fps`,1,60)}function no(e){if(e===void 0)return;let t=Xe(e);if(t===void 0)throw new s(`INVALID_ARGS`,`quality must be one of: medium, high (legacy numeric values 5-10 are accepted)`);return t}function ro(e,t){if(e===`start`||e===`stop`)return e;throw new s(`INVALID_ARGS`,`${t} action must be start or stop`)}function io(e,t,n){return{...typeof t.path==`string`?{path:t.path}:{},...typeof t.telemetryPath==`string`?{telemetryPath:t.telemetryPath}:{},...typeof t.warning==`string`?{warning:t.warning}:{},...oo(e,t,n,{startKind:`recordingStarted`,stopKind:`recordingStopped`,startMessage:`Recording started`,stopMessage:`Recording stopped`})}}function ao(e,t,n){return{...typeof t.outPath==`string`?{outPath:t.outPath}:{},...oo(e,t,n,{startKind:`traceStarted`,stopKind:`traceStopped`,startMessage:`Trace started`,stopMessage:`Trace stopped`})}}function oo(e,t,n,r){return{kind:e===`start`?r.startKind:r.stopKind,action:e,...n?{artifact:n}:{},backendResult:t,...b(e===`start`?r.startMessage:r.stopMessage)}}const so={record:Qa,trace:$a},co=async(e,t={})=>{if(!e.backend.pressBack)throw new s(`UNSUPPORTED_OPERATION`,`system.back is not supported by this backend`);let n=t.mode??`in-app`;if(n!==`in-app`&&n!==`system`)throw new s(`INVALID_ARGS`,`system.back mode must be in-app or system`);let r=C(await e.backend.pressBack(x(e,t),{mode:n}));return{kind:`systemBack`,mode:n,...r?{backendResult:r}:{},...b(`Back`)}},lo=async(e,t={})=>{if(!e.backend.pressHome)throw new s(`UNSUPPORTED_OPERATION`,`system.home is not supported by this backend`);let n=C(await e.backend.pressHome(x(e,t)));return{kind:`systemHome`,...n?{backendResult:n}:{},...b(`Home`)}},uo=async(e,t)=>{if(!e.backend.pressTvRemote)throw new s(`UNSUPPORTED_OPERATION`,`system.tvRemote is not supported by this backend`);let n=ae(t.button),r=t.durationMs===void 0?void 0:w(t.durationMs,`durationMs`,0,1e4),i=C(await e.backend.pressTvRemote(x(e,t),{button:n,...r===void 0?{}:{durationMs:r}}));return{kind:`tvRemotePressed`,button:n,...r===void 0?{}:{durationMs:r},...i?{backendResult:i}:{},...b(`Pressed TV remote ${n}`)}},fo=async(e,t)=>{if(!e.backend.setOrientation)throw new s(`UNSUPPORTED_OPERATION`,`system.orientation is not supported by this backend`);let n=vo(t.orientation),r=C(await e.backend.setOrientation(x(e,t),n));return{kind:`systemOrientationSet`,orientation:n,...r?{backendResult:r}:{},...b(`Rotated to ${n}`)}},po=async(e,t={})=>{if(!e.backend.setKeyboard)throw new s(`UNSUPPORTED_OPERATION`,`system.keyboard is not supported by this backend`);let n=t.action??`status`;if(!rt(n))throw new s(`INVALID_ARGS`,`system.keyboard action must be status, get, dismiss, enter, or return`);let r=await e.backend.setKeyboard(x(e,t),{action:n}),i=C(r),a=Do(r)?r:{};return n===`enter`||n===`return`?bo(a,i):n===`dismiss`?xo(n,a,i):Co(n,a,i)},mo=async(e,t)=>{if(t.action===`read`){if(!e.backend.getClipboard)throw new s(`UNSUPPORTED_OPERATION`,`system.clipboard read is not supported by this backend`);let n=await e.backend.getClipboard(x(e,t));return{kind:`clipboardText`,action:`read`,text:typeof n==`string`?n:n.text}}if(t.action!==`write`)throw new s(`INVALID_ARGS`,`system.clipboard action must be read or write`);if(!e.backend.setClipboard)throw new s(`UNSUPPORTED_OPERATION`,`system.clipboard write is not supported by this backend`);if(typeof t.text!=`string`)throw new s(`INVALID_ARGS`,`system.clipboard write requires text`);let n=C(await e.backend.setClipboard(x(e,t),t.text));return{kind:`clipboardUpdated`,action:`write`,textLength:Array.from(t.text).length,...n?{backendResult:n}:{},...b(`Clipboard updated`)}},ho=async(e,t={})=>{if(!e.backend.openSettings)throw new s(`UNSUPPORTED_OPERATION`,`system.settings is not supported by this backend`);let n=q(t.target,`target`),r=C(await e.backend.openSettings(x(e,t),n));return{kind:`settingsOpened`,...n?{target:n}:{},...r?{backendResult:r}:{},...b(n?`Opened settings: ${n}`:`Opened settings`)}},go=async(e,t={})=>{if(!e.backend.handleAlert)throw new s(`UNSUPPORTED_OPERATION`,`system.alert is not supported by this backend`);let n=t.action??`get`;if(n!==`get`&&n!==`accept`&&n!==`dismiss`&&n!==`wait`)throw new s(`INVALID_ARGS`,`system.alert action must be get, accept, dismiss, or wait`);let r=t.timeoutMs===void 0?void 0:w(t.timeoutMs,`timeoutMs`,0,12e4);return yo(n,await e.backend.handleAlert(x(e,t),n,{timeoutMs:r}))},_o=async(e,t={})=>{if(!e.backend.openAppSwitcher)throw new s(`UNSUPPORTED_OPERATION`,`system.appSwitcher is not supported by this backend`);let n=C(await e.backend.openAppSwitcher(x(e,t)));return{kind:`appSwitcherOpened`,...n?{backendResult:n}:{},...b(`Opened app switcher`)}};function vo(e){switch(e){case`portrait`:case`portrait-upside-down`:case`landscape-left`:case`landscape-right`:return e;default:throw new s(`INVALID_ARGS`,`system.orientation must be portrait, portrait-upside-down, landscape-left, or landscape-right`)}}function yo(e,t){return e===`get`?wo(t):e===`wait`?To(t):Eo(e,t)}function bo(e,t){return{kind:`keyboardEnterPressed`,action:`enter`,state:e,...t?{backendResult:t}:{},...b(`Keyboard enter pressed`)}}function xo(e,t,n){return{kind:`keyboardDismissed`,action:e,state:t,...n?{backendResult:n}:{},...b(So(t))}}function So(e){return e.dismissed===!1?`Keyboard already hidden`:e.mechanism===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`}function Co(e,t,n){return{kind:`keyboardState`,action:e,state:t,...n?{backendResult:n}:{}}}function wo(e){if(e.kind!==`alertStatus`)throw new s(`COMMAND_FAILED`,`system.alert get returned an invalid backend result`);return{kind:`alertStatus`,action:`get`,alert:e.alert}}function To(e){if(e.kind!==`alertWait`)throw new s(`COMMAND_FAILED`,`system.alert wait returned an invalid backend result`);return{kind:`alertWait`,action:`wait`,alert:e.alert,...e.waitedMs===void 0?{}:{waitedMs:e.waitedMs},...e.timedOut===void 0?{}:{timedOut:e.timedOut},...b(e.alert?`Alert visible`:`Alert wait timed out`)}}function Eo(e,t){if(t.kind!==`alertHandled`)throw new s(`COMMAND_FAILED`,`system.alert ${e} returned an invalid backend result`);return{kind:`alertHandled`,action:e,handled:t.handled,...t.alert?{alert:t.alert}:{},...t.button?{button:t.button}:{},...b(t.handled?`Alert ${e}ed`:`No alert handled`)}}function Do(e){return!!(e&&typeof e==`object`)}const Oo={back:co,home:lo,orientation:fo,keyboard:po,clipboard:mo,settings:ho,alert:go,appSwitcher:_o,tvRemote:uo};function ko(e){return{capture:S(qr,e),selectors:Hi(e),interactions:Ui(e),system:S(Oo,e),apps:Sa(e),admin:S(xa,e),recording:S(so,e),observability:S(Za,e)}}var Ao=r({createAgentDevice:()=>jo,createMemorySessionStore:()=>Mo,localCommandPolicy:()=>Fo,restrictedCommandPolicy:()=>Io});function jo(e){let t={backend:e.backend,artifacts:e.artifacts,sessions:e.sessions??Mo(),policy:e.policy??Io(),diagnostics:e.diagnostics,clock:e.clock,signal:e.signal};return{...t,...ko(t)}}function Mo(e=[]){let t=new Map(e.map(e=>[e.name,No(e)]));return{get:e=>No(t.get(e)),set:e=>{t.set(e.name,No(e))},delete:e=>{t.delete(e)},list:()=>Array.from(t.values(),e=>No(e))}}function No(e){if(e)return{...e,...e.snapshot?{snapshot:structuredClone(e.snapshot)}:{},...e.metadata?{metadata:Po(e.metadata)}:{}}}function Po(e){try{return structuredClone(e)}catch{return{...e}}}function Fo(e={}){return{allowLocalInputPaths:!0,allowLocalOutputPaths:!0,maxImagePixels:2e7,...e}}function Io(e={}){return{allowLocalInputPaths:!1,allowLocalOutputPaths:!1,maxImagePixels:2e7,...e}}export{Nt as _,wr as a,N as c,dn as d,Zt as f,At as g,vt as h,Xr as i,P as l,_t as m,Fo as n,yr as o,gt as p,Ao as r,fn as s,jo as t,un as u};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{F as t,L as n,P as r,W as i}from"./sdk-batch-runner.js";import{C as a}from"./sdk-device.js";import{S as o,a as s,b as c,c as l,h as u,n as d,o as f,s as p,t as m}from"./src2.js";import h from"node:path";function g(t){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new e(`INVALID_ARGS`,`Invalid Android package name for logs: ${t}`)}const _=Object.freeze({resourceKind:t,version:1,encode:e=>({...e}),decode:e=>e.transport!==`android-logcat-local`&&e.transport!==`android-logcat-transport-composed`||!y(e.outputPath)||!y(e.pidPath)?{status:`invalid`,message:`Invalid Android app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:e.transport,outputPath:e.outputPath,pidPath:e.pidPath})}});function v(e){let n=_.decode(e.descriptor);if(n.status!==`decoded`)throw TypeError(n.message);return c({resourceKind:t,sessionId:e.sessionId,device:{id:e.device.id,family:`android`,kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:o(_,n.descriptor)})}function y(e){return typeof e==`string`&&e.trim().length>0}function b(e){return p(e,{family:`android`,backend:`android`,label:`Android`,codec:_,startUnavailableHint:`The selected Android transport cannot start a background adb logcat stream.`,cleanupFailureMessage:`Android app-log cleanup did not settle every owned resource`,doctor:async({host:e,device:t,signal:n},r)=>await x(e,t.id,r,n),validateStart:({input:e})=>g(e.appBundleId),process:async({host:e,device:t,input:n})=>({resolvePid:async r=>await l(e,S(t.id,n.appBundleId),r),command:e=>({kind:`android-adb`,serial:t.id,args:[`logcat`,`-v`,`time`,`--pid`,e],options:{allowFailure:!0}})}),descriptor:({artifacts:e,transport:t})=>({transport:t.mode===`transport-composed`?`android-logcat-transport-composed`:`android-logcat-local`,...e}),envelope:({input:e,device:t,owner:n,descriptor:r})=>v({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function x(e,t,n,r){let i={};return i.adbAvailable=await f(async()=>s(await e.commands.run({executable:`adb`,args:[`-s`,t,`shell`,`echo`,`ok`],allowFailure:!0,timeoutMs:1e3},r)),r),n&&(i.androidPidVisible=await f(async()=>!!await l(e,S(t,n),r),r)),{backend:`android`,checks:i,notes:n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}}function S(e,t){return{executable:`adb`,args:[`-s`,e,`shell`,`pidof`,t],allowFailure:!0,timeoutMs:5e3}}async function C(e,t,n,r){let i=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),a=d(i.text,{...n,path:i.path,exists:i.exists,lineNumberOffset:i.skippedLines,backend:`android`}),o=[],s=await ee(e,t,n,r);if(s&&n.appBundleId){g(n.appBundleId);let c=await ne(e,t,n.appBundleId,r);if(c){let e=d(c.text,{...n,path:`${i.path} (adb logcat recovery)`,exists:!0,backend:`android`});e.entries.length>0&&(a=m(e,a,n.maxEntries),o.push(s.reason===`stale-active`?`Session app log stream was still bound to prior Android PID ${s.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`))}}return n.appLogSnapshot?n.appLogSnapshot.state!==`active`&&o.length===0&&o.push(`Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.`):o.push(`Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests.`),a.entries.length===0&&o.push(`No HTTP(s) entries were found in recent session app logs.`),Object.freeze({source:`app-log`,backend:`android`,dump:a,notes:Object.freeze(o)})}async function w(e,t,n){n.throwIfAborted();try{let r=await e.commands.run(t,n);return n.throwIfAborted(),r}catch{n.throwIfAborted();return}}async function ee(e,t,n,r){if(!n.appBundleId||n.appLogSnapshot?.state===void 0)return;if(n.appLogSnapshot.state!==`active`)return{reason:`inactive`};let i=te(await e.appLogs.readProcessMarker(n.sessionId));if(!i)return;let a=await T(e,t.id,n.appBundleId,r);if(!(!a||a===i))return{reason:`stale-active`,trackedPid:i}}function te(e){if(e.status===`decoded`)return/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(e.marker.command)?.[1]}async function ne(e,t,n,r){let i=await T(e,t.id,n,r),a=await w(e,{executable:`adb`,args:[`-s`,t.id,`logcat`,`-d`,`-v`,`time`,`-t`,`4000`],allowFailure:!0,timeoutMs:3e3},r);if(!a||a.exitCode!==0||!a.stdout.trim())return;let o=re(a.stdout,n,i);if(o.length===0)return;let s=new Set(o),c=a.stdout.split(`
|
|
2
|
+
`).filter(e=>{if(!e.trim())return!1;if(e.includes(n))return!0;let t=/\(\s*(\d+)\)\s*:/.exec(e)?.[1];return!!(t&&s.has(t))}).join(`
|
|
3
|
+
`);return c.trim()?{text:c,pids:o}:void 0}async function T(e,t,n,r){let i=await w(e,{executable:`adb`,args:[`-s`,t,`shell`,`pidof`,n],allowFailure:!0},r);if(!i)return;let a=i.stdout.trim().split(/\s+/)[0];return a&&/^\d+$/.test(a)?a:void 0}function re(e,t,n){let r=new Set(n?[n]:[]),i=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),a=[RegExp(`\\bStart proc\\s+(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`\\b(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`${i}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,`i`),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${i}`,`i`)];for(let n of e.split(`
|
|
4
|
+
`))if(n.includes(t))for(let e of a){let t=e.exec(n)?.[1];t&&/^\d+$/.test(t)&&r.add(t)}return Object.freeze([...r])}const ie=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-\d{1,20}\.mp4$/,ae=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-active\.json$/;function oe(e){return le(e)&&ue(e)&&de(e)}function se(e){if(!O(e))return!1;let t=e;return fe(t)&&pe(t)&&me(t)&&he(t)&&(t.completion===void 0||xe(t))}function ce(e,t){return E(e,t)&&D(e,t.outputPath,t.clientOutputPath)}function le(e){return e.backend===`adb-screenrecord`&&typeof e.manifestPath==`string`&&ae.test(e.manifestPath)&&typeof e.outputPath==`string`}function ue(e){return(e.clientOutputPath===void 0||typeof e.clientOutputPath==`string`)&&k(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`}function de(e){return A(e.transportMode)&&j(e.exportQuality)&&M(e.activeSessionApp)}function fe(e){return e.version===1&&e.resourceKind===`screen-recording`&&typeof e.fenceToken==`string`&&Number.isInteger(e.fenceGeneration)&&typeof e.sessionId==`string`&&typeof e.deviceId==`string`&&Number.isFinite(e.startedAt)}function pe(e){return typeof e.outputPath==`string`&&(e.clientOutputPath===void 0||typeof e.clientOutputPath==`string`)&&k(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`}function me(e){return M(e.activeSessionApp)&&j(e.exportQuality)&&A(e.transportMode)&&(e.pendingRemotePath===void 0||N(e.pendingRemotePath))}function he(e){return Array.isArray(e.chunks)&&e.chunks.every(ge)&&(e.chunks.length>0||e.pendingRemotePath!==void 0)&&(e.completion===void 0||_e(e.completion))}function ge(e,t){if(!O(e))return!1;let n=e;return n.index===t+1&&N(n.remotePath)&&P(n.remotePid)&&P(n.remoteStartTime)}function _e(e){if(!O(e))return!1;let t=e;return ve(t)&&ye(t)&&(t.chunks===void 0||t.chunks.every(be))}function ve(e){return typeof e.backend==`string`&&typeof e.outPath==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)&&Number.isFinite(e.startedAt)&&Number.isFinite(e.completedAt)}function ye(e){return k(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`&&M(e.activeSessionApp)}function be(e,t){return e.index===t+1&&typeof e.path==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)}function xe(e){let t=e.completion;return t!==void 0&&E(t,e)&&t.startedAt===e.startedAt&&D(t,e.outputPath,e.clientOutputPath,e.chunks.length)}function E(e,t){return e.backend===`adb screenrecord`&&e.outPath===t.outputPath&&e.clientOutPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&Se(e.activeSessionApp,t.activeSessionApp)}function D(e,t,n,r=e.chunks===void 0?1:e.chunks.length){return r===1?e.chunks===void 0:e.chunks?.length===r&&e.chunks.every((e,r)=>e.path===F(t,r+1)&&e.clientOutPath===(n===void 0?void 0:F(n,r+1)))}function O(e){return typeof e==`object`&&!!e}function k(e){return e===`app`||e===`device`||e===`system`}function A(e){return e===`local`||e===`transport-composed`}function j(e){return e===void 0||e===`medium`||e===`high`}function M(e){return e===void 0||O(e)&&typeof e.bundleId==`string`&&(e.name===void 0||typeof e.name==`string`)}function N(e){return typeof e==`string`&&ie.test(e)}function P(e){return typeof e==`string`&&/^\d+$/.test(e)}function Se(e,t){return JSON.stringify(e)===JSON.stringify(t)}function F(e,t){if(t===1)return e;let n=e.lastIndexOf(`.`),r=n>e.lastIndexOf(`/`)?e.slice(0,n):e,i=n>e.lastIndexOf(`/`)?e.slice(n):`.mp4`;return`${r}.part-${String(t).padStart(3,`0`)}${i}`}const I=Object.freeze({resourceKind:r,version:1,encode:e=>({...e}),decode:e=>oe(e)?{status:`decoded`,descriptor:Object.freeze({backend:`adb-screenrecord`,manifestPath:e.manifestPath,outputPath:e.outputPath,...e.clientOutputPath===void 0?{}:{clientOutputPath:e.clientOutputPath},scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,transportMode:e.transportMode,...e.activeSessionApp===void 0?{}:{activeSessionApp:e.activeSessionApp},...e.exportQuality===void 0?{}:{exportQuality:e.exportQuality}})}:{status:`invalid`,message:`Invalid Android screen-recording descriptor`}});function L(e,t,n,r,i,a=`local`){return Object.freeze({version:1,resourceKind:`screen-recording`,fenceToken:t.fence.token,fenceGeneration:t.fence.generation,sessionId:t.sessionId,deviceId:e.id,startedAt:n,outputPath:t.outputPath,...t.clientOutputPath===void 0?{}:{clientOutputPath:t.clientOutputPath},scope:t.scope,showTouches:t.showTouches,recordOnlySession:t.recordOnlySession,...t.activeSessionApp===void 0?{}:{activeSessionApp:t.activeSessionApp},...t.exportQuality===void 0?{}:{exportQuality:t.exportQuality},chunks:r,...i===void 0?{}:{pendingRemotePath:i},transportMode:a})}function Ce(e,t){return Object.freeze({...e,completion:t})}function R(e){try{let t=e&&JSON.parse(e);return se(t)?t:void 0}catch{return}}function we(e,t,n){return e.deviceId===t.id&&e.deviceId===n.device.id&&e.fenceToken===n.fence.token&&e.fenceGeneration===n.fence.generation&&e.sessionId===n.sessionId}function Te(e,t){return e.outputPath===t.outputPath&&e.clientOutputPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&JSON.stringify(e.activeSessionApp)===JSON.stringify(t.activeSessionApp)&&e.exportQuality===t.exportQuality&&e.transportMode===t.transportMode&&(e.completion===void 0||ce(e.completion,t))}const z=1e4,B=1e3;var V=class extends Error{constructor(e){super(`Android screenrecord launch rollback could not be confirmed`,{cause:e})}};function H(e,t=Date.now()){return[...new Set(e?[e,`/sdcard`,`/data/local/tmp`]:[`/sdcard`,`/data/local/tmp`])].map(e=>`${e}/agent-device-recording-${t}.mp4`)}async function U(e,t,n,r){let i;try{if(i=(await e.start({remotePath:t,quality:n.exportQuality??`medium`},r)).process,!/^\d+$/.test(i.pid)||!/^\d+$/.test(i.startTime)||i.remotePath!==t)throw Error(`Android screenrecord returned an invalid process identity`);if(!await ke(e,t,i,r))throw Error(`Android screenrecord did not begin producing frames`);return{index:1,remotePath:t,remotePid:i.pid,remoteStartTime:i.startTime}}catch(t){throw i&&Ee(i)&&!await Ae(e,i)?new V(t):r?.aborted?r.reason:t}}function Ee(e){return/^\d+$/.test(e.pid)&&/^\d+$/.test(e.startTime)&&e.remotePath.length>0}async function W(e,t){let n=!1,r;for(let i of[...t].reverse())try{n=await q(e,i)||n}catch(e){r??=e}if(r)throw r;return n}async function De(e,t){for(let n of t){let t;for(let r=0;r<3;r+=1){let i=await e.size(n.remotePath);if(typeof i==`number`&&i>0&&i===t)break;if(t=typeof i==`number`&&i>0?i:void 0,r===2)throw Error(`Android recording artifact is not stable: ${n.remotePath}`);await new Promise(e=>setTimeout(e,250))}}}async function Oe(e,t,n,r){let i=[];for(let[a,o]of t.entries()){let t=a===0?n:Pe(n,a+1);await je(e,o.remotePath,t);let s=a===0||r===void 0?r:Pe(r,a+1);i.push({index:a+1,path:t,...s===void 0?{}:{clientOutPath:s}})}return Object.freeze(i)}async function G(e,t){let n;for(let r of t)try{if(!await e.remove(r.remotePath))throw Error(`failed to remove Android recording artifact: ${r.remotePath}`)}catch(e){n??=e}if(n)throw n}async function K(e,t){try{await W(e,t)}finally{await G(e,t)}}async function ke(e,t,n,r){for(let i=0;i<3;i+=1){if(r?.throwIfAborted(),await e.exists(t,r)===!0)return!0;if(await e.inspect(n,r)!==`owned-alive`)return!1;i<2&&await new Promise(e=>setTimeout(e,250))}return!0}async function Ae(e,t){try{let n=await e.stop(t,{force:!0});return(n===`stopped`||n===`already-missing`)&&await e.remove(t.remotePath)}catch{return!1}}async function q(e,t){if(!t)return!1;let n={pid:t.remotePid,remotePath:t.remotePath,startTime:t.remoteStartTime},r=await e.stop(n);if(r===`already-missing`)return!0;if(r===`ownership-lost`)throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.remotePid}`);if(await Me(e,n))return!1;let i=await e.stop(n,{force:!0});if(i===`stopped`||i===`already-missing`)return!1;throw Error(`failed to stop Android screenrecord pid ${t.remotePid}`)}async function je(e,t,n){for(let r=0;r<3;r+=1){let i=await e.pullPlayable({remotePath:t,outputPath:n});if(i.exitCode===0&&i.playable)return;r+1<3&&await Ne(1e3)}throw Error(`failed to retrieve playable Android recording`)}async function Me(e,t){for(let n=0;n<=z;n+=B){let r=await e.inspect(t);if(r===`missing`)return!0;if(r===`ownership-lost`)throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.pid}`);n<z&&await Ne(B)}return!1}function Ne(e){return new Promise(t=>setTimeout(t,e))}function Pe(e,t){let n=h.parse(e);return h.join(n.dir,`${n.name}.part-${String(t).padStart(3,`0`)}${n.ext||`.mp4`}`)}async function Fe(e){let{transport:t,device:n,input:r,startedAt:i,signal:a,prepareOutput:o}=e;await Ie(t,n),await o();let s;for(let e of H(void 0)){let o=t.manifestPathFor(e);await J(t,o,L(n,r,i,[],e,t.mode),a);let c;try{c=await U(t,e,r,a)}catch(e){if(a.aborted)throw a.reason;await We(t,o,e),s=e;continue}try{await J(t,o,L(n,r,i,[c],void 0,t.mode),a)}catch(e){throw await K(t,[c]).catch(()=>{}),e}return{chunk:c,manifestPath:o}}throw s??Error(`Android screenrecord did not begin producing frames`)}async function Ie(e,t){let n=(await Le(e)).flatMap(n=>Re(n,t,e.mode));for(let t of n)await He(e,t.evidence,t.manifestPath)}async function Le(e){return await Promise.all(H(void 0).map(async t=>{let n=e.manifestPathFor(t);return{manifestPath:n,read:await e.readManifest(n)}}))}function Re(e,t,n){if(e.read.status===`missing`)return[];if(e.read.status!==`read`)throw Be();let r=R(e.read.contents);if(!ze(r,t,n))throw Ve();return[{manifestPath:e.manifestPath,evidence:r}]}function ze(e,t,n){return e!==void 0&&e.completion!==void 0&&e.pendingRemotePath===void 0&&e.deviceId===t.id&&e.transportMode===n}function Be(){return Error(`Android screenrecord native recovery evidence is unavailable`)}function Ve(){return Error(`Android screenrecord native recovery evidence already exists`)}async function He(e,t,n){for(let n of t.chunks)if(await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime})!==`missing`)throw Error(`Android screenrecord completed evidence cannot be safely retired`);if(await G(e,t.chunks),await Y(e,n),(await e.readManifest(n)).status!==`missing`)throw Error(`Android screenrecord completed evidence removal could not be confirmed`)}async function Ue(e){let{transport:t,device:n,input:r,startedAt:i,chunks:a,manifestPath:o,preferredDir:s}=e,c;for(let e of H(s)){await J(t,o,L(n,r,i,a,e,t.mode));try{return await U(t,e,r)}catch(e){if(e instanceof V)throw e;try{await J(t,o,L(n,r,i,a,void 0,t.mode))}catch{throw new V(e)}c=e}}throw c??Error(`failed to start next Android recording chunk`)}async function We(e,t,n){if(n instanceof V)throw n;try{await Y(e,t)}catch{throw new V(n)}}async function J(e,t,n,r){await e.writeManifest({manifestPath:t,contents:JSON.stringify(n)},r)}async function Y(e,t){if(!await e.removeManifest(t))throw Error(`failed to remove Android recording manifest: ${t}`)}function Ge(e,t){return Object.freeze({backend:`adb screenrecord`,outPath:e.outputPath,...e.clientOutputPath?{clientOutPath:e.clientOutputPath}:{},startedAt:t,scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,...e.activeSessionApp?{activeSessionApp:e.activeSessionApp}:{},...e.exportQuality?{exportQuality:e.exportQuality}:{},gestureEvents:[]})}async function Ke(e,t,n,r,i=!1){let a=n.length>1,o=await e.screenRecording.finalize.complete({outputPath:t.outPath,showTouches:a?!1:t.showTouches,gestureEvents:t.gestureEvents,exportQuality:t.exportQuality??`medium`,targetLabel:r}),s=[...i?[`Android adb screenrecord stopped before record stop, likely after reaching the 180s platform limit. The MP4 may be truncated; final interactions after the limit are not in the video.`]:[],...a?[`Android adb screenrecord is capped at 180s, so this recording was split into multiple MP4 chunks.`]:[]];return{status:`completed`,result:{backend:t.backend,outPath:t.outPath,...t.clientOutPath?{clientOutPath:t.clientOutPath}:{},startedAt:t.startedAt,completedAt:Date.now(),scope:t.scope,showTouches:t.showTouches,recordOnlySession:t.recordOnlySession,...t.activeSessionApp?{activeSessionApp:t.activeSessionApp}:{},...a?{chunks:n}:{},...s.length?{warning:s.join(` `)}:{},...o,...a&&t.showTouches&&t.gestureEvents.length>0?{overlayWarning:`touch overlay burn-in is skipped for chunked Android recordings; returning raw chunks plus gesture telemetry`}:{}}}}function qe(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:String(e)}}async function Je(e){let t=await W(e.transport,e.evidence.chunks)||e.reachedLimit===!0;await De(e.transport,e.evidence.chunks);let n=await Oe(e.transport,e.evidence.chunks,e.recording.outPath,e.recording.clientOutPath),r=await Ke(e.host,e.recording,n,`Android recording`,t);return await J(e.transport,e.manifestPath,Ce(e.evidence,r.result)),await G(e.transport,e.evidence.chunks),r}async function Ye(e,t,n){try{let r=t.pendingRemotePath,i=r===void 0?[]:(await e.findRunning(r)).map(e=>({index:t.chunks.length+1,remotePath:r,remotePid:e.pid,remoteStartTime:e.startTime}));if(await W(e,[...t.chunks,...i]),await G(e,t.chunks),r!==void 0&&!await e.remove(r))throw Error(`failed to remove Android recording artifact: ${r}`);return await Y(e,n),{status:`cleaned`}}catch(e){return qe(e)}}async function Xe(e){let{transport:t,device:n,envelope:r,descriptor:i}=e;if(i.transportMode!==t.mode)return{status:`transport-unavailable`};let a=await t.readManifest(i.manifestPath);if(a.status===`unavailable`)return{status:`transport-unavailable`};let o=a.status===`read`?R(a.contents):void 0;return o&&we(o,n,r)&&Te(o,i)?{status:`matched`,evidence:o}:{status:`ownership-lost`}}async function Ze(e){let t=await e.transport.readManifest(e.manifestPath);if(t.status!==`read`)return;let n=R(t.contents);return n&&Qe(n,e)?n:void 0}function Qe(e,t){return e.deviceId===t.deviceId&&e.sessionId===t.sessionId&&e.fenceToken===t.fence.token&&e.fenceGeneration===t.fence.generation}async function $e(e){let{host:t,transport:n,device:r,input:i}=e,a=I.decode(i.envelope.descriptor.body);if(a.status!==`decoded`)return Z(`descriptor-invalid`);let o=await Xe({transport:n,device:r,envelope:i.envelope,descriptor:a.descriptor});return o.status===`matched`?await et({host:t,transport:n,device:r,input:i,descriptor:a.descriptor,evidence:o.evidence}):Z(o.status===`transport-unavailable`?`transport-not-reattachable`:`ownership-fence-lost`)}async function X(e){let t=I.decode(e.input.envelope.descriptor.body);if(t.status!==`decoded`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};let n=await Xe({transport:e.transport,device:e.device,envelope:e.input.envelope,descriptor:t.descriptor});return n.status===`matched`?await Ye(e.transport,n.evidence,t.descriptor.manifestPath):n.status===`transport-unavailable`?{status:`cleanup-pending`,reason:`owner-unavailable`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`}}async function et(e){let{host:t,transport:n,device:r,input:i,descriptor:a,evidence:o}=e;if(o.completion!==void 0&&await tt(n,o))return{status:`completed`,result:o.completion};if(o.completion!==void 0)return Z(`ownership-fence-lost`,`Android recording completed evidence still names a live or unverifiable recorder.`);if(o.pendingRemotePath!==void 0)return Z(`transport-not-reattachable`,`Android recording launch was interrupted before its process identity was committed.`);let s=o.chunks.at(-1);if(!s)return{status:`missing`};let c=await n.inspect({pid:s.remotePid,remotePath:s.remotePath,startTime:s.remoteStartTime});if(c!==`owned-alive`&&await n.exists(s.remotePath)!==!0)return Z(`transport-not-reattachable`,`Android recording process ended before its artifact could be recovered.`);let l=nt(i.envelope.sessionId,i.envelope.fence,a),d=!1;return{status:`active`,handle:u(Ge(l,o.startedAt),{finish:async e=>{let r=await Je({host:t,transport:n,evidence:o,manifestPath:a.manifestPath,recording:e,reachedLimit:c===`missing`});return d=!0,r},forceCleanup:async()=>d?{status:`cleaned`}:await X({transport:n,device:r,input:i})})}}async function tt(e,t){try{for(let n of t.chunks)if(await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime})!==`missing`)return!1;return!0}catch{return!1}}function nt(e,t,n){return{sessionId:e,outputPath:n.outputPath,...n.clientOutputPath===void 0?{}:{clientOutputPath:n.clientOutputPath},scope:n.scope,showTouches:n.showTouches,hideTouchesRequested:!1,recordOnlySession:n.recordOnlySession,...n.activeSessionApp===void 0?{}:{activeSessionApp:n.activeSessionApp},...n.exportQuality===void 0?{}:{exportQuality:n.exportQuality},fence:t}}function Z(e,t){return{status:`unreattachable`,reason:e,...t===void 0?{}:{message:t}}}async function rt(e){let{host:t,device:n,owner:r,signal:i}=e,a=await t.screenRecording.android.resolve(n);return Object.freeze({screenRecordingStart:async e=>await it({host:t,transport:a,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async e=>await $e({host:t,transport:a,device:n,input:e}),screenRecordingCleanup:async e=>await X({transport:a,device:n,input:e})})}async function it(e){let{host:t,transport:n,device:s,owner:l,input:d,signal:f}=e;f.throwIfAborted();let p=Date.now(),m=await Fe({transport:n,device:s,input:d,startedAt:p,signal:f,prepareOutput:async()=>await t.screenRecording.outputs.prepare(d.outputPath)}),g=m.manifestPath,_=[m.chunk],v,y,b,x=!1,S=()=>{v=setTimeout(()=>{y=C().catch(e=>{b=e})},17e4),v.unref?.()},C=async()=>{let e=_.at(-1);if(!e)throw Error(`Android recording has no active chunk`);let t=!1,r;try{r=await Ue({transport:n,device:s,input:d,startedAt:p,chunks:_,manifestPath:g,preferredDir:h.posix.dirname(e.remotePath)})}catch(i){await q(n,e),t=!0;try{r=await Ue({transport:n,device:s,input:d,startedAt:p,chunks:_,manifestPath:g,preferredDir:h.posix.dirname(e.remotePath)})}catch(e){throw e instanceof Error?e:i}}let i=[..._,{...r,index:_.length+1}];try{await J(n,g,L(s,d,p,i,void 0,n.mode))}catch(i){if(await K(n,[r]).catch(()=>{}),t)await J(n,g,L(s,d,p,_,r.remotePath,n.mode)).catch(()=>{});else try{await J(n,g,L(s,d,p,_,void 0,n.mode))}catch{await q(n,e).catch(()=>{}),await J(n,g,L(s,d,p,_,r.remotePath,n.mode)).catch(()=>{})}throw i}_=i,t||await q(n,e),S()};S();let w=u(Ge(d,p),{finish:async e=>{if(v&&clearTimeout(v),await y,b)throw b;let r=await Je({host:t,transport:n,evidence:L(s,d,p,_,void 0,n.mode),manifestPath:g,recording:e});return x=!0,r},forceCleanup:async()=>{if(v&&clearTimeout(v),x)return{status:`cleaned`};try{await y}catch(e){b=e}let e=await Ze({transport:n,deviceId:s.id,sessionId:d.sessionId,fence:d.fence,manifestPath:g});return e?await Ye(n,e,g):{status:`cleanup-pending`,reason:`ownership-fence-lost`}}});return Object.freeze({pendingHandle:new i(w),envelope:c({resourceKind:r,sessionId:d.sessionId,device:a(s),owner:l,fence:d.fence,lifecycle:`open`,descriptor:o(I,{backend:`adb-screenrecord`,manifestPath:g,outputPath:d.outputPath,...d.clientOutputPath===void 0?{}:{clientOutputPath:d.clientOutputPath},scope:d.scope,showTouches:d.showTouches,recordOnlySession:d.recordOnlySession,...d.activeSessionApp===void 0?{}:{activeSessionApp:d.activeSessionApp},...d.exportQuality===void 0?{}:{exportQuality:d.exportQuality},transportMode:n.mode})})})}const Q=n(`android`),$=Object.freeze({available:!0});function at(e){let t=b(e);return Object.freeze({owner:Q,ownsDevice:e=>e.platform===`android`,bind:async n=>{let r=await t.bind(n),i=await rt({host:e,device:n.device,owner:Q,signal:n.scope.signal});return Object.freeze({device:r.device,owner:Q,facts:Object.freeze({device:r.facts.device,operations:{...r.facts.operations,networkDump:$,screenRecordingStart:$,screenRecordingReattach:$,screenRecordingCleanup:$}}),operations:Object.freeze({...r.operations,networkDump:async t=>await C(e,n.device,t,n.scope.signal),...i}),[Symbol.asyncDispose]:async()=>await r[Symbol.asyncDispose]()})},shutdown:async()=>await t.shutdown()})}export{at as createAndroidPlatformRuntime};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{F as t,H as n,L as r,P as i,U as a,W as o}from"./sdk-batch-runner.js";import{C as s,c,l}from"./sdk-device.js";import{S as u,_ as d,a as f,b as p,d as m,f as ee,g as te,h,l as g,m as ne,n as _,o as v,t as re,u as ie,v as ae}from"./src2.js";import y from"node:path";const b=`This command requires a CoreDevice-backed physical iOS device. The selected XCTest backend supports open, close, interactions, snapshots, and screenshots.`;function x(e){return l(e)?`macos`:e.kind===`device`?`ios-device`:`ios-simulator`}const S=Object.freeze({resourceKind:t,version:1,encode:e=>({...e}),decode:e=>!se(e.transport)||!ce(e.backend)||!C(e.outputPath)||!ue(e.pidPath)||!le(e.transport,e.backend)?oe():{status:`decoded`,descriptor:Object.freeze({transport:e.transport,backend:e.backend,outputPath:e.outputPath,...e.pidPath===void 0?{}:{pidPath:e.pidPath}})}});function oe(){return{status:`invalid`,message:`Invalid Apple app-log descriptor`}}function se(e){return e===`apple-log-stream`||e===`coredevice-console`}function ce(e){return e===`ios-simulator`||e===`ios-device`||e===`macos`}function le(e,t){return e===`coredevice-console`?t===`ios-device`:t!==`ios-device`}function ue(e){return e===void 0||C(e)}function de(e){if(!e.device.appleOs)throw TypeError(`Apple app-log persistence requires an explicit appleOs identity`);return p({resourceKind:t,sessionId:e.sessionId,device:{id:e.device.id,family:`apple`,appleOs:e.device.appleOs,kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target},...e.device.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:e.device.iosPhysicalDeviceBackend}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:u(S,e.descriptor)})}function C(e){return typeof e==`string`&&e.trim().length>0}const w={message:`iOS physical-device app console capture is not supported by the installed devicectl.`,hint:`This devicectl does not expose process launch --console. Markers can still be written to app.log, but app output is not being captured. Use an iOS simulator for agent-device app logs or inspect physical-device logs in Console.app/Xcode until this Xcode toolchain exposes scriptable console capture.`},T={message:`Could not verify iOS physical-device app console capture support.`,hint:`Retry logs clear --restart. If the probe keeps failing, run logs doctor and inspect the request diagnostics for the devicectl help command.`};async function E(e,t){try{let n=await e.appleTools.run({tool:`devicectl`,args:[`device`,`process`,`launch`,`--help`],allowFailure:!0,timeoutMs:5e3},t),r=n.stderr.trim()||void 0;if(n.exitCode!==0)return{supported:!1,reason:`probe-failed`,stderr:r};let i=`${n.stdout}\n${n.stderr}`;return/\bUSAGE:\s+devicectl device process launch\b/i.test(i)&&/--console\b/.test(i)&&/--terminate-existing\b/.test(i)?{supported:!0,...r?{stderr:r}:{}}:{supported:!1,reason:`unsupported`,...r?{stderr:r}:{}}}catch(e){if(t?.aborted)throw t.reason;return{supported:!1,reason:`probe-failed`,...e instanceof Error?{stderr:e.message}:{}}}}async function fe(e,t,n,r){let i={},a=n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`];if(l(t))i.logAvailable=!!await e.commands.which(`log`);else if(t.kind===`simulator`)i.simctlAvailable=await v(async()=>f(await e.appleTools.run({tool:`simctl`,args:[`help`],allowFailure:!0},r)),r);else if(t.iosPhysicalDeviceBackend===`xctest`)i.devicectlAvailable=!1,i.devicectlConsoleCapture=!1,a.push(b);else{i.devicectlAvailable=await v(async()=>f(await e.appleTools.run({tool:`devicectl`,args:[`--version`],allowFailure:!0},r)),r);let t=await E(e,r);if(i.devicectlConsoleCapture=t.supported,!t.supported){let e=t.reason===`unsupported`?w:T;a.push(`${e.message} ${e.hint}`)}}return{backend:x(t),checks:i,notes:a}}function D(e,t){let n=A(e),r=[`subsystem == "${n}"`,`subsystem CONTAINS "${n}"`,`processImagePath ENDSWITH[c] "/${n}"`,`senderImagePath ENDSWITH[c] "/${n}"`];if(t){let e=A(t);r.push(`process == "${e}"`,`processImagePath ENDSWITH[c] "/${e}"`,`senderImagePath ENDSWITH[c] "/${e}"`,`processImagePath CONTAINS[c] "/${e}.app/"`,`senderImagePath CONTAINS[c] "/${e}.app/"`)}return r.join(` OR `)}function O(e){return[...e.simulatorSetPath?[`simctl`,`--set`,e.simulatorSetPath]:[`simctl`],`spawn`,e.deviceId,`log`,`stream`,`--style`,`compact`,`--level`,`info`,`--predicate`,D(e.appBundleId,e.executableName)]}function k(e,t){return[`devicectl`,`device`,`process`,`launch`,`--device`,e,`--console`,`--terminate-existing`,t]}function A(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`)}async function j(e,t,n,r,i){M(t),ie(e,n);let o=x(t),s=await P(e,t,n.appBundleId,i),c=new a,l=!1;try{let a=await e.outputs.openAppend(n.outputPath);c.defer(async()=>{l||await a[Symbol.asyncDispose]()}),i?.throwIfAborted();let u=await N(e,t,s,a,n.pidPath,i);c.defer(async()=>{l||await u[Symbol.asyncDispose]()});let d=I(e,u,a,o,n.outputPath),f={transport:o===`ios-device`?`coredevice-console`:`apple-log-stream`,backend:o,outputPath:n.outputPath,...n.pidPath===void 0?{}:{pidPath:n.pidPath}},p=ae(d,de({sessionId:n.sessionId,device:t,owner:r,fence:n.fence,descriptor:f}));return l=!0,p}finally{await c[Symbol.asyncDispose]()}}function M(t){if(t.appleOs===`watchos`)throw new e(`UNSUPPORTED_PLATFORM`,`watchOS app logs are not supported`);if(c(t)&&t.kind===`device`&&t.iosPhysicalDeviceBackend===`xctest`)throw new e(`UNSUPPORTED_OPERATION`,b,{hint:b})}async function N(t,n,r,i,a,o){if(c(n)&&n.kind===`device`){let n=await E(t,o);if(!n.supported){let t=n.reason===`unsupported`?w:T;throw new e(n.reason===`unsupported`?`UNSUPPORTED_OPERATION`:`COMMAND_FAILED`,t.message,{backend:`ios-device`,hint:t.hint,stderr:n.stderr})}}return o?.throwIfAborted(),await t.processes.start({command:{kind:`host`,request:r},output:i,...a?{markerPath:a}:{}})}async function P(e,t,n,r){if(l(t))return{executable:`log`,args:[`stream`,`--style`,`compact`,`--predicate`,D(n)],allowFailure:!0};if(t.kind===`device`)return{executable:`xcrun`,args:k(t.id,n),allowFailure:!0};let i=await F(e,t,n,r);return{executable:`xcrun`,args:O({deviceId:t.id,appBundleId:n,executableName:i,simulatorSetPath:t.simulatorSetPath}),allowFailure:!0}}async function F(e,t,n,r){let i=t.simulatorSetPath?[`--set`,t.simulatorSetPath]:[],a=await e.appleTools.run({tool:`simctl`,args:[...i,`get_app_container`,t.id,n,`app`],allowFailure:!0,timeoutMs:4e3},r),o=a.exitCode===0?a.stdout.trim():``;if(!o)return;let s=await e.commands.run({executable:`plutil`,args:[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,y.join(o,`Info.plist`)],allowFailure:!0,timeoutMs:4e3},r);return s.exitCode===0&&s.stdout.trim()||void 0}function I(e,t,n,r,i){let a=e.clock.now(),o=`active`;t.wait.then(e=>{o=e.exitCode===0?`ended`:`failed`},()=>{o=`failed`});let s;return te({inspect:()=>({backend:r,state:o,startedAt:a}),finish:async()=>s??=(async()=>(await L([async()=>await t.terminate(),async()=>await t.wait.then(()=>void 0),async()=>await t[Symbol.asyncDispose](),async()=>await n[Symbol.asyncDispose]()])).length>0?(o=`failed`,{status:`cleanup-pending`,reason:`transport-failed`,message:`Apple app-log cleanup did not settle every owned resource`}):(o=`ended`,{status:`completed`,result:{backend:r,outputPath:i,completedAt:e.clock.now()}}))()})}async function L(e){let t=[];for(let n of e)try{await n()}catch(e){t.push(e)}return t}const R=r(`apple`),z=Object.freeze({available:!0});function B(t){return Object.freeze({owner:R,ownsDevice:e=>e.platform===`apple`,bind:async r=>{if(r.intent.kind===`exact-owner`&&!n(r.intent.owner,R))throw new e(`UNSUPPORTED_OPERATION`,`Apple app-log owner identity does not match`);return V(t,r.device,r.scope.signal)},shutdown:async()=>void 0})}function V(t,n,r){if(n.platform!==`apple`)throw new e(`UNSUPPORTED_PLATFORM`,`Apple app-log owner cannot bind ${n.platform}`);let i=d({codec:S,reattach:async(e,r)=>e.backend!==x(n)||!g(t,r.sessionId,e)?{status:`unreattachable`,reason:`descriptor-invalid`,message:`Apple app-log descriptor does not match the bound device or owning session`}:await ee(t,e.pidPath),cleanup:async(e,r)=>e.backend===x(n)&&g(t,r.sessionId,e)?await m(t,e.pidPath):{status:`cleanup-pending`,reason:`ownership-fence-lost`,message:`Apple app-log descriptor does not match the bound device or owning session`}}),a=Object.freeze({appLogInspect:async()=>({backend:x(n)}),appLogDoctor:async({appBundleId:e})=>await fe(t,n,e,r),appLogStart:async e=>await j(t,n,e,R,r),...i});return Object.freeze({device:n,owner:R,facts:pe(n),operations:a,[Symbol.asyncDispose]:async()=>void 0})}function pe(e){if(e.appleOs===`watchos`)return me(e);let t=c(e)&&e.kind===`device`&&e.iosPhysicalDeviceBackend===`xctest`?{available:!1,reason:`unsupported-device-backend`,hint:b}:z;return Object.freeze({device:{family:`apple`,appleOs:e.appleOs,kind:e.kind,...e.target===void 0?{}:{target:e.target},...e.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:e.iosPhysicalDeviceBackend},providerMode:`local`},operations:{appLogInspect:t,appLogDoctor:t,appLogStart:t,appLogReattach:z,appLogCleanup:z}})}function me(e){let t=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`watchOS app logs are not supported.`});return Object.freeze({device:{family:`apple`,appleOs:`watchos`,kind:e.kind,...e.target===void 0?{}:{target:e.target},providerMode:`local`},operations:{appLogInspect:t,appLogDoctor:t,appLogStart:t,appLogReattach:t,appLogCleanup:t}})}async function he(e,t,n,r){let i=x(t),a=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),o=_(a.text,{...n,path:a.path,exists:a.exists,lineNumberOffset:a.skippedLines,backend:i}),s=[];if(ge(t,n,o)){let i=await _e(e,t,n,a.path,r);i&&(i.dump.entries.length>0?(o=re(i.dump,o,n.maxEntries),s.push(`Recovered ${i.dump.entries.length} iOS simulator HTTP entr${i.dump.entries.length===1?`y`:`ies`} from simctl log show (${i.lineCount} app log lines scanned).`)):i.lineCount>0&&s.push(`Recovered ${i.lineCount} recent iOS simulator app log lines from simctl log show, but none looked like HTTP traffic. This app may not emit request URLs, status, or timing into Unified Logging for this repro window.`))}return ye(s,t,n),o.entries.length===0&&s.push(be(t)),Object.freeze({source:`app-log`,backend:i,dump:o,notes:Object.freeze(s)})}function ge(e,t,n){return c(e)&&e.kind===`simulator`&&!!t.appBundleId&&n.entries.length===0}async function _e(e,t,n,r,i){let a=[...t.simulatorSetPath?[`--set`,t.simulatorSetPath]:[],`spawn`,t.id,`log`,`show`,`--style`,`compact`,`--info`,`--predicate`,ve(n.appBundleId)],o=n.appLogSnapshot?.startedAt;a.push(...typeof o==`number`&&Number.isFinite(o)&&o>0?[`--start`,`@${Math.floor(o/1e3)}`]:[`--last`,`5m`]);let s=await e.appleTools.run({tool:`simctl`,args:a,allowFailure:!0,timeoutMs:4e3},i);if(s.exitCode!==0||!s.stdout.trim())return;let c=s.stdout.split(`
|
|
2
|
+
`).map(e=>e.trimEnd()).filter(e=>e.trim()&&!e.trim().startsWith(`Timestamp Ty Process[PID:TID]`));if(c.length!==0)return{dump:_(`${c.join(`
|
|
3
|
+
`)}\n`,{...n,path:`${r} (simctl log show recovery)`,exists:!0,backend:`ios-simulator`}),lineCount:c.length}}function ve(e){let t=e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`);return[`subsystem == "${t}"`,`subsystem CONTAINS "${t}"`,`processImagePath ENDSWITH[c] "/${t}"`,`senderImagePath ENDSWITH[c] "/${t}"`].join(` OR `)}function ye(e,t,n){n.appLogSnapshot?n.appLogSnapshot.state!==`active`&&e.length===0&&e.push(c(t)&&t.kind===`simulator`?`Session app log stream is inactive. The iOS simulator recovery path scanned recent simctl log history, but a fresh logs clear --restart window is still the most reliable repro loop.`:`Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.`):e.push(`Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests.`)}function be(e){return c(e)&&e.kind===`simulator`?`No HTTP(s) entries were found in recent iOS simulator app logs. If the app only emits non-HTTP diagnostics, inspect logs path or add app-side URLSession/network logging for per-request timing and payload details.`:c(e)?`No HTTP(s) entries were found in recent iOS device app logs. iOS network dump only sees what the app emits into Unified Logging for this process.`:`No HTTP(s) entries were found in recent session app logs.`}async function H(e,t,n){if(t.invalidatedReason&&!t.showTouches)throw Error(`recording invalidated: ${t.invalidatedReason}`);return ne(t,{...await e.screenRecording.finalize.complete({outputPath:t.outPath,showTouches:t.invalidatedReason?!1:t.showTouches,gestureEvents:t.gestureEvents,exportQuality:t.exportQuality??`medium`,...t.runnerStartedAtUptimeMs!==void 0&&t.targetAppReadyUptimeMs!==void 0?{trimStartMs:Math.max(0,t.targetAppReadyUptimeMs-t.runnerStartedAtUptimeMs)}:{},targetLabel:n}),...t.invalidatedReason?{overlayWarning:`overlay unavailable: ${t.invalidatedReason}`}:{}})}const U=Object.freeze({resourceKind:i,version:1,encode:e=>e.backend===`simctl`?{backend:e.backend,outputPath:e.outputPath,processes:e.processes.map(e=>({...e}))}:{backend:e.backend,outputPath:e.outputPath,appBundleId:e.appBundleId,runnerSessionId:e.runnerSessionId,runnerAuthority:e.runnerAuthority,...e.remotePath===void 0?{}:{remotePath:e.remotePath}},decode:e=>Ee(e)});function xe(e){let{device:t,owner:n,input:r,descriptor:a}=e;return p({resourceKind:i,sessionId:r.sessionId,device:s(t),owner:n,fence:r.fence,lifecycle:`open`,descriptor:u(U,a)})}async function Se(e,t,n){let r=U.decode(n);return r.status!==`decoded`||!K(t,r.descriptor)?{status:`cleanup-pending`,reason:`manual-recovery-required`}:r.descriptor.backend===`simctl`?await Ce(e,r.descriptor.processes):await we(e,t,r.descriptor)}async function Ce(e,t){let n=await Promise.all(t.map(async t=>await e.screenRecording.apple.inspectProcess(t)));if(n.includes(`ownership-lost`))return{status:`cleanup-pending`,reason:`ownership-fence-lost`};if(n.every(e=>e===`missing`))return{status:`already-missing`};let r=await Promise.all(t.flatMap((t,r)=>n[r]===`owned-alive`?[e.screenRecording.apple.terminateProcess(t)]:[]));return r.includes(`ownership-lost`)?{status:`cleanup-pending`,reason:`ownership-fence-lost`}:r.every(e=>e===`already-missing`)?{status:`already-missing`}:{status:`cleaned`}}async function we(e,t,n){try{let r=await e.screenRecording.apple.inspectRunner(t,n.runnerSessionId,n.runnerAuthority);return r===`missing`?{status:`already-missing`}:r===`ownership-lost`?{status:`cleanup-pending`,reason:`ownership-fence-lost`}:(await e.screenRecording.apple.runRunner(t,{kind:`stop`,appBundleId:n.appBundleId,runnerSessionId:n.runnerSessionId,runnerAuthority:n.runnerAuthority}),{status:`cleaned`})}catch(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:`Apple recording cleanup failed`}}}async function Te(e,t,n){let r=U.decode(n);if(r.status!==`decoded`)return{status:`unreattachable`,reason:`descriptor-invalid`,message:r.message};if(!K(t,r.descriptor))return{status:`unreattachable`,reason:`descriptor-invalid`,message:`Apple screen-recording descriptor does not match the bound device.`};let i=r.descriptor.backend===`simctl`?await Promise.all(r.descriptor.processes.map(async t=>await e.screenRecording.apple.inspectProcess(t))):[await e.screenRecording.apple.inspectRunner(t,r.descriptor.runnerSessionId,r.descriptor.runnerAuthority)];return i.every(e=>e===`missing`)?{status:`missing`}:{status:`unreattachable`,reason:`transport-not-reattachable`,message:i.includes(`ownership-lost`)?`Apple recording ownership no longer matches the durable descriptor.`:`Apple screen recordings require exact cleanup after daemon restart.`}}function Ee(e){return typeof e.outputPath!=`string`||e.outputPath.length===0?q():e.backend===`simctl`?De(e,e.outputPath):e.backend===`runner`?Oe(e,e.outputPath):q()}function De(e,t){let n=je(e.processes);return n?{status:`decoded`,descriptor:Object.freeze({backend:`simctl`,outputPath:t,processes:n})}:q()}function Oe(e,t){return!W(e.appBundleId)||!W(e.runnerSessionId)||!ke(e.runnerAuthority)||!Ae(e.remotePath)?q():{status:`decoded`,descriptor:Object.freeze({backend:`runner`,outputPath:t,appBundleId:e.appBundleId,runnerSessionId:e.runnerSessionId,runnerAuthority:e.runnerAuthority,...e.remotePath===void 0?{}:{remotePath:e.remotePath}})}}function W(e){return typeof e==`string`&&e.length>0}function ke(e){return e===`local-lease`||e===`scoped-provider`}function Ae(e){return e===void 0||G(e)}function G(e){return typeof e==`string`&&/^tmp\/agent-device-recording-\d+\.mp4$/.test(e)}function K(e,t){return e.kind===`simulator`?t.backend===`simctl`:t.backend===`runner`?e.appleOs===`macos`?t.remotePath===void 0:c(e)?t.remotePath!==void 0&&G(t.remotePath):t.remotePath===void 0:!1}function je(e){if(!Array.isArray(e)||e.length===0)return;let t=e.filter(e=>typeof e==`object`&&!!e&&Number.isInteger(e.pid)&&(e.pid??0)>0&&typeof e.startTime==`string`&&e.startTime.length>0&&typeof e.command==`string`&&e.command.length>0);return t.length===e.length?Object.freeze([...t]):void 0}function q(){return{status:`invalid`,message:`Invalid Apple screen-recording descriptor`}}async function Me(e,t,n){if(e.kind!==`simulator`||t.scope!==`app`)return;let r=t.activeSessionApp?.bundleId;if(!r)throw TypeError(`App-scoped recording requires an active app session; open the app under test before recording.`);if(await n(r))throw TypeError(`App-scoped recording requires a real application session; open the app under test before recording.`)}function Ne(e){return e.appleOs===`watchos`?Q(`unsupported-platform-leaf`,`watchOS recording is not supported.`):c(e)&&e.kind===`device`&&e.iosPhysicalDeviceBackend===`xctest`?Q(`unsupported-device-backend`,`This command requires a CoreDevice-backed physical iOS device. The selected XCTest backend supports open, close, interactions, snapshots, and screenshots.`):Object.freeze({available:!0})}function Pe(e){let{host:t,device:n,owner:r,signal:i}=e;return Object.freeze({screenRecordingStart:async e=>await Fe({host:t,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async e=>await Te(t,n,e.envelope.descriptor.body),screenRecordingCleanup:async e=>await Se(t,n,e.envelope.descriptor.body)})}async function Fe(e){return e.signal.throwIfAborted(),e.device.kind===`simulator`?await J(e):await Ie(e)}async function J(e){let{host:t,device:n,owner:r,input:i,signal:a}=e;await Me(n,i,t.screenRecording.apple.isRunnerBundleId);let o=i.activeSessionApp?await t.screenRecording.apple.captureClockAnchor(n,i.activeSessionApp.bundleId,a):void 0;await t.screenRecording.outputs.prepare(i.outputPath);let s=await t.screenRecording.apple.startSimulator(n,i.outputPath,a),c=s.markers;if(!c||c.length===0)throw await Y(s).catch(()=>{}),Error(`simctl recordVideo did not expose durable process identity`);try{a.throwIfAborted()}catch(e){throw await Y(s).catch(()=>{}),e}return X({device:n,owner:r,input:i,descriptor:{backend:`simctl`,outputPath:i.outputPath,processes:c},snapshot:Z(i,`simctl recordVideo`,{},o),finish:async e=>{await s.terminate();let n=await s.wait;if(n.exitCode!==0)throw Error(`simctl recordVideo exited with code ${n.exitCode}`);return await H(t,e,`iOS recording`)},cleanup:async()=>await Re(s)})}async function Ie(e){let{host:t,device:n,owner:r,input:i,signal:a}=e,o=i.activeSessionApp?.bundleId;if(!o)throw TypeError(`Apple runner recording requires an active app session identity`);await t.screenRecording.outputs.prepare(i.outputPath);let s=await t.screenRecording.apple.runRunner(n,{kind:`start`,appBundleId:o,outputPath:i.outputPath,...i.fps===void 0?{}:{fps:i.fps}},a);if(!s.runnerSessionId||!s.runnerAuthority)throw Error(`Apple runner recording did not expose durable session ownership`);let c={runnerSessionId:s.runnerSessionId,runnerAuthority:s.runnerAuthority},l,u=()=>l??=t.screenRecording.apple.runRunner(n,{kind:`stop`,appBundleId:o,...c}).then(()=>void 0);if(!Le(n,s.remotePath))throw await u().catch(()=>{}),Error(`Apple runner recording did not expose coherent durable media ownership`);try{a.throwIfAborted()}catch(e){throw await u().catch(()=>{}),e}return X({device:n,owner:r,input:i,descriptor:{backend:`runner`,outputPath:i.outputPath,appBundleId:o,...c,...s.remotePath===void 0?{}:{remotePath:s.remotePath}},snapshot:Z(i,`runner AVAssetWriter`,s),finish:async e=>(await u(),s.remotePath!==void 0&&await t.screenRecording.apple.retrieveRunnerRecording(n,s.remotePath,e.outPath),await H(t,e,n.appleOs===`macos`?`macOS recording`:`iOS recording`)),cleanup:async()=>(await u(),{status:`cleaned`})})}function Le(e,t){return e.appleOs===`macos`||!c(e)?t===void 0:t!==void 0&&/^tmp\/agent-device-recording-\d+\.mp4$/.test(t)}async function Y(e){return await e.terminate(),await e.wait}async function Re(e){try{return await Y(e),{status:`cleaned`}}catch(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:`Apple simulator cleanup failed`}}}function X(e){let{device:t,owner:n,input:r,descriptor:i,snapshot:a,finish:s,cleanup:c}=e,l=h(a,{finish:s,forceCleanup:c});return Object.freeze({pendingHandle:new o(l),envelope:xe({device:t,owner:n,input:r,descriptor:i})})}function Z(e,t,n={},r){let i=Date.now();return Object.freeze({backend:t,outPath:e.outputPath,...e.clientOutputPath===void 0?{}:{clientOutPath:e.clientOutputPath},startedAt:i,scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,...e.activeSessionApp===void 0?{}:{activeSessionApp:e.activeSessionApp},...e.exportQuality===void 0?{}:{exportQuality:e.exportQuality},gestureEvents:[],...r===void 0?{}:{gestureClockOriginAtMs:r.wallClockAtMs,gestureClockOriginUptimeMs:r.uptimeMs},...n.recorderStartUptimeMs===void 0?{}:{gestureClockOriginAtMs:i,gestureClockOriginUptimeMs:n.recorderStartUptimeMs,runnerStartedAtUptimeMs:n.recorderStartUptimeMs},...n.targetAppReadyUptimeMs===void 0?{}:{targetAppReadyUptimeMs:n.targetAppReadyUptimeMs},...n.runnerSessionId===void 0?{}:{runnerSessionId:n.runnerSessionId}})}function Q(e,t){return Object.freeze({available:!1,reason:e,hint:t})}const $=r(`apple`),ze=Object.freeze({available:!0});function Be(e){let t=B(e);return Object.freeze({owner:$,ownsDevice:e=>e.platform===`apple`,bind:async n=>{let r=await t.bind(n),i=Ne(n.device),a=i.available?await e.screenRecording.apple.availability(n.device):void 0,o=i.available&&a?.available===!1?Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:a.hint}):i;return Object.freeze({device:r.device,owner:$,facts:Object.freeze({device:r.facts.device,operations:{...r.facts.operations,networkDump:ze,screenRecordingStart:o,screenRecordingReattach:o,screenRecordingCleanup:o}}),operations:Object.freeze({...r.operations,networkDump:async t=>await he(e,n.device,t,n.scope.signal),...o.available?Pe({host:e,device:n.device,owner:$,signal:n.scope.signal}):{}}),[Symbol.asyncDispose]:async()=>await r[Symbol.asyncDispose]()})},shutdown:async()=>await t.shutdown()})}export{Be as createApplePlatformRuntime};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{F as t,L as n,P as r,W as i}from"./sdk-batch-runner.js";import{C as a}from"./sdk-device.js";import{S as o,b as s,c,h as l,m as u,p as d,s as f}from"./src2.js";import{randomUUID as p}from"node:crypto";const m=Object.freeze({resourceKind:t,version:1,encode:e=>({...e}),decode:e=>e.transport!==`harmony-hilog`||!g(e.outputPath)||!g(e.pidPath)?{status:`invalid`,message:`Invalid HarmonyOS app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:`harmony-hilog`,outputPath:e.outputPath,pidPath:e.pidPath})}});function h(e){return s({resourceKind:t,sessionId:e.sessionId,device:{id:e.device.id,family:`harmonyos`,kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:o(m,e.descriptor)})}function g(e){return typeof e==`string`&&e.trim().length>0}function _(e){return f(e,{family:`harmonyos`,backend:`harmonyos`,label:`HarmonyOS`,codec:m,startUnavailableHint:`The selected HarmonyOS transport cannot start a background hilog stream.`,cleanupFailureMessage:`HarmonyOS app-log cleanup did not settle every owned resource`,doctor:async(e,t)=>({backend:`harmonyos`,checks:{},notes:t?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}),process:async({host:e,device:t,input:n,signal:r})=>{let i=await v(e,r);return{resolvePid:async r=>await c(e,{executable:i,args:[`-t`,t.id,`shell`,`pidof`,n.appBundleId],allowFailure:!0,timeoutMs:5e3},r),command:e=>({kind:`host`,request:{executable:i,args:[`-t`,t.id,`shell`,`hilog`,`-P`,e],allowFailure:!0}})}},descriptor:({artifacts:e})=>({transport:`harmony-hilog`,...e}),envelope:({input:e,device:t,owner:n,descriptor:r})=>h({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function v(t,n){n.throwIfAborted(),await y(async()=>await t.toolchains.prepare(`harmonyos`),n),n.throwIfAborted();let r=await y(async()=>await t.commands.which(`hdc`),n);if(n.throwIfAborted(),!r)throw new e(`TOOL_MISSING`,`hdc not found in PATH`,{hint:`Install HarmonyOS Command Line Tools, then add its sdk/default/openharmony/toolchains directory to PATH.`});return r}async function y(e,t){try{return await e()}catch(e){throw t.throwIfAborted(),e}}const b=Object.freeze({resourceKind:r,version:1,encode:e=>({...e}),decode:e=>e.backend===`harmony-screen-recorder`&&typeof e.fileName==`string`&&C(e.fileName)&&e.remotePath===`/data/local/tmp/${e.fileName}`?{status:`decoded`,descriptor:Object.freeze({backend:`harmony-screen-recorder`,fileName:e.fileName,remotePath:e.remotePath})}:{status:`invalid`,message:`Invalid HarmonyOS screen-recording descriptor`}});function x(e){let{device:t,owner:n,input:i,descriptor:c}=e;return s({resourceKind:r,sessionId:i.sessionId,device:a(t),owner:n,fence:i.fence,lifecycle:`open`,descriptor:o(b,c)})}function S(e){return b.decode(e).status===`decoded`?{status:`cleanup-pending`,reason:`manual-recovery-required`,message:`HarmonyOS recorder ownership cannot be proven after daemon restart; no recorder was stopped.`}:{status:`cleanup-pending`,reason:`manual-recovery-required`}}function C(e){return/^agent-device-recording-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.mp4$/i.test(e)}function w(e){return e.kind===`device`?Object.freeze({available:!0}):Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`HarmonyOS recording is supported on physical devices only.`})}function T(e){let{host:t,device:n,owner:r,signal:i}=e;return Object.freeze({screenRecordingStart:async e=>await E({host:t,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async()=>({status:`unreattachable`,reason:`transport-not-reattachable`,message:`HarmonyOS recordings cannot be reattached after daemon restart.`}),screenRecordingCleanup:async e=>S(e.envelope.descriptor.body)})}async function E(t){let{host:n,device:r,owner:a,input:o,signal:s}=t;if(o.scope===`app`)throw new e(`INVALID_ARGS`,`HarmonyOS recording captures the whole physical-device screen; use --scope device or --scope system`);d(o,{scopes:[`device`,`system`],fps:!1,exportQuality:!1,hideTouches:!1},e=>`HarmonyOS recordings do not support ${e.join(`, `)}`),s.throwIfAborted(),await n.screenRecording.outputs.prepare(o.outputPath);let c=`agent-device-recording-${p()}.mp4`,u={backend:`harmony-screen-recorder`,fileName:c,remotePath:`/data/local/tmp/${c}`},f;try{f=await n.screenRecording.harmony.start(r,c,s),s.throwIfAborted()}catch(e){throw s.aborted?(await A(n,r,u).catch(()=>{}),s.reason):e}N(f,`start`);try{s.throwIfAborted()}catch(e){throw await A(n,r,u).catch(()=>{}),e}let m=D(o),h=!1,g=async()=>{h||=(N(await n.screenRecording.harmony.stop(r),`stop`),!0)},_=l(m,{finish:async e=>await O(n,r,e,u,g),forceCleanup:async()=>await A(n,r,u,g)});return Object.freeze({pendingHandle:new i(_),envelope:x({device:r,owner:a,input:o,descriptor:u})})}function D(e){return Object.freeze({backend:`HarmonyOS ScreenRecorder`,outPath:e.outputPath,...e.clientOutputPath===void 0?{}:{clientOutPath:e.clientOutputPath},startedAt:Date.now(),scope:e.scope,showTouches:!1,recordOnlySession:e.recordOnlySession,...e.activeSessionApp===void 0?{}:{activeSessionApp:e.activeSessionApp},gestureEvents:[]})}async function O(e,t,n,r,i){await i();let a=await e.screenRecording.harmony.findMedia(t,r.fileName);if(!a)throw Error(`failed to find finalized HarmonyOS recording '${r.fileName}'`);if(!await k(e,t,r,a))throw Error(`failed to finalize HarmonyOS recording: ${r.fileName} did not produce a non-empty media file`);let o=!1;try{if((await e.screenRecording.harmony.pull(t,{remotePath:r.remotePath,outputPath:n.outPath})).exitCode!==0)throw Error(`failed to retrieve HarmonyOS recording`);let i=await e.screenRecording.finalize.complete({outputPath:n.outPath,showTouches:!1,gestureEvents:n.gestureEvents,targetLabel:`HarmonyOS recording`});return o=!0,u(n,i,!1)}finally{await e.screenRecording.harmony.remove(t,r.remotePath).catch(()=>{}),o&&await e.screenRecording.harmony.removeMedia(t,a).catch(()=>{})}}async function k(e,t,n,r){let i;for(let a=0;a<40;a+=1){if(await e.screenRecording.harmony.remove(t,n.remotePath).catch(()=>{}),await e.screenRecording.harmony.stageMedia(t,{mediaUri:r,remotePath:n.remotePath})){let r=await e.screenRecording.harmony.stagedFileSize(t,n.remotePath);if(r!==void 0&&r>0&&r===i)return!0;i=r!==void 0&&r>0?r:void 0}else i=void 0;a<39&&await e.clock.sleep(250)}return!1}async function A(e,t,n,r=async()=>{N(await e.screenRecording.harmony.stop(t),`stop`)}){let i=[await M(r),await M(async()=>{if(!await e.screenRecording.harmony.remove(t,n.remotePath))throw Error(`HarmonyOS recording staging artifact removal was not confirmed`)}),await M(async()=>await j(e,t,n.fileName))].find(e=>e!==void 0);return i===void 0?{status:`cleaned`}:{status:`cleanup-pending`,reason:`transport-failed`,message:i instanceof Error?i.message:`HarmonyOS recording cleanup failed`}}async function j(e,t,n){let r=await e.screenRecording.harmony.findMedia(t,n);if(r&&!await e.screenRecording.harmony.removeMedia(t,r))throw Error(`HarmonyOS recording media removal was not confirmed`)}async function M(e){try{await e();return}catch(e){return e}}function N(e,t){if(e.exitCode===0&&e.stdout.includes(`start ability successfully`))return;let n=e.stdout.trim()||e.stderr.trim()||`hdc exit ${e.exitCode}`;throw Error(`failed to ${t} HarmonyOS screen recording: ${n}`)}const P=n(`harmonyos`),F=Object.freeze({available:!1,reason:`unsupported-platform-leaf`});function I(e){let t=_(e);return Object.freeze({owner:P,ownsDevice:e=>e.platform===`harmonyos`,bind:async n=>{let r=await t.bind(n),i=w(n.device);return Object.freeze({device:r.device,owner:P,facts:Object.freeze({device:r.facts.device,operations:{...r.facts.operations,networkDump:F,screenRecordingStart:i,screenRecordingReattach:i,screenRecordingCleanup:i}}),operations:Object.freeze({...r.operations,...i.available?T({host:e,device:n.device,owner:P,signal:n.scope.signal}):{}}),[Symbol.asyncDispose]:async()=>await r[Symbol.asyncDispose]()})},shutdown:async()=>await t.shutdown()})}export{I as createHarmonyPlatformRuntime};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e}from"./src2.js";const t=Object.freeze({available:!1,reason:`unsupported-platform-leaf`});function n(){return e(`linux`,{appLog:t,network:t})}export{n as createLinuxPlatformRuntime};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e}from"./src2.js";const t=Object.freeze({available:!1,reason:`unsupported-platform-leaf`});function n(){return e(`vega`,{appLog:t,network:t})}export{n as createVegaPlatformRuntime};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{H as t,L as n,P as r,W as i}from"./sdk-batch-runner.js";import{C as a}from"./sdk-device.js";import{S as o,b as s,h as c,m as l,p as u}from"./src2.js";const d=Object.freeze({resourceKind:r,version:1,encode:e=>({...e}),decode:e=>e.backend===`agent-browser`&&typeof e.outputPath==`string`?{status:`decoded`,descriptor:Object.freeze({backend:`agent-browser`,outputPath:e.outputPath})}:{status:`invalid`,message:`Invalid web screen-recording descriptor`}});async function f(e){let{host:t,device:n,owner:r,signal:i}=e,a=await t.screenRecording.web.resolve(n);return a?{available:!0,operations:{screenRecordingStart:async e=>await p({host:t,transport:a,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async()=>({status:`unreattachable`,reason:`transport-not-reattachable`,message:`Web recordings cannot be reattached after daemon restart.`}),screenRecordingCleanup:async()=>m()}}:{available:!1,operations:{}}}async function p(t){let{host:n,transport:f,device:p,owner:m,input:h,signal:g}=t;if(h.recordOnlySession)throw new e(`INVALID_ARGS`,`record on web requires an active browser session; run open <url> --platform web first`);if(!h.outputPath.toLowerCase().endsWith(`.webm`))throw new e(`INVALID_ARGS`,`web recordings require a .webm output path; agent-browser records WebM directly`);u(h,{scopes:[`app`],fps:!1,exportQuality:!1,hideTouches:!1},e=>`web recordings do not support ${e.join(`, `)}; agent-browser records WebM directly`),g.throwIfAborted(),await n.screenRecording.outputs.prepare(h.outputPath);let _=!1;try{await f.start(h.outputPath,g),_=!0,g.throwIfAborted()}catch(e){throw _&&await f.stop().catch(()=>{}),g.throwIfAborted(),e}let v=!1,y=async()=>{v||=(await f.stop(),!0)},b=c({backend:`agent-browser`,outPath:h.outputPath,...h.clientOutputPath===void 0?{}:{clientOutPath:h.clientOutputPath},startedAt:Date.now(),scope:h.scope,showTouches:!1,recordOnlySession:h.recordOnlySession,...h.activeSessionApp===void 0?{}:{activeSessionApp:h.activeSessionApp},gestureEvents:[]},{finish:async e=>(await y(),l(e,await n.screenRecording.finalize.complete({outputPath:e.outPath,showTouches:!1,gestureEvents:e.gestureEvents,targetLabel:`web recording`}),!1)),forceCleanup:async()=>{try{return await y(),{status:`cleaned`}}catch(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:`Web recording cleanup failed`}}}});return Object.freeze({pendingHandle:new i(b),envelope:s({resourceKind:r,sessionId:h.sessionId,device:a(p),owner:m,fence:h.fence,lifecycle:`open`,descriptor:o(d,{backend:`agent-browser`,outputPath:h.outputPath})})})}function m(){return{status:`cleanup-pending`,reason:`manual-recovery-required`,message:`Web recordings cannot be cleaned after daemon restart.`}}const h=n(`web`),g=Object.freeze({available:!0}),_=Object.freeze({available:!1,reason:`unsupported-platform-leaf`}),v=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`record is not supported by this web provider`});function y(n){return Object.freeze({owner:h,ownsDevice:e=>e.platform===`web`,bind:async r=>{if(r.intent.kind===`exact-owner`&&!t(r.intent.owner,h))throw new e(`UNSUPPORTED_OPERATION`,`Web runtime owner identity does not match`);if(r.device.platform!==`web`)throw new e(`UNSUPPORTED_PLATFORM`,`Web runtime owner cannot bind ${r.device.platform}`);let i=await n.networkTransports.resolve(r.device),a=await f({host:n,device:r.device,owner:h,signal:r.scope.signal});return b(r.device,r.scope.signal,i,a)},shutdown:async()=>void 0})}function b(e,t,n,r){let i=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`network is not supported by this web provider`}),a=n.dump,o={...a?{networkDump:async e=>{let n=await a({maxEntries:e.maxEntries,include:e.include},t);return Object.freeze({source:`provider`,...n})}}:{},...r.operations},s=Object.freeze({device:{family:`web`,kind:e.kind,...e.target===void 0?{}:{target:e.target},providerMode:n.mode},operations:{appLogInspect:_,appLogDoctor:_,appLogStart:_,appLogReattach:_,appLogCleanup:_,networkDump:n.dump?g:i,screenRecordingStart:r.available?g:v,screenRecordingReattach:r.available?g:v,screenRecordingCleanup:r.available?g:v}});return Object.freeze({device:e,owner:h,facts:s,operations:Object.freeze(o),[Symbol.asyncDispose]:async()=>void 0})}export{y as createWebPlatformRuntime};
|