stim 1.20.2 → 1.22.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 (231) hide show
  1. package/README.md +141 -8
  2. package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
  3. package/dist/act-DsuqEkiM.mjs +2801 -0
  4. package/dist/activity-CMLmzp7o.mjs +1397 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
  6. package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
  7. package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
  8. package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
  9. package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +2 -2
  11. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/android-project-DVWyCbWU.d.mts +391 -0
  14. package/dist/api.d.mts +810 -64
  15. package/dist/api.mjs +782 -1
  16. package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
  17. package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
  18. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  19. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
  20. package/dist/budget-Cvwn54qV.mjs +9285 -0
  21. package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
  22. package/dist/build-cache-Dv7RN200.mjs +602 -0
  23. package/dist/build-plan-DUC8Ka9y.mjs +248 -0
  24. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
  25. package/dist/cache-manifest.mjs +1 -1
  26. package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
  27. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
  28. package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
  29. package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
  30. package/dist/cli.mjs +1 -1
  31. package/dist/client-OyRoEuSr.mjs +1577 -0
  32. package/dist/collector-run.d.mts +4 -40
  33. package/dist/collector-run.mjs +9 -8
  34. package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
  35. package/dist/config-DlrsduwG.mjs +955 -0
  36. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
  37. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
  38. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  39. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
  40. package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
  41. package/dist/device-DklWZLqb.mjs +1068 -0
  42. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
  43. package/dist/device-host-worker.mjs +76 -79
  44. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
  45. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
  46. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
  49. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  50. package/dist/doctor-fingerprint.mjs +19 -0
  51. package/dist/doctor-thjWAV0z.mjs +2 -0
  52. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
  53. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
  54. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
  55. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
  56. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
  57. package/dist/exec-DEoAhcze.mjs +858 -0
  58. package/dist/exec-DnYc4HGH.d.mts +78 -0
  59. package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
  60. package/dist/gc-DnNDQyaP.mjs +3 -0
  61. package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
  62. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
  63. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
  64. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  65. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
  66. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
  67. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
  68. package/dist/idle-C4cZ757K.d.mts +24 -0
  69. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
  70. package/dist/ios-CDvlmUs7.d.mts +24 -0
  71. package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
  73. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  74. package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
  75. package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
  76. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
  77. package/dist/ios-signing-BtAffm0A.mjs +489 -0
  78. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  79. package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
  80. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
  81. package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
  82. package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
  83. package/dist/logs-BfwwadsZ.mjs +479 -0
  84. package/dist/logs-jTS_lHSo.mjs +248 -0
  85. package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
  86. package/dist/macos-NfV2D7dO.mjs +694 -0
  87. package/dist/macos-run.mjs +1 -1
  88. package/dist/maintenance-run.mjs +123 -248
  89. package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
  90. package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
  91. package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
  92. package/dist/native-android-CqgnOgsT.mjs +645 -0
  93. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  94. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
  95. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  96. package/dist/native-run-NwUuxbkg.mjs +276 -0
  97. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
  98. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  99. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
  100. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
  101. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  102. package/dist/offload-worker.d.mts +59 -41
  103. package/dist/offload-worker.mjs +478 -115
  104. package/dist/operation-exec-BW0em61G.mjs +171 -0
  105. package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
  106. package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
  107. package/dist/paths-BsJMoPP2.mjs +12 -0
  108. package/dist/paths-DQtTgsBf.mjs +42 -0
  109. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
  110. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
  111. package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  112. package/dist/prebuild-D4JoEAEs.mjs +484 -0
  113. package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
  114. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  115. package/dist/pull-request-eODyIqZF.d.mts +124 -0
  116. package/dist/pull-requests.d.mts +2 -120
  117. package/dist/pull-requests.mjs +2 -2
  118. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
  119. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
  120. package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
  121. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
  122. package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
  123. package/dist/registration-BcRgF6Ox.mjs +51 -0
  124. package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
  125. package/dist/reload-D7AVlb8N.mjs +2 -0
  126. package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
  127. package/dist/result-D2Ykz_iD.mjs +435 -0
  128. package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
  129. package/dist/selection-DSMbWEX2.mjs +620 -0
  130. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
  131. package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
  132. package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
  133. package/dist/server-expo-D58c9L0M.mjs +2 -0
  134. package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
  135. package/dist/settings-DpR-1Wnn.mjs +114 -0
  136. package/dist/settings-write-CzD60rOD.mjs +360 -0
  137. package/dist/settings.schema.json +176 -16
  138. package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
  139. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
  140. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  141. package/dist/stage-Bps5oius.mjs +200 -0
  142. package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
  143. package/dist/start-EojN4WFz.mjs +1364 -0
  144. package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
  145. package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
  146. package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
  147. package/dist/stats-report-BzaPrRm6.mjs +16 -0
  148. package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
  149. package/dist/status-EvrK72L2.mjs +2 -0
  150. package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
  151. package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
  152. package/dist/status-worker.d.mts +1 -0
  153. package/dist/status-worker.mjs +19 -0
  154. package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
  155. package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
  156. package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
  157. package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
  158. package/dist/supervisor-run.d.mts +8 -17
  159. package/dist/supervisor-run.mjs +56 -28
  160. package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
  161. package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
  162. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  163. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  164. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  165. package/dist/toolchain-DpJMHq0n.mjs +876 -0
  166. package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
  167. package/dist/trigger-yb_nFzPF.mjs +2 -0
  168. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
  169. package/dist/web-CZ07gd77.mjs +2 -0
  170. package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
  171. package/dist/web-run.mjs +13 -12
  172. package/dist/windows-report.d.mts +1 -0
  173. package/dist/windows-report.mjs +18 -0
  174. package/dist/windows-report.ps1 +43 -0
  175. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
  176. package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
  177. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
  178. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  179. package/dist/xcode-BXn9-xYx.mjs +896 -0
  180. package/package.json +7 -5
  181. package/shim/android-audio/Main.java +24 -0
  182. package/shim/android-audio/README.md +17 -0
  183. package/shim/android-audio.jar +0 -0
  184. package/shim/android-optimizations.gradle +7 -5
  185. package/dist/activity-BSV745Kz.mjs +0 -629
  186. package/dist/api-qvOzWyfO.mjs +0 -154
  187. package/dist/api-run.mjs +0 -294
  188. package/dist/app-install-BIKtMfPq.mjs +0 -896
  189. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  190. package/dist/budget-f7516Zk0.mjs +0 -4106
  191. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  192. package/dist/cancellation-C_22VQTH.mjs +0 -24
  193. package/dist/client-qQAaXSUs.mjs +0 -1771
  194. package/dist/config-BYDxlMY3.mjs +0 -562
  195. package/dist/device-DuiPJQSn.mjs +0 -290
  196. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  197. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  198. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  199. package/dist/exec-DqKo9GKJ.mjs +0 -268
  200. package/dist/git-DDfFzkMm.mjs +0 -45
  201. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  202. package/dist/logs-BGrEUaEs.mjs +0 -383
  203. package/dist/macos-Ch5VJmcS.mjs +0 -584
  204. package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
  205. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  206. package/dist/native-android-D5qc3-_v.mjs +0 -226
  207. package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
  208. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  209. package/dist/plan-C4TjdPsR.mjs +0 -260
  210. package/dist/prebuild-DYbucPXy.mjs +0 -212
  211. package/dist/preview-78a9kR_-.mjs +0 -1011
  212. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  213. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  214. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  215. package/dist/result-CaJg5Iat.mjs +0 -186
  216. package/dist/server-expo-Bigriskl.mjs +0 -2
  217. package/dist/settings-BORNaaCO.mjs +0 -402
  218. package/dist/settings-vk3mJGSm.d.mts +0 -13
  219. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  220. package/dist/stage-KNTQopqv.mjs +0 -157
  221. package/dist/start-BWqzODpb.mjs +0 -1116
  222. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  223. package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
  224. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  225. package/dist/toolchain-BFkAcstd.mjs +0 -2
  226. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  227. package/dist/trigger-9_USgmxz.mjs +0 -2
  228. package/dist/web-Dq-i3wzJ.mjs +0 -2
  229. package/dist/worktree-DpLdCHga.mjs +0 -2
  230. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  231. package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
@@ -1,23 +1,26 @@
1
- import { B as deviceSlotKey, V as deviceSlotPlatforms, p as getProject } from "./config-BYDxlMY3.mjs";
2
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
3
- import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-BX1sJQ2E.mjs";
4
- import { D as withDirLock, r as readWorkspaceState$1 } from "./workspace-state-DJt_MMvf.mjs";
5
- import { v as launchErrorPreview } from "./command-output-BTy8hZ0F.mjs";
6
- import { F as readWorkspaceLaunches } from "./project-_phNIJfs.mjs";
7
- import { o as androidHome, u as androidToolCwd } from "./android-Mz_Inn3w.mjs";
8
- import { u as resolveProjectMetro } from "./metro-DnCEjCxs.mjs";
9
- import { r as deviceConsoleLevel } from "./ios-device-B5veSDDQ.mjs";
10
- import { n as parseLogcatLine, t as androidClockOffset } from "./android-HqP1_vB_.mjs";
11
- import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
12
- import { basename, dirname, join, resolve, sep } from "node:path";
13
- import { NATIVE_CRASH_LOG_PREFIX, attachExpoErrorContext, readLogRecords, readLogTimeline } from "@stim-cli/core/state";
1
+ import { t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { v as withDirLock$1 } from "./paths-DQtTgsBf.mjs";
3
+ import { H as deviceSlotPlatforms, V as deviceSlotKey, p as getProject } from "./config-DlrsduwG.mjs";
4
+ import { v as launchErrorPreview } from "./command-output-gwpm28fu.mjs";
5
+ import { r as readWorkspaceState$1 } from "./workspace-state-U08dEzhG.mjs";
6
+ import { I as readWorkspaceLaunches } from "./project-wM_XFTvE.mjs";
7
+ import { d as resolveProjectMetro } from "./metro-DiXtA3Ty.mjs";
8
+ import { S as parseLease, v as deviceLeasePath, y as fileLeaseIo } from "./activity-CMLmzp7o.mjs";
9
+ import { o as androidHome, u as androidToolCwd } from "./android-C7sVmyI9.mjs";
10
+ import { r as deviceConsoleLevel } from "./ios-device-BXZ0c7Kb.mjs";
11
+ import { n as parseLogcatLine } from "./android-DR5lZ2Az.mjs";
14
12
  import { createHash, randomUUID } from "node:crypto";
13
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
15
14
  import { homedir } from "node:os";
15
+ import { basename, dirname, join, resolve, sep } from "node:path";
16
+ import { withDirLockAsync } from "@stim-cli/core";
17
+ import { NATIVE_CRASH_LOG_PREFIX, attachExpoErrorContext, readLogRecords, readLogTimeline } from "@stim-cli/core/state";
18
+ import { mkdir, readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
16
19
  //#region src/diagnostics/diagnostic-store.ts
17
20
  /** Publishes an immutable diagnostic snapshot atomically; existing evidence wins. */
18
21
  function writeDiagnosticOnce(path, content) {
19
22
  mkdirSync(dirname(path), { recursive: true });
20
- withDirLock(`${path}.lock`, () => {
23
+ withDirLock$1(`${path}.lock`, () => {
21
24
  if (existsSync(path)) return;
22
25
  const temporary = `${path}.${randomUUID()}.tmp`;
23
26
  try {
@@ -33,6 +36,27 @@ function writeDiagnosticOnce(path, content) {
33
36
  pollMs: 10
34
37
  });
35
38
  }
39
+ /** Publishes an immutable diagnostic snapshot without blocking on content writes or lock contention. */
40
+ async function writeDiagnosticOnceAsync(path, content, signal) {
41
+ signal?.throwIfAborted();
42
+ await mkdir(dirname(path), { recursive: true });
43
+ const temporary = `${path}.${randomUUID()}.tmp`;
44
+ try {
45
+ await writeFile(temporary, content, {
46
+ flag: "wx",
47
+ signal
48
+ });
49
+ await withDirLockAsync(`${path}.lock`, () => {
50
+ signal?.throwIfAborted();
51
+ if (!existsSync(path)) renameSync(temporary, path);
52
+ }, {
53
+ waitMs: 100,
54
+ pollMs: 10
55
+ });
56
+ } finally {
57
+ await unlink(temporary).catch(() => {});
58
+ }
59
+ }
36
60
  //#endregion
37
61
  //#region src/diagnostics/native-crash.ts
38
62
  const IOS_CRASH_REPORT_RETRY = "iOS crash reports can take about a minute or longer to appear. Run `stim logs --errors` again for the native stack.";
@@ -115,7 +139,7 @@ function parseAndroidCrashes(text, target, clockOffsetMs) {
115
139
  }];
116
140
  });
117
141
  }
118
- function symbolicateIos(record, report, appPath, deadline) {
142
+ async function symbolicateIos(record, report, appPath, deadline, signal) {
119
143
  if (!appPath || !existsSync(appPath) || !Array.isArray(record.stack)) return record;
120
144
  const thread = report.threads?.find((entry) => entry.triggered) ?? report.threads?.[report.faultingThread ?? -1];
121
145
  const stack = [...record.stack];
@@ -133,11 +157,11 @@ function symbolicateIos(record, report, appPath, deadline) {
133
157
  const binary = relative ? resolve(appPath, relative) : null;
134
158
  let matched = null;
135
159
  if (binary && binary.startsWith(resolve(appPath) + sep) && existsSync(binary)) {
136
- if (getExecutor().runFileQuiet("xcrun", [
160
+ if ((await crashCommand("xcrun", [
137
161
  "dwarfdump",
138
162
  "--uuid",
139
163
  binary
140
- ], { timeoutMs: 2e3 })?.toLowerCase().includes(`uuid: ${image.uuid.toLowerCase()} (${image.arch.toLowerCase()})`)) matched = binary;
164
+ ], { timeoutMs: 2e3 }, signal))?.toLowerCase().includes(`uuid: ${image.uuid.toLowerCase()} (${image.arch.toLowerCase()})`)) matched = binary;
141
165
  }
142
166
  verified.set(imageIndex, matched);
143
167
  }
@@ -145,7 +169,7 @@ function symbolicateIos(record, report, appPath, deadline) {
145
169
  if (!binary || Date.now() >= deadline) continue;
146
170
  const address = image.base + frame.imageOffset;
147
171
  if (!Number.isSafeInteger(address)) continue;
148
- const output = getExecutor().runFileQuiet("xcrun", [
172
+ const output = await crashCommand("xcrun", [
149
173
  "atos",
150
174
  "-o",
151
175
  binary,
@@ -154,7 +178,7 @@ function symbolicateIos(record, report, appPath, deadline) {
154
178
  "-l",
155
179
  `0x${image.base.toString(16)}`,
156
180
  `0x${address.toString(16)}`
157
- ], { timeoutMs: 2e3 });
181
+ ], { timeoutMs: 2e3 }, signal);
158
182
  if (output && !/^0x[0-9a-f]+$/i.test(output) && !/error:|cannot|unable/i.test(output)) stack[index] = {
159
183
  file: image.name ?? basename(binary),
160
184
  fn: output
@@ -165,7 +189,7 @@ function symbolicateIos(record, report, appPath, deadline) {
165
189
  stack
166
190
  };
167
191
  }
168
- function symbolicateAndroid(record, root, budget) {
192
+ async function symbolicateAndroid(record, root, budget, signal, env = process.env) {
169
193
  if (!root || typeof record.msg !== "string" || !/#\d+ pc /.test(record.msg)) return record;
170
194
  const frames = [...record.msg.matchAll(/^\s*#\d+ pc ([0-9a-f]+)\s+(\S+)(.*)$/gim)];
171
195
  const stack = frames.map(([, address, file, suffix]) => ({
@@ -173,12 +197,12 @@ function symbolicateAndroid(record, root, budget) {
173
197
  fn: `${suffix?.trim() || `0x${address}`} [captured native frame]`
174
198
  }));
175
199
  let deadline = Math.min(Date.now() + 2e3, budget - 1e3);
176
- const ndks = join(androidHome(), "ndk");
200
+ const ndks = join(androidHome(env), "ndk");
177
201
  let tools;
178
202
  try {
179
- for (const version of readdirSync(ndks).toSorted().toReversed()) {
203
+ for (const version of (await readdir(ndks)).toSorted().toReversed()) {
180
204
  const prebuilt = join(ndks, version, "toolchains/llvm/prebuilt");
181
- for (const host of readdirSync(prebuilt)) {
205
+ for (const host of await readdir(prebuilt)) {
182
206
  const bin = join(prebuilt, host, "bin");
183
207
  if (existsSync(join(bin, "llvm-symbolizer"))) {
184
208
  tools = bin;
@@ -189,10 +213,10 @@ function symbolicateAndroid(record, root, budget) {
189
213
  }
190
214
  } catch {}
191
215
  const files = [];
192
- const visit = (directory, depth) => {
216
+ const visit = async (directory, depth) => {
193
217
  if (depth > 10 || files.length > 500 || Date.now() >= deadline) return;
194
218
  try {
195
- for (const entry of readdirSync(directory, { withFileTypes: true })) if (entry.isDirectory()) visit(join(directory, entry.name), depth + 1);
219
+ for (const entry of await readdir(directory, { withFileTypes: true })) if (entry.isDirectory()) await visit(join(directory, entry.name), depth + 1);
196
220
  else if (entry.isFile() && entry.name.endsWith(".so")) files.push(join(directory, entry.name));
197
221
  } catch {}
198
222
  };
@@ -201,7 +225,7 @@ function symbolicateAndroid(record, root, budget) {
201
225
  "android/app/src/main/jniLibs",
202
226
  "android/app/build/intermediates/cxx",
203
227
  "android/app/.cxx"
204
- ]) visit(join(root, directory), 0);
228
+ ]) await visit(join(root, directory), 0);
205
229
  deadline = budget;
206
230
  const byId = /* @__PURE__ */ new Map();
207
231
  for (const [index, [, address, file, suffix]] of frames.entries()) {
@@ -209,21 +233,25 @@ function symbolicateAndroid(record, root, budget) {
209
233
  const id = /\(BuildId: ([0-9a-f]+)\)/i.exec(suffix ?? "")?.[1]?.toLowerCase();
210
234
  if (!id) continue;
211
235
  if (!byId.has(id)) {
212
- const binary = files.filter((path) => file.endsWith(".apk") || basename(path) === basename(file)).find((path) => {
213
- if (Date.now() >= deadline) return false;
214
- const notes = getExecutor().runFileQuiet(join(tools, "llvm-readelf"), ["--notes", path], { timeoutMs: 1e3 });
215
- return /Build ID: ([0-9a-f]+)/i.exec(notes ?? "")?.[1]?.toLowerCase() === id;
216
- });
236
+ let binary;
237
+ for (const path of files.filter((candidate) => file.endsWith(".apk") || basename(candidate) === basename(file))) {
238
+ if (Date.now() >= deadline) break;
239
+ const notes = await crashCommand(join(tools, "llvm-readelf"), ["--notes", path], { timeoutMs: 1e3 }, signal);
240
+ if (/Build ID: ([0-9a-f]+)/i.exec(notes ?? "")?.[1]?.toLowerCase() === id) {
241
+ binary = path;
242
+ break;
243
+ }
244
+ }
217
245
  byId.set(id, binary ?? null);
218
246
  }
219
247
  const binary = byId.get(id);
220
248
  if (!binary) continue;
221
- const [fn, location] = getExecutor().runFileQuiet(join(tools, "llvm-symbolizer"), [
249
+ const [fn, location] = (await crashCommand(join(tools, "llvm-symbolizer"), [
222
250
  "--no-inlines",
223
251
  "--demangle",
224
252
  `--obj=${binary}`,
225
253
  `0x${address}`
226
- ], { timeoutMs: 1e3 })?.split("\n") ?? [];
254
+ ], { timeoutMs: 1e3 }, signal))?.split("\n") ?? [];
227
255
  const match = /^(.*):(\d+):(\d+)$/.exec(location ?? "");
228
256
  if (fn && fn !== "??" && match && match[1] !== "??" && Number(match[2]) > 0) stack[index] = {
229
257
  fn,
@@ -241,15 +269,15 @@ function symbolicateAndroid(record, root, budget) {
241
269
  symbolicationNote: stack.some((frame) => !frame.line) ? "Native symbols are partial: unresolved frames retain crash-buffer symbols/addresses. Full captured report: stim logs --source device --json." : void 0
242
270
  };
243
271
  }
244
- function simulatorConsolePaths(target, prepare = false, remote = false) {
272
+ async function simulatorConsolePaths(target, prepare = false, remote = false, signal) {
245
273
  if (remote) return void 0;
246
- const container = getExecutor().runFileQuiet("xcrun", [
274
+ const container = await crashCommand("xcrun", [
247
275
  "simctl",
248
276
  "get_app_container",
249
277
  target.deviceId,
250
278
  target.appId,
251
279
  "data"
252
- ], { timeoutMs: 2e3 });
280
+ ], { timeoutMs: 2e3 }, signal);
253
281
  if (!container?.startsWith("/")) return void 0;
254
282
  const directory = join(container, "Library/Caches/Stim");
255
283
  const key = createHash("sha256").update(JSON.stringify([
@@ -262,24 +290,35 @@ function simulatorConsolePaths(target, prepare = false, remote = false) {
262
290
  stderr: join(directory, `launch-${key}.stderr`)
263
291
  };
264
292
  if (prepare) try {
265
- mkdirSync(directory, { recursive: true });
266
- for (const path of Object.values(paths)) writeFileSync(path, "", { flag: "wx" });
293
+ await mkdir(directory, { recursive: true });
294
+ for (const path of Object.values(paths)) await writeFile(path, "", {
295
+ flag: "wx",
296
+ signal
297
+ });
267
298
  } catch {
299
+ signal?.throwIfAborted();
268
300
  return;
269
301
  }
302
+ signal?.throwIfAborted();
270
303
  return paths;
271
304
  }
272
- function simulatorFatalConsole(target) {
273
- const paths = simulatorConsolePaths(target);
274
- return Object.values(paths ?? {}).flatMap((path) => {
305
+ async function simulatorFatalConsole(target, signal) {
306
+ const paths = await simulatorConsolePaths(target, false, false, signal);
307
+ const records = [];
308
+ for (const path of Object.values(paths ?? {})) {
309
+ signal?.throwIfAborted();
275
310
  try {
276
- if (statSync(path).size > 8388608) return [];
277
- if (target.until !== void 0 && statSync(path).mtimeMs > target.until) return [];
278
- const text = readFileSync(path, "utf8");
311
+ const info = await stat(path);
312
+ if (info.size > 8388608) continue;
313
+ if (target.until !== void 0 && info.mtimeMs > target.until) continue;
314
+ const text = await readFile(path, {
315
+ encoding: "utf8",
316
+ signal
317
+ });
279
318
  const fatal = text.split("\n").filter((line) => deviceConsoleLevel(line) === "fatal");
280
- if (!fatal.length) return [];
281
- return [{
282
- ts: Math.max(target.since + 1, statSync(path).mtimeMs),
319
+ if (!fatal.length) continue;
320
+ records.push({
321
+ ts: Math.max(target.since + 1, info.mtimeMs),
283
322
  src: "device",
284
323
  platform: "ios",
285
324
  level: "fatal",
@@ -291,34 +330,60 @@ function simulatorFatalConsole(target) {
291
330
  msg: fatal.join("\n"),
292
331
  rawReport: text,
293
332
  symbolicationNote: `Captured app stderr; the full operating system crash report is not available yet. ${IOS_CRASH_REPORT_RETRY}`
294
- }];
295
- } catch {
296
- return [];
297
- }
298
- });
333
+ });
334
+ } catch {}
335
+ }
336
+ signal?.throwIfAborted();
337
+ return records;
299
338
  }
300
339
  /** Reads platform crash evidence without starting, stopping or modifying a device. */
301
- function captureNativeCrashes(target, logsDir) {
340
+ async function captureNativeCrashes(target, logsDir, signal, env = process.env) {
341
+ signal?.throwIfAborted();
302
342
  let records = [];
303
343
  try {
304
344
  if (target.platform === "ios" && !target.physical && process.platform === "darwin") {
305
345
  const deadline = Date.now() + 4e3;
306
- records = simulatorFatalConsole(target);
307
- const directory = join(homedir(), "Library/Logs/DiagnosticReports");
308
- const nativeReports = readdirSync(directory).filter((name) => name.endsWith(".ips")).map((name) => ({
309
- path: join(directory, name),
310
- time: statSync(join(directory, name)).mtimeMs
311
- })).filter(({ time }) => time >= target.since).toSorted((a, b) => b.time - a.time).slice(0, 50).flatMap(({ path }) => {
312
- if (Date.now() >= deadline) return [];
313
- if (statSync(path).size > 8388608) return [];
314
- const parsed = parseIosCrash(readFileSync(path, "utf8"), target);
315
- return parsed ? [symbolicateIos(parsed.record, parsed.report, target.appPath, deadline)] : [];
316
- });
346
+ records = await simulatorFatalConsole(target, signal);
347
+ const directory = join(env.HOME || homedir(), "Library/Logs/DiagnosticReports");
348
+ const reports = [];
349
+ for (const name of await readdir(directory)) {
350
+ signal?.throwIfAborted();
351
+ if (!name.endsWith(".ips")) continue;
352
+ const path = join(directory, name);
353
+ const time = (await stat(path)).mtimeMs;
354
+ if (time >= target.since) reports.push({
355
+ path,
356
+ time
357
+ });
358
+ }
359
+ reports.sort((a, b) => b.time - a.time);
360
+ const nativeReports = [];
361
+ for (const { path } of reports.slice(0, 50)) {
362
+ if (Date.now() >= deadline) break;
363
+ if ((await stat(path)).size > 8388608) continue;
364
+ const parsed = parseIosCrash(await readFile(path, {
365
+ encoding: "utf8",
366
+ signal
367
+ }), target);
368
+ if (parsed) nativeReports.push(await symbolicateIos(parsed.record, parsed.report, target.appPath, deadline, signal));
369
+ }
317
370
  if (nativeReports.length) records = nativeReports;
318
371
  } else if (target.platform === "android") {
319
- const offset = androidClockOffset(target.deviceId);
320
- if (offset === null) return [];
321
- const text = getExecutor().runFileQuiet("adb", [
372
+ const before = Date.now();
373
+ const clock = (await crashCommand("adb", [
374
+ "-s",
375
+ target.deviceId,
376
+ "shell",
377
+ "date",
378
+ "+%s%3N"
379
+ ], {
380
+ timeoutMs: 1e3,
381
+ cwd: androidToolCwd()
382
+ }, signal))?.trim();
383
+ const after = Date.now();
384
+ if (!/^\d{13}$/.test(clock ?? "") || after < before || after - before > 1e3) return [];
385
+ const offset = Math.round((before + after) / 2) - Number(clock);
386
+ const text = await crashCommand("adb", [
322
387
  "-s",
323
388
  target.deviceId,
324
389
  "logcat",
@@ -332,11 +397,12 @@ function captureNativeCrashes(target, logsDir) {
332
397
  ], {
333
398
  timeoutMs: 3e3,
334
399
  cwd: androidToolCwd()
335
- });
400
+ }, signal);
336
401
  const deadline = Date.now() + 4e3;
337
- if (text) records = parseAndroidCrashes(text, target, offset).map((record) => symbolicateAndroid(record, target.root, deadline));
402
+ if (text) for (const record of parseAndroidCrashes(text, target, offset)) records.push(await symbolicateAndroid(record, target.root, deadline, signal, env));
338
403
  }
339
404
  } catch {}
405
+ signal?.throwIfAborted();
340
406
  for (const record of records) {
341
407
  if (target.slot && target.slot !== "default") record.slot = target.slot;
342
408
  try {
@@ -346,23 +412,26 @@ function captureNativeCrashes(target, logsDir) {
346
412
  record.incident ?? record.deviceTs,
347
413
  record.rawReport
348
414
  ])).digest("hex");
349
- writeDiagnosticOnce(join(logsDir, `${NATIVE_CRASH_LOG_PREFIX}${key}.ndjson`), `${JSON.stringify(record)}\n`);
415
+ await writeDiagnosticOnceAsync(join(logsDir, `${NATIVE_CRASH_LOG_PREFIX}${key}.ndjson`), `${JSON.stringify(record)}\n`, signal);
350
416
  } catch {}
351
417
  }
418
+ signal?.throwIfAborted();
352
419
  return records;
353
420
  }
354
- function printNativeCrashReport(target, logsDir, emit, remote) {
421
+ async function printNativeCrashReport(target, logsDir, emit, remote, signal, env) {
355
422
  if (remote) return;
356
- for (const line of launchErrorPreview(captureNativeCrashes(target, logsDir), target.root)) emit(line);
423
+ for (const line of launchErrorPreview(await captureNativeCrashes(target, logsDir, signal, env), target.root)) emit(line);
357
424
  }
358
- /** Captures native crash reports for this workspace's current launches and returns the whole timeline. */
359
- function captureWorkspaceCrashes(root, logsDir) {
360
- const timeline = readLogRecords(logsDir, (name) => !name.startsWith(NATIVE_CRASH_LOG_PREFIX));
361
- const attempts = timeline.filter((record) => record.event === "launch_attempt");
425
+ /** Captures current launch crashes. Supplying attempts skips the timeline read and returns an empty array. */
426
+ async function captureWorkspaceCrashes(root, logsDir, attempts, signal, env = process.env) {
427
+ signal?.throwIfAborted();
428
+ const timeline = attempts === void 0 ? readLogRecords(logsDir, (name) => !name.startsWith(NATIVE_CRASH_LOG_PREFIX)) : [];
429
+ const launchAttempts = attempts ?? timeline.filter((record) => record.event === "launch_attempt");
362
430
  const launches = readWorkspaceLaunches(root);
363
431
  const latest = /* @__PURE__ */ new Map();
364
- for (const attempt of attempts) if (attempt.platform === "ios" || attempt.platform === "android") latest.set(deviceSlotKey(attempt.platform, String(attempt.slot ?? "default")), attempt);
432
+ for (const attempt of launchAttempts) if (attempt.platform === "ios" || attempt.platform === "android") latest.set(deviceSlotKey(attempt.platform, String(attempt.slot ?? "default")), attempt);
365
433
  for (const [key, attempt] of latest) {
434
+ signal?.throwIfAborted();
366
435
  const platform = attempt.platform;
367
436
  const slot = String(attempt.slot ?? "default");
368
437
  try {
@@ -383,7 +452,7 @@ function captureWorkspaceCrashes(root, logsDir) {
383
452
  if (platform === "ios" && configured.deviceUdid !== deviceId) continue;
384
453
  if (platform === "android") {
385
454
  if (!configured.avdName) continue;
386
- if (getExecutor().runFileQuiet("adb", [
455
+ if ((await crashCommand("adb", [
387
456
  "-s",
388
457
  deviceId,
389
458
  "emu",
@@ -392,10 +461,10 @@ function captureWorkspaceCrashes(root, logsDir) {
392
461
  ], {
393
462
  timeoutMs: 2e3,
394
463
  cwd: androidToolCwd()
395
- })?.split("\n")[0]?.trim() !== configured.avdName) continue;
464
+ }, signal))?.split("\n")[0]?.trim() !== configured.avdName) continue;
396
465
  }
397
466
  }
398
- captureNativeCrashes({
467
+ await captureNativeCrashes({
399
468
  root,
400
469
  slot,
401
470
  platform,
@@ -405,10 +474,31 @@ function captureWorkspaceCrashes(root, logsDir) {
405
474
  until,
406
475
  physical: attempt?.physical === true,
407
476
  appPath: attempt?.appPath ?? readWorkspaceState$1(root)?.lastBuild?.appPath
408
- }, logsDir);
477
+ }, logsDir, signal, env);
409
478
  } catch {}
410
479
  }
411
- return readLogTimeline(logsDir, timeline);
480
+ signal?.throwIfAborted();
481
+ return attempts === void 0 ? readLogTimeline(logsDir, timeline) : [];
482
+ }
483
+ async function crashCommand(file, args, options, signal) {
484
+ signal?.throwIfAborted();
485
+ let cancel;
486
+ try {
487
+ const result = await getExecutor().runFileQuietAsync(file, args, {
488
+ ...options,
489
+ ...signal ? { onSpawn(child) {
490
+ cancel = () => {
491
+ child.kill("SIGKILL");
492
+ };
493
+ signal.addEventListener("abort", cancel, { once: true });
494
+ if (signal.aborted) cancel();
495
+ } } : {}
496
+ });
497
+ signal?.throwIfAborted();
498
+ return result;
499
+ } finally {
500
+ if (cancel) signal?.removeEventListener("abort", cancel);
501
+ }
412
502
  }
413
503
  //#endregion
414
504
  //#region src/diagnostics/error-symbolication.ts