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,19 +1,19 @@
1
- import { H as deviceSlotPlatforms, U as parseDeviceSlotKey, p as getProject } from "./config-DlrsduwG.mjs";
2
- import { f as refuseNoProject, l as phaseLine } from "./command-output-YKGWivpG.mjs";
3
- import { d as cancelledError, f as throwIfCancelled, u as cancellableSleep } from "./operation-exec-BW0em61G.mjs";
4
- import { a as recordWorkspaceUseAsync, r as readWorkspaceState$1 } from "./workspace-state-U08dEzhG.mjs";
5
- import { Nt as repoRootAsync } from "./settings-C7O8A6ZI.mjs";
6
- import { I as readWorkspaceLaunches, r as findCommandWorkspaceAsync } from "./project-DhCtQWWU.mjs";
7
- import { a as listeningPidsAsync, d as resolveProjectMetro, h as isMetroRunning, u as processCwds } from "./metro-DiXtA3Ty.mjs";
8
- import { d as webFactsAsync, o as readWebRecord, r as cdpEndpoint } from "./state--smjFSTL.mjs";
9
- import { Sn as iosAppProcess, _n as ensureMetroReverse, dn as androidAppProcess } from "./budget-3ivAK99e.mjs";
10
- import { et as resolveOwnedAvdSerialAsync } from "./android-C7sVmyI9.mjs";
11
- import { E as resolveOwnedIosSim, f as listAllIosSimsAsync } from "./ios-hcBpnEGk.mjs";
12
- import { f as probeHostedSession } from "./hosted-client-Bt-tndxV.mjs";
13
- import { r as readHostedNative } from "./ios-state-Dtw5K2aI.mjs";
14
- import { r as reopenHostedAndroidMetro } from "./hosted-android-xcfgCgSF.mjs";
15
- import { n as nativeRunCommand } from "./slot-launch-B7AuoWJv.mjs";
16
- import { n as sendToOwnedPage, t as liveWebRecord } from "./page-DBL2PiUU.mjs";
1
+ import { c as throwIfCancelled, i as loadScaledBudgetMs, o as cancellableSleep, s as cancelledError } from "./exec-VFRpu1iA.mjs";
2
+ import { H as deviceSlotPlatforms, U as parseDeviceSlotKey, p as getProject } from "./config-BZhXY15H.mjs";
3
+ import { f as refuseNoProject, l as phaseLine } from "./command-output-BBvS1H6v.mjs";
4
+ import { a as recordWorkspaceUseAsync, r as readWorkspaceState$1 } from "./workspace-state-CPSp3mav.mjs";
5
+ import { Pt as repoRootAsync } from "./settings-B5tCoq9N.mjs";
6
+ import { I as readWorkspaceLaunches, P as readRemoteSession, r as findCommandWorkspaceAsync } from "./project-BiC68mIp.mjs";
7
+ import { nt as resolveOwnedAvdSerialAsync } from "./android-Cjcj8MCw.mjs";
8
+ import { a as listeningPidsAsync, d as resolveProjectMetro, h as isMetroRunning, u as processCwds } from "./metro-1pJgCX4U.mjs";
9
+ import { d as webFactsAsync, o as readWebRecord, r as cdpEndpoint } from "./state-DMRNP7-4.mjs";
10
+ import { Tn as iosAppProcess, bn as ensureMetroReverse, mn as androidAppProcess } from "./budget-HyShrIpL.mjs";
11
+ import { E as resolveOwnedIosSim, f as listAllIosSimsAsync } from "./ios-BQzvJlzw.mjs";
12
+ import { f as probeHostedSession } from "./hosted-client-rsRqysJc.mjs";
13
+ import { r as readHostedNative } from "./ios-state-CT9nV5SP.mjs";
14
+ import { r as reopenHostedAndroidMetro } from "./hosted-android-Bvb2-ZxD.mjs";
15
+ import { n as nativeRunCommand } from "./slot-launch-QeuJMlnJ.mjs";
16
+ import { n as sendToOwnedPage, t as liveWebRecord } from "./page-CzEA_-5_.mjs";
17
17
  import { hostedAndroidDeviceName, hostedNativeRecords } from "@stim-cli/core/state";
18
18
  import { WebSocket } from "ws";
19
19
  import chalk from "chalk";
@@ -33,17 +33,21 @@ function peerQuery(metadata) {
33
33
  for (const [key, value] of Object.entries(metadata)) if (typeof value === "string") query.set(key, value);
34
34
  return query;
35
35
  }
36
+ function peerPlatform(query) {
37
+ return query.get("role")?.toLowerCase() === "ios" ? "ios" : "android";
38
+ }
36
39
  function peerMatches(query, role, appId) {
37
- if (role === "ios") return query.get("role")?.toLowerCase() === "ios";
38
- return query.get("app") === appId;
40
+ if (role === "ios") return peerPlatform(query) === "ios";
41
+ return appId === void 0 ? peerPlatform(query) === "android" : query.get("app") === appId;
39
42
  }
40
43
  /**
41
- * Asks Metro for its peers and reloads the ones matching `role` and `appId`. With `peersOnly`, it sends nothing and
42
- * only reports the outcome a reload would have, so a caller can wait for the app to connect.
44
+ * Asks Metro for its peers and reloads the ones matching `role` and `appId`. Without `role` every peer matches, and
45
+ * without `appId` every Android peer does. With `peersOnly`, it sends nothing and only reports the outcome a reload
46
+ * would have, so a caller can wait for the app to connect. With `exact`, a miss never falls back to a broadcast.
43
47
  */
44
- function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS, peersOnly = false, signal }) {
48
+ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS, peersOnly = false, exact = false, signal }) {
45
49
  if (signal?.aborted) return Promise.reject(cancelledError("reload"));
46
- const roleName = ROLE_NAMES[role];
50
+ const roleName = role ? `${ROLE_NAMES[role]} ` : "";
47
51
  return new Promise((resolve, reject) => {
48
52
  const requestId = `stim-reload-${process.pid}-${Date.now()}`;
49
53
  const socket = new WebSocket(`ws://127.0.0.1:${port}/message`);
@@ -93,6 +97,7 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS, p
93
97
  const entries = Object.entries(message.result);
94
98
  const peers = entries.length;
95
99
  const rolePeers = entries.filter(([, metadata]) => {
100
+ if (!role) return true;
96
101
  const query = peerQuery(metadata);
97
102
  return query ? peerMatches(query, role, appId) : false;
98
103
  });
@@ -101,21 +106,21 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS, p
101
106
  failed: true,
102
107
  noPeer: true,
103
108
  peers,
104
- reason: `No ${roleName} React Native app is connected to Metro on port ${port}.`
109
+ reason: `No ${roleName}React Native app is connected to Metro on port ${port}.`
105
110
  });
106
111
  return;
107
112
  }
108
113
  if (rolePeers.length === 0) {
109
- socket.send(JSON.stringify({
114
+ if (!exact) socket.send(JSON.stringify({
110
115
  version: 2,
111
116
  method: "reload"
112
117
  }));
113
- const others = peers === 0 ? " Nothing at all is connected to it, so the broadcast Stim sent anyway reached nothing." : ` Metro has ${peers} other connected client${peers === 1 ? "" : "s"}, and Stim broadcast a reload to them in case one is this app unmatched.`;
118
+ const others = exact ? peers === 0 ? " Nothing at all is connected to it." : ` Metro has ${peers} other connected client${peers === 1 ? "" : "s"}; Stim sent them nothing.` : peers === 0 ? " Nothing at all is connected to it, so the broadcast Stim sent anyway reached nothing." : ` Metro has ${peers} other connected client${peers === 1 ? "" : "s"}, and Stim broadcast a reload to them in case one is this app unmatched.`;
114
119
  finish({
115
120
  failed: true,
116
121
  noPeer: true,
117
122
  peers,
118
- reason: `No ${roleName} React Native app is connected to Metro on port ${port}.${others}`
123
+ reason: `No ${roleName}React Native app is connected to Metro on port ${port}.${others}`
119
124
  });
120
125
  return;
121
126
  }
@@ -124,10 +129,16 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS, p
124
129
  method: "reload",
125
130
  target: id
126
131
  }));
132
+ const platforms = /* @__PURE__ */ new Set();
133
+ for (const [, metadata] of rolePeers) {
134
+ const query = peerQuery(metadata);
135
+ if (query) platforms.add(peerPlatform(query));
136
+ }
127
137
  finish({
128
138
  ok: true,
129
139
  peers,
130
- targets: rolePeers.length
140
+ targets: rolePeers.length,
141
+ ...role ? {} : { platforms: [...platforms] }
131
142
  });
132
143
  return;
133
144
  }
@@ -158,8 +169,9 @@ const DEFAULT_DEPS = {
158
169
  findWorkspace: (cwd) => findCommandWorkspaceAsync(cwd, repoRootAsync, (line) => console.error(line)),
159
170
  getProject,
160
171
  readLaunches: readWorkspaceLaunches,
172
+ readRemote: readRemoteSession,
161
173
  resolveIos: async (udid) => resolveOwnedIosSim(udid, await listAllIosSimsAsync({})),
162
- resolveAndroid: resolveOwnedAvdSerialAsync,
174
+ resolveAndroid: (avdName, preferredSerial) => resolveOwnedAvdSerialAsync(avdName, { preferredSerial }),
163
175
  iosProcess: iosAppProcess,
164
176
  androidProcess: androidAppProcess,
165
177
  resolveMetro: (port, root, signal) => resolveProjectMetro(port, root, {
@@ -218,8 +230,13 @@ async function reloadBrowser(browser, metroPort, d, signal) {
218
230
  }
219
231
  };
220
232
  }
221
- async function processFailure(platform, record, d, slot = "default") {
222
- const { state } = platform === "ios" ? await d.iosProcess(record.deviceId, record.appId) : await d.androidProcess(record.deviceId, record.appId);
233
+ const PROCESS_PROBE_BASE_MS = 5e3;
234
+ const PROCESS_PROBE_CAP_MS = 3e4;
235
+ async function appProcessState(platform, record, d) {
236
+ const { state } = platform === "ios" ? await d.iosProcess(record.deviceId, record.appId, { timeoutMs: loadScaledBudgetMs(PROCESS_PROBE_BASE_MS, PROCESS_PROBE_CAP_MS) }) : await d.androidProcess(record.deviceId, record.appId);
237
+ return state;
238
+ }
239
+ function processFailure(platform, record, state, slot = "default") {
223
240
  if (state === "unknown") {
224
241
  const probe = platform === "ios" ? `xcrun simctl spawn ${record.deviceId} launchctl list` : `adb -s ${record.deviceId} shell pidof ${record.appId}`;
225
242
  return failure("STIM_RELOAD_PROBE_FAILED", `Stim could not determine whether ${record.appId} is running on ${record.deviceId}.`, `Run \`${probe}\` and retry when the device tool responds.`);
@@ -248,7 +265,8 @@ async function inspectTarget(platform, record, project, d, slot = "default") {
248
265
  platform,
249
266
  error: failure("STIM_RELOAD_STOPPED", `The recorded iOS app is not running on a booted owned simulator.`, `Run \`${runCommand}\` to boot, install, and launch it.`)
250
267
  };
251
- const stopped = await processFailure(platform, record, d, slot);
268
+ const state = await appProcessState(platform, record, d);
269
+ const stopped = state === "unknown" ? null : processFailure(platform, record, state, slot);
252
270
  if (stopped) return {
253
271
  platform,
254
272
  error: stopped
@@ -257,7 +275,8 @@ async function inspectTarget(platform, record, project, d, slot = "default") {
257
275
  platform,
258
276
  slot,
259
277
  record,
260
- deviceName: resolved.sim.name
278
+ deviceName: resolved.sim.name,
279
+ processUnknown: state === "unknown"
261
280
  };
262
281
  }
263
282
  const configured = project.platforms?.android;
@@ -267,7 +286,7 @@ async function inspectTarget(platform, record, project, d, slot = "default") {
267
286
  };
268
287
  let resolved;
269
288
  try {
270
- resolved = await d.resolveAndroid(configured.avdName);
289
+ resolved = await d.resolveAndroid(configured.avdName, record.deviceId);
271
290
  } catch (error) {
272
291
  return {
273
292
  platform,
@@ -278,7 +297,8 @@ async function inspectTarget(platform, record, project, d, slot = "default") {
278
297
  platform,
279
298
  error: failure("STIM_RELOAD_STOPPED", `The recorded Android app is not running on this workspace's owned emulator.`, `Run \`${runCommand}\` to boot, install, and launch it.`)
280
299
  };
281
- const stopped = await processFailure(platform, record, d, slot);
300
+ const state = await appProcessState(platform, record, d);
301
+ const stopped = state === "unknown" ? null : processFailure(platform, record, state, slot);
282
302
  if (stopped) return {
283
303
  platform,
284
304
  error: stopped
@@ -287,7 +307,81 @@ async function inspectTarget(platform, record, project, d, slot = "default") {
287
307
  platform,
288
308
  slot,
289
309
  record,
290
- deviceName: configured.avdName
310
+ deviceName: configured.avdName,
311
+ processUnknown: state === "unknown"
312
+ };
313
+ }
314
+ function remoteSessionFor(session, platform) {
315
+ return session && (!platform || !session.platform || session.platform === platform) ? session : null;
316
+ }
317
+ function unlaunchedRefusal(platform, metroPort, remote) {
318
+ const connected = metroPort ? ` and no app is connected to this workspace's Metro on port ${metroPort}` : "";
319
+ if (remote) {
320
+ const run = `stim ${platform ?? remote.platform ?? "ios"} --remote eas`;
321
+ return failure("STIM_RELOAD_STOPPED", `This workspace's remote device is EAS Simulator session ${remote.sessionId}, and no app is connected to this workspace's Metro${metroPort ? ` on port ${metroPort}` : ""}. An app in an EAS session may not open Metro's websocket through the tunnel, so Stim cannot reload it.`, `Run \`${run}\` to relaunch the app on the session; that restarts the app and loses in-memory state.`);
322
+ }
323
+ const run = platform ? `Run \`stim ${platform}\` first.` : "Run `stim ios` or `stim android` first.";
324
+ return failure("STIM_RELOAD_STOPPED", platform ? `No ${platform} app launch is recorded for this workspace${connected}.` : `No live app launch is recorded${connected}.`, metroPort ? `${run} An app on a physical device (--device) is reloaded through Metro once it is running and connected${platform === "ios" ? "" : `; an Android phone needs \`adb reverse tcp:${metroPort} tcp:${metroPort}\``}.` : run);
325
+ }
326
+ async function reloadUnrecorded(root, platform, project, d, signal) {
327
+ const port = project.metroPort ?? null;
328
+ const remote = remoteSessionFor(d.readRemote(root), platform);
329
+ const refusal = () => ({
330
+ ok: false,
331
+ error: unlaunchedRefusal(platform, port, remote)
332
+ });
333
+ if (!port) return refusal();
334
+ const metro = await d.resolveMetro(port, root, signal);
335
+ throwIfCancelled(signal, "reload");
336
+ if (!metro.metro) return refusal();
337
+ const probe = await d.reloadMetro(port, {
338
+ peersOnly: true,
339
+ ...platform ? { role: platform } : {},
340
+ ...signal ? { signal } : {}
341
+ });
342
+ throwIfCancelled(signal, "reload");
343
+ if (!probe.ok) return probe.unreachable ? {
344
+ ok: false,
345
+ error: failure("STIM_RELOAD_FAILED", probe.reason, `Metro is registered for this workspace but did not answer on port ${port}. Run \`stim reload${platform ? ` ${platform}` : ""}\` again. If it keeps timing out, run \`stim doctor\` to check the dev server.`)
346
+ } : refusal();
347
+ let target = platform;
348
+ if (!target) {
349
+ const platforms = probe.platforms ?? [];
350
+ const [only] = platforms;
351
+ const recorded = remote?.platform ?? null;
352
+ if (only && platforms.length === 1) target = only;
353
+ else if (recorded && platforms.length === 0) target = recorded;
354
+ else return {
355
+ ok: false,
356
+ error: failure("STIM_RELOAD_AMBIGUOUS", platforms.length > 1 ? `More than one platform is connected to this workspace's Metro: ${platforms.join(", ")}.` : `Apps are connected to this workspace's Metro on port ${port}, but Metro does not say which platform.`, "Choose one with `stim reload ios` or `stim reload android`.")
357
+ };
358
+ }
359
+ const session = remoteSessionFor(remote, target);
360
+ const reloaded = await d.reloadMetro(port, {
361
+ role: target,
362
+ exact: true,
363
+ ...signal ? { signal } : {}
364
+ });
365
+ throwIfCancelled(signal, "reload");
366
+ if (!reloaded.ok) return reloaded.unreachable ? {
367
+ ok: false,
368
+ error: failure("STIM_RELOAD_FAILED", reloaded.reason, `Metro is registered for this workspace but did not answer on port ${port}. Run \`stim reload ${target}\` again. If it keeps timing out, run \`stim doctor\` to check the dev server.`)
369
+ } : {
370
+ ok: false,
371
+ error: unlaunchedRefusal(target, port, session)
372
+ };
373
+ return {
374
+ ok: true,
375
+ facts: {
376
+ platform: target,
377
+ deviceId: `metro:${port}`,
378
+ deviceName: session ? `EAS Simulator session ${session.sessionId}` : "devices connected to Metro",
379
+ appId: null,
380
+ metroPort: port,
381
+ strategy: reloaded.broadcast ? "metro-broadcast" : "metro-websocket",
382
+ targets: reloaded.targets ?? null,
383
+ reverseRestored: []
384
+ }
291
385
  };
292
386
  }
293
387
  function isTargetFailure(value) {
@@ -389,13 +483,15 @@ async function runReload({ root, platform = null, deps = {}, signal }) {
389
483
  };
390
484
  if (live.length === 0) {
391
485
  const nativeFailure = inspected.find(isTargetFailure)?.error;
392
- return {
486
+ const firstFailure = nativeFailure && browser ? {
487
+ ...nativeFailure,
488
+ remedy: `${nativeFailure.remedy ?? ""} To reload the owned Chrome page instead, run \`stim reload web\`.`.trim()
489
+ } : nativeFailure;
490
+ if (firstFailure) return {
393
491
  ok: false,
394
- error: (nativeFailure && browser ? {
395
- ...nativeFailure,
396
- remedy: `${nativeFailure.remedy ?? ""} To reload the owned Chrome page instead, run \`stim reload web\`.`.trim()
397
- } : nativeFailure) ?? failure("STIM_RELOAD_STOPPED", platform ? `No ${platform} app launch is recorded for this workspace.` : "No live app launch is recorded.", platform ? `Run \`stim ${platform}\` first.` : "Run `stim ios` or `stim android` first.")
492
+ error: firstFailure
398
493
  };
494
+ return reloadUnrecorded(root, platform, project, d, signal);
399
495
  }
400
496
  const target = live.find((candidate) => !candidate.record.release && candidate.record.metroPort === project.metroPort) ?? live[0];
401
497
  if (target.record.runtime === "process") return {
@@ -417,8 +513,9 @@ async function runReload({ root, platform = null, deps = {}, signal }) {
417
513
  ok: false,
418
514
  error: failure("STIM_NO_METRO", `Port ${port} is not serving this workspace's Metro.`, "Run `stim start`, then retry.")
419
515
  };
420
- const stopped = target.hosted ? null : await processFailure(target.platform, target.record, d, target.slot);
516
+ const rechecked = target.hosted || target.processUnknown ? "running" : await appProcessState(target.platform, target.record, d);
421
517
  throwIfCancelled(signal, "reload");
518
+ const stopped = rechecked === "unknown" ? null : processFailure(target.platform, target.record, rechecked, target.slot);
422
519
  if (stopped) return {
423
520
  ok: false,
424
521
  error: stopped
@@ -473,7 +570,7 @@ async function runReload({ root, platform = null, deps = {}, signal }) {
473
570
  throwIfCancelled(signal, "reload");
474
571
  const reloaded = await d.reloadMetro(port, request);
475
572
  if (!reloaded.ok) {
476
- const stoppedAfterMetro = target.hosted ? null : await processFailure(target.platform, target.record, d, target.slot);
573
+ const stoppedAfterMetro = target.hosted ? null : processFailure(target.platform, target.record, await appProcessState(target.platform, target.record, d), target.slot);
477
574
  if (stoppedAfterMetro) return {
478
575
  ok: false,
479
576
  error: stoppedAfterMetro
@@ -546,6 +643,11 @@ function registerReload(program, deps = {}) {
546
643
  console.log(`Reload requested for ${facts.appId} in the owned Chrome (DevTools ${facts.deviceId}). Completion is not observed; run stim logs --errors.`);
547
644
  return;
548
645
  }
646
+ if (facts.appId === null) {
647
+ const reached = facts.strategy === "metro-broadcast" ? "This Metro cannot name its connected apps, so the request was broadcast to all of them." : `The request addressed ${facts.targets} connected ${facts.platform} Metro client${facts.targets === 1 ? "" : "s"}.`;
648
+ console.log(`Reload requested through this workspace's Metro on port ${facts.metroPort}, for apps Stim did not launch (a physical device or ${facts.deviceName}). ${reached} Completion is not observed; verify the expected UI and run stim logs --errors.`);
649
+ return;
650
+ }
549
651
  const scope = facts.strategy === "metro-broadcast" ? ` This Metro cannot name its connected apps, so the reload request was broadcast to all of them and Stim cannot confirm ${facts.appId} was one. Check the expected UI on ${facts.deviceId}; if nothing changed, reload from the app's own error screen or dev menu.` : facts.targets && facts.targets > 1 ? ` ${facts.targets} devices are running this app on that Metro and the reload request addressed all of them, not only ${facts.deviceId}.` : "";
550
652
  const restored = facts.reverseRestored.length ? ` The adb reverse for tcp:${facts.metroPort} was missing on ${facts.reverseRestored.join(", ")}, so Stim restored it first.` : "";
551
653
  console.log(`Reload requested for ${facts.appId} on ${facts.deviceName} (${facts.deviceId}) via ${facts.strategy}; ${facts.platform} Metro port ${facts.metroPort}.${restored}${scope} Completion is not observed; verify the expected UI and run stim logs --errors.`);
@@ -1,10 +1,11 @@
1
- import { H as deviceSlotPlatforms } from "./config-DlrsduwG.mjs";
2
- import { l as phaseLine } from "./command-output-YKGWivpG.mjs";
3
- import { F as parseIosRemote, H as remoteEasFallbackSetting, R as publicUrlSetting, U as remoteIosSetting, rt as tunnelModeSetting } from "./settings-C7O8A6ZI.mjs";
4
- import "./budget-3ivAK99e.mjs";
5
- import { b as resolveSimulatorAppFlag } from "./support-TWuQlHQo.mjs";
6
- import { n as devicePlacementRecord } from "./placement-log-BnGgJRRZ.mjs";
7
- import { r as devicePlacementLine } from "./eas-fallback-vKlrqxgE.mjs";
1
+ import { l as WorkspaceProcessCleanupError } from "./exec-VFRpu1iA.mjs";
2
+ import { H as deviceSlotPlatforms } from "./config-BZhXY15H.mjs";
3
+ import { l as phaseLine } from "./command-output-BBvS1H6v.mjs";
4
+ import { I as parseIosRemote, U as remoteEasFallbackSetting, W as remoteIosSetting, it as tunnelModeSetting, z as publicUrlSetting } from "./settings-B5tCoq9N.mjs";
5
+ import "./budget-HyShrIpL.mjs";
6
+ import { b as resolveSimulatorAppFlag } from "./support-qKcbgmI5.mjs";
7
+ import { n as devicePlacementRecord } from "./placement-log-DjOXJRIH.mjs";
8
+ import { r as devicePlacementLine } from "./eas-fallback-gaZi-dJL.mjs";
8
9
  import chalk from "chalk";
9
10
  //#region src/commands/ios/remote.ts
10
11
  function deviceRemoteConflict(remote, physical) {
@@ -73,11 +74,19 @@ async function selectIosPlacement(args) {
73
74
  const refusal = await args.validateSelectors();
74
75
  if (refusal) return { failure: refusal };
75
76
  const easFallback = args.supportsRemote && remoteEasFallbackSetting(args.settings);
77
+ const localSims = await args.simSnapshot.readAsync?.({
78
+ signal: args.operation?.signal,
79
+ operation: args.operation
80
+ }).then((sims) => sims.filter((sim) => sim.available)).catch((error) => {
81
+ if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
82
+ args.operation?.signal.throwIfAborted();
83
+ });
76
84
  try {
77
85
  const placed = await d.automaticDevicePlacement({
78
86
  root,
79
87
  slot,
80
88
  platform: "ios",
89
+ ...localSims ? { localSims } : {},
81
90
  selectors: hostedIosSelectors(deviceType, runtime),
82
91
  appMode,
83
92
  buildMachine: opts.remoteBuild,
@@ -1,19 +1,20 @@
1
1
  import { l as workspaceAgentDeviceDir } from "./paths-DQtTgsBf.mjs";
2
- import { H as deviceSlotPlatforms, p as getProject } from "./config-DlrsduwG.mjs";
3
- import { i as formatDuration, l as phaseLine } from "./command-output-YKGWivpG.mjs";
4
- import { $ as settingOriginScope, F as parseIosRemote, G as resolveCacheProviderConfig, V as remoteAndroidSetting, W as resolveAndroidLayout, Z as settingFile, a as SETTING_SHAPE_REMEDY, d as androidLayoutSetting, et as settingShapeErrors, f as androidLayoutSettingError, it as unknownSettingKeys, nt as settingsLayers, p as cacheProviderSettingError, s as androidAvdConfigSettingError, u as androidDataPartitionSizeGbSettingError } from "./settings-C7O8A6ZI.mjs";
5
- import { v as detectIsExpo } from "./project-DhCtQWWU.mjs";
6
- import { B as recordFinishedBuild, Hn as isEasAuthFailureText, Rn as UPLOAD_TIMEOUT_MS, Vn as easAuthNote, zn as cacheLevel } from "./budget-3ivAK99e.mjs";
7
- import { B as ownedAvdDeviceProfile, I as listInstalledSystemImages, K as ownedAvdSystemImage, N as listAvdDeviceProfilesAsync, Q as profileNeedsFoldFeature, X as pickDefaultSystemImage, _t as parkedMaxSetting, rt as systemImageSupportsFold, t as DEFAULT_AVD_DEVICE_PROFILE } from "./android-C7sVmyI9.mjs";
8
- import { a as workspaceLinkLine } from "./stim-desktop-D5OGpYZM.mjs";
9
- import { d as optimizationBuildProfile, l as artifactCachePolicy, p as resolveOptimizations, u as compilerCacheFallbackMessage } from "./errors-ccaPc4ox.mjs";
10
- import { n as CCACHE_UNAVAILABLE, r as ccacheActivityLine } from "./ccache-CH2EWGPB.mjs";
11
- import { c as readProductFlavors, s as productFlavorRefusal } from "./react-native-build-CelbTO_y.mjs";
12
- import { l as parseDeviceWait } from "./device-lease-run-DXPSwdbb.mjs";
13
- import { t as DEFAULT_DEVICE_SLOT_WAIT_MS } from "./device-capacity-DH0QsZYZ.mjs";
14
- import { n as resolveAndroidCas, r as resolveAndroidCompilerCache } from "./android-cas-ngferVq2.mjs";
15
- import { r as isPhysicalDeviceRequest } from "./native-runtime-DBRfY_PN.mjs";
16
- import { C as remoteAvdFlagRefusal, D as systemImageRefusal, E as resolveVariant, T as resolveSystemImage, a as PLATFORM, m as deviceProfileRefusal, v as foldableImageRefusal, w as resolveDeviceProfile, y as isReleaseVariant } from "./support-CbXPbUMJ.mjs";
2
+ import { H as deviceSlotPlatforms, p as getProject } from "./config-BZhXY15H.mjs";
3
+ import { i as formatDuration, l as phaseLine } from "./command-output-BBvS1H6v.mjs";
4
+ import { G as resolveAndroidLayout, H as remoteAndroidSetting, I as parseIosRemote, K as resolveCacheProviderConfig, Q as settingFile, a as SETTING_SHAPE_REMEDY, at as unknownSettingKeys, d as androidLayoutSetting, et as settingOriginScope, f as androidLayoutSettingError, p as cacheProviderSettingError, rt as settingsLayers, s as androidAvdConfigSettingError, tt as settingShapeErrors, u as androidDataPartitionSizeGbSettingError } from "./settings-B5tCoq9N.mjs";
5
+ import { v as detectIsExpo } from "./project-BiC68mIp.mjs";
6
+ import { a as workspaceLinkLine } from "./stim-desktop-DS0mzR8U.mjs";
7
+ import { B as ownedAvdDeviceProfile, I as listInstalledSystemImages, K as ownedAvdSystemImage, N as listAvdDeviceProfilesAsync, Q as profileNeedsFoldFeature, X as pickDefaultSystemImage, at as systemImageSupportsFold, k as hostSystemImageArch, l as androidSystemImageAbi, t as DEFAULT_AVD_DEVICE_PROFILE, vt as parkedMaxSetting } from "./android-Cjcj8MCw.mjs";
8
+ import { B as recordFinishedBuild, Gn as isEasAuthFailureText, Hn as cacheLevel, Vn as UPLOAD_TIMEOUT_MS, Wn as easAuthNote } from "./budget-HyShrIpL.mjs";
9
+ import { d as optimizationBuildProfile, l as artifactCachePolicy, p as resolveOptimizations, u as compilerCacheFallbackMessage } from "./errors-DHm_U5gv.mjs";
10
+ import { n as CCACHE_UNAVAILABLE, r as ccacheActivityLine } from "./ccache-h1FKhZeg.mjs";
11
+ import { n as buildPlacementCandidates } from "./client-BQsmyp_-.mjs";
12
+ import { c as readProductFlavors, s as productFlavorRefusal } from "./react-native-build-CwZB-agu.mjs";
13
+ import { l as parseDeviceWait } from "./device-lease-run-ogEeJ62K.mjs";
14
+ import { t as DEFAULT_DEVICE_SLOT_WAIT_MS } from "./device-capacity-ZYaRALv5.mjs";
15
+ import { n as resolveAndroidCas, r as resolveAndroidCompilerCache } from "./android-cas-BVqh2Zep.mjs";
16
+ import { r as isPhysicalDeviceRequest } from "./native-runtime-B9w_Qyz3.mjs";
17
+ import { C as remoteAvdFlagRefusal, D as systemImageRefusal, E as resolveVariant, T as resolveSystemImage, a as PLATFORM, m as deviceProfileRefusal, v as foldableImageRefusal, w as resolveDeviceProfile, y as isReleaseVariant } from "./support-Cxj9CmII.mjs";
17
18
  import { buildDiagnostics } from "@stim-cli/core/state";
18
19
  import chalk from "chalk";
19
20
  //#region src/commands/android/plan.ts
@@ -27,6 +28,14 @@ function slotOwnedAvd(projectPath, slot) {
27
28
  deviceProfile: ownedAvdDeviceProfile(android.avdName)
28
29
  } : null;
29
30
  }
31
+ function localBuildPreflight(preflight, target, { release, targetAbiOnly, variant }) {
32
+ if (target.kind !== "emulator" && target.kind !== "remote") return null;
33
+ const abi = targetAbiOnly && !release ? androidSystemImageAbi(target.systemImage) ?? hostSystemImageArch() : null;
34
+ return preflight?.({
35
+ abi,
36
+ variant
37
+ }) ?? null;
38
+ }
30
39
  function fail(code, message, remedy, { lines = [] } = {}) {
31
40
  return {
32
41
  ok: false,
@@ -118,10 +127,10 @@ function resolveAndroidBuildPlan({ settings, settingsContext, env, easProfile, v
118
127
  }
119
128
  };
120
129
  }
121
- async function resolveAndroidRunPlan({ settings, settingsContext, env, slot, signal, easProfile, variant: variantFlag, systemImage: systemImageFlag, deviceProfile: deviceProfileFlag, device: deviceFlag, wait: waitFlag, waitConflict, remote: commandRemoteBackend, buildCache: requestedBuildCache }, { warn, runtimeKind, resolveCompilerCache = androidCompilerCache, resolveCacheProvider = resolveCacheProviderConfig, validateAvdConfig = androidAvdConfigSettingError, readFlavors = readProductFlavors, variantProblem = (variant) => productFlavorRefusal({
130
+ async function resolveAndroidRunPlan({ settings, settingsContext, env, slot, signal, easProfile, variant: variantFlag, systemImage: systemImageFlag, deviceProfile: deviceProfileFlag, device: deviceFlag, wait: waitFlag, waitConflict, remote: commandRemoteBackend, buildCache: requestedBuildCache, buildMachine }, { warn, runtimeKind, resolveCompilerCache = androidCompilerCache, resolveCacheProvider = resolveCacheProviderConfig, validateAvdConfig = androidAvdConfigSettingError, readFlavors = readProductFlavors, variantProblem = (variant) => productFlavorRefusal({
122
131
  flavors: readFlavors(resolveAndroidLayout(settings, settingsContext.projectPath, settingsContext.repoRoot ?? settingsContext.projectPath)),
123
132
  variant
124
- }), detectExpo = () => detectIsExpo(settingsContext.projectPath), listSystemImages = listInstalledSystemImages, listDeviceProfiles = listAvdDeviceProfilesAsync, parkedLimit = parkedMaxSetting, supportsFold = systemImageSupportsFold, ownedAvd = slotOwnedAvd }) {
133
+ }), detectExpo = () => detectIsExpo(settingsContext.projectPath), listSystemImages = listInstalledSystemImages, listDeviceProfiles = listAvdDeviceProfilesAsync, parkedLimit = parkedMaxSetting, supportsFold = systemImageSupportsFold, ownedAvd = slotOwnedAvd, preflight, buildMachines = (selected) => buildPlacementCandidates(selected).machines }) {
125
134
  const root = settingsContext.projectPath;
126
135
  const [shapeError, ...moreShapeErrors] = [parkedLimit("android").error, ...settingShapeErrors(settings)].filter((error) => Boolean(error));
127
136
  if (shapeError) return fail("STIM_BAD_ARG", shapeError, SETTING_SHAPE_REMEDY, { lines: moreShapeErrors });
@@ -200,6 +209,8 @@ async function resolveAndroidRunPlan({ settings, settingsContext, env, slot, sig
200
209
  systemImage,
201
210
  deviceProfile
202
211
  };
212
+ const preflightRefusal = preflight && easProfile === void 0 && buildMachines(buildMachine ?? "local").length === 0 ? localBuildPreflight(preflight, target, plannedBuild.plan.build) : null;
213
+ if (preflightRefusal) return fail(preflightRefusal.code, preflightRefusal.reason, preflightRefusal.remedy);
203
214
  return {
204
215
  ok: true,
205
216
  plan: {
@@ -431,5 +442,17 @@ function persistLastBuild({ recordBuild = recordFinishedBuild, root, record, sta
431
442
  }
432
443
  return lastBuild;
433
444
  }
445
+ function logPostBuildFailure(acquired, writer, record) {
446
+ if (acquired) writer.write(record);
447
+ }
448
+ function persistThrownBuild({ acquired, error, ...args }) {
449
+ if (!acquired) return;
450
+ const { code } = error;
451
+ persistLastBuild({
452
+ ...args,
453
+ status: "failed",
454
+ errorCode: typeof code === "string" ? code : void 0
455
+ });
456
+ }
434
457
  //#endregion
435
- export { reportAndroidResult as a, resolveAndroidRunPlan as c, persistLastBuild as i, finishAndroidUpload as n, androidDeviceSelectorRefusal as o, lastBuildRecord as r, resolveAndroidBuildPlan as s, androidFacts as t };
458
+ export { persistLastBuild as a, androidDeviceSelectorRefusal as c, logPostBuildFailure as i, resolveAndroidBuildPlan as l, finishAndroidUpload as n, persistThrownBuild as o, lastBuildRecord as r, reportAndroidResult as s, androidFacts as t, resolveAndroidRunPlan as u };
@@ -1,5 +1,5 @@
1
- import { g as process_identity_exports, t as getExecutor, x as ownership_claim_exports } from "./exec-DEoAhcze.mjs";
2
- import { a as macosRuntimeClaim, i as macosProcess, r as macosLogFile, s as updateMacosRecord } from "./state-08I3hw3_.mjs";
1
+ import { D as ownership_claim_exports, S as process_identity_exports, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { a as macosRuntimeClaim, i as macosProcess, r as macosLogFile, s as updateMacosRecord } from "./state-DPaM3u5K.mjs";
3
3
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
4
4
  import { LOG_ROTATE_BYTES } from "@stim-cli/core";
5
5
  import { readMacosRecord } from "@stim-cli/core/state";
@@ -1,6 +1,6 @@
1
- import { _ as reportSignal, m as operationState } from "./exec-DEoAhcze.mjs";
1
+ import { C as reportSignal, b as operationState } from "./exec-VFRpu1iA.mjs";
2
2
  import { v as withDirLock$1 } from "./paths-DQtTgsBf.mjs";
3
- import { $ as outdatedServer, X as endpoint, Z as findPeer$1, _ as loadConfig$1, at as setupRemedy, d as getConfigDir, et as parseMachine$1, nt as realIo, ot as tailscaleStatusAsync, st as readHostPermissions, tt as reachMachine } from "./config-DlrsduwG.mjs";
3
+ import { $ as outdatedServer, X as endpoint, Z as findPeer$1, _ as loadConfig$1, at as setupRemedy, d as getConfigDir, et as parseMachine$1, nt as realIo, ot as tailscaleStatusAsync, st as readHostPermissions, tt as reachMachine } from "./config-BZhXY15H.mjs";
4
4
  import { releaseClaim, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
5
5
  import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
6
6
  import { hostname } from "node:os";
@@ -312,7 +312,7 @@ function note(title, detail, fix = null) {
312
312
  const PROBLEM_TITLES = {
313
313
  unreachable: "does not answer a build offer",
314
314
  checkout: "cannot build an app outside a git checkout",
315
- "stim-build": "runs another Stim build",
315
+ "stim-build": "runs an incompatible Stim build",
316
316
  arch: "has another CPU architecture",
317
317
  xcode: "has another Xcode",
318
318
  "macos-sdk": "has another macOS SDK",
@@ -333,7 +333,7 @@ function problemFix(code, entry) {
333
333
  switch (code) {
334
334
  case "unreachable": return `Check that stim-server runs on ${entry} and that its tailscale serve route answers, then run \`stim doctor\` again. To keep it running there, run \`stim-server service install --serve\` on ${entry}.`;
335
335
  case "checkout": return "Offload syncs the files git lists; run Stim from a git checkout of the app.";
336
- case "stim-build": return `Update stim-server on ${entry} to the same Stim build as this machine: there, run \`stim-server service update --release <version>\` for this machine's release, or \`--from <dir>\` with the packed packages of this machine's checkout.`;
336
+ case "stim-build": return `Update stim-server on ${entry} to a Stim release with the same build compatibility version as this machine (an older stim-server needs the same Stim build): there, run \`stim-server service update --release <version>\` for this machine's release, or \`--from <dir>\` with the packed packages of this machine's checkout.`;
337
337
  case "arch": return "Use a remote machine with the same CPU architecture as this machine.";
338
338
  case "xcode":
339
339
  case "simulator-sdk":
@@ -542,11 +542,17 @@ async function inspectBuildMachines({ fix, check = null, version = "<version>",
542
542
  }
543
543
  //#endregion
544
544
  //#region src/offload/selection.ts
545
+ const FINGERPRINT_MISMATCH_REMEDY = "The build Mac fingerprints the synced checkout differently; the message names the sources that differ. Stim sends tracked and untracked files and the gitignored files the fingerprint reads, except under node_modules. A source still differs when the build Mac's dependency install or pod install writes it differently, or when the app config reads an environment variable or file that differs. Make that input agree on both Macs, for example by committing the lockfile pod install rewrote there, or rerun with --remote-build auto or --remote-build local.";
546
+ /** The remedy for a React Native worker's fingerprint-mismatch reason, or undefined for any other reason. */
547
+ function fingerprintMismatchRemedy(reason) {
548
+ return reason.startsWith("fingerprint-mismatch: the checkout there ") ? FINGERPRINT_MISMATCH_REMEDY : void 0;
549
+ }
545
550
  var OffloadRefusal = class extends Error {
546
551
  code = "STIM_OFFLOAD_REFUSED";
547
- remedy = "Run stim doctor --fix to ask for build access if not paired; it prints the stim-server setup command a person runs on the worker to approve this machine. Check stim settings get remote.machines, or rerun with --remote-build auto or --remote-build local.";
548
- constructor(machine, reason) {
552
+ remedy;
553
+ constructor(machine, reason, remedy = "Run stim doctor --fix to ask for build access if not paired; it prints the stim-server setup command a person runs on the worker to approve this machine. Check stim settings get remote.machines, or rerun with --remote-build auto or --remote-build local.") {
549
554
  super(reason.startsWith(`${machine}: `) ? reason : `${machine}: ${reason}`);
555
+ this.remedy = remedy;
550
556
  }
551
557
  };
552
558
  function resolveBuildMachine(flag, env, setting) {
@@ -617,4 +623,4 @@ function resolveBuildPlacement(flag) {
617
623
  }
618
624
  }
619
625
  //#endregion
620
- export { requireLocalBuild as a, inspectBuildMachines as c, hostingMachines as d, inspectDeviceHostMachines as f, parseBuildMachineOption as i, pairedMachines as l, buildPlacementSettings as n, resolveBuildMachine as o, namedBuildMachine as r, resolveBuildPlacement as s, OffloadRefusal as t, configuredMachines as u };
626
+ export { parseBuildMachineOption as a, resolveBuildPlacement as c, configuredMachines as d, hostingMachines as f, namedBuildMachine as i, inspectBuildMachines as l, buildPlacementSettings as n, requireLocalBuild as o, inspectDeviceHostMachines as p, fingerprintMismatchRemedy as r, resolveBuildMachine as s, OffloadRefusal as t, pairedMachines as u };
@@ -1,6 +1,6 @@
1
- import { C as __require, S as __commonJSMin, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
- import { q as resolveProjectSettings } from "./settings-C7O8A6ZI.mjs";
3
- import { c as registerMetroStore, f as resolveMetroSharedCache, n as supervisorError, r as appendCacheStore, s as metroStoreRoot } from "./errors-ccaPc4ox.mjs";
1
+ import { O as __commonJSMin, k as __require, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { J as resolveProjectSettings } from "./settings-B5tCoq9N.mjs";
3
+ import { c as registerMetroStore, f as resolveMetroSharedCache, n as supervisorError, r as appendCacheStore, s as metroStoreRoot } from "./errors-DHm_U5gv.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { isAbsolute, join, relative, sep } from "node:path";
6
6
  //#endregion
@@ -14,6 +14,12 @@ var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) =
14
14
  ]);
15
15
  const PROGRESS_PART = /^\{"done":(\d+),"total":(\d+),"percent":(\d+)\}$/;
16
16
  const PROGRESS_INTERVAL_MS = 1e3;
17
+ const MANIFEST_PATHS = /* @__PURE__ */ new Set([
18
+ "/",
19
+ "/manifest",
20
+ "/index.exp"
21
+ ]);
22
+ const observedServers = /* @__PURE__ */ new WeakSet();
17
23
  function clientPidFromLsof(output, clientPort, serverPort) {
18
24
  const connection = new RegExp(`:${clientPort}->\\S*:${serverPort}$`);
19
25
  let pid = null;
@@ -30,9 +36,54 @@ var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) =
30
36
  "-Fpn"
31
37
  ])).then((output) => clientPidFromLsof(output, remotePort, localPort)).catch(() => null);
32
38
  }
33
- function bundleResponseMiddleware(write, { runLsof } = {}) {
39
+ function manifestPlatform(req) {
40
+ if (req.method !== "GET") return null;
41
+ let url;
42
+ try {
43
+ url = new URL(req.url, "http://localhost");
44
+ } catch {
45
+ return null;
46
+ }
47
+ if (!MANIFEST_PATHS.has(url.pathname)) return null;
48
+ const platform = url.searchParams.get("platform") || req.headers["expo-platform"] || req.headers["exponent-platform"];
49
+ return platform === "ios" || platform === "android" ? platform : null;
50
+ }
51
+ function observeManifestRequests(server, write) {
52
+ if (!server || observedServers.has(server)) return;
53
+ observedServers.add(server);
54
+ server.prependListener("request", (req, res) => {
55
+ const platform = manifestPlatform(req);
56
+ if (!platform || req.headers["x-stim-metro-warmup"] === "1") return;
57
+ const requestId = randomUUID();
58
+ const emit = (stage, statusCode) => {
59
+ try {
60
+ write({
61
+ ts: Date.now(),
62
+ src: "metro",
63
+ level: "debug",
64
+ event: `manifest_request_${stage}`,
65
+ platform,
66
+ requestId,
67
+ ...statusCode ? { statusCode } : {},
68
+ msg: `${platform} manifest request ${stage}`
69
+ });
70
+ } catch {}
71
+ };
72
+ emit("started");
73
+ let ended = false;
74
+ const finish = (complete) => {
75
+ if (ended) return;
76
+ ended = true;
77
+ emit(complete && res.statusCode === 200 ? "finished" : "failed", res.statusCode);
78
+ };
79
+ res.once("finish", () => finish(true));
80
+ res.once("close", () => finish(false));
81
+ });
82
+ }
83
+ function bundleResponseMiddleware(write, { runLsof, manifests = false } = {}) {
34
84
  return (req, res, next) => {
35
85
  if (req.method === "GET" && req.url === "/_stim/metro-warmup") {
86
+ if (manifests) observeManifestRequests(req.socket.server, write);
36
87
  res.end("ready");
37
88
  return;
38
89
  }
@@ -59,6 +110,7 @@ var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) =
59
110
  requestId,
60
111
  ...progress ?? { statusCode },
61
112
  msg: progress ? `${platform} bundle ${progress.percent}%` : `${platform} bundle ${kind} ${stage}`,
113
+ ...stage === "started" && !prefetch ? { url: `${url.pathname}${url.search}` } : {},
62
114
  ...pid ? { clientPid: pid } : {}
63
115
  });
64
116
  } catch {}
@@ -1,9 +1,9 @@
1
- import { t as getExecutor } from "./exec-DEoAhcze.mjs";
2
- import { n as METRO_COMMAND_PORT } from "./settings-C7O8A6ZI.mjs";
3
- import { T as MODE_COMMAND } from "./project-DhCtQWWU.mjs";
1
+ import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { n as METRO_COMMAND_PORT } from "./settings-B5tCoq9N.mjs";
3
+ import { T as MODE_COMMAND } from "./project-BiC68mIp.mjs";
4
+ import { f as signalProcessTree } from "./metro-1pJgCX4U.mjs";
4
5
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
5
- import { f as signalProcessTree } from "./metro-DiXtA3Ty.mjs";
6
- import { _ as withProjectNode, f as recordFromLine, h as projectNodeLine, v as superviseChildServer } from "./server-expo-BXrWxNYh.mjs";
6
+ import { g as projectNodeLine, p as recordFromLine, v as withProjectNode, y as superviseChildServer } from "./server-expo-Ck8EIidM.mjs";
7
7
  import { join } from "node:path";
8
8
  import { LOG_ROTATE_BYTES } from "@stim-cli/core";
9
9
  //#region src/supervisor/server-command.ts
@@ -0,0 +1,2 @@
1
+ import { m as startExpoServer } from "./server-expo-Ck8EIidM.mjs";
2
+ export { startExpoServer };