agent-device 0.20.6 → 0.20.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/README.md +3 -3
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.apk → agent-device-android-ime-helper-0.20.8.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.manifest.json → agent-device-android-ime-helper-0.20.8.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.apk → agent-device-android-snapshot-helper-0.20.8.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.manifest.json → agent-device-android-snapshot-helper-0.20.8.manifest.json} +6 -6
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +20 -0
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +67 -0
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +339 -4
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +78 -0
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +31 -2
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +34 -8
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +4 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -28
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +7 -0
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +4 -0
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +4 -0
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -1
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +100 -12
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -0
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +57 -0
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -0
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +18 -3
  25. package/dist/src/agent-browser-tool.js +1 -1
  26. package/dist/src/agent-device-client.js +2 -2
  27. package/dist/src/android-adb.js +1 -1
  28. package/dist/src/android.js +1 -1
  29. package/dist/src/app-helpers.js +1 -1
  30. package/dist/src/app-lifecycle.js +7 -7
  31. package/dist/src/app-lifecycle2.js +2 -0
  32. package/dist/src/app-log-files.js +1 -0
  33. package/dist/src/app-log-reconnect.js +1 -0
  34. package/dist/src/app-log-runtime.js +4 -0
  35. package/dist/src/app-resolution.js +2 -1
  36. package/dist/src/apps.js +5 -5
  37. package/dist/src/audio-probe.js +1 -1
  38. package/dist/src/auth-session.js +1 -0
  39. package/dist/src/auth.js +2 -0
  40. package/dist/src/boot-diagnostics.js +2 -2
  41. package/dist/src/cli-config.js +1 -1
  42. package/dist/src/cli-grammar.js +1 -0
  43. package/dist/src/cli-help.js +199 -259
  44. package/dist/src/cli-output.js +1 -0
  45. package/dist/src/cli-runner.js +1 -2
  46. package/dist/src/cli.js +6 -16
  47. package/dist/src/client-metro.js +1 -1
  48. package/dist/src/cloud-artifacts.d.ts +2 -137
  49. package/dist/src/command-schema.js +3 -3
  50. package/dist/src/connection-runtime.js +1 -0
  51. package/dist/src/connection.js +5 -0
  52. package/dist/src/daemon-shutdown-report.js +1 -0
  53. package/dist/src/daemon.js +2 -0
  54. package/dist/src/debug-symbols.js +1 -1
  55. package/dist/src/device-claim-inspection.js +1 -0
  56. package/dist/src/device-input-state.js +2 -2
  57. package/dist/src/device-ready.js +1 -0
  58. package/dist/src/device.js +1 -1
  59. package/dist/src/device2.js +2 -0
  60. package/dist/src/dispatch.js +1 -0
  61. package/dist/src/find.js +1 -1
  62. package/dist/src/finders.js +1 -1
  63. package/dist/src/generic-settle.js +1 -1
  64. package/dist/src/generic.js +1 -1
  65. package/dist/src/handler-utils.js +1 -0
  66. package/dist/src/harmonyos.js +1 -0
  67. package/dist/src/hdc.js +1 -0
  68. package/dist/src/host-process.js +3 -2
  69. package/dist/src/ime-lifecycle.js +7 -7
  70. package/dist/src/index.d.ts +52 -21
  71. package/dist/src/input-actions.js +4 -4
  72. package/dist/src/input-actions2.js +1 -1
  73. package/dist/src/input-actions3.js +1 -0
  74. package/dist/src/install-artifact.js +1 -5
  75. package/dist/src/install-artifact2.js +1 -1
  76. package/dist/src/install-source2.js +1 -1
  77. package/dist/src/interaction-runtime.js +1 -1
  78. package/dist/src/interaction-snapshot.js +1 -1
  79. package/dist/src/interaction-touch-reference-frame.js +1 -1
  80. package/dist/src/interaction.js +1 -1
  81. package/dist/src/interactor.js +2 -2
  82. package/dist/src/interactor2.js +1 -1
  83. package/dist/src/internal/bin.js +2 -2
  84. package/dist/src/internal/daemon.js +7 -36
  85. package/dist/src/inventory.js +5 -0
  86. package/dist/src/inventory2.js +1 -0
  87. package/dist/src/inventory3.js +2 -0
  88. package/dist/src/inventory4.js +1 -0
  89. package/dist/src/inventory5.js +1 -0
  90. package/dist/src/inventory6.js +1 -0
  91. package/dist/src/lease-context.js +1 -1
  92. package/dist/src/lease.js +1 -1
  93. package/dist/src/limrun-runtime-dependencies.js +1 -0
  94. package/dist/src/limrun.d.ts +10 -125
  95. package/dist/src/limrun.js +1 -1
  96. package/dist/src/linux.js +1 -1
  97. package/dist/src/logcat.js +1 -1
  98. package/dist/src/manifest.js +1 -1
  99. package/dist/src/notifications.js +1 -1
  100. package/dist/src/output-path.js +1 -0
  101. package/dist/src/owner-identity.js +1 -0
  102. package/dist/src/physical-device-control.js +1 -1
  103. package/dist/src/platform-runtime-app-log-android-transport.js +1 -0
  104. package/dist/src/platform-runtime-app-log-process.js +1 -0
  105. package/dist/src/platform-runtime-host.js +1 -0
  106. package/dist/src/platform-runtime-network-web-transport.js +1 -0
  107. package/dist/src/platform-runtime-operation-host.js +5 -0
  108. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -0
  109. package/dist/src/platform-runtime-screen-recording-apple-host.js +1 -0
  110. package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -0
  111. package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -0
  112. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -0
  113. package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -0
  114. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -0
  115. package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -0
  116. package/dist/src/platform-runtime-screen-recording-output-host.js +1 -0
  117. package/dist/src/platform-runtime-screen-recording-web-host.js +1 -0
  118. package/dist/src/platform-runtime-toolchain-host.js +1 -0
  119. package/dist/src/platform-runtime.js +1 -0
  120. package/dist/src/prepare-kind.js +15 -0
  121. package/dist/src/process-entry.js +1 -0
  122. package/dist/src/process-lock.js +1 -1
  123. package/dist/src/provider-webdriver.js +1 -0
  124. package/dist/src/proxy.js +2 -0
  125. package/dist/src/react-native.js +1 -1
  126. package/dist/src/record-runtime.js +1 -0
  127. package/dist/src/record-trace.js +1 -1
  128. package/dist/src/recording-telemetry.js +1 -0
  129. package/dist/src/registry.js +24 -24
  130. package/dist/src/replay.js +3 -0
  131. package/dist/src/reporting.js +3 -3
  132. package/dist/src/runner-disposal.js +1 -1
  133. package/dist/src/runner-lease.js +1 -1
  134. package/dist/src/runtime.js +3 -3
  135. package/dist/src/runtime2.js +4 -0
  136. package/dist/src/runtime3.js +3 -0
  137. package/dist/src/runtime4.js +1 -0
  138. package/dist/src/runtime5.js +1 -0
  139. package/dist/src/runtime6.js +1 -0
  140. package/dist/src/runtime7.js +1 -0
  141. package/dist/src/screenshot-result.js +4 -4
  142. package/dist/src/screenshot.js +1 -0
  143. package/dist/src/sdk-android-adb.js +4 -4
  144. package/dist/src/sdk-batch-runner.js +3 -3
  145. package/dist/src/sdk-contracts.d.ts +31 -5
  146. package/dist/src/sdk-contracts.js +1 -1
  147. package/dist/src/sdk-device.js +1 -1
  148. package/dist/src/sdk-finders.js +1 -1
  149. package/dist/src/sdk-remote-config.js +1 -1
  150. package/dist/src/sdk-selectors.d.ts +285 -5
  151. package/dist/src/sdk-selectors.js +1 -1
  152. package/dist/src/selector-runtime.js +1 -1
  153. package/dist/src/selector-vocabulary.js +1 -1
  154. package/dist/src/selectors.js +1 -1
  155. package/dist/src/server.js +3 -3
  156. package/dist/src/session-target-evidence.js +1 -1
  157. package/dist/src/session.js +10 -9
  158. package/dist/src/shared.js +2 -0
  159. package/dist/src/shell-quote.js +1 -0
  160. package/dist/src/simulator.js +1 -1
  161. package/dist/src/snapshot-runtime.js +1 -0
  162. package/dist/src/snapshot-session.js +1 -0
  163. package/dist/src/snapshot2.js +1 -1
  164. package/dist/src/src.js +1 -1
  165. package/dist/src/src2.js +2 -0
  166. package/dist/src/src3.js +1 -0
  167. package/dist/src/text-surface.js +1 -1
  168. package/dist/src/timing-safe-equal.js +1 -0
  169. package/dist/src/tool-provider.js +2 -2
  170. package/dist/src/update-check.js +1 -1
  171. package/dist/src/version.js +1 -1
  172. package/dist/src/video.js +23 -0
  173. package/dist/src/web.js +1 -1
  174. package/package.json +34 -20
  175. package/server.json +2 -2
  176. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.6.apk.sha256 +0 -1
  177. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.6.apk.sha256 +0 -1
  178. package/dist/src/app-log-request-scope.js +0 -1
  179. package/dist/src/context.js +0 -1
  180. package/dist/src/devices.js +0 -1
  181. package/dist/src/devices2.js +0 -1
  182. package/dist/src/devices3.js +0 -1
  183. package/dist/src/devices4.js +0 -1
  184. package/dist/src/provider-limrun-runtime.js +0 -1
  185. package/dist/src/register-builtins.js +0 -1
  186. package/dist/src/runner-client.js +0 -1
  187. package/dist/src/runner-provider.js +0 -1
  188. package/dist/src/screenshot-geometry.js +0 -1
  189. package/dist/src/viewport-dimension.js +0 -15
  190. package/skills/agent-device/SKILL.md +0 -45
  191. package/skills/dogfood/SKILL.md +0 -27
@@ -0,0 +1,5 @@
1
+ import{_ as e,v as t}from"./sdk-contracts.js";import n from"node:path";const r=[[/device unauthorized|device still authorizing/,{reason:`device_unauthorized`,hint:`USB debugging is not authorized — accept the authorization prompt on the device screen (re-plug the cable if none appears), then retry.`}],[/device offline/,{reason:`device_offline`,hint:`The device is connected but offline — wait for it to finish booting or run adb reconnect, then retry.`,retriable:!0}],[/more than one (?:device\/emulator|device and emulator)/,{reason:`multiple_devices`,hint:`Multiple Android devices are connected — pass --serial <serial> (see adb devices) to select one.`}],[/no devices\/emulators found|no devices found/,{reason:`no_devices`,hint:`No Android devices detected — boot an emulator or connect a device and verify it appears in adb devices.`}],[/device (?:'[^']*' )?not found/,{reason:`device_not_found`,hint:`The device disconnected or is restarting — verify it is listed in adb devices, then retry.`,retriable:!0}],[/adb server version \(\d+\) doesn't match this client/,{reason:`server_version_mismatch`,hint:`Multiple adb installs conflict — adb restarts its server automatically, so retry; align PATH to a single adb to stop recurrences.`,retriable:!0}],[/transport error|connection reset|broken pipe|protocol fault/,{reason:`connection_dropped`,hint:`The adb connection dropped — retry; if it persists, run adb kill-server and reconnect the device.`,retriable:!0}],[/install_failed_insufficient_storage/,{reason:`install_insufficient_storage`,hint:`The device is out of storage — free up space or uninstall unused apps, then retry the install.`},!0],[/install_failed_update_incompatible/,{reason:`install_update_incompatible`,hint:`The installed app has an incompatible signature — uninstall the existing app first, then retry the install.`},!0],[/install_failed_version_downgrade/,{reason:`install_version_downgrade`,hint:`The APK is older than the installed app — uninstall the app first (or install with downgrade allowed), then retry.`},!0],[/install_failed_\w+|install_parse_failed_\w+/,{reason:`install_failed`,hint:`The Android package installer rejected the APK — see the INSTALL_FAILED code in the error output for the exact cause.`},!0]],i=Object.freeze({reason:`timeout`,hint:`adb timed out — the adb server may be wedged. Run adb kill-server && adb start-server, check adb devices, then retry.`});function a(e,t=``){let n=e.toLowerCase(),i=t.toLowerCase();for(let[e,t,a]of r)if(e.test(n)||a&&e.test(i))return t}function o(t,n,r){let i=a(n.stderr,n.stdout);return new e(`COMMAND_FAILED`,t,{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode,processExitError:!0,hint:i?.hint??r,...i?{adbFailure:i.reason}:{},...i?.retriable===void 0?{}:{retriable:i.retriable}})}function s(t){return!(t instanceof e)||t.code!==`COMMAND_FAILED`||typeof t.details?.timeoutMs!=`number`||(t.details={...t.details,adbFailure:i.reason,...typeof t.details.hint==`string`?{}:{hint:i.hint}}),t}function c(e){return e.startsWith(`emulator-`)}function l(e){return e.toLowerCase().replace(/_/g,` `).replace(/\s+/g,` `).trim()}function u(e){let t=[];for(let n of e.split(`
2
+ `)){let e=n.trim().split(/\s+/),r=e[0];!r||r===`List`||e[1]!==`device`||t.push({serial:r,rawModel:(e.find(e=>e.startsWith(`model:`))??``).replace(`model:`,``)})}return t}function d(e){return e.split(`
3
+ `).map(e=>e.trim()).filter(e=>e.length>0)}function f(e){let t=e.split(`
4
+ `).map(e=>e.trim()).filter(e=>e.length>0);return t.at(-1)===`OK`&&t.pop(),t.join(`
5
+ `).trim()||void 0}function p(e){let t=e.toLowerCase();return t.includes(`tv`)||t.includes(`leanback`)?`tv`:null}function m(e){return/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(e)}function h(e){return/\b(tv|television)\b/i.test(l(e))?`tv`:`mobile`}const g=[`android.software.leanback`,`android.software.leanback_only`,`android.hardware.type.television`];function _(e,t={sdkRoots:[]}){return{discover:async(n,r)=>await v(e,t,n,r)}}async function v(t,r,i,a){await t.toolchains.prepare(`android`);let o=[...r.sdkRoots,n.join(t.homeDirectory,`Android`,`Sdk`)],s=await b(t,`adb`,o,[`platform-tools`,`adb`]);if(!s)throw new e(`TOOL_MISSING`,`adb not found in PATH`);let c={host:t,adb:s,emulator:await b(t,`emulator`,o,[`emulator`,`emulator`]),scope:a},l=y(i),u=await M((await x(c)).filter(e=>!l||l.has(e.serial)),3,async e=>await S(c,e));return[...u,...await O(c,u)]}function y(e){let t=e.serial?.trim(),n=e.androidSerialAllowlist;return t?n?new Set(n.includes(t)?[t]:[]):new Set([t]):n?new Set(n):void 0}async function b(e,t,r,i){for(let t of r){let r=n.join(t,...i);if(await e.files.isExecutable(r))return r}return await e.commands.which(t)}async function x(e){let t=await A(e,e.adb,[`devices`,`-l`]);if(t.exitCode!==0)throw o(`Failed to list Android devices`,t,"Verify adb is running and the device appears in `adb devices`.");return u(t.stdout)}async function S(e,t){let[n,r,i]=await Promise.all([C(e,t),E(e,t.serial),D(e,t.serial)]);return{platform:`android`,id:t.serial,name:n,kind:c(t.serial)?`emulator`:`device`,target:i,booted:r}}async function C(e,t){let n=t.rawModel.replace(/_/g,` `).trim();return c(t.serial)?(await w(e,t.serial))?.replace(/_/g,` `)||n||t.serial:n||t.serial}async function w(e,t){for(let n of[`ro.boot.qemu.avd_name`,`persist.sys.avd_name`]){let r=await T(e,t,[`shell`,`getprop`,n]),i=r?.stdout.trim();if(r?.exitCode===0&&i)return i}let n=await T(e,t,[`emu`,`avd`,`name`]),r=n&&f(n.stdout);return n?.exitCode===0?r:void 0}async function T(e,n,r){try{return await k(e,n,r)}catch(e){let n=t(e);if(n.code===`COMMAND_FAILED`&&typeof n.details?.timeoutMs==`number`)return;throw e}}async function E(e,t){try{return(await k(e,t,[`shell`,`getprop`,`sys.boot_completed`])).stdout.trim()===`1`}catch(t){if(e.scope.signal.aborted)throw t;return!1}}async function D(e,t){return p(j(await k(e,t,[`shell`,`getprop`,`ro.build.characteristics`])))===`tv`||(await M(g,2,async n=>await k(e,t,[`shell`,`cmd`,`package`,`has-feature`,n]))).some(e=>j(e).toLowerCase().includes(`true`))||m(j(await k(e,t,[`shell`,`pm`,`list`,`features`])))?`tv`:`mobile`}async function O(e,t){if(!e.emulator)return[];let n;try{n=await A(e,e.emulator,[`-list-avds`])}catch(t){if(e.scope.signal.aborted)throw t;return[]}if(n.exitCode!==0)return[];let r=new Set(t.filter(e=>e.kind===`emulator`).map(e=>l(e.name)));return d(n.stdout).filter(e=>!r.has(l(e))).map(e=>({platform:`android`,id:e,name:e,kind:`emulator`,target:h(e),booted:!1}))}async function k(e,t,n){return await A(e,e.adb,[`-s`,t,...n])}async function A(e,t,n){try{return await e.host.commands.run({executable:t,args:n,allowFailure:!0,timeoutMs:1e4},e.scope.signal)}catch(e){throw s(e)}}function j(e){return`${e.stdout}\n${e.stderr}`}async function M(e,t,n){let r=Array(e.length),i=0;return await Promise.all(Array.from({length:Math.min(t,e.length)},async()=>{for(;i<e.length;){let t=i++;r[t]=await n(e[t])}})),r}export{_ as createAndroidInventory};
@@ -0,0 +1 @@
1
+ import{_ as e}from"./sdk-contracts.js";import{S as t}from"./sdk-device.js";const n=/^(iphone|ipad|ipod|appletv|realitydevice)/i,r=/ipad/i,i=/\b(apple vision|vision pro|xros|visionos|realitydevice)\b/i,a=/\b(iphone|ipad|ipod)\b/i,o=/^appletv/i,s=[`apple tv`,`appletv`,`tvos`];function c(e){return(e??``).trim().toLowerCase()}function l(e){return e.includes(`tvos`)}function u(e){return e.includes(`xros`)||e.includes(`visionos`)}function d(e){return l(c(e))?`tv`:`mobile`}function f(e){let t=c(e);return t.includes(`ios`)||t.includes(`tvos`)||t.includes(`xros`)||t.includes(`visionos`)}function p(e){let t=c(e);return s.some(e=>t.includes(e))}function m(e){return a.test(e.trim())}function h(e){return p(e)?`tv`:m(e)||i.test(e)?`mobile`:null}function g(e,t){return e===`tv`?`tvos`:t.some(e=>i.test(e))?`visionos`:t.some(e=>r.test(e))?`ipados`:`ios`}function _(e){return n.test(e.trim())}function v(e){return o.test(e.trim())}function y(e){return[e.name??``,e.deviceProperties?.name??``,e.deviceProperties?.deviceType??``]}function b(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??``}function x(e){return l(c(e.hardwareProperties?.platform))||v(b(e))||y(e).some(p)?`tv`:`mobile`}function S(e){let t=c(e.hardwareProperties?.platform);return t.includes(`ios`)||l(t)||u(t)||_(b(e))?!0:y(e).some(p)}function C(e){if(!S(e))return null;let t=e.hardwareProperties?.udid??e.identifier??``,n=e.name??e.deviceProperties?.name??t;if(!t)return null;let r=x(e);return{platform:`apple`,id:t,name:n,kind:`device`,target:r,appleOs:g(r,[b(e),...y(e)]),iosPhysicalDeviceBackend:`coredevice`,booted:!0}}const w=/^==\s*(.+?)\s*==$/,T=/^(?<name>.+?)\s+(?:\[(?<idBracket>[^[\]]+)\]|\((?<osVersion>[^)]+)\)\s+\((?<idParen>[^)]+)\))\s*$/;function E(e){let t=[],n=null;for(let r of e.split(/\r?\n/)){let e=r.trim();if(!e)continue;let i=w.exec(e);if(i){n=i[1]?.trim()??null;continue}if(n!==`Devices`)continue;let a=D(e);a&&t.push(a)}return t}function D(e){let t=T.exec(e)?.groups;if(!t)return;let n=t.name?.trim(),r=t.idBracket?.trim()||t.idParen?.trim();if(!n||!r)return;let i=h(n);if(!i)return;let a=t.osVersion?.trim();return{platform:`apple`,id:r,name:n,kind:`device`,target:i,appleOs:g(i,a?[n,a]:[n]),iosPhysicalDeviceBackend:`xctest`,booted:!0}}async function O(e,t){let[n,r]=await Promise.all([k(e,t),A(e,t)]);return j(n,r)}async function k(e,t){let n;try{return n=await e.files.createTemporaryTextFile({prefix:`agent-device-devicectl-`,suffix:`.json`}),(await e.appleTools.run({tool:`devicectl`,args:[`list`,`devices`,`--json-output`,n.path],allowFailure:!0,timeoutMs:8e3},t.signal)).exitCode===0?(JSON.parse(await n.readText()).result?.devices??[]).flatMap(e=>{let t=C(e);return t?[t]:[]}):[]}catch{return t.signal.throwIfAborted(),[]}finally{try{await n?.[Symbol.asyncDispose]()}catch{}}}async function A(e,t){try{let n=await e.appleTools.run({tool:`xctrace`,args:[`list`,`devices`],allowFailure:!0},t.signal);return n.exitCode===0?E(n.stdout):[]}catch{return t.signal.throwIfAborted(),[]}}function j(e,t){let n=new Set(e.map(e=>e.id)),r=[...e];for(let e of t)n.has(e.id)||(n.add(e.id),r.push(e));return r}function M(e){let t=e?.trim();return t?[`--set`,t,`list`,`devices`,`-j`]:[`list`,`devices`,`-j`]}function N(e,t){let n=[];for(let[r,i]of Object.entries(e.devices))if(f(r))for(let e of i){if(!e.isAvailable)continue;let i=d(r);n.push({platform:`apple`,id:e.udid,name:e.name,kind:`simulator`,target:i,appleOs:g(i,[e.deviceTypeIdentifier??``,e.name]),booted:e.state===`Booted`,...t?{simulatorSetPath:t}:{}})}return n}async function P(n,r,i){let a=r.iosSimulatorSetPath?.trim()||void 0,o=await n.appleTools.run({tool:`simctl`,args:M(a),...r.booted===!0?{timeoutMs:3e3}:{}},i.signal),s;try{s=N(JSON.parse(o.stdout),a)}catch(t){throw new e(`COMMAND_FAILED`,`Failed to parse simctl devices JSON`,void 0,t)}for(let e of s)e.booted===!0&&await n.observations.deviceBooted(e);return t(s)}function F(e){return Object.freeze({discover:async(t,n)=>await I(e,t,n)})}async function I(n,r,i){if(L(r))return[R(n)];if(n.hostOs!==`darwin`)throw new e(`UNSUPPORTED_PLATFORM`,`Apple tools are only available on macOS`);if(!await n.appleTools.isXcrunAvailable(i.signal))throw new e(`TOOL_MISSING`,`xcrun not found in PATH`);let a=P(n,r,i);if(r.kind===`simulator`)return await a;if(r.iosSimulatorSetPath||r.udid){let e=await a,o=[...e,R(n)];return r.iosSimulatorSetPath||e.some(e=>e.id===r.udid)?t(o):t(z(o,await O(n,i)))}let[o,s]=await Promise.all([a,O(n,i)]);return t(z([...o,R(n)],s))}function L(e){return e.platform===`macos`||e.platform===`apple`&&e.target===`desktop`}function R(e){return{platform:`apple`,id:`host-macos-local`,name:e.hostName,kind:`device`,target:`desktop`,appleOs:`macos`,booted:!0}}function z(e,t){let n=new Set(e.map(e=>e.id));return[...e,...t.filter(e=>n.has(e.id)?!1:(n.add(e.id),!0))]}export{F as createAppleInventorySource};
@@ -0,0 +1,2 @@
1
+ import{_ as e}from"./sdk-contracts.js";import t from"node:path";function n(e,t={}){return{discover:async(n,r)=>await i(e,t,n,r)}}function r(e){return e.split(`
2
+ `).map(e=>e.trim()).filter(e=>e.length>0&&e!==`[Empty]`)}async function i(t,n,i,l){await t.toolchains.prepare(`harmonyos`);let u=await o(t,a(n));if(!u)throw new e(`TOOL_MISSING`,`hdc not found in PATH`,{hint:`Install HarmonyOS Command Line Tools, then add its sdk/default/openharmony/toolchains directory to PATH.`});let d=await c(t,u,[`list`,`targets`],l);if(d.exitCode!==0)throw new e(`COMMAND_FAILED`,`hdc list targets failed`,{stderr:d.stderr,hint:`Confirm the HarmonyOS emulator or device is running, then run hdc list targets.`});let f=r(d.stdout).filter(e=>!i.serial||i.serial===e);return await Promise.all(f.map(async e=>await s(t,u,e,l)))}function a(e){return[e.hdcSdkPath,e.devecoSdkHome&&t.join(e.devecoSdkHome,`default`,`openharmony`,`toolchains`),e.commandLineToolsHome&&t.join(e.commandLineToolsHome,`sdk`,`default`,`openharmony`,`toolchains`)].filter(e=>e!==void 0)}async function o(e,n){for(let r of n){let n=t.join(r,`hdc`);if(await e.files.isExecutable(n))return n}return await e.commands.which(`hdc`)}async function s(e,t,n,r){let i=[`-t`,n,`shell`,`param`,`get`],[a,o]=await Promise.all([c(e,t,[...i,`const.product.name`],r),c(e,t,[...i,`const.build.characteristics`],r)]),s=a.exitCode===0?a.stdout.trim():``,l=s.toLowerCase()===`emulator`;return{platform:`harmonyos`,id:n,name:s||n,kind:l?`emulator`:`device`,target:o.stdout.toLowerCase().includes(`tv`)?`tv`:`mobile`,booted:!0}}async function c(e,t,n,r){return await e.commands.run({executable:t,args:n,allowFailure:!0,timeoutMs:1e4},r.signal)}export{n as createHarmonyInventory};
@@ -0,0 +1 @@
1
+ function e(e){return{discover:async()=>t(e)}}function t(e){return e.hostOs===`linux`?[{platform:`linux`,id:`local`,name:e.hostName,kind:`device`,target:`desktop`,booted:!0}]:[]}export{e as createLinuxInventory};
@@ -0,0 +1 @@
1
+ import{_ as e}from"./sdk-contracts.js";import t from"node:path";const n=`VirtualDevice`;function r(e){return{discover:async(t,n)=>await a(e,n)}}function i(e){return l(e).some(c)?[{platform:`vega`,id:n,name:`Vega Virtual Device (${n})`,kind:`emulator`,target:`tv`,booted:!0}]:[]}async function a(t,n){let r=await o(t);if(!r)throw new e(`TOOL_MISSING`,`Vega CLI not found in PATH`,{hint:`Install Vega Developer Tools, source ~/vega/env, and retry devices.`});let a=await t.commands.run({executable:r,args:[`device`,`list`],allowFailure:!0,timeoutMs:1e4},n.signal);s(a);let c=i(a.stdout),u=l(a.stdout);if(c.length===0&&u.length>0)throw new e(`DEVICE_NOT_FOUND`,`Vega CLI found devices, but no supported Vega Virtual Device is running.`,{listedSerials:u,hint:`Start the Vega Virtual Device, then retry with --platform vega --target tv.`});return c}async function o(e){let n=await e.commands.which(`vega`);if(n)return n;let r=t.join(e.homeDirectory,`vega`,`bin`,`vega`);return await e.files.isExecutable(r)?r:void 0}function s(t){if(t.exitCode!==0)throw new e(`COMMAND_FAILED`,`Failed to list Vega devices`,{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode,processExitError:!0})}function c(e){return e.toLowerCase()===`virtualdevice`}function l(e){let t=new Set;for(let n of e.split(/\r?\n/)){let e=/^\s*([^\s:]+)\s*:\s*\S/.exec(n)?.[1]?.trim();e&&t.add(e)}return[...t]}export{r as createVegaInventory};
@@ -0,0 +1 @@
1
+ import{s as e}from"./device.js";function t(){return{discover:async()=>[e]}}export{t as createWebInventory};
@@ -1 +1 @@
1
- import{wn as e}from"./sdk-batch-runner.js";import{vn as t}from"./viewport-dimension.js";function n(e){return t(e)}function r(t,r){let i=n(t),a=i.leaseId??r?.leaseId,o=i.tenantId??r?.tenantId,s=i.runId??r?.runId;if(!(!o||!s||!a))return e({tenantId:o,runId:s,leaseId:a,leaseBackend:i.leaseBackend??r?.backend,leaseProvider:i.leaseProvider??r?.leaseProvider,deviceKey:i.deviceKey??r?.deviceKey,clientId:i.clientId??r?.clientId,expiresAt:r?.expiresAt})}function i(t,r){let i=n(t),a=r?.lease??r?.deviceLease??void 0;return e({tenantId:i.tenantId??a?.tenantId,runId:i.runId??a?.runId,leaseId:i.leaseId??a?.leaseId,leaseTtlMs:i.leaseTtlMs,leaseBackend:i.leaseBackend??a?.leaseBackend,leaseProvider:i.leaseProvider??a?.leaseProvider,deviceKey:i.deviceKey??a?.deviceKey,clientId:i.clientId??a?.clientId})}function a(t){let n=t.meta,r=e({leaseId:o(n?.leaseId),clientId:o(n?.clientId),tenantId:o(n?.tenantId),runId:o(n?.runId),leaseProvider:o(n?.leaseProvider),deviceKey:o(n?.deviceKey)});return Object.keys(r).length>0?r:void 0}function o(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}export{a as i,n,i as r,r as t};
1
+ import{nr as e}from"./sdk-batch-runner.js";import{Sn as t}from"./prepare-kind.js";function n(e){return t(e)}function r(t,r){let i=n(t),a=i.leaseId??r?.leaseId,o=i.tenantId??r?.tenantId,s=i.runId??r?.runId;if(!(!o||!s||!a))return e({tenantId:o,runId:s,leaseId:a,leaseBackend:i.leaseBackend??r?.backend,leaseProvider:i.leaseProvider??r?.leaseProvider,deviceKey:i.deviceKey??r?.deviceKey,clientId:i.clientId??r?.clientId,expiresAt:r?.expiresAt})}function i(t,r){let i=n(t),a=r?.lease??r?.deviceLease??void 0;return e({tenantId:i.tenantId??a?.tenantId,runId:i.runId??a?.runId,leaseId:i.leaseId??a?.leaseId,leaseTtlMs:i.leaseTtlMs,leaseBackend:i.leaseBackend??a?.leaseBackend,leaseProvider:i.leaseProvider??a?.leaseProvider,deviceKey:i.deviceKey??a?.deviceKey,clientId:i.clientId??a?.clientId})}function a(t){let n=t.meta,r=e({leaseId:o(n?.leaseId),clientId:o(n?.clientId),tenantId:o(n?.tenantId),runId:o(n?.runId),leaseProvider:o(n?.leaseProvider),deviceKey:o(n?.deviceKey)});return Object.keys(r).length>0?r:void 0}function o(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}export{a as i,n,i as r,r as t};
package/dist/src/lease.js CHANGED
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{Kt as t,Sn as n,gn as r,wn as i,yn as a}from"./viewport-dimension.js";import{n as o,r as s}from"./lease-context.js";import{mn as c}from"./internal/daemon.js";async function l(e){let{req:r,sessionName:c,sessionStore:l,leaseRegistry:p,providerRuntimeIds:m,providerRuntimeRequiredIds:h,leaseLifecycleProvider:g,cloudArtifactProvider:_}=e,v=o(r);switch(r.command){case t.artifacts:return{ok:!0,data:await f(r,s(r,l.get(c)),_)};case`lease_allocate`:{d(v.leaseProvider,m,h);let e=p.allocateLease(a(v)),t;try{t=await g?.allocate?.(e,u(r))}catch(t){throw p.releaseLease(i({leaseId:e.leaseId,tenantId:e.tenantId,runId:e.runId,leaseBackend:e.backend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId})),t}return{ok:!0,data:{lease:e,...t?{provider:t}:{}}}}case`lease_heartbeat`:{let e=p.heartbeatLease(n(v)),t=await g?.heartbeat?.(e,u(r));return{ok:!0,data:{lease:e,...t?{provider:t}:{}}}}case`lease_release`:{let e=i(v),t=p.getLease(e),n=t?await g?.release?.(t,u(r)):void 0;return{ok:!0,data:{released:p.releaseLease(e).released,...n?{provider:n}:{}}}}default:return null}}function u(e){return{flags:e.flags,cwd:typeof e.meta?.cwd==`string`?e.meta.cwd:void 0}}function d(t,n,r){if(!(!t||n===void 0||r===void 0||!r.includes(t)||n.includes(t)))throw new e(`UNSUPPORTED_OPERATION`,`Provider "${t}" is not available in this daemon runtime.`,{provider:t,hint:`Restart the daemon with ${t} configured, then retry lease allocation.`})}async function f(e,t,n){let r=g(e.flags,`providerSessionId`);return p(t,r)?await m(t.tenantId):await h(t,r,n)}function p(e,t){return r(e)||!e.leaseProvider&&!t}async function m(e){let t=await c(e);return{source:`daemon`,status:`ready`,artifacts:t,...t.length===0?{message:`No daemon artifacts available.`}:{}}}async function h(t,n,r){if(!t.leaseProvider)throw new e(`INVALID_ARGS`,`artifacts requires --provider for provider session lookup or an active cloud connection.`);if(!t.leaseId&&!n)throw new e(`INVALID_ARGS`,`artifacts requires an active cloud lease or --provider-session <id>.`);let i=await r?.listCloudArtifacts?.({provider:t.leaseProvider,leaseId:t.leaseId,providerSessionId:n});if(!i)throw new e(`UNSUPPORTED_OPERATION`,`Cloud artifacts are not available for provider "${t.leaseProvider}".`);return i}function g(e,t){let n=e?.[t];return typeof n==`string`&&n.length>0?n:void 0}export{l as handleLeaseCommands};
1
+ import{_ as e}from"./sdk-contracts.js";import{Cn as t,En as n,On as r,Xt as i,bn as a}from"./prepare-kind.js";import{n as o,r as s}from"./lease-context.js";import{Tn as c}from"./internal/daemon.js";async function l(e){let{req:a,sessionName:c,sessionStore:l,leaseRegistry:p,providerRuntimeIds:m,providerRuntimeRequiredIds:h,leaseLifecycleProvider:g,cloudArtifactProvider:_}=e,v=o(a);switch(a.command){case i.artifacts:return{ok:!0,data:await f(a,s(a,l.get(c)),_)};case`lease_allocate`:{d(v.leaseProvider,m,h);let e=p.allocateLease(t(v)),n;try{n=await g?.allocate?.(e,u(a))}catch(t){throw p.releaseLease(r({leaseId:e.leaseId,tenantId:e.tenantId,runId:e.runId,leaseBackend:e.backend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId})),t}return{ok:!0,data:{lease:e,...n?{provider:n}:{}}}}case`lease_heartbeat`:{let e=p.heartbeatLease(n(v)),t=await g?.heartbeat?.(e,u(a));return{ok:!0,data:{lease:e,...t?{provider:t}:{}}}}case`lease_release`:{let e=r(v),t=p.getLease(e),n=t?await g?.release?.(t,u(a)):void 0;return{ok:!0,data:{released:p.releaseLease(e).released,...n?{provider:n}:{}}}}default:return null}}function u(e){return{flags:e.flags,cwd:typeof e.meta?.cwd==`string`?e.meta.cwd:void 0}}function d(t,n,r){if(!(!t||n===void 0||r===void 0||!r.includes(t)||n.includes(t)))throw new e(`UNSUPPORTED_OPERATION`,`Provider "${t}" is not available in this daemon runtime.`,{provider:t,hint:`Restart the daemon with ${t} configured, then retry lease allocation.`})}async function f(e,t,n){let r=g(e.flags,`providerSessionId`);return p(t,r)?await m(t.tenantId):await h(t,r,n)}function p(e,t){return a(e)||!e.leaseProvider&&!t}async function m(e){let t=await c(e);return{source:`daemon`,status:`ready`,artifacts:t,...t.length===0?{message:`No daemon artifacts available.`}:{}}}async function h(t,n,r){if(!t.leaseProvider)throw new e(`INVALID_ARGS`,`artifacts requires --provider for provider session lookup or an active cloud connection.`);if(!t.leaseId&&!n)throw new e(`INVALID_ARGS`,`artifacts requires an active cloud lease or --provider-session <id>.`);let i=await r?.listCloudArtifacts?.({provider:t.leaseProvider,leaseId:t.leaseId,providerSessionId:n});if(!i)throw new e(`UNSUPPORTED_OPERATION`,`Cloud artifacts are not available for provider "${t.leaseProvider}".`);return i}function g(e,t){let n=e?.[t];return typeof n==`string`&&n.length>0?n:void 0}export{l as handleLeaseCommands};
@@ -0,0 +1 @@
1
+ import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{n}from"./version.js";import{f as r,v as i}from"./sdk-android-adb.js";import{n as a}from"./android.js";var o=e({createLimrunRuntimeDependencies:()=>s});function s(){return{clientVersion:n(),android:{createInteractor:(e,t)=>a(e,t),createPortReverse:async e=>{let{createAndroidPortReverseManager:t}=await import(`./sdk-android-adb.js`).then(e=>e.t);return t(e)},inferAppName:async e=>{let{inferAndroidAppName:t}=await import(`./app-lifecycle.js`).then(e=>e.t);return t(e)},listApps:async(e,t)=>{let{listAndroidAppsWithAdb:n}=await import(`./app-helpers.js`).then(e=>e.t);return(await n(e,{filter:t,target:`mobile`})).map(e=>({id:e.package,name:e.name}))},getForegroundApp:async e=>{let{getAndroidAppStateWithAdb:t}=await import(`./app-helpers.js`).then(e=>e.t),n=await t(e);return n.package?{appId:n.package,activity:n.activity}:void 0},getKeyboardState:async e=>{let{getAndroidKeyboardStatusWithAdb:t}=await import(`./device-input-state.js`).then(e=>e.t);return await t(e)},dismissKeyboard:async e=>{let{dismissAndroidKeyboardWithAdb:t}=await import(`./device-input-state.js`).then(e=>e.t);return await t(e)},readLogs:async(e,t)=>{let{captureAndroidLogcatWithAdb:n}=await import(`./logcat.js`).then(e=>e.n);return await n(e,{lines:t,timeoutMs:5e3})},adbError:async(e,t,n)=>{let{androidAdbResultError:r}=await import(`./sdk-android-adb.js`).then(e=>e.t);return r(e,t,n)}},host:{runAdb:async(e,t)=>await i(`adb`,e,t),archiveDirectory:async({sourceDirectory:e,entryName:n,archivePath:a})=>{let o=[`-qr`,a,n],s=await i(`zip`,o,{cwd:e,timeoutMs:12e4});if(s.exitCode!==0)throw new t(`COMMAND_FAILED`,`Failed to package iOS .app for Limrun install`,{command:[`zip`,...o].join(` `),...r(s)})}},ios:{resolveAppAlias:async e=>{let{resolveIosAppAlias:t}=await import(`./app-resolution.js`).then(e=>e.t);return t(e)},readBundleAppName:async e=>{let{readIosBundleInfo:t}=await import(`./install-artifact2.js`).then(e=>e.t);return(await t(e)).appName}}}}export{o as n,s as t};
@@ -1,132 +1,12 @@
1
- import { B as DeviceTarget, D as Rect, E as RawSnapshotNode, H as PlatformSelector, R as DeviceInfo, T as Point, f as LeaseBackend, j as SnapshotOptions$1, k as SnapshotBackend } from "./sdk-contracts.js";
2
- import { c as ScrollDirection, o as GesturePlan, r as AndroidAdbProvider } from "./sdk-android-adb.js";
3
- import { a as BackendSnapshotResult, d as DeviceRotation, f as BackMode, l as SessionSurface, n as CloudArtifactProvider, u as TvRemoteButton } from "./cloud-artifacts.js";
1
+ import { B as DeviceTarget, H as PlatformSelector, R as DeviceInfo, f as LeaseBackend, z as DeviceKind } from "./sdk-contracts.js";
2
+ import { r as AndroidAdbProvider } from "./sdk-android-adb.js";
3
+ import { _ as Interactor, v as RunnerContext } from "./sdk-selectors.js";
4
4
  import { t as AppsFilter } from "./app-inventory.js";
5
+ import { n as CloudArtifactProvider } from "./cloud-artifacts.js";
5
6
  import { n as AndroidKeyboardState, s as AndroidInputOwner, t as AndroidKeyboardDismissResult } from "./device-input-state.js";
6
7
  import Limrun from "@limrun/api";
7
8
  import "@limrun/api/instance-client";
8
9
  import "@limrun/api/ios-client";
9
- //#region packages/contracts/src/settings.d.ts
10
- type SettingOptions = {
11
- permissionTarget?: string;
12
- permissionMode?: string;
13
- latitude?: number;
14
- longitude?: number;
15
- };
16
- //#endregion
17
- //#region packages/contracts/src/runner-lease-context.d.ts
18
- type RunnerLogicalLeaseContext = {
19
- leaseId?: string;
20
- clientId?: string;
21
- tenantId?: string;
22
- runId?: string;
23
- leaseProvider?: string;
24
- deviceKey?: string;
25
- };
26
- //#endregion
27
- //#region packages/contracts/src/interactor-types.d.ts
28
- type RunnerContext = {
29
- requestId?: string;
30
- signal?: AbortSignal;
31
- appBundleId?: string;
32
- verbose?: boolean;
33
- logPath?: string;
34
- traceLogPath?: string;
35
- iosXctestrunFile?: string;
36
- iosXctestDerivedDataPath?: string;
37
- iosXctestEnvDir?: string;
38
- runnerLeaseContext?: RunnerLogicalLeaseContext;
39
- };
40
- type ScreenshotOptions = {
41
- appBundleId?: string;
42
- pixelDensity?: number;
43
- fullscreen?: boolean;
44
- normalizeStatusBar?: boolean;
45
- stabilize?: boolean;
46
- surface?: SessionSurface;
47
- skipIosSimulatorBootCheck?: boolean;
48
- captureBackend?: 'runner';
49
- };
50
- type ElementSelectorKey = 'id' | 'label' | 'text' | 'value';
51
- type ElementSelectorTapOptions = {
52
- key: ElementSelectorKey;
53
- value: string;
54
- allowNonHittableCoordinateFallback?: boolean;
55
- expectedPoint?: Point;
56
- };
57
- /**
58
- * The channel the XCTest runner actually entered text through — the Swift
59
- * `TextEntryResult.textEntryRoute` (RunnerTests+TextTyping.swift,
60
- * RunnerTests+SynthesizedTextEntry.swift). Closed set, because the runner is
61
- * its only producer and the boundary that narrows it
62
- * (readTypeTextBackendResult, src/platforms/apple/interactions.ts) drops a
63
- * route it cannot name — so a Swift-side addition would silently vanish. The
64
- * route-parity test in src/platforms/apple/core/__tests__/interactions.test.ts
65
- * reads the Swift sources and fails instead.
66
- */
67
- declare const TEXT_ENTRY_ROUTES: readonly ['xctest-element', 'synthesized-first-responder', 'synthesized-first-responder-replacement', 'xctest-application-fallback'];
68
- type TextEntryRoute = (typeof TEXT_ENTRY_ROUTES)[number];
69
- /**
70
- * What `Interactor.type` reports back about the entry it performed. Only the
71
- * Apple runner populates it; every other platform types blind and returns void.
72
- */
73
- type TypeTextBackendResult = {
74
- textEntryRoute?: TextEntryRoute;
75
- };
76
- type SnapshotOptions = SnapshotOptions$1 & {
77
- appBundleId?: string;
78
- signal?: AbortSignal;
79
- includeRects?: boolean;
80
- includeHiddenContentHints?: boolean;
81
- surface?: SessionSurface;
82
- };
83
- type SnapshotResult = Omit<BackendSnapshotResult, 'backend' | 'nodes'> & {
84
- nodes?: RawSnapshotNode[];
85
- backend: Extract<SnapshotBackend, 'android' | 'xctest' | 'linux-atspi' | 'web'>;
86
- };
87
- type Interactor = {
88
- open(app: string, options?: {
89
- activity?: string;
90
- appBundleId?: string;
91
- launchConsole?: string;
92
- launchArgs?: string[];
93
- terminateRunningApp?: boolean;
94
- url?: string;
95
- }): Promise<void>;
96
- openDevice(): Promise<void>;
97
- close(app: string): Promise<void>;
98
- tap(x: number, y: number): Promise<Record<string, unknown> | void>;
99
- tapElementSelector?(selector: ElementSelectorTapOptions): Promise<Record<string, unknown> | void>;
100
- doubleTap(x: number, y: number): Promise<Record<string, unknown> | void>;
101
- longPress(x: number, y: number, durationMs?: number): Promise<Record<string, unknown> | void>;
102
- focus(x: number, y: number): Promise<Record<string, unknown> | void>;
103
- type(text: string, delayMs?: number): Promise<TypeTextBackendResult | void>;
104
- fillElementSelector?(selector: ElementSelectorTapOptions, text: string, delayMs?: number): Promise<Record<string, unknown> | void>;
105
- fill(x: number, y: number, text: string, delayMs?: number, options?: {
106
- allowNonHittableCoordinateFallback?: boolean;
107
- }): Promise<Record<string, unknown> | void>;
108
- scroll(direction: ScrollDirection, options?: {
109
- amount?: number;
110
- pixels?: number;
111
- durationMs?: number;
112
- }): Promise<Record<string, unknown> | void>;
113
- screenshot(outPath: string, options?: ScreenshotOptions): Promise<void>;
114
- setViewport?(width: number, height: number): Promise<Record<string, unknown> | void>;
115
- snapshot(options?: SnapshotOptions): Promise<SnapshotResult>;
116
- gestureViewport?(): Promise<Rect>;
117
- back(mode?: BackMode): Promise<void>;
118
- home(): Promise<void>;
119
- setOrientation(orientation: DeviceRotation): Promise<{
120
- orientation?: DeviceRotation;
121
- } | void>;
122
- performGesture?(plan: GesturePlan): Promise<Record<string, unknown> | void>;
123
- appSwitcher(): Promise<void>;
124
- tvRemote(button: TvRemoteButton, durationMs?: number): Promise<void>;
125
- readClipboard(): Promise<string>;
126
- writeClipboard(text: string): Promise<void>;
127
- setSetting(setting: string, state: string, appId?: string, options?: SettingOptions): Promise<Record<string, unknown> | void>;
128
- };
129
- //#endregion
130
10
  //#region packages/contracts/src/device-inventory.d.ts
131
11
  type DeviceInventoryRequest = {
132
12
  platform?: PlatformSelector;
@@ -140,7 +20,11 @@ type DeviceInventoryRequest = {
140
20
  clientId?: string;
141
21
  iosSimulatorSetPath?: string;
142
22
  androidSerialAllowlist?: string[];
23
+ /** Internal local-inventory projection filters; not public command grammar. */
24
+ kind?: DeviceKind;
25
+ booted?: boolean;
143
26
  };
27
+ type ProviderDeviceInventoryRequest = Omit<DeviceInventoryRequest, 'booted' | 'kind'>;
144
28
  //#endregion
145
29
  //#region packages/contracts/src/device-provider.d.ts
146
30
  type DeviceLease = {
@@ -164,7 +48,7 @@ type LeaseLifecycleProvider = {
164
48
  heartbeat?: (lease: DeviceLease, context?: LeaseLifecycleContext) => Promise<Record<string, unknown> | undefined>;
165
49
  release?: (lease: DeviceLease, context?: LeaseLifecycleContext) => Promise<Record<string, unknown> | undefined>;
166
50
  };
167
- type DeviceInventoryProvider = (request: DeviceInventoryRequest) => Promise<DeviceInfo[] | null | undefined>;
51
+ type DeviceInventoryProvider = (request: ProviderDeviceInventoryRequest, signal?: AbortSignal) => Promise<DeviceInfo[] | null | undefined>;
168
52
  //#endregion
169
53
  //#region packages/contracts/src/provider-device-runtime.d.ts
170
54
  type ProviderDeviceInstallResult = {
@@ -333,6 +217,7 @@ type LimrunIosDeviceSession = LimrunDeviceSessionBase & {
333
217
  type LimrunRuntimeOptions = {
334
218
  apiKey: string;
335
219
  region?: string;
220
+ runtimeInstance?: string;
336
221
  };
337
222
  //#endregion
338
223
  //#region src/sdk/limrun-runtime-types.d.ts
@@ -1 +1 @@
1
- import{t as e}from"./provider-limrun-runtime.js";export{e as LimrunRuntime};
1
+ import{i as e,r as t}from"./src.js";import{t as n}from"./limrun-runtime-dependencies.js";var r=class{implementation;provider=e;constructor(e){this.implementation=t(e,n())}get leaseLifecycle(){return this.implementation.leaseLifecycle}get recoverExpiredLease(){return this.implementation.recoverExpiredLease}get deviceInventoryProvider(){return this.implementation.deviceInventoryProvider}ownsDevice(e){return this.implementation.ownsDevice(e)}getInteractor(e){return this.implementation.getInteractor(e)}getDeviceSession(e){return this.implementation.getDeviceSession(e)}async installApp(e,t,n,r){return await this.implementation.installApp?.(e,t,n,r)}async installInstallablePath(e,t,n){return await this.implementation.installInstallablePath?.(e,t,n)}async configurePortReverse(e){return await this.implementation.configurePortReverse?.(e)}async shutdown(){await this.implementation.shutdown()}};export{r as LimrunRuntime};
package/dist/src/linux.js CHANGED
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{L as t}from"./screenshot-geometry.js";import{I as n}from"./sdk-android-adb.js";import{t as r}from"./snapshot.js";import{t as i}from"./tool-provider2.js";import{doubleClickLinux as a,fillLinux as o,focusLinux as s,longPressLinux as c,pressLinux as l,scrollLinux as u,sendKey as d,swipeLinux as f,typeLinux as p}from"./input-actions2.js";async function m(e){await i().desktop.openTarget(e)}async function h(e){await i().desktop.closeApp(e)}async function g(){await d(`alt+Left`,[`56:1`,`105:1`,`105:0`,`56:0`])}async function _(){await d(`super+d`,[`125:1`,`32:1`,`32:0`,`125:0`])}async function v(){return await i().clipboard.readText()}async function y(e){await i().clipboard.writeText(e)}async function b(e,t){await i().screenshot.capture(e,t)}function x(){return{open:e=>m(e),openDevice:()=>Promise.resolve(),close:e=>h(e),tap:(e,t)=>l(e,t),doubleTap:(e,t)=>a(e,t),longPress:(e,t,n)=>c(e,t,n),focus:(e,t)=>s(e,t),type:(e,t)=>p(e,t),fill:(e,t,n,r)=>o(e,t,n,r),scroll:(e,t)=>u(e,t),performGesture:async n=>{if(n.topology===`two`)throw new e(`UNSUPPORTED_OPERATION`,`Multi-touch gestures are not supported on Linux`);let{start:r,end:i}=t(n);await f(r.x,r.y,i.x,i.y,n.durationMs)},screenshot:(e,t)=>b(e,t),snapshot:async e=>{let t=await n(`snapshot_capture`,async()=>await r(e?.surface,e?.signal),{backend:`linux-atspi`});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:`linux-atspi`}},back:()=>g(),home:()=>_(),setOrientation:()=>{throw new e(`UNSUPPORTED_OPERATION`,`orientation not supported on Linux`)},appSwitcher:()=>{throw new e(`UNSUPPORTED_OPERATION`,`appSwitcher not yet supported on Linux`)},tvRemote:()=>{throw new e(`UNSUPPORTED_OPERATION`,`tv-remote not supported on Linux`)},readClipboard:()=>v(),writeClipboard:e=>y(e),setSetting:()=>{throw new e(`UNSUPPORTED_OPERATION`,`setSetting not supported on Linux`)}}}export{x as createLinuxInteractor};
1
+ import{_ as e}from"./sdk-contracts.js";import{B as t}from"./version.js";import{I as n}from"./sdk-android-adb.js";import{t as r}from"./snapshot.js";import{t as i}from"./tool-provider2.js";import{doubleClickLinux as a,fillLinux as o,focusLinux as s,longPressLinux as c,pressLinux as l,scrollLinux as u,sendKey as d,swipeLinux as f,typeLinux as p}from"./input-actions3.js";async function m(e){await i().desktop.openTarget(e)}async function h(e){await i().desktop.closeApp(e)}async function g(){await d(`alt+Left`,[`56:1`,`105:1`,`105:0`,`56:0`])}async function _(){await d(`super+d`,[`125:1`,`32:1`,`32:0`,`125:0`])}async function v(){return await i().clipboard.readText()}async function y(e){await i().clipboard.writeText(e)}async function b(e,t){await i().screenshot.capture(e,t)}function x(){return{open:e=>m(e),openDevice:()=>Promise.resolve(),close:e=>h(e),tap:(e,t)=>l(e,t),doubleTap:(e,t)=>a(e,t),longPress:(e,t,n)=>c(e,t,n),focus:(e,t)=>s(e,t),type:(e,t)=>p(e,t),fill:(e,t,n,r)=>o(e,t,n,r),scroll:(e,t)=>u(e,t),performGesture:async n=>{if(n.topology===`two`)throw new e(`UNSUPPORTED_OPERATION`,`Multi-touch gestures are not supported on Linux`);let{start:r,end:i}=t(n);await f(r.x,r.y,i.x,i.y,n.durationMs)},screenshot:(e,t)=>b(e,t),snapshot:async e=>{let t=await n(`snapshot_capture`,async()=>await r(e?.surface,e?.signal),{backend:`linux-atspi`});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:`linux-atspi`}},back:()=>g(),home:()=>_(),setOrientation:()=>{throw new e(`UNSUPPORTED_OPERATION`,`orientation not supported on Linux`)},appSwitcher:()=>{throw new e(`UNSUPPORTED_OPERATION`,`appSwitcher not yet supported on Linux`)},tvRemote:()=>{throw new e(`UNSUPPORTED_OPERATION`,`tv-remote not supported on Linux`)},readClipboard:()=>v(),writeClipboard:e=>y(e),setSetting:()=>{throw new e(`UNSUPPORTED_OPERATION`,`setSetting not supported on Linux`)}}}export{x as createLinuxInteractor};
@@ -1 +1 @@
1
- import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{n}from"./sdk-android-adb.js";import"node:fs";var r=e({captureAndroidLogcatWithAdb:()=>i,streamAndroidLogcatWithAdb:()=>a});async function i(e,t={}){let r=[`logcat`,`-d`,`-v`,`time`];t.lines!==void 0&&r.push(`-t`,String(Math.max(1,Math.floor(t.lines))));let i=await e(r,{allowFailure:!0,timeoutMs:t.timeoutMs,signal:t.signal});if(i.exitCode!==0)throw n(`Failed to capture Android logcat`,i);return i.stdout}function a(e,n={}){if(!e.spawn)throw new t(`UNSUPPORTED_OPERATION`,`Android ADB provider does not support streams`,{capability:`adb.spawn`});let r=[`logcat`,`-v`,`time`];n.pid&&r.push(`--pid`,n.pid);let i=e.spawn(r,{stdio:[`ignore`,`pipe`,`pipe`],signal:n.signal});return n.output&&i.stdout&&i.stdout.pipe(n.output,{end:!1}),i}export{r as n,a as r,i as t};
1
+ import{o as e}from"./png-worker-contract.js";import{n as t}from"./sdk-android-adb.js";import"node:fs";var n=e({captureAndroidLogcatWithAdb:()=>r});async function r(e,n={}){let r=[`logcat`,`-d`,`-v`,`time`];n.lines!==void 0&&r.push(`-t`,String(Math.max(1,Math.floor(n.lines))));let i=await e(r,{allowFailure:!0,timeoutMs:n.timeoutMs,signal:n.signal});if(i.exitCode!==0)throw t(`Failed to capture Android logcat`,i);return i.stdout}export{n,r as t};
@@ -1 +1 @@
1
- import{m as e,v as t}from"./sdk-android-adb.js";import n from"node:path";import{TextDecoder as r}from"node:util";import{promises as i}from"node:fs";import a from"node:os";import o from"node:fs/promises";const s=[`emulator`,`platform-tools`,n.join(`cmdline-tools`,`latest`,`bin`),n.join(`cmdline-tools`,`tools`,`bin`)];function c(e){let t=new Set,n=[];for(let r of e){let e=r.trim();!e||t.has(e)||(t.add(e),n.push(e))}return n}function l(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),i=e.HOME?.trim()||a.homedir(),o=i?n.join(i,`Android`,`Sdk`):``;return c([t??``,r??``,o])}async function u(e){try{return await i.access(e,i.constants.X_OK),!0}catch{return!1}}async function d(e=process.env){let t=[],r;for(let i of l(e)){let e=[];for(let t of s){let r=n.join(i,t);await u(r)&&e.push(r)}e.length!==0&&(r||=i,t.push(...e))}if(r&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||r,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||r),t.length===0)return;let i=(e.PATH??``).split(n.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=c([...t,...i]).join(n.delimiter)}const f=new r(`utf-16le`);let p;async function m(e){for(let t of[`AndroidManifest.xml`,`base/manifest/AndroidManifest.xml`]){let n=await h(e,t);if(!n)continue;let r=g(n);if(r)return r}return await T(e)}async function h(e,n){try{let r=await t(`unzip`,[`-p`,e,n],{allowFailure:!0,binaryStdout:!0});return r.exitCode!==0||!r.stdoutBuffer||r.stdoutBuffer.length===0?void 0:r.stdoutBuffer}catch{return}}function g(e){return e.subarray(0,Math.min(e.length,128)).toString(`utf8`).trimStart().startsWith(`<`)?_(e.toString(`utf8`)):v(e)}function _(e){return e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i)?.[1]}function v(e){if(e.length<8||e.readUInt16LE(0)!==3)return;let t;for(let n=e.readUInt16LE(2);n+8<=e.length;){let r=e.readUInt16LE(n),i=e.readUInt16LE(n+2),a=e.readUInt32LE(n+4);if(a<=0||n+a>e.length)return;if(r===1)t=b(e.subarray(n,n+a));else if(r===258&&t){let r=y(e,n,i,t);if(r)return r}n+=a}}function y(e,t,n,r){if(n<36||t+n>e.length||r[e.readUInt32LE(t+20)]!==`manifest`)return;let i=e.readUInt16LE(t+24),a=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let n=s+t*a;if(n+20>e.length)return;if(r[e.readUInt32LE(n+4)]!==`package`)continue;let i=e.readUInt32LE(n+8);if(i!==4294967295)return r[i];let o=e.readUInt8(n+15),c=e.readUInt32LE(n+16);return o===3?r[c]:void 0}}function b(e){if(e.length<28)return[];let t=e.readUInt32LE(8),n=e.readUInt32LE(16),r=e.readUInt32LE(20),i=(n&256)!=0,a=[];for(let n=0;n<t;n+=1){let t=28+n*4;if(t+4>e.length)return a;let o=r+e.readUInt32LE(t);a.push(i?x(e,o):S(e,o))}return a}function x(e,t){let[,n]=C(e,t),[r,i]=C(e,t+n),a=t+n+i;return e.subarray(a,a+r).toString(`utf8`)}function S(e,t){let[n,r]=w(e,t),i=t+r;return f.decode(e.subarray(i,i+n*2))}function C(e,t){let n=e.readUInt8(t);if(!(n&128))return[n,1];let r=e.readUInt8(t+1);return[(n&127)<<8|r,2]}function w(e,t){let n=e.readUInt16LE(t);if(!(n&32768))return[n,2];let r=e.readUInt16LE(t+2);return[(n&32767)<<16|r,4]}async function T(e){let n=await E();if(!n)return;let r=await t(n,[`dump`,`badging`,e],{allowFailure:!0});if(r.exitCode===0)return r.stdout.match(/package:\s+name='([^']+)'/)?.[1]}async function E(){if(p!==void 0)return p??void 0;try{for(let t of l()){let r=n.join(t,`build-tools`);try{let t=(await o.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(let i of t){let t=n.join(r,i,`aapt`);if(n.isAbsolute(t)&&await e(t))return p=t,t}}catch{}}}catch{}p=null}export{d as n,m as t};
1
+ import{o as e}from"./png-worker-contract.js";import{m as t,v as n}from"./sdk-android-adb.js";import r from"node:path";import{TextDecoder as i}from"node:util";import{promises as a}from"node:fs";import o from"node:os";import s from"node:fs/promises";var c=e({ensureAndroidSdkPathConfigured:()=>p,resolveAndroidSdkRoots:()=>d});const l=[`emulator`,`platform-tools`,r.join(`cmdline-tools`,`latest`,`bin`),r.join(`cmdline-tools`,`tools`,`bin`)];function u(e){let t=new Set,n=[];for(let r of e){let e=r.trim();!e||t.has(e)||(t.add(e),n.push(e))}return n}function d(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),n=e.ANDROID_HOME?.trim(),i=e.HOME?.trim()||o.homedir(),a=i?r.join(i,`Android`,`Sdk`):``;return u([t??``,n??``,a])}async function f(e){try{return await a.access(e,a.constants.X_OK),!0}catch{return!1}}async function p(e=process.env){let t=[],n;for(let i of d(e)){let e=[];for(let t of l){let n=r.join(i,t);await f(n)&&e.push(n)}e.length!==0&&(n||=i,t.push(...e))}if(n&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||n,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||n),t.length===0)return;let i=(e.PATH??``).split(r.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=u([...t,...i]).join(r.delimiter)}const m=new i(`utf-16le`);let h;async function g(e){for(let t of[`AndroidManifest.xml`,`base/manifest/AndroidManifest.xml`]){let n=await _(e,t);if(!n)continue;let r=v(n);if(r)return r}return await D(e)}async function _(e,t){try{let r=await n(`unzip`,[`-p`,e,t],{allowFailure:!0,binaryStdout:!0});return r.exitCode!==0||!r.stdoutBuffer||r.stdoutBuffer.length===0?void 0:r.stdoutBuffer}catch{return}}function v(e){return e.subarray(0,Math.min(e.length,128)).toString(`utf8`).trimStart().startsWith(`<`)?y(e.toString(`utf8`)):b(e)}function y(e){return e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i)?.[1]}function b(e){if(e.length<8||e.readUInt16LE(0)!==3)return;let t;for(let n=e.readUInt16LE(2);n+8<=e.length;){let r=e.readUInt16LE(n),i=e.readUInt16LE(n+2),a=e.readUInt32LE(n+4);if(a<=0||n+a>e.length)return;if(r===1)t=S(e.subarray(n,n+a));else if(r===258&&t){let r=x(e,n,i,t);if(r)return r}n+=a}}function x(e,t,n,r){if(n<36||t+n>e.length||r[e.readUInt32LE(t+20)]!==`manifest`)return;let i=e.readUInt16LE(t+24),a=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let n=s+t*a;if(n+20>e.length)return;if(r[e.readUInt32LE(n+4)]!==`package`)continue;let i=e.readUInt32LE(n+8);if(i!==4294967295)return r[i];let o=e.readUInt8(n+15),c=e.readUInt32LE(n+16);return o===3?r[c]:void 0}}function S(e){if(e.length<28)return[];let t=e.readUInt32LE(8),n=e.readUInt32LE(16),r=e.readUInt32LE(20),i=(n&256)!=0,a=[];for(let n=0;n<t;n+=1){let t=28+n*4;if(t+4>e.length)return a;let o=r+e.readUInt32LE(t);a.push(i?C(e,o):w(e,o))}return a}function C(e,t){let[,n]=T(e,t),[r,i]=T(e,t+n),a=t+n+i;return e.subarray(a,a+r).toString(`utf8`)}function w(e,t){let[n,r]=E(e,t),i=t+r;return m.decode(e.subarray(i,i+n*2))}function T(e,t){let n=e.readUInt8(t);if(!(n&128))return[n,1];let r=e.readUInt8(t+1);return[(n&127)<<8|r,2]}function E(e,t){let n=e.readUInt16LE(t);if(!(n&32768))return[n,2];let r=e.readUInt16LE(t+2);return[(n&32767)<<16|r,4]}async function D(e){let t=await O();if(!t)return;let r=await n(t,[`dump`,`badging`,e],{allowFailure:!0});if(r.exitCode===0)return r.stdout.match(/package:\s+name='([^']+)'/)?.[1]}async function O(){if(h!==void 0)return h??void 0;try{for(let e of d()){let n=r.join(e,`build-tools`);try{let e=(await s.readdir(n)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(let i of e){let e=r.join(n,i,`aapt`);if(r.isAbsolute(e)&&await t(e))return h=e,e}}catch{}}}catch{}h=null}export{p as n,c as r,g as t};
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{a as t}from"./install-artifact.js";async function n(n,i,a){let o=typeof a.action==`string`&&a.action.trim()?a.action.trim():`${i}.TEST_PUSH`,s=[`shell`,`am`,`broadcast`,`-a`,o,`-p`,i],c=typeof a.receiver==`string`?a.receiver.trim():``;c&&s.push(`-n`,c);let l=a.extras;if(l!==void 0&&(typeof l!=`object`||!l||Array.isArray(l)))throw new e(`INVALID_ARGS`,`Android push payload extras must be an object`);let u=l??{},d=0;for(let[e,t]of Object.entries(u))e&&(r(s,e,t),d+=1);return await t(n,s),{action:o,extrasCount:d}}function r(t,n,r){if(typeof r==`string`){t.push(`--es`,n,r);return}if(typeof r==`boolean`){t.push(`--ez`,n,r?`true`:`false`);return}if(typeof r==`number`&&Number.isFinite(r)){if(Number.isInteger(r)){t.push(`--ei`,n,String(r));return}t.push(`--ef`,n,String(r));return}throw new e(`INVALID_ARGS`,`Unsupported Android broadcast extra type for "${n}". Use string, boolean, or number.`)}export{n as pushAndroidNotification};
1
+ import{_ as e}from"./sdk-contracts.js";import{i as t}from"./install-artifact.js";async function n(n,i,a){let o=typeof a.action==`string`&&a.action.trim()?a.action.trim():`${i}.TEST_PUSH`,s=[`shell`,`am`,`broadcast`,`-a`,o,`-p`,i],c=typeof a.receiver==`string`?a.receiver.trim():``;c&&s.push(`-n`,c);let l=a.extras;if(l!==void 0&&(typeof l!=`object`||!l||Array.isArray(l)))throw new e(`INVALID_ARGS`,`Android push payload extras must be an object`);let u=l??{},d=0;for(let[e,t]of Object.entries(u))e&&(r(s,e,t),d+=1);return await t(n,s),{action:o,extrasCount:d}}function r(t,n,r){if(typeof r==`string`){t.push(`--es`,n,r);return}if(typeof r==`boolean`){t.push(`--ez`,n,r?`true`:`false`);return}if(typeof r==`number`&&Number.isFinite(r)){if(Number.isInteger(r)){t.push(`--ei`,n,String(r));return}t.push(`--ef`,n,String(r));return}throw new e(`INVALID_ARGS`,`Unsupported Android broadcast extra type for "${n}". Use string, boolean, or number.`)}export{n as pushAndroidNotification};
@@ -0,0 +1 @@
1
+ import{n as e}from"./path-resolution.js";import t from"node:path";const n=`.webm`;function r(e){return e===`web`?n:`.mp4`}function i(e,n){return t.extname(e)?e:`${e}${n}`}function a(e){return`./recording-${Date.now()}${r(e)}`}function o(t){let r=t.requestedPath===void 0?a(t.platform):t.platform===`web`?i(t.requestedPath,n):t.requestedPath;return Object.freeze({requestedPath:r,outputPath:e(r,{cwd:t.cwd})})}export{o as i,a as n,r,i as t};
@@ -0,0 +1 @@
1
+ import{c as e,i as t,n}from"./host-process.js";import r from"node:fs";function i(){return{pid:process.pid,startTime:e(process.pid)}}function a(e,t){return e.pid===t.pid&&e.startTime===t.startTime}function o(e){return s(e)}function s(i,a){let{owner:o,stateDir:s}=i;if(!n(o.pid)||(a===void 0?t(o.pid):a?.state.startsWith(`Z`)))return`owner-process-dead`;if(o.startTime){let t=a===void 0?e(o.pid):a?.startTime??null;if(t!==null&&t!==o.startTime)return`owner-process-dead`}if(!s)return`live`;try{return r.statSync(s),`live`}catch(e){let t=e?.code;return t===`ENOENT`||t===`ENOTDIR`?`owner-state-dir-gone`:`unknown`}}export{i,s as n,a as r,o as t};
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{c as t,g as n,o as r,s as i}from"./sdk-device.js";import{C as a,j as o,p as s}from"./sdk-android-adb.js";import{n as c,t as ee}from"./version.js";import{c as te,o as ne,s as re}from"./boot-diagnostics.js";import{a as l,s as ie}from"./tool-provider.js";import u from"node:path";import d from"node:crypto";import f,{promises as p}from"node:fs";import m from"node:os";function h(e,t={}){let n=ne(t.simulatorSetPath);return n?[`simctl`,`--set`,n,...e]:[`simctl`,...e]}function g(e,t){return!i(e)||e.kind!==`simulator`?[`simctl`,...t]:h(t,{simulatorSetPath:e.simulatorSetPath})}function ae(e,t,n){return l(g(e,t),n)}const _={iOS:{sdkName:{simulator:`iphonesimulator`,device:`iphoneos`},derivedBaseName:{simulator:`ios-simulator`,device:`ios-device`},xctestrunHints:{simulator:{preferred:[`iphonesimulator`],disallowed:[`iphoneos`,`appletvos`,`appletvsimulator`,`macos`]},device:{preferred:[`iphoneos`],disallowed:[`iphonesimulator`,`appletvos`,`appletvsimulator`,`macos`]}}},tvOS:{sdkName:{simulator:`appletvsimulator`,device:`appletvos`},derivedBaseName:{simulator:`tvos-simulator`,device:`tvos-device`},xctestrunHints:{simulator:{preferred:[`appletvsimulator`],disallowed:[`appletvos`,`iphoneos`,`iphonesimulator`,`macos`]},device:{preferred:[`appletvos`],disallowed:[`appletvsimulator`,`iphoneos`,`iphonesimulator`,`macos`]}}},macOS:{sdkName:{simulator:`macosx`,device:`macosx`},derivedBaseName:{simulator:`macos`,device:`macos`},xctestrunHints:{simulator:{preferred:[`macos`],disallowed:[`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`]},device:{preferred:[`macos`],disallowed:[`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`]}}},visionOS:{sdkName:{simulator:`xrsimulator`,device:`xros`},derivedBaseName:{simulator:`visionos-simulator`,device:`visionos-device`},xctestrunHints:{simulator:{preferred:[`xrsimulator`],disallowed:[`xros`,`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`,`macos`]},device:{preferred:[`xros`],disallowed:[`xrsimulator`,`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`,`macos`]}}}};function v(i){if(!r(i.platform))throw new e(`UNSUPPORTED_PLATFORM`,`Unsupported platform for Apple runner: ${i.platform}`);return t(i)?`macOS`:n(i.target,i.appleOs)}function oe(e,t){return _[e].sdkName[y(t)]}function se(e){return _[v(e)].derivedBaseName[y(e.kind)]}function ce(e){return _[v(e)].xctestrunHints[y(e.kind)]}function le(e){let t=v(e);return t===`macOS`?`platform=macOS,arch=${b()}`:e.kind===`simulator`?`platform=${t} Simulator,id=${e.id}`:`platform=${t},id=${e.id}`}function ue(e){let t=v(e);return t===`macOS`?`platform=macOS,arch=${b()}`:e.kind===`simulator`?`platform=${t} Simulator,id=${e.id}`:`generic/platform=${t}`}function de(e){let t=v(e);return t===`macOS`?`platform=macOS,arch=${b()}`:e.kind===`simulator`?`generic/platform=${t} Simulator`:`generic/platform=${t}`}function y(e){return e===`simulator`?`simulator`:`device`}function b(){return process.arch===`arm64`?`arm64`:`x86_64`}const fe=new Set;function x(e={}){let t=new Map,n=e.now??(()=>Date.now()),r=e=>{e?.timer&&clearTimeout(e.timer)},i={get(e){let r=t.get(e);if(r){if(r.expiresAt!==void 0&&r.expiresAt<=n()){i.delete(e);return}return r.value}},set(i,a){r(t.get(i));let o=pe(e.ttlMs,n),s={value:a,expiresAt:o};e.scheduleExpiry&&o!==void 0&&(s.timer=setTimeout(()=>{t.delete(i)},Math.max(0,o-n())),s.timer.unref?.()),t.set(i,s)},delete(e){let n=t.get(e);return n?(r(n),t.delete(e)):!1},clear(){for(let e of t.values())r(e);t.clear()}};return fe.add(i.clear),i}function pe(e,t){if(!(e===void 0||!Number.isFinite(e)))return t()+Math.max(0,e)}const me=u.join(`apple`,`runner`,`AgentDeviceRunner`),he=u.join(`dist`,`apple`,`runner`,`AgentDeviceRunner`);function S(e){let t=u.join(e,me);return f.existsSync(t)?t:u.join(e,he)}function ge(e){return u.join(S(e),`AgentDeviceRunner.xcodeproj`)}const _e=u.join(m.homedir(),`.agent-device`,`apple-runner`),ve=`.agent-device-runner-cache.json`,ye=[`-IDEPackageSupportDisableManifestSandbox=1`,`-IDEPackageSupportDisablePluginExecutionSandbox=1`,`ENABLE_USER_SCRIPT_SANDBOXING=NO`],C=x();function w(e){return e?.trim()??``}function T(e=process.env){return w(e.AGENT_DEVICE_IOS_BUNDLE_ID)||w(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||`com.callstack.agentdevice.runner`}function E(e=process.env){return w(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID)||`${T(e)}.uitests`}function be(e=process.env){let t=T(e),n=E(e);return Array.from(new Set([w(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${n}.xctrunner`,t].filter(e=>e.length>0)))}const D=be(process.env);function xe(e,t=ee()){let n=v(e);return{schemaVersion:2,packageVersion:c(t),runnerSourceFingerprint:Oe(t),...Se(n,e.kind),platformName:n,deviceKind:e.kind,target:e.target??`mobile`,buildDestinationFamily:de(e),runnerBundleBuildSettings:N(process.env),runnerSigningBuildSettings:M(process.env,e.kind===`device`,e),runnerPerformanceBuildSettings:P(),runnerSandboxBuildArgs:F()}}function Se(e,t){let n=Ce(O(`xcodebuild`,[`-version`])),r=oe(e,t);return{xcodeVersion:n.version,xcodeBuildVersion:n.buildVersion,sdkName:r,sdkVersion:O(`xcrun`,[`--sdk`,r,`--show-sdk-version`]),sdkBuildVersion:O(`xcrun`,[`--sdk`,r,`--show-sdk-build-version`])}}function O(e,t){let n=JSON.stringify([e,t]),r=C.get(n);if(r!==void 0)return r;try{let r=a(e,t,{allowFailure:!0,timeoutMs:5e3,maxBuffer:128*1024}),i=r.exitCode===0&&r.stdout.trim()||`unknown`;return C.set(n,i),i}catch{return C.set(n,`unknown`),`unknown`}}function Ce(e){return{version:e.match(/^Xcode\s+(.+)$/m)?.[1]?.trim()||`unknown`,buildVersion:e.match(/^Build version\s+(.+)$/m)?.[1]?.trim()||`unknown`}}function we(e,t){let n=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim();if(n)return u.resolve(n);let r=Ee(t),i=Te(e);return u.join(i,r)}function Te(e){return u.join(_e,`derived`,se(e))}function Ee(e){return`cache-${d.createHash(`sha256`).update(De(k(e))).digest(`hex`).slice(0,16)}`}function k(e){let{artifacts:t,packageVersion:n,...r}=e;return r}function De(e){return JSON.stringify(A(e))}function A(e){return Array.isArray(e)?e.map(e=>A(e)):!e||typeof e!=`object`?e:Object.fromEntries(Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,A(t)]))}const j=new Map;function Oe(e){let t=S(e),n=Ae(t),r=ke(t,n),i=j.get(t);if(i?.fileStatsFingerprint===r)return i.sourceFingerprint;let a=d.createHash(`sha256`);for(let e of n){let n=u.relative(t,e);a.update(n),a.update(`\0`),a.update(f.readFileSync(e)),a.update(`\0`)}let o=a.digest(`hex`);return j.set(t,{fileStatsFingerprint:r,sourceFingerprint:o}),o}function ke(e,t){let n=d.createHash(`sha256`);for(let r of t){let t=u.relative(e,r),i=f.statSync(r);n.update(t),n.update(`\0`),n.update(String(i.size)),n.update(`\0`),n.update(String(Math.trunc(i.mtimeMs))),n.update(`\0`)}return n.digest(`hex`)}function Ae(e){if(!f.existsSync(e))return[];let t=[],n=[e];for(;n.length>0;){let e=n.pop();for(let r of f.readdirSync(e,{withFileTypes:!0})){let i=u.join(e,r.name);if(r.isDirectory()){if(r.name===`xcuserdata`)continue;n.push(i);continue}r.isFile()&&je(r.name,i)&&t.push(i)}}return t.sort((e,t)=>e.localeCompare(t))}function je(e,t){return e===`project.pbxproj`?t.includes(`${u.sep}.xcodeproj${u.sep}`):[`.jpg`,`.json`,`.png`,`.swift`,`.m`,`.h`,`.plist`,`.entitlements`,`.xctestplan`,`.xcconfig`,`.storyboard`,`.xib`].includes(u.extname(e))}function Me(e){return t(e)||e.kind===`device`?`-maximum-concurrent-test-device-destinations`:`-maximum-concurrent-test-simulator-destinations`}function M(e=process.env,n=!1,r={platform:`apple`}){if(t(r))return[`CODE_SIGNING_ALLOWED=NO`,`CODE_SIGNING_REQUIRED=NO`,`CODE_SIGN_IDENTITY=`,`DEVELOPMENT_TEAM=`];if(!n)return[];let i=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||``,a=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||``,o=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||``,s=[`CODE_SIGN_STYLE=Automatic`];return i&&s.push(`DEVELOPMENT_TEAM=${i}`),a&&s.push(`CODE_SIGN_IDENTITY=${a}`),o&&s.push(`PROVISIONING_PROFILE_SPECIFIER=${o}`),s}function N(e=process.env){let t=T(e),n=E(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${n}`]}function P(){return[`COMPILER_INDEX_STORE_ENABLE=NO`,`ENABLE_CODE_COVERAGE=NO`,`ONLY_ACTIVE_ARCH=YES`,`ENABLE_PREVIEWS=NO`,`ENABLE_DEBUG_DYLIB=NO`]}function F(){return[...ye,`OTHER_SWIFT_FLAGS=${Ne(process.env)}`]}function Ne(e){return te(e.AGENT_DEVICE_XCUITEST_INCLUDE_UNIT_TESTS)?`$(inherited) -disable-sandbox -D AGENT_DEVICE_RUNNER_UNIT_TESTS`:`$(inherited) -disable-sandbox`}const Pe=18e4,Fe=6e4,Ie=6e4,Le=1e4,Re=15e3,ze=2e4,Be=15e3,I=2e4,Ve=1e3,He=5e3;async function L(t,n,r={}){let i=[`devicectl`,...t],a=await l(i,{allowFailure:!0,timeoutMs:r.timeoutMs??2e4});if(a.exitCode===0)return;let{stdout:o,stderr:c}=a;if(!r.tolerateOutput?.(o,c))throw new e(`COMMAND_FAILED`,`Failed to ${n.action}`,s(a,{cmd:`xcrun`,args:i,stdout:o,stderr:c,deviceId:n.deviceId,hint:G(o,c)??`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`}))}async function R(e,t){return Ye(qe(await B(e,{jsonPrefix:`agent-device-ios-apps`,args:[`devicectl`,`device`,`info`,`apps`,`--device`,e.id,`--include-all-apps`],failureMessage:`Failed to list iOS apps`,parseFailureMessage:`Failed to parse iOS apps list`})),t)}async function Ue(t){let n=await B(t,{jsonPrefix:`agent-device-ios-processes`,args:[`devicectl`,`device`,`info`,`processes`,`--device`,t.id],failureMessage:`Failed to list iOS processes`,parseFailureMessage:`Failed to parse iOS process list`,fallbackHint:W});if(!Ge(n))throw new e(`COMMAND_FAILED`,`Unsupported iOS process list response`,{deviceId:t.id,hint:W});return Je(n)}async function We(e,t){let{appBundleUrl:n,processes:r}=await z(e,t),i=r.sort((e,t)=>H(e,n)-H(t,n))[0];i&&await B(e,{jsonPrefix:`agent-device-ios-process-terminate`,args:[`devicectl`,`device`,`process`,`terminate`,`--device`,e.id,`--pid`,String(i.pid),`--kill`],failureMessage:`Failed to terminate iOS app`,parseFailureMessage:`Failed to parse iOS process termination response`,tolerateFailurePayload:Ke})}async function z(t,n){let r=(await R(t,`all`)).find(e=>e.bundleId===n);if(!r)throw new e(`APP_NOT_INSTALLED`,`No iOS device app found for ${n}`,{appBundleId:n,deviceId:t.id});if(!r.url)throw new e(`COMMAND_FAILED`,`Missing app bundle URL for ${n}`,{appBundleId:n,deviceId:t.id,hint:`Installed-app metadata from devicectl did not include the bundle URL required to match running processes. Use an Xcode/CoreDevice toolchain that reports app URLs.`});let i=r.url.replace(/\/+$/,``);return{appBundleUrl:i,processes:(await Ue(t)).filter(e=>e.executable.startsWith(`${i}/`))}}async function B(t,n){let r=u.join(m.tmpdir(),`${n.jsonPrefix}-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),i=[...n.args,`--json-output`,r],a=await l(i,{allowFailure:!0,timeoutMs:2e4});try{if(a.exitCode!==0){let{stdout:o,stderr:c}=a;if(n.tolerateFailurePayload){let e=await V(r).catch(()=>void 0);if(e!==void 0&&n.tolerateFailurePayload(e))return e}throw new e(`COMMAND_FAILED`,n.failureMessage,s(a,{cmd:`xcrun`,args:i,stdout:o,stderr:c,deviceId:t.id,hint:G(o,c)??n.fallbackHint??`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`}))}return await V(r)}catch(r){throw r instanceof e?r:new e(`COMMAND_FAILED`,n.parseFailureMessage,{deviceId:t.id,cause:String(r)})}finally{await p.unlink(r).catch(()=>{})}}async function V(e){return JSON.parse(await p.readFile(e,`utf8`))}function H(e,t){return e.executable.slice(t.length+1).split(`/`).length}function Ge(e){return Array.isArray(e?.result?.runningProcesses)}function Ke(e){let t=e?.error?.userInfo?.NSUnderlyingError?.error;return t?.domain===`NSPOSIXErrorDomain`&&t.code===3}function qe(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=typeof e.bundleIdentifier==`string`?e.bundleIdentifier.trim():``;if(!t)continue;let r=typeof e.name==`string`&&e.name.trim().length>0?e.name.trim():t,i=typeof e.url==`string`&&e.url.trim().length>0?e.url.trim():void 0;n.push({bundleId:t,name:r,url:i})}return n}function Je(e){let t=e?.result?.runningProcesses;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=typeof e.executable==`string`?e.executable.trim():``,r=typeof e.processIdentifier==`number`&&Number.isFinite(e.processIdentifier)?e.processIdentifier:NaN;!t||!Number.isFinite(r)||n.push({executable:t,pid:r})}return n}function Ye(e,t){return ie(e,t)}const U=`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`,W=`This Xcode/CoreDevice toolchain must support 'devicectl device info processes' with JSON runningProcesses so agent-device can resolve app process IDs. Inspect diagnostics for the exact devicectl API failure.`;function G(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`device is busy`)&&n.includes(`connecting`)?`iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.`:n.includes(`coredeviceservice`)&&n.includes(`timed out`)?`CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.`:n.includes(`developer disk image`)||n.includes(`developer mode is disabled`)?`Enable Developer Mode on the iOS device (Settings > Privacy & Security > Developer Mode), restart it when prompted, unlock it, then retry.`:n.includes(`must be paired`)?`Pair the iOS device with this Mac: connect it by cable, unlock it, accept the Trust prompt, and enter the device passcode, then retry.`:null}function K(e,t){return g(e,t)}function Xe(e,t,n){return l(K(e,t),n)}function q(e){return e.includes(`not installed`)||e.includes(`not found`)||e.includes(`no such file`)}async function Ze(e,t){return await R(e,t)}async function Qe(e,t){await L([`device`,`install`,`app`,`--device`,e.id,t],{action:`install iOS app`,deviceId:e.id},{timeoutMs:12e4})}async function $e(e,t){await L([`device`,`uninstall`,`app`,`--device`,e.id,t],{action:`uninstall iOS app ${t}`,deviceId:e.id},{tolerateOutput:(e,t)=>q(`${e}\n${t}`.toLowerCase())})}async function et(e,t){await We(e,t)}async function tt(e,t){return await z(e,t)}const J=1e4;async function nt(e,t,n={}){let r=[`device`,`process`,`launch`,`--device`,e.id,t];n.payloadUrl&&r.push(`--payload-url`,n.payloadUrl),n.launchArgs&&n.launchArgs.length>0&&r.push(`--`,...n.launchArgs),await L(r,{action:`launch iOS app`,deviceId:e.id})}async function rt(t){try{let{result:n,parsed:r}=await Y(t.id,15e3,3e3);if(n.exitCode===0){if(!r.parsed)throw new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{kind:`probe_inconclusive`,deviceId:t.id,stdout:n.stdout,stderr:n.stderr,hint:`CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device.`});let i=r.tunnelState?.toLowerCase();if(i===`connecting`)throw new e(`COMMAND_FAILED`,`iOS device is not ready for automation`,{kind:`not_ready`,deviceId:t.id,tunnelState:i,hint:`Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry.`});return}throw new e(`COMMAND_FAILED`,`iOS device is not ready for automation`,s(n,{kind:`not_ready`,deviceId:t.id,tunnelState:r.tunnelState,hint:Z(n.stdout,n.stderr)}))}catch(e){throw it(t.id,e)}}function it(t,n){return!(n instanceof e)||n.code!==`COMMAND_FAILED`?ot(t,n):(typeof n.details?.kind==`string`?n.details.kind:``)===`not_ready`?n:at(t,n)}function at(t,n){let r=n.details??{},i=String(r.stdout??``),a=String(r.stderr??``),o=Number(r.timeoutMs??15e3),s=`CoreDevice did not respond within ${o}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;return new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:t,cause:n.message,timeoutMs:o,stdout:i,stderr:a,hint:i||a?Z(i,a):s},n)}function ot(t,n){return new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:t,hint:`Reconnect the device, keep it unlocked, and retry.`},n instanceof Error?n:void 0)}async function st(e,t){if(typeof t==`number`&&t<=0)return null;let n=typeof t==`number`?Math.max(1,Math.min(J,t)):J;try{let t=await Y(e.id,n);return t.result.exitCode!==0||!t.parsed.parsed||t.parsed.outcome&&t.parsed.outcome!==`success`?null:t.parsed.tunnelIp??null}catch{return null}}async function Y(e,t,n=0){let r=u.join(m.tmpdir(),`agent-device-coredevice-info-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),i=Math.max(1,Math.ceil(t/1e3));try{return{result:await l([`devicectl`,`device`,`info`,`details`,`--device`,e,`--json-output`,r,`--timeout`,String(i)],{allowFailure:!0,timeoutMs:t+n}),parsed:await ct(r)}}finally{await p.rm(r,{force:!0}).catch(()=>{})}}async function ct(e){try{return{parsed:!0,...lt(JSON.parse(await p.readFile(e,`utf8`)))}}catch{return{parsed:!1}}}function lt(e){let t=e?.result;if(!t||typeof t!=`object`)return{};let n=t.connectionProperties,r=t.device?.connectionProperties,i=X(n?.tunnelState)??X(r?.tunnelState),a=X(n?.tunnelIPAddress)??X(r?.tunnelIPAddress),o=X(e?.info?.outcome);return{...o?{outcome:o}:{},...i?{tunnelState:i}:{},...a?{tunnelIp:a}:{}}}function X(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function Z(e,t){return G(e,t)||(`${e}\n${t}`.toLowerCase().includes(`timed out waiting for all destinations`)?`Xcode destination did not become available in time. Keep device unlocked and retry.`:U)}async function Q(t,n,r,i=I){let a=re.fromTimeoutMs(i),o={exitCode:1,stdout:``,stderr:``};for(let e of D)if(o=await l([`devicectl`,`device`,`copy`,`from`,`--device`,t.id,`--source`,n,`--destination`,r,`--domain-type`,`appDataContainer`,`--domain-identifier`,e],{allowFailure:!0,timeoutMs:ut(a,i)}),o.exitCode===0)return;throw new e(`COMMAND_FAILED`,`Failed to copy runner file from iOS device: ${o.stderr.trim()||o.stdout.trim()||`devicectl exited with code ${o.exitCode}`}`)}function ut(t,n){let r=t.remainingMs();if(r>0)return r;throw new e(`COMMAND_FAILED`,`iOS runner file copy timed out after ${n}ms`,{timeoutMs:n,step:`runner file copy`})}function $(t){if(!(t instanceof e))return{reason:t instanceof Error?t.message:String(t)};let n=t.details??{},r=Array.isArray(n.args)?n.args.filter(e=>typeof e==`string`).join(` `):void 0;return{errorCode:t.code,reason:t.message,timeoutMs:typeof n.timeoutMs==`number`?n.timeoutMs:void 0,exitCode:typeof n.exitCode==`number`?n.exitCode:void 0,stderr:typeof n.stderr==`string`&&n.stderr.trim()?n.stderr:void 0,stdout:typeof n.stdout==`string`&&n.stdout.trim()?n.stdout:void 0,commandArgs:r}}function dt(e){let t=e.details??{},n=typeof t.stdout==`string`?t.stdout:``,r=typeof t.stderr==`string`?t.stderr:``,i=Array.isArray(t.args)?t.args.filter(e=>typeof e==`string`).join(` `):``;return`${e.message}\n${n}\n${r}\n${i}`.toLowerCase()}async function ft(e,t,n){if(!n.preferRunner)try{await L([`device`,`screenshot`,`--device`,e.id,t],{action:`capture iOS screenshot`,deviceId:e.id});return}catch(t){if(!vt(t))throw t;_t(e,t)}let r=await mt(e,n,!1);await ht(r,t)||await Q(e,gt(r),t)}async function pt(t,n,r){if(!await ht(await mt(t,r,!0),n))throw new e(`COMMAND_FAILED`,`Failed to capture iOS screenshot: XCTest runner returned no inline image`,{deviceId:t.id,backend:`xctest`})}async function mt(e,t,n){return await t.runRunnerCommand(e,{command:`screenshot`,appBundleId:t.appBundleId,fullscreen:t.fullscreen,inlineScreenshot:n},t.runnerOptions??{})}async function ht(e,t){let n=e.imageBase64;return typeof n!=`string`||n.length===0?!1:(await p.writeFile(t,Buffer.from(n,`base64`)),!0)}function gt(t){let n=t.message;if(typeof n==`string`&&n.length>0)return n;throw new e(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`)}function _t(e,t){o({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:`devicectl_screenshot`,to:`runner`,...$(t)}})}function vt(t){if(!(t instanceof e)||t.code!==`COMMAND_FAILED`)return!1;let n=dt(t);return n.includes(`unknown option '--device'`)||n.includes(`unknown subcommand`)&&n.includes(`screenshot`)||n.includes(`unrecognized subcommand`)&&n.includes(`screenshot`)}const yt={coredevice:{backend:`coredevice`,assertAppInstallationSupported:()=>{},ensureReady:rt,listApps:Ze,installApp:Qe,uninstallApp:$e,launchApp:nt,terminateApp:async(e,t)=>await et(e,t),resolveAppProcesses:tt,captureScreenshot:ft,copyRunnerFile:Q,resolveTunnel:async(e,t)=>({tunnelIp:await st(e,t)})},xctest:{backend:`xctest`,assertAppInstallationSupported:xt,ensureReady:Dt,listApps:Ct,installApp:St,uninstallApp:St,launchApp:Ot,terminateApp:kt,resolveAppProcesses:wt,captureScreenshot:pt,copyRunnerFile:Et,resolveTunnel:Tt}};function bt(e){return yt[e.iosPhysicalDeviceBackend===`xctest`?`xctest`:`coredevice`]}function xt(t){throw new e(`UNSUPPORTED_OPERATION`,`Installing apps is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Install the app with Xcode, then open it in agent-device by bundle ID.`})}async function St(e){return xt(e)}async function Ct(t){throw new e(`UNSUPPORTED_OPERATION`,`App inventory is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Use an installed app bundle ID when opening the device.`})}async function wt(t){throw new e(`UNSUPPORTED_OPERATION`,`Process lookup is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Use a CoreDevice-backed iOS device for performance sampling.`})}async function Tt(t){throw new e(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices have no CoreDevice tunnel.`,{deviceId:t.id,backend:`xctest`,hint:`Connect the device by cable so it is reachable through usbmux.`})}async function Et(t){throw new e(`UNSUPPORTED_OPERATION`,`Runner file copy is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`})}async function Dt(t){let n=[`xcdevice`,`wait`,`--both`,`--timeout=15`,t.id],r=await l(n,{allowFailure:!0,timeoutMs:18e3});if(r.exitCode!==0)throw new e(`COMMAND_FAILED`,`iOS device is not ready for XCTest automation`,s(r,{cmd:`xcrun`,args:n,deviceId:t.id,backend:`xctest`,hint:"Keep the device unlocked, trusted, connected, and visible in `xcrun xcdevice list`, then retry."}))}async function Ot(t,n,r){if(r.payloadUrl||r.launchArgs&&r.launchArgs.length>0)throw new e(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices do not support deep links or launch arguments during open.`,{deviceId:t.id,backend:`xctest`,hint:`Open the installed app by bundle ID without a URL or --launch-args.`});await r.runRunnerCommand(t,{command:`activate`,appBundleId:n},r.runnerOptions??{})}async function kt(e,t,n){await n.runRunnerCommand(e,{command:`terminate`,appBundleId:t},n.runnerOptions??{})}export{De as A,T as C,P as D,Me as E,ce as F,h as I,g as L,x as M,ue as N,F as O,le as P,ae as R,xe as S,we as T,ze as _,Xe as a,ve as b,G as c,I as d,Fe as f,Be as g,He as h,q as i,ge as j,M as k,Ie as l,Ve as m,dt as n,K as o,Le as p,$ as r,U as s,bt as t,Pe as u,Re as v,N as w,k as x,D as y};
1
+ import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{n,t as r}from"./version.js";import{c as i,l as a,s as o,v as s}from"./sdk-device.js";import{C as ee,f as c,j as te}from"./sdk-android-adb.js";import{a as ne,i as re}from"./boot-diagnostics.js";import{a as l,s as ie}from"./tool-provider.js";import u from"node:path";import d from"node:crypto";import f,{promises as p}from"node:fs";import m from"node:os";function h(e){return e?.trim()||void 0}function g(e){return h(e)}function _(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function ae(e,t=process.env){let n=h(e)??h(t.AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST);if(n)return _(n)}var oe=e({buildSimctlArgs:()=>v,buildSimctlArgsForDevice:()=>y,runSimctlForDevice:()=>b});function v(e,t={}){let n=g(t.simulatorSetPath);return n?[`simctl`,`--set`,n,...e]:[`simctl`,...e]}function y(e,t){return!i(e)||e.kind!==`simulator`?[`simctl`,...t]:v(t,{simulatorSetPath:e.simulatorSetPath})}function b(e,t,n){return l(y(e,t),n)}const x={iOS:{sdkName:{simulator:`iphonesimulator`,device:`iphoneos`},derivedBaseName:{simulator:`ios-simulator`,device:`ios-device`},xctestrunHints:{simulator:{preferred:[`iphonesimulator`],disallowed:[`iphoneos`,`appletvos`,`appletvsimulator`,`macos`]},device:{preferred:[`iphoneos`],disallowed:[`iphonesimulator`,`appletvos`,`appletvsimulator`,`macos`]}}},tvOS:{sdkName:{simulator:`appletvsimulator`,device:`appletvos`},derivedBaseName:{simulator:`tvos-simulator`,device:`tvos-device`},xctestrunHints:{simulator:{preferred:[`appletvsimulator`],disallowed:[`appletvos`,`iphoneos`,`iphonesimulator`,`macos`]},device:{preferred:[`appletvos`],disallowed:[`appletvsimulator`,`iphoneos`,`iphonesimulator`,`macos`]}}},macOS:{sdkName:{simulator:`macosx`,device:`macosx`},derivedBaseName:{simulator:`macos`,device:`macos`},xctestrunHints:{simulator:{preferred:[`macos`],disallowed:[`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`]},device:{preferred:[`macos`],disallowed:[`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`]}}},visionOS:{sdkName:{simulator:`xrsimulator`,device:`xros`},derivedBaseName:{simulator:`visionos-simulator`,device:`visionos-device`},xctestrunHints:{simulator:{preferred:[`xrsimulator`],disallowed:[`xros`,`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`,`macos`]},device:{preferred:[`xros`],disallowed:[`xrsimulator`,`iphoneos`,`iphonesimulator`,`appletvos`,`appletvsimulator`,`macos`]}}}};function S(e){if(!o(e.platform))throw new t(`UNSUPPORTED_PLATFORM`,`Unsupported platform for Apple runner: ${e.platform}`);return a(e)?`macOS`:s(e.target,e.appleOs)}function se(e,t){return x[e].sdkName[C(t)]}function ce(e){return x[S(e)].derivedBaseName[C(e.kind)]}function le(e){return x[S(e)].xctestrunHints[C(e.kind)]}function ue(e){let t=S(e);return t===`macOS`?`platform=macOS,arch=${w()}`:e.kind===`simulator`?`platform=${t} Simulator,id=${e.id}`:`platform=${t},id=${e.id}`}function de(e){let t=S(e);return t===`macOS`?`platform=macOS,arch=${w()}`:e.kind===`simulator`?`platform=${t} Simulator,id=${e.id}`:`generic/platform=${t}`}function fe(e){let t=S(e);return t===`macOS`?`platform=macOS,arch=${w()}`:e.kind===`simulator`?`generic/platform=${t} Simulator`:`generic/platform=${t}`}function C(e){return e===`simulator`?`simulator`:`device`}function w(){return process.arch===`arm64`?`arm64`:`x86_64`}const pe=new Set;function me(e={}){let t=new Map,n=e.now??(()=>Date.now()),r=e=>{e?.timer&&clearTimeout(e.timer)},i={get(e){let r=t.get(e);if(r){if(r.expiresAt!==void 0&&r.expiresAt<=n()){i.delete(e);return}return r.value}},set(i,a){r(t.get(i));let o=he(e.ttlMs,n),s={value:a,expiresAt:o};e.scheduleExpiry&&o!==void 0&&(s.timer=setTimeout(()=>{t.delete(i)},Math.max(0,o-n())),s.timer.unref?.()),t.set(i,s)},delete(e){let n=t.get(e);return n?(r(n),t.delete(e)):!1},clear(){for(let e of t.values())r(e);t.clear()}};return pe.add(i.clear),i}function he(e,t){if(!(e===void 0||!Number.isFinite(e)))return t()+Math.max(0,e)}const ge=u.join(`apple`,`runner`,`AgentDeviceRunner`),_e=u.join(`dist`,`apple`,`runner`,`AgentDeviceRunner`);function T(e){let t=u.join(e,ge);return f.existsSync(t)?t:u.join(e,_e)}function ve(e){return u.join(T(e),`AgentDeviceRunner.xcodeproj`)}const ye=u.join(m.homedir(),`.agent-device`,`apple-runner`),be=`.agent-device-runner-cache.json`,xe=[`-IDEPackageSupportDisableManifestSandbox=1`,`-IDEPackageSupportDisablePluginExecutionSandbox=1`,`ENABLE_USER_SCRIPT_SANDBOXING=NO`],E=me();function D(e){return e?.trim()??``}function O(e=process.env){return D(e.AGENT_DEVICE_IOS_BUNDLE_ID)||D(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||`com.callstack.agentdevice.runner`}function k(e=process.env){return D(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID)||`${O(e)}.uitests`}function Se(e=process.env){let t=O(e),n=k(e);return Array.from(new Set([D(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${n}.xctrunner`,t].filter(e=>e.length>0)))}const Ce=Se(process.env);function we(e,t=r()){let i=S(e);return{schemaVersion:2,packageVersion:n(t),runnerSourceFingerprint:Ae(t),...Te(i,e.kind),platformName:i,deviceKind:e.kind,target:e.target??`mobile`,buildDestinationFamily:fe(e),runnerBundleBuildSettings:I(process.env),runnerSigningBuildSettings:F(process.env,e.kind===`device`,e),runnerPerformanceBuildSettings:L(),runnerSandboxBuildArgs:R()}}function Te(e,t){let n=Ee(A(`xcodebuild`,[`-version`])),r=se(e,t);return{xcodeVersion:n.version,xcodeBuildVersion:n.buildVersion,sdkName:r,sdkVersion:A(`xcrun`,[`--sdk`,r,`--show-sdk-version`]),sdkBuildVersion:A(`xcrun`,[`--sdk`,r,`--show-sdk-build-version`])}}function A(e,t){let n=JSON.stringify([e,t]),r=E.get(n);if(r!==void 0)return r;try{let r=ee(e,t,{allowFailure:!0,timeoutMs:5e3,maxBuffer:128*1024}),i=r.exitCode===0&&r.stdout.trim()||`unknown`;return E.set(n,i),i}catch{return E.set(n,`unknown`),`unknown`}}function Ee(e){return{version:e.match(/^Xcode\s+(.+)$/m)?.[1]?.trim()||`unknown`,buildVersion:e.match(/^Build version\s+(.+)$/m)?.[1]?.trim()||`unknown`}}function De(e,t){let n=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim();if(n)return u.resolve(n);let r=ke(t),i=Oe(e);return u.join(i,r)}function Oe(e){return u.join(ye,`derived`,ce(e))}function ke(e){return`cache-${d.createHash(`sha256`).update(M(j(e))).digest(`hex`).slice(0,16)}`}function j(e){let{artifacts:t,packageVersion:n,...r}=e;return r}function M(e){return JSON.stringify(N(e))}function N(e){return Array.isArray(e)?e.map(e=>N(e)):!e||typeof e!=`object`?e:Object.fromEntries(Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,N(t)]))}const P=new Map;function Ae(e){let t=T(e),n=Me(t),r=je(t,n),i=P.get(t);if(i?.fileStatsFingerprint===r)return i.sourceFingerprint;let a=d.createHash(`sha256`);for(let e of n){let n=u.relative(t,e);a.update(n),a.update(`\0`),a.update(f.readFileSync(e)),a.update(`\0`)}let o=a.digest(`hex`);return P.set(t,{fileStatsFingerprint:r,sourceFingerprint:o}),o}function je(e,t){let n=d.createHash(`sha256`);for(let r of t){let t=u.relative(e,r),i=f.statSync(r);n.update(t),n.update(`\0`),n.update(String(i.size)),n.update(`\0`),n.update(String(Math.trunc(i.mtimeMs))),n.update(`\0`)}return n.digest(`hex`)}function Me(e){if(!f.existsSync(e))return[];let t=[],n=[e];for(;n.length>0;){let e=n.pop();for(let r of f.readdirSync(e,{withFileTypes:!0})){let i=u.join(e,r.name);if(r.isDirectory()){if(r.name===`xcuserdata`)continue;n.push(i);continue}r.isFile()&&Ne(r.name,i)&&t.push(i)}}return t.sort((e,t)=>e.localeCompare(t))}function Ne(e,t){return e===`project.pbxproj`?t.includes(`${u.sep}.xcodeproj${u.sep}`):[`.jpg`,`.json`,`.png`,`.swift`,`.m`,`.h`,`.plist`,`.entitlements`,`.xctestplan`,`.xcconfig`,`.storyboard`,`.xib`].includes(u.extname(e))}function Pe(e){return a(e)||e.kind===`device`?`-maximum-concurrent-test-device-destinations`:`-maximum-concurrent-test-simulator-destinations`}function F(e=process.env,t=!1,n={platform:`apple`}){if(a(n))return[`CODE_SIGNING_ALLOWED=NO`,`CODE_SIGNING_REQUIRED=NO`,`CODE_SIGN_IDENTITY=`,`DEVELOPMENT_TEAM=`];if(!t)return[];let r=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||``,i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||``,o=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||``,s=[`CODE_SIGN_STYLE=Automatic`];return r&&s.push(`DEVELOPMENT_TEAM=${r}`),i&&s.push(`CODE_SIGN_IDENTITY=${i}`),o&&s.push(`PROVISIONING_PROFILE_SPECIFIER=${o}`),s}function I(e=process.env){let t=O(e),n=k(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${n}`]}function L(){return[`COMPILER_INDEX_STORE_ENABLE=NO`,`ENABLE_CODE_COVERAGE=NO`,`ONLY_ACTIVE_ARCH=YES`,`ENABLE_PREVIEWS=NO`,`ENABLE_DEBUG_DYLIB=NO`]}function R(){return[...xe,`OTHER_SWIFT_FLAGS=${Fe(process.env)}`]}function Fe(e){return ne(e.AGENT_DEVICE_XCUITEST_INCLUDE_UNIT_TESTS)?`$(inherited) -disable-sandbox -D AGENT_DEVICE_RUNNER_UNIT_TESTS`:`$(inherited) -disable-sandbox`}const Ie=18e4,Le=6e4,Re=6e4,ze=1e4,Be=15e3,Ve=2e4,He=15e3,z=2e4,Ue=1e3,We=5e3;async function B(e,n,r={}){let i=[`devicectl`,...e],a=await l(i,{allowFailure:!0,timeoutMs:r.timeoutMs??2e4});if(a.exitCode===0)return;let{stdout:o,stderr:s}=a;if(!r.tolerateOutput?.(o,s))throw new t(`COMMAND_FAILED`,`Failed to ${n.action}`,c(a,{cmd:`xcrun`,args:i,stdout:o,stderr:s,deviceId:n.deviceId,hint:q(o,s)??`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`}))}async function V(e,t){return Ze(Ye(await U(e,{jsonPrefix:`agent-device-ios-apps`,args:[`devicectl`,`device`,`info`,`apps`,`--device`,e.id,`--include-all-apps`],failureMessage:`Failed to list iOS apps`,parseFailureMessage:`Failed to parse iOS apps list`})),t)}async function Ge(e){let n=await U(e,{jsonPrefix:`agent-device-ios-processes`,args:[`devicectl`,`device`,`info`,`processes`,`--device`,e.id],failureMessage:`Failed to list iOS processes`,parseFailureMessage:`Failed to parse iOS process list`,fallbackHint:Qe});if(!qe(n))throw new t(`COMMAND_FAILED`,`Unsupported iOS process list response`,{deviceId:e.id,hint:Qe});return Xe(n)}async function Ke(e,t){let{appBundleUrl:n,processes:r}=await H(e,t),i=r.sort((e,t)=>G(e,n)-G(t,n))[0];i&&await U(e,{jsonPrefix:`agent-device-ios-process-terminate`,args:[`devicectl`,`device`,`process`,`terminate`,`--device`,e.id,`--pid`,String(i.pid),`--kill`],failureMessage:`Failed to terminate iOS app`,parseFailureMessage:`Failed to parse iOS process termination response`,tolerateFailurePayload:Je})}async function H(e,n){let r=(await V(e,`all`)).find(e=>e.bundleId===n);if(!r)throw new t(`APP_NOT_INSTALLED`,`No iOS device app found for ${n}`,{appBundleId:n,deviceId:e.id});if(!r.url)throw new t(`COMMAND_FAILED`,`Missing app bundle URL for ${n}`,{appBundleId:n,deviceId:e.id,hint:`Installed-app metadata from devicectl did not include the bundle URL required to match running processes. Use an Xcode/CoreDevice toolchain that reports app URLs.`});let i=r.url.replace(/\/+$/,``);return{appBundleUrl:i,processes:(await Ge(e)).filter(e=>e.executable.startsWith(`${i}/`))}}async function U(e,n){let r=u.join(m.tmpdir(),`${n.jsonPrefix}-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),i=[...n.args,`--json-output`,r],a=await l(i,{allowFailure:!0,timeoutMs:2e4});try{if(a.exitCode!==0){let{stdout:o,stderr:s}=a;if(n.tolerateFailurePayload){let e=await W(r).catch(()=>void 0);if(e!==void 0&&n.tolerateFailurePayload(e))return e}throw new t(`COMMAND_FAILED`,n.failureMessage,c(a,{cmd:`xcrun`,args:i,stdout:o,stderr:s,deviceId:e.id,hint:q(o,s)??n.fallbackHint??`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`}))}return await W(r)}catch(r){throw r instanceof t?r:new t(`COMMAND_FAILED`,n.parseFailureMessage,{deviceId:e.id,cause:String(r)})}finally{await p.unlink(r).catch(()=>{})}}async function W(e){return JSON.parse(await p.readFile(e,`utf8`))}function G(e,t){return e.executable.slice(t.length+1).split(`/`).length}function qe(e){return Array.isArray(e?.result?.runningProcesses)}function Je(e){let t=e?.error?.userInfo?.NSUnderlyingError?.error;return t?.domain===`NSPOSIXErrorDomain`&&t.code===3}function Ye(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=typeof e.bundleIdentifier==`string`?e.bundleIdentifier.trim():``;if(!t)continue;let r=typeof e.name==`string`&&e.name.trim().length>0?e.name.trim():t,i=typeof e.url==`string`&&e.url.trim().length>0?e.url.trim():void 0;n.push({bundleId:t,name:r,url:i})}return n}function Xe(e){let t=e?.result?.runningProcesses;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=typeof e.executable==`string`?e.executable.trim():``,r=typeof e.processIdentifier==`number`&&Number.isFinite(e.processIdentifier)?e.processIdentifier:NaN;!t||!Number.isFinite(r)||n.push({executable:t,pid:r})}return n}function Ze(e,t){return ie(e,t)}const K=`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`,Qe=`This Xcode/CoreDevice toolchain must support 'devicectl device info processes' with JSON runningProcesses so agent-device can resolve app process IDs. Inspect diagnostics for the exact devicectl API failure.`;function q(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`device is busy`)&&n.includes(`connecting`)?`iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.`:n.includes(`coredeviceservice`)&&n.includes(`timed out`)?`CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.`:n.includes(`developer disk image`)||n.includes(`developer mode is disabled`)?`Enable Developer Mode on the iOS device (Settings > Privacy & Security > Developer Mode), restart it when prompted, unlock it, then retry.`:n.includes(`must be paired`)?`Pair the iOS device with this Mac: connect it by cable, unlock it, accept the Trust prompt, and enter the device passcode, then retry.`:null}function J(e,t){return y(e,t)}function $e(e,t,n){return l(J(e,t),n)}function Y(e){return e.includes(`not installed`)||e.includes(`not found`)||e.includes(`no such file`)}async function et(e,t){return await V(e,t)}async function tt(e,t){await B([`device`,`install`,`app`,`--device`,e.id,t],{action:`install iOS app`,deviceId:e.id},{timeoutMs:12e4})}async function nt(e,t){await B([`device`,`uninstall`,`app`,`--device`,e.id,t],{action:`uninstall iOS app ${t}`,deviceId:e.id},{tolerateOutput:(e,t)=>Y(`${e}\n${t}`.toLowerCase())})}async function rt(e,t){await Ke(e,t)}async function it(e,t){return await H(e,t)}const X=1e4;async function at(e,t,n={}){let r=[`device`,`process`,`launch`,`--device`,e.id,t];n.payloadUrl&&r.push(`--payload-url`,n.payloadUrl),n.launchArgs&&n.launchArgs.length>0&&r.push(`--`,...n.launchArgs),await B(r,{action:`launch iOS app`,deviceId:e.id})}async function ot(e){try{let{result:n,parsed:r}=await Z(e.id,15e3,3e3);if(n.exitCode===0){if(!r.parsed)throw new t(`COMMAND_FAILED`,`iOS device readiness probe failed`,{kind:`probe_inconclusive`,deviceId:e.id,stdout:n.stdout,stderr:n.stderr,hint:`CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device.`});let i=r.tunnelState?.toLowerCase();if(i===`connecting`)throw new t(`COMMAND_FAILED`,`iOS device is not ready for automation`,{kind:`not_ready`,deviceId:e.id,tunnelState:i,hint:`Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry.`});return}throw new t(`COMMAND_FAILED`,`iOS device is not ready for automation`,c(n,{kind:`not_ready`,deviceId:e.id,tunnelState:r.tunnelState,hint:pt(n.stdout,n.stderr)}))}catch(t){throw st(e.id,t)}}function st(e,n){return!(n instanceof t)||n.code!==`COMMAND_FAILED`?lt(e,n):(typeof n.details?.kind==`string`?n.details.kind:``)===`not_ready`?n:ct(e,n)}function ct(e,n){let r=n.details??{},i=String(r.stdout??``),a=String(r.stderr??``),o=Number(r.timeoutMs??15e3),s=`CoreDevice did not respond within ${o}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;return new t(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:e,cause:n.message,timeoutMs:o,stdout:i,stderr:a,hint:i||a?pt(i,a):s},n)}function lt(e,n){return new t(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:e,hint:`Reconnect the device, keep it unlocked, and retry.`},n instanceof Error?n:void 0)}async function ut(e,t){if(typeof t==`number`&&t<=0)return null;let n=typeof t==`number`?Math.max(1,Math.min(X,t)):X;try{let t=await Z(e.id,n);return t.result.exitCode!==0||!t.parsed.parsed||t.parsed.outcome&&t.parsed.outcome!==`success`?null:t.parsed.tunnelIp??null}catch{return null}}async function Z(e,t,n=0){let r=u.join(m.tmpdir(),`agent-device-coredevice-info-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),i=Math.max(1,Math.ceil(t/1e3));try{return{result:await l([`devicectl`,`device`,`info`,`details`,`--device`,e,`--json-output`,r,`--timeout`,String(i)],{allowFailure:!0,timeoutMs:t+n}),parsed:await dt(r)}}finally{await p.rm(r,{force:!0}).catch(()=>{})}}async function dt(e){try{return{parsed:!0,...ft(JSON.parse(await p.readFile(e,`utf8`)))}}catch{return{parsed:!1}}}function ft(e){let t=e?.result;if(!t||typeof t!=`object`)return{};let n=t.connectionProperties,r=t.device?.connectionProperties,i=Q(n?.tunnelState)??Q(r?.tunnelState),a=Q(n?.tunnelIPAddress)??Q(r?.tunnelIPAddress),o=Q(e?.info?.outcome);return{...o?{outcome:o}:{},...i?{tunnelState:i}:{},...a?{tunnelIp:a}:{}}}function Q(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function pt(e,t){return q(e,t)||(`${e}\n${t}`.toLowerCase().includes(`timed out waiting for all destinations`)?`Xcode destination did not become available in time. Keep device unlocked and retry.`:K)}async function mt(e,n,r,i=z){let a=re.fromTimeoutMs(i),o={exitCode:1,stdout:``,stderr:``};for(let t of Ce)if(o=await l([`devicectl`,`device`,`copy`,`from`,`--device`,e.id,`--source`,n,`--destination`,r,`--domain-type`,`appDataContainer`,`--domain-identifier`,t],{allowFailure:!0,timeoutMs:ht(a,i)}),o.exitCode===0)return;throw new t(`COMMAND_FAILED`,`Failed to copy runner file from iOS device: ${o.stderr.trim()||o.stdout.trim()||`devicectl exited with code ${o.exitCode}`}`)}function ht(e,n){let r=e.remainingMs();if(r>0)return r;throw new t(`COMMAND_FAILED`,`iOS runner file copy timed out after ${n}ms`,{timeoutMs:n,step:`runner file copy`})}function gt(e){if(!(e instanceof t))return{reason:e instanceof Error?e.message:String(e)};let n=e.details??{},r=Array.isArray(n.args)?n.args.filter(e=>typeof e==`string`).join(` `):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:typeof n.timeoutMs==`number`?n.timeoutMs:void 0,exitCode:typeof n.exitCode==`number`?n.exitCode:void 0,stderr:typeof n.stderr==`string`&&n.stderr.trim()?n.stderr:void 0,stdout:typeof n.stdout==`string`&&n.stdout.trim()?n.stdout:void 0,commandArgs:r}}function _t(e){let t=e.details??{},n=typeof t.stdout==`string`?t.stdout:``,r=typeof t.stderr==`string`?t.stderr:``,i=Array.isArray(t.args)?t.args.filter(e=>typeof e==`string`).join(` `):``;return`${e.message}\n${n}\n${r}\n${i}`.toLowerCase()}async function vt(e,t,n){if(!n.preferRunner)try{await B([`device`,`screenshot`,`--device`,e.id,t],{action:`capture iOS screenshot`,deviceId:e.id});return}catch(t){if(!Ct(t))throw t;St(e,t)}let r=await bt(e,n,!1);await $(r,t)||await mt(e,xt(r),t)}async function yt(e,n,r){if(!await $(await bt(e,r,!0),n))throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: XCTest runner returned no inline image`,{deviceId:e.id,backend:`xctest`})}async function bt(e,t,n){return await t.runRunnerCommand(e,{command:`screenshot`,appBundleId:t.appBundleId,fullscreen:t.fullscreen,inlineScreenshot:n},t.runnerOptions??{})}async function $(e,t){let n=e.imageBase64;return typeof n!=`string`||n.length===0?!1:(await p.writeFile(t,Buffer.from(n,`base64`)),!0)}function xt(e){let n=e.message;if(typeof n==`string`&&n.length>0)return n;throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`)}function St(e,t){te({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:`devicectl_screenshot`,to:`runner`,...gt(t)}})}function Ct(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=_t(e);return n.includes(`unknown option '--device'`)||n.includes(`unknown subcommand`)&&n.includes(`screenshot`)||n.includes(`unrecognized subcommand`)&&n.includes(`screenshot`)}var wt=e({resolveIosPhysicalDeviceControl:()=>Et});const Tt={coredevice:{backend:`coredevice`,assertAppInstallationSupported:()=>{},ensureReady:ot,listApps:et,installApp:tt,uninstallApp:nt,launchApp:at,terminateApp:async(e,t)=>await rt(e,t),resolveAppProcesses:it,captureScreenshot:vt,copyRunnerFile:mt,resolveTunnel:async(e,t)=>({tunnelIp:await ut(e,t)})},xctest:{backend:`xctest`,assertAppInstallationSupported:Dt,ensureReady:Nt,listApps:kt,installApp:Ot,uninstallApp:Ot,launchApp:Pt,terminateApp:Ft,resolveAppProcesses:At,captureScreenshot:yt,copyRunnerFile:Mt,resolveTunnel:jt}};function Et(e){return Tt[e.iosPhysicalDeviceBackend===`xctest`?`xctest`:`coredevice`]}function Dt(e){throw new t(`UNSUPPORTED_OPERATION`,`Installing apps is unavailable on this XCTest-backed physical iOS device.`,{deviceId:e.id,backend:`xctest`,hint:`Install the app with Xcode, then open it in agent-device by bundle ID.`})}async function Ot(e){return Dt(e)}async function kt(e){throw new t(`UNSUPPORTED_OPERATION`,`App inventory is unavailable on this XCTest-backed physical iOS device.`,{deviceId:e.id,backend:`xctest`,hint:`Use an installed app bundle ID when opening the device.`})}async function At(e){throw new t(`UNSUPPORTED_OPERATION`,`Process lookup is unavailable on this XCTest-backed physical iOS device.`,{deviceId:e.id,backend:`xctest`,hint:`Use a CoreDevice-backed iOS device for performance sampling.`})}async function jt(e){throw new t(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices have no CoreDevice tunnel.`,{deviceId:e.id,backend:`xctest`,hint:`Connect the device by cable so it is reachable through usbmux.`})}async function Mt(e){throw new t(`UNSUPPORTED_OPERATION`,`Runner file copy is unavailable on this XCTest-backed physical iOS device.`,{deviceId:e.id,backend:`xctest`})}async function Nt(e){let n=[`xcdevice`,`wait`,`--both`,`--timeout=15`,e.id],r=await l(n,{allowFailure:!0,timeoutMs:18e3});if(r.exitCode!==0)throw new t(`COMMAND_FAILED`,`iOS device is not ready for XCTest automation`,c(r,{cmd:`xcrun`,args:n,deviceId:e.id,backend:`xctest`,hint:"Keep the device unlocked, trusted, connected, and visible in `xcrun xcdevice list`, then retry."}))}async function Pt(e,n,r){if(r.payloadUrl||r.launchArgs&&r.launchArgs.length>0)throw new t(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices do not support deep links or launch arguments during open.`,{deviceId:e.id,backend:`xctest`,hint:`Open the installed app by bundle ID without a URL or --launch-args.`});await r.runRunnerCommand(e,{command:`activate`,appBundleId:n},r.runnerOptions??{})}async function Ft(e,t,n){await n.runRunnerCommand(e,{command:`terminate`,appBundleId:t},n.runnerOptions??{})}export{F as A,oe as B,we as C,Pe as D,De as E,ue as F,ae as H,le as I,v as L,ve as M,me as N,L as O,de as P,y as R,j as S,I as T,g as U,_ as V,He as _,Y as a,Ce as b,K as c,Ie as d,z as f,We as g,Ue as h,gt as i,M as j,R as k,q as l,ze as m,Et as n,$e as o,Le as p,_t as r,J as s,wt as t,Re as u,Ve as v,O as w,be as x,Be as y,b as z};
@@ -0,0 +1 @@
1
+ import{t as e}from"./platform-runtime-app-log-process.js";async function t(t,i,a){let{resolveScopedAndroidAdbBackgroundTransport:o}=await import(`./sdk-android-adb.js`).then(e=>e.t),s=o(i);if(s.mode===`local`)return a;if(!s.spawn)return Object.freeze({mode:`transport-composed`});let c=s.spawn,l=e(t,{launch:async(e,t)=>{t?.throwIfAborted();let a=n(e,i.id);return r(c([...a.args],{allowFailure:a.options?.allowFailure,cwd:a.options?.cwd,env:a.options?.env?{...process.env,...a.options.env}:void 0,timeoutMs:a.options?.timeoutMs,captureOutput:!1,signal:t}))}});return Object.freeze({mode:`transport-composed`,start:l.start})}function n(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 r(e){return Object.freeze({child:e,wait:i(e)})}function i(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{t as resolveAndroidAppLogProcessTransport};
@@ -0,0 +1 @@
1
+ import{y as e}from"./sdk-android-adb.js";import{c as t,d as n,n as r,s as i}from"./host-process.js";import{y as a}from"./src2.js";import{x as o}from"./internal/daemon.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(t,n){let r=g(t);return e(r.executable,[...r.args],{allowFailure:r.allowFailure,cwd:r.cwd,env:r.env?{...process.env,...r.env}:void 0,timeoutMs:r.timeoutMs,captureOutput:!1,signal:n})}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 n=t(e),r=i(e);if(!(!n||!r))return Object.freeze({pid:e,startTime:n,command:r})}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=o(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{return a(JSON.parse(c.readFileSync(r,`utf8`)))}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 r(e.pid)?j(e)?`owned-alive`:`ownership-lost`:`missing`}async function A(e){if(!r(e.pid))return`already-missing`;if(!j(e))return`ownership-lost`;try{process.kill(e.pid,`SIGTERM`)}catch{return`already-missing`}if(!await n(e.pid,2e3)){if(!j(e))return`ownership-lost`;try{process.kill(e.pid,`SIGKILL`)}catch{return`already-missing`}await n(e.pid,2e3)}return r(e.pid)?`ownership-lost`:`terminated`}function j(e){return!e.startTime||!e.command?!1:t(e.pid)===e.startTime&&i(e.pid)===e.command}export{f as n,l as r,d as t};
@@ -0,0 +1 @@
1
+ import{v as e,w as t}from"./sdk-android-adb.js";import{n,t as r}from"./platform-runtime-toolchain-host.js";import i from"node:path";import{constants as a}from"node:fs";import o from"node:os";import{access as s,mkdtemp as c,readFile as l,rm as u}from"node:fs/promises";function d(){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:n(),toolchains:r(),files:Object.freeze({isExecutable:async e=>await p(e),createTemporaryTextFile:async e=>await m(e)}),hostOs:f(process.platform),hostName:o.hostname(),homeDirectory:o.homedir(),observations:Object.freeze({deviceBooted:async e=>{let{markSimulatorBooted:t}=await import(`./simulator.js`).then(e=>e.a);t(e)}})})}function f(e){return e===`darwin`||e===`linux`||e===`win32`?e:`other`}async function p(e){try{return await s(e,a.X_OK),!0}catch{return!1}}async function m(e){let t=await c(i.join(o.tmpdir(),e.prefix)),n=i.join(t,`value${e.suffix}`),r=!1;return{path:n,readText:async()=>await l(n,`utf8`),[Symbol.asyncDispose]:async()=>{r||(r=!0,await u(t,{recursive:!0,force:!0}))}}}export{d as createDeviceInventoryHost};
@@ -0,0 +1 @@
1
+ async function e(e){if(e.platform!==`web`)return Object.freeze({mode:`local`});let{hasScopedWebProvider:t,resolveWebProvider:n}=await import(`./internal/daemon.js`).then(e=>e.hn),r=n().dumpNetwork,i=t()?`transport-composed`:`local`;return Object.freeze(r?{mode:i,dump:async e=>{let t=await r({limit:e.maxEntries,include:e.include});return Object.freeze({backend:t.backend??`agent-browser`,entries:t.entries,...t.notes===void 0?{}:{notes:t.notes}})}}:{mode:i})}export{e as resolveWebNetworkTransport};
@@ -0,0 +1,5 @@
1
+ import{v as e,w as t}from"./sdk-android-adb.js";import{b as n,x as r}from"./internal/daemon.js";import{t as i}from"./app-log-files.js";import{n as a,r as o,t as s}from"./platform-runtime-app-log-process.js";import{n as c,t as l}from"./platform-runtime-toolchain-host.js";import u from"node:fs";import{setTimeout as d}from"node:timers/promises";async function f(e,t){t=m(e,t),i(t);let r=n(t),a;try{a=u.createWriteStream(t,{fd:r,autoClose:!0})}catch(e){throw u.closeSync(r),e}let o;a.on(`error`,e=>{o??=e});let s=h(),c=``,l=Promise.resolve(),d,f=e=>{let t=l.then(e);return l=t.catch(()=>void 0),t},p=async e=>{let t=`${c}${e}`.split(`
2
+ `);c=t.pop()??``;for(let e of t)await v(a,g(`${e}\n`,s))};return{write:async e=>await f(async()=>await p(_(e))),[Symbol.asyncDispose]:async()=>{d??=f(async()=>{if(c&&=(await v(a,g(c,s)),``),await y(a),o)throw o}),await d}}}async function p(e,t,n){if(t=m(e,t),!Number.isInteger(n)||n<1||n>1024*1024)throw TypeError(`App-log tail size must be between 1 byte and 1 MiB`);let i=r(t);if(i===void 0)return``;let a=u.fstatSync(i).size,o=Math.min(a,n),s=a-o,c=+(s>0),l=Buffer.alloc(o+c);try{u.readSync(i,l,0,l.length,s-c)}finally{u.closeSync(i)}let d=l.subarray(c).toString(`utf8`);if(c===0||l[0]===10)return d;let f=d.indexOf(`
3
+ `);return f<0?``:d.slice(f+1)}function m(e,t){return o({sessionsDir:e,pathname:t,basename:`app.log`,label:`App-log output`})}function h(){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 g(e,t){return t.reduce((e,t)=>e.replace(t,`[REDACTED]`),e)}function _(e){return typeof e==`string`?e:Buffer.from(e).toString(`utf8`)}async function v(e,t){t&&await new Promise((n,r)=>{e.write(t,e=>e?r(e):n())})}async function y(e){e.closed||await new Promise((t,n)=>{e.once(`error`,n),e.end(()=>{e.off(`error`,n),t()})})}function b(e){return Object.freeze({appLogs:Object.freeze({resolveSession:e.resolveSessionArtifacts,readRecent:async(t,n)=>{let{outputPath:r}=e.resolveSessionArtifacts(t);return x(r,n)},readProcessMarker:async t=>{let{pidPath:n}=e.resolveSessionArtifacts(t);return await e.processes.readMarker(n)}}),networkTransports:Object.freeze({resolve:e.resolveTransport})})}function x(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=r(e);if(n===void 0)return Object.freeze({path:e,exists:!1,text:``,skippedLines:0});try{let r=S(u.readFileSync(n,`utf8`),t);return Object.freeze({path:e,exists:!0,...r})}finally{u.closeSync(n)}}function S(e,t){let n=e.split(`
4
+ `),r=Math.max(0,n.length-t);return Object.freeze({text:n.slice(r).join(`
5
+ `),skippedLines:r})}function C(){let e=Object.freeze({resolve:async e=>{let{createAndroidScreenRecordingTransport:t}=await import(`./platform-runtime-screen-recording-android-host.js`);return await t(e)}}),t=Object.freeze({resolve:async e=>{let{resolveWebScreenRecordingTransport:t}=await import(`./platform-runtime-screen-recording-web-host.js`);return await t(e)}}),n=Object.freeze({prepare:async e=>{let{createScreenRecordingOutputHost:t}=await import(`./platform-runtime-screen-recording-output-host.js`);await t().prepare(e)}}),r=Object.freeze({complete:async(e,t)=>{let{createScreenRecordingFinalizer:n}=await import(`./platform-runtime-screen-recording-finalizer-host.js`);return await n().complete(e,t)}});return Object.freeze({apple:w(),android:e,harmony:T(),web:t,outputs:n,finalize:r})}function w(){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 T(){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 E(n){let r=s(n.sessionsDir),i=Object.freeze({mode:`local`,start:r.start}),a=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}}}),o=b({resolveSessionArtifacts:n.resolveSessionArtifacts,processes:r,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)}});return Object.freeze({commands:a,appleTools:c(),toolchains:l(),artifacts:Object.freeze({resolveSession:n.resolveSessionArtifacts}),outputs:Object.freeze({openAppend:async e=>await f(n.sessionsDir,e),readTail:async(e,t)=>await p(n.sessionsDir,e,t)}),processes:r,processTransports:Object.freeze({resolve:async e=>{if(e.platform!==`android`)return i;let{resolveAndroidAppLogProcessTransport:t}=await import(`./platform-runtime-app-log-android-transport.js`);return t(n.sessionsDir,e,i)}}),...o,screenRecording:C(),clock:Object.freeze({now:()=>Date.now(),sleep:async(e,t)=>{await d(e,void 0,t?{signal:t}:void 0)}})})}export{E as createPlatformRuntimeHost,a as recoverLegacyAppLogMarkersAfterDaemonLock};
@@ -0,0 +1 @@
1
+ import{t as e}from"./shell-quote.js";import{t}from"./video.js";import n from"node:path";const r={medium:8e6,high:2e7};async function i(i){let{resolveAndroidAdbExecutor:o,resolveScopedAndroidAdbBackgroundTransport:s}=await import(`./sdk-android-adb.js`).then(e=>e.t),c=o(i),l=s(i),u=async(e,t)=>await c([`shell`,e],{allowFailure:!0,timeoutMs:5e3,signal:t});return Object.freeze({mode:l.mode,start:async({remotePath:t,quality:n=`medium`},i)=>{let o=(await u(`screenrecord --bit-rate ${r[n]} ${e(t)} >/dev/null 2>&1 & echo $!`,i)).stdout.split(/\s+/).find(e=>/^\d+$/.test(e));if(!o)throw Error(`Android screenrecord did not return a process id`);let s=await a(u,{pid:o,remotePath:t,startTime:``},i);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 a(u,e,t)).status,stop:async(e,t,n)=>{let r=await a(u,e,n);return r.status===`missing`?`already-missing`:r.status===`owned-alive`?(await u(`kill ${t?.force?`-9 `:`-2 `}${e.pid}`,n)).exitCode===0?`stopped`:`uncertain`:r.status},exists:async(t,n)=>(await u(`test -e ${e(t)}`,n)).exitCode===0,size:async(t,n)=>{let r=await u(`test -e ${e(t)}`,n);if(r.exitCode!==0)return r.stderr.trim()===``?void 0:`uncertain`;let i=await u(`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`},findRunning:async(e,t)=>{let n=await u(`ps -A -o pid=`,t);if(n.exitCode!==0)throw Error(`failed to enumerate Android screenrecord processes`);let r=n.stdout.split(/\s+/).filter(e=>/^\d+$/.test(e));return(await Promise.all(r.map(async n=>await a(u,{pid:n,remotePath:e,startTime:``},t)))).flatMap(e=>e.status===`owned-alive`&&e.process?[e.process]:[])},pullPlayable:async({remotePath:e,outputPath:n},r)=>{let i=await c([`pull`,e,n],{allowFailure:!0,signal:r});return{...i,playable:i.exitCode===0&&await t(n)}},remove:async(t,n)=>(await u(`rm -f ${e(t)}`,n)).exitCode===0,manifestPathFor:e=>`${n.posix.dirname(e)}/agent-device-recording-active.json`,readManifest:async(t,n)=>{let r=await u(`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 u(`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 u(`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 u(`rm -f ${e(t)}`,n)).exitCode===0})}async function a(e,t,n){let r=await o(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=c(i.stdout);if(!a)return{status:`uncertain`};let l=await e(`cat /proc/${t.pid}/cmdline`,n);return l.exitCode===0?!s(l.stdout,t.remotePath)||t.startTime.length>0&&t.startTime!==a?{status:`ownership-lost`}:{status:`owned-alive`,process:Object.freeze({pid:t.pid,remotePath:t.remotePath,startTime:a})}:{status:`uncertain`}}async function o(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 s(e,t){let r=e.split(`\0`).filter(e=>e.length>0),i=r[0];return i!==void 0&&n.posix.basename(i)===`screenrecord`&&r.at(-1)===t}function c(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{i as createAndroidScreenRecordingTransport};
@@ -0,0 +1 @@
1
+ function e(){return Object.freeze({availability:t,runRunner:async(e,t,n)=>{let{runAppleRecordingRunner:r}=await import(`./platform-runtime-screen-recording-apple-runner-host.js`);return await r(e,t,n)},startSimulator:async(e,t,n)=>{let{startAppleSimulatorRecording:r}=await import(`./platform-runtime-screen-recording-apple-simulator-host.js`);return await r(e,t,n)},inspectProcess:async e=>{let{inspectAppleSimulatorRecordingProcess:t}=await import(`./platform-runtime-screen-recording-apple-simulator-host.js`);return t(e)},terminateProcess:async e=>{let{terminateAppleSimulatorRecordingProcess:t}=await import(`./platform-runtime-screen-recording-apple-simulator-host.js`);return await t(e)},inspectRunner:async(e,t,n)=>{let{inspectAppleRunnerOwnership:r}=await import(`./platform-runtime-screen-recording-apple-runner-host.js`);return await r(e,t,n)},retrieveRunnerRecording:async(e,t,n,r)=>{let{retrieveAppleRunnerRecording:i}=await import(`./platform-runtime-screen-recording-apple-runner-host.js`);await i(e,t,n,r)},captureClockAnchor:async(e,t,n)=>{let{captureAppleClockAnchor:r}=await import(`./platform-runtime-screen-recording-apple-runner-host.js`);return await r(e,t,n)},isRunnerBundleId:async e=>{let{isAppleRunnerBundleId:t}=await import(`./platform-runtime-screen-recording-apple-runner-host.js`);return await t(e)}})}async function t(e){if(e.kind===`simulator`){let{resolveAppleSimulatorScreenRecordingTransport:e}=await import(`./platform-runtime-screen-recording-apple-transport.js`);return e().available?{available:!0}:{available:!1,hint:`Configure a focused Apple simulator recording transport for this provider.`}}let{resolveAppleRunnerScreenRecordingTransport:t}=await import(`./platform-runtime-screen-recording-apple-runner-transport.js`);return t().available?{available:!0}:{available:!1,hint:`This scoped Apple runner provider does not expose durable recording authority.`}}export{e as createAppleScreenRecordingHost};
@@ -0,0 +1 @@
1
+ async function e(e,t,n){let{resolveAppleRunnerScreenRecordingTransport:r}=await import(`./platform-runtime-screen-recording-apple-runner-transport.js`),i=r();if(t.kind===`stop`){if(i.authority!==t.runnerAuthority)throw Error(`Apple runner recording ownership changed before cleanup`);return await i.stop({device:e,runnerSessionId:t.runnerSessionId,appBundleId:t.appBundleId,signal:n}),{}}let a=await i.start({device:e,appBundleId:t.appBundleId,outputPath:t.outputPath,fps:t.fps,signal:n});return Object.freeze({runnerSessionId:a.runnerSessionId,runnerAuthority:i.authority,...a.remotePath===void 0?{}:{remotePath:a.remotePath},...typeof a.recorderStartUptimeMs==`number`?{recorderStartUptimeMs:a.recorderStartUptimeMs}:{},...typeof a.targetAppReadyUptimeMs==`number`?{targetAppReadyUptimeMs:a.targetAppReadyUptimeMs}:{}})}async function t(e,t,n){let{resolveAppleRunnerScreenRecordingTransport:r}=await import(`./platform-runtime-screen-recording-apple-runner-transport.js`),i=r();return i.authority===n?await i.inspect(e,t):`ownership-lost`}async function n(e,t,n,r){r?.throwIfAborted();let{resolveIosPhysicalDeviceControl:i}=await import(`./physical-device-control.js`).then(e=>e.t);await i(e).copyRunnerFile(e,t,n),r?.throwIfAborted()}async function r(e,t,n){try{let[r,i]=await Promise.all([import(`./platform-runtime-screen-recording-apple-transport.js`).then(e=>e.resolveAppleSimulatorScreenRecordingTransport()),import(`./platform-runtime-screen-recording-apple-runner-transport.js`).then(e=>e.resolveAppleRunnerScreenRecordingTransport())]);if(r.mode===`transport-composed`&&i.authority!==`scoped-provider`)return;let{runAppleRunnerCommand:a}=await import(`./internal/daemon.js`).then(e=>e.lt),o=await a(e,{command:`snapshot`,appBundleId:t,interactiveOnly:!0,depth:1},{signal:n}),s=Date.now();return typeof o.currentUptimeMs==`number`&&Number.isFinite(o.currentUptimeMs)&&o.currentUptimeMs>0?{wallClockAtMs:s,uptimeMs:o.currentUptimeMs}:void 0}catch{n?.throwIfAborted();return}}async function i(e){let{IOS_RUNNER_CONTAINER_BUNDLE_IDS:t}=await import(`./internal/daemon.js`).then(e=>e.lt);return t.includes(e)}export{r as captureAppleClockAnchor,t as inspectAppleRunnerOwnership,i as isAppleRunnerBundleId,n as retrieveAppleRunnerRecording,e as runAppleRecordingRunner};
@@ -0,0 +1 @@
1
+ import{n as e}from"./host-process.js";import{c as t}from"./tool-provider.js";import n from"node:path";const r=Object.freeze({authority:`local-lease`,available:!0,start:i,inspect:async(e,t)=>await f(e,t),stop:async({device:e,runnerSessionId:t,appBundleId:n,signal:r})=>{let{runAppleRunnerCommand:i}=await import(`./internal/daemon.js`).then(e=>e.lt);await i(e,{command:`recordStop`,appBundleId:n},{signal:r,expectedRunnerSessionId:t})}});async function i({device:e,appBundleId:t,outputPath:n,fps:r,signal:i}){let{getRunnerSessionSnapshot:c,runAppleRunnerCommand:l}=await import(`./internal/daemon.js`).then(e=>e.lt),u=`agent-device-recording-${Date.now()}.mp4`,d=e.kind===`device`?`tmp/${u}`:void 0,f=await l(e,{command:`recordStart`,outPath:a(e,n,u,d),...r===void 0?{}:{fps:r},appBundleId:t},{signal:i}),p=c(e.id);if(!p?.alive)throw await s(e,t),Error(`Apple runner recording did not expose a durable runner session identity`);try{i?.throwIfAborted()}catch(n){throw await s(e,t),n}return o(p.sessionId,d,f)}function a(e,t,r,i){return e.appleOs===`macos`?t:i===void 0?n.basename(t):r}function o(e,t,n){return Object.freeze({runnerSessionId:e,...t===void 0?{}:{remotePath:t},...typeof n.recorderStartUptimeMs==`number`?{recorderStartUptimeMs:n.recorderStartUptimeMs}:{},...typeof n.targetAppReadyUptimeMs==`number`?{targetAppReadyUptimeMs:n.targetAppReadyUptimeMs}:{}})}async function s(e,t){let{runAppleRunnerCommand:n}=await import(`./internal/daemon.js`).then(e=>e.lt);await n(e,{command:`recordStop`,appBundleId:t},{}).catch(()=>{})}const c=Object.freeze({authority:`scoped-provider`,available:!1,start:async()=>{throw Error(`Scoped Apple runner provider does not expose durable recording authority`)},inspect:async()=>`ownership-lost`,stop:async()=>{throw Error(`Scoped Apple runner recording authority is unavailable`)}}),l=t(r);function u(){return l.resolve()}async function d(e,t){return await l.run(e??c,t)}async function f(t,n){let[{getRunnerSessionSnapshot:r},{readStaleRunnerLease:i,verifyLeaseRunnerPidIdentity:a}]=await Promise.all([import(`./internal/daemon.js`).then(e=>e.lt),import(`./runner-lease.js`).then(e=>e.c)]),o=r(t.id);if(o)return o.alive?o.sessionId===n?`owned-alive`:`ownership-lost`:`missing`;let s=i(t.id);return s?s.sessionId===n?s.runnerPid===null||!e(s.runnerPid)?`missing`:a(s,s.runnerPid)?`owned-alive`:`ownership-lost`:`ownership-lost`:`missing`}export{u as resolveAppleRunnerScreenRecordingTransport,d as withAppleRunnerScreenRecordingTransport};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,d as n,i as r,l as i,n as a,s as o,t as s}from"./host-process.js";import c from"node:fs";const l=2e3,u=(e,t)=>e===t;async function d(e){if(e===void 0)return;let[n,r]=await Promise.all([Promise.resolve(t(e)),Promise.resolve(o(e))]);return n&&r?Object.freeze({pid:e,startTime:n,command:r}):void 0}async function f(t){let n=await e({timeoutMs:1e3}),r=s([t.pid],n),i=(await Promise.all(r.map(async e=>await d(e.pid)))).filter(e=>e!==void 0);return Object.freeze([t,...i.filter(e=>e.pid!==t.pid)])}function p(e,t=u){return!a(e.pid)||r(e.pid)?`missing`:v(e,t)?`owned-alive`:`ownership-lost`}async function m(e,t,n=u){let r=e.map(e=>({marker:e,ownership:p(e,n)}));if(r.some(({ownership:e})=>e===`ownership-lost`))return`ownership-lost`;let i=r.filter(({ownership:e})=>e===`owned-alive`).map(({marker:e})=>e);if(i.length===0)return`already-missing`;let a=e[0],o=a&&p(a,n)===`owned-alive`?await f(a):[],s=_([...i,...o]);if(s.some(e=>p(e,n)===`ownership-lost`))return`ownership-lost`;for(let[e,r]of[[`SIGINT`,5e3],[`SIGTERM`,l],[`SIGKILL`,l]])if(h(s,e,t),await g(s,r,t?.wait,n))return`terminated`;return`ownership-lost`}function h(e,t,n){let r=n?.child.pid;i(e.map(({pid:e})=>e).filter(e=>e!==r),t),r!==void 0&&e.some(({pid:e})=>e===r)&&n?.child.kill(t)}async function g(e,t,r,i=u){let a=e[0]?.pid,o=r?await y(r,t):!1;return await Promise.all(e.filter(({pid:e})=>!o||e!==a).map(async({pid:e})=>await n(e,t))),e.every(e=>o&&e.pid===a||p(e,i)===`missing`)}function _(e){return[...new Map(e.map(e=>[e.pid,e])).values()]}function v(e,n){let r=o(e.pid);return e.startTime.length>0&&e.command.length>0&&t(e.pid)===e.startTime&&r!==null&&n(e.command,r)}async function y(e,t){return await Promise.race([e.then(()=>!0,()=>!0),new Promise(e=>setTimeout(()=>e(!1),t))])}const b=(e,t)=>{if(e===t)return!0;let n=/^(?:\S*\/)?xcrun simctl (.+)$/.exec(e)?.[1],r=/^(?:\S*\/)?simctl (.+)$/.exec(t)?.[1];return n!==void 0&&n===r&&/^(?:--set .+ )?io \S+ recordVideo .+$/.test(n)};async function x(e,t,n){let{resolveAppleSimulatorScreenRecordingTransport:r}=await import(`./platform-runtime-screen-recording-apple-transport.js`);n?.throwIfAborted();let i;try{i=await C(r().start({device:e,outputPath:t,signal:n}),n),n?.throwIfAborted()}catch(e){throw i&&await T(i),c.rmSync(t,{force:!0}),n?.throwIfAborted(),e}if(!i)throw Error(`simctl recordVideo acquisition did not return a process`);let a;try{if(a=await S(i.child.pid,n),!a)throw Error(`simctl recordVideo did not expose a complete process identity`)}catch(e){throw i.child.kill(`SIGKILL`),await i.wait.catch(()=>void 0),n?.throwIfAborted(),e}try{await k(t,i.wait,n);let e=await f(a);return E(i,e)}catch(e){throw await m([a],i,b).catch(()=>{}),await i.wait.catch(()=>void 0),c.rmSync(t,{force:!0}),n?.throwIfAborted(),e}}async function S(e,t){if(e!==void 0)for(let n=0;n<=80;n+=1){t?.throwIfAborted();let r=await d(e);if(r)return r;n<80&&await j(25,t)}}async function C(e,t){let n=Promise.resolve(e);if(!t)return await n;if(t.aborted)throw w(e)?await T(e):n.then(T),t.reason;let r=()=>{},i=new Promise((e,n)=>{let i=()=>n(t.reason);t.addEventListener(`abort`,i,{once:!0}),r=()=>t.removeEventListener(`abort`,i),t.aborted&&i()});try{return await Promise.race([n,i])}catch(e){throw t.aborted?(n.then(T),t.reason):e}finally{r()}}function w(e){return`child`in e}async function T(e){e.child.kill(`SIGKILL`),await e.wait.catch(()=>void 0)}function E(e,t){let n,r=!1,i=()=>n??=m(t,e,b).then(e=>{if(e===`ownership-lost`)throw Error(`simctl recordVideo process ownership changed before cleanup`);if(e!==`terminated`&&e!==`already-missing`)throw Error(`simctl recordVideo cleanup was not confirmed`);r=e===`terminated`}),a=e.wait.then(async e=>{let t=n;return t&&await t.catch(()=>void 0),r&&e.exitCode!==0?{...e,exitCode:0}:e});return Object.freeze({markers:Object.freeze([...t]),wait:a,terminate:i})}function D(e){return p(e,b)}async function O(e){return await m([e],void 0,b)}async function k(e,t,n){let r=t.then(e=>({kind:`exited`,result:e}),e=>({kind:`failed`,error:e})),i;r.then(e=>{i=e}),await Promise.resolve();for(let t=0;t<=60;t+=1){if(n?.throwIfAborted(),i)throw A(i);if(c.existsSync(e)){let e=await Promise.race([r,j(50,n).then(()=>void 0)]);if(e)throw A(e);return}if(t===60)throw Error(`simctl recordVideo did not create its output within 15000ms`);let a=await Promise.race([r,j(250,n).then(()=>void 0)]);if(a)throw A(a)}}function A(e){return e.kind===`failed`?e.error instanceof Error?e.error:Error(String(e.error)):Error(`simctl recordVideo exited with code ${e.result.exitCode}`)}function j(e,t){return t?.throwIfAborted(),new Promise((n,r)=>{let i=e=>{clearTimeout(a),t?.removeEventListener(`abort`,o),e===void 0?n():r(e)},a=setTimeout(()=>i(),e);if(!t)return;let o=()=>i(t.reason);t.addEventListener(`abort`,o,{once:!0}),t.aborted&&o()})}export{D as inspectAppleSimulatorRecordingProcess,x as startAppleSimulatorRecording,O as terminateAppleSimulatorRecordingProcess};
@@ -0,0 +1 @@
1
+ import{c as e}from"./tool-provider.js";const t=Object.freeze({available:!0,mode:`local`,async start({device:e,outputPath:t,signal:n}){let[{buildSimctlArgsForDevice:r},{runCmdBackground:i}]=await Promise.all([import(`./physical-device-control.js`).then(e=>e.B),import(`./sdk-android-adb.js`).then(e=>e.p)]);return n?.throwIfAborted(),i(`xcrun`,r(e,[`io`,e.id,`recordVideo`,t]),{allowFailure:!0})}}),n=Object.freeze({available:!1,mode:`transport-composed`,start:async()=>{throw Error(`Scoped Apple provider does not expose an Apple simulator screen-recording transport`)}}),r=e(t);function i(){return r.resolve()}async function a(e,t){return await r.run(e??n,t)}export{i as resolveAppleSimulatorScreenRecordingTransport,a as withAppleSimulatorScreenRecordingTransport};
@@ -0,0 +1 @@
1
+ import{_ as e}from"./sdk-contracts.js";import{t}from"./version.js";import{tn as n}from"./prepare-kind.js";import{v as r}from"./sdk-android-adb.js";import{n as i}from"./recording-telemetry.js";import{a,i as o,n as s,r as c,t as l}from"./video.js";import u from"node:path";import d from"node:fs";import{fileURLToPath as f}from"node:url";function p(e,t,n,r){let i=`apple/runner/AgentDeviceRunner/RecordingScripts/${e}`,a=`dist/${i}`;return[u.resolve(t,e),u.resolve(n,i),u.resolve(t,`../${i}`),u.resolve(t,`../../${i}`),u.resolve(t,`../../../${i}`),u.resolve(n,a),u.resolve(r,i)]}function m(n){let r=p(n,u.dirname(f(import.meta.url)),t(),process.cwd());for(let e of r)if(d.existsSync(e))return e;throw new e(`COMMAND_FAILED`,`Missing recording helper script: ${n}`,{hint:`Ensure apple/runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled under dist/apple/runner in the package.`,scriptName:n,searchedPaths:r})}let h,g;function _(e=process.platform){if(e!==`darwin`)return`touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry`}function v(){return h??=m(`recording-overlay.swift`),h}function y(){return g??=m(`recording-trim.swift`),g}async function b(t){let{videoPath:n,scriptPath:i,scriptArgs:l,commandDescription:u}=t;await c(n),await s(n);let f=x(n);try{await r(await a({sourcePath:i}),[`--input`,n,`--output`,f,...l],{timeoutMs:12e4,env:o()}),await s(f),d.renameSync(f,n)}catch(t){let r=t instanceof e?t:new e(`COMMAND_FAILED`,String(t),void 0,t instanceof Error?t:void 0);throw new e(`COMMAND_FAILED`,u,{...r.details,videoPath:n,script:i},r)}finally{d.rmSync(f,{force:!0})}}function x(e){let t=u.parse(e),n=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;return u.join(t.dir,`.${t.name}.agent-device-${n}${t.ext||`.mp4`}`)}async function S(e){let{videoPath:t,trimStartMs:n}=e;n>0&&await b({videoPath:t,scriptPath:y(),scriptArgs:[`--trim-start-ms`,String(n)],commandDescription:`Failed to trim the start of the iOS recording`})}async function C(e){let{videoPath:t,telemetryPath:r,exportQuality:i=n,targetLabel:a=`recording`}=e;await b({videoPath:t,scriptPath:v(),scriptArgs:[`--events`,r,`--quality`,i],commandDescription:`Failed to add touch overlays to the ${a}`})}function w(){return Object.freeze({complete:T})}async function T(e){if(await c(e.outputPath),await s(e.outputPath),!await l(e.outputPath))throw Error(`recording was not finalized into a playable video: ${e.outputPath}`);e.trimStartMs&&e.trimStartMs>0&&await S({videoPath:e.outputPath,trimStartMs:e.trimStartMs});let t=i({recording:{outPath:e.outputPath,gestureEvents:[...e.gestureEvents]},...e.trimStartMs===void 0?{}:{trimStartMs:e.trimStartMs}});return!e.showTouches||e.gestureEvents.length===0?{telemetryPath:t}:await E(e,t)}async function E(e,t){let n=_();if(n)return{telemetryPath:t,overlayWarning:n};try{if(await C({videoPath:e.outputPath,telemetryPath:t,exportQuality:e.exportQuality,targetLabel:e.targetLabel}),!await l(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};
@@ -0,0 +1 @@
1
+ function e(){return Object.freeze({start:async(e,n,r)=>await t(e,[`shell`,`aa`,`start`,`-b`,`com.huawei.hmos.screenrecorder`,`-a`,`com.huawei.hmos.screenrecorder.ServiceExtAbility`,`--ps`,`CustomizedFileName`,n],r),stop:async(e,n)=>await t(e,[`shell`,`aa`,`start`,`-b`,`com.huawei.hmos.screenrecorder`,`-a`,`com.huawei.hmos.screenrecorder.ServiceExtAbility`],n),findMedia:async(e,n,r)=>(await t(e,[`shell`,`mediatool`,`query`,n,`-u`],r)).stdout.match(/file:\/\/[^\s"']+/)?.[0],stageMedia:async(e,n,r)=>(await t(e,[`shell`,`mediatool`,`recv`,n.mediaUri,n.remotePath],r)).exitCode===0,stagedFileSize:async(e,n,r)=>{let i=await t(e,[`shell`,`stat`,`-c`,`%s`,n],r);if(i.exitCode!==0)return;let a=Number(i.stdout.trim());return Number.isSafeInteger(a)&&a>0?a:void 0},pull:async(e,n,r)=>await t(e,[`file`,`recv`,n.remotePath,n.outputPath],r),remove:async(e,n,r)=>(await t(e,[`shell`,`rm`,`-f`,n],r)).exitCode===0,removeMedia:async(e,n,r)=>(await t(e,[`shell`,`mediatool`,`delete`,n],r)).exitCode===0})}async function t(e,t,n){let{runHarmonyHdc:r}=await import(`./hdc.js`).then(e=>e.t);return await r(e,t,{allowFailure:!0,signal:n})}export{e as createHarmonyScreenRecordingHost};
@@ -0,0 +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};
@@ -0,0 +1 @@
1
+ async function e(e){if(e.platform!==`web`)return;let{hasScopedWebProvider:t,resolveWebProvider:n}=await import(`./internal/daemon.js`).then(e=>e.hn);if(!t())return;let r=n();if(!(!r.startRecording||!r.stopRecording))return Object.freeze({start:async e=>await r.startRecording(e),stop:async()=>await r.stopRecording()})}export{e as resolveWebScreenRecordingTransport};
@@ -0,0 +1 @@
1
+ function e(){return Object.freeze({isXcrunAvailable:async e=>{let{resolveAppleToolProvider:n}=await t(async()=>await import(`./tool-provider.js`).then(e=>e.o),e);return await t(async()=>await n().whichCommand(`xcrun`),e)},run:async(e,n)=>{let{runXcrun:r}=await t(async()=>await import(`./tool-provider.js`).then(e=>e.o),n),i=await t(async()=>await r([e.tool,...e.args],{allowFailure:e.allowFailure,signal:n,timeoutMs:e.timeoutMs}),n);return{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode}}})}async function t(e,t){t?.throwIfAborted();try{let n=await e();return t?.throwIfAborted(),n}catch(e){throw t?.throwIfAborted(),e}}function n(){return Object.freeze({prepare:async e=>{if(e===`android`){let{ensureAndroidSdkPathConfigured:e}=await import(`./manifest.js`).then(e=>e.r);await e();return}if(e===`harmonyos`){let{ensureHarmonyToolchainPathConfigured:e}=await import(`./hdc.js`).then(e=>e.t);await e()}}})}export{e as n,n as t};
@@ -0,0 +1 @@
1
+ import{_ as e}from"./sdk-contracts.js";import{H as t}from"./sdk-batch-runner.js";import{n,r}from"./src2.js";const i=Object.freeze({available:!0}),a=Object.freeze({available:!1,reason:`unsupported-provider-mode`}),o=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`WebDriver provider runtimes do not expose screen recording.`});function s(n){return Object.freeze({owner:n.owner,ownsDevice:n.ownsDevice,bind:async r=>{if(r.intent.kind===`exact-owner`&&!t(r.intent.owner,n.owner))throw new e(`UNSUPPORTED_OPERATION`,`WebDriver runtime owner identity does not match`);if(!n.ownsDevice(r.device))throw new e(`UNSUPPORTED_PLATFORM`,`WebDriver runtime does not own this device`);return c(n.host,n.owner,r.device)},shutdown:async()=>void 0})}function c(e,t,s){let c=s.platform===`apple`?`ios-device`:`android`,l=r(s,t,{appLog:a,network:a,screenRecording:o}),u=Object.freeze({device:l.facts.device,operations:{appLogInspect:a,appLogDoctor:a,appLogStart:a,appLogReattach:a,appLogCleanup:a,networkDump:i,screenRecordingStart:o,screenRecordingReattach:o,screenRecordingCleanup:o}}),d=Object.freeze({networkDump:async t=>{let r=await e.appLogs.readRecent(t.sessionId,t.maxScanLines),i=n(r.text,{...t,path:r.path,exists:r.exists,lineNumberOffset:r.skippedLines,backend:c});return Object.freeze({source:`app-log`,backend:c,dump:i,notes:Object.freeze(i.entries.length===0?[`No HTTP(s) entries were found in recent session app logs.`]:[])})}});return Object.freeze({device:s,owner:t,facts:u,operations:d,[Symbol.asyncDispose]:async()=>void 0})}export{s as createWebDriverPlatformRuntimeOwner};