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,23 +1,16 @@
1
- import { _ as loadConfig$1, p as getProject } from "./config-BYDxlMY3.mjs";
2
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
3
- import { Ft as makeTemporaryDirectory, It as removeTemporaryEntry, ot as detectProviders, st as planMetroReach } from "./settings-B717odTD.mjs";
4
- import { w as entryDir, y as artifactIn } from "./device-lease-BX1sJQ2E.mjs";
5
- import { i as formatDuration, l as phaseLine, m as shortHash, u as plural } from "./command-output-BTy8hZ0F.mjs";
6
- import { N as readRemoteSession, j as readMetroTunnel } from "./project-_phNIJfs.mjs";
7
- import { Mt as readStats$1, s as peekBudget, wt as estimateBuild } from "./budget-f7516Zk0.mjs";
8
- import { a as easAuthNote, f as resolveEasCliBin, s as isEasAuthFailureText } from "./remote-cache-OyOyVIS3.mjs";
9
- import { S as hostingMachines, h as namedBuildMachine, v as resolveBuildMachine } from "./client-qQAaXSUs.mjs";
10
- import { P as readHostMemoryPressure } from "./ios-RkW4pnQf.mjs";
11
- import { r as predictBuildMiss } from "./miss-reason-mKzZ4VvN.mjs";
12
- import { s as peekDeviceSlots } from "./device-capacity-CBUAcRyQ.mjs";
13
- import { c as connectHost, f as requireHostedAppMode, s as call } from "./hosted-client-ZEKpS9vw.mjs";
14
- import { r as readHostedNative, s as writeHostedNative } from "./ios-state-CBLe1xYw.mjs";
15
- import { n as prepareHostedNative } from "./hosted-native-A4s1QPXe.mjs";
16
- import { h as easCliSupport, m as MIN_EAS_CLI_SIMULATOR_VERSION, p as MIN_EAS_CLI_DEVICE_VERSION, s as readInstalledEasCliVersion } from "./device-remote-xRT0Vmo9.mjs";
17
- import { i as staleNativeDirRefusal } from "./prebuild-DYbucPXy.mjs";
1
+ import { t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
+ import { _ as loadConfig$1, p as getProject } from "./config-CYcBF478.mjs";
3
+ import { Gt as childEnvironment, ct as detectProviders, en as throwIfCancelled, lt as planMetroReach } from "./settings-CsJDEXgK.mjs";
4
+ import { M as readMetroTunnel, P as readRemoteSession } from "./project-BZNjmW_8.mjs";
5
+ import { $n as MIN_EAS_CLI_DEVICE_VERSION, Hn as isEasAuthFailureText, Ht as readInstalledEasCliVersionAsync, Qn as remoteCommand, er as MIN_EAS_CLI_SIMULATOR_VERSION, qn as resolveEasCliBin, s as peekBudget, tr as easCliSupport } from "./budget-Bs6SxxzO.mjs";
6
+ import { P as readHostMemoryPressure } from "./ios-CpByZy12.mjs";
7
+ import { d as hostingMachines, o as resolveBuildMachine, r as namedBuildMachine } from "./selection-CSl9i5qU.mjs";
8
+ import { c as call, l as connectHost, p as requireHostedAppMode } from "./hosted-client-DB_gBPfY.mjs";
9
+ import { r as readHostedNative, s as writeHostedNative } from "./ios-state-DvFX-K_l.mjs";
10
+ import { n as prepareHostedNative } from "./hosted-native-Ksyjgzq-.mjs";
11
+ import { c as peekDeviceSlots } from "./device-capacity-CMlqEcvw.mjs";
12
+ import { ambientEnv } from "@stim-cli/core";
18
13
  import { automaticMachineEnabled, isJsonObject, machineCapacity, parseHostedChoice, parseHostedNativeOffer } from "@stim-cli/core/state";
19
- import { resolveTieredBuild } from "@stim-cli/cache";
20
- import chalk from "chalk";
21
14
  //#region src/device-host/placement.ts
22
15
  function local$1(code, reason, skipped = [], atCapacity = false) {
23
16
  return {
@@ -85,7 +78,7 @@ function decideDevicePlacement(inputs) {
85
78
  atCapacity: true
86
79
  };
87
80
  };
88
- if (!offers.length) return nowhere("no-remote-mac", "no remote Macs configured; " + localReason);
81
+ if (!offers.length) return nowhere("no-remote-mac", "no remote machines configured; " + localReason);
89
82
  if (localEnabled && count === null) return local$1("device-count-unknown", localReason);
90
83
  if (!cannotTake && here.memoryPressure === "normal" && !here.budgetRefusal && here.loadPerCore < here.maxLoadPerCore) return local$1("this-mac-free", localReason);
91
84
  const skipped = [];
@@ -100,7 +93,7 @@ function decideDevicePlacement(inputs) {
100
93
  else if (offer.platform !== platform || !offer.choice) [code, reason] = ["no-matching-device", `no matching ${platform} device choice`];
101
94
  else if (offer.resources.memoryPressure !== "normal") [code, reason] = ["memory", "host memory pressure unknown or elevated"];
102
95
  else if (offer.capacity.available === 0) [code, reason] = ["no-capacity", "no hosted device capacity available"];
103
- else if (!cannotTake && (offer.resources.loadPerCore === null || offer.resources.loadPerCore >= here.loadPerCore)) [code, reason] = ["load", offer.resources.loadPerCore === null ? "host load unknown while this Mac has room" : "host is not less loaded than this Mac"];
96
+ else if (!cannotTake && (offer.resources.loadPerCore === null || offer.resources.loadPerCore >= here.loadPerCore)) [code, reason] = ["load", offer.resources.loadPerCore === null ? "host load unknown while this machine has room" : "host is not less loaded than this machine"];
104
97
  else admitted.push({
105
98
  machine: probe.machine,
106
99
  offer,
@@ -117,7 +110,7 @@ function decideDevicePlacement(inputs) {
117
110
  if (!admitted.length) return nowhere("no-host-admits", `${localReason}; no host admits`, skipped, localEnabled && cannotTake && !noWait ? "; waiting locally if needed" : "");
118
111
  const machines = admitted.map(({ machine, offer }) => ({
119
112
  machine,
120
- reason: `${localReason}; ${machine}${machine === buildMachine ? " is the explicit remote Mac," : ""} load ${offer.resources.loadPerCore === null ? "unknown" : offer.resources.loadPerCore.toFixed(1) + "/core"}`
113
+ reason: `${localReason}; ${machine}${machine === buildMachine ? " is the explicit remote machine," : ""} load ${offer.resources.loadPerCore === null ? "unknown" : offer.resources.loadPerCore.toFixed(1) + "/core"}`
121
114
  }));
122
115
  return {
123
116
  kind: "host",
@@ -223,7 +216,7 @@ async function automaticDevicePlacement({ root, slot, platform, selectors, appMo
223
216
  platform,
224
217
  project: getProject(root),
225
218
  slot
226
- }), capacity = machineCapacity, memory = readHostMemoryPressure, probe = probeHost, budget = peekBudget } = {}) {
219
+ }), capacity = machineCapacity, memory = readHostMemoryPressure, probe = probeHost, budget = (projectRoot) => peekBudget(projectRoot, {}, ambientEnv()) } = {}) {
227
220
  const recorded = read(root, platform, slot)[slot];
228
221
  if (recorded) {
229
222
  const target = await resume(recorded.machine, selectors, recorded, platform, true, appMode);
@@ -249,7 +242,7 @@ async function automaticDevicePlacement({ root, slot, platform, selectors, appMo
249
242
  if (configured === null) throw Object.assign(/* @__PURE__ */ new Error("remote.machines is invalid. Run stim guide settings and correct it."), { code: "STIM_HOSTING_REFUSED" });
250
243
  const config = loadConfig$1();
251
244
  const entries = configured.filter((machine) => automaticMachineEnabled("device", machine, config));
252
- const preference = resolveBuildMachine(buildMachine, process.env.STIM_REMOTE_BUILD, config?.remote?.build);
245
+ const preference = resolveBuildMachine(buildMachine, ambientEnv().STIM_REMOTE_BUILD, config?.remote?.build);
253
246
  buildMachine = namedBuildMachine(preference) ? preference : void 0;
254
247
  const load = capacity();
255
248
  const here = {
@@ -323,14 +316,18 @@ function parseSimulatorAvailability(outcome) {
323
316
  * Whether this run could use an EAS Simulator the way `--remote eas` does, without starting a session or a build.
324
317
  * Each refusal names what `--remote eas` would refuse later, so automatic placement falls through instead.
325
318
  */
326
- async function checkEasFallback({ root, platform, slot, release, isExpo, tunnelMode, publicUrl, deviceTypeFlag, localOnlyFlags, env = process.env, resolveBin = resolveEasCliBin, readVersion = readInstalledEasCliVersion, onPath = (bin) => getExecutor().findExecutable(bin) !== null, readTunnel = readMetroTunnel, readSession = readRemoteSession, metroPort = () => getProject(root)?.metroPort ?? null, availability = async (bin) => {
319
+ async function checkEasFallback({ root, platform, slot, release, isExpo, tunnelMode, publicUrl, deviceTypeFlag, localOnlyFlags, env = process.env, resolveBin = resolveEasCliBin, readVersion = readInstalledEasCliVersionAsync, operation, onPath = (bin) => getExecutor().findExecutable(bin) !== null, readTunnel = readMetroTunnel, readSession = readRemoteSession, metroPort = () => getProject(root)?.metroPort ?? null, availability = async (bin) => {
327
320
  try {
328
- return { stdout: await getExecutor().runFileAsync(bin, [
321
+ return { stdout: await remoteCommand({
322
+ operation,
323
+ easBin: bin
324
+ }, bin, [
329
325
  "simulator:availability",
330
326
  "--json",
331
327
  "--non-interactive"
332
328
  ], {
333
329
  cwd: root,
330
+ ...childEnvironment(env),
334
331
  timeoutMs: AVAILABILITY_TIMEOUT_MS
335
332
  }) };
336
333
  } catch (error) {
@@ -347,9 +344,10 @@ async function checkEasFallback({ root, platform, slot, release, isExpo, tunnelM
347
344
  if (session && session.platform !== platform) return unusable("eas-session-busy", `this workspace's EAS Simulator session ${session.sessionId} runs ${session.platform ?? "another platform"}`);
348
345
  if (session && deviceTypeFlag?.trim() && session.deviceType !== deviceTypeFlag.trim()) return unusable("eas-session-busy", `this workspace's EAS Simulator session ${session.sessionId} runs ${session.deviceType ?? "the model EAS chose"}, not ${deviceTypeFlag.trim()}`);
349
346
  if (!onPath("agent-device")) return unusable("eas-no-agent-device", "agent-device is not on PATH");
347
+ throwIfCancelled(operation?.signal, "EAS availability");
350
348
  const bin = resolveBin(root);
351
349
  if (!bin) return unusable("eas-no-cli", "eas-cli is not installed for this project or on PATH");
352
- const versionOutput = readVersion(bin.file, root);
350
+ const versionOutput = await readVersion(bin.file, root, operation);
353
351
  const minimum = platform === "ios" && deviceTypeFlag?.trim() ? MIN_EAS_CLI_DEVICE_VERSION : MIN_EAS_CLI_SIMULATOR_VERSION;
354
352
  const { supported, version } = easCliSupport(versionOutput, minimum);
355
353
  if (!supported) return unusable("eas-cli-too-old", `eas-cli ${version ?? "(unknown version)"} is older than ${minimum}`);
@@ -370,184 +368,4 @@ async function checkEasFallback({ root, platform, slot, release, isExpo, tunnelM
370
368
  return parseSimulatorAvailability(await availability(bin.file));
371
369
  }
372
370
  //#endregion
373
- //#region src/commands/build-plan.ts
374
- const DISCARD = {
375
- file: "",
376
- written: 0,
377
- dropped: 0,
378
- lastError: null,
379
- write: () => true,
380
- close: () => ({
381
- file: "",
382
- written: 0,
383
- dropped: 0,
384
- lastError: null
385
- })
386
- };
387
- async function providerHit({ root, platform, cacheKey, providerConfig }, deps) {
388
- if (!providerConfig) return null;
389
- let destinationDir;
390
- try {
391
- destinationDir = makeTemporaryDirectory(root, "stim-plan-");
392
- } catch (error) {
393
- deps.note(chalk.yellow(phaseLine("cache", `provider not checked: ${error?.message || error}`)));
394
- return null;
395
- }
396
- try {
397
- const found = await resolveTieredBuild({
398
- local: {
399
- resolve: () => null,
400
- store: () => null
401
- },
402
- loadProvider: () => deps.loadCacheProvider({
403
- projectRoot: root,
404
- config: providerConfig
405
- }),
406
- target: {
407
- projectRoot: root,
408
- platform,
409
- key: cacheKey
410
- },
411
- destinationDir,
412
- warn: (_code, message) => deps.note(chalk.yellow(phaseLine("cache", message)))
413
- });
414
- return found ? found.providerName ?? "the cache provider" : null;
415
- } finally {
416
- removeTemporaryEntry(destinationDir);
417
- }
418
- }
419
- async function expoRemoteHit(lookup, deps) {
420
- if (!lookup.expoRemote) return null;
421
- const { root, platform, isExpo, fingerprint } = lookup;
422
- const loaded = await deps.loadProjectProvider(root, { isExpo });
423
- if (loaded?.unavailable) {
424
- deps.note(chalk.yellow(phaseLine("cache", `provider not usable: ${loaded.unavailable}`)));
425
- return null;
426
- }
427
- if (!loaded?.provider) return null;
428
- const name = loaded.name ?? "the build cache provider";
429
- if (name === "eas") {
430
- const auth = deps.checkEasAuth({
431
- projectRoot: root,
432
- owner: loaded.owner || null
433
- });
434
- const authNote = easAuthNote(auth);
435
- if (authNote) deps.note(chalk.yellow(phaseLine("cache", authNote)));
436
- if (auth?.code === "logged-out") return null;
437
- }
438
- const hit = await deps.resolveRemote({
439
- provider: loaded.provider,
440
- platform,
441
- projectRoot: root,
442
- fingerprintHash: fingerprint,
443
- runOptions: lookup.expoRemote.runOptions,
444
- logWriter: DISCARD
445
- });
446
- if (hit?.timedOut) deps.note(chalk.yellow(phaseLine("cache", `${name} did not answer; counted as a miss`)));
447
- else if (hit?.failed) deps.note(chalk.yellow(phaseLine("cache", `${name} could not be used: ${hit.failed}`)));
448
- return hit?.appPath ? name : null;
449
- }
450
- async function planCachedBuild(lookup, deps) {
451
- const { root, platform, isExpo, fingerprint, sources, cacheKey, cachePolicy } = lookup;
452
- let cacheHit = false;
453
- let provider = null;
454
- if (cachePolicy.read) {
455
- if (artifactIn(entryDir(platform, cacheKey))) cacheHit = "local";
456
- else {
457
- provider = (cachePolicy.remote ? await providerHit(lookup, deps) : null) ?? await expoRemoteHit(lookup, deps);
458
- if (provider) cacheHit = "remote";
459
- }
460
- }
461
- let prebuild = null;
462
- let refusal = null;
463
- let missReason;
464
- if (!cacheHit) {
465
- prebuild = deps.planPrebuild(root, platform, {
466
- isExpo,
467
- fingerprint,
468
- sources
469
- });
470
- if (prebuild === "refuse") refusal = staleNativeDirRefusal(platform);
471
- else if (cachePolicy.read) missReason = predictBuildMiss({
472
- root,
473
- platform,
474
- current: {
475
- hash: fingerprint,
476
- sources
477
- },
478
- prebuild: prebuild === "generate" || prebuild === "regenerate" ? prebuild : null
479
- });
480
- }
481
- return planPayload(lookup, {
482
- fingerprint,
483
- cacheKey,
484
- cacheHit,
485
- provider,
486
- cacheSkipped: !cachePolicy.read,
487
- prebuild,
488
- ...missReason ? { missReason } : {},
489
- refusal
490
- });
491
- }
492
- function planPayload({ platform, slot, projectKey }, found) {
493
- const { refusal, missReason, ...rest } = found;
494
- const outcome = refusal ? null : found.cacheHit ? "hit" : "cold";
495
- const estimate = outcome ? estimateBuild(readStats$1().record?.history?.[projectKey], platform, outcome) : {
496
- expectedMs: null,
497
- basis: 0
498
- };
499
- return {
500
- platform,
501
- ...slot === "default" ? {} : { slot },
502
- ...rest,
503
- outcome,
504
- expectedMs: estimate.expectedMs,
505
- basis: estimate.basis,
506
- ...missReason ? { missReason } : {},
507
- ...refusal ? { refusal } : {}
508
- };
509
- }
510
- function cacheLine(plan) {
511
- if (plan.refusal) return `the build would refuse with ${plan.refusal.code}`;
512
- if (plan.cacheHit === "local") return "local cache hit";
513
- if (plan.cacheHit === "remote") return `remote cache hit (${plan.provider})`;
514
- return `${plan.cacheSkipped ? "cache reads are off" : "cache miss"}: compiles${plan.prebuild === "generate" || plan.prebuild === "regenerate" ? `, ${plan.prebuild}s the native dir` : ""}`;
515
- }
516
- function printPlan(plan, json) {
517
- if (json) {
518
- console.log(JSON.stringify(plan));
519
- return;
520
- }
521
- const slot = plan.slot ? ` [${plan.slot}]` : "";
522
- console.log(phaseLine("plan", `${plan.platform}${slot} ${shortHash(plan.fingerprint)} -> ${cacheLine(plan)}`));
523
- if (plan.placement) console.log(phaseLine("placement", plan.placement));
524
- if (plan.missReason) console.log(phaseLine("cache", `miss: ${plan.missReason.summary}`));
525
- if (plan.refusal) {
526
- console.log(phaseLine("error", plan.refusal.message));
527
- console.log(phaseLine("remedy", plan.refusal.remedy));
528
- return;
529
- }
530
- console.log(phaseLine("expect", plan.expectedMs === null ? `unknown: no ${plan.outcome} run of this project is recorded yet` : `~${formatDuration(plan.expectedMs)} (median of ${plural(plan.basis, `${plan.outcome} run`)})`));
531
- }
532
- function refusePlan({ code, message, remedy }, json, lines = []) {
533
- console.error(chalk.red(phaseLine("error", message)));
534
- for (const line of lines) console.error(chalk.dim(phaseLine("", line)));
535
- console.error(chalk.dim(phaseLine("remedy", remedy)));
536
- console.error(chalk.red(phaseLine("failed", code)));
537
- if (json) console.log(JSON.stringify({
538
- code,
539
- message,
540
- remedy
541
- }));
542
- process.exitCode = 1;
543
- }
544
- const PLAN_ONLY_REMEDY = "Drop the flag to plan the owned simulator or emulator build, or run the command without --plan.";
545
- function planFlagRefusal(flag) {
546
- return {
547
- code: "STIM_BAD_ARG",
548
- message: `${flag} does not apply to --plan, which predicts the next local build without choosing a device.`,
549
- remedy: PLAN_ONLY_REMEDY
550
- };
551
- }
552
- //#endregion
553
- export { refusePlan as a, devicePlacementLine as c, printPlan as i, probeHost as l, planFlagRefusal as n, checkEasFallback as o, planPayload as r, automaticDevicePlacement as s, planCachedBuild as t };
371
+ export { probeHost as i, automaticDevicePlacement as n, devicePlacementLine as r, checkEasFallback as t };
@@ -1,11 +1,14 @@
1
- import { B as deviceSlotKey, W as projectDeviceSlots } from "./config-BYDxlMY3.mjs";
2
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
3
- import { y as workspaceAgentDeviceDir } from "./workspace-state-DJt_MMvf.mjs";
4
- import { a as formatElapsed, o as formatLongDuration, r as clockTime, u as plural } from "./command-output-BTy8hZ0F.mjs";
5
- import { n as isInsideProject } from "./metro-DnCEjCxs.mjs";
6
- import { r as cdpEndpoint } from "./state-D1Icyjlu.mjs";
7
- import { basename, sep } from "path";
8
- import { ACTIVITY_RECENCY_BASES } from "@stim-cli/core/state";
1
+ import { m as reportSignal, t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
+ import { l as workspaceAgentDeviceDir, v as withDirLock$1, y as withDirLockAsync$1 } from "./paths-DQtTgsBf.mjs";
3
+ import { H as deviceSlotKey, K as projectDeviceSlots } from "./config-CYcBF478.mjs";
4
+ import { a as formatElapsed, o as formatLongDuration, r as clockTime, u as plural } from "./command-output-B1UrjZHL.mjs";
5
+ import { n as isInsideProject } from "./metro-DEXpIhHC.mjs";
6
+ import { r as cdpEndpoint } from "./state-C4ZtUisW.mjs";
7
+ import { accessSync, constants, existsSync, mkdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
8
+ import { delimiter, dirname, join, resolve } from "node:path";
9
+ import { workspaceId } from "@stim-cli/core";
10
+ import { ACTIVITY_RECENCY_BASES, easMachineStateRoot, easMachineStateRoot as easMachineStateRoot$1, easSessionLedgerFile, easSessionLedgerLock, readEasSessionLedger, readEasSessionLedger as readEasSessionLedger$1, validEasSessionClaim } from "@stim-cli/core/state";
11
+ import { basename as basename$1, sep as sep$1 } from "path";
9
12
  //#region src/status.ts
10
13
  const IOS_SIM_MB = 1500;
11
14
  const ANDROID_EMULATOR_MB = 2500;
@@ -127,6 +130,7 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
127
130
  }
128
131
  return {
129
132
  path: project.__path,
133
+ workspaceId: workspaceId(project.__path),
130
134
  ...slots.length ? { slots } : {},
131
135
  live,
132
136
  memoryMb,
@@ -292,7 +296,7 @@ function warningTexts(issues) {
292
296
  function portHolder(cwd, self, workspaces = []) {
293
297
  if (!cwd) return "another app";
294
298
  const owner = workspaces.filter((path) => path !== self && isInsideProject(cwd, path)).toSorted((a, b) => b.length - a.length)[0];
295
- if (owner) return `Metro for workspace ${basename(owner)}`;
299
+ if (owner) return `Metro for workspace ${basename$1(owner)}`;
296
300
  return `a dev server in ${cwd.split(/[\\/]/).filter(Boolean).slice(-3).join("/")}`;
297
301
  }
298
302
  function issueText(issue) {
@@ -383,7 +387,7 @@ function tightVolumes(volumes) {
383
387
  return (volumes || []).filter((v) => v && diskIsTight(v.disk));
384
388
  }
385
389
  function contains(dir, path) {
386
- return path === dir || path.startsWith(dir.endsWith(sep) ? dir : dir + sep);
390
+ return path === dir || path.startsWith(dir.endsWith(sep$1) ? dir : dir + sep$1);
387
391
  }
388
392
  function enclosingWorktree(worktrees, path) {
389
393
  return worktrees.filter((w) => contains(w.path, path)).toSorted((a, b) => b.path.length - a.path.length)[0] ?? null;
@@ -501,4 +505,218 @@ function parseWatchmanClients(payload) {
501
505
  return parsed;
502
506
  }
503
507
  //#endregion
504
- export { statusActivity as C, withWebFacts as E, remoteDeviceState as S, unprovisionedWorktrees as T, gitSummaryText as _, parseWatchmanPid as a, poolLine as b, activityLabel as c, capacity as d, deviceLeaseLines as f, formatSpace as g, environmentState as h, parseWatchmanClients as i, addReverseMissingIssue as l, diskLine as m, parseTriggerCount as n, runWatchman as o, deviceLeaseStates as p, parseWatchRoots as r, RECENT_LAUNCH_MS as s, parseSubscriberNames as t, applyMachineMemory as u, metroReverseTargets as v, tightVolumes as w, remoteDeviceLine as x, parseDfFree as y };
508
+ //#region src/diagnostics/stim-installations.ts
509
+ const VERSION_OUTPUT_LIMIT = 4096;
510
+ function parsedVersion(version) {
511
+ const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(version);
512
+ if (!match) return null;
513
+ const core = [
514
+ match[1],
515
+ match[2],
516
+ match[3]
517
+ ];
518
+ if (core.some((part) => part.length > 1 && part.startsWith("0"))) return null;
519
+ const prereleaseParts = match[4]?.split(".");
520
+ if (prereleaseParts?.some((part) => !part || /^\d+$/.test(part) && part.length > 1 && part.startsWith("0"))) return null;
521
+ const prerelease = prereleaseParts?.map((part) => /^\d+$/.test(part) ? Number(part) : part);
522
+ return {
523
+ core: core.map(Number),
524
+ prerelease: prerelease ?? null
525
+ };
526
+ }
527
+ function compareStimVersions(left, right) {
528
+ const a = parsedVersion(left);
529
+ const b = parsedVersion(right);
530
+ if (!a || !b) return null;
531
+ for (let index = 0; index < a.core.length; index += 1) {
532
+ const difference = (a.core[index] ?? 0) - (b.core[index] ?? 0);
533
+ if (difference !== 0) return difference;
534
+ }
535
+ if (!a.prerelease && !b.prerelease) return 0;
536
+ if (!a.prerelease) return 1;
537
+ if (!b.prerelease) return -1;
538
+ for (let index = 0; index < Math.max(a.prerelease.length, b.prerelease.length); index += 1) {
539
+ const x = a.prerelease[index];
540
+ const y = b.prerelease[index];
541
+ if (x === void 0) return -1;
542
+ if (y === void 0) return 1;
543
+ if (x === y) continue;
544
+ if (typeof x === "number" && typeof y === "number") return x - y;
545
+ if (typeof x === "number") return -1;
546
+ if (typeof y === "number") return 1;
547
+ return x < y ? -1 : 1;
548
+ }
549
+ return 0;
550
+ }
551
+ function parseStimVersionOutput(output) {
552
+ const version = output?.split("\n")[0]?.trim() ?? "";
553
+ return parsedVersion(version) ? version.replace(/^v/, "") : null;
554
+ }
555
+ function executableNames(platform) {
556
+ return platform === "win32" ? [
557
+ "stim.cmd",
558
+ "stim.exe",
559
+ "stim"
560
+ ] : ["stim"];
561
+ }
562
+ function stimExecutablePaths(pathValue, { platform = process.platform, cwd = process.cwd() } = {}) {
563
+ const found = [];
564
+ const seen = /* @__PURE__ */ new Set();
565
+ for (const entry of pathValue.split(delimiter)) {
566
+ const directory = resolve(cwd, entry || ".");
567
+ for (const name of executableNames(platform)) {
568
+ const path = join(directory, name);
569
+ try {
570
+ accessSync(path, platform === "win32" ? constants.F_OK : constants.X_OK);
571
+ if (!statSync(path).isFile()) continue;
572
+ const realPath = realpathSync(path);
573
+ if (seen.has(realPath)) continue;
574
+ seen.add(realPath);
575
+ found.push({
576
+ path,
577
+ realPath
578
+ });
579
+ } catch {}
580
+ }
581
+ }
582
+ return found;
583
+ }
584
+ function canonicalPath(path, cwd) {
585
+ if (!path) return null;
586
+ try {
587
+ return realpathSync(resolve(cwd, path));
588
+ } catch {
589
+ return resolve(cwd, path);
590
+ }
591
+ }
592
+ function analyzeStimVersions(runningVersion, runningPath, installations) {
593
+ const candidates = [runningVersion, ...installations.map((entry) => entry.version)];
594
+ const versions = [...new Set(candidates)].filter((version) => version !== null && compareStimVersions(version, version) !== null).toSorted((left, right) => -(compareStimVersions(left, right) ?? 0));
595
+ const highestVersion = versions[0] ?? null;
596
+ const resolved = installations[0] ?? null;
597
+ return {
598
+ runningVersion,
599
+ runningPath,
600
+ resolved,
601
+ installations,
602
+ versions,
603
+ highestVersion,
604
+ resolvedIsOlder: Boolean(resolved?.version && highestVersion && (compareStimVersions(resolved.version, highestVersion) ?? 0) < 0)
605
+ };
606
+ }
607
+ function probeStimVersion(path, timeoutMs, cwd, env, operation) {
608
+ if (reportSignal(operation)) return getExecutor().runFileQuietAsync(path, ["--version"], {
609
+ timeoutMs,
610
+ cwd,
611
+ env: Object.fromEntries(Object.entries(env).filter((entry) => entry[1] !== void 0))
612
+ }).then((output) => output === null ? null : parseStimVersionOutput(output.slice(0, VERSION_OUTPUT_LIMIT)));
613
+ return new Promise((resolveProbe) => {
614
+ let settled = false;
615
+ let output = "";
616
+ const finish = (version) => {
617
+ if (settled) return;
618
+ settled = true;
619
+ clearTimeout(timer);
620
+ resolveProbe(version);
621
+ };
622
+ let child;
623
+ try {
624
+ child = getExecutor().spawn(path, ["--version"], {
625
+ cwd,
626
+ env,
627
+ stdio: [
628
+ "ignore",
629
+ "pipe",
630
+ "ignore"
631
+ ],
632
+ detached: process.platform !== "win32"
633
+ });
634
+ } catch {
635
+ resolveProbe(null);
636
+ return;
637
+ }
638
+ const timer = setTimeout(() => {
639
+ try {
640
+ if (process.platform !== "win32" && child.pid) process.kill(-child.pid, "SIGKILL");
641
+ else child.kill("SIGKILL");
642
+ } catch {}
643
+ finish(null);
644
+ }, timeoutMs);
645
+ child.stdout?.on("data", (chunk) => {
646
+ if (output.length < VERSION_OUTPUT_LIMIT) output += String(chunk).slice(0, VERSION_OUTPUT_LIMIT - output.length);
647
+ });
648
+ child.on("error", () => finish(null));
649
+ child.on("close", (code) => finish(code === 0 ? parseStimVersionOutput(output) : null));
650
+ });
651
+ }
652
+ async function inspectStimVersions(runningVersion, { cwd = process.cwd(), env = process.env, pathValue = env[process.platform === "win32" ? Object.keys(env).toSorted().find((key) => key.toUpperCase() === "PATH") ?? "PATH" : "PATH"] ?? "", runningPath = process.argv[1], probeTimeoutMs = 5e3, operation } = {}) {
653
+ const paths = stimExecutablePaths(pathValue, { cwd });
654
+ const versions = await Promise.all(paths.map((entry) => probeStimVersion(entry.path, probeTimeoutMs, cwd, env, operation)));
655
+ const installations = paths.map((entry, index) => ({
656
+ path: entry.path,
657
+ realPath: entry.realPath,
658
+ version: versions[index] ?? null
659
+ }));
660
+ return analyzeStimVersions(runningVersion, canonicalPath(runningPath, cwd), installations);
661
+ }
662
+ //#endregion
663
+ //#region src/engine/eas-machine-root-guard-env.ts
664
+ const EAS_TEST_GUARD_ROOT_ENV = "STIM_TEST_GUARD_REAL_EAS_ROOT";
665
+ //#endregion
666
+ //#region src/engine/eas-session-ledger.ts
667
+ function assertEasMachineRootWritable(root) {
668
+ const guardedRoot = process.env[EAS_TEST_GUARD_ROOT_ENV];
669
+ if (!guardedRoot || resolve(root) !== resolve(guardedRoot)) return;
670
+ throw new Error(`Refusing to write the real EAS machine root ${root} from a test process. Pass a temporary ledgerRoot, machineRoot, or easLedgerRoot, or point HOME (and USERPROFILE on Windows) at a temporary directory.`);
671
+ }
672
+ function writeLedger(root, ledger) {
673
+ mkdirSync(root, { recursive: true });
674
+ const file = easSessionLedgerFile(root);
675
+ const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
676
+ writeFileSync(tmp, `${JSON.stringify(ledger, null, 2)}\n`);
677
+ try {
678
+ renameSync(tmp, file);
679
+ } catch (error) {
680
+ rmSync(tmp, { force: true });
681
+ throw error;
682
+ }
683
+ }
684
+ function recordEasSessionClaim(claim, root = easMachineStateRoot()) {
685
+ assertEasMachineRootWritable(root);
686
+ const normalized = validEasSessionClaim(claim.sessionId, claim);
687
+ if (!normalized) throw new Error(`Invalid EAS session claim for ${claim.sessionId}.`);
688
+ withDirLock$1(easSessionLedgerLock(root), () => {
689
+ const current = readEasSessionLedger(root);
690
+ if (!current.safe) throw new Error(current.notice ?? "EAS ownership ledger is unreadable.");
691
+ current.claims.set(normalized.sessionId, normalized);
692
+ writeLedger(root, {
693
+ version: 1,
694
+ claims: Object.fromEntries(current.claims)
695
+ });
696
+ }, { ensureParent: () => mkdirSync(dirname(easSessionLedgerLock(root)), { recursive: true }) });
697
+ }
698
+ function removeEasSessionClaim(sessionId, root = easMachineStateRoot(), when = () => true) {
699
+ const file = easSessionLedgerFile(root);
700
+ if (!existsSync(file)) return false;
701
+ assertEasMachineRootWritable(root);
702
+ return withDirLock$1(easSessionLedgerLock(root), () => {
703
+ const current = readEasSessionLedger(root);
704
+ if (!current.safe) return false;
705
+ const claim = current.claims.get(sessionId);
706
+ if (!claim || !when(claim)) return false;
707
+ current.claims.delete(sessionId);
708
+ writeLedger(root, {
709
+ version: 1,
710
+ claims: Object.fromEntries(current.claims)
711
+ });
712
+ return true;
713
+ });
714
+ }
715
+ /** Removes a matching EAS session claim after asynchronously acquiring the ownership ledger lock. */
716
+ async function removeEasSessionClaimAsync(sessionId, root = easMachineStateRoot(), when = () => true) {
717
+ if (!existsSync(easSessionLedgerFile(root))) return false;
718
+ assertEasMachineRootWritable(root);
719
+ return withDirLockAsync$1(easSessionLedgerLock(root), () => removeEasSessionClaim(sessionId, root, when));
720
+ }
721
+ //#endregion
722
+ export { remoteDeviceState as A, environmentState as C, parseDfFree as D, metroReverseTargets as E, tightVolumes as M, unprovisionedWorktrees as N, poolLine as O, withWebFacts as P, diskLine as S, gitSummaryText as T, addReverseMissingIssue as _, removeEasSessionClaim as a, deviceLeaseLines as b, inspectStimVersions as c, parseWatchRoots as d, parseWatchmanClients as f, activityLabel as g, RECENT_LAUNCH_MS as h, recordEasSessionClaim as i, statusActivity as j, remoteDeviceLine as k, parseSubscriberNames as l, runWatchman as m, easMachineStateRoot$1 as n, removeEasSessionClaimAsync as o, parseWatchmanPid as p, readEasSessionLedger$1 as r, compareStimVersions as s, assertEasMachineRootWritable as t, parseTriggerCount as u, applyMachineMemory as v, formatSpace as w, deviceLeaseStates as x, capacity as y };