agent-device 0.21.18 → 0.21.19

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 (145) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.18.apk → agent-device-android-ime-helper-0.21.19.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.19.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.18.manifest.json → agent-device-android-ime-helper-0.21.19.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.18.apk → agent-device-android-snapshot-helper-0.21.19.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.19.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.18.manifest.json → agent-device-android-snapshot-helper-0.21.19.manifest.json} +6 -6
  7. package/dist/src/adapter.js +1 -1
  8. package/dist/src/adb-executor.js +2 -2
  9. package/dist/src/adb-failure.js +2 -1
  10. package/dist/src/agent-browser-lifecycle.js +1 -1
  11. package/dist/src/agent-browser-process-record.js +1 -1
  12. package/dist/src/agent-browser-provider.js +1 -1
  13. package/dist/src/agent-device-client.js +2 -2
  14. package/dist/src/ai-sdk.js +1 -1
  15. package/dist/src/alert-runtime.js +1 -1
  16. package/dist/src/android-input-ownership.js +1 -1
  17. package/dist/src/android.js +1 -1
  18. package/dist/src/app-log-runtime2.js +1 -1
  19. package/dist/src/cache.js +1 -1
  20. package/dist/src/catalog.js +1 -1
  21. package/dist/src/cli-help.js +1 -1
  22. package/dist/src/cli.js +4 -4
  23. package/dist/src/client-types.d.ts +11 -4
  24. package/dist/src/command-metadata.js +1 -1
  25. package/dist/src/command-tools.js +2 -2
  26. package/dist/src/contracts.js +1 -1
  27. package/dist/src/daemon-client-lease-beat.js +1 -1
  28. package/dist/src/daemon-client-lifecycle.js +1 -1
  29. package/dist/src/daemon-client-transport.js +1 -1
  30. package/dist/src/daemon-policy-file.js +1 -1
  31. package/dist/src/device-claim-inspection.js +1 -1
  32. package/dist/src/device-claim-rule.js +1 -1
  33. package/dist/src/device-inventory-context.js +1 -1
  34. package/dist/src/device-session.js +1 -1
  35. package/dist/src/diagnostics.js +1 -1
  36. package/dist/src/diagnostics2.js +1 -1
  37. package/dist/src/durable-resource.js +1 -1
  38. package/dist/src/engine-eval-script.js +1 -1
  39. package/dist/src/error.js +1 -1
  40. package/dist/src/find.js +1 -1
  41. package/dist/src/finders.js +1 -1
  42. package/dist/src/generic-settle.js +1 -1
  43. package/dist/src/gesture-runtime.js +1 -1
  44. package/dist/src/index.d.ts +2 -2
  45. package/dist/src/index.js +1 -1
  46. package/dist/src/input-actions2.js +2 -2
  47. package/dist/src/install-source-network-transport.js +1 -1
  48. package/dist/src/interaction-positionals.js +1 -1
  49. package/dist/src/interaction-ref-policy.js +1 -1
  50. package/dist/src/interaction.js +1 -1
  51. package/dist/src/interaction2.js +1 -1
  52. package/dist/src/interactor.js +5 -5
  53. package/dist/src/internal/bin.js +1 -1
  54. package/dist/src/internal/daemon.js +2 -2
  55. package/dist/src/internal/png-worker.js +1 -1
  56. package/dist/src/ios-snapshot-acquisition.js +1 -1
  57. package/dist/src/ios-snapshot-engine.js +1 -1
  58. package/dist/src/lease.js +1 -1
  59. package/dist/src/local-interactor-operation-set.js +1 -1
  60. package/dist/src/mechanics.js +16 -17
  61. package/dist/src/mobile-snapshot-semantics.js +1 -1
  62. package/dist/src/observe-until.js +1 -0
  63. package/dist/src/overlay.js +2 -2
  64. package/dist/src/parameterized-recorded-fill.js +1 -1
  65. package/dist/src/perf-facade.js +1 -1
  66. package/dist/src/perf-runtime-operation-builder.js +1 -1
  67. package/dist/src/perf-runtime-plan.js +1 -1
  68. package/dist/src/physical-device-control.js +1 -1
  69. package/dist/src/platform-request-scope.js +1 -1
  70. package/dist/src/platform-runtime-managed-owner.js +1 -1
  71. package/dist/src/platform-runtime-operation-host.js +1 -1
  72. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  73. package/dist/src/platform-runtime.js +1 -1
  74. package/dist/src/platform-runtime2.js +1 -1
  75. package/dist/src/png-worker-client.js +1 -1
  76. package/dist/src/provider-device-admission.js +1 -0
  77. package/dist/src/provider-webdriver.js +1 -1
  78. package/dist/src/proxy.js +1 -1
  79. package/dist/src/react-native.js +1 -1
  80. package/dist/src/record-runtime.js +1 -1
  81. package/dist/src/registry.js +36 -36
  82. package/dist/src/replay-divergence.js +1 -1
  83. package/dist/src/replay.js +1 -1
  84. package/dist/src/request-admission.js +1 -1
  85. package/dist/src/request-runtime-binding.js +1 -1
  86. package/dist/src/runner-cache-metadata.js +2 -2
  87. package/dist/src/runner-client.js +1 -1
  88. package/dist/src/runner-dev-tools-security.js +1 -1
  89. package/dist/src/runner-disposal.js +1 -1
  90. package/dist/src/runner-error-classification.js +3 -3
  91. package/dist/src/runner-exchange.js +1 -1
  92. package/dist/src/runner-start-budget.js +1 -1
  93. package/dist/src/runner-startup-transport.js +1 -1
  94. package/dist/src/runner-xctestrun.js +1 -1
  95. package/dist/src/runner.js +1 -1
  96. package/dist/src/runtime-admission.js +1 -0
  97. package/dist/src/runtime.js +1 -1
  98. package/dist/src/runtime10.js +2 -2
  99. package/dist/src/runtime2.js +1 -1
  100. package/dist/src/runtime3.js +1 -1
  101. package/dist/src/runtime4.js +4 -4
  102. package/dist/src/runtime5.js +1 -1
  103. package/dist/src/runtime6.js +1 -1
  104. package/dist/src/runtime7.js +1 -1
  105. package/dist/src/runtime8.js +1 -1
  106. package/dist/src/runtime9.js +1 -1
  107. package/dist/src/screen-recording-resource-recovery.js +1 -1
  108. package/dist/src/screenshot-runtime.js +1 -1
  109. package/dist/src/script.js +1 -1
  110. package/dist/src/scroll-gesture.js +1 -1
  111. package/dist/src/sdk-batch-runner.js +2 -2
  112. package/dist/src/sdk-batch.js +1 -1
  113. package/dist/src/sdk-contracts.d.ts +16 -2
  114. package/dist/src/sdk-contracts.js +2 -2
  115. package/dist/src/sdk-finders.js +1 -1
  116. package/dist/src/sdk-selectors.d.ts +9 -0
  117. package/dist/src/sdk-selectors.js +1 -1
  118. package/dist/src/selection.js +0 -0
  119. package/dist/src/selector-pipeline-policy.js +1 -0
  120. package/dist/src/selector-runtime.js +1 -1
  121. package/dist/src/selectors.js +1 -1
  122. package/dist/src/server.js +1 -1
  123. package/dist/src/session-runtime-admission.js +1 -1
  124. package/dist/src/session-snapshot.js +1 -1
  125. package/dist/src/session-store.js +3 -3
  126. package/dist/src/session2.js +5 -5
  127. package/dist/src/snapshot-desktop-projection.js +1 -1
  128. package/dist/src/snapshot-runtime-binding.js +1 -1
  129. package/dist/src/snapshot-runtime.js +1 -1
  130. package/dist/src/snapshot-state.js +1 -1
  131. package/dist/src/snapshot4.js +1 -1
  132. package/dist/src/src.js +1 -1
  133. package/dist/src/src7.js +1 -1
  134. package/dist/src/target-evidence.js +1 -1
  135. package/dist/src/text-entry-focus.js +1 -1
  136. package/dist/src/touch-runtime.js +1 -1
  137. package/dist/src/touch-runtime2.js +1 -0
  138. package/dist/src/tree.js +1 -1
  139. package/dist/src/type-text-runtime.js +1 -1
  140. package/dist/src/video.js +1 -1
  141. package/package.json +1 -1
  142. package/server.json +2 -2
  143. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.18.apk.sha256 +0 -1
  144. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.18.apk.sha256 +0 -1
  145. package/dist/src/runner-command-traits.js +0 -1
@@ -1,2 +1,2 @@
1
- import{F as e,L as t,N as n,V as r}from"./sdk-contracts.js";import{i}from"./recording-export-quality.js";import{D as a,E as o,T as s,a as c,b as l,i as u,k as d,o as f,r as p,t as ee,w as te,x as m,y as h}from"./runtime.js";import{r as g}from"./success-text.js";import{n as ne,t as re}from"./app-inventory.js";import"./app-inventory-contract.js";import{k as ie}from"./owner-identity.js";import{c as ae}from"./exec.js";import"./file.js";import{r as oe}from"./tv-remote.js";import"./command.js";import{r as _}from"./version.js";import{t as se}from"./keyboard-actions.js";import{i as ce}from"./quality-warnings.js";import{r as v}from"./png.js";import{i as le}from"./png-worker-client.js";import{t as ue}from"./png-size.js";import{i as y,n as de,r as fe}from"./screenshot-overlay-draw.js";import{t as pe}from"./png-encode.js";import{r as me}from"./artifact-paths.js";import{t as he}from"./mp4-duration.js";import{c as b,o as ge,r as _e,s as ve}from"./video.js";import x from"node:path";import S from"node:fs";import ye from"node:os";function C(e,t){if(e!==void 0)return w(e,t)}function w(e,t){let r=e?.trim();if(!r)throw new n(`INVALID_ARGS`,`${t} must be a non-empty string`);return r}const be=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(m(e,t),t.filter)}},xe=async(e,t={})=>{if(!e.backend.bootDevice)throw new n(`UNSUPPORTED_OPERATION`,`admin.boot is not supported by this backend`);let r=D(t.target),i=await e.backend.bootDevice(m(e,t),r),a=l(i);return{kind:`deviceBooted`,...r?{target:r}:{},...a?{backendResult:a}:{},...g(`Booted device`)}},Se=async(e,t={})=>{if(!e.backend.shutdownDevice)throw new n(`UNSUPPORTED_OPERATION`,`admin.shutdown is not supported by this backend`);let r=D(t.target),i=await e.backend.shutdownDevice(m(e,t),r),a=l(i);return{kind:`deviceShutdown`,...r?{target:r}:{},...a?{backendResult:a}:{},...g(`Shutdown device`)}},Ce=async(e,t)=>await T(e,t,`install`),we=async(e,t)=>await T(e,t,`reinstall`),Te=async(e,t)=>await T(e,t,`installFromSource`);async function T(e,t,r){let i=r===`reinstall`?`reinstallApp`:`installApp`,a=e.backend[i];if(!a)throw new n(`UNSUPPORTED_OPERATION`,`admin.${r} is not supported by this backend`);let o=`app`in t&&t.app!==void 0?w(t.app,`app`):void 0;if(r!==`installFromSource`&&!o)throw new n(`INVALID_ARGS`,`admin.${r} requires app`);let s=m(e,t),c=await Ee(e,s,t.source);try{let t=await a.call(e.backend,s,{...o?{app:o}:{},source:c.source});return ke(r,o,c.source,t)}finally{await c.cleanup?.()}}async function Ee(e,t,n){let r=await De(e,E(n));try{return{source:E(e.backend.resolveInstallSource?await e.backend.resolveInstallSource(t,r.source):r.source),...r.cleanup?{cleanup:r.cleanup}:{}}}catch(e){if(r.cleanup)try{await r.cleanup()}catch{}throw e}}async function De(e,t){if(t.kind===`url`)return{source:t};let n=await u(e,t,{usage:`admin.install`,field:`source`});return{source:{kind:`path`,path:n.path},...n.cleanup?{cleanup:n.cleanup}:{}}}function E(e){if(!e||typeof e!=`object`)throw new n(`INVALID_ARGS`,`install source is required`);if(e.kind===`path`)return{kind:`path`,path:w(e.path,`source.path`)};if(e.kind===`uploadedArtifact`)return{kind:`uploadedArtifact`,id:w(e.id,`source.id`)};if(e.kind===`url`){let t=w(e.url,`source.url`);return Oe(t),{kind:`url`,url:t}}throw new n(`INVALID_ARGS`,`install source kind must be path, uploadedArtifact, or url`)}function Oe(e){let t;try{t=new URL(e)}catch{throw new n(`INVALID_ARGS`,`Invalid install source URL: ${e}`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new n(`INVALID_ARGS`,`Install source URL must use http or https`)}function D(e){if(!e)return;let t=C(e.id,`target.id`),n=C(e.name,`target.name`),r={...t?{id:t}:{},...n?{name:n}:{},...e.platform?{platform:e.platform}:{},...e.target?{target:e.target}:{},...e.headless===void 0?{}:{headless:e.headless}};return Object.keys(r).length>0?r:void 0}function ke(e,t,n,r){let i=l(r),a=e===`reinstall`?`appReinstalled`:e===`installFromSource`?`appInstalledFromSource`:`appInstalled`,o=O(r,`appName`),s=O(r,`appId`),c=O(r,`bundleId`),u=O(r,`packageName`),d=O(r,`launchTarget`),f=O(r,`installablePath`),p=O(r,`archivePath`);return{kind:a,...t?{app:t}:{},source:n,...s?{appId:s}:{},...o?{appName:o}:{},...c?{bundleId:c}:{},...u?{packageName:u}:{},...d?{launchTarget:d}:{},...f?{installablePath:f}:{},...p?{archivePath:p}:{},...i?{backendResult:i}:{},...g(`${e===`reinstall`?`Reinstalled`:`Installed`}: ${o??d??t??Ae(n)}`)}}function O(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function Ae(e){return e.kind===`path`?e.path:e.kind===`uploadedArtifact`?e.id:e.url}const je=/^[A-Za-z0-9_.:-]{1,64}$/,Me=async(e,t)=>{if(!e.backend.openApp)throw new n(`UNSUPPORTED_OPERATION`,`apps.open is not supported by this backend`);let r=Re(t),i=await e.backend.openApp(A(e,t),r,{launchArgs:t.launchArgs,relaunch:t.relaunch}),a=l(i);return{kind:`appOpened`,target:r,relaunch:t.relaunch===!0,...a?{backendResult:a}:{},...g(`Opened: ${Be(r)}`)}},Ne=async(e,t={})=>{if(!e.backend.closeApp)throw new n(`UNSUPPORTED_OPERATION`,`apps.close is not supported by this backend`);let r=C(t.app,`app`),i=await e.backend.closeApp(A(e,t),r),a=l(i);return{kind:`appClosed`,...r?{app:r}:{},...a?{backendResult:a}:{},...g(r?`Closed: ${r}`:`Closed app`)}},Pe=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(A(e,t),re(t.filter))}},Fe=async(e,t)=>{if(!e.backend.getAppState)throw new n(`UNSUPPORTED_OPERATION`,`apps.state is not supported by this backend`);let r=w(t.app,`app`);return{kind:`appState`,app:r,state:await e.backend.getAppState(A(e,t),r)}},Ie=async(e,t)=>{if(!e.backend.pushFile)throw new n(`UNSUPPORTED_OPERATION`,`apps.push is not supported by this backend`);let r=w(t.app,`app`),i=await Ve(e,t.input);try{let n=await e.backend.pushFile(A(e,t),i.backendInput,r),a=l(n);return{kind:`appPushed`,app:r,inputKind:i.inputKind,...a?{backendResult:a}:{},...g(`Pushed to ${r}`)}}finally{await i.cleanup?.()}},Le=async(e,t)=>{if(!e.backend.triggerAppEvent)throw new n(`UNSUPPORTED_OPERATION`,`apps.triggerEvent is not supported by this backend`);let r=He(t.name);Ue(t.payload,`apps.triggerEvent payload for "${r}"`);let i=await e.backend.triggerAppEvent(A(e,t),{name:r,...t.payload?{payload:t.payload}:{}}),a=l(i);return{kind:`appEventTriggered`,name:r,...t.payload?{payload:t.payload}:{},...a?{backendResult:a}:{},...g(`Triggered app event: ${r}`)}};function Re(e){let t=C(e.app,`app`),r=C(e.appId,`appId`),i=C(e.bundleId,`bundleId`),a=C(e.packageName,`packageName`),o=C(e.url,`url`),s=C(e.activity,`activity`),c={...t?{app:t}:{},...r?{appId:r}:{},...i?{bundleId:i}:{},...a?{packageName:a}:{},...o?{url:o}:{},...s?{activity:s}:{}};if(!ze(c))throw new n(`INVALID_ARGS`,`apps.open requires app, appId, bundleId, packageName, url, or activity`);return c}function ze(e){return!!(e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity)}function Be(e){return e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity??`app`}async function Ve(e,t){if(!t||typeof t!=`object`)throw new n(`INVALID_ARGS`,`apps.push requires an input`);if(t.kind===`json`)return k(t.payload,`apps.push JSON payload`,8192),{backendInput:{kind:`json`,payload:t.payload},inputKind:`json`};let r=await u(e,t,{usage:`apps.push`,field:`input`});return{backendInput:{kind:`file`,path:r.path},inputKind:`file`,...r.cleanup?{cleanup:r.cleanup}:{}}}function He(e){let t=w(e,`name`);if(!je.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}function Ue(e,t){e!==void 0&&k(e,t,8192)}function k(e,t,r){if(We(e,t),Buffer.byteLength(Ge(e,t),`utf8`)>r)throw new n(`INVALID_ARGS`,`${t} exceeds ${r} bytes`)}function We(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`${t} must be a JSON object`)}function Ge(e,t){try{let r=JSON.stringify(e);if(typeof r!=`string`)throw new n(`INVALID_ARGS`,`${t} must be JSON-serializable`);return r}catch{throw new n(`INVALID_ARGS`,`${t} must be JSON-serializable`)}}function A(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}const j={open:Me,close:Ne,list:Pe,state:Fe,push:Ie,triggerEvent:Le},Ke={devices:be,boot:xe,shutdown:Se,install:Ce,reinstall:we,installFromSource:Te};function qe(e){return{...h(j,e),list:(t={})=>j.list(e,{...t,filter:ne(t.filter)})}}const Je=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i,Ye=/\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/g;function M(e){let t=!1,n=e;return n=n.replaceAll(/(authorization|token|secret|password|passwd|api[-_]?key)=([^&\s]+)/gi,(e,n)=>(t=!0,`${String(n)}=[REDACTED]`)),n=n.replaceAll(/("(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)"\s*:\s*")([^"]*)(")/gi,(e,n,r,i)=>(t=!0,`${String(n)}[REDACTED]${String(i)}`)),n=n.replaceAll(/\b(Bearer\s+)([^\s",;]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(/((?:authorization|cookie|token|secret|password|passwd|api[-_]?key)\s*[:=]\s*)([^\s,;&]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(Ye,()=>(t=!0,`[REDACTED]`)),n=Ze(n,()=>{t=!0}),{value:n,redacted:t}}function Xe(e){try{let t=new URL(e),n=Qe(t);return(t.username||t.password)&&(t.username=`REDACTED`,t.password=`REDACTED`,n=!0),{value:t.toString(),redacted:n}}catch{return}}function Ze(e,t){return/(https?:\/\/|token|secret|password|authorization|cookie|api[-_]?key)/i.test(e)?e.replaceAll(/https?:\/\/[^\s"'<>)]+/gi,e=>{let n=Xe(e);return n?(n.redacted&&t(),n.value):e}):e}function Qe(e){let t=!1;for(let n of Array.from(e.searchParams.keys()))Je.test(n)&&(e.searchParams.set(n,`[REDACTED]`),t=!0);return t}const N=2048,P=4096,F=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i;function $e(e){let t=e.redacted===!0;return{kind:`diagnosticsLogs`,entries:e.entries.map(e=>{let n=B(e.message,P),r=R(e.metadata);return t||=n.redacted||r.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.level?{level:e.level}:{},message:n.value??``,...e.source?{source:e.source}:{},...r.value?{metadata:r.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function et(e,t){let n=e.redacted===!0;return{kind:`diagnosticsNetwork`,entries:e.entries.map(e=>{let r=e.url?nt(e.url):void 0,i=t===`headers`||t===`all`?I(e.requestHeaders):void 0,a=t===`headers`||t===`all`?I(e.responseHeaders):void 0,o=t===`body`||t===`all`?L(e.requestBody):void 0,s=t===`body`||t===`all`?L(e.responseBody):void 0,c=R(e.metadata);return n||=(r?.redacted??!1)||(i?.redacted??!1)||(a?.redacted??!1)||(o?.redacted??!1)||(s?.redacted??!1)||c.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.method?{method:e.method}:{},...r?{url:r.value}:{},...e.status===void 0?{}:{status:e.status},...e.durationMs===void 0?{}:{durationMs:e.durationMs},...i?.value?{requestHeaders:i.value}:{},...a?.value?{responseHeaders:a.value}:{},...o?.value===void 0?{}:{requestBody:o.value},...s?.value===void 0?{}:{responseBody:s.value},...c.value?{metadata:c.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:n,...e.notes?{notes:e.notes}:{}}}function tt(e){let t=e.redacted===!0;return{kind:`diagnosticsPerf`,metrics:e.metrics.map(e=>{let n=B(e.message,P),r=R(e.metadata);return t||=n.redacted||r.redacted,{name:e.name,...e.value===void 0?{}:{value:e.value},...e.unit?{unit:e.unit}:{},...e.status?{status:e.status}:{},...n.value===void 0?{}:{message:n.value},...r.value?{metadata:r.value}:{}}}),...e.startedAt?{startedAt:e.startedAt}:{},...e.endedAt?{endedAt:e.endedAt}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function I(e){if(!e)return{redacted:!1};let t=!1,n={};for(let[r,i]of Object.entries(e))if(F.test(r))n[r]=`[REDACTED]`,t=!0;else{let e=B(i,N);n[r]=e.value??``,t||=e.redacted}return{value:n,redacted:t}}function nt(e){return Xe(e)??B(e,N)}function L(e){return e===void 0?{redacted:!1}:rt(e)??B(e,N)}function rt(e){try{let t=z(JSON.parse(e),M);return V(JSON.stringify(t.value),N,t.redacted)}catch{return}}function R(e){return z(e,e=>B(e,N))}function z(e,t){if(e===void 0)return{redacted:!1};if(typeof e==`string`)return t(e);if(!e||typeof e!=`object`)return{value:e,redacted:!1};if(Array.isArray(e)){let n=!1;return{value:e.map(e=>{let r=z(e,t);return n||=r.redacted,r.value}),redacted:n}}let n=!1,r={};for(let[i,a]of Object.entries(e)){if(F.test(i)){r[i]=`[REDACTED]`,n=!0;continue}let e=z(a,t);r[i]=e.value,n||=e.redacted}return{value:r,redacted:n}}function B(e,t){if(e===void 0)return{redacted:!1};let n=M(e);return V(n.value,t,n.redacted)}function V(e,t,n){if(e===void 0)return{redacted:n};let r=e;return r.length>t&&(r=`${r.slice(0,t)}...[truncated]`,n=!0),{value:r,redacted:n}}const it=async(e,t={})=>{if(!e.backend.readLogs)throw new n(`UNSUPPORTED_OPERATION`,`diagnostics.logs is not supported by this backend`);return $e(await e.backend.readLogs(await H(e,t),st(t)))},at=async(e,t={})=>{if(!e.backend.dumpNetwork)throw new n(`UNSUPPORTED_OPERATION`,`diagnostics.network is not supported by this backend`);let r=ct(t);return et(await e.backend.dumpNetwork(await H(e,t),r),r.include??`summary`)},ot=async(e,t={})=>{if(!e.backend.measurePerf)throw new n(`UNSUPPORTED_OPERATION`,`diagnostics.perf is not supported by this backend`);return tt(await e.backend.measurePerf(await H(e,t),lt(t)))};async function H(e,t){let n=m(e,t),r=t.session?await e.sessions.get(t.session):void 0;return{...n,...t.appId??r?.appId?{appId:t.appId??r?.appId}:{},...t.appBundleId??r?.appBundleId?{appBundleId:t.appBundleId??r?.appBundleId}:{}}}function st(e){return{...U(e,100,500,`logs limit`),...e.levels===void 0?{}:{levels:G(e.levels,`levels`)},...e.search===void 0?{}:{search:w(e.search,`search`)},...e.source===void 0?{}:{source:w(e.source,`source`)}}}function ct(e){return{...U(e,25,200,`network limit`),include:ut(e.include)}}function lt(e){return{...W(e),...e.sampleMs===void 0?{}:{sampleMs:d(e.sampleMs,`sampleMs`,100,6e4)},...e.metrics===void 0?{}:{metrics:G(e.metrics,`metrics`,20)}}}function U(e,t,n,r){return{...W(e),...e.cursor===void 0?{}:{cursor:w(e.cursor,`cursor`)},limit:e.limit===void 0?t:d(e.limit,r,1,n)}}function W(e){return{...e.since===void 0?{}:{since:w(e.since,`since`)},...e.until===void 0?{}:{until:w(e.until,`until`)}}}function ut(e){if(e===void 0)return`summary`;if(e===`summary`||e===`headers`||e===`body`||e===`all`)return e;throw new n(`INVALID_ARGS`,`network include must be summary, headers, body, or all`)}function G(e,t,r=50){if(!Array.isArray(e))throw new n(`INVALID_ARGS`,`${t} must be an array of strings`);if(e.length>r)throw new n(`INVALID_ARGS`,`${t} must contain at most ${r} entries`);return e.map((e,n)=>w(e,`${t}[${n}]`))}const dt={logs:it,network:at,perf:ot},K=`contact_sheet_frame_extraction_failed`,q=`contact_sheet_no_frames`;function J(e=process.platform){if(e!==`darwin`)throw new n(`UNSUPPORTED_OPERATION`,`Contact sheets can only be built on macOS hosts, which is where the frame decoder runs`,{reason:`contact_sheet_unsupported_host`,hostPlatform:e,hint:`Run this command on the macOS host that recorded the clip, or read the video artifact itself.`})}async function ft(e){if(J(e.hostPlatform??process.platform),e.timesMs.length===0)throw new n(`COMMAND_FAILED`,`Contact sheet sampling requested no frames`,{reason:q,videoPath:e.videoPath});vt(e.signal);let t=await _t(e);vt(e.signal);let r;try{r=await ae(t,[`--input`,e.videoPath,`--output-dir`,e.scratchDir,`--times`,e.timesMs.join(`,`),`--max-width`,String(e.maxWidth)],{timeoutMs:9e4,env:ge(),allowFailure:!0,...e.signal===void 0?{}:{signal:e.signal}})}catch(t){Z(t,e.videoPath,`Failed to run the frame decoder`)}if(r.exitCode!==0)throw new n(`COMMAND_FAILED`,`Failed to extract frames from the recording: ${gt(r.stderr)||`exit ${r.exitCode}`}`,{reason:K,videoPath:e.videoPath,exitCode:r.exitCode});let i=pt(r.stdout,e.videoPath,e.scratchDir,e.timesMs.length);if(i.frames.length===0)throw new n(`COMMAND_FAILED`,`The recording returned no decodable frames for a contact sheet`,{reason:q,videoPath:e.videoPath,skippedSampleCount:i.skippedSampleCount});return i}function pt(e,t,n,r){let i;try{i=JSON.parse(e)}catch(e){throw X(t,`invalid manifest: ${String(e)}`)}let a=Q(i).frames;if(!Array.isArray(a))throw X(t,`manifest has no frames array`);let o=Q(i).skipped;if(a.length>r)throw X(t,`returned ${a.length} frames for ${r} requested samples`);let s=a.flatMap(e=>{let r=Q(e),i=mt(r.path),a=ht(r.actualTimeMs);if(i===void 0||a===void 0||a<0)throw X(t,`frame entry is missing a path or presentation time`);let o=x.resolve(n,x.basename(i));return S.existsSync(o)?[{requestedTimeMs:ht(r.requestedTimeMs)??a,actualTimeMs:a,path:o}]:[]});return{frames:s.sort((e,t)=>e.actualTimeMs-t.actualTimeMs),skippedSampleCount:Math.max(Array.isArray(o)?o.length:0,r-s.length)}}function Y(e,t,r){return new n(`COMMAND_FAILED`,e,{reason:K,videoPath:t},r)}function X(e,t){return Y(`Frame extraction returned an unreadable manifest: ${t}`,e)}function Z(e,i,a){throw r(e)||e instanceof n&&e.code===`COMMAND_FAILED`&&e.details?.reason?e:Y(`${a} for ${i}: ${t(e)}`,i,e)}function Q(e){return typeof e==`object`&&e?e:{}}function mt(e){return typeof e==`string`&&e!==``?e:void 0}function ht(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function gt(e){return(e.trim().split(`
2
- `).pop()??``).trim()}async function _t(e){try{return await ve({sourcePath:b(`recording-frames.swift`,_()),extraSourcePaths:[b(`RecordingExportSupport.swift`,_())],cacheName:`recording-frames`,timeoutMs:12e4})}catch(t){Z(t,e.videoPath,`Could not build the frame decoder`)}}function vt(t){if(t?.aborted)throw e()}function yt(e,t){if(e===void 0||!Number.isFinite(e)||e<0)throw new n(`COMMAND_FAILED`,`Cannot plan a contact sheet: the video timeline of ${t} could not be read`,{reason:`contact_sheet_duration_unknown`,videoPath:t,hint:`Retry once the recording finished finalizing; a clip whose container is still being written has no readable duration.`});if(e<=250)return{durationMs:e,timesMs:e>0?[0,Math.round(e)]:[0]};let r=Math.min(48,Math.floor(e/250)+1),i=e/(r-1);return{durationMs:e,timesMs:Array.from({length:r},(e,t)=>Math.round(t*i))}}const bt=[360,320,280,240,200,160],xt=[255,255,255,255],St=[17,24,39,255],$=fe(2)+8;function Ct(e){let{cells:t}=e;if(t.length===0)throw new n(`COMMAND_FAILED`,`Contact sheet has no cells to render`);let r=Tt(t[0].image.height/Math.max(1,t[0].image.width),t.length,e),i=Ot(r.width,r.height,St);return t.forEach((e,t)=>{let n=t%r.columns,a=Math.floor(t/r.columns);wt(i,8+n*(r.cellWidth+8),8+a*($+r.cellHeight+8),e,r.cellWidth,r.cellHeight)}),{bytes:pe(i.data,r.width,r.height,4),width:r.width,height:r.height,cellWidth:r.cellWidth}}function wt(e,t,n,r,i,a){de(e,{x:t+4,y:n+4,text:jt(r.timeMs),color:xt,scale:2}),kt(e,ce(At(r.image),i,a),t,n+$)}function Tt(e,t,r){let i=Et(e,t,r.maxPixels);if(i)return i;let a=Dt(e,t,160);throw new n(`COMMAND_FAILED`,`Contact sheet would be ${a.width*a.height} pixels, above the configured maxImagePixels limit of ${r.maxPixels}`,{reason:`contact_sheet_pixel_budget_exceeded`,cellCount:r.cells.length,maxPixels:r.maxPixels,hint:`Shorten the recording or raise the command policy maxImagePixels limit.`})}function Et(e,t,n){for(let r of bt){let i=Dt(e,t,r);if(i.width*i.height<=n)return i}}function Dt(e,t,n){let r=Math.min(4,t),i=Math.ceil(t/r),a=Math.max(1,Math.round(n*e));return{columns:r,cellWidth:n,cellHeight:a,width:16+r*n+(r-1)*8,height:16+i*($+a)+(i-1)*8}}function Ot(e,t,n){let r=new v.PNG({width:e,height:t});for(let i=0;i<t;i+=1)for(let t=0;t<e;t+=1)y(r,t,i,n);return r}function kt(e,t,n,r){for(let i=0;i<t.height;i+=1)for(let a=0;a<t.width;a+=1){let o=(i*t.width+a)*4;y(e,n+a,r+i,[t.data[o],t.data[o+1],t.data[o+2],t.data[o+3]])}}function At(e){let t=new v.PNG({width:e.width,height:e.height});return Buffer.from(e.data.buffer,e.data.byteOffset,e.data.byteLength).copy(t.data),t}function jt(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=Math.floor(e%1e3);return`${[n,r,i].map(e=>String(e).padStart(2,`0`)).join(`:`)}.${String(a).padStart(3,`0`)}`}function Mt(e,t){if(e.width!==t.width||e.height!==t.height)return{status:`dimension_mismatch`};let n=e.width*e.height;if(n===0)return{status:`compared`,changedPixelRatio:0};if(e.data.length!==t.data.length)return{status:`dimension_mismatch`};let r=0;for(let n=0;n+3<e.data.length;n+=4)(e.data[n]!==t.data[n]||e.data[n+1]!==t.data[n+1]||e.data[n+2]!==t.data[n+2])&&(r+=1);return{status:`compared`,changedPixelRatio:r/n}}function Nt(e,t=.02,n=24){let r=[],i;for(let n of e){let e=i?Ft(i,n.image):1;e<t||(r.push({timeMs:n.timeMs,changedPixelRatio:e,image:n.image}),i=n.image)}Pt(r,e);let a=r.length>n?It(r,n):r;return{cells:a,keptCellCount:r.length,thinned:a.length<r.length}}function Pt(e,t){let n=t.at(-1);if(!n)return;let r=e.at(-1);!r||r.timeMs===n.timeMs||e.push({timeMs:n.timeMs,changedPixelRatio:Ft(r.image,n.image),image:n.image})}function Ft(e,t){let n=Mt(e,t);return n.status===`compared`?n.changedPixelRatio:1}function It(e,t){if(t<=1)return[e.at(-1)];let n=(e.length-1)/(t-1);return Array.from({length:t},(t,r)=>e[Math.round(r*n)])}async function Lt(e){J(e.hostPlatform??process.platform);let t=x.resolve(e.videoPath),r=x.resolve(e.outputPath??me(t));Bt(t,r);let i=await _e(t);if(i!==`mp4`)throw new n(`INVALID_ARGS`,i===`webm`?`Contact sheets need an MP4 recording; ${t} is WebM, whose frames this decoder does not read`:`Contact sheets need an MP4 recording; ${t} is not a readable MP4`,{reason:`contact_sheet_container_unsupported`,videoPath:t,container:i??`unknown`,hint:`Re-record on a backend that exports MP4, or pass the MP4 artifact the recording produced.`});let a=yt(he(t),t),o=S.mkdtempSync(x.join(ye.tmpdir(),`agent-device-contact-sheet-`));try{let n=await ft({videoPath:t,scratchDir:o,timesMs:a.timesMs,maxWidth:360,hostPlatform:e.hostPlatform??process.platform,...e.signal===void 0?{}:{signal:e.signal}}),i=await Rt(n.frames,e.maxPixels);zt(e.signal);let s=Nt(i,e.changedPixelThreshold??.02),c=Ct({cells:s.cells,maxPixels:e.maxPixels});return Gt(r,c.bytes),{path:r,videoPath:t,durationMs:a.durationMs,width:c.width,height:c.height,sampledFrameCount:a.timesMs.length,decodedFrameCount:n.frames.length,skippedSampleCount:n.skippedSampleCount,changedPixelThreshold:e.changedPixelThreshold??.02,cells:s.cells.map(Ut),...Wt(s,n)}}finally{S.rmSync(o,{recursive:!0,force:!0})}}async function Rt(e,t){let r=[];for(let i of e){let e=await ue(i.path);if(e.width>360)throw new n(`COMMAND_FAILED`,`Frame extraction returned a ${e.width}px-wide frame when the sheet asked for 360px cells`,{reason:K,framePath:i.path,frameWidth:e.width,frameWidthLimit:360});if(e.width*e.height>t)throw new n(`COMMAND_FAILED`,`Frame extraction returned a ${e.width}x${e.height} frame, above the ${t}-pixel budget for the whole sheet`,{reason:K,framePath:i.path,framePixels:e.width*e.height,maxPixels:t});let a=await le(S.readFileSync(i.path),`recording frame`);r.push({timeMs:i.actualTimeMs,image:a})}return r}function zt(t){if(t?.aborted)throw e()}function Bt(e,t){if(Vt(e,t)??t===e)throw new n(`INVALID_ARGS`,`A contact sheet cannot be written over the recording it describes: ${t}`,{reason:`contact_sheet_output_collides_with_input`,videoPath:e,outputPath:t,hint:`Choose a different --out path, or omit it to write beside the recording.`})}function Vt(e,t){let n=Ht(e),r=Ht(t);if(n!==void 0&&r!==void 0)return n.dev===r.dev&&n.ino===r.ino}function Ht(e){try{return S.statSync(e)}catch{return}}function Ut(e){return{timeMs:e.timeMs,changedPixelRatio:e.changedPixelRatio}}function Wt(e,t){let n=[];return t.skippedSampleCount>0&&n.push(`${t.skippedSampleCount} sample times returned no frame, so the sheet covers less of the recording than it asked for`),e.thinned&&n.push(`${e.keptCellCount} changes were found and 24 cells are printed, so the sheet thins evenly across the recording instead of showing every change`),n.length===0?{}:{warning:n.join(`; `)}}function Gt(e,t){try{S.mkdirSync(x.dirname(e),{recursive:!0}),ie({destination:e,contents:t})}catch(t){throw new n(`COMMAND_FAILED`,`Failed to write the contact sheet to ${e}: ${t instanceof Error?t.message:String(t)}`,{reason:`contact_sheet_output_write_failed`,outputPath:e})}}const Kt=async(e,t)=>{if(!t.video)throw new n(`INVALID_ARGS`,`record contact-sheet requires a recording to read`);Jt(t.changedPixelThreshold);let r=await u(e,t.video,{usage:`record contact-sheet`,field:`video`}),i;try{let n=qt(t,t.video,r.path);i=await p(e,n,{field:`path`,ext:`.png`,artifactType:`screen-recording-contact-sheet`});let a=await Lt({videoPath:r.path,outputPath:i.path,maxPixels:e.policy.maxImagePixels,...t.changedPixelThreshold===void 0?{}:{changedPixelThreshold:t.changedPixelThreshold},signal:t.signal??e.signal}),o=await i.publish();return{...a,path:Yt(a.path,o),...o?{artifact:o}:{}}}catch(e){throw await i?.cleanup?.(),e}finally{await r.cleanup?.()}};function qt(e,t,r){if(e.out)return e.out;if(t.kind===`path`)return{kind:`path`,path:x.resolve(me(t.path||r))};throw new n(`INVALID_ARGS`,`record contact-sheet needs an output path when the recording is an uploaded artifact`,{hint:"Pass --out <sheet.png> (CLI) or `out` (Node) to name where the sheet is written."})}function Jt(e){if(e!==void 0&&(!Number.isFinite(e)||e<0||e>1))throw new n(`INVALID_ARGS`,`record contact-sheet needs a changedPixelThreshold between 0 and 1, got ${e}`,{reason:`contact_sheet_threshold_invalid`,changedPixelThreshold:e,hint:`Omit it to use the calibrated default, or pass a share of the frame between 0 and 1.`})}function Yt(e,t){return t?t.kind===`localPath`?t.path:t.clientPath??e:e}const Xt=async(e,t)=>{let r=tn(t.action,`record`),i=r===`start`?e.backend.startRecording:e.backend.stopRecording;if(!i)throw new n(`UNSUPPORTED_OPERATION`,`record ${r} is not supported by this backend`);let a=t.out?await p(e,t.out,{field:`path`,ext:`.mp4`,artifactType:`screen-recording`}):void 0;try{let n=Qt(t,a?.path);return nn(r,await i.call(e.backend,m(e,t),n),await a?.publish())}catch(e){throw await a?.cleanup?.(),e}},Zt=async(e,t)=>{let r=tn(t.action,`trace`),i=r===`start`?e.backend.startTrace:e.backend.stopTrace;if(!i)throw new n(`UNSUPPORTED_OPERATION`,`trace ${r} is not supported by this backend`);let a=t.out?await p(e,t.out,{field:`outPath`,ext:`.trace`,artifactType:`trace-log`}):void 0;try{let n=a?.path?{outPath:a.path}:{};return rn(r,await i.call(e.backend,m(e,t),n),await a?.publish())}catch(e){throw await a?.cleanup?.(),e}};function Qt(e,t){let n={};t&&(n.outPath=t);let r=$t(e.fps);r!==void 0&&(n.fps=r);let i=en(e.quality);return i!==void 0&&(n.quality=i),e.hideTouches!==void 0&&(n.showTouches=e.hideTouches!==!0),n}function $t(e){return e===void 0?void 0:d(e,`fps`,1,60)}function en(e){if(e===void 0)return;let t=i(e);if(t===void 0)throw new n(`INVALID_ARGS`,`quality must be one of: medium, high (legacy numeric values 5-10 are accepted)`);return t}function tn(e,t){if(e===`start`||e===`stop`)return e;throw new n(`INVALID_ARGS`,`${t} action must be start or stop`)}function nn(e,t,n){return{...typeof t.path==`string`?{path:t.path}:{},...typeof t.telemetryPath==`string`?{telemetryPath:t.telemetryPath}:{},...typeof t.warning==`string`?{warning:t.warning}:{},...an(e,t,n,{startKind:`recordingStarted`,stopKind:`recordingStopped`,startMessage:`Recording started`,stopMessage:`Recording stopped`})}}function rn(e,t,n){return{...typeof t.outPath==`string`?{outPath:t.outPath}:{},...an(e,t,n,{startKind:`traceStarted`,stopKind:`traceStopped`,startMessage:`Trace started`,stopMessage:`Trace stopped`})}}function an(e,t,n,r){return{kind:e===`start`?r.startKind:r.stopKind,action:e,...n?{artifact:n}:{},backendResult:t,...g(e===`start`?r.startMessage:r.stopMessage)}}const on={record:Xt,trace:Zt,contactSheet:Kt},sn=async(e,t={})=>{if(!e.backend.pressBack)throw new n(`UNSUPPORTED_OPERATION`,`system.back is not supported by this backend`);let r=t.mode??`in-app`;if(r!==`in-app`&&r!==`system`)throw new n(`INVALID_ARGS`,`system.back mode must be in-app or system`);let i=await e.backend.pressBack(m(e,t),{mode:r}),a=l(i);return{kind:`systemBack`,mode:r,...a?{backendResult:a}:{},...g(`Back`)}},cn=async(e,t={})=>{if(!e.backend.pressHome)throw new n(`UNSUPPORTED_OPERATION`,`system.home is not supported by this backend`);let r=await e.backend.pressHome(m(e,t)),i=l(r);return{kind:`systemHome`,...i?{backendResult:i}:{},...g(`Home`)}},ln=async(e,t)=>{if(!e.backend.pressTvRemote)throw new n(`UNSUPPORTED_OPERATION`,`system.tvRemote is not supported by this backend`);let r=oe(t.button),i=t.durationMs===void 0?void 0:d(t.durationMs,`durationMs`,0,1e4),a=await e.backend.pressTvRemote(m(e,t),{button:r,...i===void 0?{}:{durationMs:i}}),o=l(a);return{kind:`tvRemotePressed`,button:r,...i===void 0?{}:{durationMs:i},...o?{backendResult:o}:{},...g(`Pressed TV remote ${r}`)}},un=async(e,t)=>{if(!e.backend.setOrientation)throw new n(`UNSUPPORTED_OPERATION`,`system.orientation is not supported by this backend`);let r=gn(t.orientation),i=await e.backend.setOrientation(m(e,t),r),a=l(i);return{kind:`systemOrientationSet`,orientation:r,...a?{backendResult:a}:{},...g(`Rotated to ${r}`)}},dn=async(e,t={})=>{if(!e.backend.setKeyboard)throw new n(`UNSUPPORTED_OPERATION`,`system.keyboard is not supported by this backend`);let r=t.action??`status`;if(!se(r))throw new n(`INVALID_ARGS`,`system.keyboard action must be status, get, dismiss, enter, or return`);let i=await e.backend.setKeyboard(m(e,t),{action:r}),a=l(i),o=Tn(i)?i:{};return r===`enter`||r===`return`?vn(o,a):r===`dismiss`?yn(r,o,a):xn(r,o,a)},fn=async(e,t)=>{if(t.action===`read`){if(!e.backend.getClipboard)throw new n(`UNSUPPORTED_OPERATION`,`system.clipboard read is not supported by this backend`);let r=await e.backend.getClipboard(m(e,t));return{kind:`clipboardText`,action:`read`,text:typeof r==`string`?r:r.text}}if(t.action!==`write`)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(typeof t.text!=`string`)throw new n(`INVALID_ARGS`,`system.clipboard write requires text`);let r=await e.backend.setClipboard(m(e,t),t.text),i=l(r);return{kind:`clipboardUpdated`,action:`write`,textLength:Array.from(t.text).length,...i?{backendResult:i}:{},...g(`Clipboard updated`)}},pn=async(e,t={})=>{if(!e.backend.openSettings)throw new n(`UNSUPPORTED_OPERATION`,`system.settings is not supported by this backend`);let r=C(t.target,`target`),i=await e.backend.openSettings(m(e,t),r),a=l(i);return{kind:`settingsOpened`,...r?{target:r}:{},...a?{backendResult:a}:{},...g(r?`Opened settings: ${r}`:`Opened settings`)}},mn=async(e,t={})=>{if(!e.backend.handleAlert)throw new n(`UNSUPPORTED_OPERATION`,`system.alert is not supported by this backend`);let r=t.action??`get`;if(r!==`get`&&r!==`accept`&&r!==`dismiss`&&r!==`wait`)throw new n(`INVALID_ARGS`,`system.alert action must be get, accept, dismiss, or wait`);let i=t.timeoutMs===void 0?void 0:d(t.timeoutMs,`timeoutMs`,0,12e4);return _n(r,await e.backend.handleAlert(m(e,t),r,{timeoutMs:i}))},hn=async(e,t={})=>{if(!e.backend.openAppSwitcher)throw new n(`UNSUPPORTED_OPERATION`,`system.appSwitcher is not supported by this backend`);let r=await e.backend.openAppSwitcher(m(e,t)),i=l(r);return{kind:`appSwitcherOpened`,...i?{backendResult:i}:{},...g(`Opened app switcher`)}};function gn(e){switch(e){case`portrait`:case`portrait-upside-down`:case`landscape-left`:case`landscape-right`:return e;default:throw new n(`INVALID_ARGS`,`system.orientation must be portrait, portrait-upside-down, landscape-left, or landscape-right`)}}function _n(e,t){return e===`get`?Sn(t):e===`wait`?Cn(t):wn(e,t)}function vn(e,t){return{kind:`keyboardEnterPressed`,action:`enter`,state:e,...t?{backendResult:t}:{},...g(`Keyboard enter pressed`)}}function yn(e,t,n){return{kind:`keyboardDismissed`,action:e,state:t,...n?{backendResult:n}:{},...g(bn(t))}}function bn(e){return e.dismissed===!1?`Keyboard already hidden`:e.mechanism===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`}function xn(e,t,n){return{kind:`keyboardState`,action:e,state:t,...n?{backendResult:n}:{}}}function Sn(e){if(e.kind!==`alertStatus`)throw new n(`COMMAND_FAILED`,`system.alert get returned an invalid backend result`);return{kind:`alertStatus`,action:`get`,alert:e.alert}}function Cn(e){if(e.kind!==`alertWait`)throw new n(`COMMAND_FAILED`,`system.alert wait returned an invalid backend result`);return{kind:`alertWait`,action:`wait`,alert:e.alert,...e.waitedMs===void 0?{}:{waitedMs:e.waitedMs},...e.timedOut===void 0?{}:{timedOut:e.timedOut},...g(e.alert?`Alert visible`:`Alert wait timed out`)}}function wn(e,t){if(t.kind!==`alertHandled`)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}:{},...g(t.handled?`Alert ${e}ed`:`No alert handled`)}}function Tn(e){return!!(e&&typeof e==`object`)}const En={back:sn,home:cn,orientation:un,keyboard:dn,clipboard:fn,settings:pn,alert:mn,appSwitcher:hn,tvRemote:ln};function Dn(e){return{capture:ee(e),selectors:f(e),interactions:c(e),system:h(En,e),apps:qe(e),admin:h(Ke,e),recording:h(on,e),observability:h(dt,e)}}function On(e){let t=te(e);return{...t,...Dn(t)}}export{On as createAgentDevice,s as createMemorySessionStore,o as localCommandPolicy,a as restrictedCommandPolicy};
1
+ import{F as e,G as t,N as n,V as r}from"./sdk-contracts.js";import{i}from"./recording-export-quality.js";import{C as a,E as o,O as s,T as c,a as l,b as u,i as d,o as f,r as p,t as ee,w as te,x as m,y as h}from"./runtime.js";import{r as g}from"./success-text.js";import{n as ne,t as re}from"./app-inventory.js";import"./app-inventory-contract.js";import{k as ie}from"./owner-identity.js";import{c as ae}from"./exec.js";import"./file.js";import{r as oe}from"./tv-remote.js";import"./command.js";import{r as se}from"./version.js";import{t as ce}from"./keyboard-actions.js";import{i as le}from"./quality-warnings.js";import{r as _}from"./png.js";import{i as ue}from"./png-worker-client.js";import{t as de}from"./png-size.js";import{i as v,n as fe,r as pe}from"./screenshot-overlay-draw.js";import{t as me}from"./png-encode.js";import{r as y}from"./artifact-paths.js";import{t as he}from"./mp4-duration.js";import{c as b,o as ge,r as _e,s as ve}from"./video.js";import x from"node:path";import S from"node:fs";import ye from"node:os";function C(e,t){if(e!==void 0)return w(e,t)}function w(e,t){let r=e?.trim();if(!r)throw new n(`INVALID_ARGS`,`${t} must be a non-empty string`);return r}const be=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(m(e,t),t.filter)}},xe=async(e,t={})=>{if(!e.backend.bootDevice)throw new n(`UNSUPPORTED_OPERATION`,`admin.boot is not supported by this backend`);let r=ke(t.target),i=await e.backend.bootDevice(m(e,t),r),a=u(i);return{kind:`deviceBooted`,...r?{target:r}:{},...a?{backendResult:a}:{},...g(`Booted device`)}},Se=async(e,t={})=>{if(!e.backend.shutdownDevice)throw new n(`UNSUPPORTED_OPERATION`,`admin.shutdown is not supported by this backend`);let r=ke(t.target),i=await e.backend.shutdownDevice(m(e,t),r),a=u(i);return{kind:`deviceShutdown`,...r?{target:r}:{},...a?{backendResult:a}:{},...g(`Shutdown device`)}},Ce=async(e,t)=>await T(e,t,`install`),we=async(e,t)=>await T(e,t,`reinstall`),Te=async(e,t)=>await T(e,t,`installFromSource`);async function T(e,t,r){let i=r===`reinstall`?`reinstallApp`:`installApp`,a=e.backend[i];if(!a)throw new n(`UNSUPPORTED_OPERATION`,`admin.${r} is not supported by this backend`);let o=`app`in t&&t.app!==void 0?w(t.app,`app`):void 0;if(r!==`installFromSource`&&!o)throw new n(`INVALID_ARGS`,`admin.${r} requires app`);let s=m(e,t),c=await Ee(e,s,t.source);try{let t=await a.call(e.backend,s,{...o?{app:o}:{},source:c.source});return Ae(r,o,c.source,t)}finally{await c.cleanup?.()}}async function Ee(e,t,n){let r=await De(e,E(n));try{return{source:E(e.backend.resolveInstallSource?await e.backend.resolveInstallSource(t,r.source):r.source),...r.cleanup?{cleanup:r.cleanup}:{}}}catch(e){if(r.cleanup)try{await r.cleanup()}catch{}throw e}}async function De(e,t){if(t.kind===`url`)return{source:t};let n=await d(e,t,{usage:`admin.install`,field:`source`});return{source:{kind:`path`,path:n.path},...n.cleanup?{cleanup:n.cleanup}:{}}}function E(e){if(!e||typeof e!=`object`)throw new n(`INVALID_ARGS`,`install source is required`);if(e.kind===`path`)return{kind:`path`,path:w(e.path,`source.path`)};if(e.kind===`uploadedArtifact`)return{kind:`uploadedArtifact`,id:w(e.id,`source.id`)};if(e.kind===`url`){let t=w(e.url,`source.url`);return Oe(t),{kind:`url`,url:t}}throw new n(`INVALID_ARGS`,`install source kind must be path, uploadedArtifact, or url`)}function Oe(e){let t;try{t=new URL(e)}catch{throw new n(`INVALID_ARGS`,`Invalid install source URL: ${e}`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new n(`INVALID_ARGS`,`Install source URL must use http or https`)}function ke(e){if(!e)return;let t=C(e.id,`target.id`),n=C(e.name,`target.name`),r={...t?{id:t}:{},...n?{name:n}:{},...e.platform?{platform:e.platform}:{},...e.target?{target:e.target}:{},...e.headless===void 0?{}:{headless:e.headless}};return Object.keys(r).length>0?r:void 0}function Ae(e,t,n,r){let i=u(r),a=e===`reinstall`?`appReinstalled`:e===`installFromSource`?`appInstalledFromSource`:`appInstalled`,o=D(r,`appName`),s=D(r,`appId`),c=D(r,`bundleId`),l=D(r,`packageName`),d=D(r,`launchTarget`),f=D(r,`installablePath`),p=D(r,`archivePath`);return{kind:a,...t?{app:t}:{},source:n,...s?{appId:s}:{},...o?{appName:o}:{},...c?{bundleId:c}:{},...l?{packageName:l}:{},...d?{launchTarget:d}:{},...f?{installablePath:f}:{},...p?{archivePath:p}:{},...i?{backendResult:i}:{},...g(`${e===`reinstall`?`Reinstalled`:`Installed`}: ${o??d??t??je(n)}`)}}function D(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function je(e){return e.kind===`path`?e.path:e.kind===`uploadedArtifact`?e.id:e.url}const Me=/^[A-Za-z0-9_.:-]{1,64}$/,Ne=async(e,t)=>{if(!e.backend.openApp)throw new n(`UNSUPPORTED_OPERATION`,`apps.open is not supported by this backend`);let r=ze(t),i=await e.backend.openApp(k(e,t),r,{launchArgs:t.launchArgs,relaunch:t.relaunch}),a=u(i);return{kind:`appOpened`,target:r,relaunch:t.relaunch===!0,...a?{backendResult:a}:{},...g(`Opened: ${Ve(r)}`)}},Pe=async(e,t={})=>{if(!e.backend.closeApp)throw new n(`UNSUPPORTED_OPERATION`,`apps.close is not supported by this backend`);let r=C(t.app,`app`),i=await e.backend.closeApp(k(e,t),r),a=u(i);return{kind:`appClosed`,...r?{app:r}:{},...a?{backendResult:a}:{},...g(r?`Closed: ${r}`:`Closed app`)}},Fe=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(k(e,t),re(t.filter))}},Ie=async(e,t)=>{if(!e.backend.getAppState)throw new n(`UNSUPPORTED_OPERATION`,`apps.state is not supported by this backend`);let r=w(t.app,`app`);return{kind:`appState`,app:r,state:await e.backend.getAppState(k(e,t),r)}},Le=async(e,t)=>{if(!e.backend.pushFile)throw new n(`UNSUPPORTED_OPERATION`,`apps.push is not supported by this backend`);let r=w(t.app,`app`),i=await He(e,t.input);try{let n=await e.backend.pushFile(k(e,t),i.backendInput,r),a=u(n);return{kind:`appPushed`,app:r,inputKind:i.inputKind,...a?{backendResult:a}:{},...g(`Pushed to ${r}`)}}finally{await i.cleanup?.()}},Re=async(e,t)=>{if(!e.backend.triggerAppEvent)throw new n(`UNSUPPORTED_OPERATION`,`apps.triggerEvent is not supported by this backend`);let r=Ue(t.name);We(t.payload,`apps.triggerEvent payload for "${r}"`);let i=await e.backend.triggerAppEvent(k(e,t),{name:r,...t.payload?{payload:t.payload}:{}}),a=u(i);return{kind:`appEventTriggered`,name:r,...t.payload?{payload:t.payload}:{},...a?{backendResult:a}:{},...g(`Triggered app event: ${r}`)}};function ze(e){let t=C(e.app,`app`),r=C(e.appId,`appId`),i=C(e.bundleId,`bundleId`),a=C(e.packageName,`packageName`),o=C(e.url,`url`),s=C(e.activity,`activity`),c={...t?{app:t}:{},...r?{appId:r}:{},...i?{bundleId:i}:{},...a?{packageName:a}:{},...o?{url:o}:{},...s?{activity:s}:{}};if(!Be(c))throw new n(`INVALID_ARGS`,`apps.open requires app, appId, bundleId, packageName, url, or activity`);return c}function Be(e){return!!(e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity)}function Ve(e){return e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity??`app`}async function He(e,t){if(!t||typeof t!=`object`)throw new n(`INVALID_ARGS`,`apps.push requires an input`);if(t.kind===`json`)return O(t.payload,`apps.push JSON payload`,8192),{backendInput:{kind:`json`,payload:t.payload},inputKind:`json`};let r=await d(e,t,{usage:`apps.push`,field:`input`});return{backendInput:{kind:`file`,path:r.path},inputKind:`file`,...r.cleanup?{cleanup:r.cleanup}:{}}}function Ue(e){let t=w(e,`name`);if(!Me.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}function We(e,t){e!==void 0&&O(e,t,8192)}function O(e,t,r){if(Ge(e,t),Buffer.byteLength(Ke(e,t),`utf8`)>r)throw new n(`INVALID_ARGS`,`${t} exceeds ${r} bytes`)}function Ge(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`${t} must be a JSON object`)}function Ke(e,t){try{let r=JSON.stringify(e);if(typeof r!=`string`)throw new n(`INVALID_ARGS`,`${t} must be JSON-serializable`);return r}catch{throw new n(`INVALID_ARGS`,`${t} must be JSON-serializable`)}}function k(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}const A={open:Ne,close:Pe,list:Fe,state:Ie,push:Le,triggerEvent:Re},qe={devices:be,boot:xe,shutdown:Se,install:Ce,reinstall:we,installFromSource:Te};function Je(e){return{...h(A,e),list:(t={})=>A.list(e,{...t,filter:ne(t.filter)})}}const Ye=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i,Xe=/\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/g;function j(e){let t=!1,n=e;return n=n.replaceAll(/(authorization|token|secret|password|passwd|api[-_]?key)=([^&\s]+)/gi,(e,n)=>(t=!0,`${String(n)}=[REDACTED]`)),n=n.replaceAll(/("(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)"\s*:\s*")([^"]*)(")/gi,(e,n,r,i)=>(t=!0,`${String(n)}[REDACTED]${String(i)}`)),n=n.replaceAll(/\b(Bearer\s+)([^\s",;]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(/((?:authorization|cookie|token|secret|password|passwd|api[-_]?key)\s*[:=]\s*)([^\s,;&]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(Xe,()=>(t=!0,`[REDACTED]`)),n=Qe(n,()=>{t=!0}),{value:n,redacted:t}}function Ze(e){try{let t=new URL(e),n=$e(t);return(t.username||t.password)&&(t.username=`REDACTED`,t.password=`REDACTED`,n=!0),{value:t.toString(),redacted:n}}catch{return}}function Qe(e,t){return/(https?:\/\/|token|secret|password|authorization|cookie|api[-_]?key)/i.test(e)?e.replaceAll(/https?:\/\/[^\s"'<>)]+/gi,e=>{let n=Ze(e);return n?(n.redacted&&t(),n.value):e}):e}function $e(e){let t=!1;for(let n of Array.from(e.searchParams.keys()))Ye.test(n)&&(e.searchParams.set(n,`[REDACTED]`),t=!0);return t}const M=2048,N=4096,P=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i;function et(e){let t=e.redacted===!0;return{kind:`diagnosticsLogs`,entries:e.entries.map(e=>{let n=z(e.message,N),r=L(e.metadata);return t||=n.redacted||r.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.level?{level:e.level}:{},message:n.value??``,...e.source?{source:e.source}:{},...r.value?{metadata:r.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function tt(e,t){let n=e.redacted===!0;return{kind:`diagnosticsNetwork`,entries:e.entries.map(e=>{let r=e.url?rt(e.url):void 0,i=t===`headers`||t===`all`?F(e.requestHeaders):void 0,a=t===`headers`||t===`all`?F(e.responseHeaders):void 0,o=t===`body`||t===`all`?I(e.requestBody):void 0,s=t===`body`||t===`all`?I(e.responseBody):void 0,c=L(e.metadata);return n||=(r?.redacted??!1)||(i?.redacted??!1)||(a?.redacted??!1)||(o?.redacted??!1)||(s?.redacted??!1)||c.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.method?{method:e.method}:{},...r?{url:r.value}:{},...e.status===void 0?{}:{status:e.status},...e.durationMs===void 0?{}:{durationMs:e.durationMs},...i?.value?{requestHeaders:i.value}:{},...a?.value?{responseHeaders:a.value}:{},...o?.value===void 0?{}:{requestBody:o.value},...s?.value===void 0?{}:{responseBody:s.value},...c.value?{metadata:c.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:n,...e.notes?{notes:e.notes}:{}}}function nt(e){let t=e.redacted===!0;return{kind:`diagnosticsPerf`,metrics:e.metrics.map(e=>{let n=z(e.message,N),r=L(e.metadata);return t||=n.redacted||r.redacted,{name:e.name,...e.value===void 0?{}:{value:e.value},...e.unit?{unit:e.unit}:{},...e.status?{status:e.status}:{},...n.value===void 0?{}:{message:n.value},...r.value?{metadata:r.value}:{}}}),...e.startedAt?{startedAt:e.startedAt}:{},...e.endedAt?{endedAt:e.endedAt}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function F(e){if(!e)return{redacted:!1};let t=!1,n={};for(let[r,i]of Object.entries(e))if(P.test(r))n[r]=`[REDACTED]`,t=!0;else{let e=z(i,M);n[r]=e.value??``,t||=e.redacted}return{value:n,redacted:t}}function rt(e){return Ze(e)??z(e,M)}function I(e){return e===void 0?{redacted:!1}:it(e)??z(e,M)}function it(e){try{let t=R(JSON.parse(e),j);return B(JSON.stringify(t.value),M,t.redacted)}catch{return}}function L(e){return R(e,e=>z(e,M))}function R(e,t){if(e===void 0)return{redacted:!1};if(typeof e==`string`)return t(e);if(!e||typeof e!=`object`)return{value:e,redacted:!1};if(Array.isArray(e)){let n=!1;return{value:e.map(e=>{let r=R(e,t);return n||=r.redacted,r.value}),redacted:n}}let n=!1,r={};for(let[i,a]of Object.entries(e)){if(P.test(i)){r[i]=`[REDACTED]`,n=!0;continue}let e=R(a,t);r[i]=e.value,n||=e.redacted}return{value:r,redacted:n}}function z(e,t){if(e===void 0)return{redacted:!1};let n=j(e);return B(n.value,t,n.redacted)}function B(e,t,n){if(e===void 0)return{redacted:n};let r=e;return r.length>t&&(r=`${r.slice(0,t)}...[truncated]`,n=!0),{value:r,redacted:n}}const at=async(e,t={})=>{if(!e.backend.readLogs)throw new n(`UNSUPPORTED_OPERATION`,`diagnostics.logs is not supported by this backend`);return et(await e.backend.readLogs(await V(e,t),ct(t)))},ot=async(e,t={})=>{if(!e.backend.dumpNetwork)throw new n(`UNSUPPORTED_OPERATION`,`diagnostics.network is not supported by this backend`);let r=lt(t);return tt(await e.backend.dumpNetwork(await V(e,t),r),r.include??`summary`)},st=async(e,t={})=>{if(!e.backend.measurePerf)throw new n(`UNSUPPORTED_OPERATION`,`diagnostics.perf is not supported by this backend`);return nt(await e.backend.measurePerf(await V(e,t),ut(t)))};async function V(e,t){let n=m(e,t),r=t.session?await e.sessions.get(t.session):void 0;return{...n,...t.appId??r?.appId?{appId:t.appId??r?.appId}:{},...t.appBundleId??r?.appBundleId?{appBundleId:t.appBundleId??r?.appBundleId}:{}}}function ct(e){return{...H(e,100,500,`logs limit`),...e.levels===void 0?{}:{levels:W(e.levels,`levels`)},...e.search===void 0?{}:{search:w(e.search,`search`)},...e.source===void 0?{}:{source:w(e.source,`source`)}}}function lt(e){return{...H(e,25,200,`network limit`),include:dt(e.include)}}function ut(e){return{...U(e),...e.sampleMs===void 0?{}:{sampleMs:s(e.sampleMs,`sampleMs`,100,6e4)},...e.metrics===void 0?{}:{metrics:W(e.metrics,`metrics`,20)}}}function H(e,t,n,r){return{...U(e),...e.cursor===void 0?{}:{cursor:w(e.cursor,`cursor`)},limit:e.limit===void 0?t:s(e.limit,r,1,n)}}function U(e){return{...e.since===void 0?{}:{since:w(e.since,`since`)},...e.until===void 0?{}:{until:w(e.until,`until`)}}}function dt(e){if(e===void 0)return`summary`;if(e===`summary`||e===`headers`||e===`body`||e===`all`)return e;throw new n(`INVALID_ARGS`,`network include must be summary, headers, body, or all`)}function W(e,t,r=50){if(!Array.isArray(e))throw new n(`INVALID_ARGS`,`${t} must be an array of strings`);if(e.length>r)throw new n(`INVALID_ARGS`,`${t} must contain at most ${r} entries`);return e.map((e,n)=>w(e,`${t}[${n}]`))}const ft={logs:at,network:ot,perf:st},G=`contact_sheet_frame_extraction_failed`,K=`contact_sheet_no_frames`;function q(e=process.platform){if(e!==`darwin`)throw new n(`UNSUPPORTED_OPERATION`,`Contact sheets can only be built on macOS hosts, which is where the frame decoder runs`,{reason:`contact_sheet_unsupported_host`,hostPlatform:e,hint:`Run this command on the macOS host that recorded the clip, or read the video artifact itself.`})}async function pt(e){if(q(e.hostPlatform??process.platform),e.timesMs.length===0)throw new n(`COMMAND_FAILED`,`Contact sheet sampling requested no frames`,{reason:K,videoPath:e.videoPath});Q(e.signal);let t=await vt(e);Q(e.signal);let r;try{r=await ae(t,[`--input`,e.videoPath,`--output-dir`,e.scratchDir,`--times`,e.timesMs.join(`,`),`--max-width`,String(e.maxWidth)],{timeoutMs:9e4,env:ge(),allowFailure:!0,...e.signal===void 0?{}:{signal:e.signal}})}catch(t){X(t,e.videoPath,`Failed to run the frame decoder`)}if(r.exitCode!==0)throw new n(`COMMAND_FAILED`,`Failed to extract frames from the recording: ${_t(r.stderr)||`exit ${r.exitCode}`}`,{reason:G,videoPath:e.videoPath,exitCode:r.exitCode});let i=mt(r.stdout,e.videoPath,e.scratchDir,e.timesMs.length);if(i.frames.length===0)throw new n(`COMMAND_FAILED`,`The recording returned no decodable frames for a contact sheet`,{reason:K,videoPath:e.videoPath,skippedSampleCount:i.skippedSampleCount});return i}function mt(e,t,n,r){let i;try{i=JSON.parse(e)}catch(e){throw Y(t,`invalid manifest: ${String(e)}`)}let a=Z(i).frames;if(!Array.isArray(a))throw Y(t,`manifest has no frames array`);let o=Z(i).skipped;if(a.length>r)throw Y(t,`returned ${a.length} frames for ${r} requested samples`);let s=a.flatMap(e=>{let r=Z(e),i=ht(r.path),a=gt(r.actualTimeMs);if(i===void 0||a===void 0||a<0)throw Y(t,`frame entry is missing a path or presentation time`);let o=x.resolve(n,x.basename(i));return S.existsSync(o)?[{requestedTimeMs:gt(r.requestedTimeMs)??a,actualTimeMs:a,path:o}]:[]});return{frames:s.sort((e,t)=>e.actualTimeMs-t.actualTimeMs),skippedSampleCount:Math.max(Array.isArray(o)?o.length:0,r-s.length)}}function J(e,t,r){return new n(`COMMAND_FAILED`,e,{reason:G,videoPath:t},r)}function Y(e,t){return J(`Frame extraction returned an unreadable manifest: ${t}`,e)}function X(e,i,a){throw t(e)||e instanceof n&&e.code===`COMMAND_FAILED`&&e.details?.reason?e:J(`${a} for ${i}: ${r(e)}`,i,e)}function Z(e){return typeof e==`object`&&e?e:{}}function ht(e){return typeof e==`string`&&e!==``?e:void 0}function gt(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function _t(e){return(e.trim().split(`
2
+ `).pop()??``).trim()}async function vt(e){try{return await ve({sourcePath:b(`recording-frames.swift`,se()),extraSourcePaths:[b(`RecordingExportSupport.swift`,se())],cacheName:`recording-frames`,timeoutMs:12e4})}catch(t){X(t,e.videoPath,`Could not build the frame decoder`)}}function Q(t){if(t?.aborted)throw e()}function yt(e,t){if(e===void 0||!Number.isFinite(e)||e<0)throw new n(`COMMAND_FAILED`,`Cannot plan a contact sheet: the video timeline of ${t} could not be read`,{reason:`contact_sheet_duration_unknown`,videoPath:t,hint:`Retry once the recording finished finalizing; a clip whose container is still being written has no readable duration.`});if(e<=250)return{durationMs:e,timesMs:e>0?[0,Math.round(e)]:[0]};let r=Math.min(48,Math.floor(e/250)+1),i=e/(r-1);return{durationMs:e,timesMs:Array.from({length:r},(e,t)=>Math.round(t*i))}}const bt=[360,320,280,240,200,160],xt=[255,255,255,255],St=[17,24,39,255],$=pe(2)+8;function Ct(e){let{cells:t}=e;if(t.length===0)throw new n(`COMMAND_FAILED`,`Contact sheet has no cells to render`);let r=Tt(t[0].image.height/Math.max(1,t[0].image.width),t.length,e),i=Ot(r.width,r.height,St);return t.forEach((e,t)=>{let n=t%r.columns,a=Math.floor(t/r.columns);wt(i,8+n*(r.cellWidth+8),8+a*($+r.cellHeight+8),e,r.cellWidth,r.cellHeight)}),{bytes:me(i.data,r.width,r.height,4),width:r.width,height:r.height,cellWidth:r.cellWidth}}function wt(e,t,n,r,i,a){fe(e,{x:t+4,y:n+4,text:jt(r.timeMs),color:xt,scale:2}),kt(e,le(At(r.image),i,a),t,n+$)}function Tt(e,t,r){let i=Et(e,t,r.maxPixels);if(i)return i;let a=Dt(e,t,160);throw new n(`COMMAND_FAILED`,`Contact sheet would be ${a.width*a.height} pixels, above the configured maxImagePixels limit of ${r.maxPixels}`,{reason:`contact_sheet_pixel_budget_exceeded`,cellCount:r.cells.length,maxPixels:r.maxPixels,hint:`Shorten the recording or raise the command policy maxImagePixels limit.`})}function Et(e,t,n){for(let r of bt){let i=Dt(e,t,r);if(i.width*i.height<=n)return i}}function Dt(e,t,n){let r=Math.min(4,t),i=Math.ceil(t/r),a=Math.max(1,Math.round(n*e));return{columns:r,cellWidth:n,cellHeight:a,width:16+r*n+(r-1)*8,height:16+i*($+a)+(i-1)*8}}function Ot(e,t,n){let r=new _.PNG({width:e,height:t});for(let i=0;i<t;i+=1)for(let t=0;t<e;t+=1)v(r,t,i,n);return r}function kt(e,t,n,r){for(let i=0;i<t.height;i+=1)for(let a=0;a<t.width;a+=1){let o=(i*t.width+a)*4;v(e,n+a,r+i,[t.data[o],t.data[o+1],t.data[o+2],t.data[o+3]])}}function At(e){let t=new _.PNG({width:e.width,height:e.height});return Buffer.from(e.data.buffer,e.data.byteOffset,e.data.byteLength).copy(t.data),t}function jt(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=Math.floor(e%1e3);return`${[n,r,i].map(e=>String(e).padStart(2,`0`)).join(`:`)}.${String(a).padStart(3,`0`)}`}function Mt(e,t){if(e.width!==t.width||e.height!==t.height)return{status:`dimension_mismatch`};let n=e.width*e.height;if(n===0)return{status:`compared`,changedPixelRatio:0};if(e.data.length!==t.data.length)return{status:`dimension_mismatch`};let r=0;for(let n=0;n+3<e.data.length;n+=4)(e.data[n]!==t.data[n]||e.data[n+1]!==t.data[n+1]||e.data[n+2]!==t.data[n+2])&&(r+=1);return{status:`compared`,changedPixelRatio:r/n}}function Nt(e,t=.02,n=24){let r=[],i;for(let n of e){let e=i?Ft(i,n.image):1;e<t||(r.push({timeMs:n.timeMs,changedPixelRatio:e,image:n.image}),i=n.image)}Pt(r,e);let a=r.length>n?It(r,n):r;return{cells:a,keptCellCount:r.length,thinned:a.length<r.length}}function Pt(e,t){let n=t.at(-1);if(!n)return;let r=e.at(-1);!r||r.timeMs===n.timeMs||e.push({timeMs:n.timeMs,changedPixelRatio:Ft(r.image,n.image),image:n.image})}function Ft(e,t){let n=Mt(e,t);return n.status===`compared`?n.changedPixelRatio:1}function It(e,t){if(t<=1)return[e.at(-1)];let n=(e.length-1)/(t-1);return Array.from({length:t},(t,r)=>e[Math.round(r*n)])}async function Lt(e){q(e.hostPlatform??process.platform);let t=x.resolve(e.videoPath),r=x.resolve(e.outputPath??y(t));Bt(t,r);let i=await _e(t);if(i!==`mp4`)throw new n(`INVALID_ARGS`,i===`webm`?`Contact sheets need an MP4 recording; ${t} is WebM, whose frames this decoder does not read`:`Contact sheets need an MP4 recording; ${t} is not a readable MP4`,{reason:`contact_sheet_container_unsupported`,videoPath:t,container:i??`unknown`,hint:`Re-record on a backend that exports MP4, or pass the MP4 artifact the recording produced.`});let a=yt(he(t),t),o=S.mkdtempSync(x.join(ye.tmpdir(),`agent-device-contact-sheet-`));try{let n=await pt({videoPath:t,scratchDir:o,timesMs:a.timesMs,maxWidth:360,hostPlatform:e.hostPlatform??process.platform,...e.signal===void 0?{}:{signal:e.signal}}),i=await Rt(n.frames,e.maxPixels);zt(e.signal);let s=Nt(i,e.changedPixelThreshold??.02),c=Ct({cells:s.cells,maxPixels:e.maxPixels});return Gt(r,c.bytes),{path:r,videoPath:t,durationMs:a.durationMs,width:c.width,height:c.height,sampledFrameCount:a.timesMs.length,decodedFrameCount:n.frames.length,skippedSampleCount:n.skippedSampleCount,changedPixelThreshold:e.changedPixelThreshold??.02,cells:s.cells.map(Ut),...Wt(s,n)}}finally{S.rmSync(o,{recursive:!0,force:!0})}}async function Rt(e,t){let r=[];for(let i of e){let e=await de(i.path);if(e.width>360)throw new n(`COMMAND_FAILED`,`Frame extraction returned a ${e.width}px-wide frame when the sheet asked for 360px cells`,{reason:G,framePath:i.path,frameWidth:e.width,frameWidthLimit:360});if(e.width*e.height>t)throw new n(`COMMAND_FAILED`,`Frame extraction returned a ${e.width}x${e.height} frame, above the ${t}-pixel budget for the whole sheet`,{reason:G,framePath:i.path,framePixels:e.width*e.height,maxPixels:t});let a=await ue(S.readFileSync(i.path),`recording frame`);r.push({timeMs:i.actualTimeMs,image:a})}return r}function zt(t){if(t?.aborted)throw e()}function Bt(e,t){if(Vt(e,t)??t===e)throw new n(`INVALID_ARGS`,`A contact sheet cannot be written over the recording it describes: ${t}`,{reason:`contact_sheet_output_collides_with_input`,videoPath:e,outputPath:t,hint:`Choose a different --out path, or omit it to write beside the recording.`})}function Vt(e,t){let n=Ht(e),r=Ht(t);if(n!==void 0&&r!==void 0)return n.dev===r.dev&&n.ino===r.ino}function Ht(e){try{return S.statSync(e)}catch{return}}function Ut(e){return{timeMs:e.timeMs,changedPixelRatio:e.changedPixelRatio}}function Wt(e,t){let n=[];return t.skippedSampleCount>0&&n.push(`${t.skippedSampleCount} sample times returned no frame, so the sheet covers less of the recording than it asked for`),e.thinned&&n.push(`${e.keptCellCount} changes were found and 24 cells are printed, so the sheet thins evenly across the recording instead of showing every change`),n.length===0?{}:{warning:n.join(`; `)}}function Gt(e,t){try{S.mkdirSync(x.dirname(e),{recursive:!0}),ie({destination:e,contents:t})}catch(t){throw new n(`COMMAND_FAILED`,`Failed to write the contact sheet to ${e}: ${t instanceof Error?t.message:String(t)}`,{reason:`contact_sheet_output_write_failed`,outputPath:e})}}const Kt=async(e,t)=>{if(!t.video)throw new n(`INVALID_ARGS`,`record contact-sheet requires a recording to read`);Jt(t.changedPixelThreshold);let r=await d(e,t.video,{usage:`record contact-sheet`,field:`video`}),i;try{let n=qt(t,t.video,r.path);i=await p(e,n,{field:`path`,ext:`.png`,artifactType:`screen-recording-contact-sheet`});let a=await Lt({videoPath:r.path,outputPath:i.path,maxPixels:e.policy.maxImagePixels,...t.changedPixelThreshold===void 0?{}:{changedPixelThreshold:t.changedPixelThreshold},signal:t.signal??e.signal}),o=await i.publish();return{...a,path:Yt(a.path,o),...o?{artifact:o}:{}}}catch(e){throw await i?.cleanup?.(),e}finally{await r.cleanup?.()}};function qt(e,t,r){if(e.out)return e.out;if(t.kind===`path`)return{kind:`path`,path:x.resolve(y(t.path||r))};throw new n(`INVALID_ARGS`,`record contact-sheet needs an output path when the recording is an uploaded artifact`,{hint:"Pass --out <sheet.png> (CLI) or `out` (Node) to name where the sheet is written."})}function Jt(e){if(e!==void 0&&(!Number.isFinite(e)||e<0||e>1))throw new n(`INVALID_ARGS`,`record contact-sheet needs a changedPixelThreshold between 0 and 1, got ${e}`,{reason:`contact_sheet_threshold_invalid`,changedPixelThreshold:e,hint:`Omit it to use the calibrated default, or pass a share of the frame between 0 and 1.`})}function Yt(e,t){return t?t.kind===`localPath`?t.path:t.clientPath??e:e}const Xt=async(e,t)=>{let r=tn(t.action,`record`),i=r===`start`?e.backend.startRecording:e.backend.stopRecording;if(!i)throw new n(`UNSUPPORTED_OPERATION`,`record ${r} is not supported by this backend`);let a=t.out?await p(e,t.out,{field:`path`,ext:`.mp4`,artifactType:`screen-recording`}):void 0;try{let n=Qt(t,a?.path);return nn(r,await i.call(e.backend,m(e,t),n),await a?.publish())}catch(e){throw await a?.cleanup?.(),e}},Zt=async(e,t)=>{let r=tn(t.action,`trace`),i=r===`start`?e.backend.startTrace:e.backend.stopTrace;if(!i)throw new n(`UNSUPPORTED_OPERATION`,`trace ${r} is not supported by this backend`);let a=t.out?await p(e,t.out,{field:`outPath`,ext:`.trace`,artifactType:`trace-log`}):void 0;try{let n=a?.path?{outPath:a.path}:{};return rn(r,await i.call(e.backend,m(e,t),n),await a?.publish())}catch(e){throw await a?.cleanup?.(),e}};function Qt(e,t){let n={};t&&(n.outPath=t);let r=$t(e.fps);r!==void 0&&(n.fps=r);let i=en(e.quality);return i!==void 0&&(n.quality=i),e.hideTouches!==void 0&&(n.showTouches=e.hideTouches!==!0),n}function $t(e){return e===void 0?void 0:s(e,`fps`,1,60)}function en(e){if(e===void 0)return;let t=i(e);if(t===void 0)throw new n(`INVALID_ARGS`,`quality must be one of: medium, high (legacy numeric values 5-10 are accepted)`);return t}function tn(e,t){if(e===`start`||e===`stop`)return e;throw new n(`INVALID_ARGS`,`${t} action must be start or stop`)}function nn(e,t,n){return{...typeof t.path==`string`?{path:t.path}:{},...typeof t.telemetryPath==`string`?{telemetryPath:t.telemetryPath}:{},...typeof t.warning==`string`?{warning:t.warning}:{},...an(e,t,n,{startKind:`recordingStarted`,stopKind:`recordingStopped`,startMessage:`Recording started`,stopMessage:`Recording stopped`})}}function rn(e,t,n){return{...typeof t.outPath==`string`?{outPath:t.outPath}:{},...an(e,t,n,{startKind:`traceStarted`,stopKind:`traceStopped`,startMessage:`Trace started`,stopMessage:`Trace stopped`})}}function an(e,t,n,r){return{kind:e===`start`?r.startKind:r.stopKind,action:e,...n?{artifact:n}:{},backendResult:t,...g(e===`start`?r.startMessage:r.stopMessage)}}const on={record:Xt,trace:Zt,contactSheet:Kt},sn=async(e,t={})=>{if(!e.backend.pressBack)throw new n(`UNSUPPORTED_OPERATION`,`system.back is not supported by this backend`);let r=t.mode??`in-app`;if(r!==`in-app`&&r!==`system`)throw new n(`INVALID_ARGS`,`system.back mode must be in-app or system`);let i=await e.backend.pressBack(m(e,t),{mode:r}),a=u(i);return{kind:`systemBack`,mode:r,...a?{backendResult:a}:{},...g(`Back`)}},cn=async(e,t={})=>{if(!e.backend.pressHome)throw new n(`UNSUPPORTED_OPERATION`,`system.home is not supported by this backend`);let r=await e.backend.pressHome(m(e,t)),i=u(r);return{kind:`systemHome`,...i?{backendResult:i}:{},...g(`Home`)}},ln=async(e,t)=>{if(!e.backend.pressTvRemote)throw new n(`UNSUPPORTED_OPERATION`,`system.tvRemote is not supported by this backend`);let r=oe(t.button),i=t.durationMs===void 0?void 0:s(t.durationMs,`durationMs`,0,1e4),a=await e.backend.pressTvRemote(m(e,t),{button:r,...i===void 0?{}:{durationMs:i}}),o=u(a);return{kind:`tvRemotePressed`,button:r,...i===void 0?{}:{durationMs:i},...o?{backendResult:o}:{},...g(`Pressed TV remote ${r}`)}},un=async(e,t)=>{if(!e.backend.setOrientation)throw new n(`UNSUPPORTED_OPERATION`,`system.orientation is not supported by this backend`);let r=gn(t.orientation),i=await e.backend.setOrientation(m(e,t),r),a=u(i);return{kind:`systemOrientationSet`,orientation:r,...a?{backendResult:a}:{},...g(`Rotated to ${r}`)}},dn=async(e,t={})=>{if(!e.backend.setKeyboard)throw new n(`UNSUPPORTED_OPERATION`,`system.keyboard is not supported by this backend`);let r=t.action??`status`;if(!ce(r))throw new n(`INVALID_ARGS`,`system.keyboard action must be status, get, dismiss, enter, or return`);let i=await e.backend.setKeyboard(m(e,t),{action:r}),a=u(i),o=Tn(i)?i:{};return r===`enter`||r===`return`?vn(o,a):r===`dismiss`?yn(r,o,a):xn(r,o,a)},fn=async(e,t)=>{if(t.action===`read`){if(!e.backend.getClipboard)throw new n(`UNSUPPORTED_OPERATION`,`system.clipboard read is not supported by this backend`);let r=await e.backend.getClipboard(m(e,t));return{kind:`clipboardText`,action:`read`,text:typeof r==`string`?r:r.text}}if(t.action!==`write`)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(typeof t.text!=`string`)throw new n(`INVALID_ARGS`,`system.clipboard write requires text`);let r=await e.backend.setClipboard(m(e,t),t.text),i=u(r);return{kind:`clipboardUpdated`,action:`write`,textLength:Array.from(t.text).length,...i?{backendResult:i}:{},...g(`Clipboard updated`)}},pn=async(e,t={})=>{if(!e.backend.openSettings)throw new n(`UNSUPPORTED_OPERATION`,`system.settings is not supported by this backend`);let r=C(t.target,`target`),i=await e.backend.openSettings(m(e,t),r),a=u(i);return{kind:`settingsOpened`,...r?{target:r}:{},...a?{backendResult:a}:{},...g(r?`Opened settings: ${r}`:`Opened settings`)}},mn=async(e,t={})=>{if(!e.backend.handleAlert)throw new n(`UNSUPPORTED_OPERATION`,`system.alert is not supported by this backend`);let r=t.action??`get`;if(r!==`get`&&r!==`accept`&&r!==`dismiss`&&r!==`wait`)throw new n(`INVALID_ARGS`,`system.alert action must be get, accept, dismiss, or wait`);let i=t.timeoutMs===void 0?void 0:s(t.timeoutMs,`timeoutMs`,0,12e4);return _n(r,await e.backend.handleAlert(m(e,t),r,{timeoutMs:i}))},hn=async(e,t={})=>{if(!e.backend.openAppSwitcher)throw new n(`UNSUPPORTED_OPERATION`,`system.appSwitcher is not supported by this backend`);let r=await e.backend.openAppSwitcher(m(e,t)),i=u(r);return{kind:`appSwitcherOpened`,...i?{backendResult:i}:{},...g(`Opened app switcher`)}};function gn(e){switch(e){case`portrait`:case`portrait-upside-down`:case`landscape-left`:case`landscape-right`:return e;default:throw new n(`INVALID_ARGS`,`system.orientation must be portrait, portrait-upside-down, landscape-left, or landscape-right`)}}function _n(e,t){return e===`get`?Sn(t):e===`wait`?Cn(t):wn(e,t)}function vn(e,t){return{kind:`keyboardEnterPressed`,action:`enter`,state:e,...t?{backendResult:t}:{},...g(`Keyboard enter pressed`)}}function yn(e,t,n){return{kind:`keyboardDismissed`,action:e,state:t,...n?{backendResult:n}:{},...g(bn(t))}}function bn(e){return e.dismissed===!1?`Keyboard already hidden`:e.mechanism===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`}function xn(e,t,n){return{kind:`keyboardState`,action:e,state:t,...n?{backendResult:n}:{}}}function Sn(e){if(e.kind!==`alertStatus`)throw new n(`COMMAND_FAILED`,`system.alert get returned an invalid backend result`);return{kind:`alertStatus`,action:`get`,alert:e.alert}}function Cn(e){if(e.kind!==`alertWait`)throw new n(`COMMAND_FAILED`,`system.alert wait returned an invalid backend result`);return{kind:`alertWait`,action:`wait`,alert:e.alert,...e.waitedMs===void 0?{}:{waitedMs:e.waitedMs},...e.timedOut===void 0?{}:{timedOut:e.timedOut},...g(e.alert?`Alert visible`:`Alert wait timed out`)}}function wn(e,t){if(t.kind!==`alertHandled`)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}:{},...g(t.handled?`Alert ${e}ed`:`No alert handled`)}}function Tn(e){return!!(e&&typeof e==`object`)}const En={back:sn,home:cn,orientation:un,keyboard:dn,clipboard:fn,settings:pn,alert:mn,appSwitcher:hn,tvRemote:ln};function Dn(e){return{capture:ee(e),selectors:f(e),interactions:l(e),system:h(En,e),apps:Je(e),admin:h(qe,e),recording:h(on,e),observability:h(ft,e)}}function On(e){let t=a(e);return{...t,...Dn(t)}}export{On as createAgentDevice,te as createMemorySessionStore,c as localCommandPolicy,o as restrictedCommandPolicy};
@@ -1,4 +1,4 @@
1
- import{N as e,U as t}from"./sdk-contracts.js";import{i as n}from"./sdk-batch-runner.js";import{A as r}from"./sdk-device.js";import{Yt as i,tn as a}from"./sdk-batch.js";import{n as o}from"./device-shell.js";import{n as s,t as c}from"./android-snapshot-quality.js";import{i as l,n as u}from"./recording-stop-observation.js";import{n as d,r as f,t as p}from"./application-lifecycle-runtime.js";import{A as m,B as h,C as g,D as ee,G as te,H as ne,I as re,J as ie,N as ae,V as oe,d as se,h as ce,n as le,o as ue,s as de,v as fe,w as pe,x as me,z as he}from"./alert-runtime.js";import{n as ge}from"./audio-probe-runtime.js";import{n as _e}from"./perf-runtime.js";import{i as ve}from"./touch-runtime.js";import{a as ye,n as be}from"./durable-resource.js";import{n as xe}from"./async-lifecycle.js";import{i as Se,l as Ce,n as we,r as Te,t as Ee}from"./src7.js";import{n as De}from"./screen-recording-completion.js";import{a as _,c as Oe,n as ke,o as Ae,s as je,t as Me}from"./device-readiness-runtime.js";import{n as Ne}from"./screen-recording-runtime.js";import{readAndroidAppStateWithExecutor as Pe}from"./app-state.js";import{ANDROID_CLIPBOARD_SHELL_COMMAND_UNAVAILABLE_HINT as Fe}from"./clipboard-shell-response.js";import{i as Ie,t as Le}from"./gesture-admission.js";import{t as Re}from"./local-interactor-operation-set.js";import{a as ze,i as v,n as y,r as Be,t as Ve}from"./perf-runtime-operation-builder.js";import{t as He}from"./app-log-runtime.js";import{t as Ue}from"./mp4-duration.js";import{n as b,r as We}from"./managed-device-scope.js";import{a as Ge,i as Ke,n as qe,o as Je}from"./application-lifecycle-interaction.js";import x from"node:path";function Ye(e){return Ae(e)?Object.freeze({available:!0}):e.kind===`emulator`?Object.freeze({available:!1,reason:`unsupported-device-backend`,hint:`audio probe capture requires a macOS host.`}):Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`audio probe capture is supported for Android emulators on macOS hosts.`})}function Xe(e){let{resolveHost:t,device:n,owner:r}=e;return Object.freeze({...Ve({platform:`Android`,expectedProfileKind:`simpleperf`,start:async e=>await t().start(n,r,e),reattach:async e=>await t().reattach(n,e),cleanup:async e=>await t().cleanup(n,e),writeProfileReport:async e=>await t().writeProfileReport(n,e)}),perfFrames:async({appId:e})=>({metric:e?await v(t().sampleFrames(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-gfxinfo-framestats`,description:`Rendered-frame health from the current adb shell dumpsys gfxinfo <package> framestats window. Dropped frames use Android gfxinfo janky-frame/frame-deadline data when available; this is not video recording FPS.`,unit:`percent`,primaryField:`droppedFramePercent`,window:`since previous Android gfxinfo reset or app process start`,resetsAfterRead:!0,relatedActionsLimit:12}}),perfMemorySample:async({appId:e})=>({metric:e?await v(t().sampleMemory(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-meminfo`,description:`Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.`,unit:`kB`,topConsumerLimit:5}}),perfMemorySnapshot:async({appId:e,kind:r,outPath:i,artifactsDir:a})=>{let o=r??`android-hprof`,s=Ze();if(o!==`android-hprof`)return ze(`Android`,o,s,`Use perf memory snapshot --kind android-hprof for Android Java heap artifacts.`);if(!e)throw Be();let c=i??x.join(a,`memory-android-hprof-${Qe()}.hprof`);return{artifact:await t().captureMemorySnapshot(n,e,c),support:s,sampling:{method:`adb-shell-am-dumpheap`,description:`Java heap dump captured with adb shell am dumpheap, pulled to a local artifact path.`,defaultKind:`android-hprof`,artifactOnly:!0}}}})}function Ze(){return{platform:`android`,defaultKind:`android-hprof`,androidHprof:!0,memgraph:!1,heapprofd:!1,heapprofdDecision:`Deferred until Android Perfetto/heapprofd plumbing is available in the perf trace slice.`}}function Qe(){return new Date().toISOString().replaceAll(/[:.]/g,`-`)}function $e(t){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new e(`INVALID_ARGS`,`Invalid Android package name for logs: ${t}`)}const S=Object.freeze({resourceKind:He,version:1,encode:e=>({...e}),decode:e=>e.transport!==`android-logcat-local`&&e.transport!==`android-logcat-transport-composed`||!tt(e.outputPath)||!tt(e.pidPath)?{status:`invalid`,message:`Invalid Android app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:e.transport,outputPath:e.outputPath,pidPath:e.pidPath})}});function et(e){let t=S.decode(e.descriptor);if(t.status!==`decoded`)throw TypeError(t.message);return be({resourceKind:He,sessionId:e.sessionId,device:{id:e.device.id,family:`android`,kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:ye(S,t.descriptor)})}function tt(e){return typeof e==`string`&&e.trim().length>0}function nt(e){return Te(e,{family:`android`,backend:`android`,label:`Android`,codec:S,startUnavailableHint:`The selected Android transport cannot start a background adb logcat stream.`,cleanupFailureMessage:`Android app-log cleanup did not settle every owned resource`,doctor:async({host:e,device:t,signal:n},r)=>await rt(e,t.id,r,n),validateStart:({input:e})=>$e(e.appBundleId),process:async({host:e,device:t,input:n})=>({resolvePid:async r=>await Se(e,it(t.id,n.appBundleId),r),command:e=>({kind:`android-adb`,serial:t.id,args:[`logcat`,`-v`,`time`,`--pid`,e],options:{allowFailure:!0}})}),descriptor:({artifacts:e,transport:t})=>({transport:t.mode===`transport-composed`?`android-logcat-transport-composed`:`android-logcat-local`,...e}),envelope:({input:e,device:t,owner:n,descriptor:r})=>et({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function rt(e,t,n,r){let i={};return i.adbAvailable=await Oe(async()=>je(await e.commands.run({executable:`adb`,args:o(`adb`,`shell`,[`echo`,`ok`],[`-s`,t]),allowFailure:!0,timeoutMs:1e3},r)),r),n&&(i.androidPidVisible=await Oe(async()=>!!await Se(e,it(t,n),r),r)),{backend:`android`,checks:i,notes:n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}}function it(e,t){return{executable:`adb`,args:o(`adb`,`shell`,[`pidof`,t],[`-s`,e]),allowFailure:!0,timeoutMs:5e3}}async function at(e,t,n,r){let i=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),a=we(i.text,{...n,path:i.path,exists:i.exists,lineNumberOffset:i.skippedLines,backend:`android`}),o=[],s=await st(e,t,n,r);if(s&&n.appBundleId){$e(n.appBundleId);let c=await lt(e,t,n.appBundleId,r);if(c){let e=we(c.text,{...n,path:`${i.path} (adb logcat recovery)`,exists:!0,backend:`android`});e.dump.entries.length>0&&(a=Ee(e,a,n.maxEntries),o.push(s.reason===`stale-active`?`Session app log stream was still bound to prior Android PID ${s.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`))}}return n.appLogSnapshot?n.appLogSnapshot.state!==`active`&&o.length===0&&o.push(`Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.`):o.push(`Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests.`),a.dump.entries.length===0&&o.push(`No HTTP(s) entries were found in recent session app logs.`),Object.freeze({source:`app-log`,backend:`android`,dump:a.dump,notes:Object.freeze(o)})}async function ot(e,t,n){n.throwIfAborted();try{let r=await e.commands.run(t,n);return n.throwIfAborted(),r}catch{n.throwIfAborted();return}}async function st(e,t,n,r){if(!n.appBundleId||n.appLogSnapshot?.state===void 0)return;if(n.appLogSnapshot.state!==`active`)return{reason:`inactive`};let i=ct(await e.appLogs.readProcessMarker(n.sessionId));if(!i)return;let a=await ut(e,t.id,n.appBundleId,r);if(!(!a||a===i))return{reason:`stale-active`,trackedPid:i}}function ct(e){if(e.status===`decoded`)return/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(e.marker.command)?.[1]}async function lt(e,t,n,r){let i=await ut(e,t.id,n,r),a=await ot(e,{executable:`adb`,args:[`-s`,t.id,`logcat`,`-d`,`-v`,`time`,`-t`,`4000`],allowFailure:!0,timeoutMs:3e3},r);if(!a||a.exitCode!==0||!a.stdout.trim())return;let o=dt(a.stdout,n,i);if(o.length===0)return;let s=new Set(o),c=a.stdout.split(`
1
+ import{N as e,q as t}from"./sdk-contracts.js";import{i as n}from"./sdk-batch-runner.js";import{A as r}from"./sdk-device.js";import{Xt as i,nn as a}from"./sdk-batch.js";import{n as o}from"./device-shell.js";import{n as s,t as c}from"./android-snapshot-quality.js";import{i as l,n as u}from"./recording-stop-observation.js";import{n as d,r as f,t as p}from"./application-lifecycle-runtime.js";import{A as m,B as h,C as g,D as ee,G as te,H as ne,I as re,J as ie,N as ae,V as oe,d as se,h as ce,n as le,o as ue,s as de,v as fe,w as pe,x as me,z as he}from"./alert-runtime.js";import{n as ge}from"./audio-probe-runtime.js";import{n as _e}from"./perf-runtime.js";import{i as ve}from"./touch-runtime.js";import{a as ye,n as be}from"./durable-resource.js";import{n as xe}from"./async-lifecycle.js";import{i as Se,l as Ce,n as we,r as Te,t as Ee}from"./src7.js";import{n as De}from"./screen-recording-completion.js";import{a as _,c as Oe,n as ke,o as Ae,s as je,t as Me}from"./device-readiness-runtime.js";import{n as Ne}from"./screen-recording-runtime.js";import{readAndroidAppStateWithExecutor as Pe}from"./app-state.js";import{ANDROID_CLIPBOARD_SHELL_COMMAND_UNAVAILABLE_HINT as Fe}from"./clipboard-shell-response.js";import{i as Ie,t as Le}from"./gesture-admission.js";import{t as Re}from"./local-interactor-operation-set.js";import{a as ze,i as v,n as y,r as Be,t as Ve}from"./perf-runtime-operation-builder.js";import{t as He}from"./app-log-runtime.js";import{t as Ue}from"./mp4-duration.js";import{n as b,r as We}from"./managed-device-scope.js";import{a as Ge,i as Ke,n as qe,o as Je}from"./application-lifecycle-interaction.js";import x from"node:path";function Ye(e){return Ae(e)?Object.freeze({available:!0}):e.kind===`emulator`?Object.freeze({available:!1,reason:`unsupported-device-backend`,hint:`audio probe capture requires a macOS host.`}):Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`audio probe capture is supported for Android emulators on macOS hosts.`})}function Xe(e){let{resolveHost:t,device:n,owner:r}=e;return Object.freeze({...Ve({platform:`Android`,expectedProfileKind:`simpleperf`,start:async e=>await t().start(n,r,e),reattach:async e=>await t().reattach(n,e),cleanup:async e=>await t().cleanup(n,e),writeProfileReport:async e=>await t().writeProfileReport(n,e)}),perfFrames:async({appId:e})=>({metric:e?await v(t().sampleFrames(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-gfxinfo-framestats`,description:`Rendered-frame health from the current adb shell dumpsys gfxinfo <package> framestats window. Dropped frames use Android gfxinfo janky-frame/frame-deadline data when available; this is not video recording FPS.`,unit:`percent`,primaryField:`droppedFramePercent`,window:`since previous Android gfxinfo reset or app process start`,resetsAfterRead:!0,relatedActionsLimit:12}}),perfMemorySample:async({appId:e})=>({metric:e?await v(t().sampleMemory(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-meminfo`,description:`Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.`,unit:`kB`,topConsumerLimit:5}}),perfMemorySnapshot:async({appId:e,kind:r,outPath:i,artifactsDir:a})=>{let o=r??`android-hprof`,s=Ze();if(o!==`android-hprof`)return ze(`Android`,o,s,`Use perf memory snapshot --kind android-hprof for Android Java heap artifacts.`);if(!e)throw Be();let c=i??x.join(a,`memory-android-hprof-${Qe()}.hprof`);return{artifact:await t().captureMemorySnapshot(n,e,c),support:s,sampling:{method:`adb-shell-am-dumpheap`,description:`Java heap dump captured with adb shell am dumpheap, pulled to a local artifact path.`,defaultKind:`android-hprof`,artifactOnly:!0}}}})}function Ze(){return{platform:`android`,defaultKind:`android-hprof`,androidHprof:!0,memgraph:!1,heapprofd:!1,heapprofdDecision:`Deferred until Android Perfetto/heapprofd plumbing is available in the perf trace slice.`}}function Qe(){return new Date().toISOString().replaceAll(/[:.]/g,`-`)}function $e(t){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new e(`INVALID_ARGS`,`Invalid Android package name for logs: ${t}`)}const S=Object.freeze({resourceKind:He,version:1,encode:e=>({...e}),decode:e=>e.transport!==`android-logcat-local`&&e.transport!==`android-logcat-transport-composed`||!tt(e.outputPath)||!tt(e.pidPath)?{status:`invalid`,message:`Invalid Android app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:e.transport,outputPath:e.outputPath,pidPath:e.pidPath})}});function et(e){let t=S.decode(e.descriptor);if(t.status!==`decoded`)throw TypeError(t.message);return be({resourceKind:He,sessionId:e.sessionId,device:{id:e.device.id,family:`android`,kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:ye(S,t.descriptor)})}function tt(e){return typeof e==`string`&&e.trim().length>0}function nt(e){return Te(e,{family:`android`,backend:`android`,label:`Android`,codec:S,startUnavailableHint:`The selected Android transport cannot start a background adb logcat stream.`,cleanupFailureMessage:`Android app-log cleanup did not settle every owned resource`,doctor:async({host:e,device:t,signal:n},r)=>await rt(e,t.id,r,n),validateStart:({input:e})=>$e(e.appBundleId),process:async({host:e,device:t,input:n})=>({resolvePid:async r=>await Se(e,it(t.id,n.appBundleId),r),command:e=>({kind:`android-adb`,serial:t.id,args:[`logcat`,`-v`,`time`,`--pid`,e],options:{allowFailure:!0}})}),descriptor:({artifacts:e,transport:t})=>({transport:t.mode===`transport-composed`?`android-logcat-transport-composed`:`android-logcat-local`,...e}),envelope:({input:e,device:t,owner:n,descriptor:r})=>et({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function rt(e,t,n,r){let i={};return i.adbAvailable=await Oe(async()=>je(await e.commands.run({executable:`adb`,args:o(`adb`,`shell`,[`echo`,`ok`],[`-s`,t]),allowFailure:!0,timeoutMs:1e3},r)),r),n&&(i.androidPidVisible=await Oe(async()=>!!await Se(e,it(t,n),r),r)),{backend:`android`,checks:i,notes:n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}}function it(e,t){return{executable:`adb`,args:o(`adb`,`shell`,[`pidof`,t],[`-s`,e]),allowFailure:!0,timeoutMs:5e3}}async function at(e,t,n,r){let i=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),a=we(i.text,{...n,path:i.path,exists:i.exists,lineNumberOffset:i.skippedLines,backend:`android`}),o=[],s=await st(e,t,n,r);if(s&&n.appBundleId){$e(n.appBundleId);let c=await lt(e,t,n.appBundleId,r);if(c){let e=we(c.text,{...n,path:`${i.path} (adb logcat recovery)`,exists:!0,backend:`android`});e.dump.entries.length>0&&(a=Ee(e,a,n.maxEntries),o.push(s.reason===`stale-active`?`Session app log stream was still bound to prior Android PID ${s.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`))}}return n.appLogSnapshot?n.appLogSnapshot.state!==`active`&&o.length===0&&o.push(`Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.`):o.push(`Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests.`),a.dump.entries.length===0&&o.push(`No HTTP(s) entries were found in recent session app logs.`),Object.freeze({source:`app-log`,backend:`android`,dump:a.dump,notes:Object.freeze(o)})}async function ot(e,t,n){n.throwIfAborted();try{let r=await e.commands.run(t,n);return n.throwIfAborted(),r}catch{n.throwIfAborted();return}}async function st(e,t,n,r){if(!n.appBundleId||n.appLogSnapshot?.state===void 0)return;if(n.appLogSnapshot.state!==`active`)return{reason:`inactive`};let i=ct(await e.appLogs.readProcessMarker(n.sessionId));if(!i)return;let a=await ut(e,t.id,n.appBundleId,r);if(!(!a||a===i))return{reason:`stale-active`,trackedPid:i}}function ct(e){if(e.status===`decoded`)return/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(e.marker.command)?.[1]}async function lt(e,t,n,r){let i=await ut(e,t.id,n,r),a=await ot(e,{executable:`adb`,args:[`-s`,t.id,`logcat`,`-d`,`-v`,`time`,`-t`,`4000`],allowFailure:!0,timeoutMs:3e3},r);if(!a||a.exitCode!==0||!a.stdout.trim())return;let o=dt(a.stdout,n,i);if(o.length===0)return;let s=new Set(o),c=a.stdout.split(`
2
2
  `).filter(e=>{if(!e.trim())return!1;if(e.includes(n))return!0;let t=/\(\s*(\d+)\)\s*:/.exec(e)?.[1];return!!(t&&s.has(t))}).join(`
3
3
  `);return c.trim()?{text:c,pids:o}:void 0}async function ut(e,t,n,r){let i=await ot(e,{executable:`adb`,args:o(`adb`,`shell`,[`pidof`,n],[`-s`,t]),allowFailure:!0},r);if(!i)return;let a=i.stdout.trim().split(/\s+/)[0];return a&&/^\d+$/.test(a)?a:void 0}function dt(e,t,n){let r=new Set(n?[n]:[]),i=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),a=[RegExp(`\\bStart proc\\s+(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`\\b(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`${i}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,`i`),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${i}`,`i`)];for(let n of e.split(`
4
4
  `))if(n.includes(t))for(let e of a){let t=e.exec(n)?.[1];t&&/^\d+$/.test(t)&&r.add(t)}return Object.freeze([...r])}function C(e,t){if(t===1)return e;let n=x.parse(e);return x.join(n.dir,`${n.name}.part-${String(t).padStart(3,`0`)}${n.ext||`.mp4`}`)}const ft=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-\d{1,20}\.mp4$/,pt=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-active\.json$/;function mt(e){return _t(e)&&vt(e)&&yt(e)}function ht(e){if(!w(e))return!1;let t=e;return bt(t)&&xt(t)&&St(t)&&Ct(t)&&(t.completion===void 0||At(t))}function gt(e,t){return jt(e,t)&&Mt(e,t.outputPath,t.clientOutputPath)}function _t(e){return e.backend===`adb-screenrecord`&&typeof e.manifestPath==`string`&&pt.test(e.manifestPath)&&typeof e.outputPath==`string`}function vt(e){return Pt(e.clientOutputPath)&&_(e)}function yt(e){return Nt(e.transportMode)}function bt(e){return e.version===1&&e.resourceKind===`screen-recording`&&typeof e.fenceToken==`string`&&Number.isInteger(e.fenceGeneration)&&typeof e.sessionId==`string`&&typeof e.deviceId==`string`&&Number.isFinite(e.startedAt)}function xt(e){return typeof e.outputPath==`string`&&Pt(e.clientOutputPath)&&_(e)}function St(e){return Nt(e.transportMode)&&(e.pendingRemotePath===void 0||Ft(e.pendingRemotePath))}function Ct(e){return Array.isArray(e.chunks)&&e.chunks.every(wt)&&(e.chunks.length>0||e.pendingRemotePath!==void 0)&&(e.completion===void 0||Tt(e.completion))}function wt(e,t){if(!w(e))return!1;let n=e;return n.index===t+1&&Ft(n.remotePath)&&It(n.remotePid)&&It(n.remoteStartTime)}function Tt(e){if(!w(e))return!1;let t=e;return Dt(t)&&Ot(t)&&Et(t)&&(t.chunks===void 0||t.chunks.every(kt))}function Et(e){return(e.stopObservation===void 0||u(e.stopObservation))&&(e.nativePathDisposition===void 0||l(e.nativePathDisposition))}function Dt(e){return typeof e.backend==`string`&&typeof e.outPath==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)&&Number.isFinite(e.startedAt)&&Number.isFinite(e.completedAt)&&(e.capturedDurationMs===void 0||Number.isFinite(e.capturedDurationMs))}function Ot(e){return _(e)}function kt(e,t){return e.index===t+1&&typeof e.path==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)}function At(e){let t=e.completion;return t!==void 0&&jt(t,e)&&t.startedAt===e.startedAt&&Mt(t,e.outputPath,e.clientOutputPath,e.chunks.length)}function jt(e,t){return e.backend===`adb screenrecord`&&e.outPath===t.outputPath&&e.clientOutPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&Lt(e.activeSessionApp,t.activeSessionApp)}function Mt(e,t,n,r=e.chunks===void 0?1:e.chunks.length){return r===1?e.chunks===void 0:e.chunks?.length===r&&e.chunks.every((e,r)=>e.path===C(t,r+1)&&e.clientOutPath===(n===void 0?void 0:C(n,r+1)))}function w(e){return typeof e==`object`&&!!e}function Nt(e){return e===`local`||e===`transport-composed`}function Pt(e){return e===void 0||typeof e==`string`}function Ft(e){return typeof e==`string`&&ft.test(e)}function It(e){return typeof e==`string`&&/^\d+$/.test(e)}function Lt(e,t){return JSON.stringify(e)===JSON.stringify(t)}const T=Object.freeze({resourceKind:Ne,version:1,encode:e=>({...e}),decode:e=>mt(e)?{status:`decoded`,descriptor:Object.freeze({backend:`adb-screenrecord`,manifestPath:e.manifestPath,outputPath:e.outputPath,...e.clientOutputPath===void 0?{}:{clientOutputPath:e.clientOutputPath},scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,transportMode:e.transportMode,...e.activeSessionApp===void 0?{}:{activeSessionApp:e.activeSessionApp},...e.exportQuality===void 0?{}:{exportQuality:e.exportQuality}})}:{status:`invalid`,message:`Invalid Android screen-recording descriptor`}});function E(e,t,n,r,i,a=`local`){return Object.freeze({version:1,resourceKind:`screen-recording`,fenceToken:t.fence.token,fenceGeneration:t.fence.generation,sessionId:t.sessionId,deviceId:e.id,startedAt:n,outputPath:t.outputPath,...t.clientOutputPath===void 0?{}:{clientOutputPath:t.clientOutputPath},scope:t.scope,showTouches:t.showTouches,recordOnlySession:t.recordOnlySession,...t.activeSessionApp===void 0?{}:{activeSessionApp:t.activeSessionApp},...t.exportQuality===void 0?{}:{exportQuality:t.exportQuality},chunks:r,...i===void 0?{}:{pendingRemotePath:i},transportMode:a})}function Rt(e,t){return Object.freeze({...e,completion:t})}function D(e){try{let t=e&&JSON.parse(e);return ht(t)?t:void 0}catch{return}}function zt(e,t,n){return e.deviceId===t.id&&e.deviceId===n.device.id&&e.fenceToken===n.fence.token&&e.fenceGeneration===n.fence.generation&&e.sessionId===n.sessionId}function Bt(e,t){return e.outputPath===t.outputPath&&e.clientOutputPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&JSON.stringify(e.activeSessionApp)===JSON.stringify(t.activeSessionApp)&&e.exportQuality===t.exportQuality&&e.transportMode===t.transportMode&&(e.completion===void 0||gt(e.completion,t))}function O(e){switch(e){case`missing`:case`ownership-lost`:case`foreign-writer`:return!0;case`owned-alive`:case`uncertain`:return!1}}function Vt(e){switch(e){case`missing`:case`ownership-lost`:return!0;case`foreign-writer`:case`owned-alive`:case`uncertain`:return!1}}const Ht=1e4,k=1e3;var A=class extends Error{constructor(e){super(`Android screenrecord launch rollback could not be confirmed`,{cause:e})}};function j(e,t=Date.now()){return[...new Set(e?[e,`/sdcard`,`/data/local/tmp`]:[`/sdcard`,`/data/local/tmp`])].map(e=>`${e}/agent-device-recording-${t}.mp4`)}async function Ut(e,t,n,r){let i;try{if(i=(await e.start({remotePath:t,quality:n.exportQuality??`medium`},r)).process,!/^\d+$/.test(i.pid)||!/^\d+$/.test(i.startTime)||i.remotePath!==t)throw Error(`Android screenrecord returned an invalid process identity`);if(!await Yt(e,t,i,r))throw Error(`Android screenrecord did not begin producing frames`);return{index:1,remotePath:t,remotePid:i.pid,remoteStartTime:i.startTime}}catch(t){throw i&&Wt(i)&&!await Xt(e,i)?new A(t):r?.aborted?r.reason:t}}function Wt(e){return/^\d+$/.test(e.pid)&&/^\d+$/.test(e.startTime)&&e.remotePath.length>0}async function M(e,t){let n=t.at(-1),r=!1,i;for(let a of[...t].reverse())try{let t=await P(e,a);a===n&&(r=t)}catch(e){i??=e}if(i)throw i;return r}async function Gt(e,t){for(let n of t){let t;for(let r=0;r<3;r+=1){let i=await e.size(n.remotePath);if(typeof i==`number`&&i>0&&i===t)break;if(t=typeof i==`number`&&i>0?i:void 0,r===2)throw Error(`Android recording artifact is not stable: ${n.remotePath}`);await new Promise(e=>setTimeout(e,250))}}}async function Kt(e,t,n){for(let[r,i]of t.entries())await Zt(e,i.remotePath,C(n,r+1))}async function N(e,t){let n;for(let r of t)try{if(!await e.remove(r.remotePath))throw Error(`failed to remove Android recording artifact: ${r.remotePath}`)}catch(e){n??=e}if(n)throw n}async function qt(e,t){for(let n of t)if(await e.exists(n.remotePath)!==!1)return`retirable`;return`retired`}async function Jt(e,t){try{await M(e,t)}finally{await N(e,t)}}async function Yt(e,t,n,r){for(let i=0;i<3;i+=1){if(r?.throwIfAborted(),await e.exists(t,r)===!0)return!0;if(await e.inspect(n,r)!==`owned-alive`)return!1;i<2&&await new Promise(e=>setTimeout(e,250))}return!0}async function Xt(e,t){try{let n=await e.stop(t,{force:!0});return(n===`stopped`||n===`already-missing`)&&await e.remove(t.remotePath)}catch{return!1}}async function P(e,t){if(!t)return!1;let n={pid:t.remotePid,remotePath:t.remotePath,startTime:t.remoteStartTime},r=await e.stop(n);if(r===`already-missing`)return!0;if(r===`ownership-lost`)throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.remotePid}`);if(await Qt(e,n))return!1;let i=await e.stop(n,{force:!0});if(i===`stopped`||i===`already-missing`)return!1;throw Error(`failed to stop Android screenrecord pid ${t.remotePid}`)}async function Zt(e,t,n){for(let r=0;r<3;r+=1){let i=await e.pullPlayable({remotePath:t,outputPath:n});if(i.exitCode===0&&i.playable)return;r+1<3&&await $t(1e3)}throw Error(`failed to retrieve playable Android recording`)}async function Qt(e,t){for(let n=0;n<=Ht;n+=k){let r=await e.inspect(t);if(r===`missing`)return!0;if(O(r))throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.pid}`);n<Ht&&await $t(k)}return!1}function $t(e){return new Promise(t=>setTimeout(t,e))}async function F(e,t,n,r){await e.writeManifest({manifestPath:t,contents:JSON.stringify(n)},r)}async function I(e,t){if(!await e.removeManifest(t))throw Error(`failed to remove Android recording manifest: ${t}`)}async function en(e,t){let n=(await tn(e)).flatMap(n=>nn(n,t,e.mode));for(let t of n)await an(e,t.evidence,t.manifestPath)}async function tn(e){return await Promise.all(j(void 0).map(async t=>{let n=e.manifestPathFor(t);return{manifestPath:n,read:await e.readManifest(n)}}))}function nn(e,t,n){if(e.read.status===`missing`)return[];if(e.read.status!==`read`)throw cn(e.manifestPath,e.read.message);let r=D(e.read.contents);if(r===void 0)throw ln(e.manifestPath);if(r.transportMode!==n)throw un(e.manifestPath,r,n);if(!rn(r,t))throw dn(e.manifestPath,r,t);return[{manifestPath:e.manifestPath,evidence:r}]}function rn(e,t){return e.completion!==void 0||e.deviceId!==t.id}async function an(e,t,n){if(await on(e,t),await N(e,t.chunks),await sn(e,t),await I(e,n),(await e.readManifest(n)).status!==`missing`)throw mn(n)}async function on(e,t){for(let n of t.chunks){let t=await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime});if(!Vt(t))throw t===`uncertain`?hn(n.remotePath):fn(n.remotePath,t===`owned-alive`?`named-recorder`:`other-recorder`)}let n=t.pendingRemotePath;if(n===void 0)return;let r=await e.probeRunningWriters(n);if(r.writers.length>0)throw fn(n,`other-recorder`);if(!r.conclusive)throw hn(n)}async function sn(e,t){let n=t.pendingRemotePath;if(n!==void 0&&!await e.remove(n))throw pn(n)}function cn(t,n){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unavailable: ${t}`,{reason:`native_recovery_evidence_unavailable`,manifestPath:t,hint:`Confirm the device is online and its storage readable, then run record start again.`},Error(n))}function ln(t){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unreadable: ${t}`,{reason:`native_recovery_evidence_unreadable`,manifestPath:t,hint:L(t)})}function un(t,n,r){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence was written by the ${n.transportMode} transport, not this ${r} one: ${t}`,{reason:`native_recovery_evidence_transport_mismatch`,manifestPath:t,evidenceTransportMode:n.transportMode,hint:L(t)})}function dn(t,n,r){return new e(`DEVICE_IN_USE`,`Android screenrecord native recovery evidence already exists: ${t} (open recording of session "${n.sessionId}" on ${r.id})`,{reason:`native_recovery_evidence_open`,manifestPath:t,sessionId:n.sessionId,retriable:!1,hint:`Run record stop --session ${n.sessionId} to retire it, or close that session. If it is already closed, ${L(t)}`})}function fn(t,n){let r=n===`named-recorder`;return new e(`DEVICE_IN_USE`,`Android screenrecord recovery evidence is retained: ${r?`its recorder`:`another recorder`} is writing ${t}`,{reason:`native_recording_artifact_claimed`,remotePath:t,writer:n,...r?{retriable:!1}:{},hint:r?`Run record stop for the session that owns that recording before starting another.`:`Android ends any recorder after 180 seconds. Run record start again once that recorder has stopped.`})}function pn(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence could not remove ${t}`,{reason:`native_recording_artifact_removal_failed`,remotePath:t,hint:`Confirm the device is online and run record start again.`})}function mn(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence removal could not be confirmed: ${t}`,{reason:`native_recovery_evidence_retirement_unconfirmed`,manifestPath:t,hint:`Run record start again; the marker is retired from the beginning.`})}function hn(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence cannot be safely retired: ${t}`,{reason:`native_recording_recorder_unproven`,remotePath:t,hint:`Confirm the device is online and run record start again.`})}function L(e){return`no recording session can retire this marker; remove it on the device with \`adb shell rm -f ${e}\`.`}async function gn(e){let{transport:t,device:n,input:r,startedAt:i,signal:a,prepareOutput:o}=e;await en(t,n),await o();let s;for(let e of j(void 0)){let o=t.manifestPathFor(e);await F(t,o,E(n,r,i,[],e,t.mode),a);let c,l;try{l=Date.now(),c=await Ut(t,e,r,a)}catch(e){if(a.aborted)throw await _n(t,o,e),a.reason;await bn(t,o,e),s=e;continue}try{await F(t,o,E(n,r,i,[c],void 0,t.mode),a)}catch(e){throw await vn(t,o,c),e}return{chunk:c,manifestPath:o,startedAtMs:l}}throw s??Error(`Android screenrecord did not begin producing frames`)}async function _n(e,t,n){n instanceof A||await I(e,t).catch(()=>{})}async function vn(e,t,n){try{await Jt(e,[n])}catch{return}await I(e,t).catch(()=>{})}async function yn(e){let{transport:t,device:n,input:r,startedAt:i,chunks:a,manifestPath:o,preferredDir:s}=e,c;for(let e of j(s)){await F(t,o,E(n,r,i,a,e,t.mode));try{return await Ut(t,e,r)}catch(e){if(e instanceof A)throw e;try{await F(t,o,E(n,r,i,a,void 0,t.mode))}catch{throw new A(e)}c=e}}throw c??Error(`failed to start next Android recording chunk`)}async function bn(e,t,n){if(n instanceof A)throw n;try{await I(e,t)}catch{throw new A(n)}}function xn(e,t){return Object.freeze({backend:`adb screenrecord`,outPath:e.outputPath,...e.clientOutputPath?{clientOutPath:e.clientOutputPath}:{},startedAt:t,scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,...e.activeSessionApp?{activeSessionApp:e.activeSessionApp}:{},...e.exportQuality?{exportQuality:e.exportQuality}:{},gestureEvents:[]})}function Sn(e){let t=Cn(e.chunkPaths);if(t===void 0)return{};let n=e.stoppedAtMs-e.startedAtMs;return n-t<2e3?{capturedDurationMs:t}:{capturedDurationMs:t,idleTailWarning:`Android screenrecord encodes a frame only when the screen changes, so this video ends at the last frame it encoded: it covers ${wn(t)}s of the ${wn(n)}s recording window.`}}function Cn(e){let t=0;for(let n of e){let e=Ue(n);if(e===void 0)return;t+=e}return t}function wn(e){return(e/1e3).toFixed(1)}async function Tn(e){let{host:t,transport:n,evidence:r,recording:i,startedAtMs:a,progress:o}=e,s=e.reachedLimit===!0;return await An(e,await ke({snapshot:i,progress:o,steps:{stop:async()=>(s=await M(n,r.chunks)||s,await Gt(n,r.chunks),{observation:{recorder:`confirmed`},...s?{warning:`Android adb screenrecord stopped before record stop, likely after reaching the 180s platform limit. The MP4 may be truncated; final interactions after the limit are not in the video.`}:{}}),collect:e=>Kt(n,r.chunks,e),finalize:({collectedPath:e,exportPath:n,stoppedAtMs:o})=>En({host:t,evidence:r,recording:i,startedAtMs:a,stoppedAtMs:o,collectedPath:e,exportPath:n}),discard:e=>On(t,e,r.chunks.length)}}))}async function En(e){let{host:t,evidence:n,recording:r,collectedPath:i,exportPath:a}=e,o=jn({collectedPath:i,exportPath:a,exportClientPath:r.clientOutPath,count:n.chunks.length}),s=o.length>1,c;try{await Dn(t,o),c=await t.screenRecording.finalize.complete({outputPath:a,showTouches:!s&&r.showTouches,gestureEvents:r.gestureEvents,exportQuality:r.exportQuality??`medium`,targetLabel:`Android recording`})}catch(e){for(let{served:e}of o)await t.screenRecording.outputs.remove(e.path);throw e}let l=Sn({chunkPaths:o.map(({collected:e})=>e.path),startedAtMs:e.startedAtMs,stoppedAtMs:e.stoppedAtMs});return kn({finalization:c,captured:l,recording:r,chunked:s,files:o})}async function Dn(e,t){for(let{collected:n,served:r}of t)await e.screenRecording.outputs.copy({from:n.path,to:r.path})}async function On(e,t,n){for(let r=1;r<=n;r+=1)await e.screenRecording.outputs.remove(C(t,r))}function kn(e){let{finalization:t,captured:n,recording:r,chunked:i,files:a}=e,o=[t.warning,...i?[`Android adb screenrecord is capped at 180s, so this recording was split into multiple MP4 chunks.`]:[],n.idleTailWarning].filter(e=>e!==void 0&&e.length>0);return{...t.telemetryPath===void 0?{}:{telemetryPath:t.telemetryPath},...o.length===0?{}:{warning:o.join(` `)},...i&&r.showTouches&&r.gestureEvents.length>0?{overlayWarning:`touch overlay burn-in is skipped for chunked Android recordings; returning raw chunks plus gesture telemetry`}:{},...n.capturedDurationMs===void 0?{}:{capturedDurationMs:n.capturedDurationMs},...i?{chunks:a.map(e=>e.served)}:{},nativePathDisposition:`retirable`}}async function An(e,t){let{transport:n,evidence:r,manifestPath:i}=e;return await F(n,i,Rt(r,t.result)),await N(n,r.chunks),{status:`completed`,result:{...t.result,nativePathDisposition:await qt(n,r.chunks)}}}function jn(e){return Object.freeze(Array.from({length:e.count},(t,n)=>({collected:Object.freeze({index:n+1,path:C(e.collectedPath,n+1)}),served:Object.freeze({index:n+1,path:C(e.exportPath,n+1),...e.exportClientPath===void 0?{}:{clientOutPath:C(e.exportClientPath,n+1)}})})))}async function Mn(e,t,n){try{let r=t.pendingRemotePath;if(await M(e,[...t.chunks,...await Nn(e,t)]),await N(e,t.chunks),r!==void 0&&!await e.remove(r))throw Error(`failed to remove Android recording artifact: ${r}`);return await I(e,n),{status:`cleaned`}}catch(e){return Pn(e)}}async function Nn(e,t){let n=t.pendingRemotePath;if(n===void 0)return[];let r=await e.probeRunningWriters(n);if(!r.conclusive)throw Error(`cannot list every recorder writing Android artifact: ${n}`);return r.writers.map((e,r)=>({index:t.chunks.length+1+r,remotePath:n,remotePid:e.pid,remoteStartTime:e.startTime}))}function Pn(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:String(e)}}async function Fn(e){let{transport:t,device:n,envelope:r,descriptor:i}=e;if(i.transportMode!==t.mode)return{status:`transport-unavailable`};let a=await t.readManifest(i.manifestPath);if(a.status===`unavailable`)return{status:`transport-unavailable`};let o=a.status===`read`?D(a.contents):void 0;return o&&zt(o,n,r)&&Bt(o,i)?{status:`matched`,evidence:o}:{status:`ownership-lost`}}async function In(e){let t=await e.transport.readManifest(e.manifestPath);if(t.status!==`read`)return;let n=D(t.contents);return n&&Ln(n,e)?n:void 0}function Ln(e,t){return e.deviceId===t.deviceId&&e.sessionId===t.sessionId&&e.fenceToken===t.fence.token&&e.fenceGeneration===t.fence.generation}async function Rn(e){let{host:t,transport:n,device:r,input:i}=e,a=T.decode(i.envelope.descriptor.body);if(a.status!==`decoded`)return R(`descriptor-invalid`);let o=await Fn({transport:n,device:r,envelope:i.envelope,descriptor:a.descriptor});return o.status===`matched`?await Bn({host:t,transport:n,device:r,input:i,descriptor:a.descriptor,evidence:o.evidence}):R(o.status===`transport-unavailable`?`transport-not-reattachable`:`ownership-fence-lost`)}async function zn(e){let t=T.decode(e.input.envelope.descriptor.body);if(t.status!==`decoded`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};let n=await Fn({transport:e.transport,device:e.device,envelope:e.input.envelope,descriptor:t.descriptor});return n.status===`matched`?await Mn(e.transport,n.evidence,t.descriptor.manifestPath):n.status===`transport-unavailable`?{status:`cleanup-pending`,reason:`owner-unavailable`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`}}async function Bn(e){let{host:t,transport:n,device:r,input:i,descriptor:a,evidence:o}=e;if(o.completion!==void 0){let e=await Vn(n,o);return e.status===`terminal`?{status:`completed`,result:{...o.completion,nativePathDisposition:e.nativePathDisposition}}:R(`ownership-fence-lost`,`Android recording completed evidence still names a live or unverifiable recorder.`)}if(o.pendingRemotePath!==void 0)return R(`transport-not-reattachable`,`Android recording launch was interrupted before its process identity was committed.`);let s=o.chunks.at(-1);if(!s)return{status:`missing`};let c=await n.inspect({pid:s.remotePid,remotePath:s.remotePath,startTime:s.remoteStartTime});if(c!==`owned-alive`&&await n.exists(s.remotePath)===!1)return R(`transport-not-reattachable`,`Android recording process ended before its artifact could be recovered.`);let l=Hn(i.envelope.sessionId,i.envelope.fence,a),u=!1;return{status:`active`,handle:De(xn(l,o.startedAt),{finish:async(e,r)=>{let i=await Tn({host:t,transport:n,evidence:o,manifestPath:a.manifestPath,recording:e,startedAtMs:o.startedAt,reachedLimit:O(c),progress:r});return u=!0,i},forceCleanup:async()=>u?{status:`cleaned`}:await zn({transport:n,device:r,input:i})})}}async function Vn(e,t){try{for(let n of t.chunks)if(!O(await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime})))return{status:`retained`};return{status:`terminal`,nativePathDisposition:await qt(e,t.chunks)}}catch{return{status:`retained`}}}function Hn(e,t,n){return{sessionId:e,outputPath:n.outputPath,...n.clientOutputPath===void 0?{}:{clientOutputPath:n.clientOutputPath},scope:n.scope,showTouches:n.showTouches,hideTouchesRequested:!1,recordOnlySession:n.recordOnlySession,...n.activeSessionApp===void 0?{}:{activeSessionApp:n.activeSessionApp},...n.exportQuality===void 0?{}:{exportQuality:n.exportQuality},fence:t}}function R(e,t){return{status:`unreattachable`,reason:e,...t===void 0?{}:{message:t}}}async function Un(e){let{host:t,device:n,owner:r,signal:i}=e,a=await t.screenRecording.android.resolve(n);return Object.freeze({screenRecordingStart:async e=>await Wn({host:t,transport:a,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async e=>await Rn({host:t,transport:a,device:n,input:e}),screenRecordingCleanup:async e=>await zn({transport:a,device:n,input:e})})}async function Wn(e){let{host:t,transport:n,device:i,owner:a,input:o,signal:s}=e;s.throwIfAborted();let c=Date.now(),l=await gn({transport:n,device:i,input:o,startedAt:c,signal:s,prepareOutput:async()=>await t.screenRecording.outputs.prepare(o.outputPath)}),u=l.manifestPath,d=[l.chunk],f,p,m,h=!1,g=()=>{f=setTimeout(()=>{p=ee().catch(e=>{m=e})},17e4),f.unref?.()},ee=async()=>{let e=d.at(-1);if(!e)throw Error(`Android recording has no active chunk`);let t=!1,r;try{r=await yn({transport:n,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:x.posix.dirname(e.remotePath)})}catch(a){await P(n,e),t=!0;try{r=await yn({transport:n,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:x.posix.dirname(e.remotePath)})}catch(e){throw e instanceof Error?e:a}}let a=[...d,{...r,index:d.length+1}];try{await F(n,u,E(i,o,c,a,void 0,n.mode))}catch(a){if(await Jt(n,[r]).catch(()=>{}),t)await F(n,u,E(i,o,c,d,r.remotePath,n.mode)).catch(()=>{});else try{await F(n,u,E(i,o,c,d,void 0,n.mode))}catch{await P(n,e).catch(()=>{}),await F(n,u,E(i,o,c,d,r.remotePath,n.mode)).catch(()=>{})}throw a}d=a,t||await P(n,e),g()};g();let te=De(xn(o,c),{finish:async(e,r)=>{if(f&&clearTimeout(f),await p,m)throw m;let a=await Tn({host:t,transport:n,evidence:E(i,o,c,d,void 0,n.mode),manifestPath:u,recording:e,startedAtMs:l.startedAtMs,progress:r});return h=!0,a},forceCleanup:async()=>{if(f&&clearTimeout(f),h)return{status:`cleaned`};try{await p}catch(e){m=e}let e=await In({transport:n,deviceId:i.id,sessionId:o.sessionId,fence:o.fence,manifestPath:u});return e?await Mn(n,e,u):{status:`cleanup-pending`,reason:`ownership-fence-lost`}}});return Object.freeze({pendingHandle:new xe(te),envelope:be({resourceKind:Ne,sessionId:o.sessionId,device:r(i),owner:a,fence:o.fence,lifecycle:`open`,descriptor:ye(T,{backend:`adb-screenrecord`,manifestPath:u,outputPath:o.outputPath,...o.clientOutputPath===void 0?{}:{clientOutputPath:o.clientOutputPath},scope:o.scope,showTouches:o.showTouches,recordOnlySession:o.recordOnlySession,...o.activeSessionApp===void 0?{}:{activeSessionApp:o.activeSessionApp},...o.exportQuality===void 0?{}:{exportQuality:o.exportQuality},transportMode:n.mode})})})}const Gn=1e3;async function z(e,t,n,r){return r.throwIfAborted(),await We(t)?{...t,booted:!0}:t.kind===`emulator`&&(t.booted!==!0||!B(t))?await Kn(e,t,n,r):(t.booted!==!0&&await Xn(e,t.id,Qn(e,n),r),{...t,booted:!0})}async function Kn(e,t,n,r){await qn(e);let i=$n(n),a=Qn(e,n),o=Jn(await e.deviceReadiness.androidEmulator.discover(i,r),t.name,n.serial),s=B(o)?o:void 0,c=s?void 0:e.deviceReadiness.androidEmulator.launch(o.name,n.headless);try{let t=s??await Yn(e,o.name,i,n.serial,a,r);return await Xn(e,t.id,a,r),{...(await e.deviceReadiness.androidEmulator.discover(i,r)).find(e=>e.id===t.id)??t,name:o.name,booted:!0}}catch(t){throw c!==void 0&&r.aborted&&await e.deviceReadiness.androidEmulator.terminate(c),r.throwIfAborted(),t}}async function qn(t){if(await t.toolchains.prepare(`android`),!await t.commands.which(`adb`))throw new e(`TOOL_MISSING`,`adb not found in PATH`);if(!await t.commands.which(`emulator`))throw new e(`TOOL_MISSING`,`emulator not found in PATH`)}function Jn(t,n,r){let i=er(t,n,r);if(i)return i;throw new e(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${n}`,{requestedAvdName:n,availableAvds:t.map(e=>e.name),hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."})}async function Yn(e,t,n,r,i,a){for(;e.clock.now()<i;){let i=er(await e.deviceReadiness.androidEmulator.discover(n,a),t,r);if(i&&B(i))return i;await e.clock.sleep(Gn,a)}throw Zn(`Android emulator did not appear in time`,{avdName:t,serial:r})}async function Xn(e,t,n,r){for(;e.clock.now()<n;){if((await e.commands.run({executable:`adb`,args:o(`adb`,`shell`,[`getprop`,`sys.boot_completed`],[`-s`,t]),allowFailure:!0,timeoutMs:Math.min(1e4,Math.max(1e3,n-e.clock.now()))},r)).stdout.trim()===`1`)return;await e.clock.sleep(Gn,r)}throw Zn(`Android device failed to finish booting`,{serial:t})}function Zn(t,n){return new e(`COMMAND_FAILED`,t,{...n,reason:Me,hint:`The emulator keeps booting in the background. Retry once it is up, or pass a larger --timeout.`})}function Qn(e,t){return t.deadlineAtMs??e.clock.now()+12e4}function $n(e){return{platform:`android`,kind:`emulator`,...e.serial?{serial:e.serial}:{},...e.androidSerialAllowlist?{androidSerialAllowlist:[...e.androidSerialAllowlist]}:{}}}function er(e,t,n){let r=tr(t);return e.find(e=>e.platform===`android`&&e.kind===`emulator`&&tr(e.name)===r&&(!n||!B(e)||e.id===n))}function B(e){return e.id.startsWith(`emulator-`)}function tr(e){return e.toLowerCase().replaceAll(`_`,` `).replaceAll(/\s+/g,` `).trim()}async function nr(e,t,n){try{let r=await e.snapshot({appBundleId:t,signal:n,transient:{settleBy:Date.now()+6e3}});return{observation:`androidSnapshot`in r&&r.androidSnapshot?.systemSurfaceOnly===!0?`unobservable`:`observable`}}catch(e){return n.throwIfAborted(),c(e)?{observation:`unobservable`}:{observation:`probe-failed`,failure:rr(e)}}}function rr(e){let n=t(e),r=s(n)??n.details?.reason;return typeof r==`string`?{code:n.code,reason:r}:{code:n.code}}function ir(e){let{host:t,device:n,signal:r}=e,i=qe({device:n,signal:r,resolveInteractor:t.localInteractors.resolve});return Object.freeze({resolveOpenTarget:async e=>await t.androidApplications.resolveOpenTarget(n,e),prepareApplicationOpen:async e=>{await z(t,n,{headless:!1,deadlineAtMs:e.execution.startupDeadlineAtMs},r)},openApplication:async e=>await ar(t,i,e),applyRuntimeHints:async e=>await t.androidApplications.applyRuntimeHints(n,e),clearRuntimeHints:async e=>await t.androidApplications.clearRuntimeHints(n,e),closeApplication:async e=>{e.ensureReady&&await z(t,n,{headless:!1},r),await Ge({device:n,interactor:await i.resolveInteractor(e.execution,e.appBundleId),positionals:e.positionals})},finalizeApplicationClose:async e=>{await t.androidApplications.restoreTestIme(n,{stateDir:e.stateDir});let i=e.shutdownTarget&&n.kind===`emulator`?await t.deviceShutdown.android.shutdownTarget(n,r):void 0;return i===void 0?{}:{shutdown:i}},prepareAppleRunner:sr,configureProviderPortReverse:sr})}async function ar(t,n,r){let i={};if(r.relaunch&&r.target){let e=Date.now();await Ge({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:[r.appBundleId??r.target]}),i.relaunchCloseDurationMs=V(e)}if(f(r.runtimeHints)){if(!r.applyRuntimeHints)throw new e(`COMMAND_FAILED`,`Runtime hint operation was not admitted for this open.`,{reason:`runtime-hints-operation-missing`});let t=Date.now();await r.applyRuntimeHints({appId:r.appBundleId,values:r.runtimeHints}),i.runtimeHintsDurationMs=V(t)}let a=Date.now();await Je({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:r.positionals,appBundleId:r.appBundleId,execution:r.execution}),i.openDispatchDurationMs=V(a),r.enableTestIme&&await t.androidApplications.activateTestIme(n.device,{stateDir:r.stateDir});let o=Ke(r);if(o){let e=Date.now();await Je({device:n.device,interactor:await n.resolveInteractor({...r.execution,clearAppState:void 0,launchConsole:void 0,launchArgs:void 0},r.appBundleId),positionals:[o],appBundleId:r.appBundleId,execution:{...r.execution,clearAppState:void 0,launchConsole:void 0,launchArgs:void 0}}),i.launchUrlDurationMs=V(e)}else i.launchUrlDurationMs=0;let s=await t.androidApplications.inferOpenedAppBundleId(n.device,r.target,r.appBundleId);s&&await t.androidApplications.resetFramePerfStats(n.device,s);let c=Date.now();return Object.assign(i,await or(n,r,s)),i.postOpenSettleDurationMs=V(c),{appBundleId:s,timing:i}}async function or(e,t,r){if(!t.target||n(t.target))return{};if(!r)return{postOpenObservation:`app-unidentified`};let i=await nr(await e.resolveInteractor(t.execution,r),r,e.signal);return i.observation===`probe-failed`?{postOpenObservation:`probe-failed`,postOpenObservationFailure:i.failure}:{postOpenObservation:i.observation}}function V(e){return Math.max(0,Date.now()-e)}async function sr(){throw new e(`UNSUPPORTED_OPERATION`,`This lifecycle operation is unavailable for Android.`)}async function H(e,t,n,r,i){U(n);let a=r?void 0:await W(e,t,i);if(x.extname(n).toLowerCase()===`.aab`?await dr(e,t,n,i):K(await e.androidTools.installPackage(t,n,{replace:!0},i),`adb install failed`),r)return r;let o=[...await W(e,t,i)].filter(e=>!a?.has(e));return o.length===1?o[0]:void 0}function U(t){if(b()&&x.extname(t).toLowerCase()===`.aab`)throw new e(`UNSUPPORTED_OPERATION`,`Managed Android deployment does not support app bundles.`,{reason:`managed-bundle-install-unavailable`,hint:`Install an APK on this managed device.`})}async function cr(e,t,n,r){let i=await G(e,t,[`uninstall`,n],r);if(i.exitCode===0)return;let a=`${i.stdout}\n${i.stderr}`.toLowerCase();a.includes(`unknown package`)||a.includes(`not installed`)||K(i,`adb uninstall failed for ${n}`)}async function lr(t,n,r,i){let a=r.payload,s=typeof a.action==`string`&&a.action.trim()?a.action.trim():`${r.appId}.TEST_PUSH`,c=[`am`,`broadcast`,`-a`,s,`-p`,r.appId];typeof a.receiver==`string`&&a.receiver.trim()&&c.push(`-n`,a.receiver.trim());let l=a.extras??{};if(typeof l!=`object`||!l||Array.isArray(l))throw new e(`INVALID_ARGS`,`Android push payload extras must be an object`);let u=0;for(let[e,t]of Object.entries(l))e&&(fr(c,e,t),u+=1);return K(await G(t,n,o(`adb`,`shell`,c),i),`adb push broadcast failed`),{action:s,extrasCount:u}}function ur(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(/[._-]+/).map(e=>e.trim().toLowerCase()).filter(Boolean),r=[...n].reverse().find(e=>!t.has(e))??n.at(-1)??e;return r.charAt(0).toUpperCase()+r.slice(1)}async function dr(t,n,r,i){if(await t.androidTools.installBundle(n,r,`universal`,i))return;let a=await t.commands.which(`bundletool`),o=t.androidDeployment.bundletoolJar;if(!a&&!o)throw new e(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR.`);let s=a?`bundletool`:`java`,c=a?[]:[`-jar`,o],l=await t.temporaryFiles.create({prefix:`agent-device-aab-`,suffix:`.apks`}),u=l.path;try{K(await t.commands.run({executable:s,args:[...c,`build-apks`,`--bundle`,r,`--output`,u,`--mode`,`universal`]},i),`bundletool build-apks failed`),K(await t.commands.run({executable:s,args:[...c,`install-apks`,`--apks`,u,`--device-id`,n.id]},i),`bundletool install-apks failed`)}finally{await l[Symbol.asyncDispose]()}}async function W(e,t,n){let r=await G(e,t,o(`adb`,`shell`,[`pm`,`list`,`packages`]),n);return K(r,`adb package inventory failed`),new Set(r.stdout.split(`
@@ -1 +1 @@
1
- import{U as e}from"./sdk-contracts.js";function t(e){return Object.freeze({canShutdownTarget:n,shutdownTarget:async(t,n)=>await r(e.commands,t,n)})}function n(e){return e.platform===`android`&&e.kind===`emulator`}async function r(t,n,r){if(n.booted===!1)return i();r.throwIfAborted();try{let e=await t.run({executable:`adb`,args:[`-s`,n.id,`emu`,`kill`],allowFailure:!0,timeoutMs:15e3},r);r.throwIfAborted();let i=e.exitCode??-1;return{success:i===0,exitCode:i,stdout:e.stdout,stderr:e.stderr}}catch(t){r.throwIfAborted();let n=e(t);return{success:!1,exitCode:-1,stdout:``,stderr:n.message,error:n}}}function i(){return{success:!0,exitCode:0,stdout:``,stderr:``}}export{t as createAndroidShutdownRuntime};
1
+ import{q as e}from"./sdk-contracts.js";function t(e){return Object.freeze({canShutdownTarget:n,shutdownTarget:async(t,n)=>await r(e.commands,t,n)})}function n(e){return e.platform===`android`&&e.kind===`emulator`}async function r(t,n,r){if(n.booted===!1)return i();r.throwIfAborted();try{let e=await t.run({executable:`adb`,args:[`-s`,n.id,`emu`,`kill`],allowFailure:!0,timeoutMs:15e3},r);r.throwIfAborted();let i=e.exitCode??-1;return{success:i===0,exitCode:i,stdout:e.stdout,stderr:e.stderr}}catch(t){r.throwIfAborted();let n=e(t);return{success:!1,exitCode:-1,stdout:``,stderr:n.message,error:n}}}function i(){return{success:!0,exitCode:0,stdout:``,stderr:``}}export{t as createAndroidShutdownRuntime};