stim 1.24.0 → 1.26.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 (162) hide show
  1. package/README.md +1 -1
  2. package/dist/{acquire-artifact-CEs02U2o.mjs → acquire-artifact-DVsvSwf7.mjs} +1 -1
  3. package/dist/{act-Cyvm8xYc.mjs → act-C-BqJEpu.mjs} +158 -36
  4. package/dist/{activity-Dq3ZcdD8.mjs → activity-Lnb_EoRY.mjs} +4 -5
  5. package/dist/{agent-device-usage-output-CccomeE0.mjs → agent-device-usage-output-DbXy5tg8.mjs} +4 -4
  6. package/dist/{android-CX5IcRuf.mjs → android-B5P81yI-.mjs} +1 -1
  7. package/dist/{android-DcztblCT.mjs → android-CSbLRD53.mjs} +5 -5
  8. package/dist/{android-BZppyPe_.mjs → android-CiNQw3kq.mjs} +81 -52
  9. package/dist/{android-882m4hxX.mjs → android-DTAcRwBC.mjs} +81 -34
  10. package/dist/{android-cas-BtCOrNqb.mjs → android-cas-BTVhZ0Qs.mjs} +4 -4
  11. package/dist/{android-project-DVWyCbWU.d.mts → android-project-DUGMbq28.d.mts} +61 -3
  12. package/dist/api.d.mts +8 -5
  13. package/dist/api.mjs +27 -27
  14. package/dist/apk-signed-tail-B46U9hXc.mjs +142 -0
  15. package/dist/{artifact-BR5VNArK.mjs → artifact-BxREhAaV.mjs} +25 -19
  16. package/dist/{artifact-Bdt_n9Jc.mjs → artifact-CsAP6AGK.mjs} +36 -21
  17. package/dist/{attempt-DW-mQqM7.mjs → attempt-ClyJlZPT.mjs} +4 -2
  18. package/dist/{browser-web-ycg9qWB8.mjs → browser-web-rYPyqhTf.mjs} +11 -12
  19. package/dist/{budget-dPGuhNai.mjs → budget-k2mZGvvk.mjs} +242 -38
  20. package/dist/{build-CaF574eS.mjs → build-DPhApsjV.mjs} +28 -24
  21. package/dist/{build-cache-HFUQ9eLz.mjs → build-cache-DrXNCy3T.mjs} +123 -23
  22. package/dist/{build-plan-JsDUq4w1.mjs → build-plan-DrMMdayj.mjs} +5 -5
  23. package/dist/{cache-manifest-BPXRONJz.mjs → cache-manifest-BEZ9Bpl1.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-CCn1S6qG.mjs → ccache-Bx5TbxwG.mjs} +6 -6
  26. package/dist/{cli-xqAidP7O.mjs → cli-BBKFGOFl.mjs} +19 -19
  27. package/dist/cli.mjs +1 -1
  28. package/dist/{client-18-ZowoT.mjs → client-D9CaRks-.mjs} +55 -71
  29. package/dist/collector-run.mjs +4 -4
  30. package/dist/{command-output-DxC0k2rk.mjs → command-output-BF5AR2dL.mjs} +1 -1
  31. package/dist/{config-BZhXY15H.mjs → config-BktkY_zC.mjs} +321 -15
  32. package/dist/{launch-BVlyQw3T.mjs → dependencies-Dw6wfQdv.mjs} +259 -256
  33. package/dist/{dependency-state-C56ll9hY.mjs → dependency-state-DFB41vfr.mjs} +1 -1
  34. package/dist/{dev-client-w_fok0Ek.mjs → dev-client-DXR_tPVY.mjs} +2 -2
  35. package/dist/{device-BktRGdjS.mjs → device-BK-zwyd_.mjs} +64 -33
  36. package/dist/{device-4RUugw5X.mjs → device-BcYeHSFu.mjs} +14 -14
  37. package/dist/{device-capacity-Ic-kdmEV.mjs → device-capacity-DCSvUF0l.mjs} +10 -17
  38. package/dist/device-host-worker.mjs +11 -13
  39. package/dist/{device-ios-DzpSlZyd.mjs → device-ios-BLGfXQeK.mjs} +68 -25
  40. package/dist/{device-lease-run-DUtkbqBQ.mjs → device-lease-run-BmvIl7bI.mjs} +5 -5
  41. package/dist/{device-pool-CgBHk401.mjs → device-pool-Dluix4H3.mjs} +3 -3
  42. package/dist/{doctor-DZgpqR6J.mjs → doctor-Bhg1ii70.mjs} +14 -14
  43. package/dist/{doctor-BZ6oxNum.mjs → doctor-Cp-BhzTS.mjs} +1 -1
  44. package/dist/{doctor-C33AzVfR.mjs → doctor-OnwP94ne.mjs} +81 -26
  45. package/dist/{doctor-fingerprint-zlujA1Gs.mjs → doctor-fingerprint-D3a04Mhu.mjs} +8 -2
  46. package/dist/doctor-fingerprint.mjs +1 -1
  47. package/dist/{doctor-watchman-B453A231.mjs → doctor-watchman-BStK05nt.mjs} +4 -4
  48. package/dist/{eas-build-CxKUNHsb.mjs → eas-build-Dsj93iM9.mjs} +2 -2
  49. package/dist/{eas-fallback-LMxk9Kw0.mjs → eas-fallback-FwkeqqGi.mjs} +13 -12
  50. package/dist/{eas-session-ledger-Ck6YXPAO.mjs → eas-session-ledger-B5vygTiD.mjs} +5 -5
  51. package/dist/{error-diagnostics-BkKCZq4P.mjs → error-diagnostics-BOOm9Db7.mjs} +8 -8
  52. package/dist/{errors-ccaPc4ox.mjs → errors-DHm_U5gv.mjs} +2 -1
  53. package/dist/{gc-DDWEAj0w.mjs → gc-C_79zvz4.mjs} +2 -2
  54. package/dist/{gc-yVKpAOKM.mjs → gc-ldgr-hXU.mjs} +74 -43
  55. package/dist/{guide-Bggftwc5.mjs → guide-D7K0X6KG.mjs} +374 -78
  56. package/dist/{hosted-android-D4dweBof.mjs → hosted-android-Bk54ej6n.mjs} +3 -3
  57. package/dist/{hosted-client-BBTVe3X6.mjs → hosted-client-fHO8yqzc.mjs} +5 -5
  58. package/dist/{hosted-ios-Sn0djzg8.mjs → hosted-ios-D55QhYaD.mjs} +1 -1
  59. package/dist/{hosted-logs-CYIZ5ubJ.mjs → hosted-logs-BfbmDM4M.mjs} +17 -11
  60. package/dist/hosted-logs-sync-B0pvmOk-.mjs +195 -0
  61. package/dist/{hosted-macos-CXjsUNBR.mjs → hosted-macos-CPl0OZ9h.mjs} +5 -5
  62. package/dist/{hosted-native-Doxbfzem.mjs → hosted-native-CpDB3-PO.mjs} +6 -7
  63. package/dist/{idle-shutdown-BInjLKqm.mjs → idle-shutdown-FfxL1KdG.mjs} +22 -9
  64. package/dist/{ios-BItP6lkn.mjs → ios-B7-lToDu.mjs} +8 -8
  65. package/dist/{ios-CVUFFZ6C.mjs → ios-WxpDJ5T1.mjs} +129 -14
  66. package/dist/{ios-device-BI38NFFH.mjs → ios-device-CsyryvpT.mjs} +1 -1
  67. package/dist/{ios-B1FXRCMX.mjs → ios-ftxdQbJS.mjs} +84 -51
  68. package/dist/{ios-project-KYqeJURj.mjs → ios-project-Ty5pHl9O.mjs} +6 -6
  69. package/dist/{ios-state-DlElquYD.mjs → ios-state-Cw7-WQf2.mjs} +1 -1
  70. package/dist/{js-swap-BvrQvXHY.mjs → js-swap-BMhXYVDS.mjs} +4 -4
  71. package/dist/{launch-SfzGH_s9.mjs → launch-DOp8RjDz.mjs} +32 -27
  72. package/dist/{logs-DXE32kyb.mjs → logs-dQDki6Tt.mjs} +9 -173
  73. package/dist/{logs-ovlU7m7N.mjs → logs-s1dRIG1E.mjs} +85 -36
  74. package/dist/{macos-B3BveDrU.mjs → macos-B0VEV3Gf.mjs} +1 -1
  75. package/dist/{macos-CCfhb-jT.mjs → macos-DBBPNnIA.mjs} +18 -19
  76. package/dist/macos-run.mjs +1 -1
  77. package/dist/maintenance-run.mjs +28 -11
  78. package/dist/{metro-Bu8LBfzS.mjs → metro-CjC10t6E.mjs} +2 -2
  79. package/dist/{metro-gateway-DtsOy-0P.mjs → metro-gateway-B6_PgD0L.mjs} +2 -3
  80. package/dist/{named-ports-BWDuU5oQ.mjs → named-ports-BG0j1X4g.mjs} +2 -2
  81. package/dist/{native-android-96BBizbq.mjs → native-android-CL2NGiik.mjs} +17 -17
  82. package/dist/{native-gradle-artifact-inputs-BcLYBZil.mjs → native-gradle-artifact-inputs-btSUulme.mjs} +3 -3
  83. package/dist/{native-run-BmH7U8pr.mjs → native-run-BfIDFKLH.mjs} +2 -3
  84. package/dist/{native-runtime-DgtJkzIa.mjs → native-runtime-Dq3RBcON.mjs} +6 -7
  85. package/dist/{native-xcode-inputs-irplbQb0.mjs → native-xcode-inputs-BW7H8JGu.mjs} +2 -2
  86. package/dist/{native-xcode-ios-BY-6hh6M.mjs → native-xcode-ios-CBXJAxfC.mjs} +18 -18
  87. package/dist/offload-worker.d.mts +7 -2
  88. package/dist/offload-worker.mjs +34 -23
  89. package/dist/{ownership-DxlZGDcV.mjs → ownership-BjYvMNX_.mjs} +2 -2
  90. package/dist/{phone-reverses-BdsdesVF.mjs → phone-reverses-lmj6kcPm.mjs} +3 -3
  91. package/dist/{placement-log-DUvqqsB-.mjs → placement-log-DIFPQAXp.mjs} +1 -1
  92. package/dist/{plan-placement-4axc0Hs7.mjs → plan-placement-IiiSQhtz.mjs} +3 -3
  93. package/dist/{ports-D-E_OiAO.mjs → ports-C2_w1Z0Z.mjs} +3 -3
  94. package/dist/prebuild-gmouvmJZ.mjs +1247 -0
  95. package/dist/{project-Dz-hWkb-.mjs → project-BUu6Is4k.mjs} +15 -16
  96. package/dist/{react-native-android-DOinxgwB.mjs → react-native-android-Cgg99REN.mjs} +48 -33
  97. package/dist/{react-native-build-AuCu-aAP.mjs → react-native-build-oNwqF5Wb.mjs} +8 -8
  98. package/dist/{react-native-doctor-2ivJUmwZ.mjs → react-native-doctor-BhA3KUte.mjs} +49 -8
  99. package/dist/{react-native-ios-D5zTIuH8.mjs → react-native-ios-B-nf4rjN.mjs} +40 -25
  100. package/dist/{recordings-CdPwYwvs.mjs → recordings-BldzVKq0.mjs} +1 -1
  101. package/dist/{reload-Ck9RJeSq.mjs → reload-C9OduiNc.mjs} +1 -1
  102. package/dist/{reload-C1TTVesC.mjs → reload-CCR7KC_l.mjs} +14 -14
  103. package/dist/{remote-DEZ7AOVq.mjs → remote-C8S7FlPF.mjs} +16 -7
  104. package/dist/{result-DqBrb12U.mjs → result-7F5hEwQJ.mjs} +17 -17
  105. package/dist/{run-BIwoU44q.mjs → run-BqB0v3pt.mjs} +1 -1
  106. package/dist/{selection-BLtvaqxc.mjs → selection-BNPBZ6T5.mjs} +157 -44
  107. package/dist/{server-bare-Z1ToVLPn.mjs → server-bare-A75rDIdD.mjs} +55 -3
  108. package/dist/{server-command-C0pmjNdG.mjs → server-command-CssKFOD7.mjs} +4 -4
  109. package/dist/{server-expo-Tt_hLRpy.mjs → server-expo-eQfOdydb.mjs} +8 -6
  110. package/dist/server-expo-wvcj5tiZ.mjs +2 -0
  111. package/dist/{settings-RKwY33wv.mjs → settings-CosW5X-S.mjs} +59 -61
  112. package/dist/{settings-kkt0vP4w.mjs → settings-OaGQF-ri.mjs} +1 -1
  113. package/dist/{settings-write--gj6MACV.mjs → settings-write-QjYfSrjF.mjs} +5 -5
  114. package/dist/settings.schema.json +71 -6
  115. package/dist/{simslim-CdWKT3vA.mjs → simslim-Bax1qcxu.mjs} +22 -6
  116. package/dist/{slot-launch-A1BgotaM.mjs → slot-launch-CYCEhfBY.mjs} +6 -6
  117. package/dist/{stage-ERTMh88n.mjs → stage-jKQ7CP_B.mjs} +1 -1
  118. package/dist/{start-Bmg_qmHi.mjs → start-C_wefNKB.mjs} +1 -1
  119. package/dist/{start-BKGrEhzG.mjs → start-_BdJ32cZ.mjs} +9 -10
  120. package/dist/{state-B1ig0Kqy.mjs → state-C1i2nMOP.mjs} +2 -3
  121. package/dist/{state-BfAltYJP.mjs → state-C4OdpOTF.mjs} +1 -2
  122. package/dist/{stats-B-ckuiUg.mjs → stats-tEpEEH-u.mjs} +4 -4
  123. package/dist/{status-Pw-807f0.mjs → status-B9M7x4CZ.mjs} +1 -1
  124. package/dist/{status-Fect2w9R.mjs → status-CRXz-Gtj.mjs} +1 -1
  125. package/dist/{status-DfFp6a76.mjs → status-DQrqodLj.mjs} +22 -23
  126. package/dist/{status-watch-XC7F-AMf.mjs → status-watch-B5wDIH_o.mjs} +4 -4
  127. package/dist/status-worker.mjs +1 -1
  128. package/dist/{stim-desktop-DS0mzR8U.mjs → stim-desktop-6Dqp-gjX.mjs} +1 -1
  129. package/dist/{stop-BFu7X_Do.mjs → stop-CmdNhGlC.mjs} +2 -2
  130. package/dist/{stop-CL1kDHds.mjs → stop-DRqQVqDJ.mjs} +74 -53
  131. package/dist/{stop-DhclRwOO.mjs → stop-ySNQHXMG.mjs} +4 -5
  132. package/dist/supervisor-run.d.mts +1 -0
  133. package/dist/supervisor-run.mjs +15 -16
  134. package/dist/{support-B3tzVhKn.mjs → support-BGSCBoib.mjs} +4 -4
  135. package/dist/{support-B1W-hmC2.mjs → support-CVOCp0Ft.mjs} +15 -12
  136. package/dist/{swiftpm-artifact-inputs-BWYPj9Sn.mjs → swiftpm-artifact-inputs-CfUzt_0Z.mjs} +1 -1
  137. package/dist/{swiftpm-macos-BVCP5mO4.mjs → swiftpm-macos-x6HPpl_2.mjs} +10 -10
  138. package/dist/toolchain-DoavrvIA.mjs +2 -0
  139. package/dist/toolchain-J4J8MrAr.mjs +2107 -0
  140. package/dist/trigger-DzJu208Q.mjs +2 -0
  141. package/dist/{trigger-CBMe2YLH.mjs → trigger-KVaWWNyn.mjs} +1 -1
  142. package/dist/{warm-progress-ol0ZypEu.mjs → warm-progress-DvhTX_eu.mjs} +3 -4
  143. package/dist/web-BFLueSh-.mjs +2 -0
  144. package/dist/{web-BH7peScT.mjs → web-Bihbf7-u.mjs} +8 -9
  145. package/dist/web-run.mjs +4 -4
  146. package/dist/{workspace-state-CeBpIZgr.mjs → workspace-state-pUg3_RRA.mjs} +45 -7
  147. package/dist/{workspaces-CSV2Orf4.mjs → workspaces-g2lhdBXF.mjs} +17 -17
  148. package/dist/{worktree-Dw8kfacb.mjs → worktree-BKuklFh_.mjs} +34 -31
  149. package/dist/{worktree-DEDUzO_L.mjs → worktree-Bm4cb-nU.mjs} +1 -1
  150. package/package.json +8 -8
  151. package/shim/bundle-response.cjs +53 -1
  152. package/shim/bundle-response.d.cts +1 -1
  153. package/shim/expo-metro-config.cjs +23 -1
  154. package/dist/created-devices-D2Aca-xu.mjs +0 -52
  155. package/dist/paths-DQtTgsBf.mjs +0 -42
  156. package/dist/prebuild-DmVCf5xb.mjs +0 -501
  157. package/dist/server-expo-CEntXzRw.mjs +0 -2
  158. package/dist/toolchain-BjgKdoEf.mjs +0 -2
  159. package/dist/toolchain-D3bmRMia.mjs +0 -897
  160. package/dist/trigger-BLsHgAGR.mjs +0 -2
  161. package/dist/web-BdOFlTJr.mjs +0 -2
  162. package/dist/xcode-DHu41qQ4.mjs +0 -910
@@ -1,6 +1,7 @@
1
1
  import { C as reportSignal, b as operationState } from "./exec-VFRpu1iA.mjs";
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-BZhXY15H.mjs";
2
+ import { M as withDirLock$1 } from "./workspace-state-pUg3_RRA.mjs";
3
+ import { $ as findPeer$1, Q as endpoint, X as diagnoseTailscale, Y as diagnoseOutcome, _ as loadConfig$1, ct as tailscaleStatusAsync, d as getConfigDir, dt as readHostPermissions, it as realIo, lt as diagnosisFinding, nt as parseMachine$1, rt as reachMachine, st as setupRemedy, tt as outdatedServer, ut as notOnTailnetDiagnosis } from "./config-BktkY_zC.mjs";
4
+ import { o as cocoapodsInstall } from "./toolchain-J4J8MrAr.mjs";
4
5
  import { releaseClaim, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
5
6
  import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
6
7
  import { hostname } from "node:os";
@@ -126,7 +127,17 @@ async function inspectDeviceHostMachines({ fix, version = "<version>", tickets =
126
127
  machines: []
127
128
  };
128
129
  const status = await io.status();
129
- if (!isJsonObject(status)) return unavailable("tailscale-off", note$1("Remote machines are unreachable", "remote.machines names remote machines, but Tailscale is not running."));
130
+ if (!isJsonObject(status)) {
131
+ const diagnosis = await diagnoseTailscale(io);
132
+ return {
133
+ findings: [note$1("Remote machines are unreachable", `remote.machines names remote machines. ${diagnosis.message}`, diagnosis.remedy)],
134
+ machines: entries.map((machine) => ({
135
+ machine,
136
+ state: "tailscale-off",
137
+ diagnosis
138
+ }))
139
+ };
140
+ }
130
141
  const self = isJsonObject(status.Self) ? status.Self : {};
131
142
  const deviceName = (typeof self.HostName === "string" && self.HostName ? self.HostName : hostname()).replace(/[\p{Cc}\p{Cf}]/gu, "").trim().slice(0, 64) || "Mac";
132
143
  const inspected = {
@@ -146,20 +157,24 @@ async function inspectDeviceHostMachines({ fix, version = "<version>", tickets =
146
157
  }
147
158
  const current = await io.status();
148
159
  if (!isJsonObject(current)) {
160
+ const diagnosis = await diagnoseTailscale(io);
149
161
  inspected.machines.push({
150
162
  machine,
151
- state: "tailscale-off"
163
+ state: "tailscale-off",
164
+ diagnosis
152
165
  });
153
- inspected.findings.push(note$1(`Remote machine ${machine} is unreachable`, "Tailscale stopped before this connection."));
166
+ inspected.findings.push(diagnosisFinding("device-host-machine", machine, diagnosis));
154
167
  continue;
155
168
  }
156
169
  const peer = findPeer$1(current, parsed.name);
157
170
  if (peer === "missing" || peer === "ambiguous") {
171
+ const diagnosis = notOnTailnetDiagnosis(machine, peer === "ambiguous");
158
172
  inspected.machines.push({
159
173
  machine,
160
- state: "not-on-tailnet"
174
+ state: "not-on-tailnet",
175
+ diagnosis
161
176
  });
162
- inspected.findings.push(note$1(`Remote machine ${machine} is not on this tailnet`, peer === "missing" ? "No peer has that name." : "Several peers match that name."));
177
+ inspected.findings.push(diagnosisFinding("device-host-machine", machine, diagnosis));
163
178
  continue;
164
179
  }
165
180
  const nodeRoute = `${peer.nodeId}:${parsed.port}`;
@@ -251,16 +266,40 @@ async function inspectDeviceHostMachines({ fix, version = "<version>", tickets =
251
266
  const outdated = outdatedServer(machine, version, outcome.command);
252
267
  inspected.machines.push({
253
268
  ...known,
254
- state: "outdated"
269
+ state: "outdated",
270
+ diagnosis: {
271
+ layer: "compat",
272
+ code: "server-outdated",
273
+ title: "Server is outdated",
274
+ message: outdated.detail,
275
+ remedy: outdated.fix
276
+ }
255
277
  });
256
278
  inspected.findings.push(note$1(outdated.title, outdated.detail, outdated.fix));
257
279
  continue;
258
280
  }
281
+ if (outcome.state === "unreachable") {
282
+ const diagnosis = await diagnoseOutcome(io, {
283
+ entry: machine,
284
+ peer,
285
+ port: parsed.port,
286
+ target: endpoint(peer, parsed.port),
287
+ reason: outcome.reason,
288
+ transport: outcome.transport
289
+ });
290
+ inspected.machines.push({
291
+ ...known,
292
+ state: "unreachable",
293
+ diagnosis
294
+ });
295
+ inspected.findings.push(diagnosisFinding("device-host-machine", machine, diagnosis));
296
+ continue;
297
+ }
259
298
  inspected.machines.push({
260
299
  ...known,
261
300
  state: outcome.state
262
301
  });
263
- inspected.findings.push(outcome.state === "key-changed" ? note$1(`Remote machine ${machine} answered with a different server key`, "Stim refuses to connect to a stim-server that does not prove it holds the key pinned at approval.", `If that machine or its Stim home was replaced, remove ${machine} from remote.machines, run \`stim doctor --fix\`, then add it back and run \`stim doctor --fix\` again.`) : outcome.state === "lapsed" ? note$1(`Hosting request to ${machine} lapsed`, `${machine} did not approve this machine before its setup ticket expired at ${outcome.credential.expiresAt}.`, "Run `stim doctor --fix` to make a new ticket.") : outcome.state === "revoked" ? note$1(`Remote machine ${machine} no longer accepts this machine for device hosting`, `${outcome.reason} The pinned key is preserved.`, "Run `stim doctor --fix` to ask again.") : note$1(`Remote machine ${machine} did not confirm hosting access`, outcome.reason, `Check stim-server and its tailnet serve route on ${machine}, then run doctor again.`));
302
+ inspected.findings.push(outcome.state === "key-changed" ? note$1(`Remote machine ${machine} answered with a different server key`, "Stim refuses to connect to a stim-server that does not prove it holds the key pinned at approval.", `If that machine or its Stim home was replaced, remove ${machine} from remote.machines, run \`stim doctor --fix\`, then add it back and run \`stim doctor --fix\` again.`) : outcome.state === "lapsed" ? note$1(`Hosting request to ${machine} lapsed`, `${machine} did not approve this machine before its setup ticket expired at ${outcome.credential.expiresAt}.`, "Run `stim doctor --fix` to make a new ticket.") : note$1(`Remote machine ${machine} no longer accepts this machine for device hosting`, `${outcome.reason} The pinned key is preserved.`, "Run `stim doctor --fix` to ask again."));
264
303
  }
265
304
  return inspected;
266
305
  } finally {
@@ -312,12 +351,12 @@ function note(title, detail, fix = null) {
312
351
  const PROBLEM_TITLES = {
313
352
  unreachable: "does not answer a build offer",
314
353
  checkout: "cannot build an app outside a git checkout",
315
- "stim-build": "runs another Stim build",
354
+ "stim-build": "runs an incompatible Stim build",
316
355
  arch: "has another CPU architecture",
317
356
  xcode: "has another Xcode",
318
357
  "macos-sdk": "has another macOS SDK",
319
358
  "simulator-sdk": "has another simulator SDK",
320
- cocoapods: "has another CocoaPods",
359
+ cocoapods: "has no CocoaPods, or another version",
321
360
  bundler: "has no Bundler",
322
361
  runtime: "has no simulator for this project's iOS runtime",
323
362
  jdk: "runs another JDK major version",
@@ -329,37 +368,69 @@ const PROBLEM_TITLES = {
329
368
  busy: "is too busy to take builds",
330
369
  platform: "cannot build this platform"
331
370
  };
332
- function problemFix(code, entry) {
371
+ const NOTE_TITLES = {
372
+ ndk: "downloads this project's NDK on its first Android build",
373
+ "build-tools": "downloads this project's Android build-tools on its first Android build",
374
+ "compile-sdk": "downloads this project's Android compile platform on its first Android build"
375
+ };
376
+ function commandFix(problem, entry) {
377
+ return problem.commands?.length && problem.lead ? [`On ${entry}, ${problem.lead}:`, ...problem.commands].join("\n") : null;
378
+ }
379
+ function problemFix(problem, entry) {
380
+ const { code } = problem;
381
+ if (problem.followsFrom) return `Fix the ${problem.followsFrom} problem on ${entry} first; this follows from it.`;
333
382
  switch (code) {
334
383
  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
384
  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.`;
385
+ 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
386
  case "arch": return "Use a remote machine with the same CPU architecture as this machine.";
338
387
  case "xcode":
339
388
  case "simulator-sdk":
340
- case "macos-sdk": return `Install and select the same Xcode on ${entry} and this Mac (\`xcode-select -p\` on each).`;
341
- case "cocoapods": return `Install the same CocoaPods version on ${entry}, on the PATH its stim-server's login shell sets.`;
389
+ case "macos-sdk": return commandFix(problem, entry) ?? `Install and select the same Xcode on ${entry} and this Mac (\`xcode-select -p\` on each).`;
390
+ case "cocoapods": return commandFix(problem, entry) ?? `Install the same CocoaPods version on ${entry}, on the PATH its stim-server sets. A build sent there with --remote-build ${entry} still runs; a version that differs rewrites the COCOAPODS line of a committed Podfile.lock.`;
342
391
  case "bundler": return `Install Bundler (\`gem install bundler\`) on ${entry}, on the PATH its stim-server's login shell sets.`;
343
- case "runtime": return `Install that iOS simulator runtime on ${entry} with at least one iPhone simulator, or set ios.runtime here to one ${entry} has.`;
344
- case "jdk": return `Start stim-server on ${entry} with JAVA_HOME at a JDK of the same major version as this machine's.`;
392
+ case "runtime": return commandFix(problem, entry) ?? `Install that iOS simulator runtime on ${entry} with at least one iPhone simulator, or set ios.runtime here to one ${entry} has.`;
393
+ case "jdk": return commandFix(problem, entry) ?? `Start stim-server on ${entry} with JAVA_HOME at a JDK of the same major version as this machine's.`;
345
394
  case "android-sdk":
346
395
  case "ndk":
347
396
  case "build-tools":
348
- case "compile-sdk": return `Install the missing package with sdkmanager in the Android SDK stim-server on ${entry} uses (its ANDROID_HOME, else ~/Library/Android/sdk on macOS or ~/Android/Sdk on Linux).`;
397
+ case "compile-sdk": return commandFix(problem, entry) ?? `Install the missing package with sdkmanager in the Android SDK stim-server on ${entry} uses (its ANDROID_HOME, else ~/Library/Android/sdk on macOS or ~/Android/Sdk on Linux).`;
349
398
  case "disk": return `Free space on ${entry}'s worker root (server.workerRoot there).`;
350
399
  case "platform": return `iOS and macOS builds need a Mac; ${entry} can take Android builds only.`;
351
400
  case "busy": return `Builds stay on this machine until ${entry} has capacity. On ${entry}, server.maxLoadPerCore sets the load it accepts and concurrency.maxBuilds how many of its own builds it runs; it takes one offloaded build at a time.`;
352
401
  }
353
402
  }
354
403
  const TRANSIENT = /* @__PURE__ */ new Set(["unreachable", "busy"]);
355
- function offloadFindings(entry, problems) {
356
- return problems.map((problem) => ({
404
+ const UNPREDICTABLE = /* @__PURE__ */ new Set([
405
+ "unreachable",
406
+ "busy",
407
+ "disk",
408
+ "checkout",
409
+ "cocoapods"
410
+ ]);
411
+ /** Why a build on the machine named for it cannot work, from the toolchain differences found before this machine changes the checkout. */
412
+ function predictedRefusal(entry, problems) {
413
+ const known = problems.filter((problem) => !UNPREDICTABLE.has(problem.code));
414
+ if (known.length === 0) return null;
415
+ return {
416
+ reason: known.map((problem) => problem.reason).join("; "),
417
+ remedy: known.map((problem) => problemFix(problem, entry)).join("\n")
418
+ };
419
+ }
420
+ function offloadFindings(entry, problems, notes) {
421
+ return [...problems.map((problem) => ({
357
422
  code: `build-machine-${problem.code}`,
358
423
  level: TRANSIENT.has(problem.code) ? "note" : "cost",
359
424
  title: `Remote machine ${entry} ${PROBLEM_TITLES[problem.code]}`,
360
- detail: `Builds fall back to this machine: ${problem.reason}.`,
361
- fix: problemFix(problem.code, entry)
362
- }));
425
+ detail: `Builds fall back to this machine: ${problem.reason}.${problem.code === "cocoapods" ? ` A build sent there with --remote-build ${entry} still runs.` : ""}`,
426
+ fix: problemFix(problem, entry)
427
+ })), ...notes.map((each) => ({
428
+ code: `build-machine-${each.code}`,
429
+ level: "note",
430
+ title: `Remote machine ${entry} ${NOTE_TITLES[each.code] ?? "needs a first-build download"}`,
431
+ detail: `The build goes there anyway: ${each.reason}.`,
432
+ fix: commandFix(each, entry)
433
+ }))];
363
434
  }
364
435
  async function inspectMachine(entry, status, deviceName, fix, version, tickets, io, check, operation) {
365
436
  const parsed = parseMachine$1(entry);
@@ -372,13 +443,14 @@ async function inspectMachine(entry, status, deviceName, fix, version, tickets,
372
443
  };
373
444
  const peer = findPeer$1(status, parsed.name);
374
445
  if (peer === "missing" || peer === "ambiguous") {
375
- const detail = peer === "missing" ? "No peer on this tailnet has that name." : "Several peers match that name.";
446
+ const diagnosis = notOnTailnetDiagnosis(entry, peer === "ambiguous");
376
447
  return {
377
448
  report: {
378
449
  machine: entry,
379
- state: "not-on-tailnet"
450
+ state: "not-on-tailnet",
451
+ diagnosis
380
452
  },
381
- finding: note(`Remote machine ${entry} is not on this tailnet`, detail)
453
+ finding: diagnosisFinding("build-machine", entry, diagnosis)
382
454
  };
383
455
  }
384
456
  const credential = readBuildMachines().find((each) => each.machine === entry);
@@ -459,21 +531,40 @@ async function inspectMachine(entry, status, deviceName, fix, version, tickets,
459
531
  };
460
532
  case "outdated": {
461
533
  const outdated = outdatedServer(entry, version, outcome.command);
534
+ const diagnosis = {
535
+ layer: "compat",
536
+ code: "server-outdated",
537
+ title: "Server is outdated",
538
+ message: outdated.detail,
539
+ remedy: outdated.fix
540
+ };
462
541
  return {
463
542
  report: {
464
543
  ...paired,
465
- state: "outdated"
544
+ state: "outdated",
545
+ diagnosis
466
546
  },
467
547
  finding: note(outdated.title, outdated.detail, outdated.fix)
468
548
  };
469
549
  }
470
- case "unreachable": return {
471
- report: {
472
- ...paired,
473
- state: "unreachable"
474
- },
475
- finding: note(`Could not reach remote machine ${entry}`, outcome.reason, `Check that stim-server runs on ${entry}. To keep it running there, run \`stim-server service install --serve\` on ${entry}.`)
476
- };
550
+ case "unreachable": {
551
+ const diagnosis = await diagnoseOutcome(io, {
552
+ entry,
553
+ peer,
554
+ port: parsed.port,
555
+ target: endpoint(peer, parsed.port),
556
+ reason: outcome.reason,
557
+ transport: outcome.transport
558
+ });
559
+ return {
560
+ report: {
561
+ ...paired,
562
+ state: "unreachable",
563
+ diagnosis
564
+ },
565
+ finding: diagnosisFinding("build-machine", entry, diagnosis)
566
+ };
567
+ }
477
568
  }
478
569
  const permissions = readHostPermissions(outcome.result.host);
479
570
  const host = permissions ? { host: permissions } : {};
@@ -485,7 +576,7 @@ async function inspectMachine(entry, status, deviceName, fix, version, tickets,
485
576
  },
486
577
  finding: null
487
578
  };
488
- const { capacity, problems } = await check(outcome.credential);
579
+ const { capacity, problems, notes = [] } = await check(outcome.credential);
489
580
  return {
490
581
  report: {
491
582
  ...paired,
@@ -494,10 +585,11 @@ async function inspectMachine(entry, status, deviceName, fix, version, tickets,
494
585
  offloadable: problems.length === 0,
495
586
  reasons: problems.map((problem) => problem.reason),
496
587
  problems,
588
+ ...notes.length ? { notes } : {},
497
589
  ...capacity ? { capacity } : {}
498
590
  },
499
591
  finding: null,
500
- extra: offloadFindings(entry, problems)
592
+ extra: offloadFindings(entry, problems, notes)
501
593
  };
502
594
  }
503
595
  /**
@@ -519,13 +611,17 @@ async function inspectBuildMachines({ fix, check = null, version = "<version>",
519
611
  machines: []
520
612
  };
521
613
  const status = await io.status();
522
- if (!isJsonObject(status)) return {
523
- findings: [note("Remote machines are unreachable", "remote.machines names remote machines, but Tailscale is not running.")],
524
- machines: entries.map((machine) => ({
525
- machine,
526
- state: "tailscale-off"
527
- }))
528
- };
614
+ if (!isJsonObject(status)) {
615
+ const diagnosis = await diagnoseTailscale(io);
616
+ return {
617
+ findings: [note("Remote machines are unreachable", `remote.machines names remote machines. ${diagnosis.message}`, diagnosis.remedy)],
618
+ machines: entries.map((machine) => ({
619
+ machine,
620
+ state: "tailscale-off",
621
+ diagnosis
622
+ }))
623
+ };
624
+ }
529
625
  const self = isJsonObject(status.Self) ? status.Self : {};
530
626
  const deviceName = (typeof self.HostName === "string" && self.HostName ? self.HostName : hostname()).replace(/[\p{Cc}\p{Cf}]/gu, "").trim().slice(0, 64) || "Mac";
531
627
  const inspection = {
@@ -547,6 +643,23 @@ const FINGERPRINT_MISMATCH_REMEDY = "The build Mac fingerprints the synced check
547
643
  function fingerprintMismatchRemedy(reason) {
548
644
  return reason.startsWith("fingerprint-mismatch: the checkout there ") ? FINGERPRINT_MISMATCH_REMEDY : void 0;
549
645
  }
646
+ const PODS_FAILED_PREFIX = "pod install failed: ";
647
+ /** The reason a failed worker job is reported with: a `pods-failed` code reads as a failed pod install. */
648
+ function workerFailureReason(code, message) {
649
+ return code === "pods-failed" ? `${PODS_FAILED_PREFIX}${String(message ?? "")}` : `${String(code ?? "failed")}: ${String(message ?? "")}`;
650
+ }
651
+ /** The remedy for a worker whose `pod install` failed, naming the install when it has no CocoaPods; undefined for any other reason. */
652
+ function podsFailedRemedy(machine, reason, localCocoapods) {
653
+ if (!reason.startsWith(PODS_FAILED_PREFIX)) return void 0;
654
+ const retry = "run the same command again, or rerun with --remote-build auto or --remote-build local";
655
+ if (!reason.includes("CocoaPods is not installed: no `pod` executable on PATH.")) return `Fix the pod install error on ${machine} (run pod install in its checkout under server.workerRoot there to see all of it), then ${retry}.`;
656
+ const { lead, commands } = cocoapodsInstall(localCocoapods);
657
+ return [
658
+ `On ${machine}, ${lead}:`,
659
+ ...commands,
660
+ `Then ${retry}.`
661
+ ].join("\n");
662
+ }
550
663
  var OffloadRefusal = class extends Error {
551
664
  code = "STIM_OFFLOAD_REFUSED";
552
665
  remedy;
@@ -623,4 +736,4 @@ function resolveBuildPlacement(flag) {
623
736
  }
624
737
  }
625
738
  //#endregion
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 };
739
+ export { parseBuildMachineOption as a, resolveBuildMachine as c, inspectBuildMachines as d, pairedMachines as f, inspectDeviceHostMachines as g, hostingMachines as h, namedBuildMachine as i, resolveBuildPlacement as l, configuredMachines as m, buildPlacementSettings as n, podsFailedRemedy as o, predictedRefusal as p, fingerprintMismatchRemedy as r, requireLocalBuild as s, OffloadRefusal as t, workerFailureReason as u };
@@ -1,6 +1,6 @@
1
1
  import { O as __commonJSMin, k as __require, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { q as resolveProjectSettings } from "./settings-RKwY33wv.mjs";
3
- import { c as registerMetroStore, f as resolveMetroSharedCache, n as supervisorError, r as appendCacheStore, s as metroStoreRoot } from "./errors-ccaPc4ox.mjs";
2
+ import { J as resolveProjectSettings } from "./settings-CosW5X-S.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
1
  import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { n as METRO_COMMAND_PORT } from "./settings-RKwY33wv.mjs";
3
- import { T as MODE_COMMAND } from "./project-Dz-hWkb-.mjs";
4
- import { f as signalProcessTree } from "./metro-Bu8LBfzS.mjs";
2
+ import { n as METRO_COMMAND_PORT } from "./settings-CosW5X-S.mjs";
3
+ import { T as MODE_COMMAND } from "./project-BUu6Is4k.mjs";
4
+ import { f as signalProcessTree } from "./metro-CjC10t6E.mjs";
5
5
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
6
- import { g as projectNodeLine, p as recordFromLine, v as withProjectNode, y as superviseChildServer } from "./server-expo-Tt_hLRpy.mjs";
6
+ import { g as projectNodeLine, p as recordFromLine, v as withProjectNode, y as superviseChildServer } from "./server-expo-eQfOdydb.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
@@ -1,9 +1,9 @@
1
1
  import { o as cancellableSleep, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
2
  import { n as stripAnsi, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
3
- import { q as resolveProjectSettings } from "./settings-RKwY33wv.mjs";
4
- import { C as resolvePackageJson } from "./project-Dz-hWkb-.mjs";
3
+ import { J as resolveProjectSettings } from "./settings-CosW5X-S.mjs";
4
+ import { C as resolvePackageJson } from "./project-BUu6Is4k.mjs";
5
5
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
6
- import { a as expoMetroStoreEnv, c as registerMetroStore, f as resolveMetroSharedCache, i as expoMetroConfigPath, n as supervisorError, o as metroStoreConfirmedRoot, s as metroStoreRoot } from "./errors-ccaPc4ox.mjs";
6
+ import { a as expoMetroStoreEnv, c as registerMetroStore, f as resolveMetroSharedCache, i as expoMetroConfigPath, n as supervisorError, o as metroStoreConfirmedRoot, s as metroStoreRoot } from "./errors-DHm_U5gv.mjs";
7
7
  import { accessSync, constants, existsSync, readFileSync } from "node:fs";
8
8
  import { delimiter, dirname, join } from "node:path";
9
9
  import { LOG_ROTATE_BYTES } from "@stim-cli/core";
@@ -249,7 +249,7 @@ function recordFromLine(line, { stream = "stdout", source = "expo" } = {}) {
249
249
  if (!msg.trim()) return null;
250
250
  if (stream === "stderr" && msg.startsWith("stim-bundle-response: ")) try {
251
251
  const record = JSON.parse(msg.slice(22));
252
- if (record.src === "metro" && /^bundle_(response|prefetch)_(started|progress|finished|failed)$/.test(record.event) && ["ios", "android"].includes(record.platform) && typeof record.requestId === "string" && Number.isFinite(record.ts)) return record;
252
+ if (record.src === "metro" && /^(?:bundle_(?:response|prefetch)_(?:started|progress|finished|failed)|manifest_request_(?:started|finished|failed))$/.test(record.event) && ["ios", "android"].includes(record.platform) && typeof record.requestId === "string" && Number.isFinite(record.ts)) return record;
253
253
  } catch {}
254
254
  const confirmed = metroStoreConfirmedRoot(msg);
255
255
  if (confirmed) return {
@@ -286,7 +286,7 @@ function parseExpoWaitingOnUrl(line) {
286
286
  if (HTTP_SCHEME_RE.test(url)) return url;
287
287
  return URL_SCHEME_RE.test(url) ? url.replace(/^[^:]+:/, "https:") : url;
288
288
  }
289
- function resolveMetroStoreInjection(root, { log, env, settings }) {
289
+ function resolveMetroStoreInjection(root, { log, env, settings, port }) {
290
290
  const sharedCache = resolveMetroSharedCache(settings);
291
291
  if (!sharedCache) log.write({
292
292
  src: "metro",
@@ -317,6 +317,7 @@ function resolveMetroStoreInjection(root, { log, env, settings }) {
317
317
  const storeRoot = sharedCache ? metroStoreRoot(root) : "";
318
318
  const additions = expoMetroStoreEnv({
319
319
  root,
320
+ port,
320
321
  storeRoot,
321
322
  adapterPath,
322
323
  existingOverride: env.EXPO_OVERRIDE_METRO_CONFIG
@@ -350,7 +351,8 @@ async function startExpoServer({ root, port, logsDir, writer = null, spawnFn = n
350
351
  const storeEnv = resolveMetroStoreInjection(root, {
351
352
  log,
352
353
  env: process.env,
353
- settings: settings ?? resolveProjectSettings(root).settings
354
+ settings: settings ?? resolveProjectSettings(root).settings,
355
+ port
354
356
  });
355
357
  const [command, commandArgs] = platform === "win32" && resolved.source === "package" ? [process.execPath, [bin, ...args]] : [bin, args];
356
358
  const node = withProjectNode(root, process.env);
@@ -0,0 +1,2 @@
1
+ import { m as startExpoServer } from "./server-expo-eQfOdydb.mjs";
2
+ export { startExpoServer };