agent-device 0.17.1 → 0.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +3 -3
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.1.apk → agent-device-android-multitouch-helper-0.17.3.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.3.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.1.manifest.json → agent-device-android-multitouch-helper-0.17.3.manifest.json} +4 -4
  5. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.1.apk → agent-device-android-snapshot-helper-0.17.3.apk} +0 -0
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.3.apk.sha256 +1 -0
  7. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.1.manifest.json → agent-device-android-snapshot-helper-0.17.3.manifest.json} +6 -6
  8. package/dist/src/123.js +1 -0
  9. package/dist/src/1231.js +1 -1
  10. package/dist/src/1352.js +1 -1
  11. package/dist/src/221.js +2 -2
  12. package/dist/src/2403.js +3 -0
  13. package/dist/src/2415.js +36 -30
  14. package/dist/src/4778.js +1 -1
  15. package/dist/src/5611.js +1 -0
  16. package/dist/src/5827.js +1 -0
  17. package/dist/src/6088.js +1 -0
  18. package/dist/src/6133.js +1 -0
  19. package/dist/src/7556.js +1 -1
  20. package/dist/src/7847.js +1 -1
  21. package/dist/src/8806.js +3 -3
  22. package/dist/src/9010.js +1 -0
  23. package/dist/src/9238.js +3 -3
  24. package/dist/src/9471.js +1 -1
  25. package/dist/src/9542.js +6 -3
  26. package/dist/src/9616.js +2 -0
  27. package/dist/src/9818.js +1 -1
  28. package/dist/src/android-adb.d.ts +12 -6
  29. package/dist/src/android-adb.js +1 -1
  30. package/dist/src/android-snapshot-helper.d.ts +15 -8
  31. package/dist/src/android.js +5 -5
  32. package/dist/src/apple.js +1 -1
  33. package/dist/src/apps.js +10 -10
  34. package/dist/src/args.js +53 -14
  35. package/dist/src/batch.d.ts +16 -4
  36. package/dist/src/batch.js +1 -1
  37. package/dist/src/cli-output.js +29 -0
  38. package/dist/src/cli.js +17 -42
  39. package/dist/src/command-surface.js +1 -1
  40. package/dist/src/contracts.d.ts +80 -4
  41. package/dist/src/contracts.js +1 -1
  42. package/dist/src/find.js +1 -1
  43. package/dist/src/finders.d.ts +3 -1
  44. package/dist/src/generic.js +7 -7
  45. package/dist/src/index.d.ts +250 -79
  46. package/dist/src/index.js +1 -1
  47. package/dist/src/input-actions.js +1 -1
  48. package/dist/src/interaction.js +1 -1
  49. package/dist/src/internal/png-worker.d.ts +26 -0
  50. package/dist/src/internal/png-worker.js +1 -0
  51. package/dist/src/metro.d.ts +3 -1
  52. package/dist/src/react-native.js +1 -1
  53. package/dist/src/record-trace-recording.js +3 -3
  54. package/dist/src/remote-config.d.ts +33 -7
  55. package/dist/src/selector-runtime.js +1 -1
  56. package/dist/src/selectors.d.ts +17 -3
  57. package/dist/src/selectors.js +1 -1
  58. package/dist/src/server.js +2 -2
  59. package/dist/src/session.js +8 -11
  60. package/dist/src/snapshot.js +2 -2
  61. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
  62. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +14 -0
  63. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +297 -0
  64. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +328 -0
  65. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +121 -172
  66. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +153 -5
  67. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +171 -0
  68. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -10
  69. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +64 -18
  70. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +200 -0
  71. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +406 -0
  72. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +82 -169
  73. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +425 -0
  74. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +77 -6
  75. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +10 -1
  76. package/ios-runner/README.md +5 -5
  77. package/ios-runner/RUNNER_PROTOCOL.md +0 -1
  78. package/package.json +8 -5
  79. package/server.json +2 -2
  80. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.1.apk.sha256 +0 -1
  81. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.1.apk.sha256 +0 -1
  82. package/dist/src/1998.js +0 -1
  83. package/dist/src/2805.js +0 -1
  84. package/dist/src/4057.js +0 -1
  85. package/dist/src/5310.js +0 -1
  86. package/dist/src/5792.js +0 -1
  87. package/dist/src/6085.js +0 -1
  88. package/dist/src/6232.js +0 -1
  89. package/dist/src/7455.js +0 -1
  90. package/dist/src/8020.js +0 -1
  91. package/dist/src/8502.js +0 -1
  92. package/dist/src/8699.js +0 -1
  93. package/dist/src/940.js +0 -1
  94. package/dist/src/9404.js +0 -1
  95. package/dist/src/9533.js +0 -1
  96. package/dist/src/command-metadata.js +0 -1
  97. /package/dist/src/{1393.js → 3675.js} +0 -0
package/README.md CHANGED
@@ -27,10 +27,10 @@ It works with native iOS and Android apps, plus apps built with Expo, Flutter, a
27
27
 
28
28
  ## Capabilities
29
29
 
30
- - **Inspect** real app UI through compact accessibility snapshots, interactive refs like `@e3`, selectors, and React Native component trees.
30
+ - **Inspect** real app UI through structured accessibility snapshots, interactive refs like `@e3`, selectors, and React Native component trees.
31
31
  - **Interact** by opening apps, tapping, typing, scrolling, performing gestures, waiting, asserting state, handling alerts, and closing sessions.
32
32
  - **Capture evidence** with screenshots, videos, logs, traces, network traffic, performance samples, crash context, and React profiles.
33
- - **Replay workflows** by recording `.ad` scripts for local runs, CI, and repeatable e2e checks.
33
+ - **Replay workflows** by recording `.ad` scripts for local runs, CI, repeatable e2e checks, and strict Maestro YAML export when a flow needs to run in Maestro.
34
34
  - **Run across platforms** with iOS Simulator automation, Android Emulator automation, physical devices, tvOS, Android TV, macOS, Linux, and desktop app automation, so agents can see and feel the app they work on.
35
35
 
36
36
  ## Use Cases
@@ -118,7 +118,7 @@ Appium, Detox, and Maestro are traditional mobile automation frameworks. `agent-
118
118
 
119
119
  ## Used By
120
120
 
121
- Used by teams and developers at Callstack, Expensify, Shopify, Kindred, Total Wine & More, LegendList, HerLyfe, App & Flow, and more.
121
+ Used by teams and developers at Callstack, JPMorgan Chase, Expensify, Shopify, Kindred, Total Wine & More, LegendList, HerLyfe, App & Flow, and more.
122
122
 
123
123
  ## Documentation
124
124
 
@@ -0,0 +1 @@
1
+ 6989d98eafa3826bd53b5d36268b5c96f2c9404f87478d0b541139c25783c26a agent-device-android-multitouch-helper-0.17.3.apk
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "android-multitouch-helper",
3
- "version": "0.17.1",
4
- "assetName": "agent-device-android-multitouch-helper-0.17.1.apk",
5
- "sha256": "185df48455dc51982c340b9e98ec761214b31fb103c72dac6ed7ab8175c3372f",
3
+ "version": "0.17.3",
4
+ "assetName": "agent-device-android-multitouch-helper-0.17.3.apk",
5
+ "sha256": "6989d98eafa3826bd53b5d36268b5c96f2c9404f87478d0b541139c25783c26a",
6
6
  "packageName": "com.callstack.agentdevice.multitouchhelper",
7
- "versionCode": 17001,
7
+ "versionCode": 17003,
8
8
  "instrumentationRunner": "com.callstack.agentdevice.multitouchhelper/.MultiTouchInstrumentation",
9
9
  "statusProtocol": "android-multitouch-helper-v1"
10
10
  }
@@ -0,0 +1 @@
1
+ 522875a8a672915e05710a4b15fb51162de206824f4a19a43028d184b337a76d agent-device-android-snapshot-helper-0.17.3.apk
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "android-snapshot-helper",
3
- "version": "0.17.1",
4
- "releaseTag": "v0.17.1",
5
- "assetName": "agent-device-android-snapshot-helper-0.17.1.apk",
3
+ "version": "0.17.3",
4
+ "releaseTag": "v0.17.3",
5
+ "assetName": "agent-device-android-snapshot-helper-0.17.3.apk",
6
6
  "apkUrl": null,
7
- "sha256": "b0c6a5572c4e7adca466d9cae744d5dc2c9b27d2b705e1a579e3fea47d9570e6",
8
- "checksumName": "agent-device-android-snapshot-helper-0.17.1.apk.sha256",
7
+ "sha256": "522875a8a672915e05710a4b15fb51162de206824f4a19a43028d184b337a76d",
8
+ "checksumName": "agent-device-android-snapshot-helper-0.17.3.apk.sha256",
9
9
  "packageName": "com.callstack.agentdevice.snapshothelper",
10
- "versionCode": 17001,
10
+ "versionCode": 17003,
11
11
  "instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
12
12
  "minSdk": 23,
13
13
  "targetSdk": 36,
@@ -0,0 +1 @@
1
+ import e,{promises as t}from"node:fs";import n from"node:path";import{Worker as a}from"node:worker_threads";import{fileURLToPath as r}from"node:url";import{buildMobileSnapshotPresentation as i,isSparseSnapshotQualityVerdict as s,now as o,isNodeVisibleInEffectiveViewport as l,sleep as d,publicSnapshotCaptureAnnotations as u,scrollCommand as c,longPressCommand as p,appendScreenshotScriptFlags as h,successText as f,focusCommand as m,toBackendResult as w,swipeCommand as g,resolveInteractionTarget as b,toBackendContext as y,snapshotCaptureAnnotationsFrom as k,requireIntInRange as x,formatReactNativeOverlayWarning as v,pinchCommand as A,renderSnapshotQualityWarnings as M}from"./6133.js";import{emitDiagnostic as I}from"./7599.js";import{asAppError as P,toAppErrorCode as R,AppError as N}from"./9152.js";import{computeScreenshotDiffPixels as S,PNG as _,toBuffer as O,decodePng as D}from"./9010.js";import{expandRect as E,intersectArea as T,unionRects as C,rectCenter as U,clamp as $,normalizedRect as L,squaredDistance as B}from"./4778.js";import{whichCmd as G,runCmd as X}from"./9818.js";import{formatSnapshotLine as q,formatRole as Y,displayLabel as K,buildSnapshotDisplayLines as F}from"./5827.js";import{buildSnapshotPresentationKey as V,normalizeRef as j,findNodeByRef as H}from"./9616.js";import{extractNodeText as z,findSnapshotAncestor as W,parseSelectorChain as J,isNodeVisible as Z,buildSnapshotNodeByIndex as Q,isNodeEditable as ee,findSelectorChainMatch as et,buildSelectorChainForNode as en,resolveSelectorChain as ea,findNodeByLabel as er,resolveRefLabel as ei,extractReadableText as es,formatSelectorFailure as eo,normalizeType as el,isFillableType as ed}from"./7847.js";import{findBestMatchesByLocator as eu}from"./7556.js";import{resolveAppsFilter as ec,assertResolvedAppsFilter as ep}from"./3675.js";let eh=/^-?\d+(\.\d+)?$/,ef=/^[^\s"\\]+$/,em=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),ew=new Map([["--count","count"],["--pause-ms","pauseMs"]]),eg=new Map([["--delay-ms","delayMs"]]);function eb(e){return"click"===e||"press"===e}function ey(e){return eb(e)||"longpress"===e}function ek(e){return"type"===e||"fill"===e}function ex(e){return eA(e,eM)}function ev(e){return JSON.stringify(e)}function eA(e,t){return t(e)?e:ev(e)}function eM(e){return eI(e)&&e.startsWith("@")||eh.test(e)}function eI(e){return ef.test(e)}function eP(e){let t=(e.positionals??[]).map(e=>ex(e));return[e.command,...t].join(" ")}function eR(e,t){let n=t.flags??{};if(eb(t.command)){"number"==typeof n.count&&e.push("--count",String(n.count)),"number"==typeof n.intervalMs&&e.push("--interval-ms",String(n.intervalMs)),"number"==typeof n.holdMs&&e.push("--hold-ms",String(n.holdMs)),"number"==typeof n.jitterPx&&e.push("--jitter-px",String(n.jitterPx)),!0===n.doubleTap&&e.push("--double-tap");let t=n.clickButton;t&&"primary"!==t&&e.push("--button",t);return}if("swipe"===t.command){"number"==typeof n.count&&e.push("--count",String(n.count)),"number"==typeof n.pauseMs&&e.push("--pause-ms",String(n.pauseMs)),("one-way"===n.pattern||"ping-pong"===n.pattern)&&e.push("--pattern",n.pattern);return}ek(t.command)&&"number"==typeof n.delayMs&&e.push("--delay-ms",String(n.delayMs))}function eN(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",eA(t.metroHost,eI)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",eA(t.bundleUrl,eI)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",eA(t.launchUrl,eI)))}function eS(e,t){let n=[],a={},r=eb(e)?em:"swipe"===e?ew:ek(e)?eg:void 0;for(let i=0;i<t.length;i+=1){let s=t[i];if(eb(e)&&"--double-tap"===s){a.doubleTap=!0;continue}let o=t[i+1];if(eb(e)&&"--button"===s&&void 0!==o){("primary"===o||"secondary"===o||"middle"===o)&&(a.clickButton=o),i+=1;continue}let l=r?.get(s);if(l&&void 0!==o){let e=eO(o);if(null!==e){a[l]=e,i+=1;continue}}if("swipe"===e&&"--pattern"===s&&void 0!==o){("one-way"===o||"ping-pong"===o)&&(a.pattern=o),i+=1;continue}n.push(s)}return{positionals:n,flags:a}}function e_(e){let t=[],n={};for(let a=0;a<e.length;a+=1){let r=e[a],i=e[a+1];if("--platform"===r&&void 0!==i){("ios"===i||"android"===i)&&(n.platform=i),a+=1;continue}if("--metro-host"===r&&void 0!==i){n.metroHost=i,a+=1;continue}if("--metro-port"===r&&void 0!==i){let e=eO(i);null!==e&&(n.metroPort=e),a+=1;continue}if("--bundle-url"===r&&void 0!==i){n.bundleUrl=i,a+=1;continue}if("--launch-url"===r&&void 0!==i){n.launchUrl=i,a+=1;continue}t.push(r)}return{positionals:t,flags:n}}function eO(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function eD(e){var t;let n=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}n.push(t)}let r=e_(n);return{positionals:r.positionals,flags:a,runtime:(t=r.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?r.flags:void 0}}function eE(e,t={}){let n=[e.command];if("snapshot"===e.command)e.flags?.snapshotInteractiveOnly&&n.push("-i"),"number"==typeof e.flags?.snapshotDepth&&n.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&n.push("-s",ex(e.flags.snapshotScope)),e.flags?.snapshotRaw&&n.push("--raw");else if("open"===e.command){for(let t of e.positionals??[])n.push(ex(t));e.flags?.relaunch&&n.push("--relaunch"),eN(n,e.runtime)}else if("runtime"===e.command)!function(e,t,n={}){let a=t.positionals??[];for(let t of n.includeAllPositionals?a:a.slice(0,1))e.push(eA(t,eI));eN(e,t.flags)}(n,e,{includeAllPositionals:t.runtimeIncludeAllPositionals});else if("record"===e.command)!function(e,t){let[n,...a]=t.positionals??[];for(let t of(n&&e.push(eA(n,eI)),a))e.push(ex(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),"number"==typeof t.flags?.quality&&e.push("--quality",String(t.flags.quality)),t.flags?.hideTouches&&e.push("--hide-touches")}(n,e);else if("screenshot"===e.command){for(let t of e.positionals??[])n.push(ex(t));h(n,e.flags)}else{for(let t of e.positionals??[])n.push(ex(t));eR(n,e)}return n.join(" ")}let eT=["status","get","dismiss","enter","return"];function eC(e){return eT.includes(e)}function eU(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}class e$ extends Error{}let eL=null,eB=!1,eG=!1,eX=0,eq=new Map;function eY(e){eB=!0,eG||(eG=!0,I({level:"warn",phase:"png_worker_unavailable",data:{reason:e}}),process.emitWarning(`PNG worker unavailable, falling back to in-process PNG processing: ${e}`))}function eK(e){let t=eq.get(e.id);t&&(eq.delete(e.id),ej(),e.ok?t.resolve(e.result):t.reject(new N(R(e.error.code),e.error.message,e.error.details)))}function eF(e,t){eL===e&&(eY(t.message),eL=null,e.terminate().catch(()=>{}),eV(new e$(`PNG worker failed: ${t.message}`)))}function eV(e){let t=[...eq.values()];for(let n of(eq.clear(),t))n.reject(e)}function ej(){eL&&(eq.size>0?eL.ref():eL.unref())}function eH(){if(eB)return null;if(eL)return eL;let t=function(t,a){try{let i=r(t),s=n.extname(i)||".js";return[n.join(n.dirname(i),`${a}${s}`),n.join(n.dirname(i),"internal",`${a}${s}`)].find(t=>e.existsSync(t))??null}catch{return null}}(import.meta.url,"png-worker");if(!t)return eY("worker entry module not found next to the current module"),null;try{let e=new a(t,{execArgv:t.endsWith(".ts")?["--experimental-strip-types"]:[]});return e.on("message",eK),e.on("error",t=>{eF(e,t)}),e.on("exit",t=>{eF(e,Error(`PNG worker exited with code ${t}`))}),e.unref(),eL=e,e}catch(e){return eY(`failed to spawn worker: ${e instanceof Error?e.message:String(e)}`),null}}async function ez(e,t){try{return await function(e){let t=eH();if(!t)return Promise.reject(new e$("PNG worker is unavailable"));let n=eX+=1;return new Promise((a,r)=>{eq.set(n,{resolve:a,reject:r}),ej();try{t.postMessage({...e,id:n})}catch(e){eq.delete(n),ej(),r(new e$(`failed to post job to PNG worker: ${e instanceof Error?e.message:String(e)}`))}})}(e)}catch(e){if(e instanceof e$)return t();throw e}}function eW(){eH()}async function eJ(){let e=eL;eL=null,eV(new e$("PNG worker terminated")),e&&await e.terminate()}async function eZ(e,t){let n=await ez({kind:"decode",png:e,label:t},()=>{let n=D(e,t);return{kind:"decode",width:n.width,height:n.height,data:n.data}});return new _({width:n.width,height:n.height,data:O(n.data)})}async function eQ(e){return O((await ez({kind:"encode",width:e.width,height:e.height,data:e.data},()=>({kind:"encode",png:_.sync.write(e)}))).png)}async function e0(e){let{kind:t,...n}=await ez({kind:"diff-pixels",...e},()=>({kind:"diff-pixels",...S(e)}));return{...n,diffData:O(n.diffData)}}let e1=[0,187,255,255];function e2(e,t,n,a){if(t<0||t>=e.width||n<0||n>=e.height)return;let r=(n*e.width+t)*4;e.data[r]=a[0],e.data[r+1]=a[1],e.data[r+2]=a[2],e.data[r+3]=a[3]}function e4(e,t,n){return Math.min(Math.max(e,t),n)}let e3=[{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 e5(e){let{mask:t,width:n,height:a,hooks:r}=e,i=new Uint8Array(t.length),s=new Int32Array(t.length),o=[];for(let e=0;e<t.length;e+=1){var l,d;if(!e8(t,i,e))continue;let u=0,c=(l=s,i[d=e]=1,l[0]=d,1),p=r.create(e);for(;u<c;){let e=s[u];u+=1,r.visit(p,e),c=function(e){let{mask:t,visited:n,queue:a,width:r,height:i,pixelIndex:s}=e,o=s%r,l=Math.floor(s/r),d=e.queueEnd;for(let e of e3){var u,c,p,h;let s=o+e.x,f=l+e.y;if(u=s,c=f,p=r,h=i,!(u>=0)||!(u<p)||!(c>=0)||!(c<h))continue;let m=f*r+s;e8(t,n,m)&&(d=function(e,t,n,a){return t[a]=1,e[n]=a,n+1}(a,n,d,m))}return d}({mask:t,visited:i,queue:s,queueEnd:c,width:n,height:a,pixelIndex:e})}o.push(p)}return o}function e8(e,t,n){return 1===e[n]&&1!==t[n]}let e6={icon:90,toggle:90,chevron:75,separator:45,visual:35,background:10},e9={leading:20,trailing:20,separator:10,unknown:0,background:-30};function e7(e){return"background"!==e.likelyKind}function te(e,t){return e.width>=.25*t.width||e.height>=.06*t.height}function tt(e,t){let n,a=0;for(let r of t){let t=ts(e,r.rect);t<=a||(a=t,n=r)}return n}function tn(e){let t=[];for(let n of[...e].sort((e,t)=>e.rect.y-t.rect.y)){let e=t.find(e=>{var t,a;return t=e.rect,ts(t,a=n.rect)>0||Math.abs(U(t).y-U(a).y)<=.5*Math.max(t.height,a.height)});if(!e){t.push({rect:n.rect,blocks:[n]});continue}e.blocks.push(n),e.blocks.sort((e,t)=>e.rect.x-t.rect.x),e.rect=C([e.rect,n.rect])}return t}function ta(e,t){let n,a=U(e);for(let e of t){let t=Math.sqrt(B(a,U(e.rect)));n&&t>=n.distance||(n={block:e,distance:t})}return n}function tr(e){let t=ti(e);return e.differentPixels>=24&&t.width>=3&&t.height>=3}function ti(e){return{x:e.minX,y:e.minY,width:e.maxX-e.minX+1,height:e.maxY-e.minY+1}}function ts(e,t){return Math.max(0,Math.min(e.y+e.height,t.y+t.height)-Math.max(e.y,t.y))}async function to(e){if(await G("tesseract"))try{let[t,n]=await Promise.all([td(e.baselinePath),td(e.currentPath)]);if(0!==t.exitCode||0!==n.exitCode)return;let a=tl(t.stdout,e.width,e.height),r=tl(n.stdout,e.width,e.height),i=function(e,t){let n=new Set,a=[];for(let i of e){var r;let e=tm(i.text),s=function(e,t,n,a){let r=null,i=1/0;for(let s=0;s<n.length;s+=1){if(a.has(s))continue;let o=n[s];if(tm(o.text)!==t)continue;let l=U(e.normalizedRect),d=B(l,U(o.normalizedRect));d>=i||(r=s,i=d)}return r}(i,e,t,n);if(null===s)continue;n.add(s);let o=function(e,t){let n={x:t.rect.x-e.rect.x,y:t.rect.y-e.rect.y,width:t.rect.width-e.rect.width,height:t.rect.height-e.rect.height},a=tb(t.rect.width/e.rect.width),r=tb(t.rect.height/e.rect.height),i=Math.abs(a-1)>=.08||Math.abs(r-1)>=.12;return{text:e.text,baselineRect:e.rect,currentRect:t.rect,delta:n,confidence:Math.round(100*Math.min(e.confidence,t.confidence))/100,possibleTextMetricMismatch:i}}(i,t[s]);r=o,(Math.abs(r.delta.x)>=2||Math.abs(r.delta.y)>=2||Math.abs(r.delta.width)>=2||Math.abs(r.delta.height)>=2||r.possibleTextMetricMismatch)&&a.push(o)}return a.sort((e,t)=>tu(t)-tu(e)).slice(0,12)}(a,r),s=function(e){let t=[];for(let n of[...e].sort((e,t)=>e.currentRect.y-t.currentRect.y)){let e=t.find(e=>32>=Math.abs(n.delta.x-tw(e.map(e=>e.delta.x))));e?e.push(n):t.push([n])}return t.filter(e=>e.length>=2).map(tc).filter(e=>e.yRange.max-e.yRange.min<=60).sort((e,t)=>tp(t)-tp(e)).slice(0,4)}(i);if(0===a.length&&0===r.length)return;return{provider:"tesseract",baselineBlocks:a.length,currentBlocks:r.length,baselineBlocksRaw:a,currentBlocksRaw:r,matches:i,...s.length>0?{movementClusters:s}:{}}}catch{return}}function tl(e,t,n){let[a,...r]=e.split(/\r?\n/);if(!a)return[];let i=new Map(a.split(" ").map((e,t)=>[e,t])),s=[];for(let e of r){var o;if(!e.trim())continue;let t=e.split(" "),n=tf(t,i,"level"),a=th(t,i,"text").trim(),r=tf(t,i,"conf");if(5!==n||(o=a,!/[\p{L}\p{N}]/u.test(o))||r<0)continue;let l=tf(t,i,"left"),d=tf(t,i,"top"),u=tf(t,i,"width"),c=tf(t,i,"height");u<=0||c<=0||s.push({key:[th(t,i,"page_num"),th(t,i,"block_num"),th(t,i,"par_num"),th(t,i,"line_num")].join(":"),text:a,confidence:r,rect:{x:l,y:d,width:u,height:c}})}let l=new Map;for(let e of s){let t=l.get(e.key);t?t.push(e):l.set(e.key,[e])}return Array.from(l.values()).flatMap(e=>(function(e){let t=[...e].sort((e,t)=>e.rect.x-t.rect.x),n=[],a=[];for(let e of t){let t=a.at(-1);if(!t){a.push(e);continue}if(e.rect.x-(t.rect.x+t.rect.width)>Math.max(48,2.5*Math.max(t.rect.height,e.rect.height))){n.push(a),a=[e];continue}a.push(e)}return a.length>0&&n.push(a),n})(e)).map(e=>(function(e,t,n){if(0===e.length)return null;let a=[...e].sort((e,t)=>e.rect.x-t.rect.x),r=C(a.map(e=>e.rect)),i=Math.round(100*tw(a.map(e=>e.confidence)))/100;return{text:a.map(e=>e.text).join(" "),confidence:i,rect:r,normalizedRect:L({x:tg(r.x/t),y:tg(r.y/n),width:tg(r.width/t),height:tg(r.height/n)})}})(e,t,n)).filter(e=>null!==e)}function td(e){return X("tesseract",[e,"stdout","-l","eng","tsv"],{allowFailure:!0,timeoutMs:1e4})}function tu(e){return Math.abs(e.delta.x)+Math.abs(e.delta.y)+Math.abs(e.delta.width)+Math.abs(e.delta.height)+25*!!e.possibleTextMetricMismatch}function tc(e){let t=e.map(e=>e.delta.x),n=e.map(e=>e.delta.y);return{texts:e.map(e=>e.text),xRange:{min:Math.min(...t),max:Math.max(...t)},yRange:{min:Math.min(...n),max:Math.max(...n)}}}function tp(e){return 2*Math.abs((e.xRange.min+e.xRange.max)/2)+Math.abs((e.yRange.min+e.yRange.max)/2)}function th(e,t,n){let a=t.get(n);return void 0===a?"":e[a]??""}function tf(e,t,n){let a=Number(th(e,t,n));return Number.isFinite(a)?a:0}function tm(e){return e.trim().replace(/\s+/g," ").toLowerCase()}function tw(e){return e.reduce((e,t)=>e+t,0)/e.length}function tg(e){return Math.round(100*e*100)/100}function tb(e){return Math.round(1e3*e)/1e3}function ty(e,t,n,a){return{r:Math.round(e/a),g:Math.round(t/a),b:Math.round(n/a)}}function tk(e){return .2126*e.r+.7152*e.g+.0722*e.b}function tx(e){return`#${tv(e.r)}${tv(e.g)}${tv(e.b)}`}function tv(e){return e.toString(16).padStart(2,"0")}function tA(e){return Math.round(100*e*100)/100}let tM=255*Math.sqrt(3);async function tI(e,a,r={}){var i,s,o,l,d;let u,c,p,h;await tP(e,"Baseline image not found"),await tP(a,"Current screenshot not found");let f=r.outputPath,[m,w]=await Promise.all([t.readFile(e),t.readFile(a)]),[g,b]=await Promise.all([eZ(m,"baseline screenshot"),eZ(w,"current screenshot")]);tR(g.width,g.height,"baseline screenshot",r.maxPixels),tR(b.width,b.height,"current screenshot",r.maxPixels);let y=r.threshold??.1;if(g.width!==b.width||g.height!==b.height){let e=g.width*g.height;return await tN(r.outputPath),{match:!1,mismatchPercentage:100,totalPixels:e,differentPixels:e,dimensionMismatch:{expected:{width:g.width,height:g.height},actual:{width:b.width,height:b.height}}}}let k=g.width*g.height,{diffData:x,diffMask:v,differentPixels:A}=await e0({width:g.width,height:g.height,baselineData:g.data,currentData:b.data,maxColorDistance:y*tM}),M=A>0?(s=(u=function(e){let{diffMask:t,baseline:n,current:a}=e,{width:r,height:i}=n;return e5({mask:t,width:r,height:i,hooks:{create:e=>{var t,n;let a,i;return a=(t=e)%(n=r),{minX:a,minY:i=Math.floor(t/n),maxX:a,maxY:i,differentPixels:0,baselineRed:0,baselineGreen:0,baselineBlue:0,currentRed:0,currentGreen:0,currentBlue:0}},visit:(e,t)=>{var i,s,o,l,d;let u,c,p;return i=e,s=t,o=r,l=n,d=a,u=s%o,c=Math.floor(s/o),p=4*s,void(i.minX=Math.min(i.minX,u),i.minY=Math.min(i.minY,c),i.maxX=Math.max(i.maxX,u),i.maxY=Math.max(i.maxY,c),i.differentPixels+=1,i.baselineRed+=l.data[p],i.baselineGreen+=l.data[p+1],i.baselineBlue+=l.data[p+2],i.currentRed+=d.data[p],i.currentGreen+=d.data[p+1],i.currentBlue+=d.data[p+2])}}})}(i={diffMask:v,baseline:g,current:b,totalPixels:k,differentPixels:A,maxRegions:r.maxRegions})).length<=2e3?function(e){let t=[];for(let r of e.sort((e,t)=>{let n=e.minY-t.minY;return 0!==n?n:e.minX-t.minX})){var n,a;let e=t.find(e=>{var t,n,a;return t=e,n=r,a=12,t.minX-a<=n.maxX&&n.minX-a<=t.maxX&&t.minY-a<=n.maxY&&n.minY-a<=t.maxY});if(!e){t.push({...r});continue}n=e,a=r,n.minX=Math.min(n.minX,a.minX),n.minY=Math.min(n.minY,a.minY),n.maxX=Math.max(n.maxX,a.maxX),n.maxY=Math.max(n.maxY,a.maxY),n.differentPixels+=a.differentPixels,n.baselineRed+=a.baselineRed,n.baselineGreen+=a.baselineGreen,n.baselineBlue+=a.baselineBlue,n.currentRed+=a.currentRed,n.currentGreen+=a.currentGreen,n.currentBlue+=a.currentBlue}return t}(u):u,s.flatMap(e=>{var t,n,a;let r;return(t=e,n=i.baseline.width,a=i.baseline.height,r=t.maxX-t.minX+1,t.maxY-t.minY+1>=Math.max(48,Math.round(.07*a))&&r>=.35*n)?function(e,t,n){var a;let r=function(e,t){let n=[],a=null;for(let r=0;r<e.length;r+=1){if(e[r]<=t){a??=r;continue}null!==a&&(r-a>=6&&n.push([a,r-1]),a=null)}return null!==a&&e.length-a>=6&&n.push([a,e.length-1]),n}((a=function(e,t,n){let a=[];for(let r=e.minY;r<=e.maxY;r+=1){let i=0;for(let a=e.minX;a<=e.maxX;a+=1)1===t[r*n+a]&&(i+=1);a.push(i)}return a}(e,t.diffMask,t.baseline.width)).map((e,t)=>{let n=0,r=0,i=Math.max(0,t-3),s=Math.min(a.length-1,t+3);for(let e=i;e<=s;e+=1)n+=a[e],r+=1;return Math.round(n/r)}),Math.max(1,Math.round((e.maxX-e.minX+1)*.08))),i=function(e,t,n){let a=[],r=e.minY;for(let[i,s]of t){let t=e.minY+Math.round((i+s)/2);t-r+1<n||e.maxY-t<n||(a.push([r,t]),r=t+1)}return a.push([r,e.maxY]),a}(e,r,n);if(i.length<=1)return[e];let s=i.map(([n,a])=>(function(e,t,n,a){let r=null;for(let o=t;o<=n;o+=1)for(let t=e.minX;t<=e.maxX;t+=1){var i,s;let e=o*a.baseline.width+t;1===a.diffMask[e]&&function(e,t,n,a,r,i){let s=4*t;e.minX=Math.min(e.minX,n),e.minY=Math.min(e.minY,a),e.maxX=Math.max(e.maxX,n),e.maxY=Math.max(e.maxY,a),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]}(r??={minX:i=t,minY:s=o,maxX:i,maxY:s,differentPixels:0,baselineRed:0,baselineGreen:0,baselineBlue:0,currentRed:0,currentGreen:0,currentBlue:0},e,t,o,a.baseline,a.current)}return r})(e,n,a,t)).filter(e=>null!==e);return s.length>1?s:[e]}(e,i,Math.max(24,Math.round(.03*i.baseline.height))):[e]})).sort((e,t)=>{let n=t.differentPixels-e.differentPixels;if(0!==n)return n;let a=e.minY-t.minY;return 0!==a?a:e.minX-t.minX}).slice(0,Math.max(0,i.maxRegions??8)).map((e,t)=>{var n,a,r,s,o,l,d,u,c,p,h;let f,m,w,g,b,y,k,x,v,A,M,I,P,R,N,S,_;return n=e,a=t+1,r={width:i.baseline.width,height:i.baseline.height,totalPixels:i.totalPixels,differentPixels:i.differentPixels},y={x:n.minX,y:n.minY,width:n.maxX-n.minX+1,height:n.maxY-n.minY+1},k={x:Math.round(n.minX+y.width/2),y:Math.round(n.minY+y.height/2)},x=ty(n.baselineRed,n.baselineGreen,n.baselineBlue,n.differentPixels),v=ty(n.currentRed,n.currentGreen,n.currentBlue,n.differentPixels),A=y.width*y.height,M=tA(n.differentPixels/A),I=Math.round(tk(x)),P=Math.round(tk(v)),R=(s=y,o=r.width,l=r.height,s.width>=.55*o&&s.height>=.12*l?"large-area":s.width>=2.5*s.height?"horizontal-band":s.height>=2.5*s.width?"vertical-band":"compact"),N=(f=A/r.totalPixels)>=.04?"large":f>=.01?"medium":"small",S=(d=x,u=v,m=tk(d),Math.abs(w=tk(u)-m)>=12?w>0?"brighter":"darker":Math.max(Math.abs(u.r-d.r),Math.abs(u.g-d.g),Math.abs(u.b-d.b))>=12?"color-shift":"mixed"),_=(c=k,p=r.width,h=r.height,g=c.x<p/3?"left":c.x>2*p/3?"right":"center",b=c.y<h/3?"top":c.y>2*h/3?"bottom":"middle","center"===g&&"middle"===b?"center":`${b}-${g}`),{index:a,rect:y,normalizedRect:L({x:tA(y.x/r.width),y:tA(y.y/r.height),width:tA(y.width/r.width),height:tA(y.height/r.height)}),differentPixels:n.differentPixels,shareOfDiffPercentage:tA(n.differentPixels/r.differentPixels),densityPercentage:M,shape:R,size:N,location:_,averageBaselineColorHex:tx(x),averageCurrentColorHex:tx(v),baselineLuminance:I,currentLuminance:P,dominantChange:S}}):[];if(A>0&&f){let e=new _({width:g.width,height:g.height,data:x});for(let t of M)t.rect.width<4||t.rect.height<4||function(e,t){let n=e4(t.x,0,e.width-1),a=e4(t.y,0,e.height-1),r=e4(t.x+t.width-1,0,e.width-1),i=e4(t.y+t.height-1,0,e.height-1);for(let t=0;t<2;t+=1){for(let s=n;s<=r;s+=1)e2(e,s,a+t,e1),e2(e,s,i-t,e1);for(let s=a;s<=i;s+=1)e2(e,n+t,s,e1),e2(e,r-t,s,e1)}}(e,t.rect);await t.mkdir(n.dirname(f),{recursive:!0}),await t.writeFile(f,await eQ(e))}else await tN(r.outputPath);let I=A>0?await to({baselinePath:e,currentPath:a,width:g.width,height:g.height}):void 0,P=I&&(I.matches.length>0||(I.movementClusters?.length??0)>0)?{provider:I.provider,baselineBlocks:I.baselineBlocks,currentBlocks:I.currentBlocks,matches:I.matches,...I.movementClusters?{movementClusters:I.movementClusters}:{}}:void 0,R=A>0&&I?(c=function(e){let t=[];for(let n of e.sort((e,t)=>e.minY-t.minY||e.minX-t.minX)){let e=t.find(e=>{var t,a,r;return t=e,a=n,r=10,t.minX-r<=a.maxX&&a.minX-r<=t.maxX&&t.minY-r<=a.maxY&&a.minY-r<=t.maxY});if(!e){t.push({...n});continue}e.minX=Math.min(e.minX,n.minX),e.minY=Math.min(e.minY,n.minY),e.maxX=Math.max(e.maxX,n.maxX),e.maxY=Math.max(e.maxY,n.maxY),e.differentPixels+=n.differentPixels}return t}((l=function(e,t,n,a){let r=new Uint8Array(e);if(!a)return r;for(let e of[...a.baselineBlocksRaw,...a.currentBlocksRaw])!function(e,t,n,a){let r=$(Math.floor(a.x),0,t-1),i=$(Math.floor(a.y),0,n-1),s=$(Math.ceil(a.x+a.width),0,t),o=$(Math.ceil(a.y+a.height),0,n);for(let n=i;n<o;n+=1)for(let a=r;a<s;a+=1)e[n*t+a]=0}(r,t,n,E(e.rect,8));return r}((o={diffMask:v,width:g.width,height:g.height,regions:M,ocr:I}).diffMask,o.width,o.height,o.ocr),d=o.width,e5({mask:l,width:d,height:o.height,hooks:{create:e=>{var t,n;let a,r;return a=(t=e)%(n=d),{minX:a,minY:r=Math.floor(t/n),maxX:a,maxY:r,differentPixels:0}},visit:(e,t)=>{var n,a,r;let i,s;return n=e,i=(a=t)%(r=d),s=Math.floor(a/r),void(n.minX=Math.min(n.minX,i),n.minY=Math.min(n.minY,s),n.maxX=Math.max(n.maxX,i),n.maxY=Math.max(n.maxY,s),n.differentPixels+=1)}}}))),p=tn(o.ocr?.currentBlocksRaw??[]),h=tn(o.ocr?.baselineBlocksRaw??[]),c.filter(tr).map(e=>{var t,n,a,r,i,s,l,d,u,c,f;let m,w,g,b,y,k,x,v,A,M;return t=e,n=o,a=p,r=h,b=function(e,t){let n,a=0;for(let r of t){let t=T(e,r.rect);t<=a||(a=t,n=r)}return n?.index}(g=ti(t),n.regions),y=function(e,t,n){let a=tt(e,t);if(a)return ta(e,a.blocks);let r=tt(e,n);return r?ta(e,r.blocks):void 0}(g,a,r),k=function(e,t,n){if(e.height<=3&&e.width>=.12*n)return"separator";if(!t)return e.width>=.4*n?"background":"unknown";if(e.width>=.4*n)return"background";let a=e.x+e.width/2,r=t.x+t.width/2;return a<r-t.width/2?"leading":a>r+t.width/2?"trailing":e.width>=.35*n?"background":"unknown"}(g,y?.block.rect,n.width),x=(i=g,s=k,l=t.differentPixels,d=n,m=i.width/i.height,w=l/(i.width*i.height),"separator"===s?"separator":"background"===s?"background":"trailing"===s&&m>=1.5&&m<=3.8&&w>=.35?"toggle":"trailing"===s&&i.width<=.06*d.width&&i.height<=.04*d.height?"chevron":"leading"===s&&m>=.55&&m<=1.8?"icon":te(i,d)?"background":"visual"),v={...b?{regionIndex:b}:{},slot:k,likelyKind:x,rect:g},{...b?{regionIndex:b}:{},slot:k,likelyKind:x,rect:g,...y?{nearestText:y.block.text.trim().replace(/^[^\p{L}\p{N}]+/u,"").replace(/^\p{L}\s+/u,"")}:{},score:(u=v,c=t.differentPixels,f=n,A=te(u.rect,f)?-35:0,M=20*!!u.regionIndex,e6[u.likelyKind]+e9[u.slot]+M+A+Math.min(20,c/200))}}).filter(e=>e.rect.y>=.08*o.height).filter(e7).sort((e,t)=>t.score-e.score).slice(0,Math.max(0,o.maxDeltas??12)).map((e,t)=>{var n;return n=e,{index:t+1,...n.regionIndex?{regionIndex:n.regionIndex}:{},slot:n.slot,likelyKind:n.likelyKind,rect:n.rect,...n.nearestText?{nearestText:n.nearestText}:{}}})):[],N=k>0?Math.round(A/k*1e4)/100:0;return{...A>0&&f?{diffPath:f}:{},...M.length>0?{regions:M}:{},...P?{ocr:P}:{},...R.length>0?{nonTextDeltas:R}:{},totalPixels:k,differentPixels:A,mismatchPercentage:N,match:0===A}}async function tP(e,n){try{await t.access(e)}catch{throw new N("INVALID_ARGS",`${n}: ${e}`)}}function tR(e,t,n,a){if(null==a||a<=0)return;let r=e*t;if(!(r<=a))throw new N("INVALID_ARGS",`${n} is ${r} pixels, which exceeds the configured maxImagePixels limit of ${a}`)}async function tN(e){if(e)try{await t.unlink(e)}catch(e){var n;if(!("object"==typeof(n=e)&&null!==n&&"code"in n&&"ENOENT"===n.code))throw e}}function tS(e){return e.width*e.height}function t_(e){return Math.round(100*e*100)/100}async function tO(e,t,n){if("path"===t.kind&&!e.policy.allowLocalInputPaths)throw new N("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 tD(e,t,n){if(t?.kind==="path"&&!e.policy.allowLocalOutputPaths)throw new N("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 tE(e,t){try{return await e.artifacts.createTempFile(t)}catch(e){throw P(e)}}let tT=async(e,t)=>{let n,a,r;if(!t.baseline)throw new N("INVALID_ARGS","diff screenshot requires a baseline image");let i=function(e){if(null==e||""===e)return .1;let t=Number(e);if(Number.isNaN(t)||t<0||t>1)throw new N("INVALID_ARGS","--threshold must be a number between 0 and 1");return t}(t.threshold),s=t.current??{kind:"live"};if(t.overlayRefs&&!tX(s))throw new N("INVALID_ARGS","diff screenshot <current.png> cannot use --overlay-refs because saved-image comparisons have no live accessibility refs");let o=await tO(e,t.baseline,{usage:"diff screenshot baseline",field:"baseline"}),l=[];try{let d;d=tX(s)?(a=await tC(e,t)).path:(n=await tO(e,s,{usage:"diff screenshot current",field:"current"})).path,r=t.out?await tD(e,t.out,{field:"diffPath",ext:".png"}):void 0;let u=await tI(o.path,d,{threshold:i,outputPath:r?.path,maxPixels:e.policy.maxImagePixels});tX(s)&&(u=await tU(e,t,r?.path,u,l));let c=u.diffPath?await r?.publish():void 0;return c&&l.push(c),u.diffPath||await r?.cleanup?.(),{...u,...l.length>0?{artifacts:l}:{}}}catch(e){throw await r?.cleanup?.(),e}finally{await o.cleanup?.(),await n?.cleanup?.(),await a?.cleanup?.()}};async function tC(e,t){let n=await tE(e,{prefix:"agent-device-diff-current",ext:".png"});try{await t$(e,t,n.path,tL(t))}catch(e){throw await n.cleanup(),e}return n}async function tU(e,t,n,a,r){var i,s,o,l;if(!t.overlayRefs)return a;if(a.match||a.dimensionMismatch)return n&&await tG(n),a;let d=(i=t,s=n,i.currentOverlayOut?i.currentOverlayOut:i.out?.kind==="path"?{kind:"path",path:tB(s??i.out.path)}:i.out?.kind==="downloadableArtifact"?{kind:"downloadableArtifact",...i.out.clientPath?{clientPath:tB(i.out.clientPath)}:{},...i.out.fileName?{fileName:tB(i.out.fileName)}:{}}:void 0),u=await tD(e,d,{field:"currentOverlayPath",ext:".png"});try{let n=await t$(e,t,u.path,{overlayRefs:!0,...tL(t)}),i=await u.publish();return i&&r.push(i),{...a,currentOverlayPath:n.path??u.path,...n.overlayRefs?{currentOverlayRefCount:n.overlayRefs.length}:{},...a.regions&&n.overlayRefs?{regions:(o=a.regions,l=n.overlayRefs,o.map(e=>{var t,n;let a,r=(t=e,n=l,a=tS(t.rect),n.map(e=>{let n=e.overlayRect,r=T(t.rect,n);return r<=0?null:{ref:e.ref,...e.label?{label:e.label}:{},rect:n,overlayCoveragePercentage:t_(r/tS(n)),regionCoveragePercentage:t_(r/a)}}).filter(e=>null!==e).sort((e,t)=>{let n=t.regionCoveragePercentage-e.regionCoveragePercentage;return 0!==n?n:t.overlayCoveragePercentage-e.overlayCoveragePercentage}).slice(0,3).map(e=>({ref:e.ref,...e.label?{label:e.label}:{},rect:e.rect,regionCoveragePercentage:e.regionCoveragePercentage})));return r.length>0?{...e,currentOverlayMatches:r}:e}))}:{}}}catch(e){throw await u.cleanup?.(),e}}async function t$(e,t,n,a={}){if(!e.backend.captureScreenshot)throw new N("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,a)??{}}function tL(e){return e.surface?{surface:e.surface}:{}}function tB(e){let t=n.extname(e),a=t?e.slice(0,-t.length):e;return`${a}.current-overlay${t||".png"}`}async function tG(e){try{await t.unlink(tB(e))}catch(e){var n;if(!("object"==typeof(n=e)&&null!==n&&"code"in n&&"ENOENT"===n.code))throw e}}function tX(e){return"live"===e.kind}async function tq(e,n){if(!Number.isInteger(n)||n<1)throw new N("INVALID_ARGS","Screenshot max size must be a positive integer");let a=await eZ(await t.readFile(e),"screenshot"),r=Math.max(a.width,a.height);if(r<=n)return;let i=n/r,s=Math.max(1,Math.round(a.width*i)),o=Math.max(1,Math.round(a.height*i)),l=function(e,t,n){let a=new _({width:t,height:n});for(let r=0;r<n;r+=1){let i=r*e.height/n,s=(r+1)*e.height/n;for(let n=0;n<t;n+=1){let o=n*e.width/t,l=(n+1)*e.width/t,d=0,u=0,c=0,p=0,h=0;for(let t=Math.floor(i);t<Math.ceil(s);t+=1){let n=Math.min(t+1,s)-Math.max(t,i);for(let a=Math.floor(o);a<Math.ceil(l);a+=1){let r=n*(Math.min(a+1,l)-Math.max(a,o)),i=(t*e.width+a)*4;d+=(e.data[i]??0)*r,u+=(e.data[i+1]??0)*r,c+=(e.data[i+2]??0)*r,p+=(e.data[i+3]??0)*r,h+=r}}let f=(r*a.width+n)*4;a.data[f]=Math.round(d/h),a.data[f+1]=Math.round(u/h),a.data[f+2]=Math.round(c/h),a.data[f+3]=Math.round(p/h)}}return a}(a,s,o);await t.writeFile(e,await eQ(l))}let tY=async(e,t)=>{let n;if(!e.backend.captureScreenshot)throw new N("UNSUPPORTED_OPERATION","screenshot is not supported by this backend");let a=await tD(e,t.out,{field:"path",ext:".png"});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},a.path,{fullscreen:t.fullscreen,overlayRefs:t.overlayRefs,stabilize:t.stabilize,surface:t.surface}),void 0!==t.maxSize&&await tq(a.path,t.maxSize),n=await a.publish()}catch(e){throw await a.cleanup?.(),e}return{path:a.path,...n?{artifacts:[n]}:{},...f(`Saved screenshot: ${a.path}`)}};function tK(e,t){let n=Y(e.type??"Element"),a=K(e,n),r=!1===e.enabled?"disabled":"enabled",i=!0===e.selected?"selected":"unselected",s=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),n,a,r,i,s].join("|")}function tF(e,t){return t.flatten?e.map(e=>({text:q(e,0,!1),comparable:tK(e,0)})):F(e).map(e=>({text:e.text,comparable:tK(e.node,e.depth)}))}function tV(e,t){return e.get(t)??0}function tj(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}))}let tH=async(e,t)=>{var n;let a,r,s=await tW(e,t),o=function(e){var t,n,a,r,i;let{previous:s,current:o,options:l,identity:d}=e;if(!0===l.forceFull||!0===l.raw||!s||!1===s.comparisonSafe||!1===o.comparisonSafe||(t=s,n=o,a=d,t.backend&&n.backend&&t.backend!==n.backend||a?.previousAppBundleId&&a.currentAppBundleId&&a.previousAppBundleId!==a.currentAppBundleId)||!s.presentationKey||s.presentationKey!==o.presentationKey||(r=s,i=o,r.truncated!==i.truncated||JSON.stringify(tj(r.nodes))!==JSON.stringify(tj(i.nodes))))return;let u=l.scope?.trim();return{ageMs:Math.max(0,o.createdAt-s.createdAt),nodeCount:o.nodes.length,...!0===l.interactiveOnly?{interactiveOnly:!0}:{},...u?{scope:u}:{}}}({previous:s.session?.snapshot,current:s.snapshot,options:t,identity:{previousAppBundleId:s.session?.appBundleId,currentAppBundleId:s.result.appBundleId??s.session?.appBundleId}});return await e.sessions.set(tJ(t.session,s)),{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,visibility:function(e){var t;let{nodes:n,backend:a,snapshotRaw:r}=e;if(r||"macos-helper"===(t=a)||"linux-atspi"===t)return{partial:!1,visibleNodeCount:n.length,totalNodeCount:n.length,reasons:[]};let s=i(n),o=new Set;return s.hiddenCount>0&&o.add("offscreen-nodes"),s.nodes.some(e=>e.hiddenContentAbove)&&o.add("scroll-hidden-above"),s.nodes.some(e=>e.hiddenContentBelow)&&o.add("scroll-hidden-below"),{partial:o.size>0,visibleNodeCount:s.nodes.length,totalNodeCount:n.length,reasons:[...o]}}({nodes:s.snapshot.nodes,backend:s.snapshot.backend,snapshotRaw:t.raw}),...u({...s.annotations,warnings:s.warnings}),...o?{unchanged:o}:{},...(a=(n=s).result.appName??n.session?.appName,r=n.result.appBundleId??n.session?.appBundleId,{...a||r?{appName:a??r}:{},...r?{appBundleId:r}:{}})}},tz=async(e,t)=>{let n=await tW(e,t),a=!0===t.interactiveOnly,r=n.session?.snapshot,i=tJ(t.session,n);if(!r){let t=function(e,t={}){return tF(e,t).length}(n.snapshot.nodes,{flatten:a});return await e.sessions.set(i),{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:t},lines:[],...n.warnings.length>0?{warnings:n.warnings}:{}}}let s=function(e,t,n={}){let a=function(e,t){let n=e.length,a=t.length,r=n+a,i=new Map,s=[];i.set(1,0);for(let o=0;o<=r;o+=1){s.push(new Map(i));for(let r=-o;r<=o;r+=2){let l=r===-o||r!==o&&tV(i,r-1)<tV(i,r+1)?tV(i,r+1):tV(i,r-1)+1,d=l-r;for(;l<n&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(i.set(r,l),l>=n&&d>=a)return function(e,t,n,a,r){let i=[],s=a,o=r;for(let a=e.length-1;a>=0;a-=1){let r=e[a],l=s-o,d=l===-a||l!==a&&tV(r,l-1)<tV(r,l+1)?l+1:l-1,u=tV(r,d),c=u-d;for(;s>u&&o>c;)i.push({kind:"unchanged",text:n[o-1].text}),s-=1,o-=1;if(0===a)break;s===u?(i.push({kind:"added",text:n[c].text}),o=c):(i.push({kind:"removed",text:t[u].text}),s=u)}return i.reverse(),i}(s,e,t,n,a)}}return[]}(tF(e,n),tF(t,n)),r={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(r.additions+=1),"removed"===e.kind&&(r.removals+=1),"unchanged"===e.kind&&(r.unchanged+=1);return{summary:r,lines:a}}(r.nodes,n.snapshot.nodes,{flatten:a});return await e.sessions.set(i),{mode:"snapshot",baselineInitialized:!1,summary:s.summary,lines:s.lines,...n.warnings.length>0?{warnings:n.warnings}:{}}};async function tW(e,t){var n,a,r,i,s,l,d;let u,c,p,h,f;if(!e.backend.captureSnapshot)throw new N("UNSUPPORTED_OPERATION","snapshot is not supported by this backend");let m=t.session??"default",w=await e.sessions.get(m),g=await e.backend.captureSnapshot({session:m,requestId:t.requestId,appId:w?.appId,appBundleId:w?.appBundleId,signal:t.signal??e.signal,metadata:t.metadata},{interactiveOnly:t.interactiveOnly,depth:t.depth,scope:t.scope,raw:t.raw}),b=(a=g,r=e,n=a.snapshot?a.snapshot:{nodes:a.nodes??[],truncated:a.truncated,backend:a.backend,createdAt:o(r)},n.presentationKey?n:{...n,presentationKey:V(t)}),y=k(g),x=o(e);return{snapshot:b,result:g,session:w,annotations:y,warnings:(u=[...(i={result:g,annotations:y,snapshot:b,options:t,session:w,capturedAt:b.createdAt??x,runtimeNow:x}).annotations.warnings??[]],i.annotations.quality&&u.push(...M(i.annotations.quality,i.snapshot.nodes)),u.push(...function(e){let t=e.annotations.analysis;if("android"!==e.snapshot.backend||!0!==e.options.interactiveOnly||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"number"==typeof e.options.depth&&"number"==typeof t.maxDepth&&t.maxDepth>=e.options.depth+2&&n.push(`Interactive output is empty at depth ${e.options.depth}; retry without -d.`),n}(i)),i.annotations.quality||(u.push(...function(e){if("xctest"!==e.snapshot.backend||!0!==e.options.interactiveOnly||1!==e.snapshot.nodes.length)return[];let t=e.snapshot.nodes[0];return t?.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."]}(i)),u.push(...(c=new Set((s=i.snapshot.nodes).map(e=>e.parentIndex).filter(e=>void 0!==e)),s.filter(e=>!(c.has(e.index)||(e.type?.toLowerCase()??"").includes("text"))&&(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.`})))),(p=function(e){if(e?.backend!=="uiautomator-dump")return;let t=e.fallbackReason?` Reason: ${e.fallbackReason}`:"";return`Android snapshot helper unavailable; using stock UIAutomator dump, which can time out on busy React Native UIs.${t}`}(i.annotations.androidSnapshot))&&u.push(p),(h=v(i.snapshot.nodes))&&u.push(h),(f=function(e){var t,n,a,r,i,s;let o=e.session?.snapshot;if(!e.annotations.freshness&&o&&(t=o,n=e.snapshot,void 0===t.presentationKey||void 0===n.presentationKey||t.presentationKey===n.presentationKey)&&(a=o,r=e.capturedAt,[r,e.runtimeNow].some(e=>{let t=e-a.createdAt;return t>=0&&t<=2e3}))&&(i=o.nodes.length,s=e.snapshot.nodes.length,!(i<12)&&s<=Math.floor(.2*i)))return tZ}(i))&&u.push(f),u.push(...(l=i.annotations.freshness,d=i.snapshot.backend,l?.staleAfterRetries&&"android"===d?"stuck-route"===l.reason?[`Recent ${l.action} was followed by a nearly identical snapshot after ${l.retryCount} automatic retr${1===l.retryCount?"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.`]:"sharp-drop"===l.reason?[tZ]:[]:[])),Array.from(new Set(u)))}}function tJ(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}}let tZ="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.",tQ=async(e,t)=>await t4(e,t,"press"),t0=async(e,t)=>await t4(e,t,"click"),t1=async(e,t)=>{var n;if(!t.text)throw new N("INVALID_ARGS","fill requires text");let a=await b(e,t,{action:"fill",requireInteractive:!0,promoteToHittableAncestor:!1});if(!e.backend.fill)throw new N("UNSUPPORTED_OPERATION","fill is not supported by this backend");let r=w(await e.backend.fill(y(e,t),a.point,t.text,{delayMs:t.delayMs})),i="node"in a?a.node.type??"":"",s=i&&!ed(i,e.backend.platform)?`fill target ${n=a,n.target?.kind==="ref"?n.target.ref:n.target?.kind==="selector"?n.target.selector:"point"} resolved to "${i}", attempting fill anyway.`:void 0;return{...a,text:t.text,...s?{warning:s}:{},...r?{backendResult:r}:{}}},t2=async(e,t)=>{let n=t.text;if(!n)throw new N("INVALID_ARGS","type requires text");let a=eU(n);if(a)throw new N("INVALID_ARGS",`type does not accept a target ref like "${a}"`,{hint:`Use fill ${a} "text" to target that field, or press ${a} then type "text" to append.`});if(!e.backend.typeText)throw new N("UNSUPPORTED_OPERATION","type is not supported by this backend");let r=x(t.delayMs??0,"delay-ms",0,1e4),i=w(await e.backend.typeText(y(e,t),n,{delayMs:r}));return{kind:"text",text:n,delayMs:r,...i?{backendResult:i}:{},...f(`Typed ${Array.from(n).length} chars`)}};async function t4(e,t,n){let a=await b(e,t,{action:n,requireInteractive:!0,promoteToHittableAncestor:!0});if(!e.backend.tap)throw new N("UNSUPPORTED_OPERATION","tap is not supported by this backend");let r=w(await e.backend.tap(y(e,t),a.point,{button:t.button,count:t.count,intervalMs:t.intervalMs,holdMs:t.holdMs,jitterPx:t.jitterPx,doubleTap:t.doubleTap}));return{...a,...r?{backendResult:r}:{}}}function t3(e){return["visible","hidden","exists","editable","selected","text"].includes(e)}function t5(e){let{predicate:t,node:n,nodes:a,expectedText:r,platform:i}=e,s=z(n),o=ee(n,i),d=!0===n.selected,u="text"===t?Z(n):function(e,t,n){var a,r,i;let s;if("android"===n&&!1===e.visibleToUser)return!1;if(t8(e.rect))return function(e,t){return l(e,t)}(e,t);if(e.rect)return!1;if("android"!==n&&!0===e.hittable)return!0;let o=(a=e,r=t,i=n,s=Q(r),W(r,a,s,e=>!function(e,t){if("android"===t&&!1===e.visibleToUser)return!1;let n=el(e.type??"");return!(n.includes("application")||n.includes("window")||n.includes("scrollview")||n.includes("tableview")||n.includes("collectionview"))&&"table"!==n&&"list"!==n&&"listview"!==n&&("android"===t?!0===e.hittable&&t8(e.rect):!0===e.hittable||t8(e.rect))}(e,i)?null:e));return!!o&&(t8(o.rect)?function(e,t){return l(e,t)}(o,t):"android"!==n&&!0===o.hittable)}(n,a,i),c=!1;switch(t){case"visible":c=u;break;case"hidden":c=!u;break;case"editable":c=o;break;case"selected":c=d;break;case"text":c=s===(r??"")}let p="text"===t?`expected="${r??""}" actual="${s}"`:`actual=${JSON.stringify({visible:u,editable:o,selected:d})}`;return{pass:c,actualText:s,details:p}}function t8(e){return!!(e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.width)&&Number.isFinite(e.height)&&e.width>0&&e.height>0)}async function t6(e,t){let n=t??"default",a=await e.sessions.get(n);if(!a)throw new N("SESSION_NOT_FOUND","No active session. Run open first.");if(!a.snapshot)throw new N("INVALID_ARGS","No snapshot in session. Run snapshot first.");return{sessionName:n,session:a,snapshot:a.snapshot}}async function t9(e,t,n={updateSession:!0}){let a=e.backend.captureSnapshot;if(!a)throw new N("UNSUPPORTED_OPERATION","snapshot is not supported by this backend");let r=t.session??"default",i=await e.sessions.get(r),l=await a(y(e,t),{interactiveOnly:!1,depth:t.depth,scope:n.scope??t.scope,raw:t.raw}),d=l.snapshot??{nodes:l.nodes??[],truncated:l.truncated,backend:l.backend,...l.quality?{snapshotQuality:l.quality}:{},createdAt:o(e)};return n.updateSession&&i&&!s(d.snapshotQuality)&&await e.sessions.set({...i,snapshot:d}),{sessionName:r,session:i,snapshot:d}}async function t7(e,t,n){if(e.backend.readText){let a=await e.backend.readText(y(e,{session:t.sessionName}),n);if(a.text.trim())return a.text}return es(n)}let ne=async(e,t)=>{let n=t.locator??"any";if(!t.query)throw new N("INVALID_ARGS","find requires a value");if("wait"===t.action)return await nd(e,t,n);let{capture:a,match:r}=await nu(e,t,n);if(!r)throw new N("COMMAND_FAILED","find did not match any element");if("exists"===t.action)return{kind:"found",found:!0};let i=`@${r.ref}`;return"get_attrs"===t.action?{kind:"attrs",ref:i,node:r}:{kind:"text",ref:i,text:await t7(e,a,r),node:r}},nt=async(e,t)=>{if("ref"===t.target.kind){let n=await t6(e,t.session),a=function(e,t,n){let a=j(t);if(!a)throw new N("INVALID_ARGS",n.invalidRefMessage);let r=H(e,a)??(n.fallbackLabel.length>0?er(e,n.fallbackLabel):null);if(!r)throw new N("COMMAND_FAILED",n.notFoundMessage);return{ref:a,node:r}}(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`}),r=en(a.node,e.backend.platform,{action:"get"}),i={kind:"ref",ref:`@${a.ref}`};return"attrs"===t.property?{kind:"attrs",target:i,node:a.node,selectorChain:r}:{kind:"text",target:i,text:await t7(e,n,a.node),node:a.node,selectorChain:r}}let n=await nf(e,t,t.session??"default",{selector:t.target.selector,disambiguateAmbiguous:"text"===t.property}),a=en(n.node,e.backend.platform,{action:"get"});if("attrs"===t.property)return{kind:"attrs",target:{kind:"selector",selector:n.selector},node:n.node,selectorChain:a};let r=await t7(e,n.capture,n.node);return{kind:"text",target:{kind:"selector",selector:n.selector},text:r,node:n.node,selectorChain:a}},nn=async(e,t)=>{let n=await nt(e,{...t,property:"text",target:t.target});if("text"!==n.kind)throw new N("COMMAND_FAILED","getText returned non-text result");return n},na=async(e,t)=>{let n=await nt(e,{...t,property:"attrs",target:t.target});if("attrs"!==n.kind)throw new N("COMMAND_FAILED","getAttrs returned non-attrs result");return n},nr=async(e,t)=>{if(!t3(t.predicate))throw new N("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");if("text"===t.predicate&&!t.expectedText)throw new N("INVALID_ARGS","is text requires expected text value");let n=await t9(e,t,{updateSession:!0}),a=J(t.selector);if("exists"===t.predicate){let r=et(n.snapshot.nodes,a,{platform:e.backend.platform});if(!r)throw new N("COMMAND_FAILED",eo(a,[],{unique:!1}));return{predicate:t.predicate,pass:!0,selector:r.selector.raw,matches:r.matches,selectorChain:a.selectors.map(e=>e.raw)}}let r=ea(n.snapshot.nodes,a,{platform:e.backend.platform,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!r)throw new N("COMMAND_FAILED",eo(a,[],{unique:!0}),{command:"is",reason:"selector_not_found",predicate:t.predicate,selector:a.raw});let i=t5({predicate:t.predicate,node:r.node,nodes:n.snapshot.nodes,expectedText:t.expectedText,platform:e.backend.platform});if(!i.pass)throw new N("COMMAND_FAILED",`is ${t.predicate} failed for selector ${r.selector.raw}: ${i.details}`,{command:"is",reason:"predicate_failed",predicate:t.predicate,selector:r.selector.raw,predicateDetails:i.details});return{predicate:t.predicate,pass:!0,selector:r.selector.raw,..."text"===t.predicate?{text:i.actualText}:{},selectorChain:a.selectors.map(e=>e.raw)}},ni=async(e,t)=>await nr(e,{...t,predicate:"visible",selector:t.target.selector}),ns=async(e,t)=>await nr(e,{...t,predicate:"hidden",selector:t.target.selector}),no=async(e,t)=>{if("sleep"===t.target.kind)return await d(e,t.target.durationMs),{kind:"sleep",waitedMs:t.target.durationMs};if("ref"===t.target.kind){let n=await t6(e,t.session),a=j(t.target.ref);if(!a)throw new N("INVALID_ARGS",`Invalid ref: ${t.target.ref}`);let r=H(n.snapshot.nodes,a),i=r?ei(r,n.snapshot.nodes):void 0;if(!i)throw new N("COMMAND_FAILED",`Ref ${t.target.ref} not found or has no label`);return await np(e,t,i,t.target.timeoutMs)}if("selector"===t.target.kind)return await nc(e,t,t.target.selector,t.target.timeoutMs);if(!t.target.text)throw new N("INVALID_ARGS","wait requires text");return await np(e,t,t.target.text,t.target.timeoutMs)},nl=async(e,t)=>{let n=await no(e,{...t,target:{kind:"text",text:t.text,timeoutMs:t.timeoutMs}});if("text"!==n.kind)throw new N("COMMAND_FAILED","waitForText returned non-text result");return n};async function nd(e,t,n){let a=t.timeoutMs??1e4,r=o(e);for(;o(e)-r<a;){let{match:a}=await nu(e,t,n);if(a)return{kind:"found",found:!0,waitedMs:o(e)-r};await d(e,300)}throw new N("COMMAND_FAILED","find wait timed out")}async function nu(e,t,n){let a=await t9(e,t,{updateSession:!0,scope:"text"===n||"label"===n||"any"===n?t.query:void 0});if(s(a.snapshot.snapshotQuality))throw new N("COMMAND_FAILED","find could not read the current accessibility tree",{reason:a.snapshot.snapshotQuality.reason,hint:"The snapshot quality verdict is sparse. Use screenshot as visual truth, navigate with coordinates if needed, then retry find after reaching a readable screen."});let r=eu(a.snapshot.nodes,n,t.query,{requireRect:!1}).matches[0];return{capture:a,match:r}}async function nc(e,t,n,a){let r=a??1e4,i=o(e),s=J(n);for(;o(e)-i<r;){let n=et((await t9(e,t,{updateSession:!0})).snapshot.nodes,s,{platform:e.backend.platform});if(n)return{kind:"selector",selector:n.selector.raw,waitedMs:o(e)-i};await d(e,300)}throw new N("COMMAND_FAILED",`wait timed out for selector: ${n}`)}async function np(e,t,n,a){let r=a??1e4,i=o(e);for(;o(e)-i<r;){if(e.backend.findText?(await e.backend.findText(y(e,t),n)).found:await nh(e,t,n))return{kind:"text",text:n,waitedMs:o(e)-i};await d(e,300)}throw new N("COMMAND_FAILED",`wait timed out for text: ${n}`)}async function nh(e,t,n){return!!er((await t9(e,t,{updateSession:!0})).snapshot.nodes,n)}async function nf(e,t,n,a){let r=await t9(e,{...t,session:n},{updateSession:!0}),i=J(a.selector),s=ea(r.snapshot.nodes,i,{platform:e.backend.platform,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:a.disambiguateAmbiguous});if(!s)throw new N("COMMAND_FAILED",eo(i,[],{unique:!0}));return{capture:r,node:s.node,selector:s.selector.raw,ref:`@${s.node.ref}`}}function nm(e,t){if(void 0!==e)return nw(e,t)}function nw(e,t){let n=e?.trim();if(!n)throw new N("INVALID_ARGS",`${t} must be a non-empty string`);return n}let ng=async(e,t={})=>{if(!e.backend.listDevices)throw new N("UNSUPPORTED_OPERATION","admin.devices is not supported by this backend");return{kind:"adminDevices",devices:await e.backend.listDevices(y(e,t),t.filter)}},nb=async(e,t={})=>{if(!e.backend.bootDevice)throw new N("UNSUPPORTED_OPERATION","admin.boot is not supported by this backend");let n=nR(t.target),a=w(await e.backend.bootDevice(y(e,t),n));return{kind:"deviceBooted",...n?{target:n}:{},...a?{backendResult:a}:{},...f("Booted device")}},ny=async(e,t={})=>{if(!e.backend.shutdownDevice)throw new N("UNSUPPORTED_OPERATION","admin.shutdown is not supported by this backend");let n=nR(t.target),a=w(await e.backend.shutdownDevice(y(e,t),n));return{kind:"deviceShutdown",...n?{target:n}:{},...a?{backendResult:a}:{},...f("Shutdown device")}},nk=async(e,t)=>await nA(e,t,"install"),nx=async(e,t)=>await nA(e,t,"reinstall"),nv=async(e,t)=>await nA(e,t,"installFromSource");async function nA(e,t,n){let a="reinstall"===n?"reinstallApp":"installApp",r=e.backend[a];if(!r)throw new N("UNSUPPORTED_OPERATION",`admin.${n} is not supported by this backend`);let i="app"in t&&void 0!==t.app?nw(t.app,"app"):void 0;if("installFromSource"!==n&&!i)throw new N("INVALID_ARGS",`admin.${n} requires app`);let s=y(e,t),o=await nM(e,s,t.source);try{var l,d,u,c,p;let t,a,h,m,g,b,y,k,x=await r.call(e.backend,s,{...i?{app:i}:{},source:o.source});return l=n,d=i,u=o.source,c=x,t=w(c),a=nN(c,"appName"),h=nN(c,"appId"),m=nN(c,"bundleId"),g=nN(c,"packageName"),b=nN(c,"launchTarget"),y=nN(c,"installablePath"),k=nN(c,"archivePath"),{kind:"reinstall"===l?"appReinstalled":"installFromSource"===l?"appInstalledFromSource":"appInstalled",...d?{app:d}:{},source:u,...h?{appId:h}:{},...a?{appName:a}:{},...m?{bundleId:m}:{},...g?{packageName:g}:{},...b?{launchTarget:b}:{},...y?{installablePath:y}:{},...k?{archivePath:k}:{},...t?{backendResult:t}:{},...f(`${"reinstall"===l?"Reinstalled":"Installed"}: ${a??b??d??(p=u,"path"===p.kind?p.path:"uploadedArtifact"===p.kind?p.id:p.url)}`)}}finally{await o.cleanup?.()}}async function nM(e,t,n){let a=nP(n),r=await nI(e,a);try{let n=e.backend.resolveInstallSource?await e.backend.resolveInstallSource(t,r.source):r.source;return{source:nP(n),...r.cleanup?{cleanup:r.cleanup}:{}}}catch(e){if(r.cleanup)try{await r.cleanup()}catch{}throw e}}async function nI(e,t){if("url"===t.kind)return{source:t};let n=await tO(e,t,{usage:"admin.install",field:"source"});return{source:{kind:"path",path:n.path},...n.cleanup?{cleanup:n.cleanup}:{}}}function nP(e){if(!e||"object"!=typeof e)throw new N("INVALID_ARGS","install source is required");if("path"===e.kind)return{kind:"path",path:nw(e.path,"source.path")};if("uploadedArtifact"===e.kind)return{kind:"uploadedArtifact",id:nw(e.id,"source.id")};if("url"===e.kind){let t=nw(e.url,"source.url");return function(e){let t;try{t=new URL(e)}catch{throw new N("INVALID_ARGS",`Invalid install source URL: ${e}`)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new N("INVALID_ARGS","Install source URL must use http or https")}(t),{kind:"url",url:t}}throw new N("INVALID_ARGS","install source kind must be path, uploadedArtifact, or url")}function nR(e){if(!e)return;let t=nm(e.id,"target.id"),n=nm(e.name,"target.name"),a={...t?{id:t}:{},...n?{name:n}:{},...e.platform?{platform:e.platform}:{},...e.target?{target:e.target}:{},...void 0!==e.headless?{headless:e.headless}:{}};return Object.keys(a).length>0?a:void 0}function nN(e,t){let n=e[t];return"string"==typeof n&&n.length>0?n:void 0}let nS=/^[A-Za-z0-9_.:-]{1,64}$/,n_=async(e,t)=>{var n;if(!e.backend.openApp)throw new N("UNSUPPORTED_OPERATION","apps.open is not supported by this backend");let a=function(e){var t;let n=nm(e.app,"app"),a=nm(e.appId,"appId"),r=nm(e.bundleId,"bundleId"),i=nm(e.packageName,"packageName"),s=nm(e.url,"url"),o=nm(e.activity,"activity"),l={...n?{app:n}:{},...a?{appId:a}:{},...r?{bundleId:r}:{},...i?{packageName:i}:{},...s?{url:s}:{},...o?{activity:o}:{}};if(!((t=l).app??t.appId??t.bundleId??t.packageName??t.url??t.activity))throw new N("INVALID_ARGS","apps.open requires app, appId, bundleId, packageName, url, or activity");return l}(t),r=w(await e.backend.openApp(nL(e,t),a,{launchArgs:t.launchArgs,relaunch:t.relaunch}));return{kind:"appOpened",target:a,relaunch:!0===t.relaunch,...r?{backendResult:r}:{},...f(`Opened: ${(n=a).app??n.appId??n.bundleId??n.packageName??n.url??n.activity??"app"}`)}},nO=async(e,t={})=>{if(!e.backend.closeApp)throw new N("UNSUPPORTED_OPERATION","apps.close is not supported by this backend");let n=nm(t.app,"app"),a=w(await e.backend.closeApp(nL(e,t),n));return{kind:"appClosed",...n?{app:n}:{},...a?{backendResult:a}:{},...f(n?`Closed: ${n}`:"Closed app")}},nD=async(e,t={})=>{if(!e.backend.listApps)throw new N("UNSUPPORTED_OPERATION","apps.list is not supported by this backend");return{kind:"appsList",apps:await e.backend.listApps(nL(e,t),ep(t.filter))}},nE=async(e,t)=>{if(!e.backend.getAppState)throw new N("UNSUPPORTED_OPERATION","apps.state is not supported by this backend");let n=nw(t.app,"app"),a=await e.backend.getAppState(nL(e,t),n);return{kind:"appState",app:n,state:a}},nT=async(e,t)=>{if(!e.backend.pushFile)throw new N("UNSUPPORTED_OPERATION","apps.push is not supported by this backend");let n=nw(t.app,"app"),a=await nU(e,t.input);try{let r=await e.backend.pushFile(nL(e,t),a.backendInput,n),i=w(r);return{kind:"appPushed",app:n,inputKind:a.inputKind,...i?{backendResult:i}:{},...f(`Pushed to ${n}`)}}finally{await a.cleanup?.()}},nC=async(e,t)=>{var n,a;if(!e.backend.triggerAppEvent)throw new N("UNSUPPORTED_OPERATION","apps.triggerEvent is not supported by this backend");let r=function(e){let t=nw(e,"name");if(!nS.test(t))throw new N("INVALID_ARGS",`Invalid apps.triggerEvent name: ${t}`,{hint:"Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash."});return t}(t.name);n=t.payload,a=`apps.triggerEvent payload for "${r}"`,void 0!==n&&n$(n,a,8192);let i=w(await e.backend.triggerAppEvent(nL(e,t),{name:r,...t.payload?{payload:t.payload}:{}}));return{kind:"appEventTriggered",name:r,...t.payload?{payload:t.payload}:{},...i?{backendResult:i}:{},...f(`Triggered app event: ${r}`)}};async function nU(e,t){if(!t||"object"!=typeof t)throw new N("INVALID_ARGS","apps.push requires an input");if("json"===t.kind)return n$(t.payload,"apps.push JSON payload",8192),{backendInput:{kind:"json",payload:t.payload},inputKind:"json"};let n=await tO(e,t,{usage:"apps.push",field:"input"});return{backendInput:{kind:"file",path:n.path},inputKind:"file",...n.cleanup?{cleanup:n.cleanup}:{}}}function n$(e,t,n){if(function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new N("INVALID_ARGS",`${t} must be a JSON object`)}(e,t),Buffer.byteLength(function(e,t){try{let n=JSON.stringify(e);if("string"!=typeof n)throw new N("INVALID_ARGS",`${t} must be JSON-serializable`);return n}catch{throw new N("INVALID_ARGS",`${t} must be JSON-serializable`)}}(e,t),"utf8")>n)throw new N("INVALID_ARGS",`${t} exceeds ${n} bytes`)}function nL(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}let nB=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i,nG=/\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/g;function nX(e){var t,n;let a=!1,r=e;return{value:(t=r=(r=(r=(r=(r=r.replaceAll(/(authorization|token|secret|password|passwd|api[-_]?key)=([^&\s]+)/gi,(e,t)=>(a=!0,`${String(t)}=[REDACTED]`))).replaceAll(/("(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)"\s*:\s*")([^"]*)(")/gi,(e,t,n,r)=>(a=!0,`${String(t)}[REDACTED]${String(r)}`))).replaceAll(/\b(Bearer\s+)([^\s",;]+)/gi,(e,t)=>(a=!0,`${String(t)}[REDACTED]`))).replaceAll(/((?:authorization|cookie|token|secret|password|passwd|api[-_]?key)\s*[:=]\s*)([^\s,;&]+)/gi,(e,t)=>(a=!0,`${String(t)}[REDACTED]`))).replaceAll(nG,()=>(a=!0,"[REDACTED]")),n=()=>{a=!0},r=/(https?:\/\/|token|secret|password|authorization|cookie|api[-_]?key)/i.test(t)?t.replaceAll(/https?:\/\/[^\s"'<>)]+/gi,e=>{let t=nq(e);return t?(t.redacted&&n(),t.value):e}):t),redacted:a}}function nq(e){try{let t=new URL(e),n=function(e){let t=!1;for(let n of Array.from(e.searchParams.keys()))nB.test(n)&&(e.searchParams.set(n,"[REDACTED]"),t=!0);return t}(t);return(t.username||t.password)&&(t.username="REDACTED",t.password="REDACTED",n=!0),{value:t.toString(),redacted:n}}catch{return}}let nY=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i;function nK(e){if(!e)return{redacted:!1};let t=!1,n={};for(let[a,r]of Object.entries(e))if(nY.test(a))n[a]="[REDACTED]",t=!0;else{let e=nH(r,2048);n[a]=e.value??"",t||=e.redacted}return{value:n,redacted:t}}function nF(e){return void 0===e?{redacted:!1}:function(e){try{let t=JSON.parse(e),n=nj(t,nX);return nz(JSON.stringify(n.value),2048,n.redacted)}catch{return}}(e)??nH(e,2048)}function nV(e){return nj(e,e=>nH(e,2048))}function nj(e,t){if(void 0===e)return{redacted:!1};if("string"==typeof e)return t(e);if(!e||"object"!=typeof e)return{value:e,redacted:!1};if(Array.isArray(e)){let n=!1;return{value:e.map(e=>{let a=nj(e,t);return n||=a.redacted,a.value}),redacted:n}}let n=!1,a={};for(let[r,i]of Object.entries(e)){if(nY.test(r)){a[r]="[REDACTED]",n=!0;continue}let e=nj(i,t);a[r]=e.value,n||=e.redacted}return{value:a,redacted:n}}function nH(e,t){if(void 0===e)return{redacted:!1};let n=nX(e);return nz(n.value,t,n.redacted)}function nz(e,t,n){if(void 0===e)return{redacted:n};let a=e;return a.length>t&&(a=`${a.slice(0,t)}...[truncated]`,n=!0),{value:a,redacted:n}}let nW=async(e,t={})=>{var n,a;let r;if(!e.backend.readLogs)throw new N("UNSUPPORTED_OPERATION","diagnostics.logs is not supported by this backend");return r=!0===(n=await e.backend.readLogs(await nQ(e,t),{...n0(a=t,100,500,"logs limit"),...void 0!==a.levels?{levels:n2(a.levels,"levels")}:{},...void 0!==a.search?{search:nw(a.search,"search")}:{},...void 0!==a.source?{source:nw(a.source,"source")}:{}})).redacted,{kind:"diagnosticsLogs",entries:n.entries.map(e=>{let t=nH(e.message,4096),n=nV(e.metadata);return r||=t.redacted||n.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.level?{level:e.level}:{},message:t.value??"",...e.source?{source:e.source}:{},...n.value?{metadata:n.value}:{}}}),...n.nextCursor?{nextCursor:n.nextCursor}:{},...n.timeWindow?{timeWindow:n.timeWindow}:{},...n.backend?{backend:n.backend}:{},redacted:r,...n.notes?{notes:n.notes}:{}}},nJ=async(e,t={})=>{var n,a,r;let i;if(!e.backend.dumpNetwork)throw new N("UNSUPPORTED_OPERATION","diagnostics.network is not supported by this backend");let s={...n0(r=t,25,200,"network limit"),include:function(e){if(void 0===e)return"summary";if("summary"===e||"headers"===e||"body"===e||"all"===e)return e;throw new N("INVALID_ARGS","network include must be summary, headers, body, or all")}(r.include)};return n=await e.backend.dumpNetwork(await nQ(e,t),s),a=s.include??"summary",i=!0===n.redacted,{kind:"diagnosticsNetwork",entries:n.entries.map(e=>{var t;let n=e.url?nq(t=e.url)??nH(t,2048):void 0,r="headers"===a||"all"===a?nK(e.requestHeaders):void 0,s="headers"===a||"all"===a?nK(e.responseHeaders):void 0,o="body"===a||"all"===a?nF(e.requestBody):void 0,l="body"===a||"all"===a?nF(e.responseBody):void 0,d=nV(e.metadata);return i||=(n?.redacted??!1)||(r?.redacted??!1)||(s?.redacted??!1)||(o?.redacted??!1)||(l?.redacted??!1)||d.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.method?{method:e.method}:{},...n?{url:n.value}:{},...void 0!==e.status?{status:e.status}:{},...void 0!==e.durationMs?{durationMs:e.durationMs}:{},...r?.value?{requestHeaders:r.value}:{},...s?.value?{responseHeaders:s.value}:{},...o?.value!==void 0?{requestBody:o.value}:{},...l?.value!==void 0?{responseBody:l.value}:{},...d.value?{metadata:d.value}:{}}}),...n.nextCursor?{nextCursor:n.nextCursor}:{},...n.timeWindow?{timeWindow:n.timeWindow}:{},...n.backend?{backend:n.backend}:{},redacted:i,...n.notes?{notes:n.notes}:{}}},nZ=async(e,t={})=>{var n,a;let r;if(!e.backend.measurePerf)throw new N("UNSUPPORTED_OPERATION","diagnostics.perf is not supported by this backend");return r=!0===(n=await e.backend.measurePerf(await nQ(e,t),{...n1(a=t),...void 0!==a.sampleMs?{sampleMs:x(a.sampleMs,"sampleMs",100,6e4)}:{},...void 0!==a.metrics?{metrics:n2(a.metrics,"metrics",20)}:{}})).redacted,{kind:"diagnosticsPerf",metrics:n.metrics.map(e=>{let t=nH(e.message,4096),n=nV(e.metadata);return r||=t.redacted||n.redacted,{name:e.name,...void 0!==e.value?{value:e.value}:{},...e.unit?{unit:e.unit}:{},...e.status?{status:e.status}:{},...void 0!==t.value?{message:t.value}:{},...n.value?{metadata:n.value}:{}}}),...n.startedAt?{startedAt:n.startedAt}:{},...n.endedAt?{endedAt:n.endedAt}:{},...n.backend?{backend:n.backend}:{},redacted:r,...n.notes?{notes:n.notes}:{}}};async function nQ(e,t){let n=y(e,t),a=t.session?await e.sessions.get(t.session):void 0;return{...n,...t.appId??a?.appId?{appId:t.appId??a?.appId}:{},...t.appBundleId??a?.appBundleId?{appBundleId:t.appBundleId??a?.appBundleId}:{}}}function n0(e,t,n,a){return{...n1(e),...void 0!==e.cursor?{cursor:nw(e.cursor,"cursor")}:{},limit:void 0===e.limit?t:x(e.limit,a,1,n)}}function n1(e){return{...void 0!==e.since?{since:nw(e.since,"since")}:{},...void 0!==e.until?{until:nw(e.until,"until")}:{}}}function n2(e,t,n=50){if(!Array.isArray(e))throw new N("INVALID_ARGS",`${t} must be an array of strings`);if(e.length>n)throw new N("INVALID_ARGS",`${t} must contain at most ${n} entries`);return e.map((e,n)=>nw(e,`${t}[${n}]`))}let n4=async(e,t)=>{let n=n5(t.action,"record"),a="start"===n?e.backend.startRecording:e.backend.stopRecording;if(!a)throw new N("UNSUPPORTED_OPERATION",`record ${n} is not supported by this backend`);let r=t.out?await tD(e,t.out,{field:"path",ext:".mp4"}):void 0;try{var i,s,o,l,d;let u,c,p=(i=t,s=r?.path,u=void 0===i.fps?void 0:x(i.fps,"fps",1,60),c=void 0===i.quality?void 0:x(i.quality,"quality",5,10),{...s?{outPath:s}:{},...void 0!==u?{fps:u}:{},...void 0!==c?{quality:c}:{},...void 0!==i.hideTouches?{showTouches:!0!==i.hideTouches}:{}}),h=await a.call(e.backend,y(e,t),p),f=await r?.publish();return o=n,l=h,d=f,{..."string"==typeof l.path?{path:l.path}:{},..."string"==typeof l.telemetryPath?{telemetryPath:l.telemetryPath}:{},..."string"==typeof l.warning?{warning:l.warning}:{},...n8(o,l,d,{startKind:"recordingStarted",stopKind:"recordingStopped",startMessage:"Recording started",stopMessage:"Recording stopped"})}}catch(e){throw await r?.cleanup?.(),e}},n3=async(e,t)=>{let n=n5(t.action,"trace"),a="start"===n?e.backend.startTrace:e.backend.stopTrace;if(!a)throw new N("UNSUPPORTED_OPERATION",`trace ${n} is not supported by this backend`);let r=t.out?await tD(e,t.out,{field:"outPath",ext:".trace"}):void 0;try{var i,s,o;let l={...r?.path?{outPath:r.path}:{}},d=await a.call(e.backend,y(e,t),l),u=await r?.publish();return i=n,s=d,o=u,{..."string"==typeof s.outPath?{outPath:s.outPath}:{},...n8(i,s,o,{startKind:"traceStarted",stopKind:"traceStopped",startMessage:"Trace started",stopMessage:"Trace stopped"})}}catch(e){throw await r?.cleanup?.(),e}};function n5(e,t){if("start"===e||"stop"===e)return e;throw new N("INVALID_ARGS",`${t} action must be start or stop`)}function n8(e,t,n,a){return{kind:"start"===e?a.startKind:a.stopKind,action:e,...n?{artifact:n}:{},backendResult:t,...f("start"===e?a.startMessage:a.stopMessage)}}let n6=async(e,t={})=>{if(!e.backend.pressBack)throw new N("UNSUPPORTED_OPERATION","system.back is not supported by this backend");let n=t.mode??"in-app";if("in-app"!==n&&"system"!==n)throw new N("INVALID_ARGS","system.back mode must be in-app or system");let a=w(await e.backend.pressBack(y(e,t),{mode:n}));return{kind:"systemBack",mode:n,...a?{backendResult:a}:{},...f("Back")}},n9=async(e,t={})=>{if(!e.backend.pressHome)throw new N("UNSUPPORTED_OPERATION","system.home is not supported by this backend");let n=w(await e.backend.pressHome(y(e,t)));return{kind:"systemHome",...n?{backendResult:n}:{},...f("Home")}},n7=async(e,t)=>{if(!e.backend.rotate)throw new N("UNSUPPORTED_OPERATION","system.rotate is not supported by this backend");let n=function(e){switch(e){case"portrait":case"portrait-upside-down":case"landscape-left":case"landscape-right":return e;default:throw new N("INVALID_ARGS","system.rotate orientation must be portrait, portrait-upside-down, landscape-left, or landscape-right")}}(t.orientation),a=w(await e.backend.rotate(y(e,t),n));return{kind:"systemRotated",orientation:n,...a?{backendResult:a}:{},...f(`Rotated to ${n}`)}},ae=async(e,t={})=>{var n,a,r,i,s,o,l;if(!e.backend.setKeyboard)throw new N("UNSUPPORTED_OPERATION","system.keyboard is not supported by this backend");let d=t.action??"status";if(!eC(d))throw new N("INVALID_ARGS","system.keyboard action must be status, get, dismiss, enter, or return");let u=await e.backend.setKeyboard(y(e,t),{action:d}),c=w(u),p=(n=u)&&"object"==typeof n?u:{};return"enter"===d||"return"===d?{kind:"keyboardEnterPressed",action:"enter",state:p,...(a=c)?{backendResult:a}:{},...f("Keyboard enter pressed")}:"dismiss"===d?(r=d,{kind:"keyboardDismissed",action:r,state:i=p,...(s=c)?{backendResult:s}:{},...f(!1===i.dismissed?"Keyboard already hidden":"Keyboard dismissed")}):(o=d,{kind:"keyboardState",action:o,state:p,...(l=c)?{backendResult:l}:{}})},at=async(e,t)=>{if("read"===t.action){if(!e.backend.getClipboard)throw new N("UNSUPPORTED_OPERATION","system.clipboard read is not supported by this backend");let n=await e.backend.getClipboard(y(e,t));return{kind:"clipboardText",action:"read",text:"string"==typeof n?n:n.text}}if("write"!==t.action)throw new N("INVALID_ARGS","system.clipboard action must be read or write");if(!e.backend.setClipboard)throw new N("UNSUPPORTED_OPERATION","system.clipboard write is not supported by this backend");if("string"!=typeof t.text)throw new N("INVALID_ARGS","system.clipboard write requires text");let n=w(await e.backend.setClipboard(y(e,t),t.text));return{kind:"clipboardUpdated",action:"write",textLength:Array.from(t.text).length,...n?{backendResult:n}:{},...f("Clipboard updated")}},an=async(e,t={})=>{if(!e.backend.openSettings)throw new N("UNSUPPORTED_OPERATION","system.settings is not supported by this backend");let n=nm(t.target,"target"),a=w(await e.backend.openSettings(y(e,t),n));return{kind:"settingsOpened",...n?{target:n}:{},...a?{backendResult:a}:{},...f(n?`Opened settings: ${n}`:"Opened settings")}},aa=async(e,t={})=>{var n,a;if(!e.backend.handleAlert)throw new N("UNSUPPORTED_OPERATION","system.alert is not supported by this backend");let r=t.action??"get";if("get"!==r&&"accept"!==r&&"dismiss"!==r&&"wait"!==r)throw new N("INVALID_ARGS","system.alert action must be get, accept, dismiss, or wait");let i=void 0===t.timeoutMs?void 0:x(t.timeoutMs,"timeoutMs",0,12e4),s=await e.backend.handleAlert(y(e,t),r,{timeoutMs:i});return n=r,a=s,"get"===n?function(e){if("alertStatus"!==e.kind)throw new N("COMMAND_FAILED","system.alert get returned an invalid backend result");return{kind:"alertStatus",action:"get",alert:e.alert}}(a):"wait"===n?function(e){if("alertWait"!==e.kind)throw new N("COMMAND_FAILED","system.alert wait returned an invalid backend result");return{kind:"alertWait",action:"wait",alert:e.alert,...void 0!==e.waitedMs?{waitedMs:e.waitedMs}:{},...void 0!==e.timedOut?{timedOut:e.timedOut}:{},...f(e.alert?"Alert visible":"Alert wait timed out")}}(a):function(e,t){if("alertHandled"!==t.kind)throw new N("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}:{},...f(t.handled?`Alert ${e}ed`:"No alert handled")}}(n,a)},ar=async(e,t={})=>{if(!e.backend.openAppSwitcher)throw new N("UNSUPPORTED_OPERATION","system.appSwitcher is not supported by this backend");let n=w(await e.backend.openAppSwitcher(y(e,t)));return{kind:"appSwitcherOpened",...n?{backendResult:n}:{},...f("Opened app switcher")}};function ai(e){let t={backend:e.backend,artifacts:e.artifacts,sessions:e.sessions??function(e=[]){let t=new Map(e.map(e=>[e.name,as(e)]));return{get:e=>as(t.get(e)),set:e=>{t.set(e.name,as(e))},delete:e=>{t.delete(e)},list:()=>Array.from(t.values(),e=>as(e))}}(),policy:e.policy??function(e={}){return{allowLocalInputPaths:!1,allowLocalOutputPaths:!1,maxImagePixels:2e7,allowNamedBackendCapabilities:[],...e}}(),diagnostics:e.diagnostics,clock:e.clock,signal:e.signal};return{...t,capture:{screenshot:e=>tY(t,e),diffScreenshot:e=>tT(t,e),snapshot:e=>tH(t,e),diffSnapshot:e=>tz(t,e)},selectors:{find:e=>ne(t,e),get:e=>nt(t,e),getText:(e,n={})=>nn(t,{...n,target:e}),getAttrs:(e,n={})=>na(t,{...n,target:e}),is:e=>nr(t,e),isVisible:(e,n={})=>ni(t,{...n,target:e}),isHidden:(e,n={})=>ns(t,{...n,target:e}),wait:e=>no(t,e),waitForText:(e,n={})=>nl(t,{...n,text:e})},interactions:{click:(e,n={})=>t0(t,{...n,target:e}),press:(e,n={})=>tQ(t,{...n,target:e}),fill:(e,n,a={})=>t1(t,{...a,target:e,text:n}),typeText:(e,n={})=>t2(t,{...n,text:e}),focus:(e,n={})=>m(t,{...n,target:e}),longPress:(e,n={})=>p(t,{...n,target:e}),swipe:e=>g(t,e),scroll:e=>c(t,e),pinch:e=>A(t,e)},system:{back:e=>n6(t,e),home:e=>n9(t,e),rotate:e=>n7(t,e),keyboard:e=>ae(t,e),clipboard:e=>at(t,e),settings:e=>an(t,e),alert:e=>aa(t,e),appSwitcher:e=>ar(t,e)},apps:{open:e=>n_(t,e),close:e=>nO(t,e),list:(e={})=>nD(t,{...e,filter:ec(e.filter)}),state:e=>nE(t,e),push:e=>nT(t,e),triggerEvent:e=>nC(t,e)},admin:{devices:e=>ng(t,e),boot:e=>nb(t,e),shutdown:e=>ny(t,e),install:e=>nk(t,e),reinstall:e=>nx(t,e),installFromSource:e=>nv(t,e)},recording:{record:e=>n4(t,e),trace:e=>n3(t,e)},observability:{logs:e=>nW(t,e),network:e=>nJ(t,e),perf:e=>nZ(t,e)}}}function as(e){if(e)return{...e,...e.snapshot?{snapshot:structuredClone(e.snapshot)}:{},...e.metadata?{metadata:function(e){try{return structuredClone(e)}catch{return{...e}}}(e.metadata)}:{}}}function ao(e={}){return{allowLocalInputPaths:!0,allowLocalOutputPaths:!0,maxImagePixels:2e7,allowNamedBackendCapabilities:[],...e}}export{eR as appendScriptSeriesFlags,ai as createAgentDevice,eZ as decodePngAsync,eQ as encodePngAsync,t5 as evaluateIsPredicate,eU as findMistargetedTypeRefToken,eE as formatPortableActionLine,eP as formatScriptActionSummary,ex as formatScriptArg,ev as formatScriptStringLiteral,eb as isClickLikeCommand,eC as isKeyboardAction,t3 as isSupportedPredicate,ey as isTouchTargetCommand,ao as localCommandPolicy,eD as parseReplayOpenFlags,e_ as parseReplayRuntimeFlags,eS as parseReplaySeriesFlags,eW as prewarmPngWorker,eJ as terminatePngWorker};
package/dist/src/1231.js CHANGED
@@ -1 +1 @@
1
- import{asAppError as t,AppError as e}from"./9152.js";let r=new Set(["batch","replay"]),a=new Set(["command","positionals","flags","runtime"]),o=["platform","target","device","udid","serial","verbose","out"];async function n(e,r,a){let o=e.flags,n=o?.batchOnError??"stop";if("stop"!==n)return m("INVALID_ARGS",`Unsupported batch on-error mode: ${n}.`);let i=o?.batchMaxSteps??100;if(!Number.isInteger(i)||i<1||i>1e3)return m("INVALID_ARGS",`Invalid batch max-steps: ${String(o?.batchMaxSteps)}`);try{let t=s(o?.batchSteps,i),n=Date.now(),l=[];for(let[o,n]of t.entries()){let s=await c(e,r,n,a,o+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:o,total:t.length,partialResults:l}}};l.push(s.result)}return{ok:!0,data:{total:t.length,executed:t.length,totalDurationMs:Date.now()-n,results:l}}}catch(r){let e=t(r);return m(e.code,e.message,e.details)}}function s(t,o){if(!Array.isArray(t)||0===t.length)throw new e("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(t.length>o)throw new e("INVALID_ARGS",`batch has ${t.length} steps; max allowed is ${o}.`);let n=[];for(let o=0;o<t.length;o+=1){let s=t[o];if(!s||"object"!=typeof s)throw new e("INVALID_ARGS",`Invalid batch step at index ${o}.`);let i=Object.keys(s).filter(t=>!a.has(t));if(i.length>0){let t=i.map(t=>`"${t}"`).join(", ");throw new e("INVALID_ARGS",`Batch step ${o+1} has unknown field(s): ${t}. Allowed fields: command, positionals, flags, runtime.`)}let l="string"==typeof s.command?s.command.trim().toLowerCase():"";if(!l)throw new e("INVALID_ARGS",`Batch step ${o+1} requires command.`);if(r.has(l))throw new e("INVALID_ARGS",`Batch step ${o+1} cannot run ${l}.`);if(void 0!==s.positionals&&!Array.isArray(s.positionals))throw new e("INVALID_ARGS",`Batch step ${o+1} positionals must be an array.`);let c=s.positionals??[];if(c.some(t=>"string"!=typeof t))throw new e("INVALID_ARGS",`Batch step ${o+1} positionals must contain only strings.`);if(void 0!==s.flags&&("object"!=typeof s.flags||Array.isArray(s.flags)||!s.flags))throw new e("INVALID_ARGS",`Batch step ${o+1} flags must be an object.`);if(void 0!==s.runtime&&("object"!=typeof s.runtime||Array.isArray(s.runtime)||!s.runtime))throw new e("INVALID_ARGS",`Batch step ${o+1} runtime must be an object.`);n.push({command:l,positionals:c,flags:s.flags??{},runtime:s.runtime})}return n}function i(t,e){let{batchSteps:r,batchOnError:a,batchMaxSteps:o,...n}=e??{};return l(t,n)}function l(t,e){let r=t??{};for(let t of o)void 0===e[t]&&void 0!==r[t]&&(e[t]=r[t]);return e}async function c(t,e,r,a,o){let n=Date.now(),s=i(t.flags,r.flags);void 0===s.session&&(s.session=e);let l=await a({token:t.token,session:e,command:r.command,positionals:r.positionals,flags:s,runtime:void 0===r.runtime?t.runtime:r.runtime,meta:t.meta}),c=Date.now()-n;return l.ok?{ok:!0,step:o,result:{step:o,command:r.command,ok:!0,data:l.data??{},durationMs:c}}:{ok:!1,step:o,error:l.error}}function m(t,e,r){return{ok:!1,error:{code:t,message:e,...r?{details:r}:{}}}}export{r as BATCH_BLOCKED_COMMANDS,o as INHERITED_PARENT_FLAG_KEYS,i as buildBatchStepFlags,l as mergeParentFlags,n as runBatch,s as validateAndNormalizeBatchSteps};
1
+ import{asAppError as t,AppError as e}from"./9152.js";import{normalizeBatchCommandName as r,INHERITED_PARENT_FLAG_KEYS as o,assertBatchRuntimeCommandAllowed as a,BATCH_DAEMON_STEP_KEYS as n}from"./6088.js";let s=new Set(n);async function i(e,r,o){let a=e.flags,n=a?.batchOnError??"stop";if("stop"!==n)return p("INVALID_ARGS",`Unsupported batch on-error mode: ${n}.`);let s=a?.batchMaxSteps??100;if(!Number.isInteger(s)||s<1||s>1e3)return p("INVALID_ARGS",`Invalid batch max-steps: ${String(a?.batchMaxSteps)}`);try{let t=l(a?.batchSteps,s),n=Date.now(),i=[];for(let[a,n]of t.entries()){let s=await h(e,r,n,o,a+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:a,total:t.length,partialResults:i}}};i.push(s.result)}return{ok:!0,data:{total:t.length,executed:t.length,totalDurationMs:Date.now()-n,results:i}}}catch(r){let e=t(r);return p(e.code,e.message,e.details)}}function l(t,o){if(!Array.isArray(t)||0===t.length)throw new e("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(t.length>o)throw new e("INVALID_ARGS",`batch has ${t.length} steps; max allowed is ${o}.`);let n=[];for(let o=0;o<t.length;o+=1){let i=t[o];if(!i||"object"!=typeof i)throw new e("INVALID_ARGS",`Invalid batch step at index ${o}.`);let l=Object.keys(i).filter(t=>!s.has(t));if(l.length>0){let t=l.map(t=>`"${t}"`).join(", ");throw new e("INVALID_ARGS",`Batch step ${o+1} has unknown field(s): ${t}. Allowed fields: command, positionals, flags, runtime.`)}let c=r(i.command);if(!c)throw new e("INVALID_ARGS",`Batch step ${o+1} requires command.`);if(a(c,o+1),void 0!==i.positionals&&!Array.isArray(i.positionals))throw new e("INVALID_ARGS",`Batch step ${o+1} positionals must be an array.`);let m=i.positionals??[];if(m.some(t=>"string"!=typeof t))throw new e("INVALID_ARGS",`Batch step ${o+1} positionals must contain only strings.`);if(void 0!==i.flags&&("object"!=typeof i.flags||Array.isArray(i.flags)||!i.flags))throw new e("INVALID_ARGS",`Batch step ${o+1} flags must be an object.`);if(void 0!==i.runtime&&("object"!=typeof i.runtime||Array.isArray(i.runtime)||!i.runtime))throw new e("INVALID_ARGS",`Batch step ${o+1} runtime must be an object.`);n.push({command:c,positionals:m,flags:i.flags??{},runtime:i.runtime})}return n}function c(t,e){let{batchSteps:r,batchOnError:o,batchMaxSteps:a,...n}=e??{};return m(t,n)}function m(t,e){let r=t??{};for(let t of o)void 0===e[t]&&void 0!==r[t]&&(e[t]=r[t]);return e}async function h(t,e,r,o,a){let n=Date.now(),s=c(t.flags,r.flags);void 0===s.session&&(s.session=e);let i=await o({token:t.token,session:e,command:r.command,positionals:r.positionals,flags:s,runtime:void 0===r.runtime?t.runtime:r.runtime,meta:t.meta}),l=Date.now()-n;return i.ok?{ok:!0,step:a,result:{step:a,command:r.command,ok:!0,data:i.data??{},durationMs:l}}:{ok:!1,step:a,error:i.error}}function p(t,e,r){return{ok:!1,error:{code:t,message:e,...r?{details:r}:{}}}}export{c as buildBatchStepFlags,m as mergeParentFlags,i as runBatch,l as validateAndNormalizeBatchSteps};
package/dist/src/1352.js CHANGED
@@ -1 +1 @@
1
- var e;import{AppError as s}from"./9152.js";import{SCREENSHOT_SPECIFIC_FLAG_DEFINITIONS as t,SCREENSHOT_COMMAND_FLAG_KEYS as a}from"./5310.js";import{DEFAULT_APPS_FILTER as o}from"./1393.js";import{listCommandDescriptionMetadata as r}from"./2805.js";let i="<wifi|airplane|location> <on|off>",n="location set <lat> <lon>",l="animations <on|off>",p="appearance <light|dark|toggle>",u="faceid <match|nonmatch|enroll|unenroll>",c="touchid <match|nonmatch|enroll|unenroll>",d="fingerprint <match|nonmatch>",m="clear-app-state [app-id]",g="permission <grant|deny|reset> <camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri> [full|limited]",h="permission <grant|reset> <accessibility|screen-recording|input-monitoring>",y=`macOS supports only settings ${p} and settings ${h}. wifi|airplane|location|animations remain unsupported on macOS.`,f=`settings ${i} | settings ${n} | settings ${l} | settings ${p} | settings ${u} | settings ${c} | settings ${d} | settings ${m} | settings ${g} | settings ${h}`,b=`settings requires ${i}, ${n}, ${l}, ${p}, ${u}, ${c}, ${d}, ${m}, ${g}, or ${h}`;function k(e){let s=e.trim().toLowerCase();return"appearance"===s||"permission"===s}function v(e){return`Unsupported macOS setting: ${e}. ${y}`}let D=["app","frontmost-app","desktop","menubar"];function w(e){let t=e?.trim().toLowerCase();if("app"===t||"frontmost-app"===t||"desktop"===t||"menubar"===t)return t;throw new s("INVALID_ARGS",`Invalid surface: ${e}. Use ${D.join("|")}.`)}let L="https://github.com/callstackincubator/agent-device/issues/558",O="https://github.com/callstackincubator/agent-device/issues/new";function S(...e){return e}let x=S("snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw"),A=S("snapshotDepth","snapshotScope","snapshotRaw"),M=S("metroProjectRoot","metroKind","metroPublicBaseUrl","metroProxyBaseUrl","metroBearerToken","metroPreparePort","metroListenHost","metroStatusHost","metroStartupTimeoutMs","metroProbeTimeoutMs","metroRuntimeFile","metroNoReuseExisting","metroNoInstallDeps"),E=S("metroHost","metroPort","bundleUrl"),R=S("count","intervalMs","holdMs","jitterPx","doubleTap"),U=S("replayUpdate","replayEnv"),T=[{key:"config",names:["--config"],type:"string",usageLabel:"--config <path>",usageDescription:"Load CLI defaults from a specific config file"},{key:"remoteConfig",names:["--remote-config"],type:"string",usageLabel:"--remote-config <path>",usageDescription:"Load remote host + Metro workflow settings from a specific profile file"},{key:"stateDir",names:["--state-dir"],type:"string",usageLabel:"--state-dir <path>",usageDescription:"Daemon state directory (defaults to ~/.agent-device)"},{key:"daemonBaseUrl",names:["--daemon-base-url"],type:"string",usageLabel:"--daemon-base-url <url>",usageDescription:"Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)"},{key:"daemonAuthToken",names:["--daemon-auth-token"],type:"string",usageLabel:"--daemon-auth-token <token>",usageDescription:"Remote HTTP daemon auth token (sent as request token and bearer header)"},{key:"daemonTransport",names:["--daemon-transport"],type:"enum",enumValues:["auto","socket","http"],usageLabel:"--daemon-transport auto|socket|http",usageDescription:"Daemon client transport preference"},{key:"daemonServerMode",names:["--daemon-server-mode"],type:"enum",enumValues:["socket","http","dual"],usageLabel:"--daemon-server-mode socket|http|dual",usageDescription:"Daemon server mode used when spawning daemon"},{key:"tenant",names:["--tenant"],type:"string",usageLabel:"--tenant <id>",usageDescription:"Tenant scope identifier for isolated daemon sessions"},{key:"sessionIsolation",names:["--session-isolation"],type:"enum",enumValues:["none","tenant"],usageLabel:"--session-isolation none|tenant",usageDescription:"Session isolation strategy (tenant prefixes session namespace)"},{key:"runId",names:["--run-id"],type:"string",usageLabel:"--run-id <id>",usageDescription:"Run identifier used for tenant lease admission checks"},{key:"leaseId",names:["--lease-id"],type:"string",usageLabel:"--lease-id <id>",usageDescription:"Lease identifier bound to tenant/run admission scope"},{key:"leaseBackend",names:["--lease-backend"],type:"enum",enumValues:["ios-simulator","ios-instance","android-instance"],usageLabel:"--lease-backend ios-simulator|ios-instance|android-instance",usageDescription:"Lease backend for remote tenant connection admission"},{key:"force",names:["--force"],type:"boolean",usageLabel:"--force",usageDescription:"Force connection state replacement when reconnecting"},{key:"noLogin",names:["--no-login"],type:"boolean",usageLabel:"--no-login",usageDescription:"Connect: fail instead of starting implicit cloud login"},{key:"sessionLock",names:["--session-lock"],type:"enum",enumValues:["reject","strip"],usageLabel:"--session-lock reject|strip",usageDescription:"Lock bound-session device routing for this CLI invocation and nested batch steps"},{key:"sessionLocked",names:["--session-locked"],type:"boolean",usageLabel:"--session-locked",usageDescription:"Deprecated alias for --session-lock reject"},{key:"sessionLockConflicts",names:["--session-lock-conflicts"],type:"enum",enumValues:["reject","strip"],usageLabel:"--session-lock-conflicts reject|strip",usageDescription:"Deprecated alias for --session-lock"},{key:"platform",names:["--platform"],type:"enum",enumValues:["ios","macos","android","linux","apple"],usageLabel:"--platform ios|macos|android|linux|apple",usageDescription:"Platform to target (`apple` aliases the Apple automation backend)"},{key:"target",names:["--target"],type:"enum",enumValues:["mobile","tv","desktop"],usageLabel:"--target mobile|tv|desktop",usageDescription:"Device target class to match"},{key:"device",names:["--device"],type:"string",usageLabel:"--device <name>",usageDescription:"Device name to target"},{key:"udid",names:["--udid"],type:"string",usageLabel:"--udid <udid>",usageDescription:"iOS device UDID"},{key:"serial",names:["--serial"],type:"string",usageLabel:"--serial <serial>",usageDescription:"Android device serial"},{key:"surface",names:["--surface"],type:"enum",enumValues:D,usageLabel:"--surface app|frontmost-app|desktop|menubar",usageDescription:"macOS session surface for open (defaults to app)"},{key:"headless",names:["--headless"],type:"boolean",usageLabel:"--headless",usageDescription:"Boot: launch Android emulator without a GUI window"},{key:"metroHost",names:["--metro-host"],type:"string",usageLabel:"--metro-host <host>",usageDescription:"Session-scoped Metro/debug host hint"},{key:"metroPort",names:["--metro-port"],type:"int",min:1,max:65535,usageLabel:"--metro-port <port>",usageDescription:"Session-scoped Metro/debug port hint"},{key:"metroProjectRoot",names:["--project-root"],type:"string",usageLabel:"--project-root <path>",usageDescription:"metro prepare: React Native project root (default: cwd)"},{key:"metroKind",names:["--kind"],type:"enum",enumValues:["auto","react-native","expo"],usageLabel:"--kind auto|react-native|expo",usageDescription:"metro prepare: detect or force the Metro launcher kind"},{key:"metroPublicBaseUrl",names:["--public-base-url"],type:"string",usageLabel:"--public-base-url <url>",usageDescription:"metro prepare: public base URL used for direct bundle hints"},{key:"metroProxyBaseUrl",names:["--proxy-base-url"],type:"string",usageLabel:"--proxy-base-url <url>",usageDescription:"metro prepare: optional bridge origin for remote Metro access"},{key:"metroBearerToken",names:["--bearer-token"],type:"string",usageLabel:"--bearer-token <token>",usageDescription:"metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)"},{key:"metroPreparePort",names:["--port"],type:"int",min:1,max:65535,usageLabel:"--port <port>",usageDescription:"metro prepare: local Metro port (default: 8081)"},{key:"metroListenHost",names:["--listen-host"],type:"string",usageLabel:"--listen-host <host>",usageDescription:"metro prepare: host Metro listens on (default: 0.0.0.0)"},{key:"metroStatusHost",names:["--status-host"],type:"string",usageLabel:"--status-host <host>",usageDescription:"metro prepare: host used for local /status polling (default: 127.0.0.1)"},{key:"metroStartupTimeoutMs",names:["--startup-timeout-ms"],type:"int",min:1,usageLabel:"--startup-timeout-ms <ms>",usageDescription:"metro prepare: timeout while waiting for Metro to become ready"},{key:"metroProbeTimeoutMs",names:["--probe-timeout-ms"],type:"int",min:1,usageLabel:"--probe-timeout-ms <ms>",usageDescription:"metro prepare: timeout for /status and proxy bridge calls"},{key:"metroRuntimeFile",names:["--runtime-file"],type:"string",usageLabel:"--runtime-file <path>",usageDescription:"metro prepare: optional file path to persist the JSON result"},{key:"metroNoReuseExisting",names:["--no-reuse-existing"],type:"boolean",usageLabel:"--no-reuse-existing",usageDescription:"metro prepare: always start a fresh Metro process"},{key:"metroNoInstallDeps",names:["--no-install-deps"],type:"boolean",usageLabel:"--no-install-deps",usageDescription:"metro prepare: skip package-manager install when node_modules is missing"},{key:"bundleUrl",names:["--bundle-url"],type:"string",usageLabel:"--bundle-url <url>",usageDescription:"Session-scoped bundle URL hint"},{key:"launchUrl",names:["--launch-url"],type:"string",usageLabel:"--launch-url <url>",usageDescription:"Session-scoped deep link / launch URL hint"},{key:"iosSimulatorDeviceSet",names:["--ios-simulator-device-set"],type:"string",usageLabel:"--ios-simulator-device-set <path>",usageDescription:"Scope iOS simulator discovery/commands to this simulator device set"},{key:"androidDeviceAllowlist",names:["--android-device-allowlist"],type:"string",usageLabel:"--android-device-allowlist <serials>",usageDescription:"Comma/space separated Android serial allowlist for discovery/selection"},{key:"activity",names:["--activity"],type:"string",usageLabel:"--activity <component>",usageDescription:"Android app launch activity (package/Activity); not for URL opens"},{key:"launchConsole",names:["--launch-console"],type:"string",usageLabel:"--launch-console <path>",usageDescription:"open: capture the initial iOS simulator launch console window to a file"},{key:"launchArgs",names:["--launch-args"],type:"string",multiple:!0,usageLabel:"--launch-args <arg>",usageDescription:"open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag."},{key:"header",names:["--header"],type:"string",multiple:!0,usageLabel:"--header <name:value>",usageDescription:"install-from-source: repeatable HTTP header for URL downloads"},{key:"githubActionsArtifact",names:["--github-actions-artifact"],type:"string",usageLabel:"--github-actions-artifact <owner/repo:artifact>",usageDescription:"install-from-source: GitHub Actions artifact resolved by a remote daemon"},{key:"installSource",names:[],type:"string"},{key:"session",names:["--session"],type:"string",usageLabel:"--session <name>",usageDescription:"Named session"},{key:"count",names:["--count"],type:"int",min:1,max:200,usageLabel:"--count <n>",usageDescription:"Repeat count for press/swipe series"},{key:"fps",names:["--fps"],type:"int",min:1,max:120,usageLabel:"--fps <n>",usageDescription:"Record: target frames per second (iOS physical device runner)"},{key:"quality",names:["--quality"],type:"int",min:5,max:10,usageLabel:"--quality <5-10>",usageDescription:"Record: scale recording resolution from 5 (50%) through 10 (native resolution)"},{key:"hideTouches",names:["--hide-touches"],type:"boolean",usageLabel:"--hide-touches",usageDescription:"Record: skip touch-overlay post-processing for faster raw benchmark videos"},{key:"intervalMs",names:["--interval-ms"],type:"int",min:0,max:1e4,usageLabel:"--interval-ms <ms>",usageDescription:"Delay between press iterations"},{key:"delayMs",names:["--delay-ms"],type:"int",min:0,max:1e4,usageLabel:"--delay-ms <ms>",usageDescription:"Delay between typed characters"},{key:"holdMs",names:["--hold-ms"],type:"int",min:0,max:1e4,usageLabel:"--hold-ms <ms>",usageDescription:"Press hold duration for each iteration"},{key:"jitterPx",names:["--jitter-px"],type:"int",min:0,max:100,usageLabel:"--jitter-px <n>",usageDescription:"Deterministic coordinate jitter radius for press"},{key:"pixels",names:["--pixels"],type:"int",min:1,max:1e5,usageLabel:"--pixels <n>",usageDescription:"Scroll: explicit gesture distance in pixels"},{key:"doubleTap",names:["--double-tap"],type:"boolean",usageLabel:"--double-tap",usageDescription:"Use double-tap gesture per press iteration"},{key:"clickButton",names:["--button"],type:"enum",enumValues:["primary","secondary","middle"],usageLabel:"--button primary|secondary|middle",usageDescription:"Click: choose mouse button (middle reserved for future macOS support)"},{key:"backMode",names:["--in-app"],type:"enum",enumValues:["in-app","system"],setValue:"in-app",usageLabel:"--in-app",usageDescription:"Back: use app-provided back UI when available"},{key:"backMode",names:["--system"],type:"enum",enumValues:["in-app","system"],setValue:"system",usageLabel:"--system",usageDescription:"Back: use system back input or gesture when available"},{key:"pauseMs",names:["--pause-ms"],type:"int",min:0,max:1e4,usageLabel:"--pause-ms <ms>",usageDescription:"Delay between swipe iterations"},{key:"pattern",names:["--pattern"],type:"enum",enumValues:["one-way","ping-pong"],usageLabel:"--pattern one-way|ping-pong",usageDescription:"Swipe repeat pattern"},{key:"verbose",names:["--debug","--verbose","-v"],type:"boolean",usageLabel:"--debug, --verbose, -v",usageDescription:"Enable debug diagnostics; test --verbose prints per-test step timings without debug logs"},{key:"json",names:["--json"],type:"boolean",usageLabel:"--json",usageDescription:"JSON output"},{key:"help",names:["--help","-h"],type:"boolean",usageLabel:"--help, -h",usageDescription:"Print help and exit"},{key:"version",names:["--version","-V"],type:"boolean",usageLabel:"--version, -V",usageDescription:"Print version and exit"},{key:"snapshotDiff",names:["--diff"],type:"boolean",usageLabel:"--diff",usageDescription:"Snapshot: show structural diff against the previous session baseline"},{key:"saveScript",names:["--save-script"],type:"booleanOrString",usageLabel:"--save-script [path]",usageDescription:"Save session script (.ad) on close; optional custom output path"},{key:"networkInclude",names:["--include"],type:"enum",enumValues:["summary","headers","body","all"],usageLabel:"--include summary|headers|body|all",usageDescription:"Network: include headers, bodies, or both in output"},{key:"shutdown",names:["--shutdown"],type:"boolean",usageLabel:"--shutdown",usageDescription:"close: shutdown associated simulator/emulator after ending session"},{key:"relaunch",names:["--relaunch"],type:"boolean",usageLabel:"--relaunch",usageDescription:"open: terminate app process before launching it"},{key:"restart",names:["--restart"],type:"boolean",usageLabel:"--restart",usageDescription:"logs clear: stop active stream, clear logs, then start streaming again"},{key:"retainPaths",names:["--retain-paths"],type:"boolean",usageLabel:"--retain-paths",usageDescription:"install-from-source: keep materialized artifact paths after install"},{key:"retentionMs",names:["--retention-ms"],type:"int",min:1,usageLabel:"--retention-ms <ms>",usageDescription:"install-from-source: retention TTL for materialized artifact paths"},{key:"noRecord",names:["--no-record"],type:"boolean",usageLabel:"--no-record",usageDescription:"Do not record this action"},{key:"replayUpdate",names:["--update","-u"],type:"boolean",usageLabel:"--update, -u",usageDescription:"Replay: update selectors and rewrite replay file in place"},{key:"replayMaestro",names:["--maestro"],type:"boolean",usageLabel:"--maestro",usageDescription:`Replay: treat input as a Maestro YAML compatibility flow. Supported subset: ${(e=["app launch with Apple-platform launch arguments and Android/iOS simulator clearState","runFlow file/inline with when.platform, when.visible, when.notVisible, and limited when.true boolean/platform expressions","onFlowStart and onFlowComplete hooks","deterministic repeat.times","tapOn including optional, index, childOf, label, and absolute/percentage point taps","doubleTapOn and longPressOn","inputText, focused-field eraseText, and pasteText","openLink","visibility assertions and extendedWaitUntil","scroll and scrollUntilVisible","absolute/percentage swipe and swipe.label","screenshots","keyboard dismiss","basic pressKey, back, animation waits, and stopApp","ordered trusted runScript file/env scripts with http.post, json, and output variables"]).length>1?`${e.slice(0,-1).join(", ")}, and ${e.at(-1)}`:e[0]??""}. Unsupported syntax fails loudly with a link to ${L}`},{key:"replayEnv",names:["-e","--env"],type:"string",multiple:!0,usageLabel:"-e KEY=VALUE, --env KEY=VALUE",usageDescription:"Replay/Test: inject or override a ${KEY} variable for the script (repeatable)"},{key:"failFast",names:["--fail-fast"],type:"boolean",usageLabel:"--fail-fast",usageDescription:"Test: stop the suite after the first failing script; with sharding, each shard stops independently"},{key:"timeoutMs",names:["--timeout"],type:"int",min:1,usageLabel:"--timeout <ms>",usageDescription:"Prepare/Replay/Snapshot/Test: maximum wall-clock time for the command or attempt"},{key:"retries",names:["--retries"],type:"int",min:0,max:3,usageLabel:"--retries <n>",usageDescription:"Test: retry each failed script up to n additional times"},{key:"recordVideo",names:["--record-video"],type:"boolean",usageLabel:"--record-video",usageDescription:"Test: record each replay attempt to recording.mp4 in its attempt artifacts"},{key:"artifactsDir",names:["--artifacts-dir"],type:"string",usageLabel:"--artifacts-dir <path>",usageDescription:"Test: root directory for suite artifacts"},{key:"reportJunit",names:["--report-junit"],type:"string",usageLabel:"--report-junit <path>",usageDescription:"Test: write a JUnit XML report for the replay suite"},{key:"shardAll",names:["--shard-all"],type:"int",min:1,usageLabel:"--shard-all <n>",usageDescription:"Test: run the full suite on each of n devices; AD_SHARD_INDEX is zero-based"},{key:"shardSplit",names:["--shard-split"],type:"int",min:1,usageLabel:"--shard-split <n>",usageDescription:"Test: split runnable suite entries across n devices; AD_SHARD_INDEX is zero-based"},{key:"steps",names:["--steps"],type:"string",usageLabel:"--steps <json>",usageDescription:"Batch: JSON array of steps"},{key:"stepsFile",names:["--steps-file"],type:"string",usageLabel:"--steps-file <path>",usageDescription:"Batch: read steps JSON from file"},{key:"batchOnError",names:["--on-error"],type:"enum",enumValues:["stop"],usageLabel:"--on-error stop",usageDescription:"Batch: stop when a step fails"},{key:"batchMaxSteps",names:["--max-steps"],type:"int",min:1,max:1e3,usageLabel:"--max-steps <n>",usageDescription:"Batch: maximum number of allowed steps"},{key:"appsFilter",names:["--all"],type:"enum",enumValues:["user-installed","all"],setValue:"all",usageLabel:"--all",usageDescription:"Apps: include system/OEM apps"},{key:"snapshotInteractiveOnly",names:["-i"],type:"boolean",usageLabel:"-i",usageDescription:"Snapshot: interactive elements only"},{key:"snapshotCompact",names:["-c"],type:"boolean",usageLabel:"-c",usageDescription:"Snapshot: compact output (drop empty structure)"},{key:"snapshotDepth",names:["--depth","-d"],type:"int",min:0,usageLabel:"--depth, -d <depth>",usageDescription:"Snapshot: limit snapshot depth"},{key:"snapshotScope",names:["--scope","-s"],type:"string",usageLabel:"--scope, -s <scope>",usageDescription:"Snapshot: scope snapshot to label/identifier"},{key:"snapshotRaw",names:["--raw"],type:"boolean",usageLabel:"--raw",usageDescription:"Snapshot: raw node output"},{key:"snapshotForceFull",names:["--force-full"],type:"boolean",usageLabel:"--force-full",usageDescription:"Snapshot: re-emit the full tree even when unchanged"},{key:"findFirst",names:["--first"],type:"boolean",usageLabel:"--first",usageDescription:"Find: pick the first match when ambiguous"},{key:"findLast",names:["--last"],type:"boolean",usageLabel:"--last",usageDescription:"Find: pick the last match when ambiguous"},{key:"out",names:["--out"],type:"string",usageLabel:"--out <path>",usageDescription:"Output path"},{key:"overlayRefs",names:["--overlay-refs"],type:"boolean",usageLabel:"--overlay-refs",usageDescription:"Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide"},...t,{key:"baseline",names:["--baseline","-b"],type:"string",usageLabel:"--baseline, -b <path>",usageDescription:"Diff screenshot: path to baseline image file"},{key:"threshold",names:["--threshold"],type:"string",usageLabel:"--threshold <0-1>",usageDescription:"Diff screenshot: color distance threshold (default 0.1)"}],P=new Set(["json","config","remoteConfig","stateDir","daemonBaseUrl","daemonAuthToken","daemonTransport","daemonServerMode","tenant","sessionIsolation","runId","leaseId","leaseBackend","sessionLock","sessionLocked","sessionLockConflicts","help","version","verbose","platform","target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist","session","noRecord"]),F=new Map;for(let e of T)for(let s of e.names)F.set(s,e);function _(e){return F.get(e)}function C(){return T}let I={auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth status|login|logout",helpDescription:"Manage cloud CLI authentication",summary:"Manage cloud authentication",positionalArgs:["status|login|logout"]},connect:{usageOverride:"connect [--remote-config <path>] [--tenant <id>] [--run-id <id>] [--lease-backend <backend>] [--force] [--no-login]",helpDescription:"Connect to a remote daemon, authenticate when needed, and save remote session state. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.",summary:"Connect to remote daemon",allowedFlags:["force","noLogin",...M,"launchUrl"]},connection:{usageOverride:"connection status",listUsageOverride:"connection status",helpDescription:"Inspect active remote connection state",summary:"Inspect remote connection",positionalArgs:["status"]},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",summary:"Disconnect remote daemon",allowedFlags:["shutdown"]},mcp:{helpDescription:"Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.",summary:"Start MCP server"},"react-devtools":{usageOverride:"react-devtools [...args]",listUsageOverride:"react-devtools [...args]",helpDescription:"Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis",summary:"Profile React Native performance and component renders",positionalArgs:["args?"],allowsExtraPositionals:!0}},j={boot:{summary:"Boot target device/simulator",allowedFlags:["headless"]},prepare:{usageOverride:"prepare ios-runner --platform ios|macos [--timeout <ms>]",listUsageOverride:"prepare ios-runner --platform ios|macos",helpDescription:"Prepare platform helper infrastructure. ios-runner builds/reuses, starts, and health-checks the XCTest runner so later Apple snapshots and interactions do not pay first-use startup cost. In CI, run it after boot/install and before replay/test; if replay/test starts a separate daemon, run clean:daemon after prepare to release the prepared runner lease. Runner build/start output is written to the session runner.log; daemon.log is for daemon lifecycle/startup issues.",summary:"Prepare platform helpers",positionalArgs:["ios-runner"],allowedFlags:["timeoutMs"]},open:{helpDescription:"Boot device/simulator; optionally launch app or deep link URL (macOS also supports --surface app|frontmost-app|desktop|menubar)",summary:"Open an app, deep link or URL, save replays",positionalArgs:["appOrUrl?","url?"],allowedFlags:["activity","launchConsole","launchArgs","saveScript","relaunch","surface"]},close:{positionalArgs:["app?"],allowedFlags:["saveScript","shutdown"]},reinstall:{positionalArgs:["app","path"]},install:{positionalArgs:["app","path"]},"install-from-source":{usageOverride:"install-from-source <url> | install-from-source --github-actions-artifact <owner/repo:artifact>",listUsageOverride:"install-from-source <url> | install-from-source --github-actions-artifact",helpDescription:"Install app from a URL or remote-resolved source",summary:"Install app from a source",positionalArgs:["url?"],allowedFlags:["header","githubActionsArtifact","installSource","retainPaths","retentionMs"]},apps:{helpDescription:"List user-installed apps; use --all to include system/OEM apps",summary:"List installed apps",allowedFlags:["appsFilter"],defaults:{appsFilter:o}},push:{positionalArgs:["bundleOrPackage","payloadOrJson"]},snapshot:{usageOverride:"snapshot [--diff] [-i] [-c] [-d <depth>] [-s <scope>] [--raw] [--force-full] [--timeout <ms>]",helpDescription:"Capture accessibility tree or diff against the previous session baseline",allowedFlags:["snapshotDiff",...x,"snapshotForceFull","timeoutMs"]},diff:{usageOverride:"diff snapshot | diff screenshot --baseline <path> [current.png] [--out <diff.png>] [--threshold <0-1>] [--overlay-refs]",helpDescription:"Diff accessibility snapshot or compare screenshots pixel-by-pixel",summary:"Diff snapshot or screenshot",positionalArgs:["kind","current?"],allowedFlags:[...x,"baseline","threshold","out","overlayRefs"]},screenshot:{helpDescription:"Capture screenshot (macOS app sessions default to the app window; use --fullscreen for full desktop, --max-size to downscale, --overlay-refs to annotate current refs, or --no-stabilize for low-latency Android capture loops)",positionalArgs:["path?"],allowedFlags:a},appstate:{helpDescription:"Show foreground app/activity"},perf:{usageOverride:"perf [metrics|frames] [sample]",listUsageOverride:"perf [metrics|frames]",helpDescription:"Show session performance metrics or focused frame/jank health. Bare perf and metrics are aliases for perf metrics.",summary:"Show session performance and frame health",positionalArgs:["area?","action?"]},metro:{usageOverride:"metro prepare (--public-base-url <url> | --proxy-base-url <url>) [--project-root <path>] [--port <port>] [--kind auto|react-native|expo]\n agent-device metro reload [--metro-host <host>] [--metro-port <port>] [--bundle-url <url>]",listUsageOverride:"metro prepare --public-base-url <url> | --proxy-base-url <url>; metro reload",helpDescription:"Prepare a local Metro runtime or ask Metro to reload connected React Native apps",summary:"Prepare Metro or reload apps",positionalArgs:["prepare|reload"],allowedFlags:[...E,...M]},clipboard:{usageOverride:"clipboard read | clipboard write <text>",listUsageOverride:"clipboard read | clipboard write <text>",helpDescription:"Read or write device clipboard text",positionalArgs:["read|write","text?"],allowsExtraPositionals:!0},keyboard:{usageOverride:"keyboard [status|get|dismiss|enter|return]",helpDescription:"Inspect Android keyboard visibility/type or press/dismiss the device keyboard",summary:"Inspect, press, or dismiss the device keyboard",positionalArgs:["action?"]},back:{usageOverride:"back [--in-app|--system]",allowedFlags:["backMode"]},rotate:{usageOverride:"rotate <portrait|portrait-upside-down|landscape-left|landscape-right>",helpDescription:"Rotate device orientation on iOS and Android",positionalArgs:["orientation"]},wait:{usageOverride:"wait <ms>|text <text>|@ref|<selector> [timeoutMs]",positionalArgs:["durationOrSelector","timeoutMs?"],allowsExtraPositionals:!0,allowedFlags:[...A]},get:{usageOverride:"get text|attrs <@ref|selector>",positionalArgs:["subcommand","target"],allowedFlags:[...A]},find:{usageOverride:"find <locator|text> <action> [value] [--first|--last]",helpDescription:"Find by text/label/value/role/id and run action",summary:"Find an element and act",positionalArgs:["query","action","value?"],allowsExtraPositionals:!0,allowedFlags:["snapshotDepth","snapshotRaw","findFirst","findLast"]},is:{positionalArgs:["predicate","selector","value?"],allowsExtraPositionals:!0,allowedFlags:[...A]},alert:{usageOverride:"alert [get|accept|dismiss|wait] [timeout]",positionalArgs:["action?","timeout?"]},click:{usageOverride:"click <x y|@ref|selector>",positionalArgs:["target"],allowsExtraPositionals:!0,allowedFlags:[...R,"clickButton",...A]},replay:{positionalArgs:["path"],allowedFlags:["replayMaestro",...U,"timeoutMs"]},test:{usageOverride:"test <path-or-glob>...",listUsageOverride:"test <path-or-glob>...",helpDescription:"Run one or more replay scripts as a serial test suite",summary:"Run replay test suites",positionalArgs:["pathOrGlob"],allowsExtraPositionals:!0,allowedFlags:["replayMaestro",...U,"failFast","timeoutMs","retries","recordVideo","artifactsDir","reportJunit","shardAll","shardSplit"]},batch:{usageOverride:"batch [--steps <json> | --steps-file <path>]",listUsageOverride:"batch --steps <json> | --steps-file <path>",helpDescription:"Execute multiple commands in one daemon request",summary:"Run multiple commands",allowedFlags:["steps","stepsFile","batchOnError","batchMaxSteps","out"]},press:{usageOverride:"press <x y|@ref|selector>",positionalArgs:["targetOrX","y?"],allowsExtraPositionals:!0,allowedFlags:[...R,...A]},longpress:{usageOverride:"longpress <x y|@ref|selector> [durationMs]",positionalArgs:["targetOrX","yOrDurationMs?","durationMs?"],allowsExtraPositionals:!0,allowedFlags:[...A]},swipe:{helpDescription:"Swipe coordinates with optional repeat pattern",positionalArgs:["x1","y1","x2","y2","durationMs?"],allowedFlags:["count","pauseMs","pattern"]},gesture:{usageOverride:"gesture <pan|fling|swipe|pinch|rotate|transform> ...",listUsageOverride:"gesture <pan|fling|swipe|pinch|rotate|transform> ...",helpDescription:"Run touch gestures: pan <x> <y> <dx> <dy> [durationMs], fling <up|down|left|right> <x> <y> [distance] [durationMs], swipe <left|right|left-edge|right-edge> [durationMs], pinch <scale> [x] [y], rotate <degrees> [x] [y] [velocity], or transform <x> <y> <dx> <dy> <scale> <degrees> [durationMs]",summary:"Run pan, fling, swipe, pinch, rotate, or transform gestures",positionalArgs:["pan|fling|swipe|pinch|rotate|transform","args?"],allowsExtraPositionals:!0},focus:{positionalArgs:["x","y"]},type:{positionalArgs:["text"],allowsExtraPositionals:!0,allowedFlags:["delayMs"]},fill:{usageOverride:"fill <x> <y> <text> | fill <@ref|selector> <text>",positionalArgs:["targetOrX","yOrText","text?"],allowsExtraPositionals:!0,allowedFlags:[...A,"delayMs"]},scroll:{usageOverride:"scroll <direction|top|bottom> [amount] [--pixels <n>]",helpDescription:"Scroll in direction, or verify hidden content and scroll toward top/bottom",summary:"Scroll in a direction or to an edge",positionalArgs:["directionOrEdge","amount?"],allowedFlags:["pixels"]},"trigger-app-event":{usageOverride:"trigger-app-event <event> [payloadJson]",positionalArgs:["event","payloadJson?"]},record:{usageOverride:"record start [path] [--fps <n>] [--quality <5-10>] [--hide-touches] | record stop",listUsageOverride:"record start [path] | record stop",helpDescription:"Start/stop screen recording; Android recordings longer than the 180s adb screenrecord limit are returned as multiple MP4 chunks",summary:"Start or stop screen recording",positionalArgs:["start|stop","path?"],allowedFlags:["fps","quality","hideTouches"]},"react-native":{usageOverride:"react-native dismiss-overlay",listUsageOverride:"react-native dismiss-overlay",positionalArgs:["dismiss-overlay"]},trace:{usageOverride:"trace start <path> | trace stop <path>",listUsageOverride:"trace start <path> | trace stop <path>",helpDescription:"Start/stop trace log capture; when an artifact path is requested, pass the same positional path to start and stop",summary:"Start or stop trace capture",positionalArgs:["start|stop","path?"]},logs:{usageOverride:"logs path | logs start | logs stop | logs clear [--restart] | logs doctor | logs mark [message...]",helpDescription:"Session app log info, start/stop streaming, diagnostics, and markers",summary:"Manage session app logs",positionalArgs:["path|start|stop|clear|doctor|mark","message?"],allowsExtraPositionals:!0,allowedFlags:["restart"]},network:{usageOverride:"network dump [limit] [summary|headers|body|all] [--include summary|headers|body|all] | network log [limit] [summary|headers|body|all] [--include summary|headers|body|all]",helpDescription:"Dump recent HTTP(s) traffic parsed from the session app log",summary:"Show recent HTTP traffic",positionalArgs:["dump|log","limit?","include?"],allowedFlags:["networkInclude"]},settings:{usageOverride:f,listUsageOverride:"settings [area] [options]",helpDescription:"Toggle OS settings, animation scales, appearance, and app permissions (macOS supports only settings appearance <light|dark|toggle> and settings permission <grant|reset> <accessibility|screen-recording|input-monitoring>; wifi|airplane|location|animations remain unsupported on macOS; mobile permission actions use the active session app)",summary:"Change OS settings and app permissions",positionalArgs:["setting","state","target?","mode?"]},session:{usageOverride:"session list",positionalArgs:["list?"]}},N=new Map(r().map(e=>[e.name,{helpDescription:e.description}]));function V(e){if(e)return B(e)}function $(e){let s=B(e);if(!s)throw Error(`Missing command schema for ${e}`);return s}function B(e){let s=Object.hasOwn(I,e)?I[e]:void 0;if(s)return s;let t=N.get(e),a=Object.hasOwn(j,e)?j[e]:void 0;if(t)return a?{...t,...a}:t}function H(e,s){let t=V(e);if(!t?.defaults)return!1;let a=!1;for(let[e,o]of Object.entries(t.defaults))void 0===s[e]&&(s[e]=o,a=!0);return a}export{P as GLOBAL_FLAG_KEYS,L as MAESTRO_COMPAT_TRACKER_URL,O as MAESTRO_NEW_ISSUE_URL,b as SETTINGS_INVALID_ARGS_MESSAGE,H as applyCommandDefaults,$ as getCliCommandSchema,V as getCommandSchema,_ as getFlagDefinition,C as getFlagDefinitions,v as getUnsupportedMacOsSettingMessage,k as isMacOsSettingSupported,w as parseSessionSurface};
1
+ import{managementCliSchemas as e,perfCliSchemas as t,captureCliSchemas as o,observabilityCliSchemas as n,replayCliSchemas as a,interactionCliSchemas as r,recordingCliSchemas as s,METRO_PREPARE_FLAGS as i,batchCliSchemas as c,systemCliSchemas as l,reactNativeCliSchemas as d}from"./6133.js";import{listCommandMetadata as m,debuggingCliSchemas as u,metroCliSchemas as p}from"./5611.js";let g={auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth status|login|logout",helpDescription:"Manage cloud CLI authentication",summary:"Manage cloud authentication",positionalArgs:["status|login|logout"]},connect:{usageOverride:"connect [--remote-config <path>] [--tenant <id>] [--run-id <id>] [--lease-backend <backend>] [--force] [--no-login]",helpDescription:"Connect to a remote daemon, authenticate when needed, and save remote session state. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.",summary:"Connect to remote daemon",allowedFlags:["force","noLogin",...i,"launchUrl"]},connection:{usageOverride:"connection status",listUsageOverride:"connection status",helpDescription:"Inspect active remote connection state",summary:"Inspect remote connection",positionalArgs:["status"]},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",summary:"Disconnect remote daemon",allowedFlags:["shutdown"]},mcp:{helpDescription:"Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.",summary:"Start MCP server"},"react-devtools":{usageOverride:"react-devtools [...args]",listUsageOverride:"react-devtools [...args]",helpDescription:"Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis",summary:"Profile React Native performance and component renders",positionalArgs:["args?"],allowsExtraPositionals:!0}},f={...e,...o,...l,...r,...n,...t,...u,...p,...a,...c,...s,...d},h=new Map(m().map(e=>[e.name,{helpDescription:e.description}]));function v(e){if(e)return C(e)}function _(e){let t=C(e);if(!t)throw Error(`Missing command schema for ${e}`);return t}function C(e){let t=Object.hasOwn(g,e)?g[e]:void 0;if(t)return t;let o=h.get(e),n=Object.hasOwn(f,e)?f[e]:void 0;if(o)return n?{...o,...n}:o}function O(e,t){let o=v(e);if(!o?.defaults)return!1;let n=!1;for(let[e,a]of Object.entries(o.defaults))void 0===t[e]&&(t[e]=a,n=!0);return n}export{O as applyCommandDefaults,_ as getCliCommandSchema,v as getCommandSchema};
package/dist/src/221.js CHANGED
@@ -1,6 +1,6 @@
1
- import e from"node:crypto";import t from"node:fs";import r from"node:fs/promises";import n from"node:os";import i from"node:path";import o from"node:net";import{AppError as a}from"./9152.js";import{intersectArea as s,isScrollableType as l}from"./4778.js";import{emitDiagnostic as u}from"./7599.js";import{installAndroidAdbPackage as d}from"./9639.js";let c="android-snapshot-helper",h="com.callstack.agentdevice.snapshothelper",p="com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",f="android-snapshot-helper-v1",w="uiautomator-xml",m={"-r":"replace","-t":"allowTestPackages","-d":"allowDowngrade","-g":"grantPermissions"};async function A(e){let t=await x(e.apkPath);if(t!==e.manifest.sha256)throw new a("COMMAND_FAILED","Android snapshot helper APK checksum mismatch",{apkPath:e.apkPath,expectedSha256:e.manifest.sha256,actualSha256:t})}async function M(e){let t=e.fetch??fetch,o=await t(e.manifestUrl);if(!o.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper manifest",{manifestUrl:e.manifestUrl,status:o.status,statusText:o.statusText});let s=g(JSON.parse((await v(o,65536,"Android snapshot helper manifest")).toString("utf8")));if(!s.apkUrl)throw new a("COMMAND_FAILED","Android snapshot helper manifest does not include apkUrl",{manifestUrl:e.manifestUrl});let l=e.cacheDir??i.join(n.tmpdir(),`agent-device-android-snapshot-helper-${s.version}`),u=!e.cacheDir;await r.mkdir(l,{recursive:!0});let d=s.assetName??`agent-device-android-snapshot-helper-${s.version}.apk`,c=i.join(l,d),h=await t(s.apkUrl);if(!h.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper APK",{apkUrl:s.apkUrl,status:h.status,statusText:h.statusText});await r.writeFile(c,await v(h,0x1400000,"Android snapshot helper APK"));let p={apkPath:c,manifest:s};return await A(p),{...p,cleanup:async()=>{await r.rm(u?l:c,{recursive:u,force:!0})}}}function g(e){var t,r;if(!e||"object"!=typeof e||Array.isArray(e))throw new a("INVALID_ARGS","Android snapshot helper manifest must be an object.");return{name:D(e.name,"name",c),version:y(e.version,"version"),releaseTag:I(e.releaseTag),assetName:I(e.assetName),apkUrl:(t=e.apkUrl,r="apkUrl",null===t?null:y(t,r)),sha256:function(e){let t=y(e,"sha256").trim().toLowerCase();if(64!==t.length||!function(e){for(let t of e){let e=t.charCodeAt(0),r=e>=48&&e<=57,n=e>=97&&e<=102;if(!r&&!n)return!1}return!0}(t))throw new a("INVALID_ARGS","Android snapshot helper manifest sha256 must be a 64-character hex string.");return t}(e.sha256),checksumName:I(e.checksumName),packageName:y(e.packageName,"packageName"),versionCode:C(e.versionCode,"versionCode"),instrumentationRunner:y(e.instrumentationRunner,"instrumentationRunner"),minSdk:C(e.minSdk,"minSdk"),targetSdk:void 0===e.targetSdk?void 0:C(e.targetSdk,"targetSdk"),outputFormat:D(e.outputFormat,"outputFormat",w),statusProtocol:D(e.statusProtocol,"statusProtocol",f),installArgs:N(e.installArgs)}}async function v(e,t,r){let n=e.headers.get("content-length");if(null!==n){let e=Number(n);if(Number.isFinite(e)&&e>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:e,maxBytes:t})}if(!e.body){let n=Buffer.from(await e.arrayBuffer());if(n.length>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:n.length,maxBytes:t});return n}let i=e.body.getReader(),o=[],s=0;try{for(;;){let{done:e,value:n}=await i.read();if(e)break;if((s+=n.byteLength)>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:s,maxBytes:t});o.push(Buffer.from(n))}}finally{i.releaseLock()}return Buffer.concat(o,s)}function N(e){let t=function(e,t){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be a string array.`);return e}(e,"installArgs");if("install"!==t[0])throw new a("INVALID_ARGS",'Android snapshot helper manifest installArgs must start with "install".');if(t.some(e=>e.includes("\0")))throw new a("INVALID_ARGS","Android snapshot helper manifest installArgs must not contain null bytes.");let r=t.slice(1).find(e=>void 0===b(e));if(r)throw new a("INVALID_ARGS",`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}async function x(r){return await new Promise((n,i)=>{let o=e.createHash("sha256"),a=t.createReadStream(r);a.on("error",i),a.on("data",e=>o.update(e)),a.on("end",()=>n(o.digest("hex")))})}function y(e,t){if("string"!=typeof e||0===e.trim().length)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} is required.`);return e}function I(e){return"string"==typeof e&&e.trim().length>0?e:void 0}function C(e,t){if("number"!=typeof e||!Number.isInteger(e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be an integer.`);return e}function D(e,t,r){if(e!==r)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be "${r}".`);return r}function b(e){if(Object.hasOwn(m,e))return m[e]}function*S(e){let t=/<node\b[^>]*>/g,r=t.exec(e);for(;r;)yield _(r[0]),r=t.exec(e)}function _(e){let t,r,n,i,o,a=(t=function(e){let t=new Map,r=e.indexOf(" "),n=e.lastIndexOf(">");if(r<0||n<=r)return t;let i=r;for(;i<n;){let r=function(e,t,r){var n,i;if((t=F(e,t,r))>=r||"/"===(n=e[t])||">"===n)return;let o=t;t=function(e,t,r){for(var n;t<r&&!("="===(n=e[t]??"")||"/"===n||">"===n||L(n));)t+=1;return t}(e,t,r);let a=e.slice(o,t);if(t=F(e,t,r),!a||"="!==e[t])return;t=F(e,t+1,r);let s=e[t];if('"'!==(i=s)&&"'"!==i)return;let l=t+1,u=e.indexOf(s,l);if(!(u<0)&&!(u>=r))return{name:a,value:function(e){let t="",r=0;for(;r<e.length;){let n=e.indexOf("&",r);if(n<0){t+=e.slice(r);break}t+=e.slice(r,n);let i=e.indexOf(";",n+1);if(i<0){t+=e.slice(n);break}t+=function(e){switch(e){case"amp":return"&";case"lt":return"<";case"gt":return">";case"quot":return'"';case"apos":return"'";default:return function(e){if(!e.startsWith("#"))return;let t=e[1]?.toLowerCase()==="x"?16:10,r=16===t?e.slice(2):e.slice(1);if(!r||!function(e,t){for(let r of e){let e=r.charCodeAt(0),n=e>=48&&e<=57;if(10===t){if(!n)return!1;continue}let i=e>=65&&e<=70,o=e>=97&&e<=102;if(!n&&!i&&!o)return!1}return!0}(r,t))return;let n=Number.parseInt(r,t);if(Number.isFinite(n))try{return String.fromCodePoint(n)}catch{return}}(e)}}(e.slice(n+1,i))??e.slice(n,i+1),r=i+1}return t}(e.slice(l,u)),nextCursor:u+1}}(e,i,n);if(!r)break;t.set(r.name,r.value),i=r.nextCursor}return t}(e),r=e=>{let r=O(t,e);if(null!==r)return"true"===r},n=(e,r)=>{let n=(e=>{let r=O(t,e);if(null===r||""===r.trim())return;let n=Number(r);return Number.isFinite(n)?n:void 0})(r);return void 0===n?{}:{[e]:n}},i=(e,t)=>{let n=r(t);return void 0===n?{}:{[e]:n}},{text:O(t,"text"),desc:O(t,"content-desc"),resourceId:O(t,"resource-id"),packageName:O(t,"package"),className:O(t,"class"),bounds:O(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused"),password:r("password"),...i("visibleToUser","visible-to-user"),...n("drawingOrder","drawing-order"),...i("scrollable","scrollable"),...i("canScrollForward","can-scroll-forward"),...i("canScrollBackward","can-scroll-backward"),...n("windowIndex","window-index"),...n("windowType","window-type"),...n("windowLayer","window-layer"),...i("windowActive","window-active"),...i("windowFocused","window-focused"),...void 0===(o=E(O(t,"window-bounds")))?{}:{windowRect:o}}),s=E(a.bounds);return{...a,...s?{rect:s}:{}}}function T(e,t,r){let{sourceNodes:n,...i}=k(P(e),t,r);return i}function k(e,t,r){let n={nodes:[],sourceNodes:[],...void 0!==t?{maxNodes:t}:{},maxDepth:r.depth??1/0,options:r,analysis:function(e){let t=0,r=0,n=[...e.children];for(;n.length>0;){let e=n.pop();t+=1,r=Math.max(r,e.depth),n.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(e),interactiveDescendantMemo:new Map,truncated:!1},i=r.scope?function(e,t){let r=t.toLowerCase(),n=[...e.children],i=0;for(;i<n.length;){let e=n[i++],t=e.label?.toLowerCase()??"",o=e.value?.toLowerCase()??"",a=e.identifier?.toLowerCase()??"";if(t.includes(r)||o.includes(r)||a.includes(r))return e;n.push(...e.children)}return null}(e,r.scope):null;for(let t of i?[i]:e.children)if(function e(t,r,n,i,o=!1,a=!1){if(void 0!==t.maxNodes&&t.nodes.length>=t.maxNodes){t.truncated=!0;return}if(n>t.maxDepth)return;let s=t.options.raw||function(e,t,r,n,i){var o,a,s;if(!1===e.visibleToUser)return!1;let u=function(e){let t=V(e.type),r=!!(e.label&&e.label.trim().length>0),n=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:r&&!B(e.label??""),hasMeaningfulId:n&&!B(e.identifier??""),isStructural:function(e){let t=e.split(".").pop()??e;return t.includes("layout")||"viewgroup"===t||"view"===t}(t),isVisual:"imageview"===t||"imagebutton"===t}}(e);return t.interactiveOnly?function(e,t,r,n,i){var o,a,s,u,d;return!((o=e).rect&&(o.rect.width<=0||o.rect.height<=0))&&(!!(e.hittable||l(t.type)&&n)||(a=t,s=r,u=n,d=i,(!!a.hasMeaningfulText||!!a.hasMeaningfulId)&&!a.isVisual&&(!a.isStructural||!!d)&&(s||u||d)))}(e,u,r,n,i):t.compact?u.hasMeaningfulText||u.hasMeaningfulId||!!e.hittable:!u.isStructural&&!u.isVisual||(o=e,a=u,s=n,!!o.hittable||!!a.hasMeaningfulText||!!a.hasMeaningfulId||s)}(r,t.options,o,function e(t,r){let n=t.interactiveDescendantMemo.get(r);if(void 0!==n)return n;for(let n of r.children)if(!1!==n.visibleToUser&&(n.hittable||e(t,n)))return t.interactiveDescendantMemo.set(r,!0),!0;return t.interactiveDescendantMemo.set(r,!1),!1}(t,r),a)?function(e,t,r,n){let i=e.nodes.length;return e.sourceNodes.push(t),e.nodes.push({index:i,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,enabled:t.enabled,visibleToUser:t.visibleToUser,hittable:t.hittable,depth:r,parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{}}),i}(t,r,n,i):i,u=o||!!r.hittable,d=a||function(e){if(!e)return!1;let t=V(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(r.type);for(let i of r.children)if(e(t,i,n+1,s,u,d),t.truncated)return}(n,t,0),n.truncated)break;let o={nodes:n.nodes,sourceNodes:n.sourceNodes,analysis:n.analysis};return n.truncated?{...o,truncated:!0}:o}function F(e,t,r){for(;t<r&&L(e[t]??"");)t+=1;return t}function L(e){return" "===e||"\n"===e||"\r"===e||" "===e}function O(e,t){return e.get(t)??null}function E(e){if(!e)return;let t=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),n=Number(t[2]);return{x:r,y:n,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-n)}}function P(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,depth:-1,children:[]},r=[t],n=/<node\b[^>]*>|<\/node>/g,i=n.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=n.exec(e);continue}let o=_(t),a=r[r.length-1],s={type:o.className,label:o.text||o.desc,value:o.text,identifier:o.resourceId,packageName:o.packageName,rect:o.rect,enabled:o.enabled,visibleToUser:o.visibleToUser,drawingOrder:o.drawingOrder,hittable:o.clickable??o.focusable,scrollable:o.scrollable,canScrollForward:o.canScrollForward,canScrollBackward:o.canScrollBackward,windowIndex:o.windowIndex,windowType:o.windowType,windowLayer:o.windowLayer,windowActive:o.windowActive,windowFocused:o.windowFocused,windowRect:o.windowRect,depth:a.depth+1,parentIndex:void 0,children:[]};a.children.push(s),t.endsWith("/>")||r.push(s),i=n.exec(e)}return function e(t){let r=0;for(let n of t.children)!1!==n.visibleToUser&&(e(n),t.children[r]=n,r+=1);r<t.children.length&&(t.children.length=r)}(t),function(e){let t,r=e.children.filter(U);if(r.length<2)return;let n=r.filter(e=>$(e)&&H(e));if(0===n.length)return;let i=(t=n.map(e=>e.windowLayer).filter(e=>void 0!==e)).length>0?Math.max(...t):void 0;e.children=e.children.filter(e=>!$(e)||!!H(e)&&(void 0===i||e.windowLayer===i))}(t),function e(t,r){for(let n of t.children)e(n,r);if(t.children.length<2)return;let n=t.children,i=n.filter(e=>{var t,n;return t=e,n=r,!1!==t.visibleToUser&&void 0!==t.drawingOrder&&R(t)&&function e(t,r){let n=r.agentVisibleContentMemo.get(t);if(void 0!==n)return n;let i=function(t,r){if(!1===t.visibleToUser)return!1;if(t.hittable)return!0;let n=t.label?.trim()??"";if(n&&!B(n))return!0;let i=t.identifier?.trim()??"";return!(!i||B(i))||t.children.some(t=>e(t,r))}(t,r);return r.agentVisibleContentMemo.set(t,i),i}(t,n)});0!==i.length&&(t.children=n.filter(e=>!function(e,t){if(!1===e.visibleToUser||void 0===e.drawingOrder||!R(e))return!1;for(let r of t)if(r!==e&&!(r.drawingOrder<=e.drawingOrder)&&function(e,t){let r=t.width*t.height;return r<=0?0:s(e,t)/r}(r.rect,e.rect)>=.9)return!0;return!1}(e,i)))}(t,{agentVisibleContentMemo:new WeakMap}),function(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),function(e){if(!e.scrollable||!l(e.type)||`${e.type??""}`.toLowerCase().includes("horizontalscrollview"))return!1;let t=function(e){if(!e.rect||0===e.children.length)return null;let t=e.children.map(e=>e.rect).filter(e=>void 0!==e);if(0===t.length)return null;let r=Math.min(...t.map(e=>e.x)),n=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),o=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,n-r-e.rect.width),vertical:Math.max(0,o-i-e.rect.height)}}(e);return!t||!(t.horizontal>t.vertical)||!(t.horizontal>16)}(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}(t),t}function R(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function U(e){return void 0!==e.windowIndex||void 0!==e.windowType}function $(e){return 1===e.windowType}function H(e){return!0===e.windowActive||!0===e.windowFocused}function V(e){return e?e.toLowerCase():""}function B(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function K(e){let t=G(e),r=await e.adb(W(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs}),{output:n,cleanupDone:i}=await X(e,t,r);if(t.outputPath&&!i&&await J(e.adb,t.outputPath),0!==r.exitCode)throw new a("COMMAND_FAILED","Android snapshot helper failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode,helper:n.metadata});return n}function G(e){let t=Q(e.timeoutMs,8e3),r=Q(e.packageName,h);return{waitForIdleTimeoutMs:Q(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:Q(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:Q(e.commandTimeoutMs,t+5e3),maxDepth:Q(e.maxDepth,128),maxNodes:Q(e.maxNodes,5e3),packageName:r,runner:Q(e.instrumentationRunner,`${r}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...void 0!==e.emitChunks?{emitChunks:e.emitChunks}:{}}}function Q(e,t){return void 0===e?t:e}function W(e){return["shell","am","instrument","-w","-e","waitForIdleTimeoutMs",String(e.waitForIdleTimeoutMs),"-e","waitForIdleQuietMs",String(e.waitForIdleQuietMs),"-e","timeoutMs",String(e.timeoutMs),"-e","maxDepth",String(e.maxDepth),"-e","maxNodes",String(e.maxNodes),...e.outputPath?["-e","outputPath",e.outputPath]:[],...void 0!==e.emitChunks?["-e","emitChunks",String(e.emitChunks)]:[],e.runner]}async function X(e,t,r){try{return{output:Y(`${r.stdout}
1
+ import e from"node:crypto";import t from"node:fs";import r from"node:fs/promises";import n from"node:os";import i from"node:path";import o from"node:net";import{AppError as a}from"./9152.js";import{intersectArea as s,isScrollableType as l}from"./4778.js";import{emitDiagnostic as u}from"./7599.js";import{installAndroidAdbPackage as d}from"./9639.js";let c="android-snapshot-helper",h="com.callstack.agentdevice.snapshothelper",p="com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",f="android-snapshot-helper-v1",w="uiautomator-xml",m={"-r":"replace","-t":"allowTestPackages","-d":"allowDowngrade","-g":"grantPermissions"};async function A(e){let t=await x(e.apkPath);if(t!==e.manifest.sha256)throw new a("COMMAND_FAILED","Android snapshot helper APK checksum mismatch",{apkPath:e.apkPath,expectedSha256:e.manifest.sha256,actualSha256:t})}async function M(e){let t=e.fetch??fetch,o=await t(e.manifestUrl);if(!o.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper manifest",{manifestUrl:e.manifestUrl,status:o.status,statusText:o.statusText});let s=g(JSON.parse((await v(o,65536,"Android snapshot helper manifest")).toString("utf8")));if(!s.apkUrl)throw new a("COMMAND_FAILED","Android snapshot helper manifest does not include apkUrl",{manifestUrl:e.manifestUrl});let l=e.cacheDir??i.join(n.tmpdir(),`agent-device-android-snapshot-helper-${s.version}`),u=!e.cacheDir;await r.mkdir(l,{recursive:!0});let d=s.assetName??`agent-device-android-snapshot-helper-${s.version}.apk`,c=i.join(l,d),h=await t(s.apkUrl);if(!h.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper APK",{apkUrl:s.apkUrl,status:h.status,statusText:h.statusText});await r.writeFile(c,await v(h,0x1400000,"Android snapshot helper APK"));let p={apkPath:c,manifest:s};return await A(p),{...p,cleanup:async()=>{await r.rm(u?l:c,{recursive:u,force:!0})}}}function g(e){var t,r;if(!e||"object"!=typeof e||Array.isArray(e))throw new a("INVALID_ARGS","Android snapshot helper manifest must be an object.");return{name:D(e.name,"name",c),version:y(e.version,"version"),releaseTag:I(e.releaseTag),assetName:I(e.assetName),apkUrl:(t=e.apkUrl,r="apkUrl",null===t?null:y(t,r)),sha256:function(e){let t=y(e,"sha256").trim().toLowerCase();if(64!==t.length||!function(e){for(let t of e){let e=t.charCodeAt(0),r=e>=48&&e<=57,n=e>=97&&e<=102;if(!r&&!n)return!1}return!0}(t))throw new a("INVALID_ARGS","Android snapshot helper manifest sha256 must be a 64-character hex string.");return t}(e.sha256),checksumName:I(e.checksumName),packageName:y(e.packageName,"packageName"),versionCode:C(e.versionCode,"versionCode"),instrumentationRunner:y(e.instrumentationRunner,"instrumentationRunner"),minSdk:C(e.minSdk,"minSdk"),targetSdk:void 0===e.targetSdk?void 0:C(e.targetSdk,"targetSdk"),outputFormat:D(e.outputFormat,"outputFormat",w),statusProtocol:D(e.statusProtocol,"statusProtocol",f),installArgs:N(e.installArgs)}}async function v(e,t,r){let n=e.headers.get("content-length");if(null!==n){let e=Number(n);if(Number.isFinite(e)&&e>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:e,maxBytes:t})}if(!e.body){let n=Buffer.from(await e.arrayBuffer());if(n.length>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:n.length,maxBytes:t});return n}let i=e.body.getReader(),o=[],s=0;try{for(;;){let{done:e,value:n}=await i.read();if(e)break;if((s+=n.byteLength)>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:s,maxBytes:t});o.push(Buffer.from(n))}}finally{i.releaseLock()}return Buffer.concat(o,s)}function N(e){let t=function(e,t){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be a string array.`);return e}(e,"installArgs");if("install"!==t[0])throw new a("INVALID_ARGS",'Android snapshot helper manifest installArgs must start with "install".');if(t.some(e=>e.includes("\0")))throw new a("INVALID_ARGS","Android snapshot helper manifest installArgs must not contain null bytes.");let r=t.slice(1).find(e=>void 0===b(e));if(r)throw new a("INVALID_ARGS",`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}async function x(r){return await new Promise((n,i)=>{let o=e.createHash("sha256"),a=t.createReadStream(r);a.on("error",i),a.on("data",e=>o.update(e)),a.on("end",()=>n(o.digest("hex")))})}function y(e,t){if("string"!=typeof e||0===e.trim().length)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} is required.`);return e}function I(e){return"string"==typeof e&&e.trim().length>0?e:void 0}function C(e,t){if("number"!=typeof e||!Number.isInteger(e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be an integer.`);return e}function D(e,t,r){if(e!==r)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be "${r}".`);return r}function b(e){if(Object.hasOwn(m,e))return m[e]}function*S(e){let t=/<node\b[^>]*>/g,r=t.exec(e);for(;r;)yield _(r[0]),r=t.exec(e)}function _(e){let t,r,n,i,o,a=(t=function(e){let t=new Map,r=e.indexOf(" "),n=e.lastIndexOf(">");if(r<0||n<=r)return t;let i=r;for(;i<n;){let r=function(e,t,r){var n,i;if((t=F(e,t,r))>=r||"/"===(n=e[t])||">"===n)return;let o=t;t=function(e,t,r){for(var n;t<r&&!("="===(n=e[t]??"")||"/"===n||">"===n||L(n));)t+=1;return t}(e,t,r);let a=e.slice(o,t);if(t=F(e,t,r),!a||"="!==e[t])return;t=F(e,t+1,r);let s=e[t];if('"'!==(i=s)&&"'"!==i)return;let l=t+1,u=e.indexOf(s,l);if(!(u<0)&&!(u>=r))return{name:a,value:function(e){let t="",r=0;for(;r<e.length;){let n=e.indexOf("&",r);if(n<0){t+=e.slice(r);break}t+=e.slice(r,n);let i=e.indexOf(";",n+1);if(i<0){t+=e.slice(n);break}t+=function(e){switch(e){case"amp":return"&";case"lt":return"<";case"gt":return">";case"quot":return'"';case"apos":return"'";default:return function(e){if(!e.startsWith("#"))return;let t=e[1]?.toLowerCase()==="x"?16:10,r=16===t?e.slice(2):e.slice(1);if(!r||!function(e,t){for(let r of e){let e=r.charCodeAt(0),n=e>=48&&e<=57;if(10===t){if(!n)return!1;continue}let i=e>=65&&e<=70,o=e>=97&&e<=102;if(!n&&!i&&!o)return!1}return!0}(r,t))return;let n=Number.parseInt(r,t);if(Number.isFinite(n))try{return String.fromCodePoint(n)}catch{return}}(e)}}(e.slice(n+1,i))??e.slice(n,i+1),r=i+1}return t}(e.slice(l,u)),nextCursor:u+1}}(e,i,n);if(!r)break;t.set(r.name,r.value),i=r.nextCursor}return t}(e),r=e=>{let r=O(t,e);if(null!==r)return"true"===r},n=(e,r)=>{let n=(e=>{let r=O(t,e);if(null===r||""===r.trim())return;let n=Number(r);return Number.isFinite(n)?n:void 0})(r);return void 0===n?{}:{[e]:n}},i=(e,t)=>{let n=r(t);return void 0===n?{}:{[e]:n}},{text:O(t,"text"),desc:O(t,"content-desc"),resourceId:O(t,"resource-id"),packageName:O(t,"package"),className:O(t,"class"),bounds:O(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused"),password:r("password"),...i("visibleToUser","visible-to-user"),...n("drawingOrder","drawing-order"),...i("scrollable","scrollable"),...i("canScrollForward","can-scroll-forward"),...i("canScrollBackward","can-scroll-backward"),...n("windowIndex","window-index"),...n("windowType","window-type"),...n("windowLayer","window-layer"),...i("windowActive","window-active"),...i("windowFocused","window-focused"),...void 0===(o=E(O(t,"window-bounds")))?{}:{windowRect:o}}),s=E(a.bounds);return{...a,...s?{rect:s}:{}}}function T(e,t,r){let{sourceNodes:n,...i}=k(P(e),t,r);return i}function k(e,t,r){let n={nodes:[],sourceNodes:[],...void 0!==t?{maxNodes:t}:{},maxDepth:r.depth??1/0,options:r,analysis:function(e){let t=0,r=0,n=[...e.children];for(;n.length>0;){let e=n.pop();t+=1,r=Math.max(r,e.depth),n.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(e),interactiveDescendantMemo:new Map,truncated:!1},i=r.scope?function(e,t){let r=t.toLowerCase(),n=[...e.children],i=0;for(;i<n.length;){let e=n[i++],t=e.label?.toLowerCase()??"",o=e.value?.toLowerCase()??"",a=e.identifier?.toLowerCase()??"";if(t.includes(r)||o.includes(r)||a.includes(r))return e;n.push(...e.children)}return null}(e,r.scope):null;for(let t of i?[i]:e.children)if(function e(t,r,n,i,o=!1,a=!1){if(void 0!==t.maxNodes&&t.nodes.length>=t.maxNodes){t.truncated=!0;return}if(n>t.maxDepth)return;let s=t.options.raw||function(e,t,r,n,i){var o,a,s;if(!1===e.visibleToUser)return!1;let u=function(e){let t=V(e.type),r=!!(e.label&&e.label.trim().length>0),n=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:r&&!B(e.label??""),hasMeaningfulId:n&&!B(e.identifier??""),isStructural:function(e){let t=e.split(".").pop()??e;return t.includes("layout")||"viewgroup"===t||"view"===t}(t),isVisual:"imageview"===t||"imagebutton"===t}}(e);return t.interactiveOnly?function(e,t,r,n,i){var o,a,s,u,d;return!((o=e).rect&&(o.rect.width<=0||o.rect.height<=0))&&(!!(e.hittable||l(t.type)&&n)||(a=t,s=r,u=n,d=i,(!!a.hasMeaningfulText||!!a.hasMeaningfulId)&&!a.isVisual&&(!a.isStructural||!!d)&&(s||u||d)))}(e,u,r,n,i):!u.isStructural&&!u.isVisual||(o=e,a=u,s=n,!!o.hittable||!!a.hasMeaningfulText||!!a.hasMeaningfulId||s)}(r,t.options,o,function e(t,r){let n=t.interactiveDescendantMemo.get(r);if(void 0!==n)return n;for(let n of r.children)if(!1!==n.visibleToUser&&(n.hittable||e(t,n)))return t.interactiveDescendantMemo.set(r,!0),!0;return t.interactiveDescendantMemo.set(r,!1),!1}(t,r),a)?function(e,t,r,n){let i=e.nodes.length;return e.sourceNodes.push(t),e.nodes.push({index:i,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,enabled:t.enabled,visibleToUser:t.visibleToUser,hittable:t.hittable,depth:r,parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{}}),i}(t,r,n,i):i,u=o||!!r.hittable,d=a||function(e){if(!e)return!1;let t=V(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(r.type);for(let i of r.children)if(e(t,i,n+1,s,u,d),t.truncated)return}(n,t,0),n.truncated)break;let o={nodes:n.nodes,sourceNodes:n.sourceNodes,analysis:n.analysis};return n.truncated?{...o,truncated:!0}:o}function F(e,t,r){for(;t<r&&L(e[t]??"");)t+=1;return t}function L(e){return" "===e||"\n"===e||"\r"===e||" "===e}function O(e,t){return e.get(t)??null}function E(e){if(!e)return;let t=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),n=Number(t[2]);return{x:r,y:n,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-n)}}function P(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,depth:-1,children:[]},r=[t],n=/<node\b[^>]*>|<\/node>/g,i=n.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=n.exec(e);continue}let o=_(t),a=r[r.length-1],s={type:o.className,label:o.text||o.desc,value:o.text,identifier:o.resourceId,packageName:o.packageName,rect:o.rect,enabled:o.enabled,visibleToUser:o.visibleToUser,drawingOrder:o.drawingOrder,hittable:o.clickable??o.focusable,scrollable:o.scrollable,canScrollForward:o.canScrollForward,canScrollBackward:o.canScrollBackward,windowIndex:o.windowIndex,windowType:o.windowType,windowLayer:o.windowLayer,windowActive:o.windowActive,windowFocused:o.windowFocused,windowRect:o.windowRect,depth:a.depth+1,parentIndex:void 0,children:[]};a.children.push(s),t.endsWith("/>")||r.push(s),i=n.exec(e)}return function e(t){let r=0;for(let n of t.children)!1!==n.visibleToUser&&(e(n),t.children[r]=n,r+=1);r<t.children.length&&(t.children.length=r)}(t),function(e){let t,r=e.children.filter(U);if(r.length<2)return;let n=r.filter(e=>$(e)&&H(e));if(0===n.length)return;let i=(t=n.map(e=>e.windowLayer).filter(e=>void 0!==e)).length>0?Math.max(...t):void 0;e.children=e.children.filter(e=>!$(e)||!!H(e)&&(void 0===i||e.windowLayer===i))}(t),function e(t,r){for(let n of t.children)e(n,r);if(t.children.length<2)return;let n=t.children,i=n.filter(e=>{var t,n;return t=e,n=r,!1!==t.visibleToUser&&void 0!==t.drawingOrder&&R(t)&&function e(t,r){let n=r.agentVisibleContentMemo.get(t);if(void 0!==n)return n;let i=function(t,r){if(!1===t.visibleToUser)return!1;if(t.hittable)return!0;let n=t.label?.trim()??"";if(n&&!B(n))return!0;let i=t.identifier?.trim()??"";return!(!i||B(i))||t.children.some(t=>e(t,r))}(t,r);return r.agentVisibleContentMemo.set(t,i),i}(t,n)});0!==i.length&&(t.children=n.filter(e=>!function(e,t){if(!1===e.visibleToUser||void 0===e.drawingOrder||!R(e))return!1;for(let r of t)if(r!==e&&!(r.drawingOrder<=e.drawingOrder)&&function(e,t){let r=t.width*t.height;return r<=0?0:s(e,t)/r}(r.rect,e.rect)>=.9)return!0;return!1}(e,i)))}(t,{agentVisibleContentMemo:new WeakMap}),function(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),function(e){if(!e.scrollable||!l(e.type)||`${e.type??""}`.toLowerCase().includes("horizontalscrollview"))return!1;let t=function(e){if(!e.rect||0===e.children.length)return null;let t=e.children.map(e=>e.rect).filter(e=>void 0!==e);if(0===t.length)return null;let r=Math.min(...t.map(e=>e.x)),n=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),o=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,n-r-e.rect.width),vertical:Math.max(0,o-i-e.rect.height)}}(e);return!t||!(t.horizontal>t.vertical)||!(t.horizontal>16)}(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}(t),t}function R(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function U(e){return void 0!==e.windowIndex||void 0!==e.windowType}function $(e){return 1===e.windowType}function H(e){return!0===e.windowActive||!0===e.windowFocused}function V(e){return e?e.toLowerCase():""}function B(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function K(e){let t=G(e),r=await e.adb(W(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs}),{output:n,cleanupDone:i}=await X(e,t,r);if(t.outputPath&&!i&&await J(e.adb,t.outputPath),0!==r.exitCode)throw new a("COMMAND_FAILED","Android snapshot helper failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode,helper:n.metadata});return n}function G(e){let t=Q(e.timeoutMs,8e3),r=Q(e.packageName,h);return{waitForIdleTimeoutMs:Q(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:Q(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:Q(e.commandTimeoutMs,t+5e3),maxDepth:Q(e.maxDepth,128),maxNodes:Q(e.maxNodes,5e3),packageName:r,runner:Q(e.instrumentationRunner,`${r}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...void 0!==e.emitChunks?{emitChunks:e.emitChunks}:{}}}function Q(e,t){return void 0===e?t:e}function W(e){return["shell","am","instrument","-w","-e","waitForIdleTimeoutMs",String(e.waitForIdleTimeoutMs),"-e","waitForIdleQuietMs",String(e.waitForIdleQuietMs),"-e","timeoutMs",String(e.timeoutMs),"-e","maxDepth",String(e.maxDepth),"-e","maxNodes",String(e.maxNodes),...e.outputPath?["-e","outputPath",e.outputPath]:[],...void 0!==e.emitChunks?["-e","emitChunks",String(e.emitChunks)]:[],e.runner]}async function X(e,t,r){try{return{output:Y(`${r.stdout}
2
2
  ${r.stderr}`),cleanupDone:!1}}catch(n){return await z(e,t,r,n)}}async function z(e,t,r,n){if(n instanceof a&&0!==r.exitCode&&n.details?.helper)throw n;let i=await j(e,t,r);if(i)return{output:i,cleanupDone:!0};throw new a("COMMAND_FAILED",0===r.exitCode?"Android snapshot helper output could not be parsed":"Android snapshot helper failed before returning parseable output",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode},n)}async function j(e,t,r){if(0===r.exitCode&&t.outputPath){var n;return await q(e.adb,t.outputPath,function(e){try{let t=er(e);return et(ee(t.results))}catch{return null}}(`${r.stdout}
3
- ${r.stderr}`)??{outputFormat:w,waitForIdleTimeoutMs:(n=t).waitForIdleTimeoutMs,waitForIdleQuietMs:n.waitForIdleQuietMs,timeoutMs:n.timeoutMs,maxDepth:n.maxDepth,maxNodes:n.maxNodes,transport:"instrumentation"})}}async function q(e,t,r){let n;try{var i;n=await e((i=t,["shell","sh","-c",'cat "$1"; status=$?; rm -f "$1"; exit "$status"',"agent-device-snapshot-helper-output",i]),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(0!==n.exitCode)return;let o=n.stdout.trim();if(o.includes("<hierarchy")&&o.includes("</hierarchy>"))return{xml:o,metadata:r}}async function J(e,t){try{await e(["shell","rm","-f",t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Y(e){let t=er(e),r=ee(t.results);return{xml:function(e,t){if(0===e.length)throw new a("COMMAND_FAILED","Android snapshot helper did not return XML chunks",{helper:t});let r=function(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{expectedChunks:t,actualChunks:e.length});return t}(e),n=Buffer.concat(function(e,t){let r=[];for(let n=0;n<t;n+=1){let i=e.get(n);if(void 0===i)throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{missingChunkIndex:n,expectedChunks:t});r.push(Buffer.from(i,"base64"))}return r}(function(e,t){let r=new Map;for(let n of e){if(void 0===n.index||n.index<0||n.index>=t)throw new a("COMMAND_FAILED","Android snapshot helper returned invalid chunk index",{chunkIndex:n.index,expectedChunks:t});if(r.has(n.index))throw new a("COMMAND_FAILED","Android snapshot helper returned duplicate XML chunks",{chunkIndex:n.index});r.set(n.index,n.payloadBase64)}return r}(e,r),r)).toString("utf8");if(!n.includes("<hierarchy")||!n.includes("</hierarchy>"))throw new a("COMMAND_FAILED","Android snapshot helper output did not contain XML",{xml:n});return n}(function(e){let t=[];for(let r of e){if(r.agentDeviceProtocol!==f||r.outputFormat!==w)continue;let{payloadBase64:e}=r;void 0!==e&&t.push({index:el(r.chunkIndex),count:el(r.chunkCount),payloadBase64:e})}return t}(t.status),r),metadata:{...et(r),transport:"instrumentation"}}}function Z(e,t={outputFormat:w},r={},n){return{...T(e,n,r),metadata:t}}function ee(e){let t=e.find(e=>e.agentDeviceProtocol===f);if(!t)throw new a("COMMAND_FAILED","Android snapshot helper did not return a final result");if("true"!==t.ok){var r;throw new a("COMMAND_FAILED",(r=t).message&&"null"!==r.message?r.message:r.errorType||"Android snapshot helper returned an error",{errorType:t.errorType,helper:t})}return t}function et(e){var t;return{helperApiVersion:e.helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:el(e.waitForIdleTimeoutMs),waitForIdleQuietMs:el(e.waitForIdleQuietMs),timeoutMs:el(e.timeoutMs),maxDepth:el(e.maxDepth),maxNodes:el(e.maxNodes),rootPresent:eu(e.rootPresent),captureMode:"interactive-windows"===(t=e.captureMode)||"active-window"===t?t:void 0,windowCount:el(e.windowCount),nodeCount:el(e.nodeCount),truncated:eu(e.truncated),elapsedMs:el(e.elapsedMs)}}function er(e){var t;let r={status:[],results:[],currentStatus:null,currentResult:null};for(let t of e.split(/\r?\n/))!function(e,t){if(e.startsWith("INSTRUMENTATION_STATUS: ")){t.currentStatus??={},eo(e.slice(24),t.currentStatus);return}if(e.startsWith("INSTRUMENTATION_STATUS_CODE: "))return en(t);if(e.startsWith("INSTRUMENTATION_RESULT: ")){t.currentResult??={},eo(e.slice(24),t.currentResult);return}e.startsWith("INSTRUMENTATION_CODE: ")&&ei(t)}(t,r);return en(t=r),ei(t),{status:r.status,results:r.results}}function en(e){e.currentStatus&&(e.status.push(e.currentStatus),e.currentStatus=null)}function ei(e){e.currentResult&&(e.results.push(e.currentResult),e.currentResult=null)}function eo(e,t){let r=e.indexOf("=");r<0||(t[e.slice(0,r)]=e.slice(r+1))}function ea(e){if(void 0===e)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function es(e){return"true"===e||"false"!==e&&void 0}let el=ea,eu=es,ed=new Map,ec=new Map;async function eh(e){var t,r,n;let i;if(!(void 0===(i=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION)||!/^(0|false|no|off)$/i.test(i))||!e.adbProvider?.spawn)return;let o=G(e),a=e.deviceKey??"android:default",s=(t=a,r=o,n=e,JSON.stringify({deviceKey:t,packageName:r.packageName,runner:r.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,waitForIdleTimeoutMs:r.waitForIdleTimeoutMs,waitForIdleQuietMs:r.waitForIdleQuietMs,timeoutMs:r.timeoutMs,maxDepth:r.maxDepth,maxNodes:r.maxNodes}));if(ec.get(a)===s)return;let l=ed.get(a);if(l&&l.identity!==s&&(await ep(a),l=void 0),!l)try{l=await ef({deviceKey:a,identity:s,options:e,resolved:o})}catch(e){ec.set(a,s),u({level:"warn",phase:"android_snapshot_helper_session_disabled",data:{deviceKey:a,reason:e instanceof Error?e.message:String(e)}});return}try{let e=l.capturedCount>0,t=await em(l,o);return l.capturedCount+=1,{xml:t.xml,metadata:{...t.metadata,transport:"persistent-session",sessionReused:e}}}catch(e){throw await ep(a),e}}async function ep(e){let t=ed.get(e);if(t){ed.delete(e);try{await eA(t,`quit ${Date.now()}`,1e3)}catch{}try{await t.process.kill("SIGTERM")}catch{}await ew(t.process,2e3);try{await eM(t)}catch{}u({phase:"android_snapshot_helper_session_stop",data:{deviceKey:e,port:t.port,capturedCount:t.capturedCount,lifetimeMs:Date.now()-t.startedAtMs}})}}async function ef(e){let t=await new Promise((e,t)=>{let r=o.createServer();r.unref(),r.on("error",t),r.listen(0,"127.0.0.1",()=>{let n=r.address();if(!n||"string"==typeof n)return void r.close(()=>t(Error("Failed to allocate a local TCP port")));let i=n.port;r.close(()=>e(i))})});await e.options.adb(["forward",`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:5e3});let r=W({...e.resolved,outputPath:void 0,emitChunks:!1}),n=r[r.length-1];if(!n)throw new a("INVALID_ARGS","Android snapshot helper runner was not resolved");let i=[...r.slice(0,-1),"-e","sessionPort",String(t),n],s=e.options.adbProvider.spawn(i,{allowFailure:!0,captureOutput:!1}),l={identity:e.identity,deviceKey:e.deviceKey,port:t,adb:e.options.adb,process:s,startedAtMs:Date.now(),capturedCount:0};try{var d;return await (d=s,new Promise((e,t)=>{let r="",n=setTimeout(()=>{t(new a("COMMAND_FAILED","Android snapshot helper session did not become ready",{output:r,timeoutMs:1e4}))},1e4),i=t=>{(r+=t.toString()).includes(`agentDeviceProtocol=${f}`)&&r.includes("sessionReady=true")&&(clearTimeout(n),e())};d.stdout?.on("data",i),d.stderr?.on("data",i),d.once("exit",(e,i)=>{clearTimeout(n),t(new a("COMMAND_FAILED","Android snapshot helper session exited before ready",{output:r,exitCode:e,signal:i}))}),d.on("error",e=>{clearTimeout(n),t(e)})})),ed.set(e.deviceKey,l),u({phase:"android_snapshot_helper_session_ready",data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),l}catch(e){await eM(l);try{s.kill("SIGTERM")}catch{}throw await ew(s,2e3),e}}function ew(e,t){return new Promise(r=>{let n=setTimeout(r,t);e.once("close",()=>{clearTimeout(n),r()}),e.once("exit",()=>{clearTimeout(n),r()})})}async function em(e,t){let r=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`,n=Math.max(t.timeoutMs+2e3,3e3);return function(e,t){var r;let{headers:n,xml:i}=function(e){let t=e.indexOf("\n\n");if(t<0)throw new a("COMMAND_FAILED","Android snapshot helper session returned malformed output",{response:e});return{headers:function(e){let t={};for(let r of e.split(/\r?\n/)){let e=r.indexOf("=");e<0||(t[r.slice(0,e)]=r.slice(e+1))}return t}(e.slice(0,t)),xml:e.slice(t+2)}}(e);return function(e,t){if(e.agentDeviceProtocol!==f)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong protocol",{headers:e});if(e.outputFormat!==w)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong output format",{headers:e});if(e.requestId!==t)throw new a("COMMAND_FAILED","Android snapshot helper session returned stale output",{headers:e,requestId:t});if("true"!==e.ok)throw new a("COMMAND_FAILED",e.message||e.errorType||"Android snapshot helper session returned an error",{helper:e})}(n,t),function(e,t){let r=ea(e.byteLength);if(void 0!==r&&Buffer.byteLength(t,"utf8")!==r)throw new a("COMMAND_FAILED","Android snapshot helper session returned truncated XML",{headers:e,actualByteLength:Buffer.byteLength(t,"utf8")});if(!t.includes("<hierarchy")||!t.includes("</hierarchy>"))throw new a("COMMAND_FAILED","Android snapshot helper session did not return XML",{headers:e,xml:t})}(n,i),{xml:i,metadata:{helperApiVersion:(r=n).helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:ea(r.waitForIdleTimeoutMs),waitForIdleQuietMs:ea(r.waitForIdleQuietMs),timeoutMs:ea(r.timeoutMs),maxDepth:ea(r.maxDepth),maxNodes:ea(r.maxNodes),rootPresent:es(r.rootPresent),captureMode:"interactive-windows"===r.captureMode||"active-window"===r.captureMode?r.captureMode:void 0,windowCount:ea(r.windowCount),nodeCount:ea(r.nodeCount),truncated:es(r.truncated),elapsedMs:ea(r.elapsedMs)}}}(await eA(e,`snapshot ${r}`,n),r)}function eA(e,t,r){return new Promise((n,i)=>{let s=o.connect({host:"127.0.0.1",port:e.port}),l=[],u=setTimeout(()=>{s.destroy(),i(new a("COMMAND_FAILED","Android snapshot helper session request timed out",{command:t,timeoutMs:r,port:e.port}))},r);s.on("connect",()=>{s.write(`${t}
3
+ ${r.stderr}`)??{outputFormat:w,waitForIdleTimeoutMs:(n=t).waitForIdleTimeoutMs,waitForIdleQuietMs:n.waitForIdleQuietMs,timeoutMs:n.timeoutMs,maxDepth:n.maxDepth,maxNodes:n.maxNodes,transport:"instrumentation"})}}async function q(e,t,r){let n;try{var i;n=await e((i=t,["shell","sh","-c",'cat "$1"; status=$?; rm -f "$1"; exit "$status"',"agent-device-snapshot-helper-output",i]),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(0!==n.exitCode)return;let o=n.stdout.trim();if(o.includes("<hierarchy")&&o.includes("</hierarchy>"))return{xml:o,metadata:r}}async function J(e,t){try{await e(["shell","rm","-f",t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Y(e){let t=er(e),r=ee(t.results);return{xml:function(e,t){if(0===e.length)throw new a("COMMAND_FAILED","Android snapshot helper did not return XML chunks",{helper:t});let r=function(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{expectedChunks:t,actualChunks:e.length});return t}(e),n=Buffer.concat(function(e,t){let r=[];for(let n=0;n<t;n+=1){let i=e.get(n);if(void 0===i)throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{missingChunkIndex:n,expectedChunks:t});r.push(Buffer.from(i,"base64"))}return r}(function(e,t){let r=new Map;for(let n of e){if(void 0===n.index||n.index<0||n.index>=t)throw new a("COMMAND_FAILED","Android snapshot helper returned invalid chunk index",{chunkIndex:n.index,expectedChunks:t});if(r.has(n.index))throw new a("COMMAND_FAILED","Android snapshot helper returned duplicate XML chunks",{chunkIndex:n.index});r.set(n.index,n.payloadBase64)}return r}(e,r),r)).toString("utf8");if(!n.includes("<hierarchy")||!n.includes("</hierarchy>"))throw new a("COMMAND_FAILED","Android snapshot helper output did not contain XML",{xml:n});return n}(function(e){let t=[];for(let r of e){if(r.agentDeviceProtocol!==f||r.outputFormat!==w)continue;let{payloadBase64:e}=r;void 0!==e&&t.push({index:el(r.chunkIndex),count:el(r.chunkCount),payloadBase64:e})}return t}(t.status),r),metadata:{...et(r),transport:"instrumentation"}}}function Z(e,t={outputFormat:w},r={},n){return{...T(e,n,r),metadata:t}}function ee(e){let t=e.find(e=>e.agentDeviceProtocol===f);if(!t)throw new a("COMMAND_FAILED","Android snapshot helper did not return a final result");if("true"!==t.ok){var r;throw new a("COMMAND_FAILED",(r=t).message&&"null"!==r.message?r.message:r.errorType||"Android snapshot helper returned an error",{errorType:t.errorType,helper:t})}return t}function et(e){var t;return{helperApiVersion:e.helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:el(e.waitForIdleTimeoutMs),waitForIdleQuietMs:el(e.waitForIdleQuietMs),timeoutMs:el(e.timeoutMs),maxDepth:el(e.maxDepth),maxNodes:el(e.maxNodes),rootPresent:eu(e.rootPresent),captureMode:"interactive-windows"===(t=e.captureMode)||"active-window"===t?t:void 0,windowCount:el(e.windowCount),nodeCount:el(e.nodeCount),truncated:eu(e.truncated),elapsedMs:el(e.elapsedMs)}}function er(e){var t;let r={status:[],results:[],currentStatus:null,currentResult:null};for(let t of e.split(/\r?\n/))!function(e,t){if(e.startsWith("INSTRUMENTATION_STATUS: ")){t.currentStatus??={},eo(e.slice(24),t.currentStatus);return}if(e.startsWith("INSTRUMENTATION_STATUS_CODE: "))return en(t);if(e.startsWith("INSTRUMENTATION_RESULT: ")){t.currentResult??={},eo(e.slice(24),t.currentResult);return}e.startsWith("INSTRUMENTATION_CODE: ")&&ei(t)}(t,r);return en(t=r),ei(t),{status:r.status,results:r.results}}function en(e){e.currentStatus&&(e.status.push(e.currentStatus),e.currentStatus=null)}function ei(e){e.currentResult&&(e.results.push(e.currentResult),e.currentResult=null)}function eo(e,t){let r=e.indexOf("=");r<0||(t[e.slice(0,r)]=e.slice(r+1))}function ea(e){if(void 0===e)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function es(e){return"true"===e||"false"!==e&&void 0}let el=ea,eu=es,ed=new Map,ec=new Map;async function eh(e){var t,r,n;let i;if(!(void 0===(i=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION)||!/^(0|false|no|off)$/i.test(i))||!e.adbProvider?.spawn)return;let o=G(e),a=e.deviceKey??"android:default",s=(t=a,r=o,n=e,JSON.stringify({deviceKey:t,packageName:r.packageName,runner:r.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,waitForIdleTimeoutMs:r.waitForIdleTimeoutMs,waitForIdleQuietMs:r.waitForIdleQuietMs,timeoutMs:r.timeoutMs,maxDepth:r.maxDepth,maxNodes:r.maxNodes}));if(ec.get(a)===s)return;let l=ed.get(a);if(l&&l.identity!==s&&(await ep(a),l=void 0),!l)try{l=await ef({deviceKey:a,identity:s,options:e,resolved:o})}catch(e){ec.set(a,s),u({level:"warn",phase:"android_snapshot_helper_session_disabled",data:{deviceKey:a,reason:e instanceof Error?e.message:String(e)}});return}try{let e=l.capturedCount>0,t=await em(l,o);return l.capturedCount+=1,{xml:t.xml,metadata:{...t.metadata,transport:"persistent-session",sessionReused:e}}}catch(e){throw await ep(a),e}}async function ep(e){let t=ed.get(e);if(t){ed.delete(e);try{await eA(t,`quit ${Date.now()}`,1e3)}catch{}try{await t.process.kill("SIGTERM")}catch{}await ew(t.process,2e3);try{await eM(t)}catch{}u({phase:"android_snapshot_helper_session_stop",data:{deviceKey:e,port:t.port,capturedCount:t.capturedCount,lifetimeMs:Date.now()-t.startedAtMs}})}}async function ef(e){let t=await new Promise((e,t)=>{let r=o.createServer();r.unref(),r.on("error",t),r.listen(0,"127.0.0.1",()=>{let n=r.address();if(!n||"string"==typeof n)return void r.close(()=>t(Error("Failed to allocate a local TCP port")));let i=n.port;r.close(()=>e(i))})});await e.options.adb(["forward",`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:5e3});let r=W({...e.resolved,outputPath:void 0,emitChunks:!1}),n=r[r.length-1];if(!n)throw new a("INVALID_ARGS","Android snapshot helper runner was not resolved");let i=[...r.slice(0,-1),"-e","sessionPort",String(t),n],s=e.options.adbProvider.spawn(i,{allowFailure:!0,captureOutput:!1}),l={identity:e.identity,deviceKey:e.deviceKey,port:t,adb:e.options.adb,process:s,startedAtMs:Date.now(),capturedCount:0};try{var d;return await (d=s,new Promise((e,t)=>{let r="",n=setTimeout(()=>{t(new a("COMMAND_FAILED","Android snapshot helper session did not become ready",{output:r,timeoutMs:1e4}))},1e4),i=t=>{(r+=t.toString()).includes(`agentDeviceProtocol=${f}`)&&r.includes("sessionReady=true")&&(clearTimeout(n),e())};d.stdout?.on("data",i),d.stderr?.on("data",i),d.once("exit",(e,i)=>{clearTimeout(n),t(new a("COMMAND_FAILED","Android snapshot helper session exited before ready",{output:r,exitCode:e,signal:i}))}),d.on("error",e=>{clearTimeout(n),t(e)})})),ed.set(e.deviceKey,l),u({phase:"android_snapshot_helper_session_ready",data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),l}catch(e){await eM(l);try{s.kill("SIGTERM")}catch{}throw await ew(s,2e3),e}}function ew(e,t){return new Promise(r=>{let n=setTimeout(r,t);e.once("close",()=>{clearTimeout(n),r()}),e.once("exit",()=>{clearTimeout(n),r()})})}async function em(e,t){let r=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`,n=Math.min(t.commandTimeoutMs,Math.max(t.timeoutMs+1e4,3e3));return function(e,t){var r;let{headers:n,xml:i}=function(e){let t=e.indexOf("\n\n");if(t<0)throw new a("COMMAND_FAILED","Android snapshot helper session returned malformed output",{response:e});return{headers:function(e){let t={};for(let r of e.split(/\r?\n/)){let e=r.indexOf("=");e<0||(t[r.slice(0,e)]=r.slice(e+1))}return t}(e.slice(0,t)),xml:e.slice(t+2)}}(e);return function(e,t){if(e.agentDeviceProtocol!==f)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong protocol",{headers:e});if(e.outputFormat!==w)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong output format",{headers:e});if(e.requestId!==t)throw new a("COMMAND_FAILED","Android snapshot helper session returned stale output",{headers:e,requestId:t});if("true"!==e.ok)throw new a("COMMAND_FAILED",e.message||e.errorType||"Android snapshot helper session returned an error",{helper:e})}(n,t),function(e,t){let r=ea(e.byteLength);if(void 0!==r&&Buffer.byteLength(t,"utf8")!==r)throw new a("COMMAND_FAILED","Android snapshot helper session returned truncated XML",{headers:e,actualByteLength:Buffer.byteLength(t,"utf8")});if(!t.includes("<hierarchy")||!t.includes("</hierarchy>"))throw new a("COMMAND_FAILED","Android snapshot helper session did not return XML",{headers:e,xml:t})}(n,i),{xml:i,metadata:{helperApiVersion:(r=n).helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:ea(r.waitForIdleTimeoutMs),waitForIdleQuietMs:ea(r.waitForIdleQuietMs),timeoutMs:ea(r.timeoutMs),maxDepth:ea(r.maxDepth),maxNodes:ea(r.maxNodes),rootPresent:es(r.rootPresent),captureMode:"interactive-windows"===r.captureMode||"active-window"===r.captureMode?r.captureMode:void 0,windowCount:ea(r.windowCount),nodeCount:ea(r.nodeCount),truncated:es(r.truncated),elapsedMs:ea(r.elapsedMs)}}}(await eA(e,`snapshot ${r}`,n),r)}function eA(e,t,r){return new Promise((n,i)=>{let s=o.connect({host:"127.0.0.1",port:e.port}),l=[],u=setTimeout(()=>{s.destroy(),i(new a("COMMAND_FAILED","Android snapshot helper session request timed out",{command:t,timeoutMs:r,port:e.port}))},r);s.on("connect",()=>{s.write(`${t}
4
4
  `)}),s.on("data",e=>{l.push(Buffer.from(e))}),s.on("error",e=>{clearTimeout(u),i(e)}),s.on("close",()=>{clearTimeout(u),n(Buffer.concat(l).toString("utf8"))})})}async function eM(e){await e.process.stdin?.end(),await e.process.stdout?.destroy(),await e.process.stderr?.destroy(),await eg(e)}async function eg(e){await e.adb(["forward","--remove",`tcp:${e.port}`],{allowFailure:!0,timeoutMs:5e3})}let ev=new Map;function eN(e){ey(ex(e.deviceKey,e.packageName,e.versionCode))}function ex(e,t,r){return e?`${e}\0${t}\0${r}`:void 0}function ey(e){e&&ev.delete(e)}async function eI(e){var t,r,n;let{adb:i,artifact:o}=e,s=e.installPolicy??"missing-or-outdated",l=o.manifest.packageName,u=o.manifest.versionCode;if("never"===s)return{packageName:l,versionCode:u,installed:!1,reason:"skipped"};let d=ex(e.deviceKey,l,u),c=d?ev.get(d):void 0;if(d&&"always"!==s&&void 0!==c)return{packageName:l,versionCode:u,installedVersionCode:c,installed:!1,reason:"current"};let h=await eC(i,l,e.timeoutMs),p=(t=s,r=h,n=u,"never"===t?"skipped":"always"===t?"forced":void 0===r?"missing":r<n?"outdated":"current");if("current"===p){if(void 0===h)throw Error("Expected installed versionCode for current Android snapshot helper");return d&&ev.set(d,h),{packageName:l,versionCode:u,installedVersionCode:h,installed:!1,reason:p}}await A(o);let f=await eD(i,e.adbProvider??i,o.apkPath,function(e){let t={};for(let r of e.slice(1)){let e=b(r);if(!e)throw new a("INVALID_ARGS",`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}(N(o.manifest.installArgs)),{packageName:l,timeoutMs:e.timeoutMs});if(0!==f.exitCode)throw ey(d),new a("COMMAND_FAILED","Failed to install Android snapshot helper",{packageName:l,versionCode:u,stdout:f.stdout,stderr:f.stderr,exitCode:f.exitCode});return d&&ev.set(d,u),{packageName:l,versionCode:u,installedVersionCode:h,installed:!0,reason:p}}async function eC(e,t,r){let n=await e(["shell","cmd","package","list","packages","--show-versioncode",t],{allowFailure:!0,timeoutMs:r});if(0===n.exitCode){var i=`${n.stdout}
5
5
  ${n.stderr}`,o=t;let e=`package:${o}`;for(let t of i.split(/\r?\n/)){if(!t.startsWith(e)||t.length>e.length&&!/\s/.test(t[e.length]??""))continue;let r=/(?:^|\s)versionCode:(\d+)(?:\s|$)/.exec(t);if(r)return Number(r[1])}return}}async function eD(e,t,r,n,i){var o;let a=async()=>await d(r,{allowFailure:!0,provider:t,...n,timeoutMs:i.timeoutMs}),s=await a();if(0===s.exitCode||(o=s,!`${o.stdout}
6
6
  ${o.stderr}`.includes("INSTALL_FAILED_UPDATE_INCOMPATIBLE")))return s;let l=await e(["uninstall",i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs}),u=await a();return 0===u.exitCode?u:{...u,stderr:[u.stderr,l.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${l.stderr}`:""].filter(Boolean).join("\n")}}export{c as ANDROID_SNAPSHOT_HELPER_NAME,w as ANDROID_SNAPSHOT_HELPER_OUTPUT_FORMAT,h as ANDROID_SNAPSHOT_HELPER_PACKAGE,f as ANDROID_SNAPSHOT_HELPER_PROTOCOL,p as ANDROID_SNAPSHOT_HELPER_RUNNER,S as androidUiNodes,k as buildUiHierarchySnapshot,K as captureAndroidSnapshotWithHelper,eh as captureAndroidSnapshotWithHelperSession,eI as ensureAndroidSnapshotHelper,eN as forgetAndroidSnapshotHelperInstall,g as parseAndroidSnapshotHelperManifest,Y as parseAndroidSnapshotHelperOutput,Z as parseAndroidSnapshotHelperXml,T as parseUiHierarchy,P as parseUiHierarchyTree,M as prepareAndroidSnapshotHelperArtifactFromManifestUrl,ep as stopAndroidSnapshotHelperSession,A as verifyAndroidSnapshotHelperArtifact};
@@ -0,0 +1,3 @@
1
+ import e from"node:fs";import{parseAllDocuments as t,stringify as n}from"yaml";import{AppError as r}from"./9152.js";import{MAESTRO_NEW_ISSUE_URL as i,MAESTRO_COMPAT_TRACKER_URL as o,readScreenshotScriptFlag as s}from"./6133.js";import{formatScriptStringLiteral as l,parseReplayOpenFlags as a,formatPortableActionLine as u,parseReplaySeriesFlags as f,parseReplayRuntimeFlags as p,isClickLikeCommand as c}from"./123.js";let h=/^[A-Z_][A-Z0-9_]*$/,d=/(\\\$\{)|\$\{([A-Za-z_][A-Za-z0-9_.]*)(?::-((?:[^}\\]|\\.)*))?\}/g,m="AD_VAR_";function g(e){return e.startsWith("AD_")}function A(e){return new r("INVALID_ARGS",`The AD_* namespace is reserved for built-in variables. Rename ${e} to avoid the AD_ prefix.`)}function y(e){let t={};if(e.builtins)for(let[n,r]of Object.entries(e.builtins))t[n]=r;for(let n of[e.fileEnv,e.shellEnv,e.cliEnv])if(n)for(let[e,r]of Object.entries(n)){if(g(e))throw A(e);t[e]=r}return{values:t}}function v(e,t){Object.assign(e.values,t)}function w(e){let t={};for(let[n,r]of Object.entries(e)){if("string"!=typeof r||!n.startsWith(m))continue;let e=n.slice(m.length);0!==e.length&&h.test(e)&&(g(e)||(t[e]=r))}return t}function b(e){let t={};for(let n of e){let e=n.indexOf("=");if(e<=0)throw new r("INVALID_ARGS",`Invalid -e entry "${n}": expected KEY=VALUE.`);let i=n.slice(0,e);if(!h.test(i))throw new r("INVALID_ARGS",`Invalid -e key "${i}": keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(g(i))throw A(i);t[i]=n.slice(e+1)}return t}function I(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):[]}function $(e){if(e&&"object"==typeof e&&!Array.isArray(e)){let t={};for(let[n,r]of Object.entries(e))"string"==typeof r&&(t[n]=r);return t}return process.env}function S(e,t,n){return e.replace(d,(e,i,o,s)=>{if(i)return"${";if(!o)return e;if(Object.prototype.hasOwnProperty.call(t.values,o))return String(t.values[o]);if(void 0!==s)return s.replace(/\\(.)/g,"$1");throw new r("INVALID_ARGS",`Unresolved variable \${${o}} at ${n.file}:${n.line}.`)})}function _(e,t,n){return{...e,positionals:(e.positionals??[]).map(e=>S(e,t,n)),flags:N(e.flags,t,n)??{},runtime:N(e.runtime,t,n),replayControl:function(e,t,n){if(!e)return e;if(e.kind==="maestroRunFlowWhen"){return{...e,selector:S(e.selector,t,n)}}return e}(e.replayControl,t,n)}}function N(e,t,n){return e?function e(t,n,r){return"string"==typeof t?S(t,n,r):Array.isArray(t)?t.map(t=>e(t,n,r)):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).map(([t,i])=>[t,e(i,n,r)])):t}(e,t,n):e}let R=new Set(["ios","android","macos","linux"]),D=new Set(["mobile","tv","desktop"]);function M(e){let t=[],n=[],i=e.split(/\r?\n/),o=!1;for(let[e,l]of i.entries()){let i=l.trim();if(0===i.length||i.startsWith("#"))continue;if(x(i)){if(o)throw new r("INVALID_ARGS",`env directives must precede all actions (line ${e+1}).`);continue}let u=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let[n,...i]=function(e){let t=[],n=0;for(;n<e.length&&!((n=function(e,t){let n=t;for(;n<e.length&&/\s/.test(e.charAt(n));)n+=1;return n}(e,n))>=e.length);){let i='"'===e[n]?function(e,t){let n=!1,i=t+1;for(;i<e.length;i+=1){let t=e.charAt(i);if('"'===t&&!n)break;if(n){n=!1;continue}n="\\"===t}if(i>=e.length)throw new r("INVALID_ARGS",`Invalid replay script line: ${e}`);return{value:JSON.parse(e.slice(t,i+1)),nextCursor:i+1}}(e,n):function(e,t){let n=t;for(;n<e.length&&!/\s/.test(e.charAt(n));)n+=1;return{value:e.slice(t,n),nextCursor:n}}(e,n);t.push(i.value),n=i.nextCursor}return t}(t);if(void 0===n||"context"===n)return null;let o={ts:Date.now(),command:n,positionals:[],flags:{}};if("snapshot"===n){o.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){o.flags.snapshotInteractiveOnly=!0;continue}if("-c"!==t){if("--raw"===t){o.flags.snapshotRaw=!0;continue}if("--force-full"===t){o.flags.snapshotForceFull=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(o.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){o.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}}return o}if("open"===n){let e=a(i);return o.positionals=e.positionals,Object.assign(o.flags,e.flags),o.runtime=e.runtime,o}if("runtime"===n){let e=p(i);return o.positionals=e.positionals,Object.assign(o.flags,e.flags),o}if(c(n)){let e=f(n,i);Object.assign(o.flags,e.flags);let t=e.positionals[0];if(void 0===t)return o;if(t.startsWith("@"))return o.positionals=[t],e.positionals[1]&&(o.result={refLabel:e.positionals[1]}),o;let r=e.positionals[0],s=e.positionals[1];return j(r)&&j(s)&&e.positionals.length>=2?o.positionals=[r,s]:o.positionals=[e.positionals.join(" ")],o}if("fill"===n){let e=f(n,i);if(Object.assign(o.flags,e.flags),!(e.positionals.length>=2))return o.positionals=e.positionals,o;let[t,r,...s]=e.positionals;return t.startsWith("@")?(s.length>0?(o.positionals=[t,s.join(" ")],o.result={refLabel:r}):o.positionals=[t,r],o):(o.positionals=[t,[r,...s].join(" ")],o)}if("get"===n){let e=i[0],t=i[1];return void 0===e||void 0===t?o.positionals=i:t.startsWith("@")?(o.positionals=[e,t],i[2]&&(o.result={refLabel:i[2]})):o.positionals=[e,i.slice(1).join(" ")],o}if("swipe"===n||"type"===n){let e=f(n,i);return Object.assign(o.flags,e.flags),o.positionals=e.positionals,o}if("record"===n){let e=[];for(let t=0;t<i.length;t+=1){let n=i[t];if("--hide-touches"===n){o.flags.hideTouches=!0;continue}if("--fps"===n&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(o.flags.fps=Math.floor(e)),t+=1;continue}if("--quality"===n&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(o.flags.quality=Math.floor(e)),t+=1;continue}e.push(n)}return o.positionals=e,o}if("screenshot"===n){let e=[];for(let t=0;t<i.length;t+=1){let n=i[t],r=s({args:i,index:t,flags:o.flags});if(r.handled){t=r.nextIndex;continue}e.push(n)}return o.positionals=e,o}return o.positionals=i,o}(l);u&&(t.push(u),n.push(e+1),o=!0)}return{actions:t,actionLines:n}}function O(e){let t=e.split(/\r?\n/),n={};for(let[e,i]of t.entries()){let t=i.trim();if(0===t.length||t.startsWith("#"))continue;if(x(t)){!function(e,t,n){let{key:i,value:o}=function(e,t){let n=e.slice(3).replace(/^[\s]+/,""),i=n.indexOf("=");if(i<=0)throw new r("INVALID_ARGS",`Invalid env directive on line ${t}: expected "env KEY=VALUE".`);let o=n.slice(0,i);if(!h.test(o))throw new r("INVALID_ARGS",`Invalid env key "${o}" on line ${t}: keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(o.startsWith("AD_"))throw new r("INVALID_ARGS",`Invalid env key "${o}" on line ${t}: the AD_* namespace is reserved for built-in variables. Rename ${o} to avoid the AD_ prefix.`);return{key:o,value:function(e,t){if(0===e.length)return"";if(e.startsWith('"'))try{let t=JSON.parse(e);if("string"!=typeof t)throw Error("not a string literal");return t}catch{throw new r("INVALID_ARGS",`Invalid quoted env value on line ${t}.`)}return e}(n.slice(i+1),t)}}(t,n),s=e.env??{};if(Object.prototype.hasOwnProperty.call(s,i))throw new r("INVALID_ARGS",`Duplicate env directive "${i}" on line ${n}.`);s[i]=o,e.env=s}(n,t,e+1);continue}if(!t.startsWith("context "))break;let o=t.match(/(?:^|\s)platform=([^\s]+)/);if(o){let e=o[1];e&&R.has(e)&&L(n,"platform",e)}let s=t.match(/(?:^|\s)target=([^\s]+)/);if(s){let e=s[1];e&&D.has(e)&&L(n,"target",e)}let l=t.match(/(?:^|\s)timeout=(\d+)/);if(l){let e=Number(l[1]);Number.isFinite(e)&&e>=1&&L(n,"timeoutMs",Math.floor(e))}let a=t.match(/(?:^|\s)retries=(\d+)/);if(a){let e=Number(a[1]);Number.isFinite(e)&&e>=0&&L(n,"retries",Math.floor(e))}}return n}function x(e){return"env"===e||e.startsWith("env ")||e.startsWith("env ")}function L(e,t,n){let i=e[t];if(void 0!==i)throw new r("INVALID_ARGS",i===n?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(i)} vs ${String(n)}.`);e[t]=n}function j(e){return!!e&&!Number.isNaN(Number(e))}function V(t,n,r){let i=[];if(r){let e=r.device.kind?` kind=${r.device.kind}`:"",t=r.device.target?` target=${r.device.target}`:"";i.push(`context platform=${r.device.platform}${t} device=${l(r.device.name)}${e} theme=unknown`)}for(let e of n)i.push(u(e,{runtimeIncludeAllPositionals:!0}));let o=`${i.join("\n")}
2
+ `,s=`${t}.tmp-${process.pid}-${Date.now()}`;e.writeFileSync(s,o),e.renameSync(s,t)}function k(e){let n=t(e);for(let e of n)if(e.errors.length>0){let t=e.errors[0]?.message??"Invalid Maestro YAML flow.";throw new r("INVALID_ARGS",`Invalid Maestro YAML flow: ${t}`)}return n.map(e=>e.toJSON()).filter(e=>null!==e)}function E(e){return`${e.map(e=>n(e).trimEnd()).join("\n---\n")}
3
+ `}function G(e,t=[],n){return{ts:Date.now(),command:e,positionals:t,flags:n??{}}}function C(e,t,n){let r=new Set(n),i=Object.keys(e).filter(e=>!r.has(e));if(i.length>0)throw H(`Maestro ${t} field "${i[0]}" is not supported yet.`)}function P(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function W(e){return e.map((e,t)=>{if("string"==typeof e||P(e))return e;throw new r("INVALID_ARGS",`Unsupported Maestro command at index ${t+1}: expected a scalar or one-key map.`)})}function F(e){if(e){let t;return"android"===(t=e.trim().toLowerCase())?"android":"ios"===t?"ios":void 0}}function K(e,t){if(null==e)return{};if(!P(e))throw new r("INVALID_ARGS",`${t} expects a map.`);let n={};for(let[t,r]of Object.entries(e))("string"==typeof r||"number"==typeof r||"boolean"==typeof r)&&(n[t]=String(r));return n}function U(e,t){return P(e)&&"number"==typeof e.timeout&&Number.isFinite(e.timeout)?Math.max(0,Math.floor(e.timeout)):t}function q(e,t){if(e.appId)return e.appId;throw new r("INVALID_ARGS",`${t} requires appId in the Maestro flow config.`)}function z(e,t){if("string"==typeof t)return t;throw new r("INVALID_ARGS",`${e} expects a string value.`)}function Y(e,t){return e.replace(/\$\{([A-Za-z_][A-Za-z0-9_.]*)\}/g,(e,n)=>Object.prototype.hasOwnProperty.call(t.env,n)?String(t.env[n]):e)}function Z(e){throw H(`Maestro command "${e}" is not supported yet.`)}function H(e){throw new r("INVALID_ARGS",`${e} See supported/unsupported Maestro compatibility at ${o}. If this syntax matters for your flows, comment there or open a focused issue at ${i}.`)}function J(e,t){return`${e},${t}`}function T(e){let t=e.match(/^(\d+),(\d+)$/);if(!t)throw H('Only absolute Maestro point selectors like "100,200" are supported.');return{x:Number(t[1]),y:Number(t[2])}}function B(e){let t=e.match(/^\s*(\d+)\s*,\s*(\d+)\s*$/);if(t)return{kind:"absolute",x:Number(t[1]),y:Number(t[2])};let n=e.match(/^\s*(\d+(?:\.\d+)?)%\s*,\s*(\d+(?:\.\d+)?)%\s*$/);if(n)return{kind:"percent",x:Number(n[1]),y:Number(n[2])};throw H('Only Maestro swipe coordinates like "100,200" or "50%,75%" are supported.')}export{C as assertOnlyKeys,y as buildReplayVarScope,w as collectReplayShellEnv,J as formatMaestroPoint,P as isPlainRecord,v as mergeReplayVarScopeValues,W as normalizeCommandList,F as normalizePlatform,T as parseAbsolutePoint,B as parseMaestroPoint,k as parseMaestroYamlDocuments,b as parseReplayCliEnvEntries,M as parseReplayScriptDetailed,K as readEnvMap,I as readReplayCliEnvEntries,O as readReplayScriptMetadata,$ as readReplayShellEnvSource,U as readTimeoutMs,q as requireAppId,z as requireStringValue,Y as resolveMaestroString,_ as resolveReplayAction,E as stringifyMaestroYamlDocuments,G as support_action,Z as unsupportedCommand,H as unsupportedMaestroSyntax,V as writeReplayScript};