agent-device 0.21.3 → 0.21.5

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 (134) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.3.apk → agent-device-android-ime-helper-0.21.5.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.5.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.3.manifest.json → agent-device-android-ime-helper-0.21.5.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.3.apk → agent-device-android-snapshot-helper-0.21.5.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.5.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.5.manifest.json +16 -0
  7. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +39 -0
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +9 -1
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +2 -1
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +10 -1
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +26 -124
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +46 -0
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +36 -4
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +229 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +15 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +4 -40
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +6 -40
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +30 -9
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +22 -6
  20. package/dist/src/adapter.js +1 -1
  21. package/dist/src/adb-executor.js +2 -2
  22. package/dist/src/adb-failure.js +1 -1
  23. package/dist/src/agent-browser-process-record.js +1 -1
  24. package/dist/src/agent-device-client.js +2 -2
  25. package/dist/src/api.js +3 -11
  26. package/dist/src/app-launch.js +1 -1
  27. package/dist/src/app-lifecycle.js +1 -1
  28. package/dist/src/app-log-reconnect.js +1 -1
  29. package/dist/src/app-log-runtime2.js +1 -1
  30. package/dist/src/archive.js +2 -2
  31. package/dist/src/cli-help.js +2 -2
  32. package/dist/src/cli.js +4 -4
  33. package/dist/src/client-metro-companion.js +1 -1
  34. package/dist/src/client-metro.js +1 -1
  35. package/dist/src/client-types.d.ts +69 -4
  36. package/dist/src/code-signature-cache.js +1 -1
  37. package/dist/src/command-tools.js +2 -2
  38. package/dist/src/command.js +1 -1
  39. package/dist/src/connection-runtime.js +1 -1
  40. package/dist/src/contracts.js +1 -1
  41. package/dist/src/daemon-client-lifecycle.js +1 -1
  42. package/dist/src/daemon-shutdown-report.js +1 -1
  43. package/dist/src/device-claim-rule.js +1 -1
  44. package/dist/src/device-input-state.d.ts +10 -8
  45. package/dist/src/device-inventory-context.js +1 -1
  46. package/dist/src/device-session.js +1 -1
  47. package/dist/src/diagnostics.js +1 -1
  48. package/dist/src/error.js +2 -2
  49. package/dist/src/exec.js +1 -1
  50. package/dist/src/file.js +1 -1
  51. package/dist/src/find.js +1 -1
  52. package/dist/src/gesture-runtime.js +1 -1
  53. package/dist/src/helper.js +1 -1
  54. package/dist/src/index.js +1 -1
  55. package/dist/src/install-source-network-transport.js +1 -1
  56. package/dist/src/interaction2.js +1 -1
  57. package/dist/src/interactor.js +4 -4
  58. package/dist/src/internal/bin.js +1 -1
  59. package/dist/src/internal/daemon.js +2 -2
  60. package/dist/src/internal/png-worker.js +1 -1
  61. package/dist/src/ios-client.js +121 -7
  62. package/dist/src/ios-snapshot-adapter.js +1 -1
  63. package/dist/src/ios-system-surface.js +1 -1
  64. package/dist/src/limrun-delta-sync-omitted.js +1 -0
  65. package/dist/src/limrun.d.ts +0 -1598
  66. package/dist/src/location-coordinates.js +1 -1
  67. package/dist/src/mechanics.js +16 -16
  68. package/dist/src/output-common.js +2 -0
  69. package/dist/src/owner-identity.js +1 -1
  70. package/dist/src/perf-runtime-operation-builder.js +1 -1
  71. package/dist/src/perf-runtime-plan.js +1 -1
  72. package/dist/src/platform-runtime-android-adb-host.js +1 -1
  73. package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
  74. package/dist/src/platform-runtime-app-log-process.js +1 -1
  75. package/dist/src/platform-runtime-host.js +1 -1
  76. package/dist/src/platform-runtime-operation-host.js +2 -2
  77. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
  78. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  79. package/dist/src/platform-runtime-screen-recording-output-host.js +1 -1
  80. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  81. package/dist/src/process.js +1 -1
  82. package/dist/src/proxy.js +1 -1
  83. package/dist/src/quality-warnings.js +1 -1
  84. package/dist/src/react-native.js +1 -1
  85. package/dist/src/record-runtime.js +1 -1
  86. package/dist/src/recording-stop-observation.js +1 -0
  87. package/dist/src/registry.js +35 -36
  88. package/dist/src/replay-divergence.js +1 -1
  89. package/dist/src/reporting.js +11 -9
  90. package/dist/src/result-serialization.js +1 -1
  91. package/dist/src/runner-cache-metadata.js +1 -1
  92. package/dist/src/runner-client.js +1 -1
  93. package/dist/src/runner-disposal.js +1 -1
  94. package/dist/src/runner-operations-facade.js +1 -1
  95. package/dist/src/runner.js +1 -1
  96. package/dist/src/runtime.js +3 -3
  97. package/dist/src/runtime10.js +1 -1
  98. package/dist/src/runtime2.js +4 -4
  99. package/dist/src/runtime3.js +1 -1
  100. package/dist/src/runtime4.js +4 -4
  101. package/dist/src/runtime5.js +1 -1
  102. package/dist/src/runtime6.js +1 -1
  103. package/dist/src/runtime9.js +1 -1
  104. package/dist/src/screen-recording-completion.js +1 -1
  105. package/dist/src/screen-recording-resource-recovery.js +1 -1
  106. package/dist/src/screenshot-result.js +1 -1
  107. package/dist/src/sdk-contracts.js +2 -2
  108. package/dist/src/sdk-selectors.d.ts +36 -24
  109. package/dist/src/selector-runtime.js +1 -1
  110. package/dist/src/semantic-index.js +1 -1
  111. package/dist/src/session-observation.js +1 -1
  112. package/dist/src/session-snapshot.js +1 -1
  113. package/dist/src/session-store.js +2 -2
  114. package/dist/src/session2.js +5 -5
  115. package/dist/src/snapshot-process.js +1 -1
  116. package/dist/src/snapshot-runtime.js +1 -1
  117. package/dist/src/snapshot.js +1 -1
  118. package/dist/src/snapshot4.js +1 -1
  119. package/dist/src/stop-sequence.js +1 -0
  120. package/dist/src/success-text.js +1 -1
  121. package/dist/src/text-entry-focus.js +1 -0
  122. package/dist/src/tool-provider.js +1 -1
  123. package/dist/src/tool-provider2.js +1 -1
  124. package/dist/src/tool-provider3.js +1 -1
  125. package/dist/src/type-text-runtime.js +1 -1
  126. package/dist/src/video.js +2 -2
  127. package/dist/src/yauzl.js +1 -0
  128. package/package.json +2 -2
  129. package/server.json +2 -2
  130. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.3.apk.sha256 +0 -1
  131. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.3.apk.sha256 +0 -1
  132. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.3.manifest.json +0 -17
  133. package/dist/src/audio-probe-support.js +0 -1
  134. package/dist/src/screen-recording-live-handle.js +0 -1
@@ -0,0 +1,2 @@
1
+ import{n as e,t}from"./success-text.js";function n(e){return({result:t})=>e(t)}const r=n(i);function i(e){return{data:e,text:t(e)}}function a(n){let r=t(n),i=e(n);return i.length===0?r:[r,...i.map(e=>`Warning: ${o(e)}`)].filter(Boolean).join(`
2
+ `)}function o(e){return e.replaceAll(/\s*\n\s*/g,` `)}const s=n(e=>({data:e,text:a(e)}));function c(e,t){if(typeof e==`string`&&e.length!==0&&typeof t==`number`)return`@${e.startsWith(`@`)?e.slice(1):e}~s${t}`}export{c as a,s as i,i as n,n as o,r,o as t};
@@ -1,3 +1,3 @@
1
1
  import{r as e}from"./diagnostics.js";import{c as t,p as n}from"./exec.js";import{t as r}from"./timeouts.js";import i from"node:path";import a from"node:fs";import o from"node:crypto";function s(e){l(e.destination,t=>{e.mode===void 0?a.writeFileSync(t,e.contents,`utf8`):a.writeFileSync(t,e.contents,{encoding:`utf8`,mode:e.mode}),e.publish===`link-exclusive`?a.linkSync(t,e.destination):a.renameSync(t,e.destination)})}function c(e){let t=i.dirname(e.destination);l(e.destination,n=>{let r,i=!1,o;try{f(e.destination),r=a.openSync(n,`wx`,e.mode??384),a.writeFileSync(r,e.contents,`utf8`),a.fsyncSync(r),a.closeSync(r),r=void 0,f(e.destination),e.publish===`link-exclusive`?a.linkSync(n,e.destination):a.renameSync(n,e.destination),u(t)}catch(e){i=!0,o=e}if(r!==void 0)try{a.closeSync(r)}catch(e){i||(i=!0,o=e)}if(i)throw o})}function l(t,n){let r=d(t);try{return n(r)}finally{try{a.rmSync(r,{force:!0})}catch(n){e({level:`warn`,phase:`atomic_file_cleanup_failed`,data:{destination:t,temporaryPath:r,error:n instanceof Error?n.message:String(n)}})}}}function u(e){let t;try{t=a.openSync(e,`r`),a.fsyncSync(t)}catch{}finally{if(t!==void 0)try{a.closeSync(t)}catch{}}}function d(e){return i.join(i.dirname(e),`.${i.basename(e)}.${process.pid}-${o.randomUUID()}.tmp`)}function f(e){let t=p(e);if(t?.isSymbolicLink())throw Error(`Refusing to replace a durable file symbolic link: ${e}`);if(t&&!t.isFile())throw Error(`Refusing to replace a durable path that is not a regular file: ${e}`)}function p(e){try{return a.lstatSync(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}const m=1e3,h=process.platform===`win32`?`ps`:`/bin/ps`;function g(){return process.env}function _(e){return g()[e]}function v(e){process.stderr.write(e)}function y(){return process.cwd()}function b(){return process.execPath}function x(){return process.version}function S(){return process.platform}function C(){return process.pid}function w(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}function T(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(-e,0),!0}catch(e){return e.code===`EPERM`}}async function E(e,t=m){let[n,r,i]=await Promise.all([M(e,`lstart=`,t),M(e,`command=`,t),M(e,`state=`,t)]);return{startTime:n,command:r,zombie:i===null?null:i.startsWith(`Z`)}}function D(e){return j(e,`lstart=`)}function O(e){return j(e,`command=`)}function k(e){return j(e,`state=`)?.startsWith(`Z`)??!1}function A(e){let t=new Map,r=L(e);if(r.length===0)return t;try{let e=n(`ps`,[`-p`,r.join(`,`),`-o`,`pid=,state=,lstart=`],{allowFailure:!0,timeoutMs:m});if(e.exitCode!==0)return t;for(let n of e.stdout.split(`
2
2
  `)){let e=/^\s*(\d+)\s+(\S+)\s+(.+?)\s*$/.exec(n);if(!e)continue;let r=Number.parseInt(e[1],10);!Number.isInteger(r)||r<=0||t.set(r,{state:e[2],startTime:e[3]})}}catch{}return t}function j(e,t){if(!Number.isInteger(e)||e<=0)return null;try{return N(n(h,[`-p`,String(e),`-o`,t],{allowFailure:!0,timeoutMs:m}))}catch{return null}}async function M(e,n,r){if(!Number.isInteger(e)||e<=0)return null;try{return N(await t(h,[`-p`,String(e),`-o`,n],{allowFailure:!0,timeoutMs:r}))}catch{return null}}function N(e){if(e.exitCode!==0)return null;let t=e.stdout.trim();return t.length>0?t:null}function P(e){let t=[];for(let n of e.split(`
3
- `)){let e=/^\s*(\d+)\s+(\d+)\s+(.+?)\s*$/.exec(n);if(!e)continue;let r=Number.parseInt(e[1],10),i=Number.parseInt(e[2],10),a=e[3];!Number.isInteger(r)||r<=0||t.push({pid:r,ppid:Number.isInteger(i)&&i>0?i:void 0,command:a})}return t}async function F(e){let n=await(e.runCommand??t)(e.runCommand?`ps`:h,[`-ax`,`-o`,`pid=,ppid=,command=`],{allowFailure:!0,timeoutMs:e.timeoutMs});return n.exitCode===0?P(n.stdout):[]}function I(e,t){let n=new Set(L(e)),r=!0;for(;r;){r=!1;for(let e of t)e.ppid===void 0||!n.has(e.ppid)||n.has(e.pid)||(n.add(e.pid),r=!0)}return t.filter(e=>n.has(e.pid))}function L(e,t={}){return[...new Set(e)].filter(e=>Number.isInteger(e)&&e>0&&e!==t.excludePid)}function R(e,t){let n=L(e,{excludePid:process.pid}),r=0;for(let e of n)try{process.kill(e,t),r+=1}catch{}return r}function z(e,t){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(-e,t),!0}catch{return!1}}async function B(e,t){if(!w(e))return!0;let n=Date.now();for(;Date.now()-n<t;)if(await r(50),!w(e))return!0;return!w(e)}async function V(e){let t=L(e.pids,{excludePid:process.pid});t.length!==0&&(R(t,`SIGTERM`),await Promise.all(t.map(async t=>await B(t,e.termTimeoutMs))),R(t.filter(e=>w(e)),`SIGKILL`),await Promise.all(t.map(async t=>await B(t,e.killTimeoutMs))))}function H(){return{pid:process.pid,startTime:D(process.pid)}}function U(e,t){return e.pid===t.pid&&e.startTime===t.startTime}function W(e,t){return e.pid!==t.pid||!!(e.startTime&&t.startTime&&e.startTime!==t.startTime)}function G(e){return K(e)}function K(e,t){let{owner:n,stateDir:r}=e;if(!w(n.pid)||(t===void 0?k(n.pid):t?.state.startsWith(`Z`)))return`owner-process-dead`;if(n.startTime){let e=t===void 0?D(n.pid):t?.startTime??null;if(e!==null&&e!==n.startTime)return`owner-process-reused`}if(!r)return`live`;try{return a.statSync(r),`live`}catch(e){let t=e?.code;return t===`ENOENT`||t===`ENOTDIR`?`owner-state-dir-gone`:`unknown`}}export{z as C,c as D,v as E,s as O,R as S,B as T,_,H as a,E as b,g as c,S as d,C as f,F as g,k as h,U as i,l as k,b as l,T as m,K as n,I as o,w as p,W as r,y as s,G as t,x as u,A as v,V as w,D as x,O as y};
3
+ `)){let e=/^\s*(\d+)\s+(\d+)\s+(.+?)\s*$/.exec(n);if(!e)continue;let r=Number.parseInt(e[1],10),i=Number.parseInt(e[2],10),a=e[3];!Number.isInteger(r)||r<=0||t.push({pid:r,ppid:Number.isInteger(i)&&i>0?i:void 0,command:a})}return t}async function F(e){let n=await(e.runCommand??t)(e.runCommand?`ps`:h,[`-ax`,`-o`,`pid=,ppid=,command=`],{allowFailure:!0,timeoutMs:e.timeoutMs});return n.exitCode===0?P(n.stdout):[]}function I(e,t){let n=new Set(L(e)),r=!0;for(;r;){r=!1;for(let e of t)e.ppid===void 0||!n.has(e.ppid)||n.has(e.pid)||(n.add(e.pid),r=!0)}return t.filter(e=>n.has(e.pid))}function L(e,t={}){return[...new Set(e)].filter(e=>Number.isInteger(e)&&e>0&&e!==t.excludePid)}function R(e,t){let n=L(e,{excludePid:process.pid}),r=0;for(let e of n)try{process.kill(e,t),r+=1}catch{}return r}async function z(e,t){if(!w(e))return!0;let n=Date.now();for(;Date.now()-n<t;)if(await r(50),!w(e))return!0;return!w(e)}async function B(e){let t=L(e.pids,{excludePid:process.pid});t.length!==0&&(R(t,`SIGTERM`),await Promise.all(t.map(async t=>await z(t,e.termTimeoutMs))),R(t.filter(e=>w(e)),`SIGKILL`),await Promise.all(t.map(async t=>await z(t,e.killTimeoutMs))))}function V(){return{pid:process.pid,startTime:D(process.pid)}}function H(e,t){return e.pid===t.pid&&e.startTime===t.startTime}function U(e,t){return e.pid!==t.pid||!!(e.startTime&&t.startTime&&e.startTime!==t.startTime)}function W(e){return G(e)}function G(e,t){let{owner:n,stateDir:r}=e;if(!w(n.pid)||(t===void 0?k(n.pid):t?.state.startsWith(`Z`)))return`owner-process-dead`;if(n.startTime){let e=t===void 0?D(n.pid):t?.startTime??null;if(e!==null&&e!==n.startTime)return`owner-process-reused`}if(!r)return`live`;try{return a.statSync(r),`live`}catch(e){let t=e?.code;return t===`ENOENT`||t===`ENOTDIR`?`owner-state-dir-gone`:`unknown`}}export{B as C,s as D,c as E,l as O,R as S,v as T,_,V as a,E as b,g as c,S as d,C as f,F as g,k as h,H as i,b as l,T as m,G as n,I as o,w as p,U as r,y as s,W as t,x as u,A as v,z as w,D as x,O as y};
@@ -1 +1 @@
1
- import{C as e,M as t}from"./sdk-contracts.js";async function n(e){try{return{available:!0,...await e}}catch(e){let n=t(e);return{available:!1,reason:n.message,error:n}}}function r(e,t){return{available:!1,reason:`No ${e} app ${t} is associated with this session. Run open <app> first.`}}function i(e,t,n,r){return{artifact:{available:!1,kind:t,reason:`${e} perf memory snapshot does not support ${t}.`,hint:r,support:n},support:n}}function a(){return new e(`INVALID_ARGS`,`perf memory snapshot requires an active app session`,{hint:`Run open <app> first so perf memory snapshot can resolve the app process.`})}function o(t){return Object.freeze({perfNativeCaptureStart:t.start,perfNativeCaptureReattach:t.reattach,perfNativeCaptureCleanup:t.cleanup,perfProfileReport:async n=>{if(n.kind!==t.expectedProfileKind)throw new e(`INVALID_ARGS`,`${t.platform} native perf requires --kind ${t.expectedProfileKind}, not ${n.kind}`);return await t.writeProfileReport(n)}})}export{i as a,n as i,r as n,a as r,o as t};
1
+ import{C as e,N as t}from"./sdk-contracts.js";async function n(e){try{return{available:!0,...await e}}catch(e){let n=t(e);return{available:!1,reason:n.message,error:n}}}function r(e,t){return{available:!1,reason:`No ${e} app ${t} is associated with this session. Run open <app> first.`}}function i(e,t,n,r){return{artifact:{available:!1,kind:t,reason:`${e} perf memory snapshot does not support ${t}.`,hint:r,support:n},support:n}}function a(){return new e(`INVALID_ARGS`,`perf memory snapshot requires an active app session`,{hint:`Run open <app> first so perf memory snapshot can resolve the app process.`})}function o(t){return Object.freeze({perfNativeCaptureStart:t.start,perfNativeCaptureReattach:t.reattach,perfNativeCaptureCleanup:t.cleanup,perfProfileReport:async n=>{if(n.kind!==t.expectedProfileKind)throw new e(`INVALID_ARGS`,`${t.platform} native perf requires --kind ${t.expectedProfileKind}, not ${n.kind}`);return await t.writeProfileReport(n)}})}export{i as a,n as i,r as n,a as r,o as t};
@@ -1 +1 @@
1
- import{C as e,M as t}from"./sdk-contracts.js";import{S as n,c as r,w as i}from"./sdk-device.js";import{At as a,Dt as o,Et as s,Tt as c,kt as l}from"./sdk-batch.js";import{m as u}from"./observability.js";import{r as d}from"./diagnostics.js";import{O as ee,a as f,i as p}from"./owner-identity.js";import{t as m}from"./file.js";import"./diagnostics2.js";import"./process.js";import{c as h,i as g,l as _,r as v,s as y,t as b,u as x}from"./device-claim-inspection.js";import{l as S,u as C}from"./screen-recording-resource-recovery.js";import w from"node:path";import T from"node:fs";import E from"node:crypto";async function te(e){let t=await e.observeDeviceBoot?.observeBootTimeMs(e.device);if(t?.observed!==!0||t.bootedAtMs<=e.claim.updatedAtMs)return;let{session:n,workspace:r,stateDir:i}=e.claim;return{session:n,workspace:r,stateDir:i,bootedAtMs:t.bootedAtMs}}function ne(e){d({level:`info`,phase:`device_claim_reboot_released`,data:{deviceKey:e.deviceKey,ownerSession:e.claim.session,ownerStateDir:e.claim.stateDir,ownerWorkspace:e.claim.workspace,claimUpdatedAtMs:e.claim.updatedAtMs,deviceBootedAtMs:e.bootedAtMs}})}function D(e){let t=_(e.deviceKey);T.mkdirSync(w.dirname(t),{recursive:!0,mode:448}),ee({destination:t,contents:`${JSON.stringify(e)}\n`,mode:384})}async function O(e,t){let n=f(),r=await m({lockDirPath:`${_(e)}.lock`,owner:{pid:n.pid,startTime:n.startTime,acquiredAtMs:Date.now()},timeoutMs:3e4,description:`device claim for ${e}`});try{return await t()}finally{await r()}}async function re(e){let t=v(_(e.deviceKey));return t?t.claim&&se(t.claim,e.stateDir,e.owner)?(F(e.deviceKey,t.claim),{status:`available`}):t.claim&&M(t.claim,e,e.owner)?{status:`held`,ownership:ie(t.claim)}:await ae(t,e):{status:`available`}}function ie(e){if(e.updatedAtMs>=Date.now())return y(e);let t={...e,updatedAtMs:Date.now()};return D(t),y(t)}async function ae(e,t){let n=e.claim;if(!n)return N(t.deviceKey,e),{status:`conflict`,conflict:e};let r=await oe({classification:e.classification,claim:n,device:t.device,observeDeviceBoot:t.observeDeviceBoot});if(!r.settles)return N(t.deviceKey,e),{status:`conflict`,conflict:e};let i=await k(n,t.reconcileOrphanedDeviceClaim);return i.status===`retained`?(N(t.deviceKey,e,i.reason),{status:`conflict`,conflict:e}):r.tookOver?(ne({deviceKey:t.deviceKey,claim:n,bootedAtMs:r.tookOver.bootedAtMs}),{status:`available`,tookOver:r.tookOver}):{status:`available`}}async function oe(e){if(b(e.classification))return{settles:!0};let t=await te(e);return t?{settles:!0,tookOver:t}:{settles:!1}}async function k(e,t){let n=await t(e);if(n.status===`retained`)return n;try{T.unlinkSync(_(e.deviceKey))}catch(e){if(e.code!==`ENOENT`)throw e}return{status:`reconciled`}}function A(e,t,n){return e.stateDir===t&&p({pid:e.ownerPid,startTime:e.ownerStartTime},n)}function j(e){return e.abandonedAtMs!==void 0}function se(e,t,n){return j(e)&&A(e,t,n)}function M(e,t,n){return e.session===t.session&&e.workspace===t.workspace&&A(e,t.stateDir,n)}function N(e,t,n){d({level:`warn`,phase:`device_claim_conflict`,data:{deviceKey:e,classification:t.classification,...P(t),...n?{reconciliationReason:n}:{}}})}function P(e){return e.allocatorClaim?{ownerStateDir:e.allocatorClaim.stateDir,allocatorInstanceId:e.allocatorClaim.allocator.instanceId,identityIncarnationId:e.allocatorClaim.allocator.identityIncarnationId}:{ownerSession:e.claim?.session,ownerStateDir:e.claim?.stateDir}}function F(e,t){d({level:`info`,phase:`device_claim_abandoned_superseded`,data:{deviceKey:e,abandonedSession:t.session,abandonedAtMs:t.abandonedAtMs}})}function I(e){return`transient:${e}`}async function L(e){let t=V(e.device),n=h(t);return await O(n,async()=>await z({...e,deviceKey:n,identity:t}))}async function R(e){let t=V(e.device),n=h(t);return await O(n,async()=>{let r=v(_(n));return r?.claim&&!j(r.claim)&&A(r.claim,e.stateDir,f())?{status:`covered-by-owned-claim`}:await z({device:e.device,deviceKey:n,identity:t,session:I(e.command),workspace:e.workspace,stateDir:e.stateDir,reconcileOrphanedDeviceClaim:e.reconcileOrphanedDeviceClaim})})}async function z(e){let{deviceKey:t,identity:n}=e,r=f(),i=await re({...e,owner:r});if(i.status===`conflict`)return i;if(i.status===`held`)return{status:`acquired`,ownership:i.ownership};let a=Date.now(),o={schemaVersion:2,deviceKey:t,device:{...n,name:e.device.name},session:e.session,workspace:e.workspace,stateDir:e.stateDir,ownerPid:r.pid,ownerStartTime:r.startTime,ownerToken:E.randomUUID(),createdAtMs:a,updatedAtMs:a};return D(o),{status:`acquired`,ownership:y(o),...i.tookOver?{tookOver:i.tookOver}:{}}}function B(e){let t=h(V(e)),n=v(_(t))?.claim;return n!==void 0&&n.deviceKey===t&&!j(n)&&p({pid:n.ownerPid,startTime:n.ownerStartTime},f())}function V(e){return i({...e,...r(e.platform)?{appleOs:n(e)}:{}})}async function H(e){let t=[];for(let n of g(e.selectors))t.push(await U(n,e.reconcile));return t}async function U(e,t){let n=e.claim,r={fileName:e.fileName,classification:e.classification,...e.deviceKey?{deviceKey:e.deviceKey}:{},...n?{device:n.device,session:n.session,workspace:n.workspace,stateDir:n.stateDir}:{},...e.allocatorClaim?{device:e.allocatorClaim.device,stateDir:e.allocatorClaim.stateDir,allocator:e.allocatorClaim.allocator}:{}};if(!n||!b(e.classification))return{...r,status:`refused`,reason:G(e.classification)};if(_(n.deviceKey)!==w.join(x(),e.fileName))return{...r,status:`refused`,reason:`claim-file-name-mismatch`};let{deviceKey:i,ownerToken:a}=n;return await O(i,async()=>{let e=v(_(i));if(!e?.claim||e.claim.ownerToken!==a||!b(e.classification))return{...r,status:`changed`,reason:`claim-changed-during-release`};let o=await k(e.claim,t);return o.status===`retained`?{...r,status:`retained`,reason:o.reason}:(d({level:`info`,phase:`device_claim_stale_released`,data:{deviceKey:i,ownerSession:n.session,ownerStateDir:n.stateDir}}),{...r,status:`released`})})}const W=Object.freeze({live:`live-owner`,"owner-process-reused":`owner-pid-reused`,"owner-state-dir-gone":`owner-process-still-running`,unknown:`owner-liveness-unknown`,inconsistent:`claim-record-inconsistent`,"allocator-inconsistent":`allocator-claim-record-inconsistent`,"allocator-held":`allocator-held-owner`,"owner-process-dead":`claim-record-unreadable`,"owner-daemon-superseded":`claim-record-unreadable`});function G(e){return W[e]}async function K(e){return e?await q(e,(e,t)=>{try{T.unlinkSync(t)}catch(e){if(e.code!==`ENOENT`)throw e;return`absent`}return`deleted`},e=>e?`ownership-changed`:`absent`):`absent`}async function ce(e){return e?await q(e,e=>{let t=Date.now();return D({...e,abandonedAtMs:t,updatedAtMs:t}),`abandoned`},e=>e?`ownership-changed`:`absent`):`absent`}async function le(e){return e?await q(e,e=>(D({...e,updatedAtMs:Date.now()}),{status:`renewed`}),e=>({status:`lost`,conflict:e})):{status:`lost`,conflict:void 0}}async function q(e,t,n){return await O(e.deviceKey,async()=>{let r=_(e.deviceKey),i=v(r);if(!i)return n(void 0);let a=i.claim;return!a||!ue(a,e)?n(i):t(a,r)})}function ue(e,t){return e.ownerToken===t.ownerToken&&p({pid:e.ownerPid,startTime:e.ownerStartTime},{pid:t.ownerPid,startTime:t.ownerStartTime})}async function de(e,t){let n=x(),r;try{r=T.readdirSync(n,{withFileTypes:!0})}catch{return{examined:0,reconciled:0,retained:0,changed:0}}let i=0,a=0,o=0,s=0;for(let c of r){if(!c.isFile()||!c.name.endsWith(`.json`))continue;let r=w.join(n,c.name),l=v(r);if(!l?.claim||!J(l.classification,l.claim.stateDir,t))continue;i+=1;let{deviceKey:u,ownerToken:d}=l.claim;if(_(u)!==r){o+=1;continue}await O(u,async()=>{let n=v(r);if(!n?.claim||!J(n.classification,n.claim.stateDir,t)||n.claim.ownerToken!==d){s+=1;return}if((await k(n.claim,e)).status===`retained`){o+=1;return}a+=1})}return{examined:i,reconciled:a,retained:o,changed:s}}function J(e,t,n){return b(e)?e!==`owner-daemon-superseded`||w.resolve(t)===w.resolve(n):!1}const Y=C({resourceKind:`app-log`,fileName:`app-log.resource.json`,displayName:`App-log`}),X=S({resourceKind:`app-log`,displayName:`app-log`,store:Y,sessionSlot:{read:e=>e.appLog,replace:(e,t)=>({...e,appLog:t,appLogFailure:void 0})},completionMetadata:e=>({backend:e.backend,outputPath:e.outputPath,completedAt:e.completedAt}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no app log stream active`,cleanupPendingHint:`Keep app-log.resource.json and retry cleanup through its exact runtime owner.`}});function fe(e){if(e.appLog){let t=e.appLog.handle.inspect();return{active:t.state===`active`||t.state===`recovering`,...t}}return e.appLogFailure?{active:!1,state:`failed`,backend:e.appLogFailure.backend,failureCode:e.appLogFailure.code,failureMessage:e.appLogFailure.message,hint:e.appLogFailure.hint}:{active:!1,state:`inactive`}}function pe(e){return X.adoptStarted(e)}function me(e){return X.finishLive(e)}function he(e){return X.forceCleanupLive(e)}function ge(e){let n=t(e.error);return e.sessionStore.set(e.sessionName,{...e.session,appLog:void 0,appLogFailure:{backend:e.backend,code:n.code,message:n.message,hint:n.hint}}),n}function _e(e){e.sessionStore.set(e.sessionName,{...e.session,appLogFailure:void 0})}const ve=C({resourceKind:`audio-probe`,fileName:`audio-probe.resource.json`,displayName:`Audio probe`}),Z=S({resourceKind:`audio-probe`,displayName:`audio probe`,store:ve,sessionSlot:{read:e=>e.audioProbe,replace:(e,t)=>({...e,audioProbe:t})},completionMetadata:e=>({backend:e.backend??`unknown`,source:e.source,durationMs:e.durationMs,elapsedMs:e.elapsedMs,bucketMs:e.bucketMs,sampleCount:e.sampleCount,heard:e.heard}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no active audio probe`,cleanupPendingHint:`Keep audio-probe.resource.json and retry stop through its exact runtime owner.`}});function ye(e){return Z.adoptStarted(e)}function be(e){return Z.finishLive(e)}const xe=C({resourceKind:`perf-capture`,fileName:`perf-capture.resource.json`,displayName:`Perf capture`}),Q=S({resourceKind:`perf-capture`,displayName:`perf capture`,store:xe,sessionSlot:{read:e=>e.perfCapture,replace:(e,t)=>({...e,perfCapture:t})},completionMetadata:e=>({kind:typeof e.kind==`string`?e.kind:`unknown`,mode:typeof e.mode==`string`?e.mode:`unknown`,...typeof e.outPath==`string`?{outPath:e.outPath}:{}}),failedFinishPolicy:`preserve-retry-material`,messages:{noActive:`no active native perf capture`,cleanupPendingHint:`Keep perf-capture.resource.json and retry stop through its exact runtime owner.`}});function Se(e){return Q.adoptStarted(e)}function $(e){return Q.finishLive(e)}function Ce(e){if(e.area===`frames`)return Object.freeze({kind:`frames`,request:e,use:c});if(e.area===`memory`)return e.action===`snapshot`?Object.freeze({kind:`memory-snapshot`,request:e,use:o}):Object.freeze({kind:`memory-sample`,request:e,use:s});if(e.area===`trace`)return e.action===`start`?Object.freeze({kind:`capture-start`,request:e,use:l}):Object.freeze({kind:`capture-stop`,request:e});switch(e.action){case`start`:return Object.freeze({kind:`capture-start`,request:e,use:l});case`stop`:return Object.freeze({kind:`capture-stop`,request:e});case`report`:return Object.freeze({kind:`profile-report`,request:e,use:a})}}function we(t){let n=t.positionals??[],r=n[0]?.toLowerCase();if(r===`frames`){let i=n[1]?.toLowerCase();if(i!==void 0&&i!==`sample`||n.length>2||t.kind!==void 0)throw new e(`INVALID_ARGS`,`perf action must be frames, memory sample|snapshot, cpu profile start|stop|report, or trace start|stop`);return Object.freeze({area:r,action:`sample`})}if(r===`memory`)return Te(n,t);if(r===`cpu`)return Ee(n,t.outPath);if(r===`trace`)return De(n,t.outPath);throw new e(`INVALID_ARGS`,`perf requires frames, memory, cpu, or trace`)}function Te(t,n){let r=(t[1]??`sample`).toLowerCase();if(r!==`sample`&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`perf memory requires sample or snapshot`);if(n.kind!==void 0&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(r===`sample`&&t.length>2)throw new e(`INVALID_ARGS`,`perf memory sample does not accept additional positionals`);if(r===`snapshot`&&t.length>3)throw new e(`INVALID_ARGS`,`perf memory snapshot accepts at most one positional kind`);let i=n.kind??t[2];if(i!==void 0&&!u(i))throw new e(`INVALID_ARGS`,`perf memory snapshot --kind must be android-hprof or memgraph`);return Object.freeze({area:`memory`,action:r,...i===void 0?{}:{kind:i},...n.outPath===void 0?{}:{outPath:n.outPath}})}function Ee(t,n){if(t[1]?.toLowerCase()!==`profile`)throw new e(`INVALID_ARGS`,`perf cpu requires profile`);let r=t[2]?.toLowerCase();if(r!==`start`&&r!==`stop`&&r!==`report`)throw new e(`INVALID_ARGS`,`perf cpu profile action must be start, stop, or report`);let i=t[3]?.toLowerCase();if(i!==`xctrace`&&i!==`simpleperf`)throw new e(`INVALID_ARGS`,`perf cpu profile requires --kind xctrace or simpleperf`);let a=n??t[5];return Object.freeze({area:`cpu`,subject:`profile`,action:r,kind:i,...t[4]?{template:t[4]}:{},...a?{outPath:a}:{},...t[6]?{tracePath:t[6]}:{}})}function De(t,n){let r=t[1]?.toLowerCase();if(r!==`start`&&r!==`stop`)throw new e(`INVALID_ARGS`,`perf trace action must be start or stop`);let i=t[2]?.toLowerCase();if(i!==`xctrace`&&i!==`perfetto`)throw new e(`INVALID_ARGS`,`perf trace requires --kind xctrace or perfetto`);let a=n??t[4];return Object.freeze({area:`trace`,action:r,kind:i,...t[3]?{template:t[3]}:{},...a?{outPath:a}:{}})}export{de as C,B as S,le as T,ce as _,Q as a,K as b,be as c,_e as d,me as f,Y as g,ge as h,$ as i,pe as l,fe as m,Ce as n,ye as o,he as p,Se as r,Z as s,we as t,X as u,L as v,H as w,V as x,R as y};
1
+ import{C as e,N as t}from"./sdk-contracts.js";import{S as n,c as r,w as i}from"./sdk-device.js";import{At as a,Dt as o,Et as s,Tt as c,kt as l}from"./sdk-batch.js";import{m as u}from"./observability.js";import{r as d}from"./diagnostics.js";import{D as ee,a as f,i as p}from"./owner-identity.js";import{t as m}from"./file.js";import"./diagnostics2.js";import"./process.js";import{c as h,i as g,l as _,r as v,s as y,t as b,u as x}from"./device-claim-inspection.js";import{l as S,u as C}from"./screen-recording-resource-recovery.js";import w from"node:path";import T from"node:fs";import E from"node:crypto";async function te(e){let t=await e.observeDeviceBoot?.observeBootTimeMs(e.device);if(t?.observed!==!0||t.bootedAtMs<=e.claim.updatedAtMs)return;let{session:n,workspace:r,stateDir:i}=e.claim;return{session:n,workspace:r,stateDir:i,bootedAtMs:t.bootedAtMs}}function ne(e){d({level:`info`,phase:`device_claim_reboot_released`,data:{deviceKey:e.deviceKey,ownerSession:e.claim.session,ownerStateDir:e.claim.stateDir,ownerWorkspace:e.claim.workspace,claimUpdatedAtMs:e.claim.updatedAtMs,deviceBootedAtMs:e.bootedAtMs}})}function D(e){let t=_(e.deviceKey);T.mkdirSync(w.dirname(t),{recursive:!0,mode:448}),ee({destination:t,contents:`${JSON.stringify(e)}\n`,mode:384})}async function O(e,t){let n=f(),r=await m({lockDirPath:`${_(e)}.lock`,owner:{pid:n.pid,startTime:n.startTime,acquiredAtMs:Date.now()},timeoutMs:3e4,description:`device claim for ${e}`});try{return await t()}finally{await r()}}async function re(e){let t=v(_(e.deviceKey));return t?t.claim&&se(t.claim,e.stateDir,e.owner)?(F(e.deviceKey,t.claim),{status:`available`}):t.claim&&M(t.claim,e,e.owner)?{status:`held`,ownership:ie(t.claim)}:await ae(t,e):{status:`available`}}function ie(e){if(e.updatedAtMs>=Date.now())return y(e);let t={...e,updatedAtMs:Date.now()};return D(t),y(t)}async function ae(e,t){let n=e.claim;if(!n)return N(t.deviceKey,e),{status:`conflict`,conflict:e};let r=await oe({classification:e.classification,claim:n,device:t.device,observeDeviceBoot:t.observeDeviceBoot});if(!r.settles)return N(t.deviceKey,e),{status:`conflict`,conflict:e};let i=await k(n,t.reconcileOrphanedDeviceClaim);return i.status===`retained`?(N(t.deviceKey,e,i.reason),{status:`conflict`,conflict:e}):r.tookOver?(ne({deviceKey:t.deviceKey,claim:n,bootedAtMs:r.tookOver.bootedAtMs}),{status:`available`,tookOver:r.tookOver}):{status:`available`}}async function oe(e){if(b(e.classification))return{settles:!0};let t=await te(e);return t?{settles:!0,tookOver:t}:{settles:!1}}async function k(e,t){let n=await t(e);if(n.status===`retained`)return n;try{T.unlinkSync(_(e.deviceKey))}catch(e){if(e.code!==`ENOENT`)throw e}return{status:`reconciled`}}function A(e,t,n){return e.stateDir===t&&p({pid:e.ownerPid,startTime:e.ownerStartTime},n)}function j(e){return e.abandonedAtMs!==void 0}function se(e,t,n){return j(e)&&A(e,t,n)}function M(e,t,n){return e.session===t.session&&e.workspace===t.workspace&&A(e,t.stateDir,n)}function N(e,t,n){d({level:`warn`,phase:`device_claim_conflict`,data:{deviceKey:e,classification:t.classification,...P(t),...n?{reconciliationReason:n}:{}}})}function P(e){return e.allocatorClaim?{ownerStateDir:e.allocatorClaim.stateDir,allocatorInstanceId:e.allocatorClaim.allocator.instanceId,identityIncarnationId:e.allocatorClaim.allocator.identityIncarnationId}:{ownerSession:e.claim?.session,ownerStateDir:e.claim?.stateDir}}function F(e,t){d({level:`info`,phase:`device_claim_abandoned_superseded`,data:{deviceKey:e,abandonedSession:t.session,abandonedAtMs:t.abandonedAtMs}})}function I(e){return`transient:${e}`}async function L(e){let t=V(e.device),n=h(t);return await O(n,async()=>await z({...e,deviceKey:n,identity:t}))}async function R(e){let t=V(e.device),n=h(t);return await O(n,async()=>{let r=v(_(n));return r?.claim&&!j(r.claim)&&A(r.claim,e.stateDir,f())?{status:`covered-by-owned-claim`}:await z({device:e.device,deviceKey:n,identity:t,session:I(e.command),workspace:e.workspace,stateDir:e.stateDir,reconcileOrphanedDeviceClaim:e.reconcileOrphanedDeviceClaim})})}async function z(e){let{deviceKey:t,identity:n}=e,r=f(),i=await re({...e,owner:r});if(i.status===`conflict`)return i;if(i.status===`held`)return{status:`acquired`,ownership:i.ownership};let a=Date.now(),o={schemaVersion:2,deviceKey:t,device:{...n,name:e.device.name},session:e.session,workspace:e.workspace,stateDir:e.stateDir,ownerPid:r.pid,ownerStartTime:r.startTime,ownerToken:E.randomUUID(),createdAtMs:a,updatedAtMs:a};return D(o),{status:`acquired`,ownership:y(o),...i.tookOver?{tookOver:i.tookOver}:{}}}function B(e){let t=h(V(e)),n=v(_(t))?.claim;return n!==void 0&&n.deviceKey===t&&!j(n)&&p({pid:n.ownerPid,startTime:n.ownerStartTime},f())}function V(e){return i({...e,...r(e.platform)?{appleOs:n(e)}:{}})}async function H(e){let t=[];for(let n of g(e.selectors))t.push(await U(n,e.reconcile));return t}async function U(e,t){let n=e.claim,r={fileName:e.fileName,classification:e.classification,...e.deviceKey?{deviceKey:e.deviceKey}:{},...n?{device:n.device,session:n.session,workspace:n.workspace,stateDir:n.stateDir}:{},...e.allocatorClaim?{device:e.allocatorClaim.device,stateDir:e.allocatorClaim.stateDir,allocator:e.allocatorClaim.allocator}:{}};if(!n||!b(e.classification))return{...r,status:`refused`,reason:G(e.classification)};if(_(n.deviceKey)!==w.join(x(),e.fileName))return{...r,status:`refused`,reason:`claim-file-name-mismatch`};let{deviceKey:i,ownerToken:a}=n;return await O(i,async()=>{let e=v(_(i));if(!e?.claim||e.claim.ownerToken!==a||!b(e.classification))return{...r,status:`changed`,reason:`claim-changed-during-release`};let o=await k(e.claim,t);return o.status===`retained`?{...r,status:`retained`,reason:o.reason}:(d({level:`info`,phase:`device_claim_stale_released`,data:{deviceKey:i,ownerSession:n.session,ownerStateDir:n.stateDir}}),{...r,status:`released`})})}const W=Object.freeze({live:`live-owner`,"owner-process-reused":`owner-pid-reused`,"owner-state-dir-gone":`owner-process-still-running`,unknown:`owner-liveness-unknown`,inconsistent:`claim-record-inconsistent`,"allocator-inconsistent":`allocator-claim-record-inconsistent`,"allocator-held":`allocator-held-owner`,"owner-process-dead":`claim-record-unreadable`,"owner-daemon-superseded":`claim-record-unreadable`});function G(e){return W[e]}async function K(e){return e?await q(e,(e,t)=>{try{T.unlinkSync(t)}catch(e){if(e.code!==`ENOENT`)throw e;return`absent`}return`deleted`},e=>e?`ownership-changed`:`absent`):`absent`}async function ce(e){return e?await q(e,e=>{let t=Date.now();return D({...e,abandonedAtMs:t,updatedAtMs:t}),`abandoned`},e=>e?`ownership-changed`:`absent`):`absent`}async function le(e){return e?await q(e,e=>(D({...e,updatedAtMs:Date.now()}),{status:`renewed`}),e=>({status:`lost`,conflict:e})):{status:`lost`,conflict:void 0}}async function q(e,t,n){return await O(e.deviceKey,async()=>{let r=_(e.deviceKey),i=v(r);if(!i)return n(void 0);let a=i.claim;return!a||!ue(a,e)?n(i):t(a,r)})}function ue(e,t){return e.ownerToken===t.ownerToken&&p({pid:e.ownerPid,startTime:e.ownerStartTime},{pid:t.ownerPid,startTime:t.ownerStartTime})}async function de(e,t){let n=x(),r;try{r=T.readdirSync(n,{withFileTypes:!0})}catch{return{examined:0,reconciled:0,retained:0,changed:0}}let i=0,a=0,o=0,s=0;for(let c of r){if(!c.isFile()||!c.name.endsWith(`.json`))continue;let r=w.join(n,c.name),l=v(r);if(!l?.claim||!J(l.classification,l.claim.stateDir,t))continue;i+=1;let{deviceKey:u,ownerToken:d}=l.claim;if(_(u)!==r){o+=1;continue}await O(u,async()=>{let n=v(r);if(!n?.claim||!J(n.classification,n.claim.stateDir,t)||n.claim.ownerToken!==d){s+=1;return}if((await k(n.claim,e)).status===`retained`){o+=1;return}a+=1})}return{examined:i,reconciled:a,retained:o,changed:s}}function J(e,t,n){return b(e)?e!==`owner-daemon-superseded`||w.resolve(t)===w.resolve(n):!1}const Y=C({resourceKind:`app-log`,fileName:`app-log.resource.json`,displayName:`App-log`}),X=S({resourceKind:`app-log`,displayName:`app-log`,store:Y,sessionSlot:{read:e=>e.appLog,replace:(e,t)=>({...e,appLog:t,appLogFailure:void 0})},completionMetadata:e=>({backend:e.backend,outputPath:e.outputPath,completedAt:e.completedAt}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no app log stream active`,cleanupPendingHint:`Keep app-log.resource.json and retry cleanup through its exact runtime owner.`}});function fe(e){if(e.appLog){let t=e.appLog.handle.inspect();return{active:t.state===`active`||t.state===`recovering`,...t}}return e.appLogFailure?{active:!1,state:`failed`,backend:e.appLogFailure.backend,failureCode:e.appLogFailure.code,failureMessage:e.appLogFailure.message,hint:e.appLogFailure.hint}:{active:!1,state:`inactive`}}function pe(e){return X.adoptStarted(e)}function me(e){return X.finishLive(e)}function he(e){return X.forceCleanupLive(e)}function ge(e){let n=t(e.error);return e.sessionStore.set(e.sessionName,{...e.session,appLog:void 0,appLogFailure:{backend:e.backend,code:n.code,message:n.message,hint:n.hint}}),n}function _e(e){e.sessionStore.set(e.sessionName,{...e.session,appLogFailure:void 0})}const ve=C({resourceKind:`audio-probe`,fileName:`audio-probe.resource.json`,displayName:`Audio probe`}),Z=S({resourceKind:`audio-probe`,displayName:`audio probe`,store:ve,sessionSlot:{read:e=>e.audioProbe,replace:(e,t)=>({...e,audioProbe:t})},completionMetadata:e=>({backend:e.backend??`unknown`,source:e.source,durationMs:e.durationMs,elapsedMs:e.elapsedMs,bucketMs:e.bucketMs,sampleCount:e.sampleCount,heard:e.heard}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no active audio probe`,cleanupPendingHint:`Keep audio-probe.resource.json and retry stop through its exact runtime owner.`}});function ye(e){return Z.adoptStarted(e)}function be(e){return Z.finishLive(e)}const xe=C({resourceKind:`perf-capture`,fileName:`perf-capture.resource.json`,displayName:`Perf capture`}),Q=S({resourceKind:`perf-capture`,displayName:`perf capture`,store:xe,sessionSlot:{read:e=>e.perfCapture,replace:(e,t)=>({...e,perfCapture:t})},completionMetadata:e=>({kind:typeof e.kind==`string`?e.kind:`unknown`,mode:typeof e.mode==`string`?e.mode:`unknown`,...typeof e.outPath==`string`?{outPath:e.outPath}:{}}),failedFinishPolicy:`preserve-retry-material`,messages:{noActive:`no active native perf capture`,cleanupPendingHint:`Keep perf-capture.resource.json and retry stop through its exact runtime owner.`}});function Se(e){return Q.adoptStarted(e)}function $(e){return Q.finishLive(e)}function Ce(e){if(e.area===`frames`)return Object.freeze({kind:`frames`,request:e,use:c});if(e.area===`memory`)return e.action===`snapshot`?Object.freeze({kind:`memory-snapshot`,request:e,use:o}):Object.freeze({kind:`memory-sample`,request:e,use:s});if(e.area===`trace`)return e.action===`start`?Object.freeze({kind:`capture-start`,request:e,use:l}):Object.freeze({kind:`capture-stop`,request:e});switch(e.action){case`start`:return Object.freeze({kind:`capture-start`,request:e,use:l});case`stop`:return Object.freeze({kind:`capture-stop`,request:e});case`report`:return Object.freeze({kind:`profile-report`,request:e,use:a})}}function we(t){let n=t.positionals??[],r=n[0]?.toLowerCase();if(r===`frames`){let i=n[1]?.toLowerCase();if(i!==void 0&&i!==`sample`||n.length>2||t.kind!==void 0)throw new e(`INVALID_ARGS`,`perf action must be frames, memory sample|snapshot, cpu profile start|stop|report, or trace start|stop`);return Object.freeze({area:r,action:`sample`})}if(r===`memory`)return Te(n,t);if(r===`cpu`)return Ee(n,t.outPath);if(r===`trace`)return De(n,t.outPath);throw new e(`INVALID_ARGS`,`perf requires frames, memory, cpu, or trace`)}function Te(t,n){let r=(t[1]??`sample`).toLowerCase();if(r!==`sample`&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`perf memory requires sample or snapshot`);if(n.kind!==void 0&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(r===`sample`&&t.length>2)throw new e(`INVALID_ARGS`,`perf memory sample does not accept additional positionals`);if(r===`snapshot`&&t.length>3)throw new e(`INVALID_ARGS`,`perf memory snapshot accepts at most one positional kind`);let i=n.kind??t[2];if(i!==void 0&&!u(i))throw new e(`INVALID_ARGS`,`perf memory snapshot --kind must be android-hprof or memgraph`);return Object.freeze({area:`memory`,action:r,...i===void 0?{}:{kind:i},...n.outPath===void 0?{}:{outPath:n.outPath}})}function Ee(t,n){if(t[1]?.toLowerCase()!==`profile`)throw new e(`INVALID_ARGS`,`perf cpu requires profile`);let r=t[2]?.toLowerCase();if(r!==`start`&&r!==`stop`&&r!==`report`)throw new e(`INVALID_ARGS`,`perf cpu profile action must be start, stop, or report`);let i=t[3]?.toLowerCase();if(i!==`xctrace`&&i!==`simpleperf`)throw new e(`INVALID_ARGS`,`perf cpu profile requires --kind xctrace or simpleperf`);let a=n??t[5];return Object.freeze({area:`cpu`,subject:`profile`,action:r,kind:i,...t[4]?{template:t[4]}:{},...a?{outPath:a}:{},...t[6]?{tracePath:t[6]}:{}})}function De(t,n){let r=t[1]?.toLowerCase();if(r!==`start`&&r!==`stop`)throw new e(`INVALID_ARGS`,`perf trace action must be start or stop`);let i=t[2]?.toLowerCase();if(i!==`xctrace`&&i!==`perfetto`)throw new e(`INVALID_ARGS`,`perf trace requires --kind xctrace or perfetto`);let a=n??t[4];return Object.freeze({area:`trace`,action:r,kind:i,...t[3]?{template:t[3]}:{},...a?{outPath:a}:{}})}export{de as C,B as S,le as T,ce as _,Q as a,K as b,be as c,_e as d,me as f,Y as g,ge as h,$ as i,pe as l,fe as m,Ce as n,ye as o,he as p,Se as r,Z as s,we as t,X as u,L as v,H as w,V as x,R as y};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime.js";import{C as t}from"./sdk-contracts.js";import{r as n}from"./diagnostics.js";import{c as r,g as i,h as a,l as o,n as s,t as c}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{t as l}from"./adb-host.js";import u from"node:path";import{constants as d}from"node:fs";import{createHash as f,randomUUID as p}from"node:crypto";import m from"node:os";import{access as h,mkdir as g,mkdtemp as _,open as v,readFile as y,readdir as b,rename as x,rm as S,stat as C,writeFile as w}from"node:fs/promises";var T=e({});const E=process.env;l({environment:E,files:{access:async e=>await h(e),ensureDirectory:async e=>{await g(e,{recursive:!0})},isExecutable:async e=>{try{return await h(e,d.X_OK),!0}catch{return!1}},makeTempDirectory:async e=>await _(u.join(m.tmpdir(),e)),readBytes:async e=>await y(e),readDirectory:async e=>await b(e),readText:async e=>await y(e,`utf8`),remove:async(e,t)=>await S(e,t),stat:async e=>{let t=await C(e);return{isFile:t.isFile(),size:t.size}},sha256:e=>f(`sha256`).update(e).digest(`hex`),writeAtomicText:async(e,t,n=384)=>{let r=u.dirname(e),i=u.join(r,`.${u.basename(e)}.${p()}.tmp`),a,o=!1;try{a=await v(i,`wx`,n),await a.writeFile(t,`utf8`),await a.sync(),await a.close(),a=void 0,await x(i,e),o=!0;let s;try{s=await v(r,`r`),await s.sync()}catch{}finally{s&&await s.close().catch(()=>{})}}finally{a&&await a.close().catch(()=>{}),o||await S(i,{force:!0}).catch(()=>{})}},writeBytes:async(e,t)=>await w(e,t)},execSerialAdb:async(e,t,n)=>{let a=D([`-s`,e,...t],n);return await i(async()=>await r(`adb`,a.args,{...a.options,detached:process.platform!==`win32`}))},spawnSerialAdb:(e,t,n)=>{let r=D([`-s`,e,...t],n),i=o(`adb`,r.args,{...r.options,allowFailure:!0,captureOutput:!1});return i.wait.catch(()=>{}),i.child},execHostAdb:async(e,t)=>{let n=D(e,t);return await r(`adb`,n.args,n.options)},withAdbCommandExecutorOverride:a,withoutAdbCommandExecutorOverride:i,coerceAdbResult:c,execFailureDetails:s,emitDiagnostic:n,imeRecoveryMarkers:{write:async(e,t)=>{let{writeAndroidTestImeRecoveryMarker:n}=await import(`./mechanics.js`).then(e=>e.r);return await n(e,t)},clear:async(e,t)=>{let{clearAndroidTestImeRecoveryMarker:n}=await import(`./mechanics.js`).then(e=>e.r);await n(e,t)},read:async e=>{let{readAndroidTestImeRecoveryMarkers:t}=await import(`./mechanics.js`).then(e=>e.r);return await t(e)}},resolveHelperArtifact:async e=>{let{resolveAndroidHelperArtifact:t}=await import(`./mechanics.js`).then(e=>e.r);return await t(e)},ensureHelperInstalled:async(e,t)=>{let{makeEnsureAndroidHelperInstalled:n}=await import(`./mechanics.js`).then(e=>e.r);return await n(e)(t)}});function D(e,t){let{serverPort:n,...r}=t??{};return n===void 0?{args:e,options:r}:{args:O(e,n),options:{...r,env:{...E,...r.env??{},ADB_SERVER_SOCKET:void 0,ANDROID_ADB_SERVER_PORT:String(n),ANDROID_ADB_SERVER_ADDRESS:`127.0.0.1`}}}}function O(e,t){let n=[`-P`,String(t)],r=0,i;for(;r<e.length;){let t=e[r];if(t===`-P`){r+=2;continue}if(t===`-s`){if(i!==void 0&&i!==e[r+1])throw A();i=e[r+1],n.push(t,e[r+1]),r+=2;continue}if(t?.startsWith(`-`))throw A();break}let a=e.slice(r);return k(a),[...n,...a]}function k(e){let t=e.find(e=>!e.startsWith(`wait-for-`));if([`nodaemon`,`server`,`fork-server`,`kill-server`,`start-server`,`connect`,`disconnect`,`reconnect`,`attach`,`detach`,`pair`].includes(t??``))throw A()}function A(){return new t(`COMMAND_FAILED`,`Managed ADB transport cannot select another target.`,{reason:`managed-device-transport-mismatch`})}export{T as t};
1
+ import{r as e}from"./rolldown-runtime.js";import{C as t}from"./sdk-contracts.js";import{r as n}from"./diagnostics.js";import{_ as r,c as i,g as a,l as o,n as s,t as c}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{t as l}from"./adb-host.js";import u from"node:path";import{constants as d}from"node:fs";import{createHash as f,randomUUID as p}from"node:crypto";import m from"node:os";import{access as h,mkdir as g,mkdtemp as _,open as v,readFile as y,readdir as b,rename as x,rm as S,stat as C,writeFile as w}from"node:fs/promises";var T=e({});const E=process.env;l({environment:E,files:{access:async e=>await h(e),ensureDirectory:async e=>{await g(e,{recursive:!0})},isExecutable:async e=>{try{return await h(e,d.X_OK),!0}catch{return!1}},makeTempDirectory:async e=>await _(u.join(m.tmpdir(),e)),readBytes:async e=>await y(e),readDirectory:async e=>await b(e),readText:async e=>await y(e,`utf8`),remove:async(e,t)=>await S(e,t),stat:async e=>{let t=await C(e);return{isFile:t.isFile(),size:t.size}},sha256:e=>f(`sha256`).update(e).digest(`hex`),writeAtomicText:async(e,t,n=384)=>{let r=u.dirname(e),i=u.join(r,`.${u.basename(e)}.${p()}.tmp`),a,o=!1;try{a=await v(i,`wx`,n),await a.writeFile(t,`utf8`),await a.sync(),await a.close(),a=void 0,await x(i,e),o=!0;let s;try{s=await v(r,`r`),await s.sync()}catch{}finally{s&&await s.close().catch(()=>{})}}finally{a&&await a.close().catch(()=>{}),o||await S(i,{force:!0}).catch(()=>{})}},writeBytes:async(e,t)=>await w(e,t)},execSerialAdb:async(e,t,n)=>{let a=D([`-s`,e,...t],n);return await r(async()=>await i(`adb`,a.args,{...a.options,detached:process.platform!==`win32`}))},spawnSerialAdb:(e,t,n)=>{let r=D([`-s`,e,...t],n),i=o(`adb`,r.args,{...r.options,allowFailure:!0,captureOutput:!1});return i.wait.catch(()=>{}),i.child},execHostAdb:async(e,t)=>{let n=D(e,t);return await i(`adb`,n.args,{...n.options,detached:process.platform!==`win32`})},withAdbCommandExecutorOverride:a,withoutAdbCommandExecutorOverride:r,coerceAdbResult:c,execFailureDetails:s,emitDiagnostic:n,imeRecoveryMarkers:{write:async(e,t)=>{let{writeAndroidTestImeRecoveryMarker:n}=await import(`./mechanics.js`).then(e=>e.r);return await n(e,t)},clear:async(e,t)=>{let{clearAndroidTestImeRecoveryMarker:n}=await import(`./mechanics.js`).then(e=>e.r);await n(e,t)},read:async e=>{let{readAndroidTestImeRecoveryMarkers:t}=await import(`./mechanics.js`).then(e=>e.r);return await t(e)}},resolveHelperArtifact:async e=>{let{resolveAndroidHelperArtifact:t}=await import(`./mechanics.js`).then(e=>e.r);return await t(e)},ensureHelperInstalled:async(e,t)=>{let{makeEnsureAndroidHelperInstalled:n}=await import(`./mechanics.js`).then(e=>e.r);return await n(e)(t)}});function D(e,t){let{serverPort:n,...r}=t??{};return n===void 0?{args:e,options:r}:{args:O(e,n),options:{...r,env:{...E,...r.env??{},ADB_SERVER_SOCKET:void 0,ANDROID_ADB_SERVER_PORT:String(n),ANDROID_ADB_SERVER_ADDRESS:`127.0.0.1`}}}}function O(e,t){let n=[`-P`,String(t)],r=0,i;for(;r<e.length;){let t=e[r];if(t===`-P`){r+=2;continue}if(t===`-s`){if(i!==void 0&&i!==e[r+1])throw A();i=e[r+1],n.push(t,e[r+1]),r+=2;continue}if(t?.startsWith(`-`))throw A();break}let a=e.slice(r);return k(a),[...n,...a]}function k(e){let t=e.find(e=>!e.startsWith(`wait-for-`));if([`nodaemon`,`server`,`fork-server`,`kill-server`,`start-server`,`connect`,`disconnect`,`reconnect`,`attach`,`detach`,`pair`].includes(t??``))throw A()}function A(){return new t(`COMMAND_FAILED`,`Managed ADB transport cannot select another target.`,{reason:`managed-device-transport-mismatch`})}export{T as t};
@@ -1 +1 @@
1
- import{t as e}from"./platform-runtime-android-mechanics.js";import{t}from"./platform-runtime-app-log-process.js";async function n(n,a,o){let{resolveScopedAndroidAdbBackgroundTransport:s}=await e(),c=s(a);if(c.mode===`local`)return o;if(!c.spawn)return Object.freeze({mode:`transport-composed`});let l=c.spawn,u=t(n,{launch:async(e,t)=>{t?.throwIfAborted();let n=r(e,a.id);return i(l([...n.args],{allowFailure:n.options?.allowFailure,cwd:n.options?.cwd,env:n.options?.env?{...process.env,...n.options.env}:void 0,timeoutMs:n.options?.timeoutMs,captureOutput:!1,signal:t}))}});return Object.freeze({mode:`transport-composed`,start:u.start})}function r(e,t){if(e.kind!==`android-adb`||e.serial!==t)throw Error(`Android app-log provider transport received a non-device-scoped adb command`);return e}function i(e){return Object.freeze({child:e,wait:a(e)})}function a(e){return new Promise((t,n)=>{let r=!1,i=e=>{r||(r=!0,e instanceof Error?n(e):t(e))};e.on(`error`,e=>i(e)),e.once(`close`,(e,t)=>i({stdout:``,stderr:``,exitCode:e??+!!t})),e.exitCode!==null&&e.exitCode!==void 0&&queueMicrotask(()=>i({stdout:``,stderr:``,exitCode:e.exitCode??0}))})}export{n as resolveAndroidAppLogProcessTransport};
1
+ import{t as e}from"./platform-runtime-android-mechanics.js";import{t}from"./platform-runtime-app-log-process.js";async function n(n,a,o){let{resolveScopedAndroidAdbBackgroundTransport:s}=await e(),c=s(a);if(c.mode===`local`)return o;if(!c.spawn)return Object.freeze({mode:`transport-composed`});let l=c.spawn,u=t(n,{launch:async(e,t)=>{t?.throwIfAborted();let n=r(e,a.id);return i(l([...n.args],{allowFailure:n.options?.allowFailure,cwd:n.options?.cwd,env:n.options?.env?{...process.env,...n.options.env}:void 0,captureOutput:!1,signal:t}))}});return Object.freeze({mode:`transport-composed`,start:u.start})}function r(e,t){if(e.kind!==`android-adb`||e.serial!==t)throw Error(`Android app-log provider transport received a non-device-scoped adb command`);return e}function i(e){return Object.freeze({child:e,wait:a(e)})}function a(e){return new Promise((t,n)=>{let r=!1,i=e=>{r||(r=!0,e instanceof Error?n(e):t(e))};e.on(`error`,e=>i(e)),e.once(`close`,(e,t)=>i({stdout:``,stderr:``,exitCode:e??+!!t})),e.exitCode!==null&&e.exitCode!==void 0&&queueMicrotask(()=>i({stdout:``,stderr:``,exitCode:e.exitCode??0}))})}export{n as resolveAndroidAppLogProcessTransport};
@@ -1 +1 @@
1
- import{T as e,p as t,x as n,y as r}from"./owner-identity.js";import{i}from"./verified-file.js";import{l as a}from"./exec.js";import"./file.js";import"./command.js";import"./process.js";import{p as o}from"./src7.js";import s from"node:path";import c from"node:fs";function l(e){let t=s.resolve(e.sessionsDir),n=s.resolve(e.pathname);if(s.basename(n)!==e.basename)throw Error(`${e.label} is outside the daemon-owned sessions directory`);if(c.existsSync(t)&&c.existsSync(s.dirname(n))){let r=c.realpathSync.native(t),i=c.realpathSync.native(s.dirname(n));if(i!==r&&!i.startsWith(`${r}${s.sep}`))throw Error(`${e.label} resolves outside the daemon-owned sessions directory`);return s.join(i,e.basename)}if(n!==t&&!n.startsWith(`${t}${s.sep}`))throw Error(`${e.label} is outside the daemon-owned sessions directory`);return n}const u=`app-log.pid`;function d(e,t={}){let n=s.resolve(e),r=t.launch??h;return Object.freeze({start:async(e,t)=>await m(n,e,r,t),readMarker:async e=>T(n,e),clearMarker:async e=>D(n,e),inspect:async e=>k(e),terminate:async e=>await A(e)})}async function f(e){let t=[],n=[];if(!c.existsSync(e))return{recovered:t,retained:n};let r=s.resolve(e);for(let e of c.readdirSync(r,{withFileTypes:!0})){if(!e.isDirectory())continue;let i=s.join(r,e.name);if(c.existsSync(s.join(i,`app-log.resource.json`)))continue;let a=s.join(i,u),o=T(r,a);if(o.status!==`missing`){if(o.status===`invalid`){n.push({markerPath:a,reason:`invalid`,message:o.message});continue}if(await A(o.marker)===`ownership-lost`){let e=p(o.marker.command);n.push({markerPath:a,reason:`ownership-lost`,...e?{device:e}:{}});continue}D(r,a),t.push(a)}}return Object.freeze({recovered:Object.freeze(t),retained:Object.freeze(n)})}function p(e){let t=/(?:^|\s)(?:\S*\/)?adb\s+-s\s+([^\s]+)/.exec(e)?.[1];if(t)return Object.freeze({id:t,family:`android`,kind:t.startsWith(`emulator-`)?`emulator`:`device`,target:`mobile`});let n=/(?:^|\s)xcrun\s+(?:--set\s+\S+\s+)?simctl\s+spawn\s+([^\s]+)/.exec(e)?.[1];if(n)return Object.freeze({id:n,family:`apple`,appleOs:`ios`,kind:`simulator`,target:`mobile`});let r=/(?:^|\s)xcrun\s+devicectl\b[^\n]*?\s--device\s+([^\s]+)/.exec(e)?.[1];if(r)return Object.freeze({id:r,family:`apple`,appleOs:`ios`,kind:`device`,target:`mobile`,iosPhysicalDeviceBackend:`coredevice`})}async function m(e,t,n,r){_(e,t.markerPath),r?.throwIfAborted();let i=await n(t.command,r),a=i.child,o=v(a,t.output),s=await y(e,t.markerPath,i),c=i.wait.then(async e=>(await o(),e)).finally(()=>{t.markerPath&&s&&S(e,t.markerPath,s)}),l=b(a,c);return{marker:s,wait:c,terminate:l,[Symbol.asyncDispose]:l}}function h(e,t){let n=g(e);return a(n.executable,[...n.args],{allowFailure:n.allowFailure,cwd:n.cwd,env:n.env?{...process.env,...n.env}:void 0,timeoutMs:n.timeoutMs,captureOutput:!1,signal:t})}function g(e){return e.kind===`host`?e.request:{executable:`adb`,args:[`-s`,e.serial,...e.args],...e.options}}function _(e,t){if(t&&T(e,t).status!==`missing`)throw Error(`Existing app-log process marker evidence must be recovered before start`)}function v(e,t){let n=Promise.resolve(),r,i=i=>{n=n.then(async()=>await t.write(i)).catch(t=>{r??=t,typeof e.exitCode!=`number`&&e.kill(`SIGKILL`)})};return e.stdout?.on(`data`,i),e.stderr?.on(`data`,i),async()=>{if(await n,r!==void 0)throw r}}async function y(e,t,n){let r=n.child.pid?await w(n.child.pid):void 0;try{if(!r)throw Error(`Managed app-log process did not expose a complete ownership marker`);return t&&E(e,t,r),r}catch(e){throw n.child.kill(`SIGKILL`),await n.wait.catch(()=>void 0),e}}function b(e,t){let n;return async()=>await(n??=(async()=>{typeof e.exitCode!=`number`&&(e.kill(`SIGINT`),await x(t,2e3)||e.kill(`SIGKILL`),await t.catch(()=>void 0))})())}async function x(e,t){return await new Promise(n=>{let r=setTimeout(()=>n(!1),t),i=()=>{clearTimeout(r),n(!0)};e.then(i,i)})}function S(e,t,n){let r=T(e,t);r.status===`decoded`&&r.marker.pid===n.pid&&r.marker.startTime===n.startTime&&r.marker.command===n.command&&D(e,t)}function C(e){let t=n(e),i=r(e);if(!(!t||!i))return Object.freeze({pid:e,startTime:t,command:i})}async function w(e){for(let t=0;t<5;t+=1){let t=C(e);if(t)return t;await new Promise(e=>setTimeout(e,10))}}function T(e,t){let n=O(e,t),r;try{let e=i(n);if(e===void 0)return{status:`missing`};r=e}catch(e){return{status:`invalid`,message:e instanceof Error?e.message:`App-log process marker is invalid`}}try{let e=JSON.parse(c.readFileSync(r,`utf8`));return o(e)}catch(e){return{status:`invalid`,message:e instanceof Error?e.message:`App-log process marker is invalid`}}finally{c.closeSync(r)}}function E(e,t,n){let r=O(e,t);if(T(e,r).status!==`missing`)throw Error(`Existing app-log process marker evidence must be recovered before replacement`);c.mkdirSync(s.dirname(r),{recursive:!0});let i=`${r}.${process.pid}.${Date.now()}.tmp`,a,o=!1,l=!1;try{a=c.openSync(i,`wx`,384),c.writeFileSync(a,`${JSON.stringify(n)}\n`),c.fsyncSync(a),c.closeSync(a),a=void 0,c.linkSync(i,r),o=!0,c.unlinkSync(i);let e=c.openSync(s.dirname(r),`r`);try{c.fsyncSync(e)}finally{c.closeSync(e)}l=!0}finally{if(a!==void 0)try{c.closeSync(a)}catch{}if(!l)for(let e of o?[r,i]:[i])try{c.unlinkSync(e)}catch{}}}function D(e,t){let n=O(e,t);try{c.unlinkSync(n)}catch(e){if(e.code!==`ENOENT`)throw e}}function O(e,t){return l({sessionsDir:e,pathname:t,basename:u,label:`App-log process marker`})}function k(e){return t(e.pid)?j(e)?`owned-alive`:`ownership-lost`:`missing`}async function A(n){if(!t(n.pid))return`already-missing`;if(!j(n))return`ownership-lost`;try{process.kill(n.pid,`SIGTERM`)}catch{return`already-missing`}if(!await e(n.pid,2e3)){if(!j(n))return`ownership-lost`;try{process.kill(n.pid,`SIGKILL`)}catch{return`already-missing`}await e(n.pid,2e3)}return t(n.pid)?`ownership-lost`:`terminated`}function j(e){return!e.startTime||!e.command?!1:n(e.pid)===e.startTime&&r(e.pid)===e.command}export{f as n,l as r,d as t};
1
+ import{p as e,w as t,x as n,y as r}from"./owner-identity.js";import{i}from"./verified-file.js";import{l as a}from"./exec.js";import"./file.js";import"./command.js";import"./process.js";import{p as o}from"./src7.js";import s from"node:path";import c from"node:fs";function l(e){let t=s.resolve(e.sessionsDir),n=s.resolve(e.pathname);if(s.basename(n)!==e.basename)throw Error(`${e.label} is outside the daemon-owned sessions directory`);if(c.existsSync(t)&&c.existsSync(s.dirname(n))){let r=c.realpathSync.native(t),i=c.realpathSync.native(s.dirname(n));if(i!==r&&!i.startsWith(`${r}${s.sep}`))throw Error(`${e.label} resolves outside the daemon-owned sessions directory`);return s.join(i,e.basename)}if(n!==t&&!n.startsWith(`${t}${s.sep}`))throw Error(`${e.label} is outside the daemon-owned sessions directory`);return n}const u=`app-log.pid`;function d(e,t={}){let n=s.resolve(e),r=t.launch??h;return Object.freeze({start:async(e,t)=>await m(n,e,r,t),readMarker:async e=>T(n,e),clearMarker:async e=>D(n,e),inspect:async e=>k(e),terminate:async e=>await A(e)})}async function f(e){let t=[],n=[];if(!c.existsSync(e))return{recovered:t,retained:n};let r=s.resolve(e);for(let e of c.readdirSync(r,{withFileTypes:!0})){if(!e.isDirectory())continue;let i=s.join(r,e.name);if(c.existsSync(s.join(i,`app-log.resource.json`)))continue;let a=s.join(i,u),o=T(r,a);if(o.status!==`missing`){if(o.status===`invalid`){n.push({markerPath:a,reason:`invalid`,message:o.message});continue}if(await A(o.marker)===`ownership-lost`){let e=p(o.marker.command);n.push({markerPath:a,reason:`ownership-lost`,...e?{device:e}:{}});continue}D(r,a),t.push(a)}}return Object.freeze({recovered:Object.freeze(t),retained:Object.freeze(n)})}function p(e){let t=/(?:^|\s)(?:\S*\/)?adb\s+-s\s+([^\s]+)/.exec(e)?.[1];if(t)return Object.freeze({id:t,family:`android`,kind:t.startsWith(`emulator-`)?`emulator`:`device`,target:`mobile`});let n=/(?:^|\s)xcrun\s+(?:--set\s+\S+\s+)?simctl\s+spawn\s+([^\s]+)/.exec(e)?.[1];if(n)return Object.freeze({id:n,family:`apple`,appleOs:`ios`,kind:`simulator`,target:`mobile`});let r=/(?:^|\s)xcrun\s+devicectl\b[^\n]*?\s--device\s+([^\s]+)/.exec(e)?.[1];if(r)return Object.freeze({id:r,family:`apple`,appleOs:`ios`,kind:`device`,target:`mobile`,iosPhysicalDeviceBackend:`coredevice`})}async function m(e,t,n,r){_(e,t.markerPath),r?.throwIfAborted();let i=await n(t.command,r),a=i.child,o=v(a,t.output),s=await y(e,t.markerPath,i),c=i.wait.then(async e=>(await o(),e)).finally(()=>{t.markerPath&&s&&S(e,t.markerPath,s)}),l=b(a,c);return{marker:s,wait:c,terminate:l,[Symbol.asyncDispose]:l}}function h(e,t){let n=g(e);return a(n.executable,[...n.args],{allowFailure:n.allowFailure,cwd:n.cwd,env:n.env?{...process.env,...n.env}:void 0,captureOutput:!1,signal:t})}function g(e){return e.kind===`host`?e.request:{executable:`adb`,args:[`-s`,e.serial,...e.args],...e.options}}function _(e,t){if(t&&T(e,t).status!==`missing`)throw Error(`Existing app-log process marker evidence must be recovered before start`)}function v(e,t){let n=Promise.resolve(),r,i=i=>{n=n.then(async()=>await t.write(i)).catch(t=>{r??=t,typeof e.exitCode!=`number`&&e.kill(`SIGKILL`)})};return e.stdout?.on(`data`,i),e.stderr?.on(`data`,i),async()=>{if(await n,r!==void 0)throw r}}async function y(e,t,n){let r=n.child.pid?await w(n.child.pid):void 0;try{if(!r)throw Error(`Managed app-log process did not expose a complete ownership marker`);return t&&E(e,t,r),r}catch(e){throw n.child.kill(`SIGKILL`),await n.wait.catch(()=>void 0),e}}function b(e,t){let n;return async()=>await(n??=(async()=>{typeof e.exitCode!=`number`&&(e.kill(`SIGINT`),await x(t,2e3)||e.kill(`SIGKILL`),await t.catch(()=>void 0))})())}async function x(e,t){return await new Promise(n=>{let r=setTimeout(()=>n(!1),t),i=()=>{clearTimeout(r),n(!0)};e.then(i,i)})}function S(e,t,n){let r=T(e,t);r.status===`decoded`&&r.marker.pid===n.pid&&r.marker.startTime===n.startTime&&r.marker.command===n.command&&D(e,t)}function C(e){let t=n(e),i=r(e);if(!(!t||!i))return Object.freeze({pid:e,startTime:t,command:i})}async function w(e){for(let t=0;t<5;t+=1){let t=C(e);if(t)return t;await new Promise(e=>setTimeout(e,10))}}function T(e,t){let n=O(e,t),r;try{let e=i(n);if(e===void 0)return{status:`missing`};r=e}catch(e){return{status:`invalid`,message:e instanceof Error?e.message:`App-log process marker is invalid`}}try{let e=JSON.parse(c.readFileSync(r,`utf8`));return o(e)}catch(e){return{status:`invalid`,message:e instanceof Error?e.message:`App-log process marker is invalid`}}finally{c.closeSync(r)}}function E(e,t,n){let r=O(e,t);if(T(e,r).status!==`missing`)throw Error(`Existing app-log process marker evidence must be recovered before replacement`);c.mkdirSync(s.dirname(r),{recursive:!0});let i=`${r}.${process.pid}.${Date.now()}.tmp`,a,o=!1,l=!1;try{a=c.openSync(i,`wx`,384),c.writeFileSync(a,`${JSON.stringify(n)}\n`),c.fsyncSync(a),c.closeSync(a),a=void 0,c.linkSync(i,r),o=!0,c.unlinkSync(i);let e=c.openSync(s.dirname(r),`r`);try{c.fsyncSync(e)}finally{c.closeSync(e)}l=!0}finally{if(a!==void 0)try{c.closeSync(a)}catch{}if(!l)for(let e of o?[r,i]:[i])try{c.unlinkSync(e)}catch{}}}function D(e,t){let n=O(e,t);try{c.unlinkSync(n)}catch(e){if(e.code!==`ENOENT`)throw e}}function O(e,t){return l({sessionsDir:e,pathname:t,basename:u,label:`App-log process marker`})}function k(t){return e(t.pid)?j(t)?`owned-alive`:`ownership-lost`:`missing`}async function A(n){if(!e(n.pid))return`already-missing`;if(!j(n))return`ownership-lost`;try{process.kill(n.pid,`SIGTERM`)}catch{return`already-missing`}if(!await t(n.pid,2e3)){if(!j(n))return`ownership-lost`;try{process.kill(n.pid,`SIGKILL`)}catch{return`already-missing`}await t(n.pid,2e3)}return e(n.pid)?`ownership-lost`:`terminated`}function j(e){return!e.startTime||!e.command?!1:n(e.pid)===e.startTime&&r(e.pid)===e.command}export{f as n,l as r,d as t};
@@ -1 +1 @@
1
- import{c as e,m as t}from"./exec.js";import"./command.js";import{t as n}from"./platform-runtime-android-mechanics.js";import r from"node:path";import{constants as i}from"node:fs";import a from"node:os";import{access as o,mkdtemp as s,readFile as c,rm as l,writeFile as u}from"node:fs/promises";function d(){return Object.freeze({isXcrunAvailable:async e=>{let{resolveAppleToolProvider:t}=await f(async()=>await import(`./tool-provider-facade.js`),e),n=t();return await f(async()=>await n.whichCommand(`xcrun`),e)},run:async(e,t)=>{let{runXcrun:n}=await f(async()=>await import(`./tool-provider-facade.js`),t),r=await f(async()=>await n([e.tool,...e.args],{allowFailure:e.allowFailure,signal:t,timeoutMs:e.timeoutMs}),t);return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}})}async function f(e,t){t?.throwIfAborted();try{let n=await e();return t?.throwIfAborted(),n}catch(e){throw t?.throwIfAborted(),e}}function p(){return Object.freeze({prepare:async e=>{if(e===`android`){let{ensureAndroidSdkPathConfigured:e}=await n();await e(process.env);return}if(e===`harmonyos`){let{ensureHarmonyToolchainPathConfigured:e}=await import(`./src4.js`).then(e=>e.b);await e()}}})}function m(){return Object.freeze({commands:Object.freeze({which:async e=>await t(e)?e:void 0,run:async(t,n)=>{let r=await e(t.executable,[...t.args],{allowFailure:t.allowFailure,cwd:t.cwd,env:t.env?{...process.env,...t.env}:void 0,signal:n,timeoutMs:t.timeoutMs});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}}),appleTools:d(),toolchains:p(),files:Object.freeze({isExecutable:async e=>await g(e),createTemporaryTextFile:async e=>await _(e)}),hostOs:h(process.platform),hostName:a.hostname(),homeDirectory:a.homedir(),observations:Object.freeze({deviceBooted:async e=>{let{markSimulatorBooted:t}=await import(`./simulator-facade.js`);t(e)}})})}function h(e){return e===`darwin`||e===`linux`||e===`win32`?e:`other`}async function g(e){try{return await o(e,i.X_OK),!0}catch{return!1}}async function _(e){let t=await s(r.join(a.tmpdir(),e.prefix)),n=r.join(t,`value${e.suffix}`),i=!1;return{path:n,readText:async()=>await c(n,`utf8`),writeText:async e=>await u(n,e,`utf8`),[Symbol.asyncDispose]:async()=>{i||(i=!0,await l(t,{recursive:!0,force:!0}))}}}export{m as createDeviceInventoryHost,_ as createTemporaryTextFile,d as n,p as t};
1
+ import{c as e,h as t}from"./exec.js";import"./command.js";import{t as n}from"./platform-runtime-android-mechanics.js";import r from"node:path";import{constants as i}from"node:fs";import a from"node:os";import{access as o,mkdtemp as s,readFile as c,rm as l,writeFile as u}from"node:fs/promises";function d(){return Object.freeze({isXcrunAvailable:async e=>{let{resolveAppleToolProvider:t}=await f(async()=>await import(`./tool-provider-facade.js`),e),n=t();return await f(async()=>await n.whichCommand(`xcrun`),e)},run:async(e,t)=>{let{runXcrun:n}=await f(async()=>await import(`./tool-provider-facade.js`),t),r=await f(async()=>await n([e.tool,...e.args],{allowFailure:e.allowFailure,signal:t,timeoutMs:e.timeoutMs}),t);return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}})}async function f(e,t){t?.throwIfAborted();try{let n=await e();return t?.throwIfAborted(),n}catch(e){throw t?.throwIfAborted(),e}}function p(){return Object.freeze({prepare:async e=>{if(e===`android`){let{ensureAndroidSdkPathConfigured:e}=await n();await e(process.env);return}if(e===`harmonyos`){let{ensureHarmonyToolchainPathConfigured:e}=await import(`./src4.js`).then(e=>e.b);await e()}}})}function m(){return Object.freeze({commands:Object.freeze({which:async e=>await t(e)?e:void 0,run:async(t,n)=>{let r=await e(t.executable,[...t.args],{allowFailure:t.allowFailure,cwd:t.cwd,env:t.env?{...process.env,...t.env}:void 0,signal:n,timeoutMs:t.timeoutMs});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}}),appleTools:d(),toolchains:p(),files:Object.freeze({isExecutable:async e=>await g(e),createTemporaryTextFile:async e=>await _(e)}),hostOs:h(process.platform),hostName:a.hostname(),homeDirectory:a.homedir(),observations:Object.freeze({deviceBooted:async e=>{let{markSimulatorBooted:t}=await import(`./simulator-facade.js`);t(e)}})})}function h(e){return e===`darwin`||e===`linux`||e===`win32`?e:`other`}async function g(e){try{return await o(e,i.X_OK),!0}catch{return!1}}async function _(e){let t=await s(r.join(a.tmpdir(),e.prefix)),n=r.join(t,`value${e.suffix}`),i=!1;return{path:n,readText:async()=>await c(n,`utf8`),writeText:async e=>await u(n,e,`utf8`),[Symbol.asyncDispose]:async()=>{i||(i=!0,await l(t,{recursive:!0,force:!0}))}}}export{m as createDeviceInventoryHost,_ as createTemporaryTextFile,d as n,p as t};
@@ -1,5 +1,5 @@
1
- import{C as e}from"./sdk-contracts.js";import{l as t,p as n,u as r,w as i}from"./sdk-device.js";import{r as a}from"./diagnostics.js";import{w as o}from"./owner-identity.js";import{i as s,r as c}from"./verified-file.js";import{c as l,m as u,u as d}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import"./process.js";import{t as f}from"./platform-runtime-android-mechanics.js";import{t as p}from"./perf-runtime.js";import{a as ee,n as te}from"./durable-resource.js";import{n as ne}from"./async-lifecycle.js";import{m}from"./src7.js";import{r as re}from"./device-inventory-context.js";import{t as ie}from"./app-log-files.js";import{n as ae,r as oe,t as h}from"./platform-runtime-app-log-process.js";import{createTemporaryTextFile as g,n as _,t as v}from"./platform-runtime-host.js";import{i as y,n as b,t as x}from"./platform-runtime-screen-recording-process-host.js";import S from"node:fs";import{setTimeout as se}from"node:timers/promises";async function ce(e,t){t=C(e,t),ie(t);let n=c(t),r;try{r=S.createWriteStream(t,{fd:n,autoClose:!0})}catch(e){throw S.closeSync(n),e}let i;r.on(`error`,e=>{i??=e});let a=ue(),o=``,s=Promise.resolve(),l,u=e=>{let t=s.then(e);return s=t.catch(()=>void 0),t},d=async e=>{let t=`${o}${e}`.split(`
1
+ import{C as e}from"./sdk-contracts.js";import{l as t,p as n,u as r,w as i}from"./sdk-device.js";import{r as a}from"./diagnostics.js";import{C as o}from"./owner-identity.js";import{i as s,r as c}from"./verified-file.js";import{c as l,h as u,u as d}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import"./process.js";import{t as f}from"./platform-runtime-android-mechanics.js";import{t as p}from"./perf-runtime.js";import{a as ee,n as te}from"./durable-resource.js";import{n as ne}from"./async-lifecycle.js";import{m}from"./src7.js";import{r as re}from"./device-inventory-context.js";import{t as ie}from"./app-log-files.js";import{n as ae,r as oe,t as h}from"./platform-runtime-app-log-process.js";import{createTemporaryTextFile as g,n as _,t as v}from"./platform-runtime-host.js";import{i as y,n as b,t as x}from"./platform-runtime-screen-recording-process-host.js";import S from"node:fs";import{setTimeout as se}from"node:timers/promises";async function ce(e,t){t=C(e,t),ie(t);let n=c(t),r;try{r=S.createWriteStream(t,{fd:n,autoClose:!0})}catch(e){throw S.closeSync(n),e}let i;r.on(`error`,e=>{i??=e});let a=ue(),o=``,s=Promise.resolve(),l,u=e=>{let t=s.then(e);return s=t.catch(()=>void 0),t},d=async e=>{let t=`${o}${e}`.split(`
2
2
  `);o=t.pop()??``;for(let e of t)await T(r,w(`${e}\n`,a))};return{write:async e=>await u(async()=>await d(de(e))),[Symbol.asyncDispose]:async()=>{l??=u(async()=>{if(o&&=(await T(r,w(o,a)),``),await fe(r),i)throw i}),await l}}}async function le(e,t,n){if(t=C(e,t),!Number.isInteger(n)||n<1||n>1048576)throw TypeError(`App-log tail size must be between 1 byte and 1 MiB`);let r=s(t);if(r===void 0)return``;let i=S.fstatSync(r).size,a=Math.min(i,n),o=i-a,c=+(o>0),l=Buffer.alloc(a+c);try{S.readSync(r,l,0,l.length,o-c)}finally{S.closeSync(r)}let u=l.subarray(c).toString(`utf8`);if(c===0||l[0]===10)return u;let d=u.indexOf(`
3
3
  `);return d<0?``:u.slice(d+1)}function C(e,t){return oe({sessionsDir:e,pathname:t,basename:`app.log`,label:`App-log output`})}function ue(){return(process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS??``).split(`,`).map(e=>e.trim()).filter(Boolean).flatMap(e=>{try{return[new RegExp(e,`gi`)]}catch{return[]}})}function w(e,t){return t.reduce((e,t)=>e.replace(t,`[REDACTED]`),e)}function de(e){return typeof e==`string`?e:Buffer.from(e).toString(`utf8`)}async function T(e,t){t&&await new Promise((n,r)=>{e.write(t,e=>e?r(e):n())})}async function fe(e){e.closed||await new Promise((t,n)=>{e.once(`error`,n),e.end(()=>{e.off(`error`,n),t()})})}function pe(e){return Object.freeze({appLogs:Object.freeze({resolveSession:e.resolveSessionArtifacts,readRecent:async(t,n)=>{let{outputPath:r}=e.resolveSessionArtifacts(t);return me(r,n)},readProcessMarker:async t=>{let{pidPath:n}=e.resolveSessionArtifacts(t);return await e.processes.readMarker(n)}}),networkTransports:Object.freeze({resolve:e.resolveTransport})})}function me(e,t){if(!Number.isInteger(t)||t<1||t>2e4)throw TypeError(`Network app-log scan lines must be between 1 and 20000`);let n=s(e);if(n===void 0)return Object.freeze({path:e,exists:!1,text:``,skippedLines:0});try{let r=he(S.readFileSync(n,`utf8`),t);return Object.freeze({path:e,exists:!0,...r})}finally{S.closeSync(n)}}function he(e,t){let n=e.split(`
4
4
  `),r=Math.max(0,n.length-t);return Object.freeze({text:n.slice(r).join(`
5
- `),skippedLines:r})}function ge(e={}){let t=Object.freeze({resolve:async e=>{let{createAndroidScreenRecordingTransport:t}=await import(`./platform-runtime-screen-recording-android-host.js`);return await t(e)}}),n=Object.freeze({resolve:async e=>{let{resolveWebScreenRecordingTransport:t}=await import(`./platform-runtime-screen-recording-web-host.js`);return await t(e)}}),r=Object.freeze({prepare:async e=>{let{createScreenRecordingOutputHost:t}=await import(`./platform-runtime-screen-recording-output-host.js`);await t().prepare(e)}}),i=Object.freeze({complete:async(e,t)=>{let{createScreenRecordingFinalizer:n}=await import(`./platform-runtime-screen-recording-finalizer-host.js`);return await n().complete(e,t)}}),a=e.ownedProcesses??Object.freeze({replace:()=>{},clear:()=>{}});return Object.freeze({apple:E(),android:t,harmony:D(),web:n,outputs:r,finalize:i,ownedProcesses:a})}function E(){let e=async()=>{let{createAppleScreenRecordingHost:e}=await import(`./platform-runtime-screen-recording-apple-host.js`);return e()};return Object.freeze({availability:async t=>(await e()).availability(t),runRunner:async(t,n,r)=>await(await e()).runRunner(t,n,r),startSimulator:async(t,n,r)=>await(await e()).startSimulator(t,n,r),inspectProcess:async t=>await(await e()).inspectProcess(t),terminateProcess:async t=>await(await e()).terminateProcess(t),inspectRunner:async(t,n,r)=>await(await e()).inspectRunner(t,n,r),retrieveRunnerRecording:async(t,n,r,i)=>await(await e()).retrieveRunnerRecording(t,n,r,i),captureClockAnchor:async(t,n,r)=>await(await e()).captureClockAnchor(t,n,r),isRunnerBundleId:async t=>await(await e()).isRunnerBundleId(t)})}function D(){let e=async()=>{let{createHarmonyScreenRecordingHost:e}=await import(`./platform-runtime-screen-recording-harmony-host.js`);return e()};return Object.freeze({start:async(t,n,r)=>await(await e()).start(t,n,r),stop:async(t,n)=>await(await e()).stop(t,n),findMedia:async(t,n,r)=>await(await e()).findMedia(t,n,r),stageMedia:async(t,n,r)=>await(await e()).stageMedia(t,n,r),stagedFileSize:async(t,n,r)=>await(await e()).stagedFileSize(t,n,r),pull:async(t,n,r)=>await(await e()).pull(t,n,r),remove:async(t,n,r)=>await(await e()).remove(t,n,r),removeMedia:async(t,n,r)=>await(await e()).removeMedia(t,n,r)})}function O(e={}){let t=e.ownedProcesses??Object.freeze({replace:()=>{},clear:()=>{}});return Object.freeze({hostCapture:Object.freeze({info:Object.freeze({source:`system-audio`,backend:`macos-screencapturekit`,sourceCount:1,notes:k}),start:async e=>{let{startMacOsAudioProbeProcess:t}=await import(`./macos-facade.js`),n=await t(e),r=await b(n.child.pid??void 0);return Object.freeze({...r===void 0?{}:{marker:r},wait:n.wait,terminate:async()=>{n.child.kill(`SIGTERM`),await n.wait.catch(()=>{})}})},inspectProcess:async e=>x(e),terminateProcess:async e=>await y([e])}),web:Object.freeze({resolve:async e=>{if(e.platform!==`web`)return;let{resolveWebProvider:t}=await import(`./src6.js`).then(e=>e.i),n=await t(),r=n.probeAudio?.bind(n);if(r)return Object.freeze({probe:async e=>await r({action:e.action,durationMs:e.durationMs,bucketMs:e.bucketMs})})}}),ownedProcesses:t})}function k(e){return[`Audio probe samples host system audio through ScreenCaptureKit for this ${t(e)?`iOS simulator`:e.platform===`android`?`Android emulator`:`macOS session`}; it is not app-instrumented audio.`,`Screen Recording permission is required for host system audio capture.`,`Other audible host apps can contribute to the measured buckets.`]}const A=f,j=async()=>await import(`./perf-facade.js`),M=Object.freeze({resourceKind:p,version:1,encode:e=>e,decode:Ce});async function N(t,n,r){if(r.kind!==`xctrace`)throw H(`Apple`,`xctrace`,r.kind);let i=r.template??(r.mode===`cpu-profile`?`Time Profiler`:`Animation Hitches`),a=await j(),o=await a.startAppleXctracePerfCapture({device:t,appBundleId:r.appId,mode:r.mode,template:i,outPath:r.outPath}),s=await b(o.child.pid??void 0);if(!s)throw await a.cleanupAppleXctracePerfCapture(o).catch(()=>{}),new e(`COMMAND_FAILED`,`Apple xctrace exposed no exact process identity`);return F(t,n,r,{family:`apple`,marker:s,capture:xe(o)},I(o),z(`started`,o))}async function P(e,t,n){let r=await A(),i;if(n.mode===`cpu-profile`){if(n.kind!==`simpleperf`)throw H(`Android`,`simpleperf`,n.kind);i=await r.startAndroidSimpleperfProfile(e,n.appId,n.outPath)}else{if(n.kind!==`perfetto`)throw H(`Android`,`perfetto`,n.kind);i=await r.startAndroidPerfettoTrace(e,n.appId,n.outPath)}return F(e,t,n,{family:`android`,capture:i},L(e,i),B(i))}function F(e,t,n,r,a,o){return Object.freeze({pendingHandle:new ne(a),envelope:te({resourceKind:p,sessionId:n.sessionId,device:i(e),owner:t,fence:n.fence,lifecycle:`open`,descriptor:ee(M,r)}),response:o})}function I(e){return R({initialOutPath:e.outPath,inspect:()=>z(`started`,e),finish:async t=>await j().then(async n=>z(`stopped`,await n.stopAppleXctracePerfCapture(e,t))),cleanup:async()=>await j().then(async t=>{await t.cleanupAppleXctracePerfCapture(e)})})}function L(e,t){return R({initialOutPath:t.outPath,inspect:()=>B(t),finish:async n=>{let r=await A();return B(t.kind===`simpleperf`?await r.stopAndroidSimpleperfProfile(e,t,n):await r.stopAndroidPerfettoTrace(e,t,n))},cleanup:async()=>{await(await A()).cleanupAndroidNativePerfSession(e,t)}})}function R(e){let t=e.initialOutPath,n,r,i=async()=>await e.cleanup().then(()=>({status:`cleaned`}),V);return Object.freeze({inspect:e.inspect,setOutputPath:e=>{t=e},finish:async()=>n??=e.finish(t).then(e=>({status:`completed`,result:e}),e=>{throw n=void 0,e}),forceCleanup:async()=>r??=i(),[Symbol.asyncDispose]:async()=>{Se(await(r??=i()))}})}async function _e(e){let t=m(e,M);if(t.status!==`decoded`||t.descriptor.family!==`apple`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};let n=await x(t.descriptor.marker);if(n===`ownership-lost`)return{status:`cleanup-pending`,reason:`ownership-fence-lost`};if(n===`missing`)return{status:`already-missing`};let r=await y([t.descriptor.marker]);return r===`terminated`?{status:`cleaned`}:r===`already-missing`?{status:`already-missing`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`}}async function ve(e){let t=m(e,M);if(t.status!==`decoded`)return t;if(t.descriptor.family!==`apple`)return{status:`unreattachable`,reason:`descriptor-invalid`};let n=await x(t.descriptor.marker);return n===`owned-alive`?{status:`unreattachable`,reason:`transport-not-reattachable`}:n===`ownership-lost`?{status:`unreattachable`,reason:`ownership-fence-lost`}:{status:`missing`}}async function ye(e){let t=m(e,M);return t.status===`decoded`?t.descriptor.family===`android`?{status:`unreattachable`,reason:`transport-not-reattachable`}:{status:`unreattachable`,reason:`descriptor-invalid`}:t}async function be(e,t){let n=m(t,M);if(n.status!==`decoded`||n.descriptor.family!==`android`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};try{return await(await A()).cleanupAndroidNativePerfSession(e,n.descriptor.capture),{status:`cleaned`}}catch(e){return V(e)}}function xe(e){let{child:t,wait:n,...r}=e;return r}function z(e,t){return{perf:e,kind:t.kind,mode:t.mode,template:t.template,outPath:t.outPath,appBundleId:t.appBundleId,deviceId:t.deviceId,platform:t.platform,targetPids:t.targetPids,targetProcesses:t.targetProcesses,startedAt:t.startedAt,endedAt:t.endedAt}}function B(e){let t={action:e.action,platform:`android`,type:e.type,packageName:e.packageName,appPid:e.appPid,profilerPid:e.profilerPid,state:e.state,startedAt:new Date(e.startedAt).toISOString(),stoppedAt:typeof e.stoppedAt==`number`?new Date(e.stoppedAt).toISOString():void 0,outPath:e.outPath,sizeBytes:e.sizeBytes,remotePath:e.remotePath,method:e.method,message:e.message,...e.action===`stop`?{durationMs:e.durationMs,summary:e.summary}:{}};return e.kind===`simpleperf`?{...t,kind:`simpleperf`,mode:`cpu-profile`}:{...t,kind:`perfetto`,mode:`trace`}}function V(e){return{status:`cleanup-pending`,reason:`cleanup-unconfirmed`,message:e instanceof Error?e.message:String(e)}}function Se(t){if(t.status===`cleanup-pending`)throw new e(`COMMAND_FAILED`,t.message??`Perf capture cleanup could not be confirmed`,{reason:t.reason})}function H(t,n,r){return new e(`INVALID_ARGS`,`${t} native perf requires --kind ${n}, not ${r}`)}function Ce(e){return e.family===`android`&&we(e.capture)?{status:`decoded`,descriptor:{family:`android`,capture:e.capture}}:e.family===`apple`&&De(e.capture)&&je(e.marker)?{status:`decoded`,descriptor:{family:`apple`,capture:e.capture,marker:e.marker}}:{status:`invalid`,message:`Perf capture descriptor body is invalid`}}function we(e){return W(e)?Te(e.kind,e.type)&&U(e,[`packageName`,`appPid`,`profilerPid`,`remotePath`,`outPath`])&&typeof e.startedAt==`number`&&Ee(e.state)&&Oe(e,[`stoppedAt`,`sizeBytes`]):!1}function Te(e,t){return e===`simpleperf`&&t===`cpu-profile`||e===`perfetto`&&t===`trace`}function Ee(e){return e===`running`||e===`stopped`}function De(e){return W(e)&&e.kind===`xctrace`&&(e.mode===`cpu-profile`||e.mode===`trace`)&&U(e,[`template`,`outPath`,`appBundleId`,`deviceId`,`startedAt`])&&n(e.platform)&&ke(e.targetProcesses)&&Ae(e.targetPids)}function U(e,t){return t.every(t=>typeof e[t]==`string`)}function Oe(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`number`)}function ke(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function Ae(e){return Array.isArray(e)&&e.every(e=>typeof e==`number`)}function W(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function je(e){return W(e)&&typeof e.pid==`number`&&typeof e.startTime==`string`&&typeof e.command==`string`}const G=f,Me=f,Ne=f,K=async()=>await import(`./perf-facade.js`),q=async()=>await import(`./perf-facade.js`),Pe=async()=>await import(`./perf-facade.js`),Fe=async()=>await import(`./src4.js`).then(e=>e.b);function Ie(){let e=Object.freeze({sampleFrames:async(e,t)=>await(await K()).sampleAppleFramePerf(e,t),frameSampling:async e=>(await q()).buildAppleFrameSamplingMetadata(e),sampleMemory:async(e,t)=>await(await K()).sampleAppleMemoryPerf(e,t),memorySampling:async e=>(await q()).buildAppleMemorySamplingMetadata(e),memorySnapshotSupport:async e=>(await q()).buildAppleMemorySnapshotSupport(e),captureMemorySnapshot:async(e,t,n)=>await(await K()).captureAppleMemorySnapshot(e,t,n),start:async(e,t,n)=>await N(e,t,n),reattach:async(e,{envelope:t})=>await ve(t),cleanup:async(e,{envelope:t})=>await _e(t),writeProfileReport:async e=>await(await Pe()).writeAppleXctracePerfReport({tracePath:e.tracePath,outPath:e.outPath,template:e.template,appBundleId:e.appId})}),t=Object.freeze({sampleFrames:async(e,t)=>await(await Me()).sampleAndroidFramePerf(e,t),sampleMemory:async(e,t)=>await(await G()).sampleAndroidMemoryPerf(e,t),captureMemorySnapshot:async(e,t,n)=>await(await G()).captureAndroidHeapSnapshot(e,t,n),start:async(e,t,n)=>await P(e,t,n),reattach:async(e,{envelope:t})=>await ye(t),cleanup:async(e,{envelope:t})=>await be(e,t),writeProfileReport:async(e,t)=>await(await Ne()).writeAndroidSimpleperfReport(e,Le(t.profile,t.tracePath),t.outPath)}),n=Object.freeze({sampleMemory:async(e,t)=>await(await Fe()).sampleHarmonyMemoryPerf(e,t)});return Object.freeze({apple:e,android:t,harmony:n})}function Le(t,n){if(t?.kind!==`simpleperf`||t.type!==`cpu-profile`||t.mode!==`cpu-profile`)throw new e(`INVALID_ARGS`,`Stopped Simpleperf profile metadata is malformed.`);return{type:`cpu-profile`,kind:`simpleperf`,packageName:t.packageName,appPid:t.appPid,profilerPid:t.profilerPid,remotePath:t.remotePath,outPath:n,startedAt:t.startedAt?Date.parse(t.startedAt):Date.now(),state:`stopped`,...t.stoppedAt?{stoppedAt:Date.parse(t.stoppedAt)}:{},...t.sizeBytes===void 0?{}:{sizeBytes:t.sizeBytes}}}function Re(){return Object.freeze({ensureConnected:async(e,t)=>{t.throwIfAborted();try{let{resolveIosPhysicalDeviceControl:n}=await import(`./physical-device-facade.js`);await n(e).ensureReady(e,t),t.throwIfAborted()}catch(e){throw t.throwIfAborted(),e}}})}function ze(){return Object.freeze({keepHot:e=>{import(`./runner-operations-facade.js`).then(({prewarmAppleRunnerCache:t})=>t(e,{})).catch(()=>{})},wasRecentlyObservedBooted:async e=>{let{wasSimulatorRecentlyObservedBooted:t}=await import(`./simulator-facade.js`);return t(e)},markBooted:e=>{import(`./simulator-facade.js`).then(({markSimulatorBooted:t})=>t(e)).catch(()=>{})}})}function Be(){return Object.freeze({discover:async(e,t)=>{t.throwIfAborted();let n=await re(e);return t.throwIfAborted(),n},launch:(e,t)=>{let n=[`-avd`,e];return t&&n.push(`-no-window`,`-no-audio`),d(`emulator`,n)},terminate:async e=>{await o({pids:[e],termTimeoutMs:1500,killTimeoutMs:1500})}})}function Ve(e,t){let n,r,i=async()=>(n??=t.apple({appleTools:e.appleTools}),await n),a=async()=>(r??=t.android({commands:e.commands}),await r),o=Object.freeze({shutdownTarget:async(e,t)=>await(await i()).shutdownTarget(e,t)}),s=Object.freeze({shutdownTarget:async(e,t)=>await(await a()).shutdownTarget(e,t)}),c=Object.freeze({canShutdownTarget:async e=>await He(e,i,a),shutdownTarget:async e=>await Ue(e,i,a)});return Object.freeze({apple:o,android:s,close:c})}async function He(e,t,n){return e.platform===`apple`?(await t()).canShutdownTarget(e):e.platform===`android`&&(await n()).canShutdownTarget(e)}async function Ue(e,t,n){let r=new AbortController().signal;return e.platform===`apple`?await(await t()).shutdownTarget(e,r):e.platform===`android`?await(await n()).shutdownTarget(e,r):{success:!1,exitCode:-1,stdout:``,stderr:`Cannot shut down unsupported device ${e.platform}/${e.kind}`}}function We(){return Object.freeze({withInvalidatedAppResolutionCache:async(e,t)=>{let{invalidateIosAppResolutionCache:n}=await import(`./app-resolution-facade.js`);return await n(e,t)},prepareArtifact:async(e,t)=>{let{prepareIosInstallArtifact:n}=await import(`./install-artifact-facade.js`);return await n(e.source,t)},resolveAppBundleId:async(e,t)=>{let{resolveIosApp:n}=await import(`./app-resolution-facade.js`);return await n(e,t)}})}function Ge(){return Object.freeze({bundletoolJar:process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim()||void 0,withInvalidatedAppResolutionCache:async(e,t)=>{let{withAndroidAppResolutionCacheInvalidated:n}=await f();return await n(e,t)},prepareArtifact:async(e,t)=>{let{prepareAndroidInstallArtifact:n}=await f();return await n(e.source,t)},resolveAppPackage:async(e,t)=>{let{resolveAndroidApp:n}=await f(),r=await n(e,t);if(r.type===`intent`){let{AppError:e}=await import(`./sdk-contracts.js`).then(e=>e.O);throw new e(`INVALID_ARGS`,`App uninstall requires a package name, not an intent`)}return r.value}})}function Ke(){return Object.freeze({probeClipboardShellSupport:async(e,t)=>{try{let{runAndroidAdb:n,isAndroidShellCommandUnsupported:r}=await f(),i=await n(e,[`shell`,`cmd`,`clipboard`,`get`,`text`],{allowFailure:!0,signal:t});return i.exitCode===0?`supported`:r(i.stdout,i.stderr)?`unsupported`:`probe-failed`}catch{return`probe-failed`}},runAdb:async(e,t,n,r)=>{let{runAndroidAdb:i}=await f(),a=await i(e,[...t],{allowFailure:n.allowFailure,timeoutMs:n.timeoutMs,signal:r});return{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode}},installPackage:async(e,t,n,r)=>{let{resolveAndroidAdbProvider:i}=await f(),a=i(e),o=a.install?await a.install(t,{replace:n.replace,signal:r}):await a.exec([`install`,...n.replace?[`-r`]:[],t],{signal:r});return{stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode}},installBundle:async(e,t,n,r)=>{let{resolveAndroidAdbProvider:i}=await f(),a=i(e).installBundle;return a?(await a(t,{mode:n,signal:r}),!0):!1}})}let qe;const J=()=>qe??=import(`./runner-operations-facade.js`);let Je;const Y=()=>Je??=import(`./platform-runtime-runtime-hints.js`);let Ye;const Xe=()=>Ye??=import(`./platform-runtime-open-target.js`).then(e=>e.t);let Ze;const Qe=()=>Ze??=import(`./app-resolution-facade.js`);let $e;const X=()=>$e??=import(`./macos-facade.js`);let et;const tt=()=>et??=import(`./retry.js`).then(e=>e.t);function nt(){return Object.freeze({resolveOpenTarget:async(e,t)=>await rt(e,t),prewarmRunnerCache:async(e,t,n)=>{let{prewarmAppleRunnerCache:r}=await J();await r(e,Q(t,n))},prewarmRunnerSession:async(e,t,n,r,i)=>{let{prewarmIosRunnerSession:a}=await J();await a(e,{...Q(t,n),propagateError:r,...i})},notifyRunnerAppRelaunched:async(e,t,n)=>{let{notifyIosRunnerAppRelaunched:r}=await J();await r(e,Q(t,n))},stopRunnerSession:async e=>{let{stopIosRunnerSession:t}=await J();await t(e)},hasLiveRunnerSession:async(e,t)=>{let{hasLiveIosRunnerSession:n}=await J();return n(e,{requestId:t.requestId})},releaseSpeculativeRunner:async(e,t)=>{let{releaseSpeculativeIosRunnerSessionFor:n}=await J();return await n(e,{requestId:t.requestId})},scheduleRunnerIdleStop:e=>{J().then(({scheduleIosRunnerIdleStop:t})=>t(e))},prepareRunner:async(e,t,n)=>{let{Deadline:r}=await tt(),{prepareIosRunner:i}=await J(),a=Date.now();return await i(e,{...Q(t.execution,n),cleanStaleBundles:!0,buildTimeoutMs:t.timeoutMs,healthTimeoutMs:t.timeoutMs,prepareDeadline:r.fromTimeoutMs(t.timeoutMs,a),startupTimeoutMs:t.timeoutMs})},applyRuntimeHints:async(e,t)=>{let{applyRuntimeHintValues:n}=await Y();await n({device:e,...t})},clearRuntimeHints:async(e,t)=>{let{clearRuntimeHintValues:n}=await Y();await n({device:e,...t})},dismissCloseAlerts:async(e,t)=>await at(e,t),detachRunnerSessionsForShutdown:async()=>{let{detachIosSimulatorRunnerSessionsForShutdown:e}=await J();await e()},finalizeRunnerSessionsForShutdown:async()=>{let{stopAllIosRunnerSessions:e}=await J();await e()}})}async function rt(t,n){if(n.foreground){let n=await Z(t);if(n)return n;throw new e(`AMBIGUOUS_MATCH`,`open --foreground requires exactly one running app on the selected iOS simulator.`,{reason:`foreground_app_ambiguous`,hint:`Pass an explicit app instead: agent-device open <app> --platform ios.`})}let r=await it(t,n.surface),{resolveSessionAppBundleIdForTarget:i}=await Xe();return{appBundleId:r.appBundleId??await i(t,n.target,n.currentAppBundleId),appName:r.appName??n.target}}async function Z(e){if(!t(e)||e.kind!==`simulator`)return;let{detectSoleRunningIosSimulatorApp:n}=await Qe(),r=await n(e);return r?{appBundleId:r.bundleId,appName:r.name}:void 0}async function it(e,t){if(!r(e)||t===`app`||t===`desktop`||t===`menubar`)return{};let{resolveFrontmostMacOsApp:n}=await X(),i=await n();return{appBundleId:i.bundleId,appName:i.appName}}function Q(e,t){return{requestId:e.requestId,logPath:e.logPath,traceLogPath:e.traceLogPath,verbose:e.verbose,iosXctestrunFile:e.iosXctestrunFile,iosXctestDerivedDataPath:e.iosXctestDerivedDataPath,iosXctestEnvDir:e.iosXctestEnvDir,runnerLeaseContext:e.runnerLeaseContext,signal:t}}async function at(e,t){if(!r(e))return;let{runMacOsAlertAction:n}=await X();await n(`dismiss`,t.surface===`frontmost-app`?{surface:`frontmost-app`}:t.appBundleId?{bundleId:t.appBundleId}:{})}let ot;const st=()=>ot??=import(`./platform-runtime-open-target.js`).then(e=>e.t);let ct;const $=()=>ct??=import(`./platform-runtime-runtime-hints.js`);function lt(){return Object.freeze({resolveOpenTarget:async(e,t)=>await ut(e,t),inferOpenedAppBundleId:async(e,t,n)=>{if(n)return n;try{let{inferAndroidPackageAfterOpen:r}=await f();return await r(e,t,n)}catch{return n}},resetFramePerfStats:async(e,t)=>{let{resetAndroidFramePerfStats:n}=await f();await n(e,t)},applyRuntimeHints:async(e,t)=>{let{applyRuntimeHintValues:n}=await $();await n({device:e,...t})},clearRuntimeHints:async(e,t)=>{let{clearRuntimeHintValues:n}=await $();await n({device:e,...t})},activateTestIme:async(t,n)=>{let{activateAndroidTestIme:r}=await f(),i=await r(t,n);if(i.outcome===`helper-unavailable`){a({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:t.id,error:i.reason}});return}if(i.persistFailed&&!(!i.alreadyActive&&!i.activated))throw new e(`COMMAND_FAILED`,`Android test IME recovery records could not be persisted for ${t.name??t.id}.`,{reason:`android_test_ime_recovery_fence_failed`,deviceId:t.id})},restoreTestIme:async(t,n)=>{let{restoreAndroidTestIme:r}=await f();if((await r(t,{stateDir:n.stateDir})).reason===`set-failed`)throw new e(`COMMAND_FAILED`,`Android test IME could not be restored on ${t.name??t.id}.`,{reason:`android_test_ime_restore_incomplete`,deviceId:t.id})},recoverTestImeStartup:async e=>{let{listAndroidAdbSerialsQuick:t,restoreOrphanedAndroidTestImeOnDaemonStartup:n}=await f();await n({stateDir:e.stateDir,listSerials:t})},hasTestImeRecoveryEvidence:async e=>{let{readAndroidTestImeRecoveryMarkers:t}=await f();return(await t(e)).length>0}})}async function ut(e,t){let{resolveSessionAppBundleIdForTarget:n}=await st();return{appBundleId:await n(e,t.target,t.currentAppBundleId),appName:t.target}}function dt(){return Object.freeze({resolve:async(e,t)=>{let{getLocalInteractor:n}=await import(`./interactors.js`).then(e=>e.n);return await n(e,t)}})}function ft(e){return Object.freeze({recoverStartupResources:async t=>{await e.android.hasTestImeRecoveryEvidence(t.stateDir)&&await e.android.recoverTestImeStartup(t)},detachForDaemonShutdown:async()=>await e.apple.detachRunnerSessionsForShutdown(),finalizeDaemonShutdown:async()=>await e.apple.finalizeRunnerSessionsForShutdown()})}function pt(e){return Object.freeze({captureSurface:async(t,n,r)=>t.platform===`linux`?await e.linux(n,r):(mt(t),await e.macos(n,r)),presentIosAcquisition:async(e,t)=>{let{presentIosSnapshotAcquisition:n}=await import(`./ios-snapshot-runtime.js`);return await n(e,t)}})}function mt(e){if(e.platform!==`apple`||e.appleOs!==`macos`)throw TypeError(`Apple surface capture requires a non-app macOS surface`)}async function ht(e,t){let{captureMacOsSurfaceSnapshot:n}=await import(`./macos-facade.js`);return await n(e??{},t)}function gt(e){let t=h(e.sessionsDir),n=Object.freeze({mode:`local`,start:t.start}),r=_(),i=Object.freeze({which:async e=>await u(e)?e:void 0,run:async(e,t)=>{let n=await l(e.executable,[...e.args],{allowFailure:e.allowFailure,cwd:e.cwd,env:e.env?{...process.env,...e.env}:void 0,signal:t,timeoutMs:e.timeoutMs});return{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode}}}),a=pe({resolveSessionArtifacts:e.resolveSessionArtifacts,processes:t,resolveTransport:async e=>{if(e.platform!==`web`)return Object.freeze({mode:`local`});let{resolveWebNetworkTransport:t}=await import(`./platform-runtime-network-web-transport.js`);return await t(e)}}),o=nt(),s=lt();return Object.freeze({commands:i,appleTools:r,toolchains:v(),artifacts:Object.freeze({resolveSession:e.resolveSessionArtifacts}),outputs:Object.freeze({openAppend:async t=>await ce(e.sessionsDir,t),readTail:async(t,n)=>await le(e.sessionsDir,t,n)}),processes:t,processTransports:Object.freeze({resolve:async t=>{if(t.platform!==`android`)return n;let{resolveAndroidAppLogProcessTransport:r}=await import(`./platform-runtime-app-log-android-transport.js`);return r(e.sessionsDir,t,n)}}),...a,appleDeployment:We(),androidDeployment:Ge(),androidTools:Ke(),temporaryFiles:Object.freeze({create:async e=>await g(e)}),deviceReadiness:Object.freeze({applePhysical:Re(),appleAutomation:ze(),androidEmulator:Be()}),deviceShutdown:Ve({appleTools:r,commands:i},e.shutdownLoaders),screenRecording:ge({ownedProcesses:e.ownedProcesses}),audioProbe:O({ownedProcesses:e.ownedProcesses}),perf:Ie(),snapshot:e.snapshot,localInteractors:dt(),appleApplications:o,androidApplications:s,applicationResources:ft({android:s,apple:o}),clock:Object.freeze({now:()=>Date.now(),sleep:async(e,t)=>{await se(e,void 0,t?{signal:t}:void 0)}})})}export{gt as createPlatformRuntimeHost,pt as createSnapshotRuntimeHost,ht as loadMacOsSurfaceSnapshot,ae as recoverLegacyAppLogMarkersAfterDaemonLock};
5
+ `),skippedLines:r})}function ge(e={}){let t=Object.freeze({resolve:async e=>{let{createAndroidScreenRecordingTransport:t}=await import(`./platform-runtime-screen-recording-android-host.js`);return await t(e)}}),n=Object.freeze({resolve:async e=>{let{resolveWebScreenRecordingTransport:t}=await import(`./platform-runtime-screen-recording-web-host.js`);return await t(e)}}),r=Object.freeze({prepare:async e=>{let{createScreenRecordingOutputHost:t}=await import(`./platform-runtime-screen-recording-output-host.js`);await t().prepare(e)},copy:async e=>{let{createScreenRecordingOutputHost:t}=await import(`./platform-runtime-screen-recording-output-host.js`);await t().copy(e)},remove:async e=>{let{createScreenRecordingOutputHost:t}=await import(`./platform-runtime-screen-recording-output-host.js`);return await t().remove(e)}}),i=Object.freeze({sniff:async e=>{let{createScreenRecordingFinalizer:t}=await import(`./platform-runtime-screen-recording-finalizer-host.js`);await t().sniff(e)},complete:async(e,t)=>{let{createScreenRecordingFinalizer:n}=await import(`./platform-runtime-screen-recording-finalizer-host.js`);return await n().complete(e,t)}}),a=e.ownedProcesses??Object.freeze({replace:()=>{},clear:()=>{}});return Object.freeze({apple:E(),android:t,harmony:D(),web:n,outputs:r,finalize:i,ownedProcesses:a})}function E(){let e=async()=>{let{createAppleScreenRecordingHost:e}=await import(`./platform-runtime-screen-recording-apple-host.js`);return e()};return Object.freeze({availability:async t=>(await e()).availability(t),runRunner:async(t,n,r)=>await(await e()).runRunner(t,n,r),startSimulator:async(t,n,r)=>await(await e()).startSimulator(t,n,r),inspectProcess:async t=>await(await e()).inspectProcess(t),terminateProcess:async t=>await(await e()).terminateProcess(t),inspectRunner:async(t,n,r)=>await(await e()).inspectRunner(t,n,r),retrieveRunnerRecording:async(t,n,r,i)=>await(await e()).retrieveRunnerRecording(t,n,r,i),captureClockAnchor:async(t,n,r)=>await(await e()).captureClockAnchor(t,n,r),isRunnerBundleId:async t=>await(await e()).isRunnerBundleId(t)})}function D(){let e=async()=>{let{createHarmonyScreenRecordingHost:e}=await import(`./platform-runtime-screen-recording-harmony-host.js`);return e()};return Object.freeze({start:async(t,n,r)=>await(await e()).start(t,n,r),stop:async(t,n)=>await(await e()).stop(t,n),findMedia:async(t,n,r)=>await(await e()).findMedia(t,n,r),stageMedia:async(t,n,r)=>await(await e()).stageMedia(t,n,r),stagedFileSize:async(t,n,r)=>await(await e()).stagedFileSize(t,n,r),pull:async(t,n,r)=>await(await e()).pull(t,n,r),remove:async(t,n,r)=>await(await e()).remove(t,n,r),removeMedia:async(t,n,r)=>await(await e()).removeMedia(t,n,r)})}function O(e={}){let t=e.ownedProcesses??Object.freeze({replace:()=>{},clear:()=>{}});return Object.freeze({hostCapture:Object.freeze({info:Object.freeze({source:`system-audio`,backend:`macos-screencapturekit`,sourceCount:1,notes:k}),start:async e=>{let{startMacOsAudioProbeProcess:t}=await import(`./macos-facade.js`),n=await t(e),r=await b(n.child.pid??void 0);return Object.freeze({...r===void 0?{}:{marker:r},wait:n.wait,terminate:async()=>{n.child.kill(`SIGTERM`),await n.wait.catch(()=>{})}})},inspectProcess:async e=>x(e),terminateProcess:async e=>await y([e])}),web:Object.freeze({resolve:async e=>{if(e.platform!==`web`)return;let{resolveWebProvider:t}=await import(`./src6.js`).then(e=>e.i),n=await t(),r=n.probeAudio?.bind(n);if(r)return Object.freeze({probe:async e=>await r({action:e.action,durationMs:e.durationMs,bucketMs:e.bucketMs})})}}),ownedProcesses:t})}function k(e){return[`Audio probe samples host system audio through ScreenCaptureKit for this ${t(e)?`iOS simulator`:e.platform===`android`?`Android emulator`:`macOS session`}; it is not app-instrumented audio.`,`Screen Recording permission is required for host system audio capture.`,`Other audible host apps can contribute to the measured buckets.`]}const A=f,j=async()=>await import(`./perf-facade.js`),M=Object.freeze({resourceKind:p,version:1,encode:e=>e,decode:Ce});async function N(t,n,r){if(r.kind!==`xctrace`)throw H(`Apple`,`xctrace`,r.kind);let i=r.template??(r.mode===`cpu-profile`?`Time Profiler`:`Animation Hitches`),a=await j(),o=await a.startAppleXctracePerfCapture({device:t,appBundleId:r.appId,mode:r.mode,template:i,outPath:r.outPath}),s=await b(o.child.pid??void 0);if(!s)throw await a.cleanupAppleXctracePerfCapture(o).catch(()=>{}),new e(`COMMAND_FAILED`,`Apple xctrace exposed no exact process identity`);return F(t,n,r,{family:`apple`,marker:s,capture:xe(o)},I(o),z(`started`,o))}async function P(e,t,n){let r=await A(),i;if(n.mode===`cpu-profile`){if(n.kind!==`simpleperf`)throw H(`Android`,`simpleperf`,n.kind);i=await r.startAndroidSimpleperfProfile(e,n.appId,n.outPath)}else{if(n.kind!==`perfetto`)throw H(`Android`,`perfetto`,n.kind);i=await r.startAndroidPerfettoTrace(e,n.appId,n.outPath)}return F(e,t,n,{family:`android`,capture:i},L(e,i),B(i))}function F(e,t,n,r,a,o){return Object.freeze({pendingHandle:new ne(a),envelope:te({resourceKind:p,sessionId:n.sessionId,device:i(e),owner:t,fence:n.fence,lifecycle:`open`,descriptor:ee(M,r)}),response:o})}function I(e){return R({initialOutPath:e.outPath,inspect:()=>z(`started`,e),finish:async t=>await j().then(async n=>z(`stopped`,await n.stopAppleXctracePerfCapture(e,t))),cleanup:async()=>await j().then(async t=>{await t.cleanupAppleXctracePerfCapture(e)})})}function L(e,t){return R({initialOutPath:t.outPath,inspect:()=>B(t),finish:async n=>{let r=await A();return B(t.kind===`simpleperf`?await r.stopAndroidSimpleperfProfile(e,t,n):await r.stopAndroidPerfettoTrace(e,t,n))},cleanup:async()=>{await(await A()).cleanupAndroidNativePerfSession(e,t)}})}function R(e){let t=e.initialOutPath,n,r,i=async()=>await e.cleanup().then(()=>({status:`cleaned`}),V);return Object.freeze({inspect:e.inspect,setOutputPath:e=>{t=e},finish:async()=>n??=e.finish(t).then(e=>({status:`completed`,result:e}),e=>{throw n=void 0,e}),forceCleanup:async()=>r??=i(),[Symbol.asyncDispose]:async()=>{Se(await(r??=i()))}})}async function _e(e){let t=m(e,M);if(t.status!==`decoded`||t.descriptor.family!==`apple`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};let n=await x(t.descriptor.marker);if(n===`ownership-lost`)return{status:`cleanup-pending`,reason:`ownership-fence-lost`};if(n===`missing`)return{status:`already-missing`};let r=await y([t.descriptor.marker]);return r===`terminated`?{status:`cleaned`}:r===`already-missing`?{status:`already-missing`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`}}async function ve(e){let t=m(e,M);if(t.status!==`decoded`)return t;if(t.descriptor.family!==`apple`)return{status:`unreattachable`,reason:`descriptor-invalid`};let n=await x(t.descriptor.marker);return n===`owned-alive`?{status:`unreattachable`,reason:`transport-not-reattachable`}:n===`ownership-lost`?{status:`unreattachable`,reason:`ownership-fence-lost`}:{status:`missing`}}async function ye(e){let t=m(e,M);return t.status===`decoded`?t.descriptor.family===`android`?{status:`unreattachable`,reason:`transport-not-reattachable`}:{status:`unreattachable`,reason:`descriptor-invalid`}:t}async function be(e,t){let n=m(t,M);if(n.status!==`decoded`||n.descriptor.family!==`android`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};try{return await(await A()).cleanupAndroidNativePerfSession(e,n.descriptor.capture),{status:`cleaned`}}catch(e){return V(e)}}function xe(e){let{child:t,wait:n,...r}=e;return r}function z(e,t){return{perf:e,kind:t.kind,mode:t.mode,template:t.template,outPath:t.outPath,appBundleId:t.appBundleId,deviceId:t.deviceId,platform:t.platform,targetPids:t.targetPids,targetProcesses:t.targetProcesses,startedAt:t.startedAt,endedAt:t.endedAt}}function B(e){let t={action:e.action,platform:`android`,type:e.type,packageName:e.packageName,appPid:e.appPid,profilerPid:e.profilerPid,state:e.state,startedAt:new Date(e.startedAt).toISOString(),stoppedAt:typeof e.stoppedAt==`number`?new Date(e.stoppedAt).toISOString():void 0,outPath:e.outPath,sizeBytes:e.sizeBytes,remotePath:e.remotePath,method:e.method,message:e.message,...e.action===`stop`?{durationMs:e.durationMs,summary:e.summary}:{}};return e.kind===`simpleperf`?{...t,kind:`simpleperf`,mode:`cpu-profile`}:{...t,kind:`perfetto`,mode:`trace`}}function V(e){return{status:`cleanup-pending`,reason:`cleanup-unconfirmed`,message:e instanceof Error?e.message:String(e)}}function Se(t){if(t.status===`cleanup-pending`)throw new e(`COMMAND_FAILED`,t.message??`Perf capture cleanup could not be confirmed`,{reason:t.reason})}function H(t,n,r){return new e(`INVALID_ARGS`,`${t} native perf requires --kind ${n}, not ${r}`)}function Ce(e){return e.family===`android`&&we(e.capture)?{status:`decoded`,descriptor:{family:`android`,capture:e.capture}}:e.family===`apple`&&De(e.capture)&&je(e.marker)?{status:`decoded`,descriptor:{family:`apple`,capture:e.capture,marker:e.marker}}:{status:`invalid`,message:`Perf capture descriptor body is invalid`}}function we(e){return W(e)?Te(e.kind,e.type)&&U(e,[`packageName`,`appPid`,`profilerPid`,`remotePath`,`outPath`])&&typeof e.startedAt==`number`&&Ee(e.state)&&Oe(e,[`stoppedAt`,`sizeBytes`]):!1}function Te(e,t){return e===`simpleperf`&&t===`cpu-profile`||e===`perfetto`&&t===`trace`}function Ee(e){return e===`running`||e===`stopped`}function De(e){return W(e)&&e.kind===`xctrace`&&(e.mode===`cpu-profile`||e.mode===`trace`)&&U(e,[`template`,`outPath`,`appBundleId`,`deviceId`,`startedAt`])&&n(e.platform)&&ke(e.targetProcesses)&&Ae(e.targetPids)}function U(e,t){return t.every(t=>typeof e[t]==`string`)}function Oe(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`number`)}function ke(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function Ae(e){return Array.isArray(e)&&e.every(e=>typeof e==`number`)}function W(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function je(e){return W(e)&&typeof e.pid==`number`&&typeof e.startTime==`string`&&typeof e.command==`string`}const G=f,Me=f,Ne=f,K=async()=>await import(`./perf-facade.js`),q=async()=>await import(`./perf-facade.js`),Pe=async()=>await import(`./perf-facade.js`),Fe=async()=>await import(`./src4.js`).then(e=>e.b);function Ie(){let e=Object.freeze({sampleFrames:async(e,t)=>await(await K()).sampleAppleFramePerf(e,t),frameSampling:async e=>(await q()).buildAppleFrameSamplingMetadata(e),sampleMemory:async(e,t)=>await(await K()).sampleAppleMemoryPerf(e,t),memorySampling:async e=>(await q()).buildAppleMemorySamplingMetadata(e),memorySnapshotSupport:async e=>(await q()).buildAppleMemorySnapshotSupport(e),captureMemorySnapshot:async(e,t,n)=>await(await K()).captureAppleMemorySnapshot(e,t,n),start:async(e,t,n)=>await N(e,t,n),reattach:async(e,{envelope:t})=>await ve(t),cleanup:async(e,{envelope:t})=>await _e(t),writeProfileReport:async e=>await(await Pe()).writeAppleXctracePerfReport({tracePath:e.tracePath,outPath:e.outPath,template:e.template,appBundleId:e.appId})}),t=Object.freeze({sampleFrames:async(e,t)=>await(await Me()).sampleAndroidFramePerf(e,t),sampleMemory:async(e,t)=>await(await G()).sampleAndroidMemoryPerf(e,t),captureMemorySnapshot:async(e,t,n)=>await(await G()).captureAndroidHeapSnapshot(e,t,n),start:async(e,t,n)=>await P(e,t,n),reattach:async(e,{envelope:t})=>await ye(t),cleanup:async(e,{envelope:t})=>await be(e,t),writeProfileReport:async(e,t)=>await(await Ne()).writeAndroidSimpleperfReport(e,Le(t.profile,t.tracePath),t.outPath)}),n=Object.freeze({sampleMemory:async(e,t)=>await(await Fe()).sampleHarmonyMemoryPerf(e,t)});return Object.freeze({apple:e,android:t,harmony:n})}function Le(t,n){if(t?.kind!==`simpleperf`||t.type!==`cpu-profile`||t.mode!==`cpu-profile`)throw new e(`INVALID_ARGS`,`Stopped Simpleperf profile metadata is malformed.`);return{type:`cpu-profile`,kind:`simpleperf`,packageName:t.packageName,appPid:t.appPid,profilerPid:t.profilerPid,remotePath:t.remotePath,outPath:n,startedAt:t.startedAt?Date.parse(t.startedAt):Date.now(),state:`stopped`,...t.stoppedAt?{stoppedAt:Date.parse(t.stoppedAt)}:{},...t.sizeBytes===void 0?{}:{sizeBytes:t.sizeBytes}}}function Re(){return Object.freeze({ensureConnected:async(e,t)=>{t.throwIfAborted();try{let{resolveIosPhysicalDeviceControl:n}=await import(`./physical-device-facade.js`);await n(e).ensureReady(e,t),t.throwIfAborted()}catch(e){throw t.throwIfAborted(),e}}})}function ze(){return Object.freeze({keepHot:e=>{import(`./runner-operations-facade.js`).then(({prewarmAppleRunnerCache:t})=>t(e,{})).catch(()=>{})},wasRecentlyObservedBooted:async e=>{let{wasSimulatorRecentlyObservedBooted:t}=await import(`./simulator-facade.js`);return t(e)},markBooted:e=>{import(`./simulator-facade.js`).then(({markSimulatorBooted:t})=>t(e)).catch(()=>{})}})}function Be(){return Object.freeze({discover:async(e,t)=>{t.throwIfAborted();let n=await re(e);return t.throwIfAborted(),n},launch:(e,t)=>{let n=[`-avd`,e];return t&&n.push(`-no-window`,`-no-audio`),d(`emulator`,n)},terminate:async e=>{await o({pids:[e],termTimeoutMs:1500,killTimeoutMs:1500})}})}function Ve(e,t){let n,r,i=async()=>(n??=t.apple({appleTools:e.appleTools}),await n),a=async()=>(r??=t.android({commands:e.commands}),await r),o=Object.freeze({shutdownTarget:async(e,t)=>await(await i()).shutdownTarget(e,t)}),s=Object.freeze({shutdownTarget:async(e,t)=>await(await a()).shutdownTarget(e,t)}),c=Object.freeze({canShutdownTarget:async e=>await He(e,i,a),shutdownTarget:async e=>await Ue(e,i,a)});return Object.freeze({apple:o,android:s,close:c})}async function He(e,t,n){return e.platform===`apple`?(await t()).canShutdownTarget(e):e.platform===`android`&&(await n()).canShutdownTarget(e)}async function Ue(e,t,n){let r=new AbortController().signal;return e.platform===`apple`?await(await t()).shutdownTarget(e,r):e.platform===`android`?await(await n()).shutdownTarget(e,r):{success:!1,exitCode:-1,stdout:``,stderr:`Cannot shut down unsupported device ${e.platform}/${e.kind}`}}function We(){return Object.freeze({withInvalidatedAppResolutionCache:async(e,t)=>{let{invalidateIosAppResolutionCache:n}=await import(`./app-resolution-facade.js`);return await n(e,t)},prepareArtifact:async(e,t)=>{let{prepareIosInstallArtifact:n}=await import(`./install-artifact-facade.js`);return await n(e.source,t)},resolveAppBundleId:async(e,t)=>{let{resolveIosApp:n}=await import(`./app-resolution-facade.js`);return await n(e,t)}})}function Ge(){return Object.freeze({bundletoolJar:process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim()||void 0,withInvalidatedAppResolutionCache:async(e,t)=>{let{withAndroidAppResolutionCacheInvalidated:n}=await f();return await n(e,t)},prepareArtifact:async(e,t)=>{let{prepareAndroidInstallArtifact:n}=await f();return await n(e.source,t)},resolveAppPackage:async(e,t)=>{let{resolveAndroidApp:n}=await f(),r=await n(e,t);if(r.type===`intent`){let{AppError:e}=await import(`./sdk-contracts.js`).then(e=>e.O);throw new e(`INVALID_ARGS`,`App uninstall requires a package name, not an intent`)}return r.value}})}function Ke(){return Object.freeze({probeClipboardShellSupport:async(e,t)=>{try{let{runAndroidAdb:n,isAndroidShellCommandUnsupported:r}=await f(),i=await n(e,[`shell`,`cmd`,`clipboard`,`get`,`text`],{allowFailure:!0,signal:t});return i.exitCode===0?`supported`:r(i.stdout,i.stderr)?`unsupported`:`probe-failed`}catch{return`probe-failed`}},runAdb:async(e,t,n,r)=>{let{runAndroidAdb:i}=await f(),a=await i(e,[...t],{allowFailure:n.allowFailure,timeoutMs:n.timeoutMs,signal:r});return{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode}},installPackage:async(e,t,n,r)=>{let{resolveAndroidAdbProvider:i}=await f(),a=i(e),o=a.install?await a.install(t,{replace:n.replace,signal:r}):await a.exec([`install`,...n.replace?[`-r`]:[],t],{signal:r});return{stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode}},installBundle:async(e,t,n,r)=>{let{resolveAndroidAdbProvider:i}=await f(),a=i(e).installBundle;return a?(await a(t,{mode:n,signal:r}),!0):!1}})}let qe;const J=()=>qe??=import(`./runner-operations-facade.js`);let Je;const Y=()=>Je??=import(`./platform-runtime-runtime-hints.js`);let Ye;const Xe=()=>Ye??=import(`./platform-runtime-open-target.js`).then(e=>e.t);let Ze;const Qe=()=>Ze??=import(`./app-resolution-facade.js`);let $e;const X=()=>$e??=import(`./macos-facade.js`);let et;const tt=()=>et??=import(`./retry.js`).then(e=>e.t);function nt(){return Object.freeze({resolveOpenTarget:async(e,t)=>await rt(e,t),prewarmRunnerCache:async(e,t,n)=>{let{prewarmAppleRunnerCache:r}=await J();await r(e,Q(t,n))},prewarmRunnerSession:async(e,t,n,r,i)=>{let{prewarmIosRunnerSession:a}=await J();await a(e,{...Q(t,n),propagateError:r,...i})},notifyRunnerAppRelaunched:async(e,t,n)=>{let{notifyIosRunnerAppRelaunched:r}=await J();await r(e,Q(t,n))},stopRunnerSession:async e=>{let{stopIosRunnerSession:t}=await J();await t(e)},hasLiveRunnerSession:async(e,t)=>{let{hasLiveIosRunnerSession:n}=await J();return n(e,{requestId:t.requestId})},releaseSpeculativeRunner:async(e,t)=>{let{releaseSpeculativeIosRunnerSessionFor:n}=await J();return await n(e,{requestId:t.requestId})},releaseRunnerOnClose:async(e,t)=>{let{releaseIosRunnerOnClose:n}=await J();await n(e,t)},prepareRunner:async(e,t,n)=>{let{Deadline:r}=await tt(),{prepareIosRunner:i}=await J(),a=Date.now();return await i(e,{...Q(t.execution,n),cleanStaleBundles:!0,buildTimeoutMs:t.timeoutMs,healthTimeoutMs:t.timeoutMs,prepareDeadline:r.fromTimeoutMs(t.timeoutMs,a),startupTimeoutMs:t.timeoutMs})},applyRuntimeHints:async(e,t)=>{let{applyRuntimeHintValues:n}=await Y();await n({device:e,...t})},clearRuntimeHints:async(e,t)=>{let{clearRuntimeHintValues:n}=await Y();await n({device:e,...t})},dismissCloseAlerts:async(e,t)=>await at(e,t),detachRunnerSessionsForShutdown:async()=>{let{detachIosSimulatorRunnerSessionsForShutdown:e}=await J();await e()},finalizeRunnerSessionsForShutdown:async()=>{let{stopAllIosRunnerSessions:e}=await J();await e()}})}async function rt(t,n){if(n.foreground){let n=await Z(t);if(n)return n;throw new e(`AMBIGUOUS_MATCH`,`open --foreground requires exactly one running app on the selected iOS simulator.`,{reason:`foreground_app_ambiguous`,hint:`Pass an explicit app instead: agent-device open <app> --platform ios.`})}let r=await it(t,n.surface),{resolveSessionAppBundleIdForTarget:i}=await Xe();return{appBundleId:r.appBundleId??await i(t,n.target,n.currentAppBundleId),appName:r.appName??n.target}}async function Z(e){if(!t(e)||e.kind!==`simulator`)return;let{detectSoleRunningIosSimulatorApp:n}=await Qe(),r=await n(e);return r?{appBundleId:r.bundleId,appName:r.name}:void 0}async function it(e,t){if(!r(e)||t===`app`||t===`desktop`||t===`menubar`)return{};let{resolveFrontmostMacOsApp:n}=await X(),i=await n();return{appBundleId:i.bundleId,appName:i.appName}}function Q(e,t){return{requestId:e.requestId,logPath:e.logPath,traceLogPath:e.traceLogPath,verbose:e.verbose,iosXctestrunFile:e.iosXctestrunFile,iosXctestDerivedDataPath:e.iosXctestDerivedDataPath,iosXctestEnvDir:e.iosXctestEnvDir,runnerLeaseContext:e.runnerLeaseContext,signal:t}}async function at(e,t){if(!r(e))return;let{runMacOsAlertAction:n}=await X();await n(`dismiss`,t.surface===`frontmost-app`?{surface:`frontmost-app`}:t.appBundleId?{bundleId:t.appBundleId}:{})}let ot;const st=()=>ot??=import(`./platform-runtime-open-target.js`).then(e=>e.t);let ct;const $=()=>ct??=import(`./platform-runtime-runtime-hints.js`);function lt(){return Object.freeze({resolveOpenTarget:async(e,t)=>await ut(e,t),inferOpenedAppBundleId:async(e,t,n)=>{if(n)return n;try{let{inferAndroidPackageAfterOpen:r}=await f();return await r(e,t,n)}catch{return n}},resetFramePerfStats:async(e,t)=>{let{resetAndroidFramePerfStats:n}=await f();await n(e,t)},applyRuntimeHints:async(e,t)=>{let{applyRuntimeHintValues:n}=await $();await n({device:e,...t})},clearRuntimeHints:async(e,t)=>{let{clearRuntimeHintValues:n}=await $();await n({device:e,...t})},activateTestIme:async(t,n)=>{let{activateAndroidTestIme:r}=await f(),i=await r(t,n);if(i.outcome===`helper-unavailable`){a({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:t.id,error:i.reason,...i.hint===void 0?{}:{hint:i.hint}}});return}if(i.persistFailed&&!(!i.alreadyActive&&!i.activated))throw new e(`COMMAND_FAILED`,`Android test IME recovery records could not be persisted for ${t.name??t.id}.`,{reason:`android_test_ime_recovery_fence_failed`,deviceId:t.id})},restoreTestIme:async(t,n)=>{let{restoreAndroidTestIme:r}=await f();if((await r(t,{stateDir:n.stateDir})).reason===`set-failed`)throw new e(`COMMAND_FAILED`,`Android test IME could not be restored on ${t.name??t.id}.`,{reason:`android_test_ime_restore_incomplete`,deviceId:t.id})},recoverTestImeStartup:async e=>{let{listAndroidAdbSerialsQuick:t,restoreOrphanedAndroidTestImeOnDaemonStartup:n}=await f();await n({stateDir:e.stateDir,listSerials:t})},hasTestImeRecoveryEvidence:async e=>{let{readAndroidTestImeRecoveryMarkers:t}=await f();return(await t(e)).length>0}})}async function ut(e,t){let{resolveSessionAppBundleIdForTarget:n}=await st();return{appBundleId:await n(e,t.target,t.currentAppBundleId),appName:t.target}}function dt(){return Object.freeze({resolve:async(e,t)=>{let{getLocalInteractor:n}=await import(`./interactors.js`).then(e=>e.n);return await n(e,t)}})}function ft(e){return Object.freeze({recoverStartupResources:async t=>{await e.android.hasTestImeRecoveryEvidence(t.stateDir)&&await e.android.recoverTestImeStartup(t)},detachForDaemonShutdown:async()=>await e.apple.detachRunnerSessionsForShutdown(),finalizeDaemonShutdown:async()=>await e.apple.finalizeRunnerSessionsForShutdown()})}function pt(e){return Object.freeze({captureSurface:async(t,n,r)=>t.platform===`linux`?await e.linux(n,r):(mt(t),await e.macos(n,r)),presentIosAcquisition:async(e,t)=>{let{presentIosSnapshotAcquisition:n}=await import(`./ios-snapshot-runtime.js`);return await n(e,t)}})}function mt(e){if(e.platform!==`apple`||e.appleOs!==`macos`)throw TypeError(`Apple surface capture requires a non-app macOS surface`)}async function ht(e,t){let{captureMacOsSurfaceSnapshot:n}=await import(`./macos-facade.js`);return await n(e??{},t)}function gt(e){let t=h(e.sessionsDir),n=Object.freeze({mode:`local`,start:t.start}),r=_(),i=Object.freeze({which:async e=>await u(e)?e:void 0,run:async(e,t)=>{let n=await l(e.executable,[...e.args],{allowFailure:e.allowFailure,cwd:e.cwd,env:e.env?{...process.env,...e.env}:void 0,signal:t,timeoutMs:e.timeoutMs});return{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode}}}),a=pe({resolveSessionArtifacts:e.resolveSessionArtifacts,processes:t,resolveTransport:async e=>{if(e.platform!==`web`)return Object.freeze({mode:`local`});let{resolveWebNetworkTransport:t}=await import(`./platform-runtime-network-web-transport.js`);return await t(e)}}),o=nt(),s=lt();return Object.freeze({commands:i,appleTools:r,toolchains:v(),artifacts:Object.freeze({resolveSession:e.resolveSessionArtifacts}),outputs:Object.freeze({openAppend:async t=>await ce(e.sessionsDir,t),readTail:async(t,n)=>await le(e.sessionsDir,t,n)}),processes:t,processTransports:Object.freeze({resolve:async t=>{if(t.platform!==`android`)return n;let{resolveAndroidAppLogProcessTransport:r}=await import(`./platform-runtime-app-log-android-transport.js`);return r(e.sessionsDir,t,n)}}),...a,appleDeployment:We(),androidDeployment:Ge(),androidTools:Ke(),temporaryFiles:Object.freeze({create:async e=>await g(e)}),deviceReadiness:Object.freeze({applePhysical:Re(),appleAutomation:ze(),androidEmulator:Be()}),deviceShutdown:Ve({appleTools:r,commands:i},e.shutdownLoaders),screenRecording:ge({ownedProcesses:e.ownedProcesses}),audioProbe:O({ownedProcesses:e.ownedProcesses}),perf:Ie(),snapshot:e.snapshot,localInteractors:dt(),appleApplications:o,androidApplications:s,applicationResources:ft({android:s,apple:o}),clock:Object.freeze({now:()=>Date.now(),sleep:async(e,t)=>{await se(e,void 0,t?{signal:t}:void 0)}})})}export{gt as createPlatformRuntimeHost,pt as createSnapshotRuntimeHost,ht as loadMacOsSurfaceSnapshot,ae as recoverLegacyAppLogMarkersAfterDaemonLock};
@@ -1 +1 @@
1
- import{n as e}from"./command.js";import{t}from"./platform-runtime-android-mechanics.js";import{t as n}from"./video.js";import r from"node:path";const i={medium:8e6,high:2e7};async function a(a){let{resolveAndroidAdbExecutor:s,resolveScopedAndroidAdbBackgroundTransport:c}=await t(),l=s(a),u=c(a),d=async(e,t)=>await l([`shell`,e],{allowFailure:!0,timeoutMs:5e3,signal:t});return Object.freeze({mode:u.mode,start:async({remotePath:t,quality:n=`medium`},r)=>{let a=(await d(`screenrecord --bit-rate ${i[n]} ${e(t)} >/dev/null 2>&1 & echo $!`,r)).stdout.split(/\s+/).find(e=>/^\d+$/.test(e));if(!a)throw Error(`Android screenrecord did not return a process id`);let s=await o(d,{pid:a,remotePath:t,startTime:``},r);if(s.status!==`owned-alive`||!s.process)throw Error(`Android screenrecord did not expose a complete process identity`);return Object.freeze({process:s.process})},inspect:async(e,t)=>(await o(d,e,t)).status,stop:async(e,t,n)=>{let r=await o(d,e,n);return r.status===`missing`?`already-missing`:r.status===`foreign-writer`?`ownership-lost`:r.status===`owned-alive`?(await d(`kill ${t?.force?`-9 `:`-2 `}${e.pid}`,n)).exitCode===0?`stopped`:`uncertain`:r.status},exists:async(t,n)=>(await d(`test -e ${e(t)}`,n)).exitCode===0,size:async(t,n)=>{let r=await d(`test -e ${e(t)}`,n);if(r.exitCode!==0)return r.stderr.trim()===``?void 0:`uncertain`;let i=await d(`stat -c %s ${e(t)}`,n);if(i.exitCode!==0)return`uncertain`;let a=Number(i.stdout.trim());return Number.isSafeInteger(a)&&a>=0?a:`uncertain`},probeRunningWriters:async(e,t)=>{let n=await d(`ps -A -o pid=`,t);if(n.exitCode!==0)return{writers:[],conclusive:!1};let r=n.stdout.split(/\s+/).filter(e=>/^\d+$/.test(e)),i=await Promise.all(r.map(async n=>await o(d,{pid:n,remotePath:e,startTime:``},t)));return{writers:i.flatMap(e=>e.status===`owned-alive`&&e.process?[e.process]:[]),conclusive:!i.some(e=>e.status===`uncertain`)}},pullPlayable:async({remotePath:e,outputPath:t},r)=>{let i=await l([`pull`,e,t],{allowFailure:!0,signal:r});return{...i,playable:i.exitCode===0&&await n(t)}},remove:async(t,n)=>(await d(`rm -f ${e(t)}`,n)).exitCode===0,manifestPathFor:e=>`${r.posix.dirname(e)}/agent-device-recording-active.json`,readManifest:async(t,n)=>{let r=await d(`test -e ${e(t)}`,n);if(r.exitCode!==0)return r.exitCode===1&&r.stderr.trim()===``?{status:`missing`}:{status:`unavailable`,message:r.stderr.trim()||`Android recording manifest probe failed`};let i=await d(`cat ${e(t)}`,n);return i.exitCode===0?{status:`read`,contents:i.stdout}:{status:`unavailable`,message:i.stderr.trim()||`Android recording manifest could not be read`}},writeManifest:async({manifestPath:t,contents:n},r)=>{let i=`${t}.tmp`;if((await d(`printf %s ${e(n)} > ${e(i)} && mv -f ${e(i)} ${e(t)}`,r)).exitCode!==0)throw Error(`failed to write Android recording manifest`)},removeManifest:async(t,n)=>(await d(`rm -f ${e(t)}`,n)).exitCode===0})}async function o(e,t,n){let r=await s(e,t.pid,n);if(r!==`present`)return{status:r};let i=await e(`cat /proc/${t.pid}/stat`,n);if(i.exitCode!==0)return{status:`uncertain`};let a=l(i.stdout);if(!a)return{status:`uncertain`};let o=await e(`cat /proc/${t.pid}/cmdline`,n);return o.exitCode===0?c(o.stdout,t.remotePath)?t.startTime.length>0&&t.startTime!==a?{status:`foreign-writer`}:{status:`owned-alive`,process:Object.freeze({pid:t.pid,remotePath:t.remotePath,startTime:a})}:{status:`ownership-lost`}:{status:`uncertain`}}async function s(e,t,n){let r=await e(`test -d /proc/${t}`,n);return r.exitCode===0?`present`:r.exitCode===1&&r.stderr.trim()===``?`missing`:`uncertain`}function c(e,t){let n=e.split(`\0`).filter(e=>e.length>0),i=n[0];return i!==void 0&&r.posix.basename(i)===`screenrecord`&&n.at(-1)===t}function l(e){let t=e.lastIndexOf(`)`);if(t<0)return;let n=e.slice(t+1).trim().split(/\s+/)[19];return n&&/^\d+$/.test(n)?n:void 0}export{a as createAndroidScreenRecordingTransport};
1
+ import{n as e}from"./command.js";import{t}from"./platform-runtime-android-mechanics.js";import{n}from"./video.js";import r from"node:path";const i={medium:8e6,high:2e7};async function a(a){let{resolveAndroidAdbExecutor:s,resolveScopedAndroidAdbBackgroundTransport:c}=await t(),l=s(a),u=c(a),d=async(e,t)=>await l([`shell`,e],{allowFailure:!0,timeoutMs:5e3,signal:t}),f=async(t,n)=>{let r=await d(`test -e ${e(t)}`,n);return r.exitCode===0?`present`:r.exitCode===1&&r.stderr.trim()===``?`absent`:`uncertain`};return Object.freeze({mode:u.mode,start:async({remotePath:t,quality:n=`medium`},r)=>{let a=(await d(`screenrecord --bit-rate ${i[n]} ${e(t)} >/dev/null 2>&1 & echo $!`,r)).stdout.split(/\s+/).find(e=>/^\d+$/.test(e));if(!a)throw Error(`Android screenrecord did not return a process id`);let s=await o(d,{pid:a,remotePath:t,startTime:``},r);if(s.status!==`owned-alive`||!s.process)throw Error(`Android screenrecord did not expose a complete process identity`);return Object.freeze({process:s.process})},inspect:async(e,t)=>(await o(d,e,t)).status,stop:async(e,t,n)=>{let r=await o(d,e,n);return r.status===`missing`?`already-missing`:r.status===`foreign-writer`?`ownership-lost`:r.status===`owned-alive`?(await d(`kill ${t?.force?`-9 `:`-2 `}${e.pid}`,n)).exitCode===0?`stopped`:`uncertain`:r.status},exists:async(e,t)=>{let n=await f(e,t);return n===`present`||n!==`absent`&&`uncertain`},size:async(t,n)=>{let r=await f(t,n);if(r!==`present`)return r===`absent`?void 0:`uncertain`;let i=await d(`stat -c %s ${e(t)}`,n);if(i.exitCode!==0)return`uncertain`;let a=Number(i.stdout.trim());return Number.isSafeInteger(a)&&a>=0?a:`uncertain`},probeRunningWriters:async(e,t)=>{let n=await d(`ps -A -o pid=`,t);if(n.exitCode!==0)return{writers:[],conclusive:!1};let r=n.stdout.split(/\s+/).filter(e=>/^\d+$/.test(e)),i=await Promise.all(r.map(async n=>await o(d,{pid:n,remotePath:e,startTime:``},t)));return{writers:i.flatMap(e=>e.status===`owned-alive`&&e.process?[e.process]:[]),conclusive:!i.some(e=>e.status===`uncertain`)}},pullPlayable:async({remotePath:e,outputPath:t},r)=>{let i=await l([`pull`,e,t],{allowFailure:!0,signal:r});return{...i,playable:i.exitCode===0&&await n(t)}},remove:async(t,n)=>(await d(`rm -f ${e(t)}`,n)).exitCode===0,manifestPathFor:e=>`${r.posix.dirname(e)}/agent-device-recording-active.json`,readManifest:async(t,n)=>{let r=await d(`test -e ${e(t)}`,n);if(r.exitCode!==0)return r.exitCode===1&&r.stderr.trim()===``?{status:`missing`}:{status:`unavailable`,message:r.stderr.trim()||`Android recording manifest probe failed`};let i=await d(`cat ${e(t)}`,n);return i.exitCode===0?{status:`read`,contents:i.stdout}:{status:`unavailable`,message:i.stderr.trim()||`Android recording manifest could not be read`}},writeManifest:async({manifestPath:t,contents:n},r)=>{let i=`${t}.tmp`;if((await d(`printf %s ${e(n)} > ${e(i)} && mv -f ${e(i)} ${e(t)}`,r)).exitCode!==0)throw Error(`failed to write Android recording manifest`)},removeManifest:async(t,n)=>(await d(`rm -f ${e(t)}`,n)).exitCode===0})}async function o(e,t,n){let r=await s(e,t.pid,n);if(r!==`present`)return{status:r};let i=await e(`cat /proc/${t.pid}/stat`,n);if(i.exitCode!==0)return{status:`uncertain`};let a=l(i.stdout);if(!a)return{status:`uncertain`};let o=await e(`cat /proc/${t.pid}/cmdline`,n);return o.exitCode===0?c(o.stdout,t.remotePath)?t.startTime.length>0&&t.startTime!==a?{status:`foreign-writer`}:{status:`owned-alive`,process:Object.freeze({pid:t.pid,remotePath:t.remotePath,startTime:a})}:{status:`ownership-lost`}:{status:`uncertain`}}async function s(e,t,n){let r=await e(`test -d /proc/${t}`,n);return r.exitCode===0?`present`:r.exitCode===1&&r.stderr.trim()===``?`missing`:`uncertain`}function c(e,t){let n=e.split(`\0`).filter(e=>e.length>0),i=n[0];return i!==void 0&&r.posix.basename(i)===`screenrecord`&&n.at(-1)===t}function l(e){let t=e.lastIndexOf(`)`);if(t<0)return;let n=e.slice(t+1).trim().split(/\s+/)[19];return n&&/^\d+$/.test(n)?n:void 0}export{a as createAndroidScreenRecordingTransport};
@@ -1 +1 @@
1
- import{C as e}from"./sdk-contracts.js";import{t}from"./recording-export-quality.js";import{c as n}from"./exec.js";import"./command.js";import{n as r}from"./version.js";import{t as i}from"./screen-recording-runtime.js";import{n as a}from"./telemetry.js";import{a as o,i as s,n as c,r as l,t as u}from"./video.js";import d from"node:path";import f from"node:fs";import{fileURLToPath as p}from"node:url";function m(e,t,n,r){let i=`apple/runner/AgentDeviceRunner/RecordingScripts/${e}`,a=`dist/${i}`;return[d.resolve(t,e),d.resolve(n,i),d.resolve(t,`../${i}`),d.resolve(t,`../../${i}`),d.resolve(t,`../../../${i}`),d.resolve(n,a),d.resolve(r,i)]}function h(t){let n=m(t,d.dirname(p(import.meta.url)),r(),process.cwd());for(let e of n)if(f.existsSync(e))return e;throw new e(`COMMAND_FAILED`,`Missing recording helper script: ${t}`,{hint:`Ensure apple/runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled under dist/apple/runner in the package.`,scriptName:t,searchedPaths:n})}let g,_;function v(e=process.platform){if(e!==`darwin`)return`touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry`}function y(){return g??=h(`recording-overlay.swift`),g}function b(){return _??=h(`RecordingExportSupport.swift`),_}async function x(t){let{videoPath:r,scriptPath:i,scriptArgs:a,commandDescription:u}=t;await l(r),await c(r);let d=S(r);try{let e=await o({sourcePath:i,extraSourcePaths:[b()]});await n(e,[`--input`,r,`--output`,d,...a],{timeoutMs:12e4,env:s()}),await c(d),f.renameSync(d,r)}catch(t){let n=t instanceof e?t:new e(`COMMAND_FAILED`,String(t),void 0,t instanceof Error?t:void 0);throw new e(`COMMAND_FAILED`,u,{...n.details,videoPath:r,script:i},n)}finally{f.rmSync(d,{force:!0})}}function S(e){let t=d.parse(e),n=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;return d.join(t.dir,`.${t.name}.agent-device-${n}${t.ext||`.mp4`}`)}async function C(e){let{videoPath:n,telemetryPath:r,exportQuality:i=t,targetLabel:a=`recording`}=e;await x({videoPath:n,scriptPath:y(),scriptArgs:[`--events`,r,`--quality`,i],commandDescription:`Failed to add touch overlays to the ${a}`})}function w(){return Object.freeze({complete:T})}async function T(t){if(await l(t.outputPath),await c(t.outputPath),!await u(t.outputPath))throw new e(`COMMAND_FAILED`,`recording was not finalized into a playable video: ${t.outputPath}`,{reason:i,retriable:!0,hint:`Run record stop again: a recorder that is still finalizing its file is playable on the next stop, and the recording keeps its evidence either way. If the recorder died before writing a video, close this session to release the device and record again.`});let n=a({recording:{outPath:t.outputPath,gestureEvents:[...t.gestureEvents]}});return!t.showTouches||t.gestureEvents.length===0?{telemetryPath:n}:await E(t,n)}async function E(e,t){let n=v();if(n)return{telemetryPath:t,overlayWarning:n};try{if(await C({videoPath:e.outputPath,telemetryPath:t,exportQuality:e.exportQuality,targetLabel:e.targetLabel}),!await u(e.outputPath))throw Error(`recording post-processing produced an unplayable video`);return{telemetryPath:t}}catch(e){return{telemetryPath:t,overlayWarning:`failed to overlay recording touches: ${e instanceof Error?e.message:String(e)}`}}}export{w as createScreenRecordingFinalizer};
1
+ import{C as e}from"./sdk-contracts.js";import{t}from"./recording-export-quality.js";import{c as n}from"./exec.js";import"./command.js";import{n as r}from"./version.js";import{t as i}from"./screen-recording-runtime.js";import{n as a}from"./telemetry.js";import{a as o,i as s,n as c,o as l,r as u,t as d}from"./video.js";import f from"node:path";import p from"node:fs";import{fileURLToPath as m}from"node:url";function h(e,t,n,r){let i=`apple/runner/AgentDeviceRunner/RecordingScripts/${e}`,a=`dist/${i}`;return[f.resolve(t,e),f.resolve(n,i),f.resolve(t,`../${i}`),f.resolve(t,`../../${i}`),f.resolve(t,`../../../${i}`),f.resolve(n,a),f.resolve(r,i)]}function g(t){let n=h(t,f.dirname(m(import.meta.url)),r(),process.cwd());for(let e of n)if(p.existsSync(e))return e;throw new e(`COMMAND_FAILED`,`Missing recording helper script: ${t}`,{hint:`Ensure apple/runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled under dist/apple/runner in the package.`,scriptName:t,searchedPaths:n})}let _,v;function y(e=process.platform){if(e!==`darwin`)return`touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry`}function b(){return _??=g(`recording-overlay.swift`),_}function x(){return v??=g(`RecordingExportSupport.swift`),v}async function S(t){let{videoPath:r,scriptPath:i,scriptArgs:a,commandDescription:c}=t;await s(r),await u(r);let d=C(r);try{let e=await l({sourcePath:i,extraSourcePaths:[x()]});await n(e,[`--input`,r,`--output`,d,...a],{timeoutMs:12e4,env:o()}),await u(d),p.renameSync(d,r)}catch(t){let n=t instanceof e?t:new e(`COMMAND_FAILED`,String(t),void 0,t instanceof Error?t:void 0);throw new e(`COMMAND_FAILED`,c,{...n.details,videoPath:r,script:i},n)}finally{p.rmSync(d,{force:!0})}}function C(e){let t=f.parse(e),n=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;return f.join(t.dir,`.${t.name}.agent-device-${n}${t.ext||`.mp4`}`)}async function w(e){let{videoPath:n,telemetryPath:r,exportQuality:i=t,targetLabel:a=`recording`}=e;await S({videoPath:n,scriptPath:b(),scriptArgs:[`--events`,r,`--quality`,i],commandDescription:`Failed to add touch overlays to the ${a}`})}function T(){return Object.freeze({sniff:E,complete:D})}async function E(e){if(!await d(e.outputPath))throw k(e.outputPath)}async function D(e){if(await s(e.outputPath),await u(e.outputPath),!await c(e.outputPath))throw k(e.outputPath);let t=a({recording:{outPath:e.outputPath,gestureEvents:[...e.gestureEvents]}});return!e.showTouches||e.gestureEvents.length===0?{telemetryPath:t}:await O(e,t)}async function O(e,t){let n=y();if(n)return{telemetryPath:t,overlayWarning:n};try{if(await w({videoPath:e.outputPath,telemetryPath:t,exportQuality:e.exportQuality,targetLabel:e.targetLabel}),!await c(e.outputPath))throw Error(`recording post-processing produced an unplayable video`);return{telemetryPath:t}}catch(e){return{telemetryPath:t,overlayWarning:`failed to overlay recording touches: ${e instanceof Error?e.message:String(e)}`}}}function k(t){return new e(`COMMAND_FAILED`,`recording was not finalized into a playable video: ${t}`,{reason:i,retriable:!0,hint:`Run record stop again: a recorder that is still finalizing its file is playable on the next stop, and the recording keeps its evidence either way. If the recorder died before writing a video, close this session to release the device and record again.`})}export{T as createScreenRecordingFinalizer};
@@ -1 +1 @@
1
- import e from"node:path";import t from"node:fs";function n(){return Object.freeze({prepare:async n=>{t.mkdirSync(e.dirname(n),{recursive:!0}),t.rmSync(n,{force:!0})}})}export{n as createScreenRecordingOutputHost};
1
+ import e from"node:path";import t from"node:fs";function n(){return Object.freeze({prepare:async n=>{t.mkdirSync(e.dirname(n),{recursive:!0}),t.rmSync(n,{force:!0})},copy:async({from:n,to:r})=>{t.mkdirSync(e.dirname(r),{recursive:!0}),t.copyFileSync(n,r)},remove:async e=>{try{t.rmSync(e,{force:!0})}catch{return`present`}return r(e)?`present`:`removed`}})}function r(e){try{return t.accessSync(e),!0}catch{return!1}}export{n as createScreenRecordingOutputHost};
@@ -1 +1 @@
1
- import{D as e}from"./sdk-contracts.js";import{r as t}from"./diagnostics.js";import{S as n,T as r,b as i,g as a,h as o,o as s,p as c,x as l,y as u}from"./owner-identity.js";import"./diagnostics2.js";import"./process.js";const d=2e3,f=(e,t)=>e===t;async function p(e){if(e===void 0)return;let[t,n]=await Promise.all([Promise.resolve(l(e)),Promise.resolve(u(e))]);return t&&n?Object.freeze({pid:e,startTime:t,command:n}):void 0}async function m(e){let t=await h(e.pid),n=s([e.pid],t),r=(await Promise.all(n.map(async e=>await p(e.pid)))).filter(e=>e!==void 0);return Object.freeze([e,...r.filter(t=>t.pid!==e.pid)])}async function h(n){try{return await a({timeoutMs:5e3})}catch(r){return t({level:`warn`,phase:`screen_recording_process_tree_unreadable`,data:{rootPid:n,reason:e(r)}}),[]}}function g(e,t=f){return!c(e.pid)||o(e.pid)?`missing`:S(e,t)?`owned-alive`:`ownership-lost`}async function _(e,t){if(!c(e.pid))return`gone`;let n=await i(e.pid,5e3);return n.zombie===!0?`gone`:e.startTime.length===0||e.command.length===0?`not-ours`:n.startTime===null||n.command===null?`unprovable`:n.startTime===e.startTime&&t(e.command,n.command)?`ours`:`not-ours`}async function v(e,t,n=f){let r=t?.child.pid,i=async e=>({marker:e,evidence:await _(e,n)}),a=({marker:e,evidence:t})=>t===`ours`||t===`unprovable`&&e.pid===r,o=await Promise.all(e.map(i)),s=o[0],c=new Set(e.map(({pid:e})=>e)),l=s!==void 0&&a(s)?await m(s.marker):[],u=await Promise.all(l.filter(({pid:e})=>!c.has(e)).map(async e=>await i(e))),p=[...o,...u],h=p.filter(a).map(({marker:e})=>e);if(h.length===0)return y(p.map(({evidence:e})=>e));let g=new Set(h.map(({pid:e})=>e)),v=p.filter(({marker:e,evidence:t})=>!g.has(e.pid)&&t!==`gone`);for(let[e,r]of[[`SIGINT`,5e3],[`SIGTERM`,d],[`SIGKILL`,d]])if(b(h,e,t),await x(h,r,t,n))return v.length===0?`terminated`:`ownership-lost`;return`ownership-lost`}function y(e){return e.every(e=>e===`gone`)?`already-missing`:`ownership-lost`}function b(e,t,r){let i=r?.child.pid;n(e.map(({pid:e})=>e).filter(e=>e!==i),t),i!==void 0&&e.some(({pid:e})=>e===i)&&r?.child.kill(t)}async function x(e,t,n,i){let a=n?.child.pid,o=n?await C(n.wait,t):!1;return await Promise.all(e.filter(({pid:e})=>!o||e!==a).map(async({pid:e})=>await r(e,t))),e.every(e=>o&&e.pid===a||g(e,i)===`missing`)}function S(e,t){let n=u(e.pid);return e.startTime.length>0&&e.command.length>0&&l(e.pid)===e.startTime&&n!==null&&t(e.command,n)}async function C(e,t){return await Promise.race([e.then(()=>!0,()=>!0),new Promise(e=>setTimeout(()=>e(!1),t))])}export{v as i,p as n,m as r,g as t};
1
+ import{D as e}from"./sdk-contracts.js";import{r as t}from"./diagnostics.js";import{S as n,b as r,g as i,h as a,o,p as s,w as c,x as l,y as u}from"./owner-identity.js";import"./diagnostics2.js";import"./process.js";const d=2e3,f=(e,t)=>e===t;async function p(e){if(e===void 0)return;let[t,n]=await Promise.all([Promise.resolve(l(e)),Promise.resolve(u(e))]);return t&&n?Object.freeze({pid:e,startTime:t,command:n}):void 0}async function m(e){let t=await h(e.pid),n=o([e.pid],t),r=(await Promise.all(n.map(async e=>await p(e.pid)))).filter(e=>e!==void 0);return Object.freeze([e,...r.filter(t=>t.pid!==e.pid)])}async function h(n){try{return await i({timeoutMs:5e3})}catch(r){return t({level:`warn`,phase:`screen_recording_process_tree_unreadable`,data:{rootPid:n,reason:e(r)}}),[]}}function g(e,t=f){return!s(e.pid)||a(e.pid)?`missing`:S(e,t)?`owned-alive`:`ownership-lost`}async function _(e,t){if(!s(e.pid))return`gone`;let n=await r(e.pid,5e3);return n.zombie===!0?`gone`:e.startTime.length===0||e.command.length===0?`not-ours`:n.startTime===null||n.command===null?`unprovable`:n.startTime===e.startTime&&t(e.command,n.command)?`ours`:`not-ours`}async function v(e,t,n=f){let r=t?.child.pid,i=async e=>({marker:e,evidence:await _(e,n)}),a=({marker:e,evidence:t})=>t===`ours`||t===`unprovable`&&e.pid===r,o=await Promise.all(e.map(i)),s=o[0],c=new Set(e.map(({pid:e})=>e)),l=s!==void 0&&a(s)?await m(s.marker):[],u=await Promise.all(l.filter(({pid:e})=>!c.has(e)).map(async e=>await i(e))),p=[...o,...u],h=p.filter(a).map(({marker:e})=>e);if(h.length===0)return y(p.map(({evidence:e})=>e));let g=new Set(h.map(({pid:e})=>e)),v=p.filter(({marker:e,evidence:t})=>!g.has(e.pid)&&t!==`gone`);for(let[e,r]of[[`SIGINT`,5e3],[`SIGTERM`,d],[`SIGKILL`,d]])if(b(h,e,t),await x(h,r,t,n))return v.length===0?`terminated`:`ownership-lost`;return`ownership-lost`}function y(e){return e.every(e=>e===`gone`)?`already-missing`:`ownership-lost`}function b(e,t,r){let i=r?.child.pid;n(e.map(({pid:e})=>e).filter(e=>e!==i),t),i!==void 0&&e.some(({pid:e})=>e===i)&&r?.child.kill(t)}async function x(e,t,n,r){let i=n?.child.pid,a=n?await C(n.wait,t):!1;return await Promise.all(e.filter(({pid:e})=>!a||e!==i).map(async({pid:e})=>await c(e,t))),e.every(e=>a&&e.pid===i||g(e,r)===`missing`)}function S(e,t){let n=u(e.pid);return e.startTime.length>0&&e.command.length>0&&l(e.pid)===e.startTime&&n!==null&&t(e.command,n)}async function C(e,t){return await Promise.race([e.then(()=>!0,()=>!0),new Promise(e=>setTimeout(()=>e(!1),t))])}export{v as i,p as n,m as r,g as t};
@@ -1 +1 @@
1
- import{T as e,h as t,k as n,p as r,x as i,y as a}from"./owner-identity.js";import o from"node:path";import s from"node:fs";async function c(e,t={}){let n=u(),r=d(t);for(let t of e.read()){if(!l(t))continue;let i=await f(t,r,n);i.length===0?e.clear(t.scope):i.length!==t.records.length&&e.replace(t.scope,i)}return Object.freeze(n)}function l(e){return e.status===`decoded`}function u(){return{inspected:0,inspectedPids:[],terminated:0,terminatedPids:[],missing:0,missingPids:[],ownershipLost:0,ownershipLostPids:[],skippedForOpenWebSession:!1}}function d(e){return{openWebSession:(e.openWebSessionNames??[]).length>0,purposes:e.purposes?new Set(e.purposes):void 0,termTimeoutMs:e.termTimeoutMs??1500,killTimeoutMs:e.killTimeoutMs??1e3}}async function f(e,t,n){let r=[];for(let i of e.records){if(p(e.scope.kind,i,t)){r.push(i),h(e.scope.kind,i,t)&&(n.skippedForOpenWebSession=!0);continue}n.inspected+=1,n.inspectedPids.push(i.pid),g(n,i,await _(i,t),r)}return r}function p(e,t,n){return!m(t,n)||h(e,t,n)}function m(e,t){return t.purposes===void 0||t.purposes.has(e.purpose)}function h(e,t,n){return e===`daemon`&&t.purpose===`managed-web-browser`&&n.openWebSession}function g(e,t,n,r){if(n===`terminated`){e.terminated+=1,e.terminatedPids.push(t.pid);return}if(n===`missing`){e.missing+=1,e.missingPids.push(t.pid);return}e.ownershipLost+=1,e.ownershipLostPids.push(t.pid),r.push(t)}async function _(e,t){let n=v(e);return n===void 0?(C(e.pid,y(e)),await b(e,t)):n}function v(e){return e.pid===process.pid||!r(e.pid)||t(e.pid)?`missing`:S(e)?void 0:`ownership-lost`}function y(e){return e.purpose===`simctl-screen-recording`?`SIGINT`:`SIGTERM`}async function b(e,t){let n=await x(e,t.termTimeoutMs);return n===`exited`?`terminated`:n===`ownership-lost`?`ownership-lost`:(C(e.pid,`SIGKILL`),await x(e,t.killTimeoutMs)===`exited`?`terminated`:`ownership-lost`)}async function x(n,i){return await e(n.pid,i),!r(n.pid)||t(n.pid)?`exited`:S(n)?`owned-alive`:`ownership-lost`}function S(e){return i(e.pid)===e.startTime&&a(e.pid)===e.command}function C(e,t){try{process.kill(e,t)}catch{}}const w=`owned-processes.json`;function T(e){let t=o.resolve(e.stateDir),r=o.resolve(e.sessionsDir),i=o.join(t,w),a=t=>{if(t.kind===`daemon`)return i;let n=o.resolve(e.resolveSessionDir(t.sessionId));if(o.dirname(n)!==r)throw TypeError(`owned process session scope must resolve directly under the sessions dir`);return o.join(n,w)};return Object.freeze({replace(e,t){let r=O(t),i=a(e);if(r.length===0){j(i);return}let c=o.dirname(i);s.mkdirSync(c,{recursive:!0}),n(i,e=>{let t=s.openSync(e,`wx`,384);try{s.writeFileSync(t,`${JSON.stringify({version:1,processes:r})}\n`,`utf8`),s.fsyncSync(t)}finally{s.closeSync(t)}M(i),s.renameSync(e,i)})},clear(e){j(a(e))},read(){return D(r,i)}})}function E(e,t){let n;try{M(e),n=JSON.parse(s.readFileSync(e,`utf8`))}catch(n){return{scope:t,path:e,status:`invalid`,records:[],message:F(n)}}if(!A(n))return{scope:t,path:e,status:`invalid`,records:[],message:`owned process record must contain version 1 and a processes array`};try{return{scope:t,path:e,status:`decoded`,records:O(n.processes)}}catch(n){return{scope:t,path:e,status:`invalid`,records:[],message:F(n)}}}function D(e,t){let n=[];if(N(t)&&n.push(E(t,{kind:`daemon`})),!s.existsSync(e))return n;for(let t of s.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){if(!t.isDirectory())continue;let r=o.join(e,t.name,w);N(r)&&n.push(E(r,{kind:`session`,sessionId:t.name}))}return n}function O(e){let t=new Set,n=[];for(let r of e){if(!k(r))throw TypeError(`owned process record has an invalid identity or purpose`);if(t.has(r.pid))throw TypeError(`duplicate owned process pid ${r.pid}`);t.add(r.pid),n.push(Object.freeze({pid:r.pid,startTime:r.startTime,command:r.command,purpose:r.purpose}))}return n.sort((e,t)=>e.pid-t.pid)}function k(e){return Number.isInteger(e.pid)&&e.pid>0&&typeof e.startTime==`string`&&e.startTime.length>0&&typeof e.command==`string`&&e.command.length>0&&typeof e.purpose==`string`&&e.purpose.length>0}function A(e){return typeof e==`object`&&!!e&&`version`in e&&e.version===1&&`processes`in e&&Array.isArray(e.processes)}function j(e){try{M(e),s.unlinkSync(e)}catch(e){if(!P(e))throw e}}function M(e){try{let t=s.lstatSync(e);if(t.isSymbolicLink())throw Error(`Refusing to follow an owned process record symlink`);if(!t.isFile())throw Error(`Owned process record is not a regular file`)}catch(e){if(!P(e))throw e}}function N(e){try{return s.lstatSync(e).isFile()}catch{return!1}}function P(e){return!!(e&&typeof e==`object`&&`code`in e&&e.code===`ENOENT`)}function F(e){return e instanceof Error?e.message:`owned process record is invalid`}export{c as n,T as t};
1
+ import{O as e,h as t,p as n,w as r,x as i,y as a}from"./owner-identity.js";import"./exec.js";import o from"node:path";import s from"node:fs";async function c(e,t={}){let n=u(),r=d(t);for(let t of e.read()){if(!l(t))continue;let i=await f(t,r,n);i.length===0?e.clear(t.scope):i.length!==t.records.length&&e.replace(t.scope,i)}return Object.freeze(n)}function l(e){return e.status===`decoded`}function u(){return{inspected:0,inspectedPids:[],terminated:0,terminatedPids:[],missing:0,missingPids:[],ownershipLost:0,ownershipLostPids:[],skippedForOpenWebSession:!1}}function d(e){return{openWebSession:(e.openWebSessionNames??[]).length>0,purposes:e.purposes?new Set(e.purposes):void 0,termTimeoutMs:e.termTimeoutMs??1500,killTimeoutMs:e.killTimeoutMs??1e3}}async function f(e,t,n){let r=[];for(let i of e.records){if(p(e.scope.kind,i,t)){r.push(i),h(e.scope.kind,i,t)&&(n.skippedForOpenWebSession=!0);continue}n.inspected+=1,n.inspectedPids.push(i.pid),g(n,i,await _(i,t),r)}return r}function p(e,t,n){return!m(t,n)||h(e,t,n)}function m(e,t){return t.purposes===void 0||t.purposes.has(e.purpose)}function h(e,t,n){return e===`daemon`&&t.purpose===`managed-web-browser`&&n.openWebSession}function g(e,t,n,r){if(n===`terminated`){e.terminated+=1,e.terminatedPids.push(t.pid);return}if(n===`missing`){e.missing+=1,e.missingPids.push(t.pid);return}e.ownershipLost+=1,e.ownershipLostPids.push(t.pid),r.push(t)}async function _(e,t){let n=v(e);return n===void 0?(C(e.pid,y(e)),await b(e,t)):n}function v(e){return e.pid===process.pid||!n(e.pid)||t(e.pid)?`missing`:S(e)?void 0:`ownership-lost`}function y(e){return e.purpose===`simctl-screen-recording`?`SIGINT`:`SIGTERM`}async function b(e,t){let n=await x(e,t.termTimeoutMs);return n===`exited`?`terminated`:n===`ownership-lost`?`ownership-lost`:(C(e.pid,`SIGKILL`),await x(e,t.killTimeoutMs)===`exited`?`terminated`:`ownership-lost`)}async function x(e,i){return await r(e.pid,i),!n(e.pid)||t(e.pid)?`exited`:S(e)?`owned-alive`:`ownership-lost`}function S(e){return i(e.pid)===e.startTime&&a(e.pid)===e.command}function C(e,t){try{process.kill(e,t)}catch{}}const w=`owned-processes.json`;function T(t){let n=o.resolve(t.stateDir),r=o.resolve(t.sessionsDir),i=o.join(n,w),a=e=>{if(e.kind===`daemon`)return i;let n=o.resolve(t.resolveSessionDir(e.sessionId));if(o.dirname(n)!==r)throw TypeError(`owned process session scope must resolve directly under the sessions dir`);return o.join(n,w)};return Object.freeze({replace(t,n){let r=O(n),i=a(t);if(r.length===0){j(i);return}let c=o.dirname(i);s.mkdirSync(c,{recursive:!0}),e(i,e=>{let t=s.openSync(e,`wx`,384);try{s.writeFileSync(t,`${JSON.stringify({version:1,processes:r})}\n`,`utf8`),s.fsyncSync(t)}finally{s.closeSync(t)}M(i),s.renameSync(e,i)})},clear(e){j(a(e))},read(){return D(r,i)}})}function E(e,t){let n;try{M(e),n=JSON.parse(s.readFileSync(e,`utf8`))}catch(n){return{scope:t,path:e,status:`invalid`,records:[],message:F(n)}}if(!A(n))return{scope:t,path:e,status:`invalid`,records:[],message:`owned process record must contain version 1 and a processes array`};try{return{scope:t,path:e,status:`decoded`,records:O(n.processes)}}catch(n){return{scope:t,path:e,status:`invalid`,records:[],message:F(n)}}}function D(e,t){let n=[];if(N(t)&&n.push(E(t,{kind:`daemon`})),!s.existsSync(e))return n;for(let t of s.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){if(!t.isDirectory())continue;let r=o.join(e,t.name,w);N(r)&&n.push(E(r,{kind:`session`,sessionId:t.name}))}return n}function O(e){let t=new Set,n=[];for(let r of e){if(!k(r))throw TypeError(`owned process record has an invalid identity or purpose`);if(t.has(r.pid))throw TypeError(`duplicate owned process pid ${r.pid}`);t.add(r.pid),n.push(Object.freeze({pid:r.pid,startTime:r.startTime,command:r.command,purpose:r.purpose}))}return n.sort((e,t)=>e.pid-t.pid)}function k(e){return Number.isInteger(e.pid)&&e.pid>0&&typeof e.startTime==`string`&&e.startTime.length>0&&typeof e.command==`string`&&e.command.length>0&&typeof e.purpose==`string`&&e.purpose.length>0}function A(e){return typeof e==`object`&&!!e&&`version`in e&&e.version===1&&`processes`in e&&Array.isArray(e.processes)}function j(e){try{M(e),s.unlinkSync(e)}catch(e){if(!P(e))throw e}}function M(e){try{let t=s.lstatSync(e);if(t.isSymbolicLink())throw Error(`Refusing to follow an owned process record symlink`);if(!t.isFile())throw Error(`Owned process record is not a regular file`)}catch(e){if(!P(e))throw e}}function N(e){try{return s.lstatSync(e).isFile()}catch{return!1}}function P(e){return!!(e&&typeof e==`object`&&`code`in e&&e.code===`ENOENT`)}function F(e){return e instanceof Error?e.message:`owned process record is invalid`}export{c as n,T as t};
package/dist/src/proxy.js CHANGED
@@ -1,2 +1,2 @@
1
- import{C as e,M as t}from"./sdk-contracts.js";import{a as n,c as r,d as i,f as a,l as o,m as s,o as c,r as l,s as u,u as d}from"./transport.js";import{i as f,s as p}from"./daemon-client-lifecycle.js";import{r as m}from"./version.js";import{t as h}from"./shared.js";import{n as ee,t as te}from"./color.js";import{randomBytes as ne,randomUUID as g}from"node:crypto";import{Readable as _}from"node:stream";import{pipeline as v}from"node:stream/promises";import y from"node:http";function b(e){let t=S(e);if(!t)return!1;let n=T(t.meta);return C(n)?!1:w(t.source)||w(n?.installSource)}function x(n,r){let i=new e(`INVALID_ARGS`,`Invalid params: an install source of kind "path" names a file on the daemon host and is not accepted through the proxy`,{hint:`Upload the artifact, or use a "url" or "github-actions-artifact" source.`});n.statusCode=400,n.setHeader(`content-type`,`application/json`),n.end(JSON.stringify({jsonrpc:`2.0`,id:r,error:{code:-32602,message:i.message,data:t(i)}}))}function S(e){if(e)try{return T(T(JSON.parse(e))?.params)}catch{return}}function C(e){let t=e?.uploadedArtifactId;return typeof t==`string`&&t.trim().length>0}function w(e){return T(e)?.kind===`path`}function T(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}const E=`${c}/`,D=[`content-type`,`content-range`,`x-artifact-type`,`x-artifact-filename`,`x-artifact-hash`,`x-artifact-hash-algorithm`,o],O=[`content-type`,`content-disposition`,`x-request-id`];function k(e){let t=V(e);return y.createServer((e,n)=>{A(e,n,t).catch(e=>{de(n,e)})})}async function A(e,t,n){let r=W(e.url??`/`);if(e.method===`GET`&&r===`/health`){await j(t,n);return}if(!G(r,e.method)){t.statusCode=404,t.end(`Not found`);return}let i;if(r===`/rpc`&&(i=(await l(e,n.maxRpcBodyBytes,`Proxy request body is too large.`)).toString(`utf8`)),!ae(e,n.clientToken,i)){ue(t,r,Z(i));return}if(b(i)){x(t,Z(i));return}await N({req:e,res:t,route:r,options:n,rpcBody:i})}async function j(e,t){let n=await M(t);e.statusCode=200,e.setHeader(`content-type`,`application/json`),e.end(JSON.stringify(d(`agent-device-proxy`,m(),{upstream:n})))}async function M(e){let t=new URL(s(e.upstreamBaseUrl,`health`)),n=await e.fetchImpl(t,{method:`GET`,headers:X({headers:{}},e.upstreamToken,`/health`),signal:AbortSignal.timeout(e.upstreamTimeoutMs)}),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function N(e){let{req:t,res:n,route:r,options:i,rpcBody:a}=e,o=Y(i.upstreamBaseUrl,r,t.url??`/`),s=t.method??`GET`,c=X(t,i.upstreamToken,r),l=ie(t,r,a,i.upstreamToken);await F({req:t,res:n,route:r,response:await i.fetchImpl(o,{method:s,headers:c,signal:P(t,n,i.upstreamTimeoutMs),...l?{body:l,duplex:`half`}:{}}),clientToken:i.clientToken})}function P(t,n,r){let i=new AbortController,a=()=>{n.writableFinished||i.signal.aborted||i.abort(new e(`COMMAND_FAILED`,`Proxy client disconnected before the upstream response ended`))};return t.on(`aborted`,a),n.on(`close`,a),AbortSignal.any([i.signal,AbortSignal.timeout(r)])}async function F(e){let{req:t,res:n,route:r,response:i,clientToken:a}=e;if(n.statusCode=i.status,I(i,n),L(t,n),J(r)){await R({req:t,res:n,response:i,clientToken:a});return}await B(i,n)}function I(e,t){for(let n of O){let r=e.headers.get(n);r&&t.setHeader(n,r)}}function L(e,t){t.hasHeader(`x-request-id`)||t.setHeader(`x-request-id`,le(e))}async function R(e){let{req:t,res:n,response:r,clientToken:i}=e,a=await r.text();n.setHeader(`content-type`,r.headers.get(`content-type`)??`application/json`),n.end(z(a,t,i))}function z(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}if(!r||typeof r!=`object`)return e;let a=r;if(!a.upload||typeof a.upload.url!=`string`)return e;let o=re(a.upload.url,t);if(!o)return e;let s=a.upload.headers&&typeof a.upload.headers==`object`?{...a.upload.headers}:{};return Object.assign(s,i(n)),JSON.stringify({...r,upload:{...a.upload,url:o,headers:s}})}function re(e,t){let n;try{n=new URL(e)}catch{return null}if(!n.pathname.startsWith(`/upload/`))return null;let r=typeof t.headers.host==`string`?t.headers.host:``;if(!r)return null;let i=new URL(t.url??`/`,`http://127.0.0.1`).pathname,a=i.lastIndexOf(`/upload/preflight`),o=a>=0?i.slice(0,a):``,s=t.headers[`x-forwarded-proto`],c=Array.isArray(s)?s[0]:s,l=new URL(`${c||`http`}://${r}`);return l.pathname=`${o}${n.pathname}`,l.search=n.search,l.toString()}async function B(e,t){if(!e.body){t.end();return}await v(_.fromWeb(e.body),t)}function V(e){return{upstreamBaseUrl:H(e.upstreamBaseUrl,`upstreamBaseUrl`),upstreamToken:U(e.upstreamToken,`upstreamToken`),clientToken:U(e.clientToken,`clientToken`),maxRpcBodyBytes:e.maxRpcBodyBytes??1048576,upstreamTimeoutMs:e.upstreamTimeoutMs??3e5,fetchImpl:e.fetchImpl??fetch}}function H(t,n){try{let e=new URL(t);if(e.protocol!==`http:`&&e.protocol!==`https:`)throw Error(`unsupported protocol`);return e.toString().replace(/\/+$/,``)}catch(r){throw new e(`INVALID_ARGS`,`Invalid ${n}`,{[n]:t},r)}}function U(t,n){let r=t.trim();if(!r)throw new e(`INVALID_ARGS`,`Proxy ${n} is required.`);return r}function W(e){let t=new URL(e,`http://127.0.0.1`).pathname;return t===`/agent-device`?`/`:t.startsWith(E)?`/${t.slice(E.length)}`:t}function G(e,t){return e===`/rpc`?t===`POST`:q(e,t)?!0:e===`/artifacts`||e===`/artifacts/`||e.startsWith(`/artifacts/`)||K(e)?t===`GET`:!1}function K(e){let t=e.split(`/`);return t.length===6&&t[1]===`sessions`&&t[3]===`requests`&&t[5]===`diagnostics`&&t[2]!==``&&t[4]!==``}function q(e,t){return e===`/upload`||J(e)||e===`/upload/finalize`?t===`POST`:e.startsWith(`/upload/direct/`)?t===`PUT`:!1}function J(e){return e===`/upload/preflight`}function Y(e,t,n){let r=new URL(s(e,t)),i=n.indexOf(`?`);return i>=0&&(r.search=n.slice(i)),r}function X(e,t,n){let a=new Headers;for(let t of D){let n=e.headers[t];typeof n==`string`&&n.trim()&&a.set(t,n)}n===`/rpc`&&!a.has(`content-type`)&&a.set(`content-type`,`application/json`),n===`/rpc`&&a.set(u,r);for(let[e,n]of Object.entries(i(t)))a.set(e,n);return a}function ie(e,t,n,r){if(e.method!==`GET`&&e.method!==`HEAD`)return t===`/rpc`?se(n??``,r):e}function ae(e,t,r){let i=oe(e,r);return i.length>0&&n(i,t)}function oe(e,t){let n=typeof e.headers.authorization==`string`?e.headers.authorization:``;if(n.toLowerCase().startsWith(`bearer `))return n.slice(7);let r=e.headers[`x-agent-device-token`];if(typeof r==`string`)return r;if(t){let e=ce(t);if(e)return e}return``}function se(e,t){let n=JSON.parse(e);return n.params={...n.params??{},token:t},JSON.stringify(n)}function ce(e){try{let t=JSON.parse(e);return typeof t.params?.token==`string`?t.params.token:``}catch{return``}}function Z(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}function le(e){let t=e.headers[`x-request-id`];return typeof t==`string`&&t.trim()?t.trim().slice(0,128):g()}function ue(n,r,i){if(n.statusCode=401,n.setHeader(`content-type`,`application/json`),r===`/rpc`){n.end(JSON.stringify({jsonrpc:`2.0`,id:i,error:{code:-32001,message:`Invalid proxy token`,data:t(new e(`UNAUTHORIZED`,`Invalid proxy token`))}}));return}n.end(JSON.stringify({ok:!1,error:`Invalid proxy token`,code:`UNAUTHORIZED`}))}function de(e,n){if(e.destroyed)return;if(e.headersSent){e.destroy(n instanceof Error?n:void 0);return}let r=t(n);e.statusCode=r.code===`INVALID_ARGS`?400:500,e.setHeader(`content-type`,`application/json`),e.end(JSON.stringify({ok:!1,error:r.message,code:r.code}))}const fe=async({positionals:t,flags:n})=>{if(t.length>0)throw new e(`INVALID_ARGS`,`proxy does not accept positional arguments.`);let r=await pe(n);return await h(n,r,()=>_e(r)),await ve(),!0};async function pe(t){let n=p({session:`default`,command:`proxy`,positionals:[],flags:{stateDir:t.stateDir,daemonBaseUrl:``,daemonTransport:`http`,daemonServerMode:`http`}}),r=await f(n),i=me(r.info.httpPort),o=Q(t),s=k({upstreamBaseUrl:i,upstreamToken:r.info.token,clientToken:o});await he(s,t.proxyHost?.trim()||`127.0.0.1`,t.proxyPort??0);let c=s.address();if(!c||typeof c==`string`)throw new e(`COMMAND_FAILED`,`Proxy did not bind to a TCP address.`);let l=`http://${ge(c.address)}:${c.port}`;return{proxyBaseUrl:l,agentDeviceBaseUrl:a(l),token:o,upstreamBaseUrl:i,stateDir:n.paths.baseDir}}function me(t){if(!t)throw new e(`COMMAND_FAILED`,`Local daemon HTTP endpoint is unavailable.`,{hint:`Retry after cleaning daemon state, or run proxy with a fresh --state-dir.`});return`http://127.0.0.1:${t}`}function Q(e){return e.daemonAuthToken?.trim()||ne(32).toString(`hex`)}function he(e,t,n){return new Promise((r,i)=>{e.once(`error`,i),e.listen(n,t,()=>{e.off(`error`,i),r()})})}function ge(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function _e(e,t={}){let n=t.useColor??ee(),r=$(`✓`,`green`,n),i=$(e.proxyBaseUrl,`cyan`,n),a=$(`<tunnel URL>`,`cyan`,n),o=$(e.token,`yellow`,n);return[`${r} Proxy listening at ${i}`,``,`Provide this to the agent-device instance connecting:`,``,`Daemon base URL: ${a}`,`Daemon auth token: ${o}`].join(`
1
+ import{C as e,N as t}from"./sdk-contracts.js";import{a as n,c as r,d as i,f as a,l as o,m as s,o as c,r as l,s as u,u as d}from"./transport.js";import{i as f,s as p}from"./daemon-client-lifecycle.js";import{r as m}from"./version.js";import{t as h}from"./shared.js";import{n as ee,t as te}from"./color.js";import{randomBytes as ne,randomUUID as g}from"node:crypto";import{Readable as _}from"node:stream";import{pipeline as v}from"node:stream/promises";import y from"node:http";function b(e){let t=S(e);if(!t)return!1;let n=T(t.meta);return C(n)?!1:w(t.source)||w(n?.installSource)}function x(n,r){let i=new e(`INVALID_ARGS`,`Invalid params: an install source of kind "path" names a file on the daemon host and is not accepted through the proxy`,{hint:`Upload the artifact, or use a "url" or "github-actions-artifact" source.`});n.statusCode=400,n.setHeader(`content-type`,`application/json`),n.end(JSON.stringify({jsonrpc:`2.0`,id:r,error:{code:-32602,message:i.message,data:t(i)}}))}function S(e){if(e)try{return T(T(JSON.parse(e))?.params)}catch{return}}function C(e){let t=e?.uploadedArtifactId;return typeof t==`string`&&t.trim().length>0}function w(e){return T(e)?.kind===`path`}function T(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}const E=`${c}/`,D=[`content-type`,`content-range`,`x-artifact-type`,`x-artifact-filename`,`x-artifact-hash`,`x-artifact-hash-algorithm`,o],O=[`content-type`,`content-disposition`,`x-request-id`];function k(e){let t=V(e);return y.createServer((e,n)=>{A(e,n,t).catch(e=>{de(n,e)})})}async function A(e,t,n){let r=W(e.url??`/`);if(e.method===`GET`&&r===`/health`){await j(t,n);return}if(!G(r,e.method)){t.statusCode=404,t.end(`Not found`);return}let i;if(r===`/rpc`&&(i=(await l(e,n.maxRpcBodyBytes,`Proxy request body is too large.`)).toString(`utf8`)),!ae(e,n.clientToken,i)){ue(t,r,Z(i));return}if(b(i)){x(t,Z(i));return}await N({req:e,res:t,route:r,options:n,rpcBody:i})}async function j(e,t){let n=await M(t);e.statusCode=200,e.setHeader(`content-type`,`application/json`),e.end(JSON.stringify(d(`agent-device-proxy`,m(),{upstream:n})))}async function M(e){let t=new URL(s(e.upstreamBaseUrl,`health`)),n=await e.fetchImpl(t,{method:`GET`,headers:X({headers:{}},e.upstreamToken,`/health`),signal:AbortSignal.timeout(e.upstreamTimeoutMs)}),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function N(e){let{req:t,res:n,route:r,options:i,rpcBody:a}=e,o=Y(i.upstreamBaseUrl,r,t.url??`/`),s=t.method??`GET`,c=X(t,i.upstreamToken,r),l=ie(t,r,a,i.upstreamToken);await F({req:t,res:n,route:r,response:await i.fetchImpl(o,{method:s,headers:c,signal:P(t,n,i.upstreamTimeoutMs),...l?{body:l,duplex:`half`}:{}}),clientToken:i.clientToken})}function P(t,n,r){let i=new AbortController,a=()=>{n.writableFinished||i.signal.aborted||i.abort(new e(`COMMAND_FAILED`,`Proxy client disconnected before the upstream response ended`))};return t.on(`aborted`,a),n.on(`close`,a),AbortSignal.any([i.signal,AbortSignal.timeout(r)])}async function F(e){let{req:t,res:n,route:r,response:i,clientToken:a}=e;if(n.statusCode=i.status,I(i,n),L(t,n),J(r)){await R({req:t,res:n,response:i,clientToken:a});return}await B(i,n)}function I(e,t){for(let n of O){let r=e.headers.get(n);r&&t.setHeader(n,r)}}function L(e,t){t.hasHeader(`x-request-id`)||t.setHeader(`x-request-id`,le(e))}async function R(e){let{req:t,res:n,response:r,clientToken:i}=e,a=await r.text();n.setHeader(`content-type`,r.headers.get(`content-type`)??`application/json`),n.end(z(a,t,i))}function z(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}if(!r||typeof r!=`object`)return e;let a=r;if(!a.upload||typeof a.upload.url!=`string`)return e;let o=re(a.upload.url,t);if(!o)return e;let s=a.upload.headers&&typeof a.upload.headers==`object`?{...a.upload.headers}:{};return Object.assign(s,i(n)),JSON.stringify({...r,upload:{...a.upload,url:o,headers:s}})}function re(e,t){let n;try{n=new URL(e)}catch{return null}if(!n.pathname.startsWith(`/upload/`))return null;let r=typeof t.headers.host==`string`?t.headers.host:``;if(!r)return null;let i=new URL(t.url??`/`,`http://127.0.0.1`).pathname,a=i.lastIndexOf(`/upload/preflight`),o=a>=0?i.slice(0,a):``,s=t.headers[`x-forwarded-proto`],c=Array.isArray(s)?s[0]:s,l=new URL(`${c||`http`}://${r}`);return l.pathname=`${o}${n.pathname}`,l.search=n.search,l.toString()}async function B(e,t){if(!e.body){t.end();return}await v(_.fromWeb(e.body),t)}function V(e){return{upstreamBaseUrl:H(e.upstreamBaseUrl,`upstreamBaseUrl`),upstreamToken:U(e.upstreamToken,`upstreamToken`),clientToken:U(e.clientToken,`clientToken`),maxRpcBodyBytes:e.maxRpcBodyBytes??1048576,upstreamTimeoutMs:e.upstreamTimeoutMs??3e5,fetchImpl:e.fetchImpl??fetch}}function H(t,n){try{let e=new URL(t);if(e.protocol!==`http:`&&e.protocol!==`https:`)throw Error(`unsupported protocol`);return e.toString().replace(/\/+$/,``)}catch(r){throw new e(`INVALID_ARGS`,`Invalid ${n}`,{[n]:t},r)}}function U(t,n){let r=t.trim();if(!r)throw new e(`INVALID_ARGS`,`Proxy ${n} is required.`);return r}function W(e){let t=new URL(e,`http://127.0.0.1`).pathname;return t===`/agent-device`?`/`:t.startsWith(E)?`/${t.slice(E.length)}`:t}function G(e,t){return e===`/rpc`?t===`POST`:q(e,t)?!0:e===`/artifacts`||e===`/artifacts/`||e.startsWith(`/artifacts/`)||K(e)?t===`GET`:!1}function K(e){let t=e.split(`/`);return t.length===6&&t[1]===`sessions`&&t[3]===`requests`&&t[5]===`diagnostics`&&t[2]!==``&&t[4]!==``}function q(e,t){return e===`/upload`||J(e)||e===`/upload/finalize`?t===`POST`:e.startsWith(`/upload/direct/`)?t===`PUT`:!1}function J(e){return e===`/upload/preflight`}function Y(e,t,n){let r=new URL(s(e,t)),i=n.indexOf(`?`);return i>=0&&(r.search=n.slice(i)),r}function X(e,t,n){let a=new Headers;for(let t of D){let n=e.headers[t];typeof n==`string`&&n.trim()&&a.set(t,n)}n===`/rpc`&&!a.has(`content-type`)&&a.set(`content-type`,`application/json`),n===`/rpc`&&a.set(u,r);for(let[e,n]of Object.entries(i(t)))a.set(e,n);return a}function ie(e,t,n,r){if(e.method!==`GET`&&e.method!==`HEAD`)return t===`/rpc`?se(n??``,r):e}function ae(e,t,r){let i=oe(e,r);return i.length>0&&n(i,t)}function oe(e,t){let n=typeof e.headers.authorization==`string`?e.headers.authorization:``;if(n.toLowerCase().startsWith(`bearer `))return n.slice(7);let r=e.headers[`x-agent-device-token`];if(typeof r==`string`)return r;if(t){let e=ce(t);if(e)return e}return``}function se(e,t){let n=JSON.parse(e);return n.params={...n.params??{},token:t},JSON.stringify(n)}function ce(e){try{let t=JSON.parse(e);return typeof t.params?.token==`string`?t.params.token:``}catch{return``}}function Z(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}function le(e){let t=e.headers[`x-request-id`];return typeof t==`string`&&t.trim()?t.trim().slice(0,128):g()}function ue(n,r,i){if(n.statusCode=401,n.setHeader(`content-type`,`application/json`),r===`/rpc`){n.end(JSON.stringify({jsonrpc:`2.0`,id:i,error:{code:-32001,message:`Invalid proxy token`,data:t(new e(`UNAUTHORIZED`,`Invalid proxy token`))}}));return}n.end(JSON.stringify({ok:!1,error:`Invalid proxy token`,code:`UNAUTHORIZED`}))}function de(e,n){if(e.destroyed)return;if(e.headersSent){e.destroy(n instanceof Error?n:void 0);return}let r=t(n);e.statusCode=r.code===`INVALID_ARGS`?400:500,e.setHeader(`content-type`,`application/json`),e.end(JSON.stringify({ok:!1,error:r.message,code:r.code}))}const fe=async({positionals:t,flags:n})=>{if(t.length>0)throw new e(`INVALID_ARGS`,`proxy does not accept positional arguments.`);let r=await pe(n);return await h(n,r,()=>_e(r)),await ve(),!0};async function pe(t){let n=p({session:`default`,command:`proxy`,positionals:[],flags:{stateDir:t.stateDir,daemonBaseUrl:``,daemonTransport:`http`,daemonServerMode:`http`}}),r=await f(n),i=me(r.info.httpPort),o=Q(t),s=k({upstreamBaseUrl:i,upstreamToken:r.info.token,clientToken:o});await he(s,t.proxyHost?.trim()||`127.0.0.1`,t.proxyPort??0);let c=s.address();if(!c||typeof c==`string`)throw new e(`COMMAND_FAILED`,`Proxy did not bind to a TCP address.`);let l=`http://${ge(c.address)}:${c.port}`;return{proxyBaseUrl:l,agentDeviceBaseUrl:a(l),token:o,upstreamBaseUrl:i,stateDir:n.paths.baseDir}}function me(t){if(!t)throw new e(`COMMAND_FAILED`,`Local daemon HTTP endpoint is unavailable.`,{hint:`Retry after cleaning daemon state, or run proxy with a fresh --state-dir.`});return`http://127.0.0.1:${t}`}function Q(e){return e.daemonAuthToken?.trim()||ne(32).toString(`hex`)}function he(e,t,n){return new Promise((r,i)=>{e.once(`error`,i),e.listen(n,t,()=>{e.off(`error`,i),r()})})}function ge(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function _e(e,t={}){let n=t.useColor??ee(),r=$(`✓`,`green`,n),i=$(e.proxyBaseUrl,`cyan`,n),a=$(`<tunnel URL>`,`cyan`,n),o=$(e.token,`yellow`,n);return[`${r} Proxy listening at ${i}`,``,`Provide this to the agent-device instance connecting:`,``,`Daemon base URL: ${a}`,`Daemon auth token: ${o}`].join(`
2
2
  `)}function $(e,t,n){return n?te(e,t,{validateStream:!1}):e}function ve(){return new Promise(()=>{})}export{fe as proxyCommand};
@@ -1 +1 @@
1
- import{C as e,R as t}from"./sdk-contracts.js";import{i as n}from"./capture.js";import{n as r}from"./snapshot-quality-backend-capabilities.js";import{r as i}from"./diagnostics.js";import"./diagnostics2.js";import{n as a,t as o}from"./png.js";import{n as s,r as c,t as l}from"./png-worker-contract.js";import u from"node:path";import d,{promises as f}from"node:fs";import{fileURLToPath as p}from"node:url";import{Worker as m}from"node:worker_threads";const h=new Set([`healthy`,`recovered`,`sparse`]),g=new Set(Object.keys(r)),_=new Set([`ax-rejected`,`sparse-tree`,`budget`,`no-nodes`,`capture-failed`,`presentation-failed`,`deferred`,`requested-backend`]);function v(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.state!=`string`||!h.has(t.state)||typeof t.backend!=`string`||!g.has(t.backend))return;let n=y(t.timing);return{state:t.state,backend:t.backend,reason:typeof t.reason==`string`?t.reason:void 0,reasonCode:typeof t.reasonCode==`string`&&_.has(t.reasonCode)?t.reasonCode:void 0,customActions:b(t.customActions),effectiveDepth:typeof t.effectiveDepth==`number`?t.effectiveDepth:void 0,collapsedLeafIndexes:Array.isArray(t.collapsedLeafIndexes)?t.collapsedLeafIndexes.filter(e=>typeof e==`number`):void 0,...n?{timing:n}:{}}}function y(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.acquisitionMs==`number`&&typeof t.presentationMs==`number`)return{acquisitionMs:t.acquisitionMs,presentationMs:t.presentationMs}}function b(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.read==`number`&&typeof t.candidates==`number`)return{read:t.read,candidates:t.candidates,truncated:typeof t.truncated==`number`?t.truncated:0,blocked:t.blocked===!0}}function x(e){return e?.state===`sparse`}function S(e){return e?.backend===`private-ax`?`private-ax`:void 0}function C(e,t){try{let n=p(e),r=u.extname(n)||`.js`;return[u.join(u.dirname(n),`${t}${r}`),u.join(u.dirname(n),`internal`,`${t}${r}`)].find(e=>d.existsSync(e))??null}catch{return null}}var w=class extends Error{};let T=null,E=!1,D=!1,O=0;const k=new Map;function A(e){E=!0,!D&&(D=!0,i({level:`warn`,phase:`png_worker_unavailable`,data:{reason:e}}),process.emitWarning(`PNG worker unavailable, falling back to in-process PNG processing: ${e}`))}function j(n){let r=k.get(n.id);r&&(k.delete(n.id),P(),n.ok?r.resolve(n.result):r.reject(new e(t(n.error.code),n.error.message,n.error.details)))}function M(e,t){T===e&&(A(t.message),T=null,e.terminate().catch(()=>{}),N(new w(`PNG worker failed: ${t.message}`)))}function N(e){let t=[...k.values()];k.clear();for(let n of t)n.reject(e)}function P(){T&&(k.size>0?T.ref():T.unref())}function F(){if(E)return null;if(T)return T;let e=C(import.meta.url,`png-worker`);if(!e)return A(`worker entry module not found next to the current module`),null;try{let t=new m(e,{execArgv:e.endsWith(`.ts`)?[`--experimental-strip-types`]:[]});return t.on(`message`,j),t.on(`error`,e=>{M(t,e)}),t.on(`exit`,e=>{M(t,Error(`PNG worker exited with code ${e}`))}),t.unref(),T=t,t}catch(e){return A(`failed to spawn worker: ${e instanceof Error?e.message:String(e)}`),null}}function I(e){let t=F();if(!t)return Promise.reject(new w(`PNG worker is unavailable`));O+=1;let n=O;return new Promise((r,i)=>{k.set(n,{resolve:r,reject:i}),P();try{t.postMessage({...e,id:n})}catch(e){k.delete(n),P(),i(new w(`failed to post job to PNG worker: ${e instanceof Error?e.message:String(e)}`))}})}async function L(e,t){try{return await I(e)}catch(e){if(e instanceof w)return await t();throw e}}function R(){F()}async function z(){let e=T;T=null,N(new w(`PNG worker terminated`)),e&&await e.terminate()}async function B(e,t){let n=await L({kind:`decode`,png:e,label:t},()=>{let n=o(e,t);return{kind:`decode`,width:n.width,height:n.height,data:n.data}}),r=new a.PNG({width:n.width,height:n.height});return r.data=l(n.data),r}async function V(e){let t=await L({kind:`encode`,width:e.width,height:e.height,data:e.data},()=>({kind:`encode`,png:a.PNG.sync.write(e)}));return l(t.png)}async function H(e,t,n){let r=await L({kind:`crop`,png:e,label:n,box:t},async()=>{let{cropPngBytes:r}=await import(`./png-crop-bytes.js`).then(e=>e.n);return{kind:`crop`,png:r(e,t,n)}});return r.png===null?null:l(r.png)}async function U(e,t,n){let{kind:r,...i}=await L({kind:`rgb-difference`,firstPng:e,secondPng:t,label:n},()=>({kind:`rgb-difference`,...s(o(e,n),o(t,n))}));return i}async function W(e){let{kind:t,...n}=await L({kind:`diff-pixels`,...e},()=>({kind:`diff-pixels`,...c(e)}));return{...n,diffData:l(n.diffData)}}async function G(t,r){let{min:i,max:a}=n;if(!Number.isFinite(r)||r<i||r>a)throw new e(`INVALID_ARGS`,`Screenshot scale must be between ${i} and ${a}`);if(r===1)return;let o=await B(await f.readFile(t),`screenshot`),s=Math.max(1,Math.round(o.width*r)),c=Math.max(1,Math.round(o.height*r));await f.writeFile(t,await V(q(o,s,c)))}async function K(t,n,r){if(!Number.isInteger(n)||n<1||!Number.isInteger(r)||r<1)throw new e(`INVALID_ARGS`,`Screenshot resize dimensions must be positive integers`);let i=await B(await f.readFile(t),`screenshot`);(i.width!==n||i.height!==r)&&await f.writeFile(t,await V(q(i,n,r)))}function q(e,t,n){let r=new a.PNG({width:t,height:n});for(let i=0;i<n;i+=1){let a=i*e.height/n,o=(i+1)*e.height/n;for(let n=0;n<t;n+=1){let s=n*e.width/t,c=(n+1)*e.width/t,l=0,u=0,d=0,f=0,p=0;for(let t=Math.floor(a);t<Math.ceil(o);t+=1){let n=Math.min(t+1,o)-Math.max(t,a);for(let r=Math.floor(s);r<Math.ceil(c);r+=1){let i=n*(Math.min(r+1,c)-Math.max(r,s)),a=(t*e.width+r)*4;l+=(e.data[a]??0)*i,u+=(e.data[a+1]??0)*i,d+=(e.data[a+2]??0)*i,f+=(e.data[a+3]??0)*i,p+=i}}let m=(i*r.width+n)*4;r.data[m]=Math.round(l/p),r.data[m+1]=Math.round(u/p),r.data[m+2]=Math.round(d/p),r.data[m+3]=Math.round(f/p)}}return r}function J(e,t){return[...Q(e),...Y(e),...ee(e),...te(e,t)]}function Y(e){let t=e.customActions;if(!t)return[];let n=[];return t.blocked?n.push(`Custom actions were not read: an earlier accessibility read is still hung, so this capture skipped the read pass instead of queueing behind it. No element’s actions list is authoritative here. Reads resume once that call returns.`):t.read<t.candidates&&n.push(`Custom actions were read for ${t.read} of ${t.candidates} merged elements, on-screen ones first; the remaining ${t.candidates-t.read} were not read, so an absent actions list on those is not evidence that they have none. Scroll them into view and re-run to read them.`),t.truncated>0&&n.push(`${t.truncated} element(s) published more custom actions than are shown; those lists are clipped to the first 8 names, and long names are shortened.`),n}function X(e){return e===!0?[`This capture was cut at a backend limit, so elements later in the tree — footers, tab bars, items after a long list — may be missing even when they are on screen; their refs and selectors cannot be resolved from this snapshot. Navigate or scroll so fewer elements render and re-run, and use screenshot as visual truth for what is missing.`]:[]}function Z(e){return`Detected an overly complex or slow accessibility tree. Fell back to the ${e} snapshot backend. It is OK to continue; use --json to inspect snapshotQuality.reason if you need recovery details.`}function Q(e){return e.state===`recovered`?e.reasonCode===`deferred`||e.reasonCode===`requested-backend`?[]:e.reasonCode===`presentation-failed`?[`Agent Device could not safely present the captured accessibility tree and fell back to the ${e.backend} snapshot backend. This is an Agent Device runner bug, not an app accessibility-tree issue. Use screenshot as visual truth and report snapshotQuality.reason with the screenshot.`]:[Z(e.backend)]:e.state===`sparse`?[`No snapshot backend could read this screen`+(e.reason?` (${e.reason})`:``)+`. Its refs and selectors are invalid. Use screenshot as visual truth and coordinate taps; retry snapshot after navigating.`,...$(e)]:[]}function $(e){return e.reasonCode===`sparse-tree`?[`This screen publishes no accessibility content at all; assistive technologies see the same empty tree, so it is worth flagging as an app accessibility bug rather than only an automation limitation.`]:[]}function ee(e){return e.effectiveDepth===void 0?[]:[`Some deeper accessibility nodes were omitted; the accessibility backend capped this tree at depth ${e.effectiveDepth}. Navigate so the content you need sits higher in the tree, and use screenshot as visual truth for the rest.`]}function te(e,t){let n=[];for(let r of e.collapsedLeafIndexes??[]){let e=t.find(e=>e.index===r);if(!e)continue;let i=e.identifier?` (${e.identifier})`:``;n.push(`@${e.ref} [${e.type??`element`}]${i} merges many labels into a single accessibility element. The app likely marks a container as accessible, which hides every descendant from assistive tech and automation — the children cannot be addressed individually. Fix the app's accessibility (mark the rows, not the container); until then use screenshot as visual truth and coordinate taps.`)}return n}export{G as a,H as c,R as d,z as f,v as h,K as i,B as l,S as m,J as n,U as o,x as p,X as r,W as s,Z as t,V as u};
1
+ import{C as e,z as t}from"./sdk-contracts.js";import{i as n}from"./capture.js";import{n as r}from"./snapshot-quality-backend-capabilities.js";import{r as i}from"./diagnostics.js";import"./diagnostics2.js";import{n as a,t as o}from"./png.js";import{n as s,r as c,t as l}from"./png-worker-contract.js";import u from"node:path";import d,{promises as f}from"node:fs";import{fileURLToPath as p}from"node:url";import{Worker as m}from"node:worker_threads";const h=new Set([`healthy`,`recovered`,`sparse`]),g=new Set(Object.keys(r)),_=new Set([`ax-rejected`,`sparse-tree`,`budget`,`no-nodes`,`capture-failed`,`presentation-failed`,`deferred`,`requested-backend`]);function v(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.state!=`string`||!h.has(t.state)||typeof t.backend!=`string`||!g.has(t.backend))return;let n=y(t.timing);return{state:t.state,backend:t.backend,reason:typeof t.reason==`string`?t.reason:void 0,reasonCode:typeof t.reasonCode==`string`&&_.has(t.reasonCode)?t.reasonCode:void 0,customActions:b(t.customActions),effectiveDepth:typeof t.effectiveDepth==`number`?t.effectiveDepth:void 0,collapsedLeafIndexes:Array.isArray(t.collapsedLeafIndexes)?t.collapsedLeafIndexes.filter(e=>typeof e==`number`):void 0,...n?{timing:n}:{}}}function y(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.acquisitionMs==`number`&&typeof t.presentationMs==`number`)return{acquisitionMs:t.acquisitionMs,presentationMs:t.presentationMs}}function b(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.read==`number`&&typeof t.candidates==`number`)return{read:t.read,candidates:t.candidates,truncated:typeof t.truncated==`number`?t.truncated:0,blocked:t.blocked===!0}}function x(e){return e?.state===`sparse`}function S(e){return e?.backend===`private-ax`?`private-ax`:void 0}function C(e,t){try{let n=p(e),r=u.extname(n)||`.js`;return[u.join(u.dirname(n),`${t}${r}`),u.join(u.dirname(n),`internal`,`${t}${r}`)].find(e=>d.existsSync(e))??null}catch{return null}}var w=class extends Error{};let T=null,E=!1,D=!1,O=0;const k=new Map;function A(e){E=!0,!D&&(D=!0,i({level:`warn`,phase:`png_worker_unavailable`,data:{reason:e}}),process.emitWarning(`PNG worker unavailable, falling back to in-process PNG processing: ${e}`))}function j(n){let r=k.get(n.id);r&&(k.delete(n.id),P(),n.ok?r.resolve(n.result):r.reject(new e(t(n.error.code),n.error.message,n.error.details)))}function M(e,t){T===e&&(A(t.message),T=null,e.terminate().catch(()=>{}),N(new w(`PNG worker failed: ${t.message}`)))}function N(e){let t=[...k.values()];k.clear();for(let n of t)n.reject(e)}function P(){T&&(k.size>0?T.ref():T.unref())}function F(){if(E)return null;if(T)return T;let e=C(import.meta.url,`png-worker`);if(!e)return A(`worker entry module not found next to the current module`),null;try{let t=new m(e,{execArgv:e.endsWith(`.ts`)?[`--experimental-strip-types`]:[]});return t.on(`message`,j),t.on(`error`,e=>{M(t,e)}),t.on(`exit`,e=>{M(t,Error(`PNG worker exited with code ${e}`))}),t.unref(),T=t,t}catch(e){return A(`failed to spawn worker: ${e instanceof Error?e.message:String(e)}`),null}}function I(e){let t=F();if(!t)return Promise.reject(new w(`PNG worker is unavailable`));O+=1;let n=O;return new Promise((r,i)=>{k.set(n,{resolve:r,reject:i}),P();try{t.postMessage({...e,id:n})}catch(e){k.delete(n),P(),i(new w(`failed to post job to PNG worker: ${e instanceof Error?e.message:String(e)}`))}})}async function L(e,t){try{return await I(e)}catch(e){if(e instanceof w)return await t();throw e}}function R(){F()}async function z(){let e=T;T=null,N(new w(`PNG worker terminated`)),e&&await e.terminate()}async function B(e,t){let n=await L({kind:`decode`,png:e,label:t},()=>{let n=o(e,t);return{kind:`decode`,width:n.width,height:n.height,data:n.data}}),r=new a.PNG({width:n.width,height:n.height});return r.data=l(n.data),r}async function V(e){let t=await L({kind:`encode`,width:e.width,height:e.height,data:e.data},()=>({kind:`encode`,png:a.PNG.sync.write(e)}));return l(t.png)}async function H(e,t,n){let r=await L({kind:`crop`,png:e,label:n,box:t},async()=>{let{cropPngBytes:r}=await import(`./png-crop-bytes.js`).then(e=>e.n);return{kind:`crop`,png:r(e,t,n)}});return r.png===null?null:l(r.png)}async function U(e,t,n){let{kind:r,...i}=await L({kind:`rgb-difference`,firstPng:e,secondPng:t,label:n},()=>({kind:`rgb-difference`,...s(o(e,n),o(t,n))}));return i}async function W(e){let{kind:t,...n}=await L({kind:`diff-pixels`,...e},()=>({kind:`diff-pixels`,...c(e)}));return{...n,diffData:l(n.diffData)}}async function G(t,r){let{min:i,max:a}=n;if(!Number.isFinite(r)||r<i||r>a)throw new e(`INVALID_ARGS`,`Screenshot scale must be between ${i} and ${a}`);if(r===1)return;let o=await B(await f.readFile(t),`screenshot`),s=Math.max(1,Math.round(o.width*r)),c=Math.max(1,Math.round(o.height*r));await f.writeFile(t,await V(q(o,s,c)))}async function K(t,n,r){if(!Number.isInteger(n)||n<1||!Number.isInteger(r)||r<1)throw new e(`INVALID_ARGS`,`Screenshot resize dimensions must be positive integers`);let i=await B(await f.readFile(t),`screenshot`);(i.width!==n||i.height!==r)&&await f.writeFile(t,await V(q(i,n,r)))}function q(e,t,n){let r=new a.PNG({width:t,height:n});for(let i=0;i<n;i+=1){let a=i*e.height/n,o=(i+1)*e.height/n;for(let n=0;n<t;n+=1){let s=n*e.width/t,c=(n+1)*e.width/t,l=0,u=0,d=0,f=0,p=0;for(let t=Math.floor(a);t<Math.ceil(o);t+=1){let n=Math.min(t+1,o)-Math.max(t,a);for(let r=Math.floor(s);r<Math.ceil(c);r+=1){let i=n*(Math.min(r+1,c)-Math.max(r,s)),a=(t*e.width+r)*4;l+=(e.data[a]??0)*i,u+=(e.data[a+1]??0)*i,d+=(e.data[a+2]??0)*i,f+=(e.data[a+3]??0)*i,p+=i}}let m=(i*r.width+n)*4;r.data[m]=Math.round(l/p),r.data[m+1]=Math.round(u/p),r.data[m+2]=Math.round(d/p),r.data[m+3]=Math.round(f/p)}}return r}function J(e,t){return[...Q(e),...Y(e),...ee(e),...te(e,t)]}function Y(e){let t=e.customActions;if(!t)return[];let n=[];return t.blocked?n.push(`Custom actions were not read: an earlier accessibility read is still hung, so this capture skipped the read pass instead of queueing behind it. No element’s actions list is authoritative here. Reads resume once that call returns.`):t.read<t.candidates&&n.push(`Custom actions were read for ${t.read} of ${t.candidates} merged elements, on-screen ones first; the remaining ${t.candidates-t.read} were not read, so an absent actions list on those is not evidence that they have none. Scroll them into view and re-run to read them.`),t.truncated>0&&n.push(`${t.truncated} element(s) published more custom actions than are shown; those lists are clipped to the first 8 names, and long names are shortened.`),n}function X(e){return e===!0?[`This capture was cut at a backend limit, so elements later in the tree — footers, tab bars, items after a long list — may be missing even when they are on screen; their refs and selectors cannot be resolved from this snapshot. Navigate or scroll so fewer elements render and re-run, and use screenshot as visual truth for what is missing.`]:[]}function Z(e){return`Detected an overly complex or slow accessibility tree. Fell back to the ${e} snapshot backend. It is OK to continue; use --json to inspect snapshotQuality.reason if you need recovery details.`}function Q(e){return e.state===`recovered`?e.reasonCode===`deferred`||e.reasonCode===`requested-backend`?[]:e.reasonCode===`presentation-failed`?[`Agent Device could not safely present the captured accessibility tree and fell back to the ${e.backend} snapshot backend. This is an Agent Device runner bug, not an app accessibility-tree issue. Use screenshot as visual truth and report snapshotQuality.reason with the screenshot.`]:[Z(e.backend)]:e.state===`sparse`?[`No snapshot backend could read this screen`+(e.reason?` (${e.reason})`:``)+`. Its refs and selectors are invalid. Use screenshot as visual truth and coordinate taps; retry snapshot after navigating.`,...$(e)]:[]}function $(e){return e.reasonCode===`sparse-tree`?[`This screen publishes no accessibility content at all; assistive technologies see the same empty tree, so it is worth flagging as an app accessibility bug rather than only an automation limitation.`]:[]}function ee(e){return e.effectiveDepth===void 0?[]:[`Some deeper accessibility nodes were omitted; the accessibility backend capped this tree at depth ${e.effectiveDepth}. Navigate so the content you need sits higher in the tree, and use screenshot as visual truth for the rest.`]}function te(e,t){let n=[];for(let r of e.collapsedLeafIndexes??[]){let e=t.find(e=>e.index===r);if(!e)continue;let i=e.identifier?` (${e.identifier})`:``;n.push(`@${e.ref} [${e.type??`element`}]${i} merges many labels into a single accessibility element. The app likely marks a container as accessible, which hides every descendant from assistive tech and automation — the children cannot be addressed individually. Fix the app's accessibility (mark the rows, not the container); until then use screenshot as visual truth and coordinate taps.`)}return n}export{G as a,H as c,R as d,z as f,v as h,K as i,B as l,S as m,J as n,U as o,x as p,X as r,W as s,Z as t,V as u};
@@ -1 +1 @@
1
- import{M as e}from"./sdk-contracts.js";import{D as t}from"./sdk-batch-runner.js";import{M as n}from"./runtime.js";import{n as r}from"./catalog.js";import{n as i}from"./success-text.js";import{a,i as o}from"./request-runtime-binding.js";import{E as s,d as c,u as l}from"./session-snapshot.js";import{n as u}from"./touch-reference-frame.js";import{p as d}from"./quality-warnings.js";import{o as f}from"./interaction-ref-policy.js";import{captureSnapshotForSession as p}from"./interaction.js";async function m(t){let{req:i,sessionName:s,sessionStore:l}=t;if(i.command!==r.reactNative)return null;let u=h(i.positionals??[]);if(!u.ok)return u.response;let f=l.get(s);if(!f)return a();let m=await c({device:f.device,command:`press`,requiresCapture:!1,inspectFacts:t.inspectFacts,bindDevice:t.bindDevice,unavailableResponse:e=>o(`UNSUPPORTED_OPERATION`,`react-native dismiss-overlay is not supported on this device`,void 0,e.hint?{hint:e.hint}:void 0)});if(!m.ok)return m.response;try{let e=await p(f,i.flags,l,t.contextFromFlags,{interactiveOnly:!0});if(d(e.snapshotQuality))return _(e.snapshotQuality);let r=n(e.nodes),a=r.primaryAction;return a?await v(t,f,e,a,m.runtime):g(r.detected)}catch(t){return{ok:!1,error:e(t)}}}function h(e){return e.length===1&&e[0]===`dismiss-overlay`?{ok:!0}:{ok:!1,response:o(`INVALID_ARGS`,`react-native supports only: dismiss-overlay`)}}function g(e){return e?o(`COMMAND_FAILED`,`React Native overlay detected, but no safe dismiss target was found`,{hint:`Use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing the warning body.`}):{ok:!0,data:{action:`dismiss-overlay`,detected:!1,dismissed:!1,...i(`No React Native overlay detected`)}}}function _(e){return o(`COMMAND_FAILED`,`React Native overlay state could not be determined because the accessibility tree is unreadable`,{reason:e.reason,hint:`The snapshot quality verdict is sparse. Use screenshot as visual truth; if an overlay is visible, report it or navigate with coordinates, then retry snapshot or dismiss-overlay on a readable screen.`})}async function v(e,n,r,a,c){let{req:d,sessionStore:p}=e,m=e.contextFromFlags(d.flags,n.appBundleId,n.trace?.outPath),h=l(c,m).tapPoint;if(!h)return o(`UNSUPPORTED_OPERATION`,`react-native dismiss-overlay is not supported on this device`);let g=Date.now();s(n);let _=await h(a.point),v=Date.now(),x=await y(e,n),S=t({...u(r.nodes),..._,action:`dismiss-overlay`,overlayAction:a.action,x:a.point.x,y:a.point.y,ref:a.ref,label:a.label,warning:a.warning,dismissed:!0,verified:x.verified,verificationRequired:!x.verified,verificationWarning:x.verificationWarning,nextCommand:x.nextCommand,...i(b(x))});return f({session:n,sessionStore:p,command:d.command,positionals:d.positionals??[],flags:d.flags,result:S,responseData:S,actionStartedAt:g,actionFinishedAt:v})}async function y(e,t){let{req:r,sessionStore:i}=e,a=await p(t,r.flags,i,e.contextFromFlags,{interactiveOnly:!0});return d(a.snapshotQuality)?{verified:!1,verificationWarning:`React Native overlay dismissal could not be verified because the post-dismiss accessibility tree is unreadable. Use screenshot as visual truth.`,nextCommand:`agent-device screenshot`}:n(a.nodes).detected?{verified:!1,verificationWarning:`React Native overlay is still detected after dismissal. Use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing the warning body.`,nextCommand:`agent-device screenshot --overlay-refs`}:{verified:!0}}function b(e){return e.verified?`React Native overlay dismiss action sent and verified gone`:`React Native overlay dismiss action sent, but verification still detects an overlay`}export{m as handleReactNativeCommands};
1
+ import{N as e}from"./sdk-contracts.js";import{D as t}from"./sdk-batch-runner.js";import{M as n}from"./runtime.js";import{n as r}from"./catalog.js";import{r as i}from"./success-text.js";import{a,i as o}from"./request-runtime-binding.js";import{E as s,d as c,u as l}from"./session-snapshot.js";import{n as u}from"./touch-reference-frame.js";import{p as d}from"./quality-warnings.js";import{o as f}from"./interaction-ref-policy.js";import{captureSnapshotForSession as p}from"./interaction.js";async function m(t){let{req:i,sessionName:s,sessionStore:l}=t;if(i.command!==r.reactNative)return null;let u=h(i.positionals??[]);if(!u.ok)return u.response;let f=l.get(s);if(!f)return a();let m=await c({device:f.device,command:`press`,requiresCapture:!1,inspectFacts:t.inspectFacts,bindDevice:t.bindDevice,unavailableResponse:e=>o(`UNSUPPORTED_OPERATION`,`react-native dismiss-overlay is not supported on this device`,void 0,e.hint?{hint:e.hint}:void 0)});if(!m.ok)return m.response;try{let e=await p(f,i.flags,l,t.contextFromFlags,{interactiveOnly:!0});if(d(e.snapshotQuality))return _(e.snapshotQuality);let r=n(e.nodes),a=r.primaryAction;return a?await v(t,f,e,a,m.runtime):g(r.detected)}catch(t){return{ok:!1,error:e(t)}}}function h(e){return e.length===1&&e[0]===`dismiss-overlay`?{ok:!0}:{ok:!1,response:o(`INVALID_ARGS`,`react-native supports only: dismiss-overlay`)}}function g(e){return e?o(`COMMAND_FAILED`,`React Native overlay detected, but no safe dismiss target was found`,{hint:`Use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing the warning body.`}):{ok:!0,data:{action:`dismiss-overlay`,detected:!1,dismissed:!1,...i(`No React Native overlay detected`)}}}function _(e){return o(`COMMAND_FAILED`,`React Native overlay state could not be determined because the accessibility tree is unreadable`,{reason:e.reason,hint:`The snapshot quality verdict is sparse. Use screenshot as visual truth; if an overlay is visible, report it or navigate with coordinates, then retry snapshot or dismiss-overlay on a readable screen.`})}async function v(e,n,r,a,c){let{req:d,sessionStore:p}=e,m=e.contextFromFlags(d.flags,n.appBundleId,n.trace?.outPath),h=l(c,m).tapPoint;if(!h)return o(`UNSUPPORTED_OPERATION`,`react-native dismiss-overlay is not supported on this device`);let g=Date.now();s(n);let _=await h(a.point),v=Date.now(),x=await y(e,n),S=t({...u(r.nodes),..._,action:`dismiss-overlay`,overlayAction:a.action,x:a.point.x,y:a.point.y,ref:a.ref,label:a.label,warning:a.warning,dismissed:!0,verified:x.verified,verificationRequired:!x.verified,verificationWarning:x.verificationWarning,nextCommand:x.nextCommand,...i(b(x))});return f({session:n,sessionStore:p,command:d.command,positionals:d.positionals??[],flags:d.flags,result:S,responseData:S,actionStartedAt:g,actionFinishedAt:v})}async function y(e,t){let{req:r,sessionStore:i}=e,a=await p(t,r.flags,i,e.contextFromFlags,{interactiveOnly:!0});return d(a.snapshotQuality)?{verified:!1,verificationWarning:`React Native overlay dismissal could not be verified because the post-dismiss accessibility tree is unreadable. Use screenshot as visual truth.`,nextCommand:`agent-device screenshot`}:n(a.nodes).detected?{verified:!1,verificationWarning:`React Native overlay is still detected after dismissal. Use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing the warning body.`,nextCommand:`agent-device screenshot --overlay-refs`}:{verified:!0}}function b(e){return e.verified?`React Native overlay dismiss action sent and verified gone`:`React Native overlay dismiss action sent, but verification still detects an overlay`}export{m as handleReactNativeCommands};
@@ -1 +1 @@
1
- import{C as e,M as t}from"./sdk-contracts.js";import{c as n}from"./capture.js";import{g as r}from"./sdk-batch-runner.js";import{D as i,w as a}from"./sdk-device.js";import{D as o,E as s,O as c}from"./sdk-batch.js";import{n as l,r as u}from"./recording-export-quality.js";import{c as d,l as f}from"./back-mode.js";import{c as p}from"./session-store.js";import{r as m}from"./diagnostics.js";import"./diagnostics2.js";import{i as h}from"./output-path.js";import{n as g}from"./request-runtime-binding.js";import{n as _}from"./dispatch-resolve.js";import{a as v,t as y}from"./session-routing.js";import{a as b,c as x,i as S,o as C,s as w,t as T}from"./screen-recording-resource-recovery.js";import{t as E}from"./telemetry.js";import D from"node:path";import O from"node:fs";const k=[`clientOutPath`,`telemetryPath`,`warning`,`overlayWarning`];function A(e){let{resourcePath:t,record:n}=M(e);if(n.status!==`decoded`)return{kind:`none`};if(N(e,n.envelope),n.envelope.lifecycle!==`completed`)return{kind:`open`,resourcePath:t};let r=P(n.envelope.metadata);return r===void 0?(m({level:`warn`,phase:`screen_recording_completed_manifest_unreplayable`,data:{resourcePath:t}}),{kind:`none`}):O.existsSync(r.outPath)?{kind:`completed`,completion:r}:{kind:`none`}}function j(e){let{record:t}=M(e);return t.status===`decoded`&&t.envelope.lifecycle===`completed`}function M(e){let t=x.resourcePath(e.sessionStore,e.sessionName);return{resourcePath:t,record:x.store.read(t)}}function N(t,n){if(n.sessionId!==t.sessionName)throw new e(`COMMAND_FAILED`,`Screen recording recovery record does not belong to the requested session`,{reason:`runtime-contract-invalid`});if(!i(n.device,a(t.device)))throw new e(`COMMAND_FAILED`,`Screen recording recovery device does not match the selected device`,{reason:`runtime-contract-invalid`})}function P(e){let t=e?.[S];if(!(!r(t)||!F(t)||!I(t)))return t}function F(e){return L(e.outPath)&&L(e.backend)&&z(e.startedAt)&&z(e.completedAt)&&(e.capturedDurationMs===void 0||z(e.capturedDurationMs))&&d(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`}function I(e){return k.every(t=>R(e[t]))&&V(e.activeSessionApp)&&U(e.chunks)}function L(e){return typeof e==`string`&&e.length>0}function R(e){return e===void 0||L(e)}function z(e){return typeof e==`number`&&Number.isFinite(e)}function B(e){return!r(e)||!L(e.bundleId)?!1:R(e.name)}function V(e){return e===void 0||B(e)}function H(e){return Array.isArray(e)&&e.every(e=>r(e)&&Number.isFinite(e.index)&&L(e.path)&&R(e.clientOutPath))}function U(e){return e===void 0||H(e)}function ee(t){let r=n(`record`,t.flags);if(r)throw new e(`INVALID_ARGS`,r);let i=t.flags?.fps;if(i!==void 0&&(!Number.isInteger(i)||i<1||i>120))throw new e(`INVALID_ARGS`,`fps must be an integer between 1 and 120`);let a=u(t.flags?.quality);if(t.flags?.quality!==void 0&&a===void 0)throw new e(`INVALID_ARGS`,`quality must be one of: ${l.join(`, `)} (legacy numeric values 5-10 are accepted)`);return{scope:W(t.flags?.recordingScope),...i===void 0?{}:{fps:i},...a===void 0?{}:{exportQuality:a},showTouches:t.flags?.hideTouches!==!0,hideTouchesRequested:t.flags?.hideTouches===!0}}function W(t){if(t===void 0)return`app`;if(t===`app`||t===`device`||t===`system`)return t;throw new e(`INVALID_ARGS`,`record scope must be app, device, or system`)}function G(e){return{ok:!1,error:{code:`INVALID_ARGS`,message:y(e)?`record start with app scope and an explicit session requires an active app session; run open <app> first, or use --scope device to record the full screen`:`record start defaults to app scope and requires an active app session; run open <app> first, or use --scope device to record the full screen`}}}function K(e,t,n){return{ok:!0,data:{recording:`started`,outPath:e.clientOutPath??n,sessionStateDir:t,recordingBackend:e.backend,recordingScope:e.scope,recordOnlySession:e.recordOnlySession,activeSessionApp:e.activeSessionApp,showTouches:e.showTouches}}}function q(e){return{action:`start`,...e.clientOutPath?{requestedFileName:D.basename(e.clientOutPath)}:{},showTouches:e.showTouches}}function J(e){return{ok:!1,error:{code:`UNSUPPORTED_OPERATION`,message:`record is not supported on this device`,hint:e.hint??`Select an Apple, Android, physical HarmonyOS, or web target that supports screen recording.`,details:{reason:e.reason}}}}function Y(e){let t=[X(e)];if(e.chunks&&e.chunks.length>1&&t.push(...e.chunks.slice(1).map(e=>({field:`chunkPath`,artifactType:`screen-recording-chunk`,path:e.path,localPath:e.clientOutPath,fileName:D.basename(e.clientOutPath??e.path)}))),e.telemetryPath){let n=e.clientOutPath?E(e.clientOutPath):void 0;t.push({field:`telemetryPath`,artifactType:`screen-recording-telemetry`,path:e.telemetryPath,localPath:n,fileName:D.basename(e.telemetryPath)})}return{ok:!0,data:{recording:`stopped`,outPath:e.outPath,telemetryPath:e.telemetryPath,artifacts:t,recordingBackend:e.backend,recordingScope:e.scope,recordOnlySession:e.recordOnlySession,activeSessionApp:e.activeSessionApp,durationMs:Math.max(0,e.completedAt-e.startedAt),...e.capturedDurationMs===void 0?{}:{capturedDurationMs:e.capturedDurationMs},showTouches:e.showTouches,warning:e.warning,overlayWarning:e.overlayWarning,chunks:e.chunks?.map(e=>({index:e.index,path:e.clientOutPath??e.path}))}}}function X(e){return{field:`outPath`,artifactType:`screen-recording`,path:e.outPath,localPath:e.clientOutPath,fileName:D.basename(e.clientOutPath??e.outPath)}}async function Z(e){try{return await Q(e)}catch(e){return{ok:!1,error:t(e)}}}async function Q(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n),{plan:a,scope:o}=$(t,i);if(a.kind===`start`&&!f(o)&&!i)return G(t);let s=await te(e,i),{session:c}=s;return a.kind===`start`?await ne(e,c,ee(t),a.use,s.needsReadiness):await oe(e,c,a.kind,s.needsReadiness)}function $(e,t){let n=W(e.flags?.recordingScope);return{scope:n,plan:s({action:e.positionals?.[0],scope:n,hasLiveHandle:t?.screenRecording!==void 0})}}async function te(e,t){let n=t?.device??await _(e.req.flags??{});return await e.retainDeviceExecutionLock(n.id),t?{session:t,needsReadiness:!1}:{session:le(e,n),needsReadiness:!0}}async function ne(e,t,n,r,i){if(t.screenRecording)return{ok:!1,error:{code:`INVALID_ARGS`,message:`recording already in progress`}};let a=await e.bindDevice(t.device,o);i&&await g(a);let s=a.facts.screenRecordingStart;if(!s.available)return J(s);let c=await e.bindDevice(t.device,r),{fence:l,outputPaths:u}=re(e,t),d=await c.operations.screenRecordingStart(ie(e,t,n,l,u.outputPath));await b({admissionLedger:e.admissionLedger,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore,device:t.device,owner:c.owner,fence:l,...d,throwIfCanceled:e.throwIfCanceled});let f=e.sessionStore.get(e.sessionName)?.screenRecording;if(!f)throw TypeError(`Screen recording adoption did not publish a live handle`);let m=f.handle.inspect();return p(e.sessionStore,t,e.req,e.req.command,q(m)),K(m,e.sessionStore.ensureSessionDir(e.sessionName),u.requestedPath)}function re(e,t){let n=x.resourcePath(e.sessionStore,e.sessionName);return{fence:x.createNextFence({admissionLedger:e.admissionLedger,resourcePath:n,device:t.device}),outputPaths:h({requestedPath:e.req.positionals?.[1],platform:t.device.platform,cwd:e.req.meta?.cwd})}}function ie(e,t,n,r,i){return{sessionId:e.sessionName,outputPath:i,clientOutputPath:e.req.meta?.clientArtifactPaths?.outPath,scope:n.scope,showTouches:n.showTouches,hideTouchesRequested:n.hideTouchesRequested,recordOnlySession:t.recordOnlySession===!0,activeSessionApp:ae(t),exportQuality:n.exportQuality,fps:n.fps,fence:r}}function ae(e){if(e.appBundleId)return{bundleId:e.appBundleId,...e.appName?{name:e.appName}:{}}}async function oe(e,t,n,r){let i;try{i=n===`stop-live`?{completion:await C({intent:`capture`,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore}),recordsSessionAction:!0}:await ce(e,t,r)}catch(n){throw se(e,t),n}let a=i.completion,o=Y(a);return i.recordsSessionAction&&p(e.sessionStore,t,e.req,e.req.command,{action:`stop`,outPath:a.outPath,...a.clientOutPath?{requestedFileName:D.basename(a.clientOutPath)}:{},showTouches:a.showTouches}),t.recordOnlySession&&e.sessionStore.delete(e.sessionName),o}function se(e,t){t.recordOnlySession&&j(e)&&e.sessionStore.delete(e.sessionName)}async function ce(t,n,r){let i=A({sessionName:t.sessionName,sessionStore:t.sessionStore,device:n.device});if(i.kind===`completed`)return{completion:i.completion,recordsSessionAction:!1};if(i.kind===`none`)throw new e(`INVALID_ARGS`,`no active recording`);return{completion:await w({resourcePath:i.resourcePath,scope:t.requestScope,acquireControl:async(e,i)=>{let a=await t.bindExactDevice(n.device,e.owner,e.fence,c,i);return r&&await g(a),T({runtime:a,dispose:async()=>{}})}}),recordsSessionAction:!0}}function le(e,t){return{name:e.sessionName,sessionScope:v(e.req),device:t,createdAt:Date.now(),recordOnlySession:!0,actions:[]}}export{Z as t};
1
+ import{C as e,N as t}from"./sdk-contracts.js";import{c as n}from"./capture.js";import{g as r}from"./sdk-batch-runner.js";import{D as i,w as a}from"./sdk-device.js";import{D as o,E as s,O as c}from"./sdk-batch.js";import{n as l,r as u}from"./recording-export-quality.js";import{c as d,l as f}from"./back-mode.js";import{c as p}from"./session-store.js";import{r as m}from"./diagnostics.js";import"./diagnostics2.js";import{i as h}from"./output-path.js";import{i as ee,n as g}from"./recording-stop-observation.js";import{n as _}from"./request-runtime-binding.js";import{n as v}from"./dispatch-resolve.js";import{a as y,t as b}from"./session-routing.js";import{a as x,c as S,i as C,o as w,s as T,t as E}from"./screen-recording-resource-recovery.js";import{t as D}from"./telemetry.js";import O from"node:path";import k from"node:fs";const A=[`clientOutPath`,`telemetryPath`,`warning`,`overlayWarning`];function j(e){let{resourcePath:t,record:n}=N(e);if(n.status!==`decoded`)return{kind:`none`};if(P(e,n.envelope),n.envelope.lifecycle!==`completed`)return{kind:`open`,resourcePath:t};let r=F(n.envelope.metadata);return r===void 0?(m({level:`warn`,phase:`screen_recording_completed_manifest_unreplayable`,data:{resourcePath:t}}),{kind:`none`}):k.existsSync(r.outPath)?{kind:`completed`,completion:r}:{kind:`none`}}function M(e){let{record:t}=N(e);return t.status===`decoded`&&t.envelope.lifecycle===`completed`}function N(e){let t=S.resourcePath(e.sessionStore,e.sessionName);return{resourcePath:t,record:S.store.read(t)}}function P(t,n){if(n.sessionId!==t.sessionName)throw new e(`COMMAND_FAILED`,`Screen recording recovery record does not belong to the requested session`,{reason:`runtime-contract-invalid`});if(!i(n.device,a(t.device)))throw new e(`COMMAND_FAILED`,`Screen recording recovery device does not match the selected device`,{reason:`runtime-contract-invalid`})}function F(e){let t=e?.[C];if(!(!r(t)||!I(t)||!L(t)||!R(t)))return t}function I(e){return z(e.outPath)&&z(e.backend)&&V(e.startedAt)&&V(e.completedAt)&&(e.capturedDurationMs===void 0||V(e.capturedDurationMs))&&d(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`}function L(e){return A.every(t=>B(e[t]))&&te(e.activeSessionApp)&&W(e.chunks)}function R(e){return(e.stopObservation===void 0||g(e.stopObservation))&&(e.nativePathDisposition===void 0||ee(e.nativePathDisposition))}function z(e){return typeof e==`string`&&e.length>0}function B(e){return e===void 0||z(e)}function V(e){return typeof e==`number`&&Number.isFinite(e)}function H(e){return!r(e)||!z(e.bundleId)?!1:B(e.name)}function te(e){return e===void 0||H(e)}function U(e){return Array.isArray(e)&&e.every(e=>r(e)&&Number.isFinite(e.index)&&z(e.path)&&B(e.clientOutPath))}function W(e){return e===void 0||U(e)}function G(t){let r=n(`record`,t.flags);if(r)throw new e(`INVALID_ARGS`,r);let i=t.flags?.fps;if(i!==void 0&&(!Number.isInteger(i)||i<1||i>120))throw new e(`INVALID_ARGS`,`fps must be an integer between 1 and 120`);let a=u(t.flags?.quality);if(t.flags?.quality!==void 0&&a===void 0)throw new e(`INVALID_ARGS`,`quality must be one of: ${l.join(`, `)} (legacy numeric values 5-10 are accepted)`);return{scope:K(t.flags?.recordingScope),...i===void 0?{}:{fps:i},...a===void 0?{}:{exportQuality:a},showTouches:t.flags?.hideTouches!==!0,hideTouchesRequested:t.flags?.hideTouches===!0}}function K(t){if(t===void 0)return`app`;if(t===`app`||t===`device`||t===`system`)return t;throw new e(`INVALID_ARGS`,`record scope must be app, device, or system`)}function q(e){return{ok:!1,error:{code:`INVALID_ARGS`,message:b(e)?`record start with app scope and an explicit session requires an active app session; run open <app> first, or use --scope device to record the full screen`:`record start defaults to app scope and requires an active app session; run open <app> first, or use --scope device to record the full screen`}}}function J(e,t,n){return{ok:!0,data:{recording:`started`,outPath:e.clientOutPath??n,sessionStateDir:t,recordingBackend:e.backend,recordingScope:e.scope,recordOnlySession:e.recordOnlySession,activeSessionApp:e.activeSessionApp,showTouches:e.showTouches}}}function Y(e){return{action:`start`,...e.clientOutPath?{requestedFileName:O.basename(e.clientOutPath)}:{},showTouches:e.showTouches}}function X(e){return{ok:!1,error:{code:`UNSUPPORTED_OPERATION`,message:`record is not supported on this device`,hint:e.hint??`Select an Apple, Android, physical HarmonyOS, or web target that supports screen recording.`,details:{reason:e.reason}}}}function Z(e){let t=[Q(e)];if(e.chunks&&e.chunks.length>1&&t.push(...e.chunks.slice(1).map(e=>({field:`chunkPath`,artifactType:`screen-recording-chunk`,path:e.path,localPath:e.clientOutPath,fileName:O.basename(e.clientOutPath??e.path)}))),e.telemetryPath){let n=e.clientOutPath?D(e.clientOutPath):void 0;t.push({field:`telemetryPath`,artifactType:`screen-recording-telemetry`,path:e.telemetryPath,localPath:n,fileName:O.basename(e.telemetryPath)})}return{ok:!0,data:{recording:`stopped`,outPath:e.outPath,telemetryPath:e.telemetryPath,artifacts:t,recordingBackend:e.backend,recordingScope:e.scope,recordOnlySession:e.recordOnlySession,activeSessionApp:e.activeSessionApp,durationMs:Math.max(0,e.completedAt-e.startedAt),...e.capturedDurationMs===void 0?{}:{capturedDurationMs:e.capturedDurationMs},...e.stopObservation===void 0?{}:{recorder:e.stopObservation.recorder},...e.nativePathDisposition===void 0?{}:{nativePathDisposition:e.nativePathDisposition},showTouches:e.showTouches,warning:e.warning,overlayWarning:e.overlayWarning,chunks:e.chunks?.map(e=>({index:e.index,path:e.clientOutPath??e.path}))}}}function Q(e){return{field:`outPath`,artifactType:`screen-recording`,path:e.outPath,localPath:e.clientOutPath,fileName:O.basename(e.clientOutPath??e.outPath)}}async function ne(e){try{return await re(e)}catch(e){return{ok:!1,error:t(e)}}}async function re(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n),{plan:a,scope:o}=ie(t,i);if(a.kind===`start`&&!f(o)&&!i)return q(t);let s=await ae(e,i),{session:c}=s;return a.kind===`start`?await oe(e,c,G(t),a.use,s.needsReadiness):await le(e,c,a.kind,s.needsReadiness)}function ie(e,t){let n=K(e.flags?.recordingScope);return{scope:n,plan:s({action:e.positionals?.[0],scope:n,hasLiveHandle:t?.screenRecording!==void 0})}}async function ae(e,t){let n=t?.device??await v(e.req.flags??{});return await e.retainDeviceExecutionLock(n.id),t?{session:t,needsReadiness:!1}:{session:fe(e,n),needsReadiness:!0}}async function oe(e,t,n,r,i){if(t.screenRecording)return{ok:!1,error:{code:`INVALID_ARGS`,message:`recording already in progress`}};let a=await e.bindDevice(t.device,o);i&&await _(a);let s=a.facts.screenRecordingStart;if(!s.available)return X(s);let c=await e.bindDevice(t.device,r),{fence:l,outputPaths:u}=$(e,t),d=await c.operations.screenRecordingStart(se(e,t,n,l,u.outputPath));await x({admissionLedger:e.admissionLedger,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore,device:t.device,owner:c.owner,fence:l,...d,throwIfCanceled:e.throwIfCanceled});let f=e.sessionStore.get(e.sessionName)?.screenRecording;if(!f)throw TypeError(`Screen recording adoption did not publish a live handle`);let m=f.handle.inspect();return p(e.sessionStore,t,e.req,e.req.command,Y(m)),J(m,e.sessionStore.ensureSessionDir(e.sessionName),u.requestedPath)}function $(e,t){let n=S.resourcePath(e.sessionStore,e.sessionName);return{fence:S.createNextFence({admissionLedger:e.admissionLedger,resourcePath:n,device:t.device}),outputPaths:h({requestedPath:e.req.positionals?.[1],platform:t.device.platform,cwd:e.req.meta?.cwd})}}function se(e,t,n,r,i){return{sessionId:e.sessionName,outputPath:i,clientOutputPath:e.req.meta?.clientArtifactPaths?.outPath,scope:n.scope,showTouches:n.showTouches,hideTouchesRequested:n.hideTouchesRequested,recordOnlySession:t.recordOnlySession===!0,activeSessionApp:ce(t),exportQuality:n.exportQuality,fps:n.fps,fence:r}}function ce(e){if(e.appBundleId)return{bundleId:e.appBundleId,...e.appName?{name:e.appName}:{}}}async function le(e,t,n,r){let i;try{i=n===`stop-live`?{completion:await w({intent:`capture`,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore}),recordsSessionAction:!0}:await de(e,t,r)}catch(n){throw ue(e,t),n}let a=i.completion,o=Z(a);return i.recordsSessionAction&&p(e.sessionStore,t,e.req,e.req.command,{action:`stop`,outPath:a.outPath,...a.clientOutPath?{requestedFileName:O.basename(a.clientOutPath)}:{},showTouches:a.showTouches}),t.recordOnlySession&&e.sessionStore.delete(e.sessionName),o}function ue(e,t){t.recordOnlySession&&M(e)&&e.sessionStore.delete(e.sessionName)}async function de(t,n,r){let i=j({sessionName:t.sessionName,sessionStore:t.sessionStore,device:n.device});if(i.kind===`completed`)return{completion:i.completion,recordsSessionAction:!1};if(i.kind===`none`)throw new e(`INVALID_ARGS`,`no active recording`);return{completion:await T({resourcePath:i.resourcePath,scope:t.requestScope,acquireControl:async(e,i)=>{let a=await t.bindExactDevice(n.device,e.owner,e.fence,c,i);return r&&await _(a),E({runtime:a,dispose:async()=>{}})}}),recordsSessionAction:!0}}function fe(e,t){return{name:e.sessionName,sessionScope:y(e.req),device:t,createdAt:Date.now(),recordOnlySession:!0,actions:[]}}export{ne as t};