stim 1.20.2 → 1.21.0

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 (217) hide show
  1. package/README.md +88 -8
  2. package/dist/acquire-artifact-CD4lbiWE.mjs +153 -0
  3. package/dist/act-DHAw2A2S.mjs +2667 -0
  4. package/dist/activity-BzVfHSrY.mjs +1376 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-zh1vhbLp.mjs} +21 -65
  6. package/dist/{android-HqP1_vB_.mjs → android-BEJ8Jpl7.mjs} +2 -2
  7. package/dist/{android-DCKZrNvV.mjs → android-BLgbNqox.mjs} +128 -78
  8. package/dist/{android-Dlzxshgp.mjs → android-CV_GCELZ.mjs} +5 -5
  9. package/dist/{android-Mz_Inn3w.mjs → android-DUYkNF4u.mjs} +184 -102
  10. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-Ct5b1xCK.mjs} +7 -6
  11. package/dist/android-cas-compiler.mjs +2 -2
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/api.d.mts +740 -8
  14. package/dist/api.mjs +585 -1
  15. package/dist/{artifact-HSwkIWEQ.mjs → artifact-B8T3S5gi.mjs} +223 -201
  16. package/dist/{artifact-D3czlUvT.mjs → artifact-DAuZ-FNU.mjs} +158 -148
  17. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-QQzVjz3O.mjs} +26 -24
  18. package/dist/budget-Bs6SxxzO.mjs +9154 -0
  19. package/dist/{build-DYDbfkk5.mjs → build-CoPzQRNw.mjs} +144 -96
  20. package/dist/build-cache-DmyR9Zzc.mjs +602 -0
  21. package/dist/build-plan-CaFskB7_.mjs +188 -0
  22. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DkkqguoK.mjs} +2 -2
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/{ccache-zdKiYQ3E.mjs → ccache-BJRZ9pG3.mjs} +10 -9
  25. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-CWmIUMbw.mjs} +18 -5
  26. package/dist/{chrome-BnzZMqsR.mjs → chrome-B6tfCta1.mjs} +7 -4
  27. package/dist/{cli-CLP3diBm.mjs → cli-0DYf8QhQ.mjs} +20 -20
  28. package/dist/cli.mjs +1 -1
  29. package/dist/client-B7QVOlCr.d.mts +253 -0
  30. package/dist/client-UXD70ZbM.mjs +1406 -0
  31. package/dist/collector-run.d.mts +4 -40
  32. package/dist/collector-run.mjs +9 -8
  33. package/dist/{command-output-BTy8hZ0F.mjs → command-output-B1UrjZHL.mjs} +1 -1
  34. package/dist/config-CYcBF478.mjs +949 -0
  35. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-CqeBlrEn.mjs} +3 -3
  36. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-BbKQW83h.mjs} +20 -5
  37. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-DFRyG1_o.mjs} +1 -1
  38. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-UOeESKm6.mjs} +2 -2
  39. package/dist/device-DCxH7_By.mjs +1068 -0
  40. package/dist/{device-BECOiufl.mjs → device-ExJq8Ei7.mjs} +35 -35
  41. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-CMlqEcvw.mjs} +43 -13
  42. package/dist/device-host-worker.mjs +65 -61
  43. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DRUeKaFV.mjs} +48 -45
  44. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-C8raGFoP.mjs} +14 -26
  45. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-DMRpVX9a.mjs} +5 -5
  46. package/dist/doctor-BLHCYxzi.mjs +2 -0
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-DTvaDOda.mjs} +281 -317
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-Dhqebm0q.mjs} +183 -91
  49. package/dist/doctor-fingerprint.mjs +19 -0
  50. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-Cv1F10Kj.mjs} +40 -21
  51. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-BomfRnFT.mjs} +53 -20
  52. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-DJwZpy0c.mjs} +26 -208
  53. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-op6A54yi.mjs} +229 -11
  54. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-Bf0rZvG9.mjs} +172 -82
  55. package/dist/exec-H20xSg2T.d.mts +65 -0
  56. package/dist/exec-_UbtCQcG.mjs +750 -0
  57. package/dist/gc-C-WwL0yi.mjs +3 -0
  58. package/dist/{gc-qWOMdnER.mjs → gc-_-dCXdyL.mjs} +584 -796
  59. package/dist/git-C3iTsJaZ.mjs +73 -0
  60. package/dist/{guide-G9cAbVAc.mjs → guide-Yqwt2bd6.mjs} +941 -269
  61. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-Bw-honsd.mjs} +8 -6
  62. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DB_gBPfY.mjs} +34 -19
  63. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CUvOf4Vr.mjs} +1 -1
  64. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-DL_P5AdN.mjs} +77 -43
  65. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-QI141yKk.mjs} +21 -17
  66. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-Ksyjgzq-.mjs} +30 -21
  67. package/dist/idle-BVeRGroT.d.mts +24 -0
  68. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DaKmZi0z.mjs} +11 -10
  69. package/dist/{ios-BwVCF7oA.mjs → ios-CQ68hG9s.mjs} +8 -8
  70. package/dist/{ios-RkW4pnQf.mjs → ios-CpByZy12.mjs} +140 -80
  71. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-CXGP1bsD.mjs} +1 -1
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device-CwFMehUS.mjs} +51 -26
  73. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-WuwwBdvW.mjs} +13 -13
  74. package/dist/{ios-nOLJGVdy.mjs → ios-qNJt4dFm.mjs} +1 -1
  75. package/dist/ios-signing-DTTIChGs.mjs +489 -0
  76. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-DvFX-K_l.mjs} +1 -1
  77. package/dist/{ios-Ce7bc7br.mjs → ios-ubFsBzwq.mjs} +129 -86
  78. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Cc1dttps.mjs} +53 -26
  79. package/dist/{launch-F4sOqAhB.mjs → launch-CD1yVc7U.mjs} +91 -90
  80. package/dist/{launch-C3qJ6Agb.mjs → launch-Zq2mOSDy.mjs} +82 -541
  81. package/dist/logs-BS00Anxf.mjs +352 -0
  82. package/dist/logs-CMm05HxN.mjs +255 -0
  83. package/dist/{macos-D7uDvO-z.mjs → macos-B65--pPd.mjs} +1 -1
  84. package/dist/{macos-Ch5VJmcS.mjs → macos-C-0qJ6zq.mjs} +225 -212
  85. package/dist/macos-run.mjs +1 -1
  86. package/dist/maintenance-run.mjs +122 -247
  87. package/dist/{metro-DnCEjCxs.mjs → metro-DEXpIhHC.mjs} +67 -12
  88. package/dist/{metro-gateway-CX9Xlkq2.mjs → metro-gateway-BMJNlj3E.mjs} +20 -12
  89. package/dist/{named-ports-4WopRPg-.mjs → named-ports-BWTzt6mu.mjs} +8 -63
  90. package/dist/native-android-JACyjTZs.mjs +844 -0
  91. package/dist/{native-gradle-inputs-BsLRrl7u.mjs → native-gradle-inputs-Bep9JcSF.mjs} +128 -140
  92. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  93. package/dist/native-run-DY_RLx3C.mjs +277 -0
  94. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-Dg1Q7tfF.mjs} +9 -8
  95. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-CB2iQeWq.mjs} +27 -18
  96. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-CXX39F7o.mjs} +96 -47
  97. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  98. package/dist/offload-worker.d.mts +1 -46
  99. package/dist/offload-worker.mjs +197 -66
  100. package/dist/{ownership-DCtw_2IA.mjs → ownership-DEmM5vhh.mjs} +3 -3
  101. package/dist/{page-DRHy329N.mjs → page-CPaHeYqj.mjs} +7 -4
  102. package/dist/paths-BsJMoPP2.mjs +12 -0
  103. package/dist/paths-DQtTgsBf.mjs +42 -0
  104. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BqGbTa61.mjs} +5 -5
  105. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-Bwj-IjY1.mjs} +6 -6
  106. package/dist/{ports-DdSUicVo.mjs → ports-D-MmCTdv.mjs} +3 -3
  107. package/dist/prebuild-uD_ipCxF.mjs +449 -0
  108. package/dist/{project-_phNIJfs.mjs → project-BZNjmW_8.mjs} +65 -37
  109. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-Lfetn8Kr.mjs} +2 -2
  110. package/dist/pull-request-zjCSAryH.d.mts +120 -0
  111. package/dist/pull-requests.d.mts +1 -119
  112. package/dist/pull-requests.mjs +1 -1
  113. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-DuzH0cn3.mjs} +74 -48
  114. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-rhk4smwQ.mjs} +292 -15
  115. package/dist/react-native-doctor-CQpuIMso.mjs +234 -0
  116. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-Bhq1rJeV.mjs} +46 -28
  117. package/dist/{recordings-D0d5aQt0.mjs → recordings-DYteQSu4.mjs} +12 -9
  118. package/dist/{reload-C8JhxjSh.mjs → reload-CmTRFJaX.mjs} +93 -47
  119. package/dist/reload-DzjSl5P_.mjs +2 -0
  120. package/dist/{remote-BiR6aYjy.mjs → remote-ByYkXdGD.mjs} +15 -10
  121. package/dist/result-DNiS-tTP.mjs +434 -0
  122. package/dist/{run-BtPgpKks.mjs → run-D23HmJMs.mjs} +4 -5
  123. package/dist/selection-CSl9i5qU.mjs +619 -0
  124. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CxTrvDg8.mjs} +3 -4
  125. package/dist/{server-command-CTtCkmcQ.mjs → server-command-CtzloH3v.mjs} +14 -7
  126. package/dist/server-expo-C-90EhcG.mjs +2 -0
  127. package/dist/{server-expo-DsguMGUF.mjs → server-expo-DT_F_uVI.mjs} +50 -9
  128. package/dist/{settings-B717odTD.mjs → settings-CsJDEXgK.mjs} +234 -24
  129. package/dist/{settings-vk3mJGSm.d.mts → settings-DkdmlelE.d.mts} +6 -4
  130. package/dist/settings-T1gtc3bf.mjs +114 -0
  131. package/dist/settings-write-HyVZ8eQ8.mjs +359 -0
  132. package/dist/settings.schema.json +163 -16
  133. package/dist/{simslim-CCr3rE-A.mjs → simslim-Cgk17SXV.mjs} +14 -12
  134. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-DF8VfT64.mjs} +15 -20
  135. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  136. package/dist/stage-BIS0ydsV.mjs +183 -0
  137. package/dist/{start-BWqzODpb.mjs → start-7lpH7hmN.mjs} +63 -44
  138. package/dist/{start-TXeMmmO2.mjs → start-RChynRDp.mjs} +1 -1
  139. package/dist/{state-D1Icyjlu.mjs → state-C4ZtUisW.mjs} +40 -13
  140. package/dist/{state-CG_OFoaA.mjs → state-XMziexv2.mjs} +3 -2
  141. package/dist/{stats-BoY5sEPU.mjs → stats-53T7OTb9.mjs} +7 -13
  142. package/dist/stats-report-BFfMpWWF.mjs +16 -0
  143. package/dist/{status-WgFbkRzj.mjs → status-BL7jVyAB.mjs} +535 -447
  144. package/dist/status-CSi6tlRq.mjs +2 -0
  145. package/dist/{status-BTA7kKiQ.mjs → status-DqEUSSxs.mjs} +6 -4
  146. package/dist/{status-watch-C23ILtf9.mjs → status-watch-GDCfqpTE.mjs} +187 -22
  147. package/dist/status-worker.d.mts +1 -0
  148. package/dist/status-worker.mjs +19 -0
  149. package/dist/stim-desktop-C12we7lz.mjs +112 -0
  150. package/dist/{stop-DR6VoDIk.mjs → stop-Bk_1qiV6.mjs} +2 -2
  151. package/dist/{stop-BNmBMi1F.mjs → stop-CPzlM1L-.mjs} +138 -98
  152. package/dist/{stop-DPEhunlw.mjs → stop-D7h6jAXQ.mjs} +11 -10
  153. package/dist/supervisor-run.d.mts +8 -17
  154. package/dist/supervisor-run.mjs +63 -27
  155. package/dist/{support-DMTqj3Hm.mjs → support-67vraa1Q.mjs} +18 -11
  156. package/dist/{support-CwjbFs9H.mjs → support-Dlu37g6H.mjs} +12 -12
  157. package/dist/{swiftpm-macos-DRNVJWlb.mjs → swiftpm-macos-p8WZbxKU.mjs} +35 -24
  158. package/dist/toolchain-DhKwp9iI.mjs +2 -0
  159. package/dist/toolchain-Hp9sCpK4.mjs +873 -0
  160. package/dist/{trigger-CigAYjeL.mjs → trigger-BAahxUPq.mjs} +20 -5
  161. package/dist/trigger-Bf3uDcpv.mjs +2 -0
  162. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-BHX5r0Ei.mjs} +250 -156
  163. package/dist/{web-BDBMxDpx.mjs → web-CJmIj6AI.mjs} +18 -13
  164. package/dist/web-DknQETPs.mjs +2 -0
  165. package/dist/web-run.mjs +11 -12
  166. package/dist/windows-report.d.mts +1 -0
  167. package/dist/windows-report.mjs +18 -0
  168. package/dist/windows-report.ps1 +43 -0
  169. package/dist/workspace-process-lock-1_1OoVW5.mjs +57 -0
  170. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-Cjuigeeu.mjs} +62 -58
  171. package/dist/{workspaces-C36s2jb9.mjs → workspaces-BccMFmGQ.mjs} +1188 -1079
  172. package/dist/worktree-CK2MpJW5.mjs +2 -0
  173. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-DQ6Zi2Mv.mjs} +304 -53
  174. package/dist/xcode-Zlx3qjEs.mjs +896 -0
  175. package/package.json +7 -5
  176. package/shim/android-optimizations.gradle +7 -5
  177. package/dist/activity-BSV745Kz.mjs +0 -629
  178. package/dist/api-qvOzWyfO.mjs +0 -154
  179. package/dist/api-run.mjs +0 -294
  180. package/dist/app-install-BIKtMfPq.mjs +0 -896
  181. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  182. package/dist/budget-f7516Zk0.mjs +0 -4106
  183. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  184. package/dist/cancellation-C_22VQTH.mjs +0 -24
  185. package/dist/client-qQAaXSUs.mjs +0 -1771
  186. package/dist/config-BYDxlMY3.mjs +0 -562
  187. package/dist/device-DuiPJQSn.mjs +0 -290
  188. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  189. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  190. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  191. package/dist/exec-DqKo9GKJ.mjs +0 -268
  192. package/dist/git-DDfFzkMm.mjs +0 -45
  193. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  194. package/dist/logs-BGrEUaEs.mjs +0 -383
  195. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  196. package/dist/native-android-D5qc3-_v.mjs +0 -226
  197. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  198. package/dist/plan-C4TjdPsR.mjs +0 -260
  199. package/dist/prebuild-DYbucPXy.mjs +0 -212
  200. package/dist/preview-78a9kR_-.mjs +0 -1011
  201. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  202. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  203. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  204. package/dist/result-CaJg5Iat.mjs +0 -186
  205. package/dist/server-expo-Bigriskl.mjs +0 -2
  206. package/dist/settings-BORNaaCO.mjs +0 -402
  207. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  208. package/dist/stage-KNTQopqv.mjs +0 -157
  209. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  210. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  211. package/dist/toolchain-BFkAcstd.mjs +0 -2
  212. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  213. package/dist/trigger-9_USgmxz.mjs +0 -2
  214. package/dist/web-Dq-i3wzJ.mjs +0 -2
  215. package/dist/worktree-DpLdCHga.mjs +0 -2
  216. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  217. package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
@@ -1,32 +1,16 @@
1
- import { C as saveConfig, D as withConfigLock$1, G as removeSlotDevice, R as assignSlotDevice, V as deviceSlotPlatforms, W as projectDeviceSlots, _ as loadConfig$1, c as ensureConfig, d as getConfigDir, f as getConfigPath$1, j as ownership_claim_exports, k as process_identity_exports } from "./config-BYDxlMY3.mjs";
2
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
3
- import { c as androidDataPartitionSizeBytes } from "./settings-B717odTD.mjs";
4
- import { n as settingDefault, r as stimDesktopInstalled, t as STIM_DESKTOP_OPEN_OPTIONS } from "./stim-desktop-BzBN2Em2.mjs";
5
- import { n as readCreatedDevices$1, r as recordCreatedDevice, t as forgetCreatedDevice } from "./created-devices-Dzd5C2LF.mjs";
6
- import { d as signalProcessTree, s as pidExists } from "./metro-DnCEjCxs.mjs";
1
+ import { f as ownership_claim_exports, p as process_identity_exports, t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
+ import { B as assignSlotDevice, C as saveConfig, D as withConfigLock$1, K as projectDeviceSlots, O as withConfigLockAsync$1, U as deviceSlotPlatforms, _ as loadConfig$1, c as ensureConfig, d as getConfigDir, f as getConfigPath$1, q as removeSlotDevice } from "./config-CYcBF478.mjs";
3
+ import { c as androidDataPartitionSizeBytes } from "./settings-CsJDEXgK.mjs";
4
+ import { l as pidExists, m as signalProcessTreeAsync } from "./metro-DEXpIhHC.mjs";
5
+ import { n as readCreatedDevices$1, r as recordCreatedDevice, t as forgetCreatedDevice } from "./created-devices-CqeBlrEn.mjs";
6
+ import { i as stimDesktopInstalledAsync, n as settingDefault, t as STIM_DESKTOP_OPEN_OPTIONS } from "./stim-desktop-C12we7lz.mjs";
7
+ import { isDeepStrictEqual } from "node:util";
7
8
  import { join } from "node:path";
8
- import { dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, resolve as resolve$1 } from "path";
9
+ import { ambientEnv, ambientWrite } from "@stim-cli/core";
9
10
  import { ANDROID_EMULATOR_APPS, getParkedMax, isJsonObject, loadConfig, settingDefinition } from "@stim-cli/core/state";
11
+ import { dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, resolve as resolve$1 } from "path";
10
12
  import { existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
11
13
  import { homedir, tmpdir } from "os";
12
- import { isDeepStrictEqual } from "node:util";
13
- //#region src/devices/android-emulator-viewer.ts
14
- function configuredAndroidEmulatorApp(platform = process.platform) {
15
- const value = loadConfig$1()?.androidEmulatorApp ?? settingDefault(settingDefinition("androidEmulatorApp"), () => stimDesktopInstalled(platform)).value;
16
- if (ANDROID_EMULATOR_APPS.includes(value)) return value;
17
- const error = /* @__PURE__ */ new Error("Invalid androidEmulatorApp in machine config. Use \"emulator\" or \"stim-desktop\".");
18
- Object.assign(error, { code: "STIM_BAD_ARG" });
19
- throw error;
20
- }
21
- function openEmulatorInStimDesktop(serial) {
22
- getExecutor().runFileQuiet("open", [
23
- "-g",
24
- "-a",
25
- "Stim",
26
- `stim-desktop://open?serial=${serial}`
27
- ], STIM_DESKTOP_OPEN_OPTIONS);
28
- }
29
- //#endregion
30
14
  //#region src/devices/sim-pool.ts
31
15
  const POOL_SETTING_REMEDY = "Run `stim guide settings` for the device pool bounds and where it can be set.";
32
16
  function parkedMaxSetting(platform, options = {}) {
@@ -154,11 +138,11 @@ function erasedRecord(record) {
154
138
  delete erased.schemeApprovals;
155
139
  return erased;
156
140
  }
157
- function settleParkedAfter(platform, udid, action, keep) {
141
+ async function settleParkedAfter(platform, udid, action, keep) {
158
142
  const claim = claimParkedOperation(platform, udid);
159
143
  if (!claim) return null;
160
144
  try {
161
- const claimed = withConfigLock$1(() => {
145
+ const claimed = await withConfigLockAsync$1(() => {
162
146
  const cfg = loadConfig$1();
163
147
  if (!cfg) return null;
164
148
  const records = readParked(platform, { config: cfg });
@@ -188,7 +172,7 @@ function settleParkedAfter(platform, udid, action, keep) {
188
172
  try {
189
173
  (0, ownership_claim_exports.markClaimChildPending)(claim);
190
174
  try {
191
- action(claimed.record, () => {
175
+ await action(claimed.record, () => {
192
176
  started = true;
193
177
  });
194
178
  } finally {
@@ -196,7 +180,7 @@ function settleParkedAfter(platform, udid, action, keep) {
196
180
  }
197
181
  completed = true;
198
182
  } finally {
199
- withConfigLock$1(() => {
183
+ await withConfigLockAsync$1(() => {
200
184
  const cfg = loadConfig$1();
201
185
  if (!cfg) return;
202
186
  const records = readParked(platform, { config: cfg });
@@ -213,8 +197,8 @@ function settleParkedAfter(platform, udid, action, keep) {
213
197
  (0, ownership_claim_exports.releaseClaim)(claim);
214
198
  }
215
199
  }
216
- function dropParked(platform, udid) {
217
- return removeParkedAfter(platform, udid, () => {}) !== null;
200
+ async function dropParked(platform, udid) {
201
+ return await removeParkedAfter(platform, udid, () => {}) !== null;
218
202
  }
219
203
  //#endregion
220
204
  //#region src/devices/device-ownership.ts
@@ -246,6 +230,27 @@ function isStimOwnedAvd(name) {
246
230
  return name.startsWith("stim-") && isStimOwnedDevice("android", name);
247
231
  }
248
232
  //#endregion
233
+ //#region src/devices/android-emulator-viewer.ts
234
+ async function configuredAndroidEmulatorApp(platform = process.platform, env) {
235
+ let value = loadConfig$1()?.androidEmulatorApp;
236
+ if (value === void 0) {
237
+ const installed = await stimDesktopInstalledAsync(platform, env);
238
+ value = settingDefault(settingDefinition("androidEmulatorApp"), () => installed).value;
239
+ }
240
+ if (ANDROID_EMULATOR_APPS.includes(value)) return value;
241
+ const error = /* @__PURE__ */ new Error("Invalid androidEmulatorApp in machine config. Use \"emulator\" or \"stim-desktop\".");
242
+ Object.assign(error, { code: "STIM_BAD_ARG" });
243
+ throw error;
244
+ }
245
+ async function openEmulatorInStimDesktop(serial) {
246
+ await getExecutor().runFileQuietAsync("open", [
247
+ "-g",
248
+ "-a",
249
+ "Stim",
250
+ `stim-desktop://open?serial=${serial}`
251
+ ], STIM_DESKTOP_OPEN_OPTIONS);
252
+ }
253
+ //#endregion
249
254
  //#region src/devices/android.ts
250
255
  const ANDROID_ABIS = /* @__PURE__ */ new Set([
251
256
  "armeabi-v7a",
@@ -254,11 +259,13 @@ const ANDROID_ABIS = /* @__PURE__ */ new Set([
254
259
  "x86_64"
255
260
  ]);
256
261
  const DEFAULT_AVD_DEVICE_PROFILE = String(settingDefinition("android.deviceProfile")?.default);
257
- function androidHome(env = process.env) {
262
+ function androidHome(env = ambientEnv()) {
258
263
  const configured = env.ANDROID_HOME || env.ANDROID_SDK_ROOT;
259
264
  if (configured) return configured;
260
- if (process.platform === "win32") return join$1(env.LOCALAPPDATA || join$1(homedir(), "AppData", "Local"), "Android", "Sdk");
261
- return join$1(homedir(), "Library", "Android", "sdk");
265
+ const home = process.platform === "win32" ? env.USERPROFILE || homedir() : env.HOME || homedir();
266
+ if (process.platform === "win32") return join$1(env.LOCALAPPDATA || join$1(home, "AppData", "Local"), "Android", "Sdk");
267
+ if (process.platform === "linux") return join$1(home, "Android", "Sdk");
268
+ return join$1(home, "Library", "Android", "sdk");
262
269
  }
263
270
  const SDK_TOOL_LOCATIONS = {
264
271
  emulator: ["emulator", "emulator"],
@@ -282,11 +289,11 @@ const WINDOWS_SDK_TOOL_EXTENSIONS = {
282
289
  avdmanager: ".bat",
283
290
  sdkmanager: ".bat"
284
291
  };
285
- function androidToolPath(tool, platform = process.platform) {
292
+ function androidToolPath(tool, platform = process.platform, env = ambientEnv()) {
286
293
  const location = SDK_TOOL_LOCATIONS[tool];
287
294
  const bare = location.at(-1);
288
295
  const name = platform === "win32" ? `${bare}${WINDOWS_SDK_TOOL_EXTENSIONS[tool]}` : bare;
289
- const abs = join$1(androidHome(), ...location.slice(0, -1), name);
296
+ const abs = join$1(androidHome(env), ...location.slice(0, -1), name);
290
297
  return existsSync(abs) ? abs : bare;
291
298
  }
292
299
  const WINDOWS_BUILD_TOOL_EXTENSIONS = { apksigner: ".bat" };
@@ -333,8 +340,8 @@ function findBuildTool(tools, { home = androidHome(), readDir = readdirSync, exi
333
340
  }
334
341
  return null;
335
342
  }
336
- function listInstalledSystemImages(onUnreadable) {
337
- const root = join$1(androidHome(), "system-images");
343
+ function listInstalledSystemImages(onUnreadable, env = ambientEnv()) {
344
+ const root = join$1(androidHome(env), "system-images");
338
345
  const images = [];
339
346
  const list = (dir) => {
340
347
  try {
@@ -402,9 +409,9 @@ async function createOwnedAvd(label, { systemImage, deviceProfile = DEFAULT_AVD_
402
409
  "--device",
403
410
  deviceProfile
404
411
  ];
405
- let env = process.env;
412
+ let env = ambientEnv();
406
413
  if (!env.ANDROID_AVD_HOME) {
407
- const root = avdLookupRoots(env, homedir())[0];
414
+ const root = avdLookupRoots(env, (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir())[0];
408
415
  mkdirSync(root, { recursive: true });
409
416
  env = {
410
417
  ...env,
@@ -496,10 +503,10 @@ function ownedAvdName(label) {
496
503
  return `stim-${clean.startsWith("stim-") ? clean.slice(5) : clean}`;
497
504
  }
498
505
  const AVDMANAGER_DELETE_TIMEOUT_MS = 12e4;
499
- function deleteAvd(avdName) {
506
+ async function deleteAvd(avdName) {
500
507
  if (!isStimOwnedAvd(avdName)) throw new Error(`Refusing to delete AVD "${avdName}": not a Stim-owned AVD; Stim has no record of creating it.`);
501
- const root = process.env.ANDROID_AVD_HOME ? void 0 : avdStorageRoots().find((candidate) => avdPathExists(join$1(candidate, `${avdName}.ini`)));
502
- getExecutor().runFile(androidToolPath("avdmanager"), [
508
+ const root = ambientEnv().ANDROID_AVD_HOME ? void 0 : avdStorageRoots().find((candidate) => avdPathExists(join$1(candidate, `${avdName}.ini`)));
509
+ await getExecutor().runFileAsync(androidToolPath("avdmanager"), [
503
510
  "delete",
504
511
  "avd",
505
512
  "-n",
@@ -559,6 +566,12 @@ function listAvds({ timeoutMs = ANDROID_LISTING_TIMEOUT_MS } = {}) {
559
566
  killSignal: "SIGKILL"
560
567
  }));
561
568
  }
569
+ async function listAvdsAsync({ timeoutMs = ANDROID_LISTING_TIMEOUT_MS } = {}) {
570
+ return parseAvdList(await getExecutor().runFileAsync(androidToolPath("emulator"), ["-list-avds"], {
571
+ timeoutMs,
572
+ killSignal: "SIGKILL"
573
+ }));
574
+ }
562
575
  /**
563
576
  * Working directory for the adb client and the emulator Stim starts. Both leave processes behind
564
577
  * that inherit it: the adb server is spawned by whichever client finds none running, and the
@@ -577,6 +590,13 @@ function listAdbDevices({ timeoutMs = ANDROID_LISTING_TIMEOUT_MS, platform = pro
577
590
  cwd: androidToolCwd(platform)
578
591
  }));
579
592
  }
593
+ async function listAdbDevicesAsync({ timeoutMs = ANDROID_LISTING_TIMEOUT_MS, platform = process.platform } = {}) {
594
+ return parseAdbDevices(await getExecutor().runFileAsync(androidToolPath("adb"), ["devices"], {
595
+ timeoutMs,
596
+ killSignal: "SIGKILL",
597
+ cwd: androidToolCwd(platform)
598
+ }));
599
+ }
580
600
  const ADB_PROP_TIMEOUT_MS = 5e3;
581
601
  const EMULATOR_HARDWARE = /* @__PURE__ */ new Set([
582
602
  "ranchu",
@@ -688,7 +708,7 @@ function nextConsolePort(claimedPorts) {
688
708
  if (claimedPorts.length === 0) return 5554;
689
709
  return Math.max(...claimedPorts) + 2;
690
710
  }
691
- function headlessEmulatorArgs(env = process.env, platform = process.platform, app = "emulator") {
711
+ function headlessEmulatorArgs(env = ambientEnv(), platform = process.platform, app = "emulator") {
692
712
  const args = [];
693
713
  if (platform === "darwin" && app === "stim-desktop") args.push("-no-window", "-gpu", "host");
694
714
  if (platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY) args.push("-no-window", "-noaudio", "-no-boot-anim", "-gpu", "swiftshader_indirect", "-no-snapshot-save", "-no-snapshot-load");
@@ -717,15 +737,15 @@ function avdIniPaths(root, ini) {
717
737
  const parsed = parseAvdRootIni(ini);
718
738
  return [parsed.relativePath && !isAbsolute$1(parsed.relativePath) ? resolve$1(dirname$1(root), parsed.relativePath) : null, parsed.path && isAbsolute$1(parsed.path) ? parsed.path : null].filter((candidate) => candidate !== null);
719
739
  }
720
- function avdStorageRoots() {
721
- const env = process.env;
740
+ function avdStorageRoots(env = ambientEnv()) {
741
+ const home = process.platform === "win32" ? env.USERPROFILE || homedir() : env.HOME || homedir();
722
742
  return [...new Set([
723
743
  env.ANDROID_AVD_HOME,
724
744
  env.ANDROID_EMULATOR_HOME ? join$1(env.ANDROID_EMULATOR_HOME, "avd") : null,
725
745
  env.ANDROID_USER_HOME ? join$1(env.ANDROID_USER_HOME, "avd") : null,
726
746
  env.ANDROID_SDK_HOME ? join$1(env.ANDROID_SDK_HOME, ".android", "avd") : null,
727
747
  env.ANDROID_SDK_HOME ? join$1(env.ANDROID_SDK_HOME, "avd") : null,
728
- join$1(homedir(), ".android", "avd")
748
+ join$1(home, ".android", "avd")
729
749
  ].filter((value) => Boolean(value)))];
730
750
  }
731
751
  function avdPathExists(path) {
@@ -803,7 +823,7 @@ function avdLookupRoots(env, home) {
803
823
  ];
804
824
  return [...new Set(roots.filter((value) => Boolean(value)))];
805
825
  }
806
- function ownedAvdDirectory(avdName, { env = process.env, home = homedir(), readFile = (path) => readFileSync(path, "utf8"), realpath = realpathSync, isDirectory = (path) => statSync(path).isDirectory() } = {}) {
826
+ function ownedAvdDirectory(avdName, { env = ambientEnv(), home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir(), readFile = (path) => readFileSync(path, "utf8"), realpath = realpathSync, isDirectory = (path) => statSync(path).isDirectory() } = {}) {
807
827
  if (!/^stim-[A-Za-z0-9._-]+$/.test(avdName)) return null;
808
828
  for (const root of avdLookupRoots(env, home)) {
809
829
  let ini;
@@ -911,16 +931,16 @@ async function resetAdoptedAvd(avdName, serial, keepPackage) {
911
931
  let firstFailure;
912
932
  let unavailableTarget = false;
913
933
  const commandTimeout = (timeoutMs) => recoveryDeadline === void 0 ? timeoutMs : Math.max(1, Math.min(timeoutMs, recoveryDeadline - Date.now()));
914
- const assertTarget = () => {
915
- const resolved = resolveOwnedAvdSerial(avdName, { timeoutMs: commandTimeout(3e4) });
934
+ const assertTarget = async () => {
935
+ const resolved = await resolveOwnedAvdSerialAsync(avdName, { timeoutMs: commandTimeout(3e4) });
916
936
  unavailableTarget = Boolean(resolved.notRunning);
917
937
  if (resolved.serial !== serial) throw new Error(`AVD ${avdName} is no longer running on ${serial}.`);
918
938
  };
919
939
  for (;;) {
920
940
  unavailableTarget = false;
921
941
  try {
922
- assertTarget();
923
- const packages = exec.runFile("adb", [
942
+ await assertTarget();
943
+ const packages = (await exec.runFileAsync("adb", [
924
944
  "-s",
925
945
  serial,
926
946
  "shell",
@@ -928,20 +948,20 @@ async function resetAdoptedAvd(avdName, serial, keepPackage) {
928
948
  "list",
929
949
  "packages",
930
950
  "-3"
931
- ], { timeoutMs: commandTimeout(3e4) }).split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => {
951
+ ], { timeoutMs: commandTimeout(3e4) })).split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => {
932
952
  const match = /^package:([A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)+)$/.exec(line);
933
953
  if (!match) throw new Error(`Could not read installed apps on ${avdName}: ${line}`);
934
954
  return match[1];
935
955
  });
936
956
  for (const packageName of packages) {
937
- assertTarget();
957
+ await assertTarget();
938
958
  const args = packageName === keepPackage ? [
939
959
  "shell",
940
960
  "pm",
941
961
  "clear",
942
962
  packageName
943
963
  ] : ["uninstall", packageName];
944
- const result = exec.runFile("adb", [
964
+ const result = await exec.runFileAsync("adb", [
945
965
  "-s",
946
966
  serial,
947
967
  ...args
@@ -974,8 +994,8 @@ function parseDfAvailableBytes(text) {
974
994
  const available = lines[1].split(/\s+/)[3];
975
995
  return available && /^\d+$/.test(available) ? Number(available) * 1024 : null;
976
996
  }
977
- function androidDataFreeBytes(serial) {
978
- return parseDfAvailableBytes(getExecutor().runFileQuiet("adb", [
997
+ async function androidDataFreeBytes(serial) {
998
+ return parseDfAvailableBytes(await getExecutor().runFileQuietAsync("adb", [
979
999
  "-s",
980
1000
  serial,
981
1001
  "shell",
@@ -984,8 +1004,8 @@ function androidDataFreeBytes(serial) {
984
1004
  "/data"
985
1005
  ], { timeoutMs: 3e4 }));
986
1006
  }
987
- function trimAndroidCaches(serial, desiredFreeBytes) {
988
- getExecutor().runFile("adb", [
1007
+ async function trimAndroidCaches(serial, desiredFreeBytes) {
1008
+ await getExecutor().runFileAsync("adb", [
989
1009
  "-s",
990
1010
  serial,
991
1011
  "shell",
@@ -1010,7 +1030,7 @@ const CRASH_REPORT_MODE_EMULATOR_VERSION = 37;
1010
1030
  * Where the emulator keeps crashpad's database on Windows: `AndroidEmulator\emu-crash-<version>.db`
1011
1031
  * under GetTempPath, which reads TMP before TEMP.
1012
1032
  */
1013
- function emulatorCrashDatabases(env = process.env) {
1033
+ function emulatorCrashDatabases(env = ambientEnv()) {
1014
1034
  const root = join$1(env.TMP || env.TEMP || tmpdir(), "AndroidEmulator");
1015
1035
  try {
1016
1036
  return readdirSync(root).filter((name) => /^emu-crash-.*\.db$/.test(name)).map((name) => join$1(root, name));
@@ -1039,9 +1059,9 @@ function suppressEmulatorCrashConsent({ platform = process.platform, version = e
1039
1059
  } catch {}
1040
1060
  return [];
1041
1061
  }
1042
- function bootAndroidEmulator(avdName, consolePort, { logFile, platform = process.platform, openViewer = true } = {}) {
1062
+ async function bootAndroidEmulator(avdName, consolePort, { logFile, platform = process.platform, openViewer = true } = {}) {
1043
1063
  const exec = getExecutor();
1044
- const app = configuredAndroidEmulatorApp(platform);
1064
+ const app = await configuredAndroidEmulatorApp(platform, ambientEnv());
1045
1065
  const child = exec.spawn(androidToolPath("emulator"), [
1046
1066
  "-avd",
1047
1067
  avdName,
@@ -1050,7 +1070,7 @@ function bootAndroidEmulator(avdName, consolePort, { logFile, platform = process
1050
1070
  "-grpc",
1051
1071
  String(consolePort + 3e3),
1052
1072
  "-grpc-use-token",
1053
- ...headlessEmulatorArgs(process.env, platform, openViewer ? app : "stim-desktop"),
1073
+ ...headlessEmulatorArgs(ambientEnv(), platform, openViewer ? app : "stim-desktop"),
1054
1074
  ...suppressEmulatorCrashConsent({ platform })
1055
1075
  ], {
1056
1076
  cwd: androidToolCwd(platform),
@@ -1059,7 +1079,7 @@ function bootAndroidEmulator(avdName, consolePort, { logFile, platform = process
1059
1079
  });
1060
1080
  child?.unref?.();
1061
1081
  const pid = child?.pid ?? null;
1062
- if (openViewer && pid !== null && platform === "darwin" && app === "stim-desktop") openEmulatorInStimDesktop(`emulator-${consolePort}`);
1082
+ if (openViewer && pid !== null && platform === "darwin" && app === "stim-desktop") await openEmulatorInStimDesktop(`emulator-${consolePort}`);
1063
1083
  return pid;
1064
1084
  }
1065
1085
  function emulatorStdio(logFile) {
@@ -1114,8 +1134,8 @@ function emulatorDiskSpaceRemedy(lines) {
1114
1134
  function emulatorFailureRemedy(lines) {
1115
1135
  return emulatorDiskSpaceRemedy(lines) ?? "Fix what the emulator reported above, then run `stim android` again.";
1116
1136
  }
1117
- function getprop(exec, serial, prop, timeoutMs) {
1118
- const out = exec.runFileQuiet(androidToolPath("adb"), [
1137
+ async function getprop(exec, serial, prop, timeoutMs) {
1138
+ const out = await exec.runFileQuietAsync(androidToolPath("adb"), [
1119
1139
  "-s",
1120
1140
  serial,
1121
1141
  "shell",
@@ -1130,8 +1150,8 @@ const PACKAGE_MANAGER_PROBE = [
1130
1150
  "path",
1131
1151
  "android"
1132
1152
  ];
1133
- function packageManagerReady(exec, serial, timeoutMs) {
1134
- const out = exec.runFileQuiet(androidToolPath("adb"), [
1153
+ async function packageManagerReady(exec, serial, timeoutMs) {
1154
+ const out = await exec.runFileQuietAsync(androidToolPath("adb"), [
1135
1155
  "-s",
1136
1156
  serial,
1137
1157
  ...PACKAGE_MANAGER_PROBE
@@ -1144,7 +1164,7 @@ async function waitForBoot(serial, timeoutMs = 6e4, { aborted = () => false, pol
1144
1164
  let exited = false;
1145
1165
  const probeTimeout = () => Math.max(1, Math.min(commandTimeoutMs ?? timeoutMs, timeoutMs - (Date.now() - start)));
1146
1166
  while (Date.now() - start < timeoutMs) {
1147
- if ((getprop(exec, serial, "sys.boot_completed", probeTimeout()) === "1" || getprop(exec, serial, "dev.bootcomplete", probeTimeout()) === "1") && packageManagerReady(exec, serial, probeTimeout())) return { ok: true };
1167
+ if ((await getprop(exec, serial, "sys.boot_completed", probeTimeout()) === "1" || await getprop(exec, serial, "dev.bootcomplete", probeTimeout()) === "1") && await packageManagerReady(exec, serial, probeTimeout())) return { ok: true };
1148
1168
  if (aborted()) {
1149
1169
  exited = true;
1150
1170
  break;
@@ -1152,39 +1172,39 @@ async function waitForBoot(serial, timeoutMs = 6e4, { aborted = () => false, pol
1152
1172
  await new Promise((r) => setTimeout(r, commandTimeoutMs === void 0 ? pollMs : Math.min(pollMs, Math.max(0, timeoutMs - (Date.now() - start)))));
1153
1173
  }
1154
1174
  const diagnosticDeadline = Date.now() + Math.min(commandTimeoutMs ?? 5e3, 5e3);
1155
- const diagnosticQuery = (args) => {
1175
+ const diagnosticQuery = async (args) => {
1156
1176
  const remaining = diagnosticDeadline - Date.now();
1157
1177
  if (remaining <= 0) return "";
1158
- const value = exec.runFileQuiet(androidToolPath("adb"), args, { timeoutMs: remaining });
1178
+ const value = await exec.runFileQuietAsync(androidToolPath("adb"), args, { timeoutMs: remaining });
1159
1179
  return typeof value === "string" ? value.trim() : "";
1160
1180
  };
1161
1181
  return {
1162
1182
  ok: false,
1163
1183
  ...exited ? { exited: true } : {},
1164
1184
  diagnostic: {
1165
- devices: diagnosticQuery(["devices"]),
1166
- sysBoot: diagnosticQuery([
1185
+ devices: await diagnosticQuery(["devices"]),
1186
+ sysBoot: await diagnosticQuery([
1167
1187
  "-s",
1168
1188
  serial,
1169
1189
  "shell",
1170
1190
  "getprop",
1171
1191
  "sys.boot_completed"
1172
1192
  ]),
1173
- devBoot: diagnosticQuery([
1193
+ devBoot: await diagnosticQuery([
1174
1194
  "-s",
1175
1195
  serial,
1176
1196
  "shell",
1177
1197
  "getprop",
1178
1198
  "dev.bootcomplete"
1179
1199
  ]),
1180
- bootAnim: diagnosticQuery([
1200
+ bootAnim: await diagnosticQuery([
1181
1201
  "-s",
1182
1202
  serial,
1183
1203
  "shell",
1184
1204
  "getprop",
1185
1205
  "init.svc.bootanim"
1186
1206
  ]),
1187
- packageManager: diagnosticQuery([
1207
+ packageManager: await diagnosticQuery([
1188
1208
  "-s",
1189
1209
  serial,
1190
1210
  ...PACKAGE_MANAGER_PROBE
@@ -1194,24 +1214,27 @@ async function waitForBoot(serial, timeoutMs = 6e4, { aborted = () => false, pol
1194
1214
  }
1195
1215
  const ANDROID_EMULATOR_SHUTDOWN_TIMEOUT_MS = 6e4;
1196
1216
  const ANDROID_EMULATOR_SHUTDOWN_POLL_MS = 100;
1197
- function shutdownAndroidEmulator(serial, timeoutMs = ANDROID_EMULATOR_SHUTDOWN_TIMEOUT_MS) {
1217
+ async function shutdownAndroidEmulator(serial, timeoutMs = ANDROID_EMULATOR_SHUTDOWN_TIMEOUT_MS) {
1198
1218
  const exec = getExecutor();
1199
1219
  const started = Date.now();
1200
- if (exec.runFileQuiet(androidToolPath("adb"), [
1220
+ if (await exec.runFileQuietAsync(androidToolPath("adb"), [
1201
1221
  "-s",
1202
1222
  serial,
1203
1223
  "shell",
1204
1224
  "sync"
1205
- ], { timeoutMs: Math.min(5e3, timeoutMs) }) === null) console.error(`warning: could not flush ${serial} before shutdown; shutting it down anyway`);
1206
- exec.runFileQuiet(androidToolPath("adb"), [
1225
+ ], {
1226
+ timeoutMs: Math.min(5e3, timeoutMs),
1227
+ killSignal: "SIGKILL"
1228
+ }) === null) ambientWrite("stderr", `warning: could not flush ${serial} before shutdown; shutting it down anyway\n`);
1229
+ await exec.runFileQuietAsync(androidToolPath("adb"), [
1207
1230
  "-s",
1208
1231
  serial,
1209
1232
  "emu",
1210
1233
  "kill"
1211
- ], { timeoutMs: Math.max(1, timeoutMs - (Date.now() - started)) });
1212
- }
1213
- function sleepSync(ms) {
1214
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
1234
+ ], {
1235
+ timeoutMs: Math.max(1, timeoutMs - (Date.now() - started)),
1236
+ killSignal: "SIGKILL"
1237
+ });
1215
1238
  }
1216
1239
  function avdProcessLockPaths(avdDirectory, platform) {
1217
1240
  return ["hardware-qemu.ini.lock", "userdata-qemu.img.lock"].map((name) => join$1(avdDirectory, name, ...platform === "win32" ? ["pid"] : []));
@@ -1263,6 +1286,18 @@ function listAvdEmulatorProcesses(avdName, platform) {
1263
1286
  ], { timeoutMs: 5e3 });
1264
1287
  return out === null ? null : parseAvdEmulatorProcesses(out, avdName);
1265
1288
  }
1289
+ async function listAvdEmulatorProcessesAsync(avdName, platform) {
1290
+ if (platform === "win32") return [];
1291
+ const out = await getExecutor().runFileQuietAsync("ps", [
1292
+ "-axww",
1293
+ "-o",
1294
+ "pid=,command="
1295
+ ], {
1296
+ timeoutMs: 5e3,
1297
+ killSignal: "SIGKILL"
1298
+ });
1299
+ return out === null ? null : parseAvdEmulatorProcesses(out, avdName);
1300
+ }
1266
1301
  function scanAvdEmulatorProcesses(avdName, platform, listProcesses) {
1267
1302
  const pids = listProcesses(avdName, platform);
1268
1303
  if (pids === null) throw new Error(`Could not read the process table to verify that owned AVD ${avdName} stopped.`);
@@ -1291,13 +1326,16 @@ const CRASH_HANDLER_EXIT_TIMEOUT_MS = 15e3;
1291
1326
  * it writes the dump, so a `stop` that returns on qemu's exit leaves it running.
1292
1327
  * https://github.com/appandflow/stim/issues/918
1293
1328
  */
1294
- function emulatorCrashHandlerPids(qemuPid) {
1295
- const out = getExecutor().runFileQuiet("powershell.exe", [
1329
+ async function emulatorCrashHandlerPids(qemuPid) {
1330
+ const out = await getExecutor().runFileQuietAsync("powershell.exe", [
1296
1331
  "-NoProfile",
1297
1332
  "-NonInteractive",
1298
1333
  "-Command",
1299
1334
  `Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'crashpad_handler.exe' -and $_.ParentProcessId -eq ${qemuPid} } | ForEach-Object ProcessId`
1300
- ], { timeoutMs: 1e4 });
1335
+ ], {
1336
+ timeoutMs: 1e4,
1337
+ killSignal: "SIGKILL"
1338
+ });
1301
1339
  return String(out ?? "").split(/\r?\n/).map((line) => Number(line.trim())).filter((pid) => Number.isSafeInteger(pid) && pid > 0);
1302
1340
  }
1303
1341
  const EMULATOR_SIGNAL_GRACE_MS = 5e3;
@@ -1308,14 +1346,19 @@ const EMULATOR_SIGNAL_GRACE_MS = 5e3;
1308
1346
  * grace, but only a process whose command line names this AVD and whose identity, captured before
1309
1347
  * shutdown, still matches. Windows has no process-table scan, so there nothing is signalled.
1310
1348
  */
1311
- function waitForAndroidEmulatorShutdown(avdName, shutdown, { timeoutMs = ANDROID_EMULATOR_SHUTDOWN_TIMEOUT_MS, pollMs = ANDROID_EMULATOR_SHUTDOWN_POLL_MS, signalGraceMs = EMULATOR_SIGNAL_GRACE_MS, platform = process.platform, resolveDirectory = ownedAvdDirectory, readProcessId = readAvdProcessId, processAlive = pidExists, listProcesses = listAvdEmulatorProcesses, captureIdentity = process_identity_exports.captureProcessIdentity, inspectIdentity = process_identity_exports.inspectProcessIdentity, signal = (pid, name) => signalProcessTree(pid, name, { platform }), directoryExists = (path) => statSync(path).isDirectory(), crashHandlerPids = emulatorCrashHandlerPids, killCrashHandler = (pid) => signalProcessTree(pid, "SIGKILL", { platform }), now = Date.now, sleep = sleepSync } = {}) {
1349
+ async function waitForAndroidEmulatorShutdown(avdName, shutdown, { timeoutMs = ANDROID_EMULATOR_SHUTDOWN_TIMEOUT_MS, pollMs = ANDROID_EMULATOR_SHUTDOWN_POLL_MS, signalGraceMs = EMULATOR_SIGNAL_GRACE_MS, platform = process.platform, resolveDirectory = ownedAvdDirectory, readProcessId = readAvdProcessId, processAlive = pidExists, listProcesses = listAvdEmulatorProcessesAsync, captureIdentity = process_identity_exports.captureProcessIdentity, inspectIdentity = process_identity_exports.inspectProcessIdentity, signal = (pid, name) => signalProcessTreeAsync(pid, name, { platform }), directoryExists = (path) => statSync(path).isDirectory(), crashHandlerPids = emulatorCrashHandlerPids, killCrashHandler = (pid) => signalProcessTreeAsync(pid, "SIGKILL", { platform }), now = Date.now, sleep = (ms) => new Promise((done) => setTimeout(done, ms)) } = {}) {
1312
1350
  const { directory, processId } = resolveAvdProcess(avdName, {
1313
1351
  platform,
1314
1352
  resolveDirectory,
1315
1353
  readProcessId
1316
1354
  });
1355
+ const scan = async () => {
1356
+ const pids = await listProcesses(avdName, platform);
1357
+ if (pids === null) throw new Error(`Could not read the process table to verify that owned AVD ${avdName} stopped.`);
1358
+ return pids;
1359
+ };
1317
1360
  const identities = /* @__PURE__ */ new Map();
1318
- for (const pid of scanAvdEmulatorProcesses(avdName, platform, listProcesses)) {
1361
+ for (const pid of await scan()) {
1319
1362
  const captured = captureIdentity(pid);
1320
1363
  identities.set(pid, captured.ok ? {
1321
1364
  pid,
@@ -1337,20 +1380,20 @@ function waitForAndroidEmulatorShutdown(avdName, shutdown, { timeoutMs = ANDROID
1337
1380
  if (processId !== null && !identities.has(processId) && processAlive(processId)) pids.push(processId);
1338
1381
  return pids;
1339
1382
  };
1340
- const waitUntil = (until) => {
1383
+ const waitUntil = async (until) => {
1341
1384
  for (;;) {
1342
1385
  if (running().length === 0) return true;
1343
1386
  const remaining = until - now();
1344
1387
  if (remaining <= 0) return false;
1345
- sleep(Math.min(pollMs, remaining));
1388
+ await sleep(Math.min(pollMs, remaining));
1346
1389
  }
1347
1390
  };
1348
1391
  const started = now();
1349
1392
  if (shutdown) {
1350
1393
  const deadline = started + timeoutMs;
1351
1394
  const shutdownTimeoutMs = deadline - now();
1352
- if (shutdownTimeoutMs > 0) shutdown(shutdownTimeoutMs);
1353
- waitUntil(deadline);
1395
+ if (shutdownTimeoutMs > 0) await shutdown(shutdownTimeoutMs);
1396
+ await waitUntil(deadline);
1354
1397
  }
1355
1398
  for (const name of ["SIGTERM", "SIGKILL"]) {
1356
1399
  const verified = running().filter((pid) => {
@@ -1359,13 +1402,13 @@ function waitForAndroidEmulatorShutdown(avdName, shutdown, { timeoutMs = ANDROID
1359
1402
  });
1360
1403
  if (verified.length === 0) break;
1361
1404
  for (const pid of verified) try {
1362
- signal(pid, name);
1405
+ await signal(pid, name);
1363
1406
  } catch {}
1364
1407
  const graceMs = name === "SIGTERM" && !shutdown ? timeoutMs : signalGraceMs;
1365
- if (waitUntil(now() + graceMs)) break;
1408
+ if (await waitUntil(now() + graceMs)) break;
1366
1409
  }
1367
1410
  const left = new Set(running());
1368
- for (const pid of scanAvdEmulatorProcesses(avdName, platform, listProcesses)) {
1411
+ for (const pid of await scan()) {
1369
1412
  const record = identities.get(pid);
1370
1413
  if (record === void 0 || (record === null ? processAlive(pid) : inspectIdentity(record) !== "gone")) left.add(pid);
1371
1414
  }
@@ -1380,10 +1423,10 @@ function waitForAndroidEmulatorShutdown(avdName, shutdown, { timeoutMs = ANDROID
1380
1423
  }
1381
1424
  if (platform === "win32" && processId !== null) {
1382
1425
  const handlerDeadline = now() + CRASH_HANDLER_EXIT_TIMEOUT_MS;
1383
- for (const handler of crashHandlerPids(processId)) {
1384
- while (processAlive(handler) && now() < handlerDeadline) sleep(pollMs);
1426
+ for (const handler of await crashHandlerPids(processId)) {
1427
+ while (processAlive(handler) && now() < handlerDeadline) await sleep(pollMs);
1385
1428
  if (processAlive(handler)) {
1386
- killCrashHandler(handler);
1429
+ await killCrashHandler(handler);
1387
1430
  if (processAlive(handler)) throw new Error(`Crashpad handler ${handler} for owned AVD ${avdName} stayed alive.`);
1388
1431
  }
1389
1432
  }
@@ -1405,8 +1448,47 @@ function getAvdNameForSerial(serial, { timeoutMs = EMU_AVD_NAME_TIMEOUT_MS } = {
1405
1448
  if (!out) return null;
1406
1449
  return out.split("\n")[0]?.trim() || null;
1407
1450
  }
1408
- function resolveOwnedAvdSerial(avdName, opts = {}) {
1409
- return ownedAvdSerialResolver(opts)(avdName);
1451
+ async function getAvdNameForSerialAsync(serial, { timeoutMs = EMU_AVD_NAME_TIMEOUT_MS } = {}) {
1452
+ const out = await getExecutor().runFileQuietAsync(androidToolPath("adb"), [
1453
+ "-s",
1454
+ serial,
1455
+ "emu",
1456
+ "avd",
1457
+ "name"
1458
+ ], {
1459
+ timeoutMs: Math.min(timeoutMs, EMU_AVD_NAME_TIMEOUT_MS),
1460
+ killSignal: "SIGKILL"
1461
+ });
1462
+ if (!out) return null;
1463
+ return out.split("\n")[0]?.trim() || null;
1464
+ }
1465
+ /** `resolveOwnedAvdSerial` without blocking the event loop, with the same reads and the same timeout budget. */
1466
+ async function resolveOwnedAvdSerialAsync(avdName, opts = {}) {
1467
+ return ownedAvdSerialResolverAsync(opts)(avdName);
1468
+ }
1469
+ /** Shares bounded asynchronous AVD, adb and emulator-name reads across the requested AVDs. */
1470
+ function ownedAvdSerialResolverAsync({ timeoutMs } = {}) {
1471
+ const started = Date.now();
1472
+ const remaining = () => ({ timeoutMs: timeoutMs === void 0 ? void 0 : Math.max(MIN_LOOKUP_TIMEOUT_MS, timeoutMs - (Date.now() - started)) });
1473
+ const avds = once(() => listAvdsAsync(remaining()));
1474
+ const adb = once(() => listAdbDevicesAsync(remaining()));
1475
+ const names = /* @__PURE__ */ new Map();
1476
+ const avdNameOf = (serial) => {
1477
+ let name = names.get(serial);
1478
+ if (!name) {
1479
+ name = getAvdNameForSerialAsync(serial, remaining());
1480
+ names.set(serial, name);
1481
+ }
1482
+ return name;
1483
+ };
1484
+ return async (avdName) => {
1485
+ if (!(await avds()).includes(avdName)) return { missing: true };
1486
+ if (!isStimOwnedAvd(avdName)) return { notOwned: true };
1487
+ const devices = await adb();
1488
+ const candidates = [...devices.emulators, ...devices.unhealthy.filter((entry) => entry.kind === "emulator" && entry.consolePort !== void 0)];
1489
+ for (const candidate of candidates) if (await avdNameOf(candidate.serial) === avdName) return { serial: candidate.serial };
1490
+ return { notRunning: true };
1491
+ };
1410
1492
  }
1411
1493
  function once(read) {
1412
1494
  let result;
@@ -1448,4 +1530,4 @@ function ownedAvdSerialResolver({ timeoutMs } = {}) {
1448
1530
  };
1449
1531
  }
1450
1532
  //#endregion
1451
- export { trimAndroidCaches as $, listAvds as A, ownedAvdSystemImage as B, emulatorFailureRemedy as C, hostSystemImageArch as D, getAvdNameForSerial as E, ownedAvdDeviceProfile as F, probeEmulatorSerial as G, parseAvdSystemImage as H, ownedAvdDirectory as I, resolveOwnedAvdSerial as J, profileNeedsFoldFeature as K, ownedAvdMatchesConfiguration as L, listOrphanedAvdDirectories as M, memoizeEmulatorProbe as N, listAdbDevices as O, nextConsolePort as P, systemImageSupportsFold as Q, ownedAvdName as R, emulatorDiskSpaceRemedy as S, findBuildTool as T, physicalDeviceModel as U, parseAvdDeviceProfile as V, pickDefaultSystemImage as W, shutdownAndroidEmulator as X, resolvePhysicalDevice as Y, sleepSync as Z, avdStorageRoots as _, androidDeviceAbi as a, POOL_SETTING_REMEDY as at, createOwnedAvd as b, androidPoolNoCandidatesRefusal as c, eraseParkedAfter as ct, androidToolPath as d, parkedMaxSetting as dt, waitForAndroidEmulatorShutdown as et, assertOwnedAvdStopped as f, readParked as ft, avdPoolConfiguration as g, avdPathExists as h, configuredAndroidEmulatorApp as ht, androidDataFreeBytes as i, isStimOwnedSim as it, listInstalledSystemImages as j, listAvdDeviceProfiles as k, androidSystemImageAbi as l, isLegacyDeletionClaim as lt, avdNameAbsent as m, selectParked as mt, OWNED_AVD_CONFIG_DEFAULTS as n, wipeAvdUserData as nt, androidHome as o, adoptParked as ot, avdIniPaths as p, removeParkedAfter as pt, resetAdoptedAvd as q, androidBuildToolName as r, isStimOwnedAvd as rt, androidPoolCandidates as s, dropParked as st, DEFAULT_AVD_DEVICE_PROFILE as t, waitForBoot as tt, androidToolCwd as u, parkSim as ut, bootAndroidEmulator as v, extractEmulatorFailure as w, deleteAvd as x, configureNewOwnedAvd as y, ownedAvdSerialResolver as z };
1533
+ export { resolvePhysicalDevice as $, listAdbDevicesAsync as A, ownedAvdMatchesConfiguration as B, emulatorFailureRemedy as C, getAvdNameForSerialAsync as D, getAvdNameForSerial as E, listOrphanedAvdDirectories as F, parseAvdDeviceProfile as G, ownedAvdSerialResolver as H, memoizeEmulatorProbe as I, pickDefaultSystemImage as J, parseAvdSystemImage as K, nextConsolePort as L, listAvds as M, listAvdsAsync as N, hostSystemImageArch as O, listInstalledSystemImages as P, resolveOwnedAvdSerialAsync as Q, ownedAvdDeviceProfile as R, emulatorDiskSpaceRemedy as S, findBuildTool as T, ownedAvdSerialResolverAsync as U, ownedAvdName as V, ownedAvdSystemImage as W, profileNeedsFoldFeature as X, probeEmulatorSerial as Y, resetAdoptedAvd as Z, avdStorageRoots as _, removeParkedAfter as _t, androidDeviceAbi as a, wipeAvdUserData as at, createOwnedAvd as b, androidPoolNoCandidatesRefusal as c, isStimOwnedSim as ct, androidToolPath as d, dropParked as dt, shutdownAndroidEmulator as et, assertOwnedAvdStopped as f, eraseParkedAfter as ft, avdPoolConfiguration as g, readParked as gt, avdPathExists as h, parkedMaxSetting as ht, androidDataFreeBytes as i, waitForBoot as it, listAvdDeviceProfiles as j, listAdbDevices as k, androidSystemImageAbi as l, POOL_SETTING_REMEDY as lt, avdNameAbsent as m, parkSim as mt, OWNED_AVD_CONFIG_DEFAULTS as n, trimAndroidCaches as nt, androidHome as o, configuredAndroidEmulatorApp as ot, avdIniPaths as p, isLegacyDeletionClaim as pt, physicalDeviceModel as q, androidBuildToolName as r, waitForAndroidEmulatorShutdown as rt, androidPoolCandidates as s, isStimOwnedAvd as st, DEFAULT_AVD_DEVICE_PROFILE as t, systemImageSupportsFold as tt, androidToolCwd as u, adoptParked as ut, bootAndroidEmulator as v, selectParked as vt, extractEmulatorFailure as w, deleteAvd as x, configureNewOwnedAvd as y, ownedAvdDirectory as z };