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,11 +1,35 @@
1
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
2
- import { Ft as makeTemporaryDirectory, It as removeTemporaryEntry } from "./settings-B717odTD.mjs";
1
+ import { s as spawnDeclared, t as getExecutor, u as operationState } from "./exec-_UbtCQcG.mjs";
3
2
  import { r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { t as cleanLine } from "./server-expo-DsguMGUF.mjs";
5
- import { M as startBuildHeartbeat, P as tailLines, y as HEARTBEAT_INTERVAL_MS } from "./toolchain-DxSsNssu.mjs";
3
+ import { Gt as childEnvironment, Xt as removeTemporaryEntry, Yt as makeTemporaryDirectory, en as throwIfCancelled, qt as killOnAbort } from "./settings-CsJDEXgK.mjs";
4
+ import { Xn as bundleInvocation } from "./budget-Bs6SxxzO.mjs";
5
+ import { t as cleanLine } from "./server-expo-DT_F_uVI.mjs";
6
+ import { _ as tailLines, h as startBuildHeartbeat, r as HEARTBEAT_INTERVAL_MS } from "./xcode-Zlx3qjEs.mjs";
7
+ import { randomUUID } from "node:crypto";
6
8
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
7
9
  import { basename, join } from "node:path";
8
- import { randomUUID } from "node:crypto";
10
+ //#region src/engine/operation-exec.ts
11
+ async function runOperationFile(context, executor, file, args, options) {
12
+ const signal = context ? operationState(context).runSignal ?? context.signal : void 0;
13
+ throwIfCancelled(signal, file);
14
+ const environment = context ? childEnvironment(context.env) : {
15
+ env: {},
16
+ omitEnv: []
17
+ };
18
+ const output = await executor.runFileAsync(file, args, {
19
+ ...environment,
20
+ ...options,
21
+ ...context ? { env: {
22
+ ...environment.env,
23
+ ...options.env
24
+ } } : {},
25
+ omitEnv: [...environment.omitEnv.filter((name) => options.env?.[name] === void 0), ...options.omitEnv ?? []],
26
+ declareFor: context,
27
+ onSpawn: killOnAbort(signal)
28
+ });
29
+ throwIfCancelled(signal, file);
30
+ return output;
31
+ }
32
+ //#endregion
9
33
  //#region src/engine/js-swap.ts
10
34
  const JS_BUNDLE_NAME = "main.jsbundle";
11
35
  const LAST_LINES = 5;
@@ -107,9 +131,9 @@ function assetCatalogTarget(infoPlist) {
107
131
  targetDevices: targetDevices.length ? targetDevices : ["iphone"]
108
132
  };
109
133
  }
110
- function readPlistKey(e, plist, key, format) {
134
+ async function readPlistKey(context, e, plist, key, format) {
111
135
  try {
112
- return e.runFile("plutil", [
136
+ return await runOperationFile(context, e, "plutil", [
113
137
  "-extract",
114
138
  key,
115
139
  format,
@@ -122,14 +146,14 @@ function readPlistKey(e, plist, key, format) {
122
146
  throw err;
123
147
  }
124
148
  }
125
- function readAssetCatalogTarget(e, plist) {
126
- const flag = readPlistKey(e, plist, "RCTUseAssetCatalog", "raw");
149
+ async function readAssetCatalogTarget(context, e, plist) {
150
+ const flag = await readPlistKey(context, e, plist, "RCTUseAssetCatalog", "raw");
127
151
  if (flag === null) return null;
128
- const families = readPlistKey(e, plist, "UIDeviceFamily", "json");
152
+ const families = await readPlistKey(context, e, plist, "UIDeviceFamily", "json");
129
153
  return assetCatalogTarget({
130
154
  RCTUseAssetCatalog: flag,
131
- DTPlatformName: readPlistKey(e, plist, "DTPlatformName", "raw"),
132
- MinimumOSVersion: readPlistKey(e, plist, "MinimumOSVersion", "raw"),
155
+ DTPlatformName: await readPlistKey(context, e, plist, "DTPlatformName", "raw"),
156
+ MinimumOSVersion: await readPlistKey(context, e, plist, "MinimumOSVersion", "raw"),
133
157
  UIDeviceFamily: families === null ? void 0 : JSON.parse(families)
134
158
  });
135
159
  }
@@ -206,7 +230,7 @@ function hermescArgs({ bundle, out }) {
206
230
  bundle
207
231
  ];
208
232
  }
209
- async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = null, exec = null, spawnFn = null, mkdtemp = () => makeTemporaryDirectory(cachedAppPath, "stim-js-swap-"), exists = existsSync, hermesEnabled = null, now = Date.now, heartbeatMs = HEARTBEAT_INTERVAL_MS, onHeartbeat = (line) => console.error(line) }) {
233
+ async function swapJsBundle({ context, root, iosDir, isExpo, cachedAppPath, logWriter = null, exec = null, spawnFn = null, mkdtemp = () => makeTemporaryDirectory(cachedAppPath, "stim-js-swap-"), exists = existsSync, hermesEnabled = null, now = Date.now, heartbeatMs = HEARTBEAT_INTERVAL_MS, onHeartbeat = (line) => console.error(line) }) {
210
234
  const e = exec || getExecutor();
211
235
  const startedAt = now();
212
236
  const elapsed = () => now() - startedAt;
@@ -232,15 +256,16 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
232
256
  tmp = mkdtemp();
233
257
  appCopy = join(tmp, basename(cachedAppPath));
234
258
  try {
235
- e.runFile("cp", [
259
+ await runOperationFile(context, e, "cp", [
236
260
  "-c",
237
261
  "-R",
238
262
  cachedAppPath,
239
263
  appCopy
240
264
  ], { timeoutMs: "unbounded" });
241
265
  } catch {
266
+ throwIfCancelled(context ? operationState(context).runSignal ?? context.signal : void 0, "JS swap");
242
267
  removeTemporaryEntry(appCopy);
243
- e.runFile("cp", [
268
+ await runOperationFile(context, e, "cp", [
244
269
  "-R",
245
270
  cachedAppPath,
246
271
  appCopy
@@ -252,7 +277,7 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
252
277
  let catalogTarget;
253
278
  const infoPlistPath = join(appCopy, "Info.plist");
254
279
  try {
255
- catalogTarget = readAssetCatalogTarget(e, infoPlistPath);
280
+ catalogTarget = await readAssetCatalogTarget(context, e, infoPlistPath);
256
281
  } catch (err) {
257
282
  return fail("catalog", `could not read ${infoPlistPath}: ${describe(err)}`);
258
283
  }
@@ -299,7 +324,8 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
299
324
  };
300
325
  let child;
301
326
  try {
302
- child = spawn(command.file, command.args, {
327
+ const invocation = bundleInvocation(root, isExpo, command.args.slice(1));
328
+ child = spawnDeclared(context, () => spawn(invocation.file, invocation.args, {
303
329
  cwd: root,
304
330
  stdio: [
305
331
  "ignore",
@@ -307,10 +333,11 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
307
333
  "pipe"
308
334
  ],
309
335
  env: {
310
- ...process.env,
336
+ ...context?.env ?? process.env,
311
337
  FORCE_COLOR: "0"
312
338
  }
313
- });
339
+ }));
340
+ killOnAbort(context ? operationState(context).runSignal ?? context.signal : void 0)(child);
314
341
  } catch (err) {
315
342
  return fail("bundle", `could not run ${command.file} ${command.args[0]}: ${describe(err)}`);
316
343
  }
@@ -350,11 +377,11 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
350
377
  else {
351
378
  const hbc = join(tmp, `${JS_BUNDLE_NAME}.hbc`);
352
379
  try {
353
- e.runFile(hermesc, hermescArgs({
380
+ await runOperationFile(context, e, hermesc, hermescArgs({
354
381
  bundle: bundleOutput,
355
382
  out: hbc
356
383
  }), { timeoutMs: "unbounded" });
357
- e.runFile("mv", [hbc, bundleOutput], { timeoutMs: 3e4 });
384
+ await runOperationFile(context, e, "mv", [hbc, bundleOutput], { timeoutMs: 3e4 });
358
385
  hermes = true;
359
386
  } catch (err) {
360
387
  return fail("hermesc", `hermesc failed on ${bundleOutput}: ${describe(err)}`);
@@ -362,8 +389,8 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
362
389
  }
363
390
  }
364
391
  try {
365
- e.runFile("cp", [bundleOutput, join(appCopy, JS_BUNDLE_NAME)], { timeoutMs: "unbounded" });
366
- e.runFile("cp", [
392
+ await runOperationFile(context, e, "cp", [bundleOutput, join(appCopy, JS_BUNDLE_NAME)], { timeoutMs: "unbounded" });
393
+ await runOperationFile(context, e, "cp", [
367
394
  "-R",
368
395
  `${assetsDest}/.`,
369
396
  `${appCopy}/`
@@ -380,7 +407,7 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
380
407
  });
381
408
  if (readdirSync(catalogDir).some((name) => name.endsWith(".imageset"))) {
382
409
  mkdirSync(catalogBundle);
383
- const output = e.runFile("xcrun", actoolArgs({
410
+ const output = await runOperationFile(context, e, "xcrun", actoolArgs({
384
411
  catalog: catalogDir,
385
412
  out: catalogBundle,
386
413
  target: catalogTarget
@@ -400,7 +427,7 @@ async function swapJsBundle({ root, iosDir, isExpo, cachedAppPath, logWriter = n
400
427
  return fail("updates", `could not refresh the expo-updates manifest ${manifest}: ${describe(err)}`);
401
428
  }
402
429
  try {
403
- e.runFile("codesign", [
430
+ await runOperationFile(context, e, "codesign", [
404
431
  "--force",
405
432
  "--sign",
406
433
  "-",
@@ -429,4 +456,4 @@ function describe(err) {
429
456
  return String(err?.message || err);
430
457
  }
431
458
  //#endregion
432
- export { swapJsBundle as i, detectEntryFile as n, refreshUpdatesManifestFile as r, UPDATES_MANIFEST_NAME as t };
459
+ export { runOperationFile as a, swapJsBundle as i, detectEntryFile as n, refreshUpdatesManifestFile as r, UPDATES_MANIFEST_NAME as t };
@@ -1,25 +1,24 @@
1
- import { B as deviceSlotKey, C as saveConfig, D as withConfigLock, E as upsertProject, N as formatBytes, V as deviceSlotPlatforms, _ as loadConfig, w as setDevice, z as deviceSlotFileKey } from "./config-BYDxlMY3.mjs";
2
- import { t as spawnEntry } from "./spawn-entry-Dcb7sDUz.mjs";
3
- import { j as providerUploadOutcome } from "./device-lease-BX1sJQ2E.mjs";
4
- import { w as workspaceLogsDir } from "./workspace-state-DJt_MMvf.mjs";
5
- import { _ as stepTimer, c as launchErrorReport, i as formatDuration, l as phaseLine, n as appReadinessMessage, v as launchErrorPreview } from "./command-output-BTy8hZ0F.mjs";
6
- import { I as workspaceDevServerMode } from "./project-_phNIJfs.mjs";
7
- import { a as workspaceLinks } from "./stim-desktop-BzBN2Em2.mjs";
8
- import { $ as trimAndroidCaches, i as androidDataFreeBytes, q as resetAdoptedAvd, u as androidToolCwd } from "./android-Mz_Inn3w.mjs";
9
- import { d as signalProcessTree, s as pidExists } from "./metro-DnCEjCxs.mjs";
10
- import { v as teardownOwnedAvd } from "./workspaces-C36s2jb9.mjs";
11
- import { o as exitAfterFlush } from "./remote-cache-OyOyVIS3.mjs";
12
- import { a as VERIFY_TIMEOUT_MS, i as RELEASE_VERIFY_WAIT_MS, l as unattributedLaunchLines, n as LAUNCH_FATAL, r as LAUNCH_UNVERIFIED, t as LAUNCH_BUNDLING, u as unverifiedLaunchLines } from "./launch-verify-B6Q8hZP-.mjs";
13
- import { C as restartedAppNote, _ as installConflictKind, c as androidDevClientUrl, s as androidAppProcess, t as ADB_INSTALL_TIMEOUT_MS } from "./app-install-BIKtMfPq.mjs";
14
- import { i as launchOutcomeRecord } from "./native-runtime-k8dTIrbK.mjs";
15
- import { a as PLATFORM, b as noDeviceDiagnostic, h as displayPath, n as LAUNCH_FAILED, r as NO_DEVICE, t as INSTALL_FAILED } from "./support-DMTqj3Hm.mjs";
16
- import { c as lostRefusal, s as lostLine, t as DEBUG_VERIFY_STEP_MS } from "./device-lease-run-Cw2M4z51.mjs";
17
- import { a as reportAndroidResult, i as persistLastBuild, n as finishAndroidUpload } from "./result-CaJg5Iat.mjs";
18
- import { n as nativeRunCommand, r as siblingPlatformSlots, t as launchSlotScope } from "./slot-launch-DPt0m9Nd.mjs";
19
- import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-DCtw_2IA.mjs";
20
- import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-BR677IDM.mjs";
1
+ import { m as workspaceLogsDir } from "./paths-DQtTgsBf.mjs";
2
+ import { C as saveConfig, E as upsertProject, H as deviceSlotKey, O as withConfigLockAsync, P as formatBytes, U as deviceSlotPlatforms, V as deviceSlotFileKey, _ as loadConfig, w as setDevice } from "./config-CYcBF478.mjs";
3
+ import { _ as stepTimer, c as launchErrorReport, i as formatDuration, l as phaseLine, n as appReadinessMessage, v as launchErrorPreview } from "./command-output-B1UrjZHL.mjs";
4
+ import { L as workspaceDevServerMode } from "./project-BZNjmW_8.mjs";
5
+ import { l as pidExists, p as signalProcessTree } from "./metro-DEXpIhHC.mjs";
6
+ import { En as restartedAppNote, Jt as LAUNCH_FATAL, Xt as RELEASE_VERIFY_WAIT_MS, Yt as LAUNCH_UNVERIFIED, Zt as VERIFY_TIMEOUT_MS, bn as installConflictKind, dn as androidAppProcess, fn as androidDevClientUrl, nn as unverifiedLaunchLines, qt as LAUNCH_BUNDLING, sn as ADB_INSTALL_TIMEOUT_MS, tn as unattributedLaunchLines } from "./budget-Bs6SxxzO.mjs";
7
+ import { E as teardownOwnedAvd } from "./workspaces-BccMFmGQ.mjs";
8
+ import { p as providerUploadOutcome } from "./build-cache-DmyR9Zzc.mjs";
9
+ import { Z as resetAdoptedAvd, i as androidDataFreeBytes, nt as trimAndroidCaches, u as androidToolCwd } from "./android-DUYkNF4u.mjs";
10
+ import { o as workspaceLinks } from "./stim-desktop-C12we7lz.mjs";
11
+ import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-DEmM5vhh.mjs";
12
+ import { n as nativeRunCommand, r as siblingPlatformSlots, t as launchSlotScope } from "./slot-launch-DF8VfT64.mjs";
13
+ import { c as lostRefusal, s as lostLine, t as DEBUG_VERIFY_STEP_MS } from "./device-lease-run-C8raGFoP.mjs";
14
+ import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-Bf0rZvG9.mjs";
15
+ import { t as spawnEntry } from "./spawn-entry-jw19m8Nl.mjs";
16
+ import { i as launchOutcomeRecord } from "./native-runtime-Dg1Q7tfF.mjs";
17
+ import { a as PLATFORM, b as noDeviceDiagnostic, h as displayPath, n as LAUNCH_FAILED, r as NO_DEVICE, t as INSTALL_FAILED } from "./support-67vraa1Q.mjs";
18
+ import { a as reportAndroidResult, i as persistLastBuild, n as finishAndroidUpload } from "./result-DNiS-tTP.mjs";
21
19
  import { mkdirSync, openSync, statSync } from "node:fs";
22
20
  import { basename, join } from "node:path";
21
+ import { ambientEnv } from "@stim-cli/core";
23
22
  import chalk from "chalk";
24
23
  //#region src/commands/android/collector.ts
25
24
  function collectorEntry() {
@@ -91,7 +90,7 @@ async function startCollector({ root, slot = "default", serial, packageName, spa
91
90
  cwd: androidToolCwd() ?? root,
92
91
  detached: true,
93
92
  stdio,
94
- env: process.env
93
+ env: ambientEnv()
95
94
  });
96
95
  child?.unref?.();
97
96
  return child?.pid ?? null;
@@ -154,7 +153,7 @@ function androidMetroRuntime(prepare) {
154
153
  })
155
154
  };
156
155
  }
157
- async function verifyAndroidProcessRun({ root, slot, remoteDevice, verifyReleaseLaunched, serial, androidPackage, variant, logsDir, launchedAt, phase, embeddedJavaScript }) {
156
+ async function verifyAndroidProcessRun({ operation, root, slot, remoteDevice, verifyReleaseLaunched, serial, androidPackage, variant, logsDir, launchedAt, phase, embeddedJavaScript }) {
158
157
  const readNativeCrashes = () => remoteDevice ? [] : captureNativeCrashes({
159
158
  root,
160
159
  slot,
@@ -162,7 +161,7 @@ async function verifyAndroidProcessRun({ root, slot, remoteDevice, verifyRelease
162
161
  deviceId: serial,
163
162
  appId: androidPackage,
164
163
  since: launchedAt
165
- }, logsDir);
164
+ }, logsDir, operation?.signal, operation?.env);
166
165
  if (remoteDevice) {
167
166
  phase("verify", chalk.yellow("UNVERIFIED: remote adapter launch accepted; process verification is unavailable"));
168
167
  return { state: LAUNCH_UNVERIFIED };
@@ -171,9 +170,9 @@ async function verifyAndroidProcessRun({ root, slot, remoteDevice, verifyRelease
171
170
  serial,
172
171
  packageName: androidPackage
173
172
  });
174
- const crashes = readNativeCrashes();
173
+ const crashes = await readNativeCrashes();
175
174
  if (processCheck?.verified && !crashes.length) {
176
- phase("verify", `process alive ${formatDuration(processCheck.waitedMs ?? 0)} after launch (${variant}: no bundle fetch to observe)`);
175
+ phase("verify", `process alive ${formatDuration(processCheck.waitedMs ?? 0)} after launch (${variant ?? "debug"}: no bundle fetch to observe)`);
177
176
  return { state: true };
178
177
  }
179
178
  if (processCheck?.reason === "probe-failed" && !crashes.length) {
@@ -186,7 +185,7 @@ async function verifyAndroidProcessRun({ root, slot, remoteDevice, verifyRelease
186
185
  phase("", chalk.yellow(`${embeddedJavaScript ? "A release process" : "The app process"} exited before readiness. Run \`stim logs --errors\` for captured crash reports, or \`stim logs --source device\` for the full device output.`));
187
186
  return { state: LAUNCH_FATAL };
188
187
  }
189
- async function verifyAndroidMetroRun({ root, slot, remoteDevice, verifyLaunched, serial, androidPackage, metroCheck, logsDir, launchedAt, metroPort, isExpo, physical, device, scheme, component = null, phase, enterActivity }) {
188
+ async function verifyAndroidMetroRun({ operation, root, slot, remoteDevice, verifyLaunched, serial, androidPackage, metroCheck, logsDir, launchedAt, metroPort, isExpo, physical, device, scheme, component = null, phase, enterActivity }) {
190
189
  const runCommand = nativeRunCommand("android", slot, {
191
190
  physical,
192
191
  deviceId: serial
@@ -198,11 +197,11 @@ async function verifyAndroidMetroRun({ root, slot, remoteDevice, verifyLaunched,
198
197
  deviceId: serial,
199
198
  appId: androidPackage,
200
199
  since: launchedAt
201
- }, logsDir);
200
+ }, logsDir, operation?.signal, operation?.env);
202
201
  const freshEmulator = Boolean((device.created || device.adoptionPending) && device.owned && !remoteDevice);
203
202
  const timeoutMs = freshEmulator ? 6e4 : VERIFY_TIMEOUT_MS;
204
203
  if (metroCheck && freshEmulator) phase("verify", `waiting up to 60s for bundle load (${device.created ? "new" : "adopted"} emulator)`);
205
- const siblings = metroCheck ? siblingPlatformSlots(root, "android", slot) : [];
204
+ const siblings = metroCheck ? await siblingPlatformSlots(root, "android", slot) : [];
206
205
  const verification = metroCheck ? await verifyLaunched({
207
206
  timeoutMs,
208
207
  requireBundleResponse: true,
@@ -216,15 +215,15 @@ async function verifyAndroidMetroRun({ root, slot, remoteDevice, verifyLaunched,
216
215
  platform: "android",
217
216
  mode: workspaceDevServerMode(root, isExpo),
218
217
  readNativeCrashes,
219
- processAlive: () => {
220
- const running = androidAppProcess(serial, androidPackage);
218
+ processAlive: async () => {
219
+ const running = await androidAppProcess(serial, androidPackage);
221
220
  return running.state === "unknown" ? null : running.state === "running";
222
221
  }
223
222
  }) : {
224
223
  verified: false,
225
224
  skipped: true
226
225
  };
227
- const nativeCrashes = verification.errors?.some((record) => record.event === "native_crash") ? [] : readNativeCrashes();
226
+ const nativeCrashes = verification.errors?.some((record) => record.event === "native_crash") ? [] : await readNativeCrashes();
228
227
  if (nativeCrashes.length) verification.fatal = true;
229
228
  verification.errors = await errorDiagnostics([...verification.errors ?? [], ...nativeCrashes], {
230
229
  root,
@@ -304,7 +303,7 @@ async function wipeAdoptedAvd(room, free) {
304
303
  room.phase("device", chalk.yellow(`${room.avdName} has ${free === null ? "too little space" : `${formatBytes(free)} free`} on /data after removing other apps and trimming caches; wiping its user data`));
305
304
  const expectedRecord = deviceSlotPlatforms(loadConfig()?.projects?.[room.root], room.slot)?.android;
306
305
  if (!expectedRecord?.adoptionPending || expectedRecord.avdName !== room.avdName) throw new Error("the emulator assignment changed before the wipe; its data was kept");
307
- const wiped = room.wipeDevice(room.avdName, {
306
+ const wiped = await room.wipeDevice(room.avdName, {
308
307
  wipe: true,
309
308
  owner: {
310
309
  projectPath: room.root,
@@ -316,7 +315,7 @@ async function wipeAdoptedAvd(room, free) {
316
315
  if (wiped.status !== "torn-down") throw new Error(`could not wipe it: ${wiped.reason ?? wiped.status}`);
317
316
  const rebooted = await room.rebootDevice();
318
317
  if (!rebooted.ok || !rebooted.serial) throw new Error(`it did not boot after its user data was wiped: ${rebooted.reason ?? "no serial"}`);
319
- if (room.resolveAvdSerial(room.avdName).serial !== rebooted.serial) throw new Error(`${rebooted.serial} is not running ${room.avdName} after the wipe`);
318
+ if ((await room.resolveAvdSerial(room.avdName)).serial !== rebooted.serial) throw new Error(`${rebooted.serial} is not running ${room.avdName} after the wipe`);
320
319
  room.phase("device", `${room.avdName} (${rebooted.serial}) booted with wiped user data`);
321
320
  return rebooted.serial;
322
321
  }
@@ -326,45 +325,45 @@ async function installOnAdoptedAvd(room, serial, installApk) {
326
325
  const outOfSpace = (result) => Boolean(result.failed) && INSUFFICIENT_STORAGE.test(result.reason ?? "");
327
326
  let target = serial;
328
327
  let wiped = false;
329
- if (!roomy(room.dataFreeBytes(target))) {
330
- room.trimCaches(target, neededBytes);
331
- const free = room.dataFreeBytes(target);
328
+ if (!roomy(await room.dataFreeBytes(target))) {
329
+ await room.trimCaches(target, neededBytes);
330
+ const free = await room.dataFreeBytes(target);
332
331
  if (roomy(free)) room.phase("install", `trimmed app caches on ${room.avdName} to make room for the APK`);
333
332
  else {
334
333
  target = await wipeAdoptedAvd(room, free);
335
334
  wiped = true;
336
335
  }
337
336
  }
338
- let installed = installApk(target);
337
+ let installed = await installApk(target);
339
338
  if (wiped || !outOfSpace(installed)) return {
340
339
  serial: target,
341
340
  installed
342
341
  };
343
- room.trimCaches(target, neededBytes);
344
- installed = installApk(target);
342
+ await room.trimCaches(target, neededBytes);
343
+ installed = await installApk(target);
345
344
  if (!outOfSpace(installed)) return {
346
345
  serial: target,
347
346
  installed
348
347
  };
349
- target = await wipeAdoptedAvd(room, room.dataFreeBytes(target));
348
+ target = await wipeAdoptedAvd(room, await room.dataFreeBytes(target));
350
349
  return {
351
350
  serial: target,
352
- installed: installApk(target)
351
+ installed: await installApk(target)
353
352
  };
354
353
  }
355
354
  async function resolveInstallSerial({ root, slot, device, physical, remoteDevice, serial, resolveAvdSerial, waitForDeviceBoot, phase }) {
356
355
  if (physical || remoteDevice || !device.owned || !device.avdName) return serial;
357
- const resolved = resolveAvdSerial(device.avdName, { timeoutMs: 5e3 });
356
+ const resolved = await resolveAvdSerial(device.avdName, { timeoutMs: 5e3 });
358
357
  if (!resolved.serial) throw new Error(`Could not verify a running owned AVD ${device.avdName} before installation.`);
359
358
  if (resolved.serial !== serial) {
360
359
  phase("device", `${device.avdName} changed serial (${serial} -> ${resolved.serial}); checking readiness before installation`);
361
360
  const ready = await waitForDeviceBoot(resolved.serial, 6e4, { commandTimeoutMs: 5e3 });
362
361
  if (!ready.ok) throw new Error(`Emulator ${resolved.serial} never reported boot completion. Diagnostic: ${JSON.stringify(ready.diagnostic)}`);
363
- if (resolveAvdSerial(device.avdName, { timeoutMs: 5e3 }).serial !== resolved.serial) throw new Error(`Could not verify AVD ${device.avdName} still runs on ${resolved.serial} after checking readiness.`);
362
+ if ((await resolveAvdSerial(device.avdName, { timeoutMs: 5e3 })).serial !== resolved.serial) throw new Error(`Could not verify AVD ${device.avdName} still runs on ${resolved.serial} after checking readiness.`);
364
363
  phase("device", `reopen agent-device on ${resolved.serial}`);
365
364
  }
366
365
  const consolePort = Number(resolved.serial.replace(/^emulator-/, ""));
367
- withConfigLock(() => {
366
+ await withConfigLockAsync(() => {
368
367
  const current = deviceSlotPlatforms(loadConfig()?.projects?.[root], slot)?.android;
369
368
  if (!current?.owned || current.avdName !== device.avdName) throw new Error("The owned emulator assignment changed before installation.");
370
369
  if (current.consolePort !== consolePort) setDevice(root, PLATFORM, {
@@ -374,7 +373,8 @@ async function resolveInstallSerial({ root, slot, device, physical, remoteDevice
374
373
  });
375
374
  return resolved.serial;
376
375
  }
377
- async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLease, root, slot, json, metroCheck, useBuildCache, variant, release, isExpo, metroPort, logsDir, emuLog, device, physical, remoteDevice, bootPromise, resolveAvdSerial, waitForDeviceBoot, bootDuration, bootPending, apkPath, androidPackage: initialPackage, androidPackageProblem, record, waitedForBuild, ccache, uploadPending, providerUpload, providerName, remote, abandonedRemote: remoteWasAbandoned, started, startedAt, writer, phase, fail, readApkPackage, readProjectPackage, packageRemedy, install, launch, launchRelease, resolveDevClientScheme, verifyLaunched, verifyReleaseLaunched, spawn, kill, pidAlive, verifyCollector, writeLaunch, recordBuild, now, out, emit, recordRun, reclaimed, devServer, enterPhase, enterActivity, rebootDevice, dataFreeBytes = androidDataFreeBytes, trimCaches = trimAndroidCaches, wipeDevice = teardownOwnedAvd }) {
376
+ async function finishAndroidRun({ operation, runtime, runtimePreparation, lease, releaseLease, root, slot, json, metroCheck, useBuildCache, variant, release, isExpo, metroPort, logsDir, emuLog, device, physical, remoteDevice, bootPromise, resolveAvdSerial, waitForDeviceBoot, bootDuration, bootPending, apkPath, androidPackage: initialPackage, androidPackageProblem, record, waitedForBuild, ccache, uploadPending, providerUpload, providerName, remote, abandonedRemote: remoteWasAbandoned, started, startedAt, writer, phase, fail, readApkPackage, readProjectPackage, packageRemedy, install, launch, launchRelease, resolveDevClientScheme, verifyLaunched, verifyReleaseLaunched, spawn, kill, pidAlive, verifyCollector, writeLaunch, recordBuild, now, out, emit, recordRun, reclaimed, devServer, enterPhase, enterActivity, rebootDevice, dataFreeBytes = androidDataFreeBytes, trimCaches = trimAndroidCaches, wipeDevice = teardownOwnedAvd }) {
377
+ const { env, signal } = operation ?? {};
378
378
  let androidPackage = initialPackage;
379
379
  let leaseWarned = false;
380
380
  const raiseLeaseFor = (boundMs, beforeInstall) => {
@@ -422,9 +422,9 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
422
422
  return fail(NO_DEVICE, error instanceof Error ? error.message : String(error), `Run \`stim status\` to inspect the owned AVD, then retry \`${runCommand}\`; the APK was not installed.`);
423
423
  }
424
424
  phase("device", physical ? `${device.deviceName || serial} (${serial}) connected, not owned by Stim` : `${device.avdName || serial} (${serial}) ${device.adopted || device.adoptionPending ? "adopted" : "booted"} ${bootDuration()}`);
425
- const packageFromApk = readApkPackage(apkPath);
425
+ const packageFromApk = await readApkPackage(apkPath);
426
426
  if (packageFromApk && androidPackage && packageFromApk !== androidPackage) phase("install", chalk.dim(`applicationId ${packageFromApk} (from the APK; project files say ${androidPackage})`));
427
- androidPackage = packageFromApk || androidPackage || readProjectPackage();
427
+ androidPackage = packageFromApk || androidPackage || await readProjectPackage();
428
428
  if (!androidPackage && androidPackageProblem) return fail(LAUNCH_FAILED, androidPackageProblem, packageRemedy, { lastBuildStatus: true });
429
429
  const adopting = !physical && !remoteDevice && Boolean(device.adoptionPending);
430
430
  if (adopting) {
@@ -467,7 +467,7 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
467
467
  } catch (error) {
468
468
  return fail(INSTALL_FAILED, `Could not make room on adopted emulator ${device.avdName}: ${String(error?.message || error)}`, `Run \`${runCommand}\` again; adoption remains pending, so it retries the cleanup.`);
469
469
  }
470
- } else installed = installApk(serial);
470
+ } else installed = await installApk(serial);
471
471
  if (installed.failed) {
472
472
  const installRemedy = remoteDevice?.failureRemedy() ?? localInstallRemedy({
473
473
  reason: installed.reason,
@@ -478,7 +478,7 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
478
478
  return fail(installed.code || "STIM_INSTALL_FAILED", installed.reason, installRemedy, { lastBuildStatus: true });
479
479
  }
480
480
  if (adopting) try {
481
- withConfigLock(() => {
481
+ await withConfigLockAsync(() => {
482
482
  const config = loadConfig();
483
483
  const current = deviceSlotPlatforms(config?.projects?.[root], slot)?.android;
484
484
  if (!config || !current || current.avdName !== device.avdName) throw new Error("The adopted emulator assignment changed during installation.");
@@ -503,7 +503,7 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
503
503
  record.bundleId = androidPackage;
504
504
  if (!androidPackage) return fail(LAUNCH_FAILED, "Could not determine this app's Android package name, so there is nothing to launch.", packageRemedy, { lastBuildStatus: true });
505
505
  if (physical) raiseLeaseFor(0, false);
506
- const scheme = runtime.scheme(root, apkPath, resolveDevClientScheme);
506
+ const scheme = await runtime.scheme(root, apkPath, resolveDevClientScheme);
507
507
  enterPhase("launch");
508
508
  const launchTimer = stepTimer(now);
509
509
  const launchedAt = now();
@@ -530,14 +530,14 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
530
530
  launchRelease
531
531
  });
532
532
  if (launched.failed) {
533
- printNativeCrashReport({
533
+ await printNativeCrashReport({
534
534
  root,
535
535
  slot,
536
536
  platform: "android",
537
537
  deviceId: serial,
538
538
  appId: androidPackage,
539
539
  since: launchedAt
540
- }, logsDir, (line) => phase("launch", chalk.red(line)), Boolean(remoteDevice));
540
+ }, logsDir, (line) => phase("launch", chalk.red(line)), Boolean(remoteDevice), signal, env);
541
541
  return fail(launched.code || "STIM_LAUNCH_FAILED", launched.reason, launchRemedy(remoteDevice, serial, androidPackage), { lastBuildStatus: true });
542
542
  }
543
543
  writer.write({
@@ -578,7 +578,7 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
578
578
  });
579
579
  }
580
580
  const uploadWasAbandoned = await finishAndroidUpload(uploadPending, remote, phase);
581
- const providerOutcome = providerUploadOutcome(providerUpload ? await providerUpload : null, providerName);
581
+ const providerOutcome = providerUploadOutcome(providerUpload ? await providerUpload : null, providerName, env);
582
582
  if (providerOutcome) phase("cache", providerOutcome.warn ? chalk.yellow(providerOutcome.line) : providerOutcome.line);
583
583
  persistLastBuild({
584
584
  recordBuild,
@@ -621,6 +621,7 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
621
621
  }
622
622
  if (physical) raiseLeaseFor(runtime.verificationWaitMs, false);
623
623
  const { state: launchState, warning: launchWarning, unattributed } = await runtime.verify(runtimePreparation, {
624
+ operation,
624
625
  root,
625
626
  slot,
626
627
  remoteDevice: Boolean(remoteDevice),
@@ -654,45 +655,45 @@ async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLea
654
655
  }));
655
656
  const leaseFacts = lease?.facts() ?? null;
656
657
  releaseLease();
657
- const facts = reportAndroidResult({
658
- root,
659
- slot,
660
- json,
661
- useBuildCache,
662
- variant,
663
- release,
664
- runtimeKind: runtime.kind,
665
- metroCheck,
666
- metroPort,
667
- logsDir: remoteRelease ? null : logsDir,
668
- serial,
669
- apkPath,
670
- androidPackage,
671
- installSkipped,
672
- record,
673
- waitedForBuild,
674
- remote,
675
- providerName,
676
- launchState,
677
- launchWarning,
678
- launched,
679
- ccache,
680
- durationMs: now() - started,
681
- writer,
682
- emit,
683
- lease: physical ? leaseFacts : void 0,
684
- recordRun,
685
- reclaimed,
686
- devServer,
687
- links: workspaceLinks(root, {
688
- platform: "android",
689
- slot
690
- })
691
- });
692
- if (remoteWasAbandoned || uploadWasAbandoned) exitAfterFlush(0);
693
658
  return {
694
659
  ok: true,
695
- facts
660
+ facts: reportAndroidResult({
661
+ root,
662
+ slot,
663
+ json,
664
+ useBuildCache,
665
+ variant,
666
+ release,
667
+ runtimeKind: runtime.kind,
668
+ metroCheck,
669
+ metroPort,
670
+ logsDir: remoteRelease ? null : logsDir,
671
+ serial,
672
+ apkPath,
673
+ androidPackage,
674
+ installSkipped,
675
+ record,
676
+ waitedForBuild,
677
+ remote,
678
+ providerName,
679
+ launchState,
680
+ launchWarning,
681
+ launched,
682
+ ccache,
683
+ durationMs: now() - started,
684
+ writer,
685
+ emit,
686
+ out,
687
+ lease: physical ? leaseFacts : void 0,
688
+ recordRun,
689
+ reclaimed,
690
+ devServer,
691
+ links: await workspaceLinks(root, {
692
+ platform: "android",
693
+ slot
694
+ })
695
+ }),
696
+ uploadsAbandoned: remoteWasAbandoned || uploadWasAbandoned
696
697
  };
697
698
  }
698
699
  function localInstallRemedy({ reason, packageName, serial, useBuildCache }) {