stim 1.21.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +60 -7
  2. package/dist/{acquire-artifact-CD4lbiWE.mjs → acquire-artifact-Co2k4f7O.mjs} +21 -3
  3. package/dist/{act-DHAw2A2S.mjs → act-DsuqEkiM.mjs} +298 -164
  4. package/dist/{activity-BzVfHSrY.mjs → activity-CMLmzp7o.mjs} +33 -12
  5. package/dist/{agent-device-usage-output-zh1vhbLp.mjs → agent-device-usage-output-DUFaTMdd.mjs} +7 -7
  6. package/dist/{android-BLgbNqox.mjs → android-ByRMUoiJ.mjs} +66 -52
  7. package/dist/{android-DUYkNF4u.mjs → android-C7sVmyI9.mjs} +160 -59
  8. package/dist/{android-CV_GCELZ.mjs → android-DGkNqa_c.mjs} +5 -5
  9. package/dist/{android-BEJ8Jpl7.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/{android-cas-Ct5b1xCK.mjs → android-cas-ngferVq2.mjs} +3 -3
  12. package/dist/{client-B7QVOlCr.d.mts → android-project-DVWyCbWU.d.mts} +145 -7
  13. package/dist/api.d.mts +132 -118
  14. package/dist/api.mjs +239 -42
  15. package/dist/{artifact-B8T3S5gi.mjs → artifact-8EY8SAPw.mjs} +40 -35
  16. package/dist/{artifact-DAuZ-FNU.mjs → artifact-DJPy518Y.mjs} +69 -40
  17. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  18. package/dist/{browser-web-QQzVjz3O.mjs → browser-web-Bcv99PBM.mjs} +187 -59
  19. package/dist/{budget-Bs6SxxzO.mjs → budget-Cvwn54qV.mjs} +830 -699
  20. package/dist/{build-CoPzQRNw.mjs → build-CabC3G23.mjs} +34 -27
  21. package/dist/{build-cache-DmyR9Zzc.mjs → build-cache-Dv7RN200.mjs} +4 -4
  22. package/dist/{build-plan-CaFskB7_.mjs → build-plan-DUC8Ka9y.mjs} +74 -14
  23. package/dist/{cache-manifest-DkkqguoK.mjs → cache-manifest-DSeQjt-Q.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-BJRZ9pG3.mjs → ccache-Btwc36-I.mjs} +6 -6
  26. package/dist/{cdp-CWmIUMbw.mjs → cdp-3fwICjzi.mjs} +1 -1
  27. package/dist/{chrome-B6tfCta1.mjs → chrome-Bbw689-6.mjs} +1 -1
  28. package/dist/{cli-0DYf8QhQ.mjs → cli-CHZa9Lvk.mjs} +20 -20
  29. package/dist/cli.mjs +1 -1
  30. package/dist/{client-UXD70ZbM.mjs → client-OyRoEuSr.mjs} +218 -47
  31. package/dist/collector-run.d.mts +1 -1
  32. package/dist/collector-run.mjs +6 -6
  33. package/dist/{command-output-B1UrjZHL.mjs → command-output-gwpm28fu.mjs} +1 -1
  34. package/dist/{config-CYcBF478.mjs → config-DlrsduwG.mjs} +17 -11
  35. package/dist/{created-devices-CqeBlrEn.mjs → created-devices-x9rN6bhs.mjs} +13 -3
  36. package/dist/{dependency-state-BbKQW83h.mjs → dependency-state-1I9KZT1Y.mjs} +2 -2
  37. package/dist/{detached-entry-DFRyG1_o.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  38. package/dist/{dev-client-UOeESKm6.mjs → dev-client-BSDR5h3F.mjs} +2 -2
  39. package/dist/{device-ExJq8Ei7.mjs → device-B-L3Fbxy.mjs} +71 -14
  40. package/dist/{device-DCxH7_By.mjs → device-DklWZLqb.mjs} +16 -16
  41. package/dist/{device-capacity-CMlqEcvw.mjs → device-capacity-DK5_EwRS.mjs} +9 -10
  42. package/dist/device-host-worker.mjs +25 -32
  43. package/dist/{device-ios-DRUeKaFV.mjs → device-ios-DoB6KFCO.mjs} +39 -16
  44. package/dist/{device-lease-run-C8raGFoP.mjs → device-lease-run-xJPQ_QQG.mjs} +5 -5
  45. package/dist/{device-pool-DMRpVX9a.mjs → device-pool-BMkdsefq.mjs} +3 -3
  46. package/dist/{doctor-DTvaDOda.mjs → doctor-Bo7BXLux.mjs} +24 -37
  47. package/dist/{doctor-Dhqebm0q.mjs → doctor-D5_EzwfA.mjs} +19 -16
  48. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  49. package/dist/doctor-fingerprint.mjs +1 -1
  50. package/dist/{doctor-BLHCYxzi.mjs → doctor-thjWAV0z.mjs} +1 -1
  51. package/dist/{doctor-watchman-Cv1F10Kj.mjs → doctor-watchman-N2wDotwQ.mjs} +5 -5
  52. package/dist/{eas-build-BomfRnFT.mjs → eas-build-CwknaQYj.mjs} +4 -4
  53. package/dist/{eas-fallback-DJwZpy0c.mjs → eas-fallback-CSgAulr5.mjs} +27 -18
  54. package/dist/{eas-session-ledger-op6A54yi.mjs → eas-session-ledger-DlY_serQ.mjs} +8 -7
  55. package/dist/{error-diagnostics-Bf0rZvG9.mjs → error-diagnostics-DBWO2rxE.mjs} +10 -10
  56. package/dist/{exec-_UbtCQcG.mjs → exec-DEoAhcze.mjs} +155 -47
  57. package/dist/{exec-H20xSg2T.d.mts → exec-DnYc4HGH.d.mts} +17 -4
  58. package/dist/{gc-_-dCXdyL.mjs → gc-CXxN-4SE.mjs} +587 -313
  59. package/dist/gc-DnNDQyaP.mjs +3 -0
  60. package/dist/{guide-Yqwt2bd6.mjs → guide-Br0LEfKy.mjs} +239 -43
  61. package/dist/{hosted-android-Bw-honsd.mjs → hosted-android-B-9f-jkd.mjs} +6 -6
  62. package/dist/{hosted-client-DB_gBPfY.mjs → hosted-client-DZAPrcro.mjs} +4 -4
  63. package/dist/{hosted-ios-CUvOf4Vr.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  64. package/dist/{hosted-logs-DL_P5AdN.mjs → hosted-logs-FIRx9X2f.mjs} +5 -5
  65. package/dist/{hosted-macos-QI141yKk.mjs → hosted-macos-_awYSpfv.mjs} +21 -12
  66. package/dist/{hosted-native-Ksyjgzq-.mjs → hosted-native-BdzE668-.mjs} +27 -14
  67. package/dist/{idle-BVeRGroT.d.mts → idle-C4cZ757K.d.mts} +3 -3
  68. package/dist/{idle-shutdown-DaKmZi0z.mjs → idle-shutdown-DDg3SdvY.mjs} +7 -7
  69. package/dist/ios-CDvlmUs7.d.mts +24 -0
  70. package/dist/{ios-CQ68hG9s.mjs → ios-Ds1clbIt.mjs} +8 -8
  71. package/dist/{ios-device-CwFMehUS.mjs → ios-device--h_-8ENa.mjs} +3 -3
  72. package/dist/{ios-device-CXGP1bsD.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  73. package/dist/{ios-CpByZy12.mjs → ios-hcBpnEGk.mjs} +81 -34
  74. package/dist/{ios-ubFsBzwq.mjs → ios-pm4nL6By.mjs} +59 -50
  75. package/dist/{ios-project-WuwwBdvW.mjs → ios-project-CZhKODF3.mjs} +5 -5
  76. package/dist/{ios-signing-DTTIChGs.mjs → ios-signing-BtAffm0A.mjs} +2 -2
  77. package/dist/{ios-state-DvFX-K_l.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  78. package/dist/{ios-qNJt4dFm.mjs → ios-xtlRHaeB.mjs} +1 -1
  79. package/dist/{js-swap-Cc1dttps.mjs → js-swap-Bwhh4S7V.mjs} +7 -29
  80. package/dist/{launch-Zq2mOSDy.mjs → launch-BjxemNpK.mjs} +40 -39
  81. package/dist/{launch-CD1yVc7U.mjs → launch-CCzXlc8r.mjs} +16 -16
  82. package/dist/{logs-BS00Anxf.mjs → logs-BfwwadsZ.mjs} +151 -24
  83. package/dist/{logs-CMm05HxN.mjs → logs-jTS_lHSo.mjs} +10 -17
  84. package/dist/{macos-B65--pPd.mjs → macos-DVlSSyUg.mjs} +1 -1
  85. package/dist/{macos-C-0qJ6zq.mjs → macos-NfV2D7dO.mjs} +143 -46
  86. package/dist/macos-run.mjs +1 -1
  87. package/dist/maintenance-run.mjs +8 -8
  88. package/dist/{metro-DEXpIhHC.mjs → metro-DiXtA3Ty.mjs} +59 -37
  89. package/dist/{metro-gateway-BMJNlj3E.mjs → metro-gateway-CKZqKqx7.mjs} +120 -22
  90. package/dist/{named-ports-BWTzt6mu.mjs → named-ports-DkEzOfzO.mjs} +40 -33
  91. package/dist/{native-android-JACyjTZs.mjs → native-android-CqgnOgsT.mjs} +43 -242
  92. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  93. package/dist/{native-gradle-inputs-Bep9JcSF.mjs → native-gradle-inputs-Dnh84Zbd.mjs} +3 -129
  94. package/dist/{native-run-DY_RLx3C.mjs → native-run-NwUuxbkg.mjs} +4 -5
  95. package/dist/{native-runtime-Dg1Q7tfF.mjs → native-runtime-B7KIafpM.mjs} +8 -7
  96. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  97. package/dist/{native-xcode-inputs-CB2iQeWq.mjs → native-xcode-inputs-D_VOfFL7.mjs} +2 -3
  98. package/dist/{native-xcode-ios-CXX39F7o.mjs → native-xcode-ios-BYDOHWLN.mjs} +27 -32
  99. package/dist/offload-worker.d.mts +65 -2
  100. package/dist/offload-worker.mjs +305 -73
  101. package/dist/operation-exec-BW0em61G.mjs +171 -0
  102. package/dist/{ownership-DEmM5vhh.mjs → ownership-C5fo5Edb.mjs} +3 -3
  103. package/dist/{page-CPaHeYqj.mjs → page-DBL2PiUU.mjs} +8 -4
  104. package/dist/{placement-log-BqGbTa61.mjs → placement-log-BnGgJRRZ.mjs} +1 -1
  105. package/dist/{plan-placement-Bwj-IjY1.mjs → plan-placement-DIsMtN-d.mjs} +12 -8
  106. package/dist/{ports-D-MmCTdv.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  107. package/dist/{prebuild-uD_ipCxF.mjs → prebuild-D4JoEAEs.mjs} +49 -14
  108. package/dist/{project-BZNjmW_8.mjs → project-wM_XFTvE.mjs} +16 -16
  109. package/dist/{pull-request-Lfetn8Kr.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  110. package/dist/{pull-request-zjCSAryH.d.mts → pull-request-eODyIqZF.d.mts} +6 -2
  111. package/dist/pull-requests.d.mts +2 -2
  112. package/dist/pull-requests.mjs +2 -2
  113. package/dist/{react-native-android-DuzH0cn3.mjs → react-native-android-6OZ7MSM7.mjs} +71 -48
  114. package/dist/{react-native-build-rhk4smwQ.mjs → react-native-build-Dvd8hC21.mjs} +8 -8
  115. package/dist/{react-native-doctor-CQpuIMso.mjs → react-native-doctor-DsoSF1Y9.mjs} +7 -7
  116. package/dist/{react-native-ios-Bhq1rJeV.mjs → react-native-ios-4u1Rn-GR.mjs} +40 -26
  117. package/dist/{recordings-DYteQSu4.mjs → recordings-CQmfzAh7.mjs} +1 -1
  118. package/dist/registration-BcRgF6Ox.mjs +51 -0
  119. package/dist/{reload-CmTRFJaX.mjs → reload-BzkYabB-.mjs} +16 -15
  120. package/dist/{reload-DzjSl5P_.mjs → reload-D7AVlb8N.mjs} +1 -1
  121. package/dist/{remote-ByYkXdGD.mjs → remote-DjGDmlTZ.mjs} +18 -15
  122. package/dist/{result-DNiS-tTP.mjs → result-D2Ykz_iD.mjs} +24 -23
  123. package/dist/{run-D23HmJMs.mjs → run-DidHghD1.mjs} +3 -2
  124. package/dist/{selection-CSl9i5qU.mjs → selection-DSMbWEX2.mjs} +6 -5
  125. package/dist/{server-bare-CxTrvDg8.mjs → server-bare-CafzuyFB.mjs} +2 -2
  126. package/dist/{server-command-CtzloH3v.mjs → server-command-C6QjeupS.mjs} +5 -5
  127. package/dist/{server-expo-DT_F_uVI.mjs → server-expo-CrjB29pq.mjs} +7 -5
  128. package/dist/server-expo-D58c9L0M.mjs +2 -0
  129. package/dist/{settings-CsJDEXgK.mjs → settings-C7O8A6ZI.mjs} +223 -243
  130. package/dist/{settings-T1gtc3bf.mjs → settings-DpR-1Wnn.mjs} +1 -1
  131. package/dist/{settings-write-HyVZ8eQ8.mjs → settings-write-CzD60rOD.mjs} +7 -6
  132. package/dist/settings.schema.json +13 -0
  133. package/dist/{simslim-Cgk17SXV.mjs → simslim-BNckWpXi.mjs} +2 -2
  134. package/dist/{slot-launch-DF8VfT64.mjs → slot-launch-CbfmNgM6.mjs} +6 -6
  135. package/dist/{stage-BIS0ydsV.mjs → stage-Bps5oius.mjs} +21 -4
  136. package/dist/{start-RChynRDp.mjs → start-Br-oxqMD.mjs} +1 -1
  137. package/dist/{start-7lpH7hmN.mjs → start-EojN4WFz.mjs} +622 -393
  138. package/dist/{state-C4ZtUisW.mjs → state--smjFSTL.mjs} +22 -7
  139. package/dist/{state-XMziexv2.mjs → state-08I3hw3_.mjs} +2 -2
  140. package/dist/{stats-53T7OTb9.mjs → stats-D3GerlFW.mjs} +5 -5
  141. package/dist/{stats-report-BFfMpWWF.mjs → stats-report-BzaPrRm6.mjs} +1 -1
  142. package/dist/{status-DqEUSSxs.mjs → status-BRROykC8.mjs} +2 -2
  143. package/dist/{status-CSi6tlRq.mjs → status-EvrK72L2.mjs} +1 -1
  144. package/dist/{status-BL7jVyAB.mjs → status-WBDajew2.mjs} +43 -29
  145. package/dist/{status-watch-GDCfqpTE.mjs → status-watch-Bg_u-pwR.mjs} +48 -16
  146. package/dist/status-worker.mjs +1 -1
  147. package/dist/{stim-desktop-C12we7lz.mjs → stim-desktop-D5OGpYZM.mjs} +2 -2
  148. package/dist/{stop-Bk_1qiV6.mjs → stop-DTZ9uTw3.mjs} +2 -2
  149. package/dist/{stop-D7h6jAXQ.mjs → stop-Dky10AEJ.mjs} +31 -22
  150. package/dist/{stop-CPzlM1L-.mjs → stop-Mv6W9FAk.mjs} +15 -16
  151. package/dist/supervisor-run.d.mts +3 -3
  152. package/dist/supervisor-run.mjs +28 -36
  153. package/dist/{support-Dlu37g6H.mjs → support-CNioewsd.mjs} +10 -10
  154. package/dist/{support-67vraa1Q.mjs → support-yUiOjnVY.mjs} +8 -8
  155. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  156. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  157. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  158. package/dist/{toolchain-Hp9sCpK4.mjs → toolchain-DpJMHq0n.mjs} +9 -6
  159. package/dist/{trigger-BAahxUPq.mjs → trigger-Cbyc41d_.mjs} +3 -3
  160. package/dist/trigger-yb_nFzPF.mjs +2 -0
  161. package/dist/{warm-progress-BHX5r0Ei.mjs → warm-progress-CA3TgT3-.mjs} +29 -16
  162. package/dist/web-CZ07gd77.mjs +2 -0
  163. package/dist/{web-CJmIj6AI.mjs → web-DKx6yoFA.mjs} +11 -10
  164. package/dist/web-run.mjs +11 -9
  165. package/dist/windows-report.mjs +1 -1
  166. package/dist/{workspace-state-Cjuigeeu.mjs → workspace-state-U08dEzhG.mjs} +3 -3
  167. package/dist/{workspaces-BccMFmGQ.mjs → workspaces-CpANmBlq.mjs} +594 -266
  168. package/dist/{worktree-DQ6Zi2Mv.mjs → worktree-CHecZ4Oq.mjs} +850 -551
  169. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  170. package/dist/{xcode-Zlx3qjEs.mjs → xcode-BXn9-xYx.mjs} +5 -5
  171. package/package.json +7 -7
  172. package/shim/android-audio/Main.java +24 -0
  173. package/shim/android-audio/README.md +17 -0
  174. package/shim/android-audio.jar +0 -0
  175. package/dist/gc-C-WwL0yi.mjs +0 -3
  176. package/dist/git-C3iTsJaZ.mjs +0 -73
  177. package/dist/server-expo-C-90EhcG.mjs +0 -2
  178. package/dist/settings-DkdmlelE.d.mts +0 -15
  179. package/dist/swiftpm-macos-p8WZbxKU.mjs +0 -130
  180. package/dist/toolchain-DhKwp9iI.mjs +0 -2
  181. package/dist/trigger-Bf3uDcpv.mjs +0 -2
  182. package/dist/web-DknQETPs.mjs +0 -2
  183. package/dist/workspace-process-lock-1_1OoVW5.mjs +0 -57
  184. package/dist/worktree-CK2MpJW5.mjs +0 -2
@@ -1,11 +1,108 @@
1
- import { p as process_identity_exports } from "./exec-_UbtCQcG.mjs";
2
- import { st as tailscaleStatusAsync } from "./config-CYcBF478.mjs";
3
- import { l as withWorkspaceStateLockAsync, o as updateWorkspaceState, r as readWorkspaceState$1, s as updateWorkspaceStateAsync } from "./workspace-state-Cjuigeeu.mjs";
4
- import { Qt as cancellableSleep, en as throwIfCancelled } from "./settings-CsJDEXgK.mjs";
1
+ import { g as process_identity_exports } from "./exec-DEoAhcze.mjs";
2
+ import { g as workspaceStateFile$1 } from "./paths-DQtTgsBf.mjs";
3
+ import { ot as tailscaleStatusAsync } from "./config-DlrsduwG.mjs";
4
+ import { d as cancelledError, f as throwIfCancelled } from "./operation-exec-BW0em61G.mjs";
5
+ import { l as withWorkspaceStateLockAsync, o as updateWorkspaceState, r as readWorkspaceState$1, s as updateWorkspaceStateAsync } from "./workspace-state-U08dEzhG.mjs";
5
6
  import { randomBytes, randomUUID } from "node:crypto";
7
+ import { statSync, watch } from "node:fs";
6
8
  import { HOSTED_METRO_REQUESTS_KEY, findPeer, hostedMetroGateways, hostedMetroRequests, isJsonObject, parseMachine } from "@stim-cli/core/state";
7
9
  import { isIP } from "node:net";
10
+ //#region src/workspace/workspace-state-watch.ts
11
+ /** Filesystem events are hints; callers retain their own bounded repair and state verification. */
12
+ function watchWorkspaceState(root, changed) {
13
+ let stopped = false;
14
+ let current;
15
+ let startup;
16
+ const clear = () => {
17
+ clearTimeout(startup);
18
+ const previous = current;
19
+ current = void 0;
20
+ previous?.watcher.close();
21
+ };
22
+ const refresh = () => {
23
+ if (stopped) return;
24
+ try {
25
+ const file = workspaceStateFile$1(root);
26
+ const stat = statSync(file);
27
+ if (current?.dev === stat.dev && current.ino === stat.ino) return;
28
+ clear();
29
+ const watcher = watch(file, { persistent: false }, () => {
30
+ if (stopped || current?.watcher !== watcher) return;
31
+ refresh();
32
+ changed();
33
+ });
34
+ current = {
35
+ watcher,
36
+ dev: stat.dev,
37
+ ino: stat.ino
38
+ };
39
+ const lost = () => {
40
+ if (current?.watcher === watcher) clear();
41
+ };
42
+ watcher.once("error", lost);
43
+ watcher.once("close", lost);
44
+ startup = setTimeout(() => {
45
+ if (stopped) return;
46
+ refresh();
47
+ changed();
48
+ }, 500);
49
+ } catch {
50
+ clear();
51
+ }
52
+ };
53
+ refresh();
54
+ return {
55
+ refresh,
56
+ close: () => {
57
+ stopped = true;
58
+ clear();
59
+ }
60
+ };
61
+ }
62
+ //#endregion
8
63
  //#region src/device-host/metro-gateway.ts
64
+ async function waitForGateway(root, read, { waitMs, signal, what }) {
65
+ throwIfCancelled(signal, what);
66
+ const startedAt = Date.now();
67
+ const deadline = startedAt + waitMs;
68
+ let observer;
69
+ let timer;
70
+ let queued;
71
+ let onAbort;
72
+ try {
73
+ return await new Promise((resolve, reject) => {
74
+ const check = () => {
75
+ clearImmediate(queued);
76
+ queued = void 0;
77
+ clearTimeout(timer);
78
+ try {
79
+ throwIfCancelled(signal, what);
80
+ observer?.refresh();
81
+ const result = read();
82
+ const remaining = deadline - Date.now();
83
+ if (result !== null || remaining <= 0) resolve(result);
84
+ else {
85
+ const repairMs = Date.now() - startedAt < 500 ? 100 : 1e3;
86
+ timer = setTimeout(check, Math.min(remaining, repairMs));
87
+ }
88
+ } catch (error) {
89
+ reject(error);
90
+ }
91
+ };
92
+ onAbort = () => reject(cancelledError(what));
93
+ signal?.addEventListener("abort", onAbort, { once: true });
94
+ observer = watchWorkspaceState(root, () => {
95
+ queued ??= setImmediate(check);
96
+ });
97
+ check();
98
+ });
99
+ } finally {
100
+ observer?.close();
101
+ clearTimeout(timer);
102
+ clearImmediate(queued);
103
+ if (onAbort) signal?.removeEventListener("abort", onAbort);
104
+ }
105
+ }
9
106
  function gatewayAddresses(credential, status) {
10
107
  const machine = parseMachine(credential.machine);
11
108
  const peer = machine ? findPeer(status, machine.name) : "missing";
@@ -46,9 +143,7 @@ async function requestHostedMetro(root, session, credential, signal) {
46
143
  [session]: request
47
144
  }
48
145
  }), signal);
49
- const deadline = Date.now() + 15e3;
50
- while (Date.now() < deadline) {
51
- throwIfCancelled(signal, "hosted Metro gateway");
146
+ const opened = await waitForGateway(root, () => {
52
147
  const state = readWorkspaceState$1(root);
53
148
  const gateway = hostedMetroGateways(state)[session];
54
149
  if (gateway?.id === request.id && gateway.processToken === state?.supervisor?.processToken) {
@@ -58,11 +153,13 @@ async function requestHostedMetro(root, session, credential, signal) {
58
153
  secret: request.secret
59
154
  };
60
155
  }
61
- await cancellableSleep(100, {
62
- signal,
63
- what: "hosted Metro gateway"
64
- });
65
- }
156
+ return null;
157
+ }, {
158
+ waitMs: 15e3,
159
+ signal,
160
+ what: "hosted Metro gateway"
161
+ });
162
+ if (opened) return opened;
66
163
  throw new Error(`The Metro supervisor did not open a private gateway for ${credential.machine}. Run stim stop; stim start, then retry.`);
67
164
  }
68
165
  function clearHostedMetro(root, session) {
@@ -75,18 +172,19 @@ function clearHostedMetro(root, session) {
75
172
  };
76
173
  });
77
174
  }
78
- async function closeHostedMetro(root, session) {
79
- await withWorkspaceStateLockAsync(root, () => clearHostedMetro(root, session));
80
- const deadline = Date.now() + 5e3;
81
- while (true) {
175
+ async function closeHostedMetro(root, session, signal) {
176
+ await withWorkspaceStateLockAsync(root, () => clearHostedMetro(root, session), signal);
177
+ if (!await waitForGateway(root, () => {
82
178
  const state = readWorkspaceState$1(root);
83
179
  const gateway = hostedMetroGateways(state)[session];
84
180
  const supervisor = state?.supervisor;
85
- if (!gateway?.port || !supervisor || gateway.processToken !== supervisor.processToken) return;
86
- if ((0, process_identity_exports.inspectProcessIdentity)(supervisor) === "gone") return;
87
- if (Date.now() >= deadline) throw new Error("The Metro supervisor did not close its private gateway. Restart Metro, then retry stim stop.");
88
- await new Promise((done) => setTimeout(done, 100));
89
- }
181
+ if (!gateway?.port || !supervisor || gateway.processToken !== supervisor.processToken) return true;
182
+ return (0, process_identity_exports.inspectProcessIdentity)(supervisor) === "gone" ? true : null;
183
+ }, {
184
+ waitMs: 5e3,
185
+ signal,
186
+ what: "close hosted Metro"
187
+ })) throw new Error("The Metro supervisor did not close its private gateway. Restart Metro, then retry stim stop.");
90
188
  }
91
189
  function hostedMetroSettings(settings, hosted) {
92
190
  return hosted ? {
@@ -108,4 +206,4 @@ function hostedMetroSettings(settings, hosted) {
108
206
  } : settings;
109
207
  }
110
208
  //#endregion
111
- export { requireHostedMetro as a, requestHostedMetro as i, closeHostedMetro as n, hostedMetroSettings as r, clearHostedMetro as t };
209
+ export { requireHostedMetro as a, requestHostedMetro as i, closeHostedMetro as n, watchWorkspaceState as o, hostedMetroSettings as r, clearHostedMetro as t };
@@ -1,7 +1,6 @@
1
- import { p as process_identity_exports, t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
- import { C as saveConfig, O as withConfigLockAsync, _ as loadConfig, c as ensureConfig, d as getConfigDir, p as getProject } from "./config-CYcBF478.mjs";
3
- import { c as parseNetstatPids, h as createPortProbe, p as signalProcessTree } from "./metro-DEXpIhHC.mjs";
4
- import { t as withWorkspaceProcessLock } from "./workspace-process-lock-1_1OoVW5.mjs";
1
+ import { g as process_identity_exports, i as withWorkspaceProcessLock, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { C as saveConfig, O as withConfigLockAsync, _ as loadConfig, c as ensureConfig, d as getConfigDir, p as getProject } from "./config-DlrsduwG.mjs";
3
+ import { f as signalProcessTree, m as createPortProbe, s as parseNetstatPids } from "./metro-DiXtA3Ty.mjs";
5
4
  import { realpathSync } from "node:fs";
6
5
  //#region src/named-ports.ts
7
6
  const FIRST_PORT = 8900;
@@ -57,8 +56,11 @@ function processCommand(pid, platform) {
57
56
  "args="
58
57
  ], { timeoutMs: 5e3 }) ?? "").trim();
59
58
  }
60
- function withPortsLock(fn) {
61
- return withWorkspaceProcessLock(getConfigDir(), "ports", fn, { external: true });
59
+ function withPortsLock(fn, signal) {
60
+ return withWorkspaceProcessLock(getConfigDir(), "ports", fn, {
61
+ external: true,
62
+ signal
63
+ });
62
64
  }
63
65
  async function getNamedPort(projectPath, label, options = {}) {
64
66
  validatePortLabel(label);
@@ -68,14 +70,14 @@ async function getNamedPort(projectPath, label, options = {}) {
68
70
  function reserveBrowserPort(projectPath, options = {}) {
69
71
  return allocateNamedPort(projectPath, BROWSER_LABEL, options);
70
72
  }
71
- function releaseBrowserPort(projectPath, port) {
72
- return withPortsLock(async () => withConfigLockAsync(() => {
73
+ function releaseBrowserPort(projectPath, port, signal) {
74
+ return withPortsLock(() => withConfigLockAsync(() => {
73
75
  const cfg = loadConfig();
74
76
  const ports = cfg?.projects?.[projectPath]?.ports;
75
77
  if (!cfg || ports?.[BROWSER_LABEL] !== port) return;
76
78
  delete ports[BROWSER_LABEL];
77
79
  saveConfig(cfg);
78
- }));
80
+ }, signal), signal);
79
81
  }
80
82
  async function allocateNamedPort(projectPath, label, { isFree = createPortProbe() }) {
81
83
  const root = realpathSync(projectPath);
@@ -103,9 +105,10 @@ async function allocateNamedPort(projectPath, label, { isFree = createPortProbe(
103
105
  throw new Error(`No free named port between ${FIRST_PORT} and ${LAST_PORT}. Use stim ports stop or stim ports release in a workspace that no longer needs its ports.`);
104
106
  });
105
107
  }
106
- async function stopListeners(port, label, dryRun, log, platform) {
108
+ async function stopListeners(port, label, dryRun, log, platform, signal) {
107
109
  const listeners = () => portListeners(port, platform);
108
110
  for (const pid of listeners()) {
111
+ signal?.throwIfAborted();
109
112
  if (pid === process.pid) throw new Error(`Refusing to stop Stim itself on ${label} (${port}).`);
110
113
  const identity = (0, process_identity_exports.captureProcessIdentity)(pid);
111
114
  if (!identity.ok) {
@@ -127,10 +130,10 @@ async function stopListeners(port, label, dryRun, log, platform) {
127
130
  if (status !== "same") throw new Error(`Cannot verify pid ${pid} on ${label} (${port}); allocation kept.`);
128
131
  try {
129
132
  signalProcessTree(pid, "SIGTERM", { platform });
130
- if (!await (0, process_identity_exports.waitForProcessExit)(record, 2e3)) {
133
+ if (!await (0, process_identity_exports.waitForProcessExit)(record, 2e3, signal)) {
131
134
  if ((0, process_identity_exports.inspectProcessIdentity)(record) !== "same") throw new Error(`Cannot verify pid ${pid} before SIGKILL.`);
132
135
  signalProcessTree(pid, "SIGKILL", { platform });
133
- if (!await (0, process_identity_exports.waitForProcessExit)(record, 2e3)) throw new Error(`Pid ${pid} did not exit.`);
136
+ if (!await (0, process_identity_exports.waitForProcessExit)(record, 2e3, signal)) throw new Error(`Pid ${pid} did not exit.`);
134
137
  }
135
138
  } catch (error) {
136
139
  if (error.code !== "ESRCH") throw error;
@@ -139,36 +142,40 @@ async function stopListeners(port, label, dryRun, log, platform) {
139
142
  }
140
143
  if (!dryRun && listeners().length) throw new Error(`Port ${port} still has a listener; allocation kept.`);
141
144
  }
142
- async function clearNamedPorts(projectPath, { label, stop = false, dryRun = false, log = console.error, platform = process.platform } = {}) {
145
+ async function clearNamedPorts(projectPath, { label, stop = false, dryRun = false, log = console.error, platform = process.platform, signal } = {}) {
143
146
  if (label !== void 0) validatePortLabel(label);
144
147
  await withPortsLock(async () => {
145
148
  const ports = getProject(projectPath)?.ports ?? {};
146
149
  const selected = Object.entries(ports).filter(([name]) => name !== BROWSER_LABEL && (label === void 0 || name === label));
147
150
  if (stop && selected.length > 0 && platform !== "win32" && !getExecutor().findExecutable("lsof")) throw new Error("Cannot stop named ports: lsof is not installed.");
148
151
  const failures = [];
149
- for (const [name, port] of selected) try {
150
- if (!Number.isInteger(port) || port < FIRST_PORT || port > LAST_PORT) throw new Error(`Invalid named port ${name} (${port}); repair its config record before cleanup.`);
151
- if (stop) {
152
- if (Object.values(loadConfig()?.projects ?? {}).some((project) => project.metroPort === port)) throw new Error(`Port ${port} is reserved for managed Metro; allocation kept.`);
153
- await stopListeners(port, name, dryRun, log, platform);
154
- }
155
- if (dryRun) {
156
- log(`would release ${name} (${port})`);
157
- continue;
152
+ for (const [name, port] of selected) {
153
+ signal?.throwIfAborted();
154
+ try {
155
+ if (!Number.isInteger(port) || port < FIRST_PORT || port > LAST_PORT) throw new Error(`Invalid named port ${name} (${port}); repair its config record before cleanup.`);
156
+ if (stop) {
157
+ if (Object.values(loadConfig()?.projects ?? {}).some((project) => project.metroPort === port)) throw new Error(`Port ${port} is reserved for managed Metro; allocation kept.`);
158
+ await stopListeners(port, name, dryRun, log, platform, signal);
159
+ }
160
+ if (dryRun) {
161
+ log(`would release ${name} (${port})`);
162
+ continue;
163
+ }
164
+ await withConfigLockAsync(() => {
165
+ const cfg = loadConfig();
166
+ const current = cfg?.projects?.[projectPath]?.ports;
167
+ if (!cfg || current?.[name] !== port) return;
168
+ delete current[name];
169
+ saveConfig(cfg);
170
+ }, signal);
171
+ log(`released ${name} (${port})`);
172
+ } catch (error) {
173
+ signal?.throwIfAborted();
174
+ failures.push(`${name} (${port}): ${error.message}`);
158
175
  }
159
- await withConfigLockAsync(() => {
160
- const cfg = loadConfig();
161
- const current = cfg?.projects?.[projectPath]?.ports;
162
- if (!cfg || current?.[name] !== port) return;
163
- delete current[name];
164
- saveConfig(cfg);
165
- });
166
- log(`released ${name} (${port})`);
167
- } catch (error) {
168
- failures.push(`${name} (${port}): ${error.message}`);
169
176
  }
170
177
  if (failures.length) throw new Error(failures.join("\n"));
171
- });
178
+ }, signal);
172
179
  }
173
180
  //#endregion
174
181
  export { reserveBrowserPort as i, getNamedPort as n, releaseBrowserPort as r, clearNamedPorts as t };