stim 1.23.1 → 1.25.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 (174) hide show
  1. package/README.md +3 -2
  2. package/dist/{acquire-artifact-BzYRDgaP.mjs → acquire-artifact-zA4S7RHE.mjs} +2 -2
  3. package/dist/{act-vxiMwdf5.mjs → act-BbHS3oV8.mjs} +41 -26
  4. package/dist/{activity-BpWUPgUm.mjs → activity-BpjwrQXU.mjs} +6 -6
  5. package/dist/{agent-device-usage-output-CUlLsbRt.mjs → agent-device-usage-output-Bnkerfod.mjs} +5 -5
  6. package/dist/{android-DtfRGLcc.mjs → android-BGwuK3Mc.mjs} +75 -50
  7. package/dist/{android-CLi6DSiS.mjs → android-CNZgRC-4.mjs} +5 -5
  8. package/dist/{android-C7sVmyI9.mjs → android-Cjcj8MCw.mjs} +140 -46
  9. package/dist/{android-cas-ngferVq2.mjs → android-cas-BVqh2Zep.mjs} +3 -3
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/{android-project-DVWyCbWU.d.mts → android-project-CTYaETc0.d.mts} +6 -2
  12. package/dist/{android-DR5lZ2Az.mjs → android-saBeB4lr.mjs} +13 -3
  13. package/dist/api.d.mts +22 -5
  14. package/dist/api.mjs +32 -31
  15. package/dist/{artifact-Xvgibgzq.mjs → artifact-Co8zixVx.mjs} +19 -17
  16. package/dist/{artifact-DBI3DALs.mjs → artifact-DN8JNwqS.mjs} +18 -17
  17. package/dist/{artifact-platform-CXcmX_j3.mjs → artifact-platform-CMRc0M_r.mjs} +3 -3
  18. package/dist/{browser-web-BJN9ZHxB.mjs → browser-web-CCgZsHmI.mjs} +16 -17
  19. package/dist/{budget-3ivAK99e.mjs → budget-HyShrIpL.mjs} +149 -47
  20. package/dist/{build-Dv9s8Fz-.mjs → build-CAiw8Ezm.mjs} +33 -29
  21. package/dist/{build-cache-Dv7RN200.mjs → build-cache-CKCzxzxA.mjs} +172 -21
  22. package/dist/{build-plan-BmbdHQbr.mjs → build-plan-zCuHGlA8.mjs} +8 -7
  23. package/dist/{cache-manifest-DSeQjt-Q.mjs → cache-manifest-BPXRONJz.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-CH2EWGPB.mjs → ccache-h1FKhZeg.mjs} +6 -6
  26. package/dist/{cdp-3fwICjzi.mjs → cdp-BG3FJCCx.mjs} +1 -1
  27. package/dist/{chrome-Bbw689-6.mjs → chrome-BvV8ssI3.mjs} +1 -1
  28. package/dist/{cli-BkK6Wr5i.mjs → cli-C4w607Pz.mjs} +20 -20
  29. package/dist/cli.mjs +1 -1
  30. package/dist/{client-B4MMzfo_.mjs → client-BQsmyp_-.mjs} +274 -39
  31. package/dist/collector-run.mjs +6 -6
  32. package/dist/{command-output-YKGWivpG.mjs → command-output-BBvS1H6v.mjs} +3 -2
  33. package/dist/{config-DlrsduwG.mjs → config-BZhXY15H.mjs} +3 -3
  34. package/dist/{created-devices-x9rN6bhs.mjs → created-devices-D2Aca-xu.mjs} +6 -2
  35. package/dist/{dependency-state-1I9KZT1Y.mjs → dependency-state-BwNCYG5Q.mjs} +2 -2
  36. package/dist/{detached-entry-BwNEtIrP.mjs → detached-entry-KmieOKgN.mjs} +1 -1
  37. package/dist/{dev-client-BFxiDpkf.mjs → dev-client-CHoXXZeg.mjs} +3 -3
  38. package/dist/{device-CiNYxqp6.mjs → device-B9FqTBYW.mjs} +81 -54
  39. package/dist/{device-B7ljwccX.mjs → device-F5-4z9ef.mjs} +16 -16
  40. package/dist/{device-capacity-DH0QsZYZ.mjs → device-capacity-ZYaRALv5.mjs} +20 -16
  41. package/dist/device-host-worker.mjs +17 -17
  42. package/dist/{device-ios-CbVDtDIy.mjs → device-ios-DkHBrmvH.mjs} +32 -50
  43. package/dist/{device-lease-run-DXPSwdbb.mjs → device-lease-run-ogEeJ62K.mjs} +6 -6
  44. package/dist/{device-pool-B4iOXIrD.mjs → device-pool-BIg8MU8l.mjs} +3 -3
  45. package/dist/{doctor-DRu-8ld6.mjs → doctor-A_Nr_fDe.mjs} +1 -1
  46. package/dist/{doctor-HUC1igzw.mjs → doctor-Bm8TVpGn.mjs} +37 -31
  47. package/dist/{doctor-fingerprint-DZLoYFVb.mjs → doctor-fingerprint-zlujA1Gs.mjs} +1 -1
  48. package/dist/doctor-fingerprint.mjs +1 -1
  49. package/dist/{doctor-C6t4Maue.mjs → doctor-k3P3PizH.mjs} +14 -14
  50. package/dist/{doctor-watchman-iGBpC6KM.mjs → doctor-watchman-BovI1y3-.mjs} +5 -5
  51. package/dist/{eas-build-DMWSSvxq.mjs → eas-build-CyDKNTBP.mjs} +4 -4
  52. package/dist/{eas-fallback-vKlrqxgE.mjs → eas-fallback-gaZi-dJL.mjs} +16 -15
  53. package/dist/{eas-session-ledger-BQF9Yyy9.mjs → eas-session-ledger-BMCA1gdO.mjs} +12 -8
  54. package/dist/{error-diagnostics-DYsjJIHz.mjs → error-diagnostics-B1Mj_-7h.mjs} +17 -42
  55. package/dist/{errors-ccaPc4ox.mjs → errors-DHm_U5gv.mjs} +2 -1
  56. package/dist/{exec-DEoAhcze.mjs → exec-VFRpu1iA.mjs} +116 -28
  57. package/dist/{gc-BW8E1uSC.mjs → gc-B9jcnmIk.mjs} +205 -28
  58. package/dist/{gc-dDE4QPVu.mjs → gc-eaz403W6.mjs} +2 -2
  59. package/dist/{guide-DYYEO3Wz.mjs → guide-DR0K0xW9.mjs} +328 -89
  60. package/dist/{hosted-android-xcfgCgSF.mjs → hosted-android-Bvb2-ZxD.mjs} +4 -4
  61. package/dist/{hosted-client-Bt-tndxV.mjs → hosted-client-rsRqysJc.mjs} +4 -4
  62. package/dist/{hosted-ios-y19jCYFF.mjs → hosted-ios-RtVcJH3u.mjs} +1 -1
  63. package/dist/{hosted-logs-DzJKzKlj.mjs → hosted-logs-CWKGYWNX.mjs} +11 -6
  64. package/dist/{hosted-macos-BJusKvqL.mjs → hosted-macos-d0pv9Tth.mjs} +7 -7
  65. package/dist/{hosted-native-BmQC6U_x.mjs → hosted-native-BxTizGU2.mjs} +58 -11
  66. package/dist/{idle-shutdown-CJmUOV5x.mjs → idle-shutdown-BIyfl0Zj.mjs} +10 -10
  67. package/dist/{ios-hcBpnEGk.mjs → ios-BQzvJlzw.mjs} +122 -17
  68. package/dist/{ios-CWjqfSm_.mjs → ios-BRVM8b0P.mjs} +81 -49
  69. package/dist/{ios-DTOYZGMJ.mjs → ios-Dvt97HgQ.mjs} +8 -8
  70. package/dist/{ios-xtlRHaeB.mjs → ios-ENC4sRPA.mjs} +1 -1
  71. package/dist/{ios-device-BXZ0c7Kb.mjs → ios-device-B6HK951C.mjs} +1 -1
  72. package/dist/{ios-device-DFGuwF4U.mjs → ios-device-CKSvk0bu.mjs} +3 -3
  73. package/dist/{ios-project-CSZYI1iu.mjs → ios-project-DCUDo06I.mjs} +5 -5
  74. package/dist/{ios-signing-BtAffm0A.mjs → ios-signing-4c_qXvQm.mjs} +2 -2
  75. package/dist/{ios-state-Dtw5K2aI.mjs → ios-state-CT9nV5SP.mjs} +15 -7
  76. package/dist/{js-swap-BSBHldmm.mjs → js-swap-Z9HbC4cj.mjs} +7 -6
  77. package/dist/{launch-D-zq8SHG.mjs → launch-D0lPvFFu.mjs} +49 -30
  78. package/dist/{launch-CP2wDCVd.mjs → launch-DscF1QfM.mjs} +52 -50
  79. package/dist/{logs-pNvA2hHK.mjs → logs-BsIRre8x.mjs} +16 -9
  80. package/dist/{logs-By5aw3g9.mjs → logs-Crs9y34Z.mjs} +8 -6
  81. package/dist/{macos-CPMahOC2.mjs → macos-CcUlJPMu.mjs} +1 -1
  82. package/dist/{macos-C67FZ2ft.mjs → macos-D477nfzH.mjs} +49 -42
  83. package/dist/macos-run.mjs +1 -1
  84. package/dist/maintenance-run.mjs +7 -7
  85. package/dist/{metro-DiXtA3Ty.mjs → metro-1pJgCX4U.mjs} +4 -4
  86. package/dist/{metro-gateway-CKZqKqx7.mjs → metro-gateway-Bp9gJQAN.mjs} +3 -4
  87. package/dist/{named-ports-DkEzOfzO.mjs → named-ports-BVbn8SvC.mjs} +3 -3
  88. package/dist/{native-android-_MWSs3PP.mjs → native-android-BvMizJn1.mjs} +17 -17
  89. package/dist/{native-gradle-artifact-inputs-DHFnmrVf.mjs → native-gradle-artifact-inputs-BJscK4vN.mjs} +5 -5
  90. package/dist/{native-run-Dv88i0aU.mjs → native-run-D5OJsGwA.mjs} +6 -6
  91. package/dist/{native-runtime-DBRfY_PN.mjs → native-runtime-B9w_Qyz3.mjs} +10 -9
  92. package/dist/{native-source-Y0yLhFyQ.mjs → native-source-D-4Dh4JU.mjs} +7 -4
  93. package/dist/{native-xcode-inputs-CqViUh3r.mjs → native-xcode-inputs-Cv4l-obn.mjs} +2 -2
  94. package/dist/{native-xcode-ios-vFgqL_yS.mjs → native-xcode-ios-DGrg90hE.mjs} +21 -20
  95. package/dist/offload-worker.d.mts +12 -4
  96. package/dist/offload-worker.mjs +78 -43
  97. package/dist/{operation-exec-BW0em61G.mjs → operation-exec-CUZifp6Z.mjs} +2 -25
  98. package/dist/{ownership-C5fo5Edb.mjs → ownership-jxxz-19m.mjs} +3 -3
  99. package/dist/{page-DBL2PiUU.mjs → page-CzEA_-5_.mjs} +2 -3
  100. package/dist/phone-reverses-CYb7RRAx.mjs +57 -0
  101. package/dist/{placement-log-BnGgJRRZ.mjs → placement-log-DjOXJRIH.mjs} +1 -1
  102. package/dist/{plan-placement-cr0fEU7b.mjs → plan-placement-BqKgKHCi.mjs} +3 -3
  103. package/dist/{ports-DpXjKkSV.mjs → ports-DtS1Amb0.mjs} +3 -3
  104. package/dist/{prebuild-BligW0QS.mjs → prebuild-JUaqOLpc.mjs} +14 -9
  105. package/dist/{project-DhCtQWWU.mjs → project-BiC68mIp.mjs} +21 -17
  106. package/dist/{pull-request-W1IuLXDt.mjs → pull-request-CbNlkFok.mjs} +2 -2
  107. package/dist/pull-requests.mjs +1 -1
  108. package/dist/{react-native-android-ZlhQfhvq.mjs → react-native-android-DRYqoJc4.mjs} +76 -32
  109. package/dist/{react-native-build-CelbTO_y.mjs → react-native-build-CwZB-agu.mjs} +23 -20
  110. package/dist/{react-native-doctor-LTIaP7lv.mjs → react-native-doctor-BCrytK7h.mjs} +10 -9
  111. package/dist/{react-native-ios-C5W0SA6f.mjs → react-native-ios-Cr1buNFo.mjs} +41 -24
  112. package/dist/{recordings-CQmfzAh7.mjs → recordings-BaoQ0t-J.mjs} +1 -1
  113. package/dist/{registration-BcRgF6Ox.mjs → registration-CN6nlhcD.mjs} +1 -1
  114. package/dist/{reload-QcwnYLYV.mjs → reload-Beftw2X3.mjs} +1 -1
  115. package/dist/{reload-COJWTbae.mjs → reload-FbSgMF8x.mjs} +144 -42
  116. package/dist/{remote-DR8qUERM.mjs → remote-BuZj6AyU.mjs} +16 -7
  117. package/dist/{result-utnBea7x.mjs → result-CR2vk2cj.mjs} +41 -18
  118. package/dist/{run-DidHghD1.mjs → run-BtzE09Dl.mjs} +2 -2
  119. package/dist/{selection-DSMbWEX2.mjs → selection-D5cxEl3t.mjs} +13 -7
  120. package/dist/{server-bare-CafzuyFB.mjs → server-bare-CH9X0RLn.mjs} +56 -4
  121. package/dist/{server-command-B9o92sLM.mjs → server-command-CaBbDNU2.mjs} +5 -5
  122. package/dist/server-expo-C16Zf2k7.mjs +2 -0
  123. package/dist/{server-expo-BXrWxNYh.mjs → server-expo-Ck8EIidM.mjs} +14 -9
  124. package/dist/{settings-C7O8A6ZI.mjs → settings-B5tCoq9N.mjs} +132 -39
  125. package/dist/{settings-PfJx8uK1.mjs → settings-DzH9mGQZ.mjs} +1 -1
  126. package/dist/{settings-write-Chuy7Cte.mjs → settings-write-n0zwfohx.mjs} +7 -7
  127. package/dist/settings.schema.json +51 -0
  128. package/dist/{simslim-BNckWpXi.mjs → simslim-BjxszUAb.mjs} +22 -7
  129. package/dist/{slot-launch-B7AuoWJv.mjs → slot-launch-QeuJMlnJ.mjs} +6 -6
  130. package/dist/{stage-C4u17aES.mjs → stage-D8xlRU2D.mjs} +2 -3
  131. package/dist/{start-BL_BsiWt.mjs → start-C1JLjkNw.mjs} +1 -1
  132. package/dist/{start-CU8mCPC7.mjs → start-YMpNwLhh.mjs} +75 -35
  133. package/dist/{state--smjFSTL.mjs → state-DMRNP7-4.mjs} +4 -4
  134. package/dist/{state-08I3hw3_.mjs → state-DPaM3u5K.mjs} +2 -2
  135. package/dist/{stats-CO6sK0Nh.mjs → stats-CP7STzZw.mjs} +5 -5
  136. package/dist/{stats-report-BzaPrRm6.mjs → stats-report-n2U5plhk.mjs} +1 -1
  137. package/dist/{status-_WPHzVft.mjs → status-CRLiJ-O_.mjs} +24 -24
  138. package/dist/{status-BRROykC8.mjs → status-Fect2w9R.mjs} +1 -1
  139. package/dist/{status-CrJutl6-.mjs → status-cNw6i0_t.mjs} +1 -1
  140. package/dist/{status-watch-BHFasOZN.mjs → status-watch-Bc2J4TZn.mjs} +5 -5
  141. package/dist/status-worker.mjs +1 -1
  142. package/dist/stim-clonefile.c +18 -0
  143. package/dist/{stim-desktop-D5OGpYZM.mjs → stim-desktop-DS0mzR8U.mjs} +2 -2
  144. package/dist/{stop-iuFHjUST.mjs → stop-Br7LKxBE.mjs} +2 -2
  145. package/dist/{stop-CR5689oB.mjs → stop-COP6PQqw.mjs} +5 -5
  146. package/dist/{stop-BJ06ipTZ.mjs → stop-Db9Kh-UA.mjs} +109 -56
  147. package/dist/supervisor-run.mjs +17 -17
  148. package/dist/{support-CbXPbUMJ.mjs → support-Cxj9CmII.mjs} +6 -6
  149. package/dist/{support-TWuQlHQo.mjs → support-qKcbgmI5.mjs} +14 -11
  150. package/dist/{swiftpm-artifact-inputs-DFcGsXDP.mjs → swiftpm-artifact-inputs-iY9fsmOc.mjs} +4 -4
  151. package/dist/{swiftpm-macos-DbwGCpZg.mjs → swiftpm-macos-Bp_sn9P4.mjs} +15 -14
  152. package/dist/{toolchain-XkA2PfJZ.mjs → toolchain-DB1aeqxO.mjs} +1 -1
  153. package/dist/{toolchain-B9hCFCQw.mjs → toolchain-VzLJzZ7O.mjs} +69 -37
  154. package/dist/trigger-BLsHgAGR.mjs +2 -0
  155. package/dist/{trigger-Cbyc41d_.mjs → trigger-CBMe2YLH.mjs} +2 -2
  156. package/dist/{warm-progress-CA3TgT3-.mjs → warm-progress-BV3ZPmcY.mjs} +6 -6
  157. package/dist/{web-DRF_oFXk.mjs → web-B4Yjyt1G.mjs} +12 -10
  158. package/dist/web-DS4UDWvf.mjs +2 -0
  159. package/dist/web-run.mjs +8 -9
  160. package/dist/windows-report.mjs +12 -1
  161. package/dist/windows-report.ps1 +1 -1
  162. package/dist/{workspace-state-U08dEzhG.mjs → workspace-state-CPSp3mav.mjs} +11 -4
  163. package/dist/{workspaces-e41xsjKr.mjs → workspaces-C9w4aeXF.mjs} +36 -32
  164. package/dist/{worktree-B4Nj3EGS.mjs → worktree-CclFIe1Z.mjs} +324 -99
  165. package/dist/{worktree-BEwxVwKF.mjs → worktree-Ct9Gk3KL.mjs} +1 -1
  166. package/dist/{xcode-Rq744mBF.mjs → xcode-CiIIDnuD.mjs} +42 -28
  167. package/package.json +7 -7
  168. package/shim/bundle-response.cjs +53 -1
  169. package/shim/bundle-response.d.cts +1 -1
  170. package/shim/expo-metro-config.cjs +23 -1
  171. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +0 -211
  172. package/dist/server-expo-Ddr8cG_c.mjs +0 -2
  173. package/dist/trigger-yb_nFzPF.mjs +0 -2
  174. package/dist/web-kDE9Myoy.mjs +0 -2
@@ -1,10 +1,10 @@
1
- import { c as declareSpawnsOn, f as stopDeclaringSpawnsOn, g as process_identity_exports, r as WorkspaceProcessCleanupError, t as getExecutor, x as ownership_claim_exports } from "./exec-DEoAhcze.mjs";
2
- import { C as saveConfig, D as withConfigLock$1, G as projectDeviceSlots, H as deviceSlotPlatforms, K as removeSlotDevice, O as withConfigLockAsync$1, _ as loadConfig$1, c as ensureConfig, d as getConfigDir, f as getConfigPath$1, z as assignSlotDevice } from "./config-DlrsduwG.mjs";
3
- import { n as runOperationFileQuiet, t as runOperationFile, u as cancellableSleep } from "./operation-exec-BW0em61G.mjs";
4
- import { c as androidDataPartitionSizeBytes } from "./settings-C7O8A6ZI.mjs";
5
- import { c as pidExists, p as signalProcessTreeAsync } from "./metro-DiXtA3Ty.mjs";
6
- import { i as recordCreatedDevice, r as readCreatedDevices$1, t as forgetCreatedDevice } from "./created-devices-x9rN6bhs.mjs";
7
- import { i as stimDesktopInstalledAsync, n as settingDefault, t as STIM_DESKTOP_OPEN_OPTIONS } from "./stim-desktop-D5OGpYZM.mjs";
1
+ import { D as ownership_claim_exports, S as process_identity_exports, l as WorkspaceProcessCleanupError, m as declareSpawnsOn, o as cancellableSleep, t as getExecutor, v as stopDeclaringSpawnsOn } from "./exec-VFRpu1iA.mjs";
2
+ import { C as saveConfig, D as withConfigLock$1, G as projectDeviceSlots, H as deviceSlotPlatforms, K as removeSlotDevice, O as withConfigLockAsync$1, _ as loadConfig$1, c as ensureConfig, d as getConfigDir, f as getConfigPath$1, z as assignSlotDevice } from "./config-BZhXY15H.mjs";
3
+ import { n as runOperationFileQuiet, t as runOperationFile } from "./operation-exec-CUZifp6Z.mjs";
4
+ import { c as androidDataPartitionSizeBytes } from "./settings-B5tCoq9N.mjs";
5
+ import { i as stimDesktopInstalledAsync, n as settingDefault, t as STIM_DESKTOP_OPEN_OPTIONS } from "./stim-desktop-DS0mzR8U.mjs";
6
+ import { a as recordCreatedDeviceAsync, n as forgetCreatedDeviceAsync, r as readCreatedDevices$1 } from "./created-devices-D2Aca-xu.mjs";
7
+ import { c as pidExists, p as signalProcessTreeAsync } from "./metro-1pJgCX4U.mjs";
8
8
  import { isDeepStrictEqual } from "node:util";
9
9
  import { join } from "node:path";
10
10
  import { ambientEnv, ambientWrite } from "@stim-cli/core";
@@ -13,6 +13,27 @@ import { dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, resol
13
13
  import { existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
14
14
  import { rm } from "node:fs/promises";
15
15
  import { homedir, tmpdir } from "os";
16
+ //#region src/devices/android-emulator-viewer.ts
17
+ async function configuredAndroidEmulatorApp(platform = process.platform, env) {
18
+ let value = loadConfig$1()?.androidEmulatorApp;
19
+ if (value === void 0) {
20
+ const installed = await stimDesktopInstalledAsync(platform, env);
21
+ value = settingDefault(settingDefinition("androidEmulatorApp"), () => installed).value;
22
+ }
23
+ if (ANDROID_EMULATOR_APPS.includes(value)) return value;
24
+ const error = /* @__PURE__ */ new Error("Invalid androidEmulatorApp in machine config. Use \"emulator\" or \"stim-desktop\".");
25
+ Object.assign(error, { code: "STIM_BAD_ARG" });
26
+ throw error;
27
+ }
28
+ async function openEmulatorInStimDesktop(serial) {
29
+ await getExecutor().runFileQuietAsync("open", [
30
+ "-g",
31
+ "-a",
32
+ "Stim",
33
+ `stim-desktop://open?serial=${serial}`
34
+ ], STIM_DESKTOP_OPEN_OPTIONS);
35
+ }
36
+ //#endregion
16
37
  //#region src/devices/sim-pool.ts
17
38
  const POOL_SETTING_REMEDY = "Run `stim guide settings` for the device pool bounds and where it can be set.";
18
39
  function parkedMaxSetting(platform, options = {}) {
@@ -89,11 +110,11 @@ function parkSim({ platform, projectPath, slot = "default", record, max }) {
89
110
  return evicted;
90
111
  });
91
112
  }
92
- function adoptParked({ platform, projectPath, slot = "default", udid, device }) {
113
+ async function adoptParked({ platform, projectPath, slot = "default", udid, device }) {
93
114
  const claim = claimParkedOperation(platform, udid);
94
115
  if (!claim) return null;
95
116
  try {
96
- return withConfigLock$1(() => {
117
+ return await withConfigLockAsync$1(() => {
97
118
  const cfg = ensureConfig();
98
119
  const records = readParked(platform, { config: cfg });
99
120
  const taken = records.find((r) => r.udid === udid);
@@ -243,27 +264,6 @@ function isStimOwnedAvd(name) {
243
264
  return name.startsWith("stim-") && isStimOwnedDevice("android", name);
244
265
  }
245
266
  //#endregion
246
- //#region src/devices/android-emulator-viewer.ts
247
- async function configuredAndroidEmulatorApp(platform = process.platform, env) {
248
- let value = loadConfig$1()?.androidEmulatorApp;
249
- if (value === void 0) {
250
- const installed = await stimDesktopInstalledAsync(platform, env);
251
- value = settingDefault(settingDefinition("androidEmulatorApp"), () => installed).value;
252
- }
253
- if (ANDROID_EMULATOR_APPS.includes(value)) return value;
254
- const error = /* @__PURE__ */ new Error("Invalid androidEmulatorApp in machine config. Use \"emulator\" or \"stim-desktop\".");
255
- Object.assign(error, { code: "STIM_BAD_ARG" });
256
- throw error;
257
- }
258
- async function openEmulatorInStimDesktop(serial) {
259
- await getExecutor().runFileQuietAsync("open", [
260
- "-g",
261
- "-a",
262
- "Stim",
263
- `stim-desktop://open?serial=${serial}`
264
- ], STIM_DESKTOP_OPEN_OPTIONS);
265
- }
266
- //#endregion
267
267
  //#region src/devices/android.ts
268
268
  const ANDROID_ABIS = /* @__PURE__ */ new Set([
269
269
  "armeabi-v7a",
@@ -410,7 +410,7 @@ async function createOwnedAvd(label, { systemImage, deviceProfile = DEFAULT_AVD_
410
410
  throw new Error(`No ${arch} Android system image is installed. Install one, e.g.: sdkmanager "system-images;android-36;google_apis;${arch}"`);
411
411
  }
412
412
  const avdName = ownedAvdName(label);
413
- recordCreatedDevice("android", avdName);
413
+ await recordCreatedDeviceAsync("android", avdName);
414
414
  const tool = androidToolPath("avdmanager");
415
415
  const args = [
416
416
  "create",
@@ -542,7 +542,7 @@ async function deleteAvd(avdName, operation) {
542
542
  cwd: operation?.cwd,
543
543
  ...root ? { env: { ANDROID_AVD_HOME: root } } : {}
544
544
  });
545
- forgetCreatedDevice("android", avdName);
545
+ await forgetCreatedDeviceAsync("android", avdName);
546
546
  }
547
547
  function parseAvdList(text) {
548
548
  return text.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("INFO") && !l.startsWith("WARNING"));
@@ -964,7 +964,10 @@ async function resetAdoptedAvd(avdName, serial, keepPackage) {
964
964
  let unavailableTarget = false;
965
965
  const commandTimeout = (timeoutMs) => recoveryDeadline === void 0 ? timeoutMs : Math.max(1, Math.min(timeoutMs, recoveryDeadline - Date.now()));
966
966
  const assertTarget = async () => {
967
- const resolved = await resolveOwnedAvdSerialAsync(avdName, { timeoutMs: commandTimeout(3e4) });
967
+ const resolved = await resolveOwnedAvdSerialAsync(avdName, {
968
+ timeoutMs: commandTimeout(3e4),
969
+ preferredSerial: serial
970
+ });
968
971
  unavailableTarget = Boolean(resolved.notRunning);
969
972
  if (resolved.serial !== serial) throw new Error(`AVD ${avdName} is no longer running on ${serial}.`);
970
973
  };
@@ -1283,6 +1286,44 @@ async function shutdownAndroidEmulator(serial, timeoutMs = ANDROID_EMULATOR_SHUT
1283
1286
  "kill"
1284
1287
  ], Math.max(1, timeoutMs - (Date.now() - started)));
1285
1288
  }
1289
+ function reverseDevicePortsTo(listing, hostPorts) {
1290
+ return String(listing ?? "").split("\n").flatMap((line) => {
1291
+ const [, device, host] = line.trim().split(/\s+/);
1292
+ return device?.startsWith("tcp:") && hostPorts.some((port) => host === `tcp:${port}`) ? [device] : [];
1293
+ });
1294
+ }
1295
+ /**
1296
+ * Removes the reverses that point an owned emulator at `metroPort`, verified by the emulator's own
1297
+ * console. The adb server connects a reverse stream from the device to the host port synchronously
1298
+ * on its single event thread (packages/modules/adb services.cpp `service_to_fd`), and on Windows a
1299
+ * refused loopback connect takes seconds, so an app retrying a stopped Metro stalls every adb call.
1300
+ * https://github.com/appandflow/stim/issues/4101
1301
+ */
1302
+ async function removeOwnedEmulatorMetroReverses(avdName, serial, metroPort, operation) {
1303
+ if (await getAvdNameForSerialAsync(serial, { operation }) !== avdName) return;
1304
+ await removeMetroReverses(serial, [metroPort], operation);
1305
+ }
1306
+ async function removeMetroReverses(serial, hostPorts, operation) {
1307
+ const adb = androidToolPath("adb", process.platform, operation?.env);
1308
+ const options = {
1309
+ timeoutMs: ADB_PROP_TIMEOUT_MS,
1310
+ killSignal: "SIGKILL",
1311
+ cwd: androidToolCwd() ?? operation?.cwd
1312
+ };
1313
+ const listing = await runOperationFileQuiet(operation, getExecutor(), adb, [
1314
+ "-s",
1315
+ serial,
1316
+ "reverse",
1317
+ "--list"
1318
+ ], options);
1319
+ for (const devicePort of reverseDevicePortsTo(listing, hostPorts)) await runOperationFileQuiet(operation, getExecutor(), adb, [
1320
+ "-s",
1321
+ serial,
1322
+ "reverse",
1323
+ "--remove",
1324
+ devicePort
1325
+ ], options);
1326
+ }
1286
1327
  function avdProcessLockPaths(avdDirectory, platform) {
1287
1328
  return ["hardware-qemu.ini.lock", "userdata-qemu.img.lock"].map((name) => join$1(avdDirectory, name, ...platform === "win32" ? ["pid"] : []));
1288
1329
  }
@@ -1557,11 +1598,20 @@ async function getAvdNameForSerialAsync(serial, { timeoutMs = EMU_AVD_NAME_TIMEO
1557
1598
  if (!out) return null;
1558
1599
  return out.split("\n")[0]?.trim() || null;
1559
1600
  }
1560
- /** `resolveOwnedAvdSerial` without blocking the event loop, with the same reads and the same timeout budget. */
1601
+ /**
1602
+ * `resolveOwnedAvdSerial` without blocking the event loop, with the same reads and the same timeout budget.
1603
+ * `preferredSerial` is the serial this workspace recorded for the AVD: it is read first, and the other
1604
+ * emulators are read only when it does not run the AVD.
1605
+ */
1561
1606
  async function resolveOwnedAvdSerialAsync(avdName, opts = {}) {
1562
- return ownedAvdSerialResolverAsync(opts)(avdName);
1607
+ return ownedAvdSerialResolverAsync(opts)(avdName, opts.preferredSerial);
1563
1608
  }
1564
- /** Shares bounded asynchronous AVD, adb and emulator-name reads across the requested AVDs. */
1609
+ /**
1610
+ * Shares bounded asynchronous AVD, adb and emulator-name reads across the requested AVDs. Emulators are
1611
+ * read concurrently within each tier (the preferred serial, then healthy ones, then unhealthy ones), and
1612
+ * the reads still pending are cancelled once one runs the requested AVD, so a wedged foreign emulator
1613
+ * neither adds up across serials nor delays the match.
1614
+ */
1565
1615
  function ownedAvdSerialResolverAsync({ timeoutMs, signal, operation } = {}) {
1566
1616
  const started = Date.now();
1567
1617
  const remaining = () => ({
@@ -1571,23 +1621,67 @@ function ownedAvdSerialResolverAsync({ timeoutMs, signal, operation } = {}) {
1571
1621
  });
1572
1622
  const avds = once(() => listAvdsAsync(remaining()));
1573
1623
  const adb = once(() => listAdbDevicesAsync(remaining()));
1574
- const names = /* @__PURE__ */ new Map();
1624
+ const reads = /* @__PURE__ */ new Map();
1575
1625
  const avdNameOf = (serial) => {
1576
- let name = names.get(serial);
1577
- if (!name) {
1578
- name = getAvdNameForSerialAsync(serial, remaining());
1579
- names.set(serial, name);
1626
+ let read = reads.get(serial);
1627
+ if (!read) {
1628
+ const own = new AbortController();
1629
+ const options = remaining();
1630
+ const entry = {
1631
+ name: getAvdNameForSerialAsync(serial, {
1632
+ ...options,
1633
+ signal: options.signal ? AbortSignal.any([options.signal, own.signal]) : own.signal
1634
+ }),
1635
+ settled: false,
1636
+ cancel: () => {
1637
+ if (entry.settled) return;
1638
+ own.abort();
1639
+ reads.delete(serial);
1640
+ }
1641
+ };
1642
+ const settle = () => {
1643
+ entry.settled = true;
1644
+ };
1645
+ entry.name.then(settle, settle);
1646
+ reads.set(serial, entry);
1647
+ read = entry;
1580
1648
  }
1581
- return name;
1649
+ return read;
1582
1650
  };
1583
- return async (avdName) => {
1651
+ const firstRunning = async (serials, avdName) => {
1652
+ try {
1653
+ return await new Promise((settle, reject) => {
1654
+ let pending = serials.length;
1655
+ if (pending === 0) return settle(void 0);
1656
+ for (const serial of serials) avdNameOf(serial).name.then((name) => {
1657
+ if (name === avdName) settle(serial);
1658
+ else if (--pending === 0) settle(void 0);
1659
+ return name;
1660
+ }, reject);
1661
+ });
1662
+ } finally {
1663
+ for (const serial of serials) reads.get(serial)?.cancel();
1664
+ }
1665
+ };
1666
+ return async (avdName, preferredSerial) => {
1584
1667
  signal?.throwIfAborted();
1585
1668
  if (!(await avds()).includes(avdName)) return { missing: true };
1586
1669
  if (!isStimOwnedAvd(avdName)) return { notOwned: true };
1587
1670
  const devices = await adb();
1588
1671
  signal?.throwIfAborted();
1589
- const candidates = [...devices.emulators, ...devices.unhealthy.filter((entry) => entry.kind === "emulator" && entry.consolePort !== void 0)];
1590
- for (const candidate of candidates) if (await avdNameOf(candidate.serial) === avdName) return { serial: candidate.serial };
1672
+ const healthy = devices.emulators.map((entry) => entry.serial);
1673
+ const unhealthy = devices.unhealthy.filter((entry) => entry.kind === "emulator" && entry.consolePort !== void 0).map((entry) => entry.serial);
1674
+ const preferred = preferredSerial && [...healthy, ...unhealthy].includes(preferredSerial) ? preferredSerial : null;
1675
+ const tiers = [
1676
+ ...preferred ? [[preferred]] : [],
1677
+ healthy.filter((serial) => serial !== preferred),
1678
+ unhealthy.filter((serial) => serial !== preferred)
1679
+ ];
1680
+ for (const tier of tiers) {
1681
+ const serial = await firstRunning(tier, avdName);
1682
+ signal?.throwIfAborted();
1683
+ if (serial) return { serial };
1684
+ }
1591
1685
  return { notRunning: true };
1592
1686
  };
1593
1687
  }
@@ -1631,4 +1725,4 @@ function ownedAvdSerialResolver({ timeoutMs } = {}) {
1631
1725
  };
1632
1726
  }
1633
1727
  //#endregion
1634
- export { resetAdoptedAvd as $, listAdbDevices as A, ownedAvdDeviceProfile as B, emulatorDiskSpaceRemedy as C, getAvdNameForSerial as D, findBuildTool as E, listAvdsAsync as F, ownedAvdSerialResolverAsync as G, ownedAvdMatchesConfiguration as H, listInstalledSystemImages as I, parseAvdSystemImage as J, ownedAvdSystemImage as K, listOrphanedAvdDirectories as L, listAvdDeviceProfiles as M, listAvdDeviceProfilesAsync as N, getAvdNameForSerialAsync as O, listAvds as P, profileNeedsFoldFeature as Q, memoizeEmulatorProbe as R, deleteAvd as S, extractEmulatorFailure as T, ownedAvdName as U, ownedAvdDirectory as V, ownedAvdSerialResolver as W, pickDefaultSystemImage as X, physicalDeviceModel as Y, probeEmulatorSerial as Z, avdPoolConfiguration as _, parkedMaxSetting as _t, androidDeviceAbi as a, waitForAndroidEmulatorShutdown as at, configureNewOwnedAvd as b, selectParked as bt, androidPoolNoCandidatesRefusal as c, configuredAndroidEmulatorApp as ct, androidToolPath as d, POOL_SETTING_REMEDY as dt, resolveOwnedAvdSerialAsync as et, assertOwnedAvdStopped as f, adoptParked as ft, avdPathExists as g, parkSim as gt, avdNameAbsent as h, isLegacyDeletionClaim as ht, androidDataFreeBytes as i, trimAndroidCaches as it, listAdbDevicesAsync as j, hostSystemImageArch as k, androidSystemImageAbi as l, isStimOwnedAvd as lt, avdIniPaths as m, eraseParkedAfter as mt, OWNED_AVD_CONFIG_DEFAULTS as n, shutdownAndroidEmulator as nt, androidHome as o, waitForBoot as ot, assertOwnedAvdStoppedAsync as p, dropParked as pt, parseAvdDeviceProfile as q, androidBuildToolName as r, systemImageSupportsFold as rt, androidPoolCandidates as s, wipeAvdUserData as st, DEFAULT_AVD_DEVICE_PROFILE as t, resolvePhysicalDevice as tt, androidToolCwd as u, isStimOwnedSim as ut, avdStorageRoots as v, readParked as vt, emulatorFailureRemedy as w, createOwnedAvd as x, bootAndroidEmulator as y, removeParkedAfter as yt, nextConsolePort as z };
1728
+ export { removeMetroReverses as $, listAdbDevices as A, ownedAvdDeviceProfile as B, emulatorDiskSpaceRemedy as C, getAvdNameForSerial as D, findBuildTool as E, listAvdsAsync as F, ownedAvdSerialResolverAsync as G, ownedAvdMatchesConfiguration as H, listInstalledSystemImages as I, parseAvdSystemImage as J, ownedAvdSystemImage as K, listOrphanedAvdDirectories as L, listAvdDeviceProfiles as M, listAvdDeviceProfilesAsync as N, getAvdNameForSerialAsync as O, listAvds as P, profileNeedsFoldFeature as Q, memoizeEmulatorProbe as R, deleteAvd as S, configuredAndroidEmulatorApp as St, extractEmulatorFailure as T, ownedAvdName as U, ownedAvdDirectory as V, ownedAvdSerialResolver as W, pickDefaultSystemImage as X, physicalDeviceModel as Y, probeEmulatorSerial as Z, avdPoolConfiguration as _, parkSim as _t, androidDeviceAbi as a, systemImageSupportsFold as at, configureNewOwnedAvd as b, removeParkedAfter as bt, androidPoolNoCandidatesRefusal as c, waitForBoot as ct, androidToolPath as d, isStimOwnedSim as dt, removeOwnedEmulatorMetroReverses as et, assertOwnedAvdStopped as f, POOL_SETTING_REMEDY as ft, avdPathExists as g, isLegacyDeletionClaim as gt, avdNameAbsent as h, eraseParkedAfter as ht, androidDataFreeBytes as i, shutdownAndroidEmulator as it, listAdbDevicesAsync as j, hostSystemImageArch as k, androidSystemImageAbi as l, wipeAvdUserData as lt, avdIniPaths as m, dropParked as mt, OWNED_AVD_CONFIG_DEFAULTS as n, resolveOwnedAvdSerialAsync as nt, androidHome as o, trimAndroidCaches as ot, assertOwnedAvdStoppedAsync as p, adoptParked as pt, parseAvdDeviceProfile as q, androidBuildToolName as r, resolvePhysicalDevice as rt, androidPoolCandidates as s, waitForAndroidEmulatorShutdown as st, DEFAULT_AVD_DEVICE_PROFILE as t, resetAdoptedAvd as tt, androidToolCwd as u, isStimOwnedAvd as ut, avdStorageRoots as v, parkedMaxSetting as vt, emulatorFailureRemedy as w, createOwnedAvd as x, selectParked as xt, bootAndroidEmulator as y, readParked as yt, nextConsolePort as z };
@@ -1,7 +1,7 @@
1
1
  import { n as ensureWorkspaceStorage, v as withDirLock$1 } from "./paths-DQtTgsBf.mjs";
2
- import { d as getConfigDir } from "./config-DlrsduwG.mjs";
3
- import { m as defaultAndroidLayout } from "./settings-C7O8A6ZI.mjs";
4
- import { r as register } from "./cache-manifest-DSeQjt-Q.mjs";
2
+ import { d as getConfigDir } from "./config-BZhXY15H.mjs";
3
+ import { m as defaultAndroidLayout } from "./settings-B5tCoq9N.mjs";
4
+ import { r as register } from "./cache-manifest-BPXRONJz.mjs";
5
5
  import { createHash, randomUUID } from "node:crypto";
6
6
  import { accessSync, constants, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, writeFileSync } from "node:fs";
7
7
  import { join } from "node:path";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
5
5
  import { join } from "node:path";
@@ -221,15 +221,19 @@ interface AndroidBuildPlan {
221
221
  //#region src/offload/toolchain.d.ts
222
222
  /** What must be identical on this Mac and a remote Mac for an iOS simulator build to come out the same. */
223
223
  interface IosToolchain {
224
- /** A digest of Stim's built code, so both sides prove they run the same Stim. */
224
+ /** A digest of Stim's built code, compared only with a remote machine that reports no `compat`. */
225
225
  stimBuild: string | null;
226
+ /** The Stim build compatibility version both sides must share. */
227
+ compat: number;
226
228
  arch: string;
227
229
  xcode: string | null;
228
230
  simulatorSdk: string | null;
229
231
  cocoapods: string | null;
230
232
  }
231
233
  /** A remote machine's toolchain, the simulator runtimes it can build for, and its JDK and Android SDK packages. */
232
- interface WorkerToolchain extends IosToolchain {
234
+ interface WorkerToolchain extends Omit<IosToolchain, "compat"> {
235
+ /** Absent from a stim-server older than build compatibility versions. */
236
+ compat?: number;
233
237
  /** The OS stim-server runs on, as Node names it; absent from a stim-server older than this field. */
234
238
  os?: string;
235
239
  macosSdk: string | null;
@@ -1,5 +1,5 @@
1
- import { t as getExecutor } from "./exec-DEoAhcze.mjs";
2
- import { u as androidToolCwd } from "./android-C7sVmyI9.mjs";
1
+ import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { u as androidToolCwd } from "./android-Cjcj8MCw.mjs";
3
3
  //#region src/collector/android.ts
4
4
  const LEVEL_BY_LETTER = {
5
5
  V: "debug",
@@ -90,6 +90,16 @@ function parseLogcatLine(line, { now = Date.now, clockOffsetMs = null } = {}) {
90
90
  proc: `${tag.trim()}(${pid})`
91
91
  };
92
92
  }
93
+ const isAndroidCrashText = (text) => /FATAL EXCEPTION:|signal \d+ \(/.test(text);
94
+ function androidLogGroups(entries) {
95
+ const groups = [];
96
+ for (const entry of entries) {
97
+ const last = groups.at(-1);
98
+ if (!last || entry.proc !== last.at(-1)?.proc || /^\s*(?:FATAL EXCEPTION:|\*\*\* \*\*\*)/.test(entry.msg ?? "")) groups.push([entry]);
99
+ else last.push(entry);
100
+ }
101
+ return groups;
102
+ }
93
103
  function logcatArgs(serial, pid) {
94
104
  return [
95
105
  "-s",
@@ -214,4 +224,4 @@ function watchAppPid({ serial, packageName, pid, intervalMs = null, exec = null,
214
224
  };
215
225
  }
216
226
  //#endregion
217
- export { waitForAppPid as a, startAndroidLogcat as i, parseLogcatLine as n, watchAppPid as o, parsePidof as r, androidClockOffset as t };
227
+ export { parsePidof as a, watchAppPid as c, parseLogcatLine as i, androidLogGroups as n, startAndroidLogcat as o, isAndroidCrashText as r, waitForAppPid as s, androidClockOffset as t };
package/dist/api.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as IosFacts, a as BuildMachinesInspection, d as DoctorPlatform, f as Finding, g as CompilationCacheActivity, h as CcacheActivity, m as AndroidFacts, n as WebLaunched, o as GeneratedTickets, s as TailnetMachineIo, u as BudgetReport } from "./android-project-DVWyCbWU.mjs";
1
+ import { _ as IosFacts, a as BuildMachinesInspection, d as DoctorPlatform, f as Finding, g as CompilationCacheActivity, h as CcacheActivity, m as AndroidFacts, n as WebLaunched, o as GeneratedTickets, s as TailnetMachineIo, u as BudgetReport } from "./android-project-CTYaETc0.mjs";
2
2
  import { a as WorkspaceLaunchPlatform } from "./ios-CDvlmUs7.mjs";
3
3
  import "./exec-DnYc4HGH.mjs";
4
4
  import "./pull-request-eODyIqZF.mjs";
@@ -19,7 +19,7 @@ interface ReleasedLease {
19
19
  }
20
20
  //#endregion
21
21
  //#region src/commands/gc/results.d.ts
22
- type GcResultKind = "archive" | "device" | "parkedDevice" | "parkedHostedDevice" | "idleDevice" | "deviceRecord" | "workspaceOutputs" | "recording" | "workspaceDirectory" | "project" | "buildLock" | "buildSlot" | "deviceLease" | "easSession" | "worktree" | "cache" | "statusCache" | "tempLeftover" | "watchmanRoot" | "watchman" | "gradleDaemon" | "gradleVersion" | "kotlinDaemon";
22
+ type GcResultKind = "archive" | "device" | "parkedDevice" | "parkedHostedDevice" | "idleDevice" | "deviceRecord" | "workspaceOutputs" | "recording" | "workspaceDirectory" | "project" | "buildLock" | "buildSlot" | "deviceLease" | "easSession" | "worktree" | "cache" | "statusCache" | "tempLeftover" | "trash" | "watchmanRoot" | "watchman" | "gradleDaemon" | "gradleVersion" | "kotlinDaemon";
23
23
  type GcResultStatus = "done" | "kept" | "failed";
24
24
  interface GcResult {
25
25
  kind: GcResultKind;
@@ -449,7 +449,8 @@ interface OwnedDeviceDisk {
449
449
  type RecordingKeptCode = "unresolved" | "retained" | "recently-recorded";
450
450
  //#endregion
451
451
  //#region src/commands/gc/temp-leftovers.d.ts
452
- type TempLeftoverKind = "stim" | "xctrace" | "jest";
452
+ type TempLeftoverKind = "stim" | "xctrace" | "swiftpm" | "jest";
453
+ type DeletableKind = Exclude<TempLeftoverKind, "jest">;
453
454
  interface TempLeftover {
454
455
  kind: TempLeftoverKind;
455
456
  path: string;
@@ -461,7 +462,7 @@ interface TempLeftoverReport {
461
462
  root: string;
462
463
  entries: TempLeftover[];
463
464
  /** Judges an entry again right before deletion (a Stim directory after its rename to `staged`), so a claim or recording use since the scan keeps it. */
464
- recheck?: (staged: string, original: string, kind: "stim" | "xctrace") => Promise<string | null>;
465
+ recheck?: (staged: string, original: string, kind: DeletableKind) => Promise<string | null>;
465
466
  }
466
467
  interface TempLeftoverGroup {
467
468
  kind: TempLeftoverKind;
@@ -480,6 +481,20 @@ declare function tempLeftoverSection(report: TempLeftoverReport | null | undefin
480
481
  groups: TempLeftoverGroup[];
481
482
  } | null;
482
483
  //#endregion
484
+ //#region src/commands/gc/trash.d.ts
485
+ interface TrashEntry {
486
+ path: string;
487
+ worktree: string | null;
488
+ removedAt: string | null;
489
+ bytes: number | null;
490
+ willDelete: boolean;
491
+ kept: string | null;
492
+ }
493
+ interface TrashReport {
494
+ root: string;
495
+ entries: TrashEntry[];
496
+ }
497
+ //#endregion
483
498
  //#region src/commands/gc/memory.d.ts
484
499
  declare const WATCHMAN_KIND = "watchman";
485
500
  declare const GRADLE_DAEMONS_KIND = "gradle-daemons";
@@ -691,6 +706,7 @@ interface GcJsonSections {
691
706
  swiftpmCache: SwiftpmCacheUsage | null;
692
707
  machineCaches: MachineCacheReport | null;
693
708
  tempLeftovers: ReturnType<typeof tempLeftoverSection>;
709
+ trash: TrashReport | null;
694
710
  gradleVersions: GradleVersionSweep | null;
695
711
  caches: {
696
712
  name: string;
@@ -793,7 +809,8 @@ interface ReloadFacts {
793
809
  platform: ReloadPlatform;
794
810
  deviceId: string;
795
811
  deviceName: string;
796
- appId: string;
812
+ /** Null when the app was not launched by Stim: a physical device or an EAS Simulator session. */
813
+ appId: string | null;
797
814
  metroPort: number | null;
798
815
  strategy: "metro-websocket" | "metro-broadcast" | "cdp";
799
816
  targets: number | null;
package/dist/api.mjs CHANGED
@@ -1,32 +1,31 @@
1
- import { m as operationState, r as WorkspaceProcessCleanupError, v as runReport, x as ownership_claim_exports, y as trackReportResource } from "./exec-DEoAhcze.mjs";
2
- import { d as workspaceDir, m as workspaceLogsDir$1, n as ensureWorkspaceStorage, r as ensureWorkspaceStorageAsync } from "./paths-DQtTgsBf.mjs";
3
- import { E as upsertProject, p as getProject, q as validateDeviceSlot, y as refuseRelativeStimPaths } from "./config-DlrsduwG.mjs";
4
- import { l as phaseLine } from "./command-output-YKGWivpG.mjs";
5
- import { d as cancelledError, f as throwIfCancelled } from "./operation-exec-BW0em61G.mjs";
6
- import { a as recordWorkspaceUseAsync, i as recordWorkspaceUse } from "./workspace-state-U08dEzhG.mjs";
7
- import { J as resolveProjectSettingsAsync, Nt as repoRootAsync, a as SETTING_SHAPE_REMEDY, et as settingShapeErrors, it as unknownSettingKeys, p as cacheProviderSettingError } from "./settings-C7O8A6ZI.mjs";
8
- import { c as projectProblem, f as projectRegistry, i as findProjectRoot$1, r as findCommandWorkspaceAsync, t as NO_PROJECT_REFUSAL } from "./project-DhCtQWWU.mjs";
9
- import { n as macosDir } from "./state-08I3hw3_.mjs";
1
+ import { D as ownership_claim_exports, T as trackReportResource, b as operationState, c as throwIfCancelled, l as WorkspaceProcessCleanupError, s as cancelledError, w as runReport } from "./exec-VFRpu1iA.mjs";
2
+ import { d as workspaceDir, m as workspaceLogsDir$1, r as ensureWorkspaceStorageAsync } from "./paths-DQtTgsBf.mjs";
3
+ import { E as upsertProject, O as withConfigLockAsync$1, p as getProject, q as validateDeviceSlot, y as refuseRelativeStimPaths } from "./config-BZhXY15H.mjs";
4
+ import { l as phaseLine } from "./command-output-BBvS1H6v.mjs";
5
+ import { a as recordWorkspaceUseAsync } from "./workspace-state-CPSp3mav.mjs";
6
+ import { Pt as repoRootAsync, Y as resolveProjectSettingsAsync, a as SETTING_SHAPE_REMEDY, at as unknownSettingKeys, p as cacheProviderSettingError, tt as settingShapeErrors } from "./settings-B5tCoq9N.mjs";
7
+ import { c as projectProblem, f as projectRegistry, i as findProjectRoot$1, r as findCommandWorkspaceAsync, t as NO_PROJECT_REFUSAL } from "./project-BiC68mIp.mjs";
8
+ import { n as macosDir } from "./state-DPaM3u5K.mjs";
9
+ import { c as ensureHomeIdentity, s as workspaceShareURL } from "./stim-desktop-DS0mzR8U.mjs";
10
10
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
11
- import { B as recordFinishedBuild, H as tapBuildLog, V as startBuildProgress } from "./budget-3ivAK99e.mjs";
12
- import { d as runCancellationSignal, f as withNativeBuildRun } from "./native-run-Dv88i0aU.mjs";
13
- import { c as ensureHomeIdentity, s as workspaceShareURL } from "./stim-desktop-D5OGpYZM.mjs";
14
- import { s as resolveBuildPlacement } from "./selection-DSMbWEX2.mjs";
15
- import { c as stopWorkspaceNow } from "./stop-BJ06ipTZ.mjs";
16
- import { r as runReload } from "./reload-COJWTbae.mjs";
17
- import { c as startDevServer } from "./start-CU8mCPC7.mjs";
18
- import { s as recordDoctorCheck } from "./doctor-watchman-iGBpC6KM.mjs";
19
- import { a as readDoctorReport } from "./doctor-C6t4Maue.mjs";
20
- import { h as warmWorktreeTarget, m as removeWorktreeTarget } from "./worktree-B4Nj3EGS.mjs";
21
- import { i as readGcReport, n as executeGc, o as withGcMaintenanceClaim } from "./gc-BW8E1uSC.mjs";
22
- import { r as readWorkspaceLogs, t as followWorkspaceLogs } from "./logs-pNvA2hHK.mjs";
23
- import { t as readProjectStats } from "./stats-report-BzaPrRm6.mjs";
24
- import { n as buildAndroidOperation, t as buildIosOperation } from "./build-Dv9s8Fz-.mjs";
25
- import { a as readAndroidBuildPlan, i as runAndroidOperation } from "./android-DtfRGLcc.mjs";
26
- import { i as readIosBuildPlan, r as runIosOperation } from "./ios-CWjqfSm_.mjs";
27
- import { a as buildMacosBundle, i as planMacos, n as runMacos } from "./macos-C67FZ2ft.mjs";
28
- import { t as runWeb } from "./web-DRF_oFXk.mjs";
29
- import { i as SettingsRefusal, o as readSettingsContext, s as readSettingsPayload, t as mutateSetting } from "./settings-write-Chuy7Cte.mjs";
11
+ import { B as recordFinishedBuild, H as startBuildProgress, U as tapBuildLog } from "./budget-HyShrIpL.mjs";
12
+ import { d as runCancellationSignal, f as withNativeBuildRun } from "./native-run-D5OJsGwA.mjs";
13
+ import { c as resolveBuildPlacement } from "./selection-D5cxEl3t.mjs";
14
+ import { c as stopWorkspaceNow } from "./stop-Db9Kh-UA.mjs";
15
+ import { r as runReload } from "./reload-FbSgMF8x.mjs";
16
+ import { c as startDevServer } from "./start-YMpNwLhh.mjs";
17
+ import { s as recordDoctorCheck } from "./doctor-watchman-BovI1y3-.mjs";
18
+ import { a as readDoctorReport } from "./doctor-k3P3PizH.mjs";
19
+ import { h as warmWorktreeTarget, m as removeWorktreeTarget } from "./worktree-CclFIe1Z.mjs";
20
+ import { i as readGcReport, n as executeGc, o as withGcMaintenanceClaim } from "./gc-B9jcnmIk.mjs";
21
+ import { r as readWorkspaceLogs, t as followWorkspaceLogs } from "./logs-BsIRre8x.mjs";
22
+ import { t as readProjectStats } from "./stats-report-n2U5plhk.mjs";
23
+ import { n as buildAndroidOperation, t as buildIosOperation } from "./build-CAiw8Ezm.mjs";
24
+ import { a as readAndroidBuildPlan, i as runAndroidOperation } from "./android-BGwuK3Mc.mjs";
25
+ import { i as readIosBuildPlan, r as runIosOperation } from "./ios-BRVM8b0P.mjs";
26
+ import { a as buildMacosBundle, i as planMacos, n as runMacos } from "./macos-D477nfzH.mjs";
27
+ import { t as runWeb } from "./web-B4Yjyt1G.mjs";
28
+ import { i as SettingsRefusal, o as readSettingsContext, s as readSettingsPayload, t as mutateSetting } from "./settings-write-n0zwfohx.mjs";
30
29
  import { randomBytes } from "node:crypto";
31
30
  import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from "node:fs";
32
31
  import { stripVTControlCharacters } from "node:util";
@@ -54,13 +53,15 @@ async function buildMacosOperation(context, root, options) {
54
53
  const placement = resolveBuildPlacement(options.remoteBuild);
55
54
  if (placement.failure) throw Object.assign(new Error(placement.failure.message), placement.failure);
56
55
  const recipe = await (await selected.load()).prepare(context, settings);
57
- ensureWorkspaceStorage(root);
56
+ await ensureWorkspaceStorageAsync(root, context.signal);
58
57
  return withNativeBuildRun(context, root, {
59
58
  command: "build",
60
59
  platform: "macos"
61
60
  }, async (claim) => {
62
- if (!getProject(root)) upsertProject(root, {});
63
- recordWorkspaceUse(root, /* @__PURE__ */ new Date(), context.env, context.cwd);
61
+ await withConfigLockAsync$1(() => {
62
+ if (!getProject(root)) upsertProject(root, {});
63
+ });
64
+ await recordWorkspaceUseAsync(root, /* @__PURE__ */ new Date(), context.env, context.cwd, context.signal);
64
65
  const started = Date.now();
65
66
  const progress = startBuildProgress({
66
67
  root,
@@ -1,18 +1,17 @@
1
- import { h as withDrainingCancellation, x as ownership_claim_exports } from "./exec-DEoAhcze.mjs";
1
+ import { D as ownership_claim_exports, c as throwIfCancelled, x as withDrainingCancellation } from "./exec-VFRpu1iA.mjs";
2
2
  import { d as workspaceDir } from "./paths-DQtTgsBf.mjs";
3
- import { _ as stepTimer, i as formatDuration, l as phaseLine, m as shortHash } from "./command-output-YKGWivpG.mjs";
4
- import { f as throwIfCancelled } from "./operation-exec-BW0em61G.mjs";
5
- import { Hn as isEasAuthFailureText, Ln as RESOLVE_TIMEOUT_MS, Vn as easAuthNote } from "./budget-3ivAK99e.mjs";
6
- import { d as runCancellationSignal, r as cancelledFailure } from "./native-run-Dv88i0aU.mjs";
7
- import { d as prepareProviderDownloadDir, f as providerDownloadPath } from "./build-cache-Dv7RN200.mjs";
8
- import { n as CCACHE_UNAVAILABLE, r as ccacheActivityLine, t as CCACHE_NOT_RUN } from "./ccache-CH2EWGPB.mjs";
9
- import { c as offloadPlacement, i as closeOffload, l as placementLoad, n as buildPlacementCandidates, o as offloadBuild, r as chooseBuildMachine, u as remotePhaseText } from "./client-B4MMzfo_.mjs";
10
- import { a as requireLocalBuild, r as namedBuildMachine, t as OffloadRefusal } from "./selection-DSMbWEX2.mjs";
11
- import { f as formatDiagnostic } from "./react-native-build-CelbTO_y.mjs";
12
- import { l as skippedMissReason } from "./prebuild-BligW0QS.mjs";
13
- import { t as buildPlacementRecord } from "./placement-log-BnGgJRRZ.mjs";
14
- import { n as settleArtifactUploads, t as acquireArtifact } from "./acquire-artifact-BzYRDgaP.mjs";
15
- import { a as PLATFORM, h as displayPath } from "./support-CbXPbUMJ.mjs";
3
+ import { _ as stepTimer, i as formatDuration, l as phaseLine, m as shortHash } from "./command-output-BBvS1H6v.mjs";
4
+ import { Bn as RESOLVE_TIMEOUT_MS, Gn as isEasAuthFailureText, Wn as easAuthNote } from "./budget-HyShrIpL.mjs";
5
+ import { d as runCancellationSignal, r as cancelledFailure } from "./native-run-D5OJsGwA.mjs";
6
+ import { g as providerDownloadPath, h as prepareProviderDownloadDir } from "./build-cache-CKCzxzxA.mjs";
7
+ import { n as CCACHE_UNAVAILABLE, r as ccacheActivityLine, t as CCACHE_NOT_RUN } from "./ccache-h1FKhZeg.mjs";
8
+ import { c as offloadPlacement, i as closeOffload, l as placementLoad, n as buildPlacementCandidates, o as offloadBuild, r as chooseBuildMachine, u as remotePhaseText } from "./client-BQsmyp_-.mjs";
9
+ import { i as namedBuildMachine, o as requireLocalBuild, r as fingerprintMismatchRemedy, t as OffloadRefusal } from "./selection-D5cxEl3t.mjs";
10
+ import { f as formatDiagnostic } from "./react-native-build-CwZB-agu.mjs";
11
+ import { u as skippedMissReason } from "./prebuild-JUaqOLpc.mjs";
12
+ import { t as buildPlacementRecord } from "./placement-log-DjOXJRIH.mjs";
13
+ import { n as settleArtifactUploads, t as acquireArtifact } from "./acquire-artifact-zA4S7RHE.mjs";
14
+ import { a as PLATFORM, h as displayPath } from "./support-Cxj9CmII.mjs";
16
15
  import { t as AndroidRecipeRefusal } from "./android-project-BCAAmMwz.mjs";
17
16
  import { rmSync } from "node:fs";
18
17
  import { join } from "node:path";
@@ -29,7 +28,7 @@ function fail(code, message, remedy, extra = {}) {
29
28
  extra
30
29
  };
31
30
  }
32
- async function acquireAndroidArtifact({ context, root, buildLog, writer, recipe, targetOffloadRefusal, buildPlan, cacheProviderConfig, requestedBuildCache, easBuild, androidPackage: initialPackage, record, maxBuilds, progress }, { acquireLock, releaseLock, waitForBuild, easAuth, resolveRemoteBuild, uploadRemoteBuild, loadCacheProviderModule, acquireSlot, releaseSlot, now }) {
31
+ async function acquireAndroidArtifact({ context, root, buildLog, writer, recipe, targetOffloadRefusal, buildPlan, cacheProviderConfig, requestedBuildCache, easBuild, androidPackage: initialPackage, record, maxBuilds, progress }, { acquireLock, releaseLock, waitForBuild, easAuth, resolveRemoteBuild, uploadRemoteBuild, loadCacheProviderModule, storedAppId: entryAppId, acquireSlot, releaseSlot, now }) {
33
32
  const { phase, out, stats, step, miss, hit: lateHit, place, waitingOn, waitingFor } = progress;
34
33
  let fallbackMachine = null;
35
34
  let hereReason = "no remote machine is paired";
@@ -47,7 +46,7 @@ async function acquireAndroidArtifact({ context, root, buildLog, writer, recipe,
47
46
  machine: info.machine
48
47
  }
49
48
  }));
50
- if (namedBuildMachine(buildMachine)) throw new OffloadRefusal(buildMachine, reason);
49
+ if (namedBuildMachine(buildMachine)) throw new OffloadRefusal(buildMachine, reason, info.remedy);
51
50
  requireLocalBuild(buildMachine);
52
51
  record.offloadFallback = reason;
53
52
  phase("build", `${line} -> building here`);
@@ -445,6 +444,7 @@ async function acquireAndroidArtifact({ context, root, buildLog, writer, recipe,
445
444
  choice,
446
445
  expectedFingerprint: uncached ? null : storeHash,
447
446
  request: recipe.offload.request,
447
+ fingerprintInputs: recipe.offload.fingerprintInputs,
448
448
  stagingDir,
449
449
  onPhase: (name, msg) => phase(name, remotePhaseText(name, msg, choice.machine)),
450
450
  onEnter: (name) => {
@@ -505,7 +505,8 @@ async function acquireAndroidArtifact({ context, root, buildLog, writer, recipe,
505
505
  fallbackMachine = choice.machine;
506
506
  fallBack(`${choice.machine}: ${why}`, `offload failed: ${why}`, {
507
507
  code: "offload-failed",
508
- machine: choice.machine
508
+ machine: choice.machine,
509
+ remedy: outcome.ok ? void 0 : fingerprintMismatchRemedy(outcome.reason)
509
510
  });
510
511
  writer.write({
511
512
  src: "build",
@@ -790,6 +791,7 @@ async function acquireAndroidArtifact({ context, root, buildLog, writer, recipe,
790
791
  apkPath: acquired.artifact,
791
792
  handoff,
792
793
  androidPackage,
794
+ apkPackage: record.cacheHit && storeKey ? entryAppId(PLATFORM, storeKey) : null,
793
795
  release: async () => {
794
796
  await settleArtifactUploads(providerUpload, uploadPending);
795
797
  acquired.release();