stim 1.20.2 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +141 -8
  2. package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
  3. package/dist/act-DsuqEkiM.mjs +2801 -0
  4. package/dist/activity-CMLmzp7o.mjs +1397 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
  6. package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
  7. package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
  8. package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
  9. package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +2 -2
  11. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/android-project-DVWyCbWU.d.mts +391 -0
  14. package/dist/api.d.mts +810 -64
  15. package/dist/api.mjs +782 -1
  16. package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
  17. package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
  18. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  19. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
  20. package/dist/budget-Cvwn54qV.mjs +9285 -0
  21. package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
  22. package/dist/build-cache-Dv7RN200.mjs +602 -0
  23. package/dist/build-plan-DUC8Ka9y.mjs +248 -0
  24. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
  25. package/dist/cache-manifest.mjs +1 -1
  26. package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
  27. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
  28. package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
  29. package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
  30. package/dist/cli.mjs +1 -1
  31. package/dist/client-OyRoEuSr.mjs +1577 -0
  32. package/dist/collector-run.d.mts +4 -40
  33. package/dist/collector-run.mjs +9 -8
  34. package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
  35. package/dist/config-DlrsduwG.mjs +955 -0
  36. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
  37. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
  38. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  39. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
  40. package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
  41. package/dist/device-DklWZLqb.mjs +1068 -0
  42. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
  43. package/dist/device-host-worker.mjs +76 -79
  44. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
  45. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
  46. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
  49. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  50. package/dist/doctor-fingerprint.mjs +19 -0
  51. package/dist/doctor-thjWAV0z.mjs +2 -0
  52. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
  53. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
  54. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
  55. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
  56. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
  57. package/dist/exec-DEoAhcze.mjs +858 -0
  58. package/dist/exec-DnYc4HGH.d.mts +78 -0
  59. package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
  60. package/dist/gc-DnNDQyaP.mjs +3 -0
  61. package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
  62. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
  63. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
  64. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  65. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
  66. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
  67. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
  68. package/dist/idle-C4cZ757K.d.mts +24 -0
  69. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
  70. package/dist/ios-CDvlmUs7.d.mts +24 -0
  71. package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
  73. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  74. package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
  75. package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
  76. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
  77. package/dist/ios-signing-BtAffm0A.mjs +489 -0
  78. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  79. package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
  80. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
  81. package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
  82. package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
  83. package/dist/logs-BfwwadsZ.mjs +479 -0
  84. package/dist/logs-jTS_lHSo.mjs +248 -0
  85. package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
  86. package/dist/macos-NfV2D7dO.mjs +694 -0
  87. package/dist/macos-run.mjs +1 -1
  88. package/dist/maintenance-run.mjs +123 -248
  89. package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
  90. package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
  91. package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
  92. package/dist/native-android-CqgnOgsT.mjs +645 -0
  93. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  94. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
  95. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  96. package/dist/native-run-NwUuxbkg.mjs +276 -0
  97. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
  98. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  99. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
  100. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
  101. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  102. package/dist/offload-worker.d.mts +59 -41
  103. package/dist/offload-worker.mjs +478 -115
  104. package/dist/operation-exec-BW0em61G.mjs +171 -0
  105. package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
  106. package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
  107. package/dist/paths-BsJMoPP2.mjs +12 -0
  108. package/dist/paths-DQtTgsBf.mjs +42 -0
  109. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
  110. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
  111. package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  112. package/dist/prebuild-D4JoEAEs.mjs +484 -0
  113. package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
  114. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  115. package/dist/pull-request-eODyIqZF.d.mts +124 -0
  116. package/dist/pull-requests.d.mts +2 -120
  117. package/dist/pull-requests.mjs +2 -2
  118. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
  119. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
  120. package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
  121. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
  122. package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
  123. package/dist/registration-BcRgF6Ox.mjs +51 -0
  124. package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
  125. package/dist/reload-D7AVlb8N.mjs +2 -0
  126. package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
  127. package/dist/result-D2Ykz_iD.mjs +435 -0
  128. package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
  129. package/dist/selection-DSMbWEX2.mjs +620 -0
  130. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
  131. package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
  132. package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
  133. package/dist/server-expo-D58c9L0M.mjs +2 -0
  134. package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
  135. package/dist/settings-DpR-1Wnn.mjs +114 -0
  136. package/dist/settings-write-CzD60rOD.mjs +360 -0
  137. package/dist/settings.schema.json +176 -16
  138. package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
  139. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
  140. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  141. package/dist/stage-Bps5oius.mjs +200 -0
  142. package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
  143. package/dist/start-EojN4WFz.mjs +1364 -0
  144. package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
  145. package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
  146. package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
  147. package/dist/stats-report-BzaPrRm6.mjs +16 -0
  148. package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
  149. package/dist/status-EvrK72L2.mjs +2 -0
  150. package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
  151. package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
  152. package/dist/status-worker.d.mts +1 -0
  153. package/dist/status-worker.mjs +19 -0
  154. package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
  155. package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
  156. package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
  157. package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
  158. package/dist/supervisor-run.d.mts +8 -17
  159. package/dist/supervisor-run.mjs +56 -28
  160. package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
  161. package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
  162. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  163. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  164. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  165. package/dist/toolchain-DpJMHq0n.mjs +876 -0
  166. package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
  167. package/dist/trigger-yb_nFzPF.mjs +2 -0
  168. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
  169. package/dist/web-CZ07gd77.mjs +2 -0
  170. package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
  171. package/dist/web-run.mjs +13 -12
  172. package/dist/windows-report.d.mts +1 -0
  173. package/dist/windows-report.mjs +18 -0
  174. package/dist/windows-report.ps1 +43 -0
  175. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
  176. package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
  177. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
  178. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  179. package/dist/xcode-BXn9-xYx.mjs +896 -0
  180. package/package.json +7 -5
  181. package/shim/android-audio/Main.java +24 -0
  182. package/shim/android-audio/README.md +17 -0
  183. package/shim/android-audio.jar +0 -0
  184. package/shim/android-optimizations.gradle +7 -5
  185. package/dist/activity-BSV745Kz.mjs +0 -629
  186. package/dist/api-qvOzWyfO.mjs +0 -154
  187. package/dist/api-run.mjs +0 -294
  188. package/dist/app-install-BIKtMfPq.mjs +0 -896
  189. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  190. package/dist/budget-f7516Zk0.mjs +0 -4106
  191. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  192. package/dist/cancellation-C_22VQTH.mjs +0 -24
  193. package/dist/client-qQAaXSUs.mjs +0 -1771
  194. package/dist/config-BYDxlMY3.mjs +0 -562
  195. package/dist/device-DuiPJQSn.mjs +0 -290
  196. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  197. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  198. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  199. package/dist/exec-DqKo9GKJ.mjs +0 -268
  200. package/dist/git-DDfFzkMm.mjs +0 -45
  201. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  202. package/dist/logs-BGrEUaEs.mjs +0 -383
  203. package/dist/macos-Ch5VJmcS.mjs +0 -584
  204. package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
  205. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  206. package/dist/native-android-D5qc3-_v.mjs +0 -226
  207. package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
  208. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  209. package/dist/plan-C4TjdPsR.mjs +0 -260
  210. package/dist/prebuild-DYbucPXy.mjs +0 -212
  211. package/dist/preview-78a9kR_-.mjs +0 -1011
  212. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  213. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  214. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  215. package/dist/result-CaJg5Iat.mjs +0 -186
  216. package/dist/server-expo-Bigriskl.mjs +0 -2
  217. package/dist/settings-BORNaaCO.mjs +0 -402
  218. package/dist/settings-vk3mJGSm.d.mts +0 -13
  219. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  220. package/dist/stage-KNTQopqv.mjs +0 -157
  221. package/dist/start-BWqzODpb.mjs +0 -1116
  222. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  223. package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
  224. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  225. package/dist/toolchain-BFkAcstd.mjs +0 -2
  226. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  227. package/dist/trigger-9_USgmxz.mjs +0 -2
  228. package/dist/web-Dq-i3wzJ.mjs +0 -2
  229. package/dist/worktree-DpLdCHga.mjs +0 -2
  230. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  231. package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
@@ -0,0 +1,114 @@
1
+ import { a as layerFile, c as settingEntry, i as SettingsRefusal, n as readScope, o as readSettingsContext, r as requireSetting, s as readSettingsPayload, t as mutateSetting } from "./settings-write-CzD60rOD.mjs";
2
+ import { SETTING_SCOPES } from "@stim-cli/core/state";
3
+ import chalk from "chalk";
4
+ //#region src/commands/settings.ts
5
+ function formatValue(value) {
6
+ return typeof value === "string" ? value : JSON.stringify(value);
7
+ }
8
+ function formatOrigin(entry) {
9
+ if (entry.origin === null) return "unset";
10
+ return entry.defaultReason ? `${entry.origin}: ${entry.defaultReason}` : entry.origin;
11
+ }
12
+ const CONSOLE = {
13
+ out: (line) => console.log(line),
14
+ note: (line) => console.error(line)
15
+ };
16
+ async function run(json, io, action) {
17
+ try {
18
+ await action();
19
+ } catch (error) {
20
+ const code = error.code;
21
+ if (!(error instanceof SettingsRefusal) && !(typeof code === "string" && code.startsWith("STIM_"))) throw error;
22
+ const failure = {
23
+ code,
24
+ message: error.message,
25
+ remedy: error instanceof SettingsRefusal ? error.remedy : null
26
+ };
27
+ io.note(chalk.red(`${failure.code}: ${failure.message}`));
28
+ if (failure.remedy) io.note(chalk.dim(failure.remedy));
29
+ if (json) io.out(JSON.stringify(failure));
30
+ process.exitCode = 1;
31
+ }
32
+ }
33
+ function wantsJson(opts, command) {
34
+ return Boolean(opts.json ?? command.parent?.opts().json);
35
+ }
36
+ function registerSettings(program, io = CONSOLE, env = process.env) {
37
+ const settings = program.command("settings").description("Show every Stim setting with its effective value and layer, or change one").option("--json", "print every setting, its origin, and each layer value as JSON").action((opts) => run(Boolean(opts.json), io, async () => {
38
+ const payload = await readSettingsPayload(await readSettingsContext(process.cwd(), env, io.note));
39
+ if (opts.json) {
40
+ io.out(JSON.stringify(payload));
41
+ return;
42
+ }
43
+ const width = Math.max(...payload.settings.map((entry) => entry.key.length));
44
+ for (const entry of payload.settings) {
45
+ const shown = entry.origin === null ? "" : formatValue(entry.value);
46
+ io.out(`${entry.key.padEnd(width)} ${shown}${shown ? " " : ""}${chalk.dim(`(${formatOrigin(entry)})`)}`);
47
+ }
48
+ for (const entry of payload.unknown) io.note(chalk.yellow(`Warning: ${entry.key} in ${entry.file} is not read by Stim.`));
49
+ }));
50
+ settings.command("get <key>").description("Print the effective value of a setting, or its value in one layer").option("--scope <scope>", `read one layer: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the setting entry as JSON").action((key, opts, command) => run(wantsJson(opts, command), io, async () => {
51
+ const setting = requireSetting(key);
52
+ const scope = opts.scope === void 0 ? null : readScope(opts.scope, setting);
53
+ const context = await readSettingsContext(process.cwd(), env, io.note);
54
+ const entry = settingEntry(context, setting);
55
+ const value = scope ? entry.layers[scope] ?? null : entry.value;
56
+ if (wantsJson(opts, command)) {
57
+ io.out(JSON.stringify(scope ? {
58
+ key,
59
+ scope,
60
+ file: layerFile(context, scope, setting),
61
+ value
62
+ } : entry));
63
+ return;
64
+ }
65
+ if (value === null) return;
66
+ io.out(formatValue(value));
67
+ if (!scope && entry.defaultReason) io.note(chalk.dim(`(${formatOrigin(entry)})`));
68
+ }));
69
+ settings.command("set <key> <value>").description("Write a setting to one layer").option("--scope <scope>", `the layer to write: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the written setting as JSON").action((key, raw, opts, command) => run(wantsJson(opts, command), io, async () => {
70
+ const result = await mutateSetting({
71
+ action: "set",
72
+ key,
73
+ value: raw,
74
+ scope: opts.scope
75
+ }, {
76
+ cwd: process.cwd(),
77
+ env,
78
+ note: io.note
79
+ });
80
+ report(io, wantsJson(opts, command), result, "set");
81
+ }));
82
+ settings.command("unset <key>").description("Remove a setting from one layer").option("--scope <scope>", `the layer to clear: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the setting after removal as JSON").action((key, opts, command) => run(wantsJson(opts, command), io, async () => {
83
+ const result = await mutateSetting({
84
+ action: "unset",
85
+ key,
86
+ scope: opts.scope
87
+ }, {
88
+ cwd: process.cwd(),
89
+ env,
90
+ note: io.note
91
+ });
92
+ report(io, wantsJson(opts, command), result, "unset");
93
+ }));
94
+ }
95
+ function report(io, json, result, verb) {
96
+ const { setting: entry, recordingsDeleted, ...write } = result;
97
+ if (json) {
98
+ io.out(JSON.stringify(result));
99
+ return;
100
+ }
101
+ for (const workspace of recordingsDeleted ?? []) io.note(`Deleted the device recordings of ${workspace}.`);
102
+ const effective = entry.origin === null ? "unset" : `${formatValue(entry.value)} (${formatOrigin(entry)})`;
103
+ if (!write.changed) {
104
+ io.out(`${write.key} was not set in ${write.file}; effective value: ${effective}`);
105
+ return;
106
+ }
107
+ const shown = verb === "set" ? ` = ${formatValue(entry.layers[write.scope])}` : "";
108
+ io.out(`${verb} ${write.key}${shown} in ${write.file}; effective value: ${effective}`);
109
+ }
110
+ function settingsCommand(program) {
111
+ registerSettings(program);
112
+ }
113
+ //#endregion
114
+ export { settingsCommand as default, registerSettings };
@@ -0,0 +1,360 @@
1
+ import { i as withWorkspaceProcessLock } from "./exec-DEoAhcze.mjs";
2
+ import { A as writeConfigSettingAsync, O as withConfigLockAsync$1, _ as loadConfig$1, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-DlrsduwG.mjs";
3
+ import { a as killOnAbort, i as gitPath } from "./operation-exec-BW0em61G.mjs";
4
+ import { it as unknownSettingKeys, z as readCommittedSettings } from "./settings-C7O8A6ZI.mjs";
5
+ import { r as findCommandWorkspaceAsync, t as NO_PROJECT_REFUSAL } from "./project-wM_XFTvE.mjs";
6
+ import { i as stimDesktopInstalledAsync, n as settingDefault, r as stimDesktopInstalled } from "./stim-desktop-D5OGpYZM.mjs";
7
+ import { n as recordingLayers, t as deleteTurnedOffRecordings } from "./recordings-CQmfzAh7.mjs";
8
+ import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { configDir } from "@stim-cli/core";
11
+ import { SETTINGS, SETTING_SCOPES, coerceSettingText, isJsonObject, isSensitiveReference, settingDefinition, settingValueError } from "@stim-cli/core/state";
12
+ //#region src/workspace/settings-payload.ts
13
+ const MASK = "********";
14
+ const PRECEDENCE = [
15
+ "workspace",
16
+ "repo",
17
+ "committed",
18
+ "machine"
19
+ ];
20
+ var SettingsRefusal = class extends Error {
21
+ code;
22
+ remedy;
23
+ constructor(code, message, remedy) {
24
+ super(message);
25
+ this.code = code;
26
+ this.remedy = remedy;
27
+ }
28
+ };
29
+ /** Reads layers using exactly `env`; `signal` kills Git children. `resolvedProject` pins a mutation's readback target. */
30
+ async function readSettingsContext(cwd, env, note = () => {}, signal, resolvedProject) {
31
+ const repoRootOf = (dir) => gitPath(dir, ["--show-toplevel"], env, signal);
32
+ const projectPath = resolvedProject === void 0 ? await findCommandWorkspaceAsync(cwd, repoRootOf, note) : resolvedProject;
33
+ const start = projectPath ?? cwd;
34
+ const [common, root] = await Promise.all([gitPath(start, ["--path-format=absolute", "--git-common-dir"], env, signal), repoRootOf(start)]);
35
+ signal?.throwIfAborted();
36
+ const repoRoot = common ? root ?? projectPath : null;
37
+ const app = projectPath ?? repoRoot;
38
+ const repository = repoRoot ?? projectPath;
39
+ const committed = readCommittedSettings(app);
40
+ let installed;
41
+ return {
42
+ projectPath,
43
+ gitCommonDir: common,
44
+ repoRoot,
45
+ machine: loadConfig$1(),
46
+ workspace: projectPath ? getProjectSettings(projectPath) : {},
47
+ repo: common ? getRepoSettings(common) : {},
48
+ committed: {
49
+ app: committed,
50
+ repository: repository === app ? committed : readCommittedSettings(repository)
51
+ },
52
+ env,
53
+ desktopInstalled: () => installed ??= stimDesktopInstalled(process.platform, env)
54
+ };
55
+ }
56
+ function valueAt(settings, key) {
57
+ let node = settings;
58
+ for (const segment of key.split(".")) {
59
+ if (!isJsonObject(node)) return void 0;
60
+ node = node[segment];
61
+ }
62
+ return node;
63
+ }
64
+ function committedDirectory(context, setting) {
65
+ return setting?.committedAt === "repository" ? repositoryDirectory(context) : appDirectory(context);
66
+ }
67
+ function repositoryDirectory(context) {
68
+ return context.repoRoot ?? context.projectPath;
69
+ }
70
+ function appDirectory(context) {
71
+ return context.projectPath ?? context.repoRoot;
72
+ }
73
+ function layerFile(context, scope, setting) {
74
+ const machineFile = getConfigPath$1();
75
+ if (scope === "machine") return machineFile;
76
+ if (scope === "workspace") return context.projectPath ? `${machineFile} (projects["${context.projectPath}"].settings)` : null;
77
+ if (scope === "repo") return context.gitCommonDir ? `${machineFile} (repos["${context.gitCommonDir}"].settings)` : null;
78
+ const directory = committedDirectory(context, setting);
79
+ return directory ? join(directory, ".stim.json") : null;
80
+ }
81
+ function layerSettings(context, scope, setting) {
82
+ if (scope === "machine") return context.machine ?? {};
83
+ if (scope === "workspace") return context.workspace;
84
+ if (scope === "repo") return context.repo;
85
+ return setting?.committedAt === "repository" ? context.committed.repository : context.committed.app;
86
+ }
87
+ function masked(setting, value) {
88
+ return setting.sensitive && value !== void 0 && value !== null ? MASK : value;
89
+ }
90
+ function settingExample(setting) {
91
+ switch (setting.type.kind) {
92
+ case "boolean": return "false";
93
+ case "number": return String(setting.default ?? setting.type.minimum ?? 1);
94
+ case "strings": return `'["node_modules"]'`;
95
+ case "object": return `'{"key": "value"}'`;
96
+ case "choice": return setting.type.choices[0];
97
+ default: return "<value>";
98
+ }
99
+ }
100
+ function envSettingValue(setting, raw) {
101
+ const value = coerceSettingText(setting, raw);
102
+ const error = settingValueError(setting, value);
103
+ if (error) throw new SettingsRefusal("STIM_BAD_ARG", `Invalid ${setting.env} value ${JSON.stringify(raw)}. Expected ${error}.`, `Fix the environment variable, or unset it and run \`stim settings set ${setting.key} ${settingExample(setting)}\`.`);
104
+ return value;
105
+ }
106
+ function settingEntry(context, setting) {
107
+ const layers = {};
108
+ for (const scope of PRECEDENCE) {
109
+ if (!setting.scopes.includes(scope) || layerFile(context, scope, setting) === null) continue;
110
+ const value = valueAt(layerSettings(context, scope, setting), setting.key);
111
+ if (value !== void 0) layers[scope] = masked(setting, value);
112
+ }
113
+ const envValue = setting.env ? context.env[setting.env] : void 0;
114
+ const env = setting.env && envValue ? {
115
+ name: setting.env,
116
+ value: String(masked(setting, envValue))
117
+ } : void 0;
118
+ const scopedHome = !env && setting.scopedHomeValue !== void 0 && context.env.STIM_HOME;
119
+ const ci = !env && setting.ciValue !== void 0 && context.env.CI;
120
+ const winner = PRECEDENCE.find((scope) => scope in layers);
121
+ let value = null;
122
+ let origin = null;
123
+ let defaultReason = null;
124
+ if (env) {
125
+ value = masked(setting, envSettingValue(setting, envValue));
126
+ origin = "env";
127
+ } else if (scopedHome) {
128
+ value = setting.scopedHomeValue;
129
+ origin = "env";
130
+ } else if (ci) {
131
+ value = setting.ciValue;
132
+ origin = "env";
133
+ } else if (winner) {
134
+ value = layers[winner];
135
+ origin = winner;
136
+ } else if (setting.default !== void 0) {
137
+ const fallback = settingDefault(setting, context.desktopInstalled);
138
+ value = fallback.value;
139
+ origin = "default";
140
+ defaultReason = fallback.reason;
141
+ }
142
+ return {
143
+ key: setting.key,
144
+ value,
145
+ origin,
146
+ layers,
147
+ ...env ? { env } : scopedHome ? { env: {
148
+ name: "STIM_HOME",
149
+ value: context.env.STIM_HOME
150
+ } } : ci ? { env: {
151
+ name: "CI",
152
+ value: context.env.CI
153
+ } } : {},
154
+ ...setting.sensitive ? { sensitive: true } : {},
155
+ ...defaultReason ? { defaultReason } : {}
156
+ };
157
+ }
158
+ function unknownEntries(context) {
159
+ const sources = [
160
+ {
161
+ scope: "machine",
162
+ file: layerFile(context, "machine", null),
163
+ settings: { optimizations: context.machine?.optimizations }
164
+ },
165
+ {
166
+ scope: "workspace",
167
+ file: layerFile(context, "workspace", null),
168
+ settings: layerSettings(context, "workspace", null)
169
+ },
170
+ {
171
+ scope: "repo",
172
+ file: layerFile(context, "repo", null),
173
+ settings: layerSettings(context, "repo", null)
174
+ },
175
+ {
176
+ scope: "committed",
177
+ file: layerFile(context, "committed", null),
178
+ settings: layerSettings(context, "committed", null)
179
+ }
180
+ ];
181
+ const repository = repositoryDirectory(context);
182
+ if (repository && repository !== appDirectory(context)) sources.push({
183
+ scope: "committed",
184
+ file: join(repository, ".stim.json"),
185
+ settings: context.committed.repository
186
+ });
187
+ return sources.flatMap(({ scope, file, settings }) => file === null ? [] : unknownSettingKeys(settings).map((key) => ({
188
+ key,
189
+ scope,
190
+ file,
191
+ value: valueAt(settings, key)
192
+ })));
193
+ }
194
+ function settingsPayload(context) {
195
+ const files = {};
196
+ for (const scope of SETTING_SCOPES) {
197
+ const file = layerFile(context, scope, null);
198
+ if (file) files[scope] = file;
199
+ }
200
+ return {
201
+ project: context.projectPath,
202
+ files,
203
+ settings: SETTINGS.map((setting) => settingEntry(context, setting)),
204
+ unknown: unknownEntries(context)
205
+ };
206
+ }
207
+ /** Every setting with its effective value and layers; looks Stim Desktop up asynchronously, and only when a default depends on it. */
208
+ async function readSettingsPayload(context, signal) {
209
+ let asked = false;
210
+ const payload = settingsPayload({
211
+ ...context,
212
+ desktopInstalled: () => {
213
+ asked = true;
214
+ return false;
215
+ }
216
+ });
217
+ if (!asked) return payload;
218
+ const installed = await stimDesktopInstalledAsync(process.platform, context.env, killOnAbort(signal));
219
+ signal?.throwIfAborted();
220
+ return settingsPayload({
221
+ ...context,
222
+ desktopInstalled: () => installed
223
+ });
224
+ }
225
+ //#endregion
226
+ //#region src/workspace/settings-write.ts
227
+ function requireSetting(key) {
228
+ const setting = settingDefinition(key);
229
+ if (setting) return setting;
230
+ throw new SettingsRefusal("STIM_BAD_ARG", `${JSON.stringify(key)} is not a Stim setting.`, "Run `stim settings` to list every setting, or `stim guide settings` for what each one does.");
231
+ }
232
+ function readScope(raw, setting) {
233
+ if (raw === void 0) {
234
+ if (setting.scopes.length === 1) return setting.scopes[0];
235
+ throw new SettingsRefusal("STIM_BAD_ARG", `${setting.key} can live in more than one layer, so the command needs --scope.`, `Pass --scope ${setting.scopes.join("|")}.`);
236
+ }
237
+ if (!SETTING_SCOPES.includes(raw)) throw new SettingsRefusal("STIM_BAD_ARG", `--scope takes ${SETTING_SCOPES.join(", ")}, not ${JSON.stringify(raw)}.`, null);
238
+ const scope = raw;
239
+ if (!setting.scopes.includes(scope)) throw new SettingsRefusal("STIM_BAD_ARG", `${setting.key} is not read from the ${scope} layer.`, `Pass --scope ${setting.scopes.join("|")}.`);
240
+ return scope;
241
+ }
242
+ function requireLayer(context, scope, setting) {
243
+ const file = layerFile(context, scope, setting);
244
+ if (file) return file;
245
+ if (scope === "repo") throw new SettingsRefusal("STIM_BAD_ARG", "The repo layer is keyed by a Git repository, and this directory is not inside one.", "Run this from inside the repository, or pick another --scope.");
246
+ throw new SettingsRefusal(NO_PROJECT_REFUSAL.code, NO_PROJECT_REFUSAL.message, NO_PROJECT_REFUSAL.remedy);
247
+ }
248
+ function parseSettingValue(setting, raw) {
249
+ const invalid = (expected) => new SettingsRefusal("STIM_BAD_ARG", `Invalid ${setting.key} value ${JSON.stringify(raw)}. Expected ${expected}.`, `For example: stim settings set ${setting.key} ${settingExample(setting)}${setting.scopes.length > 1 ? ` --scope ${setting.scopes[0]}` : ""}`);
250
+ const kind = setting.type.kind;
251
+ const value = coerceSettingText(setting, raw);
252
+ const error = settingValueError(setting, value);
253
+ if (error) throw invalid(kind === "strings" || kind === "object" ? `${error}, written as JSON` : error);
254
+ return value;
255
+ }
256
+ function committedTarget(context, setting) {
257
+ const directory = committedDirectory(context, setting);
258
+ if (!directory) throw new SettingsRefusal(NO_PROJECT_REFUSAL.code, NO_PROJECT_REFUSAL.message, NO_PROJECT_REFUSAL.remedy);
259
+ return join(directory, ".stim.json");
260
+ }
261
+ function writeCommitted(file, key, value, signal) {
262
+ return withConfigLockAsync$1(() => {
263
+ const exists = existsSync(file);
264
+ const text = exists ? readFileSync(file, "utf-8") : "";
265
+ let parsed = {};
266
+ if (exists && text.trim() !== "") try {
267
+ parsed = JSON.parse(text);
268
+ } catch (error) {
269
+ throw new SettingsRefusal("STIM_BAD_ARG", `${file} is not valid JSON: ${error.message}`, `Repair ${file}, then run the command again.`);
270
+ }
271
+ if (!isJsonObject(parsed)) throw new SettingsRefusal("STIM_BAD_ARG", `${file} is not a JSON object.`, `Repair ${file}, then run the command again.`);
272
+ const parts = key.split(".");
273
+ const chain = [parsed];
274
+ for (const part of parts.slice(0, -1)) {
275
+ const node = chain.at(-1);
276
+ if (!isJsonObject(node[part])) {
277
+ if (value === void 0) return false;
278
+ node[part] = {};
279
+ }
280
+ chain.push(node[part]);
281
+ }
282
+ const leaf = parts.at(-1);
283
+ const parent = chain.at(-1);
284
+ if (value === void 0) {
285
+ if (!(leaf in parent)) return false;
286
+ delete parent[leaf];
287
+ for (let index = chain.length - 1; index > 0; index--) {
288
+ if (Object.keys(chain[index]).length > 0) break;
289
+ delete chain[index - 1][parts[index - 1]];
290
+ }
291
+ } else parent[leaf] = value;
292
+ const indent = /\n([ \t]+)"/.exec(text)?.[1] ?? 2;
293
+ const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
294
+ writeFileSync(tmp, `${JSON.stringify(parsed, null, indent)}\n`);
295
+ try {
296
+ renameSync(tmp, file);
297
+ } catch (error) {
298
+ try {
299
+ unlinkSync(tmp);
300
+ } catch {}
301
+ throw error;
302
+ }
303
+ return true;
304
+ }, signal);
305
+ }
306
+ function writeSetting(context, setting, scope, value, signal) {
307
+ if (scope === "committed") return writeCommitted(committedTarget(context, setting), setting.key, value, signal);
308
+ if (scope === "machine") return writeConfigSettingAsync({ scope }, setting.key, value, signal);
309
+ if (scope === "workspace") return writeConfigSettingAsync({
310
+ scope,
311
+ projectPath: context.projectPath
312
+ }, setting.key, value, signal);
313
+ return writeConfigSettingAsync({
314
+ scope,
315
+ gitCommonDir: context.gitCommonDir
316
+ }, setting.key, value, signal);
317
+ }
318
+ /** Shares CLI set/unset validation and side effects; after commit, recording cleanup finishes despite cancellation. */
319
+ async function mutateSetting(request, { cwd, env, note = () => {}, signal, beforeWrite }) {
320
+ signal?.throwIfAborted();
321
+ const { key } = request;
322
+ const setting = requireSetting(key);
323
+ const scope = readScope(request.scope, setting);
324
+ const value = request.action === "set" ? parseSettingValue(setting, request.value) : void 0;
325
+ if (setting.sensitive && scope === "committed" && value !== void 0 && !isSensitiveReference(value)) throw new SettingsRefusal("STIM_BAD_ARG", `${key} is sensitive, so a committed .stim.json takes only an env: or file: reference, never the secret.`, `Set the secret with --scope workspace or --scope repo, which store it in ${getConfigPath$1()}, readable only by you, or commit a reference such as env:MY_KEYSTORE_PASSWORD.`);
326
+ const context = await readSettingsContext(cwd, env, note, signal);
327
+ const file = requireLayer(context, scope, setting);
328
+ beforeWrite?.(context.projectPath);
329
+ const apply = async () => {
330
+ const recording = setting.key === "recording.enabled" ? recordingLayers() : null;
331
+ const changed = await writeSetting(context, setting, scope, value, signal);
332
+ const updated = await readSettingsContext(cwd, env, void 0, void 0, context.projectPath);
333
+ const recordingsDeleted = recording ? await deleteTurnedOffRecordings(recording) : void 0;
334
+ let entry = settingEntry({
335
+ ...updated,
336
+ desktopInstalled: () => false
337
+ }, setting);
338
+ if (entry.origin === "default" && setting.desktopDefault !== void 0) {
339
+ const installed = await stimDesktopInstalledAsync(process.platform, env);
340
+ entry = settingEntry({
341
+ ...updated,
342
+ desktopInstalled: () => installed
343
+ }, setting);
344
+ }
345
+ return {
346
+ key,
347
+ scope,
348
+ file,
349
+ changed,
350
+ setting: entry,
351
+ ...recordingsDeleted ? { recordingsDeleted } : {}
352
+ };
353
+ };
354
+ return key === "recording.enabled" ? withWorkspaceProcessLock(configDir(), "recording-settings", apply, {
355
+ external: true,
356
+ signal
357
+ }) : apply();
358
+ }
359
+ //#endregion
360
+ export { layerFile as a, settingEntry as c, SettingsRefusal as i, readScope as n, readSettingsContext as o, requireSetting as r, readSettingsPayload as s, mutateSetting as t };