stim 1.14.0 → 1.16.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 (152) hide show
  1. package/README.md +2 -0
  2. package/dist/activity-BxwdD81S.mjs +609 -0
  3. package/dist/agent-device-usage-output-Dpih1Tfa.mjs +411 -0
  4. package/dist/{android-d6rGq1pA.mjs → android-B_NumVyQ.mjs} +169 -81
  5. package/dist/{android-LbPFRWVL.mjs → android-Ift4kVvt.mjs} +517 -413
  6. package/dist/android-cas-8U4DPqeR.mjs +167 -0
  7. package/dist/android-cas-compiler.mjs +2 -2
  8. package/dist/{android-XpvCrV7q.mjs → android-r2rBL8kV.mjs} +2 -2
  9. package/dist/{app-install-BpgSgkJj.mjs → app-install-CKWdbXIX.mjs} +128 -151
  10. package/dist/attempt-Bk2ouQVL.mjs +39 -0
  11. package/dist/budget-DjrURfQn.mjs +2700 -0
  12. package/dist/{build-plan-Dcr-3ie0.mjs → build-plan-DjeSb2Xl.mjs} +192 -653
  13. package/dist/build-slots-rUk77xqh.mjs +132 -0
  14. package/dist/{cache-manifest-C68QQ0ua.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
  15. package/dist/cache-manifest.mjs +1 -1
  16. package/dist/{chrome-BPCiC3ZX.mjs → chrome-BrcVWQyD.mjs} +1 -1
  17. package/dist/cli-BkYZ_6hy.mjs +51 -0
  18. package/dist/cli.mjs +6 -42
  19. package/dist/client-BTY686R6.mjs +1368 -0
  20. package/dist/collector-run.mjs +9 -195
  21. package/dist/{command-output-DVcpw6eE.mjs → command-output-DnJMdEY-.mjs} +1 -1
  22. package/dist/{config-lvc7d3C2.mjs → config-D0DbpZtM.mjs} +28 -29
  23. package/dist/{created-devices-CllH_8eb.mjs → created-devices-D5owjN4C.mjs} +2 -2
  24. package/dist/{dependency-state-DsT7aKeo.mjs → dependency-state-B6cMXZab.mjs} +2 -2
  25. package/dist/{deps-D9IcKqXS.mjs → deps-urbmfXig.mjs} +3 -3
  26. package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
  27. package/dist/dev-client-CroAIjjj.mjs +43 -0
  28. package/dist/{device-CjuuAJjQ.mjs → device-DZQjF7H5.mjs} +8 -7
  29. package/dist/device-capacity-BHwxNBlu.mjs +136 -0
  30. package/dist/device-host-worker.d.mts +1 -0
  31. package/dist/device-host-worker.mjs +964 -0
  32. package/dist/device-ios-BadmeL2V.mjs +381 -0
  33. package/dist/{device-lease-5c3WrVRm.mjs → device-lease-D-hLqx1b.mjs} +43 -36
  34. package/dist/{device-pool-BiyDyPP-.mjs → device-lease-run-CqjShqWW.mjs} +6 -126
  35. package/dist/device-pool-CUaEWMMm.mjs +125 -0
  36. package/dist/{device-remote-D87zEzaq.mjs → device-remote-D5WVWqOq.mjs} +69 -163
  37. package/dist/{doctor-x9pnU9fq.mjs → doctor-Cimf-gGB.mjs} +241 -103
  38. package/dist/{error-diagnostics-C5HzcwCW.mjs → error-diagnostics-B9L4Ae0x.mjs} +15 -18
  39. package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
  40. package/dist/{gc-ko6mUAYD.mjs → gc-Bqy4bjEu.mjs} +599 -108
  41. package/dist/{android-cas-iZK3DOCr.mjs → gradle-BsO1MdsH.mjs} +8 -294
  42. package/dist/{guide-6R0VNFqI.mjs → guide-B_uyKTxW.mjs} +2511 -239
  43. package/dist/{guide-status-BZrFPIA_.mjs → guide-status-CjEZMAD4.mjs} +3 -3
  44. package/dist/hosted-client-a-WmqE2L.mjs +197 -0
  45. package/dist/hosted-ios-CIWelIqf.mjs +220 -0
  46. package/dist/hosted-logs-D5g041Q3.mjs +187 -0
  47. package/dist/hosted-macos-BSZyIb3y.mjs +135 -0
  48. package/dist/idle-DYVymG92.mjs +1099 -0
  49. package/dist/idle-shutdown-CTsDnAde.mjs +122 -0
  50. package/dist/in-use-DvBw0Kxo.mjs +130 -0
  51. package/dist/{ios-BwDPrnYQ.mjs → ios-BaInn3sW.mjs} +201 -10
  52. package/dist/ios-Cr1h5gnO.mjs +189 -0
  53. package/dist/{ios-P1f5nm2n.mjs → ios-aq3QoGI3.mjs} +1159 -633
  54. package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
  55. package/dist/{ios-device-DGglU3E_.mjs → ios-device-FfCN_C8p.mjs} +12 -7
  56. package/dist/ios-state-DS5UpYTH.mjs +48 -0
  57. package/dist/{launch-verify-Deg4tB3Z.mjs → launch-verify-2DBRizjo.mjs} +5 -5
  58. package/dist/logs-CHEVK8zD.mjs +371 -0
  59. package/dist/machines-BIBUdhpj.mjs +265 -0
  60. package/dist/macos-CSYEAFmF.mjs +473 -0
  61. package/dist/macos-run.d.mts +5 -0
  62. package/dist/macos-run.mjs +2 -0
  63. package/dist/maintenance-run.d.mts +4 -0
  64. package/dist/maintenance-run.mjs +254 -0
  65. package/dist/{metro-CcEo8Fl8.mjs → metro-BeK1ZPz1.mjs} +20 -120
  66. package/dist/metro-gateway-BJ-rxQAB.mjs +84 -0
  67. package/dist/{named-ports-Blg8IxOh.mjs → named-ports-Bk_YXEmE.mjs} +6 -59
  68. package/dist/native-run-NaBrRFtQ.mjs +147 -0
  69. package/dist/{native-runtime-DjBHRg5m.mjs → native-runtime-DBzRnEKS.mjs} +9 -5
  70. package/dist/{ndjson-CDY9IkVC.mjs → ndjson-PclOIwVY.mjs} +2 -2
  71. package/dist/offload-worker.d.mts +122 -0
  72. package/dist/offload-worker.mjs +606 -0
  73. package/dist/{ownership-DyYDF5ww.mjs → ownership-DiA16AsN.mjs} +3 -2
  74. package/dist/ownership-hCkPzGmr.mjs +571 -0
  75. package/dist/{page-BHUzTDFt.mjs → page-QF_Ke10s.mjs} +7 -2
  76. package/dist/{ports-BguS83ex.mjs → ports-R2k4Knz3.mjs} +3 -3
  77. package/dist/prebuild-D2fsca_Z.mjs +213 -0
  78. package/dist/preview-DhVbvPAZ.mjs +318 -0
  79. package/dist/process-identity-BmRm1qV0.mjs +12 -0
  80. package/dist/{project-CWlvEaeN.mjs → project-Du91Ilvc.mjs} +74 -19
  81. package/dist/pull-request-pxnDCQzn.mjs +322 -0
  82. package/dist/pull-requests.d.mts +120 -0
  83. package/dist/pull-requests.mjs +2 -0
  84. package/dist/recordings-BIXOzVnr.mjs +37 -0
  85. package/dist/{reload-BiniwsSZ.mjs → reload-rM9jV1fz.mjs} +109 -24
  86. package/dist/{remote-cache-CcR6o6lI.mjs → remote-cache-C8-V13XN.mjs} +5 -5
  87. package/dist/run-f4vI6EnK.mjs +119 -0
  88. package/dist/{server-bare-DGfgyJ5J.mjs → server-bare-CpPGmnmO.mjs} +33 -15
  89. package/dist/server-expo-CVqO2c35.mjs +2 -0
  90. package/dist/{server-expo-BVuwQ65v.mjs → server-expo-MC0rHlOC.mjs} +8 -12
  91. package/dist/settings-BBpMcDbD.mjs +25 -0
  92. package/dist/{settings-B-fsC-Om.mjs → settings-ZkDzkzvB.mjs} +22 -10
  93. package/dist/settings-oTSkkNrM.mjs +1439 -0
  94. package/dist/settings.schema.json +845 -97
  95. package/dist/{simslim-DrDN4WuV.mjs → simslim-B8-7AoTI.mjs} +8 -132
  96. package/dist/{slot-launch-D5t8EiMf.mjs → slot-launch-B8VrHxn1.mjs} +11 -8
  97. package/dist/{spawn-claims-Drw_o-Fb.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
  98. package/dist/spawn-entry-jw19m8Nl.mjs +17 -0
  99. package/dist/stage-CzaiwFsI.mjs +143 -0
  100. package/dist/start-CX8Ig-U2.mjs +2 -0
  101. package/dist/{start-s4RXp1wy.mjs → start-ClDfwXa4.mjs} +116 -65
  102. package/dist/state-3DwSQIBK.mjs +41 -0
  103. package/dist/state-B4PQFXMW.d.mts +12 -0
  104. package/dist/{state-Dk9RVXI7.mjs → state-C1jB7Q8q.mjs} +70 -8
  105. package/dist/{state-DHqvsbqC.mjs → state-DcW6vOd_.mjs} +7 -4
  106. package/dist/stats-CEZ_i5je.mjs +77 -0
  107. package/dist/{status-BgAuxESg.mjs → status-BuvBFeII.mjs} +118 -20
  108. package/dist/{status-BsPAnfOI.mjs → status-Cs7VLg9D.mjs} +542 -283
  109. package/dist/status-DlKvVJBE.mjs +49 -0
  110. package/dist/stdout-reader-C8yjre1x.mjs +23 -0
  111. package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
  112. package/dist/stim-footprint.swift +32 -0
  113. package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
  114. package/dist/stop-B0Yxtmiy.mjs +48 -0
  115. package/dist/{stop-BzreOWJp.mjs → stop-Bffozsac.mjs} +83 -16
  116. package/dist/{stop-BWIF_6BK.mjs → stop-Dt_dM16A.mjs} +2 -2
  117. package/dist/stop-cause-CidxIqup.mjs +97 -0
  118. package/dist/supervisor-run.d.mts +43 -11
  119. package/dist/supervisor-run.mjs +363 -24
  120. package/dist/support-CAP8qDUF.mjs +316 -0
  121. package/dist/support-D4aYJniO.mjs +201 -0
  122. package/dist/teardown-CL6vDs2Y.mjs +727 -0
  123. package/dist/{xcode-Cp5KvK9x.mjs → toolchain-DkUflduf.mjs} +364 -14
  124. package/dist/trigger-Bemu8ytw.mjs +65 -0
  125. package/dist/trigger-CXts6qt1.mjs +2 -0
  126. package/dist/warm-progress-CpGv3Wb6.mjs +732 -0
  127. package/dist/{web-BsQs1WlO.mjs → web-DWUaMp8P.mjs} +37 -21
  128. package/dist/web-run.mjs +310 -13
  129. package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
  130. package/dist/workspace-state-B8-aJ1_5.mjs +371 -0
  131. package/dist/workspaces-BV4pdHFz.mjs +306 -0
  132. package/dist/{worktree-UrQWXSeb.mjs → worktree-K-xj9Db0.mjs} +625 -256
  133. package/dist/worktree-jnG8Iph5.mjs +2 -0
  134. package/package.json +10 -5
  135. package/shim/bundle-response.cjs +28 -12
  136. package/dist/activity-CYVDcrt3.mjs +0 -356
  137. package/dist/budget-CGDkhvv_.mjs +0 -1745
  138. package/dist/build-progress-DxKpwnaS.mjs +0 -247
  139. package/dist/idle-DXtx3RbX.mjs +0 -191
  140. package/dist/in-use-DlqBDKqY.mjs +0 -249
  141. package/dist/logs-Civ4gbBH.mjs +0 -486
  142. package/dist/merge-state-ytFQCeh4.mjs +0 -262
  143. package/dist/server-expo-DIHDhvGg.mjs +0 -2
  144. package/dist/settings-D61iNOsB.mjs +0 -629
  145. package/dist/start-Cetfvy8l.mjs +0 -2
  146. package/dist/stats-CFpFGlJV.mjs +0 -62
  147. package/dist/stats-CX1Z8Tca.mjs +0 -368
  148. package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
  149. package/dist/stop-cause-hjGBOZTG.mjs +0 -1231
  150. package/dist/worktree-BVrHsYZG.mjs +0 -752
  151. package/dist/worktree-CHWWvm5v.mjs +0 -2
  152. package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
@@ -1,7 +1,10 @@
1
- import { U as projectDeviceSlots, z as deviceSlotKey } from "./config-lvc7d3C2.mjs";
2
- import { a as formatElapsed, o as formatLongDuration, r as clockTime, u as plural } from "./command-output-DVcpw6eE.mjs";
3
- import { r as cdpEndpoint } from "./state-Dk9RVXI7.mjs";
4
- import { sep } from "path";
1
+ import { H as projectDeviceSlots, R as deviceSlotKey } from "./config-D0DbpZtM.mjs";
2
+ import { a as formatElapsed, o as formatLongDuration, r as clockTime, u as plural } from "./command-output-DnJMdEY-.mjs";
3
+ import { n as isInsideProject } from "./metro-BeK1ZPz1.mjs";
4
+ import { g as workspaceAgentDeviceDir } from "./workspace-state-B8-aJ1_5.mjs";
5
+ import { r as cdpEndpoint } from "./state-C1jB7Q8q.mjs";
6
+ import { basename, sep } from "path";
7
+ import { ACTIVITY_RECENCY_BASES } from "@stim-cli/core/state";
5
8
  //#region src/status.ts
6
9
  const IOS_SIM_MB = 1500;
7
10
  const ANDROID_EMULATOR_MB = 2500;
@@ -31,7 +34,7 @@ function avdExpected({ slot, serial, launches, leasedIds, running, now }) {
31
34
  if (!launch) return false;
32
35
  return running || now - Date.parse(launch.launchedAt) < 18e5;
33
36
  }
34
- function androidStatus(android, androidRuntime, androidDeviceProfile) {
37
+ function androidStatus(android, androidRuntime, androidDeviceProfile, facts) {
35
38
  if (!android) return null;
36
39
  return {
37
40
  name: android.avdName ?? android.serial,
@@ -41,16 +44,20 @@ function androidStatus(android, androidRuntime, androidDeviceProfile) {
41
44
  serial: androidRuntime.serial,
42
45
  state: androidRuntime.state
43
46
  } : {},
44
- ...androidDeviceProfile ? { deviceProfile: androidDeviceProfile } : {}
47
+ ...androidDeviceProfile ? { deviceProfile: androidDeviceProfile } : {},
48
+ ...facts
45
49
  };
46
50
  }
51
+ function idleShutdownFact(stopped, record) {
52
+ return stopped && record ? { idleShutdown: record } : {};
53
+ }
47
54
  function stoppedMetroFacts(idleStop, lastStop) {
48
55
  return {
49
56
  ...idleStop ? { idleStop } : {},
50
57
  ...lastStop ? { lastStop } : {}
51
58
  };
52
59
  }
53
- function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, androidRuntime = null, androidRuntimes = {}, androidDeviceProfile = null, androidDeviceProfiles = {}, supervisor = null, logs = null, remote = null, idleStop = null, lastStop = null, launches = {}, leasedIds = /* @__PURE__ */ new Set(), now = Date.now(), slot = "default", workspaceRunning = false } = {}) {
60
+ function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, androidRuntime = null, androidRuntimes = {}, androidDeviceProfile = null, androidDeviceProfiles = {}, supervisor = null, logs = null, remote = null, idleStop = null, lastStop = null, idleShutdowns = {}, launches = {}, leasedIds = /* @__PURE__ */ new Set(), now = Date.now(), slot = "default", workspaceRunning = false, workspaces } = {}) {
54
61
  const ios = project.platforms?.ios;
55
62
  const android = project.platforms?.android;
56
63
  const sim = ios ? simsByUdid[ios.deviceUdid] : null;
@@ -73,9 +80,9 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
73
80
  ...slot === "default" ? {} : { slot }
74
81
  });
75
82
  const slotFlag = slot === "default" ? "" : ` --slot ${slot}`;
76
- if (metro?.notOurs && slot === "default") add("port-not-ours", `port ${project.metroPort}: ${metro.notOurs}`, "stim guide errors teardown", "error");
77
- if (ios && !sim && simsAvailable) add("sim-missing", `recorded sim ${ios.deviceUdid} no longer exists`, `stim ios${slotFlag}`);
78
- if (simBooted && project.metroPort && !metroRunning) add("sim-without-metro", "simulator is booted with no Metro serving it", "stim start");
83
+ if (metro?.notOurs && slot === "default") add("port-not-ours", ...portNotOurs(project.metroPort, portHolder(metro.cwd, project.__path, workspaces), supervisor));
84
+ if (ios && !sim && simsAvailable) add("sim-missing", `recorded sim ${ios.deviceUdid} no longer exists`, `stim ios${slotFlag}`, "info");
85
+ if (simBooted && project.metroPort && !metroRunning) add("sim-without-metro", "simulator is booted with no Metro serving it", "stim start", "info");
79
86
  if (androidRuntime && android?.avdName) {
80
87
  const recordedSerial = android.consolePort ? `emulator-${android.consolePort}` : android.serial;
81
88
  const expected = avdExpected({
@@ -86,7 +93,7 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
86
93
  running,
87
94
  now
88
95
  });
89
- for (const [code, message] of androidIssues(android, recordedSerial, androidRuntime, expected)) add(code, message, code === "avd-unchecked" ? "stim doctor" : `stim android${slotFlag}`);
96
+ for (const [code, message, severity] of androidIssues(android, recordedSerial, androidRuntime, expected)) add(code, message, code === "avd-unchecked" ? "stim doctor" : `stim android${slotFlag}`, severity);
90
97
  }
91
98
  if (supervisor?.status === "unverified") add("supervisor-unverified", `supervisor pid ${supervisor.pid} could not be verified${supervisor.reason ? `: ${supervisor.reason}` : ""}`, "stim guide errors teardown", "error");
92
99
  const slots = [];
@@ -101,6 +108,7 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
101
108
  metro,
102
109
  androidRuntime: androidRuntimes[name],
103
110
  androidDeviceProfile: androidDeviceProfiles[name],
111
+ idleShutdowns,
104
112
  launches,
105
113
  leasedIds,
106
114
  now,
@@ -121,20 +129,23 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
121
129
  ...slots.length ? { slots } : {},
122
130
  live,
123
131
  memoryMb,
124
- warnings: issues.map(issueText),
132
+ memorySource: "estimate",
133
+ warnings: warningTexts(issues),
125
134
  issues,
126
135
  ios: ios ? {
127
136
  name: sim?.name ?? null,
128
137
  udid: ios.deviceUdid,
129
138
  owned: Boolean(ios.owned),
130
- state: sim?.state ?? (simsAvailable ? "missing" : "unknown")
139
+ state: sim?.state ?? (simsAvailable ? "missing" : "unknown"),
140
+ ...idleShutdownFact(!simBooted && sim, idleShutdowns[deviceSlotKey("ios", slot)])
131
141
  } : null,
132
- android: androidStatus(android, androidRuntime, androidDeviceProfile),
142
+ android: androidStatus(android, androidRuntime, androidDeviceProfile, idleShutdownFact(!androidDetected, idleShutdowns[deviceSlotKey("android", slot)])),
133
143
  metro: project.metroPort ? {
134
144
  port: project.metroPort,
135
145
  running: metroRunning,
136
146
  pid: metro?.metro?.pid ?? null,
137
- ...metroRunning ? {} : stoppedMetroFacts(idleStop, lastStop)
147
+ ...metroRunning ? {} : stoppedMetroFacts(idleStop, lastStop),
148
+ ...portHeldBy(metro)
138
149
  } : null,
139
150
  supervisor: supervisor && supervisor.status !== "stale" ? {
140
151
  pid: supervisor.pid ?? null,
@@ -142,6 +153,7 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
142
153
  startedAt: supervisor.startedAt ?? null,
143
154
  healthy: Boolean(supervisor.healthy)
144
155
  } : null,
156
+ agentDevice: { stateDir: workspaceAgentDeviceDir(project.__path) },
145
157
  logs: logs ? {
146
158
  dir: logs.dir,
147
159
  errorsSinceMarker: logs.errorsSinceMarker ?? 0
@@ -150,6 +162,14 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
150
162
  remoteDevices: remote ? [remote] : []
151
163
  };
152
164
  }
165
+ /** Sets each environment's `memoryMb` to the sum of its owners' footprints; without footprints it keeps the estimate. */
166
+ function applyMachineMemory(states, machine) {
167
+ if (machine.memorySource !== "footprint") return;
168
+ for (const state of states) {
169
+ state.memoryMb = machine.owners.reduce((sum, owner) => owner.workspace === state.path ? sum + owner.memoryMb : sum, 0);
170
+ state.memorySource = machine.memorySource;
171
+ }
172
+ }
153
173
  /** Adds the workspace's owned Chrome to its status: the web entry, its memory, and an unverifiable browser. */
154
174
  function withWebFacts(state, web) {
155
175
  if (!web) return state;
@@ -173,7 +193,7 @@ function withWebFacts(state, web) {
173
193
  ...state,
174
194
  live: state.live || running || web.status === "orphaned",
175
195
  memoryMb: state.memoryMb + (running || web.status === "orphaned" ? BROWSER_MB : 0),
176
- warnings: issues.map(issueText),
196
+ warnings: warningTexts(issues),
177
197
  issues,
178
198
  web: webBrowserState(web)
179
199
  };
@@ -190,20 +210,94 @@ function webBrowserState({ record, status }) {
190
210
  headless: record.headless,
191
211
  viewport: record.viewport,
192
212
  profile: record.profile,
193
- cdpEndpoint: running ? cdpEndpoint(record.cdpPort) : null
213
+ cdpEndpoint: running ? cdpEndpoint(record.cdpPort) : null,
214
+ targetId: running ? record.targetId ?? null : null
194
215
  };
195
216
  }
196
217
  function androidIssues(android, recordedSerial, runtime, expected) {
197
218
  const issues = [];
198
219
  if (runtime.serial && recordedSerial && runtime.serial !== recordedSerial) issues.push(["avd-serial-changed", `owned AVD ${android.avdName} changed serial (${recordedSerial} -> ${runtime.serial}), so Metro forwarding is lost; rerun with the same build options, then reopen agent-device on ${runtime.serial}`]);
199
- if (runtime.state === "missing") issues.push(["avd-missing", `recorded AVD ${android.avdName} no longer exists`]);
220
+ if (runtime.state === "missing") issues.push([
221
+ "avd-missing",
222
+ `recorded AVD ${android.avdName} no longer exists`,
223
+ "info"
224
+ ]);
200
225
  if (runtime.state === "not-detected" && expected) issues.push(["avd-not-detected", `owned AVD ${android.avdName} is not detected by adb`]);
201
226
  if (runtime.error) issues.push(["avd-unchecked", `could not check owned AVD ${android.avdName}: ${runtime.error}`]);
202
227
  return issues;
203
228
  }
229
+ /**
230
+ * The owned emulators worth an `adb reverse --list`: each runs this workspace's debug app, launched onto that serial
231
+ * against the Metro port that is serving now.
232
+ */
233
+ function metroReverseTargets(state, launches) {
234
+ const metroPort = state.metro?.running ? state.metro.port : null;
235
+ if (!metroPort) return [];
236
+ return [{
237
+ slot: "default",
238
+ android: state.android
239
+ }, ...state.slots ?? []].flatMap(({ slot, android }) => {
240
+ const launch = launches[deviceSlotKey("android", slot)];
241
+ if (!android?.owned || android.physical || !android.serial || android.app?.state !== "running") return [];
242
+ if (!launch || launch.release || launch.metroPort !== metroPort || launch.deviceId !== android.serial) return [];
243
+ return [{
244
+ slot,
245
+ serial: android.serial,
246
+ metroPort
247
+ }];
248
+ });
249
+ }
250
+ function addReverseMissingIssue(state, { slot, serial, metroPort }) {
251
+ const issue = {
252
+ code: "android-reverse-missing",
253
+ severity: "warning",
254
+ message: `the adb reverse for Metro port ${metroPort} is missing on ${serial}, so the app cannot reach Metro`,
255
+ remedy: "stim reload android",
256
+ workspace: state.path,
257
+ ...slot === "default" ? {} : { slot }
258
+ };
259
+ state.issues.push(issue);
260
+ state.warnings.push(issueText(issue));
261
+ }
262
+ function portNotOurs(port, holder, supervisor) {
263
+ if (supervisor?.status === "ours") return [
264
+ `port ${port} is in use by ${holder}, so this workspace's Metro cannot serve on it`,
265
+ "stim stop",
266
+ "warning"
267
+ ];
268
+ if (supervisor?.status === "unverified") return [
269
+ `port ${port} is in use by ${holder}`,
270
+ "stim guide errors teardown",
271
+ "warning"
272
+ ];
273
+ return [
274
+ `port ${port} is in use by ${holder}; stim start will choose a free port`,
275
+ "stim start",
276
+ "info"
277
+ ];
278
+ }
279
+ function portHeldBy(metro) {
280
+ return metro?.notOurs && metro.pid ? { heldBy: {
281
+ pid: metro.pid,
282
+ cwd: metro.cwd ?? null
283
+ } } : {};
284
+ }
285
+ function warningTexts(issues) {
286
+ return issues.filter((issue) => issue.severity !== "info").map(issueText);
287
+ }
288
+ function portHolder(cwd, self, workspaces = []) {
289
+ if (!cwd) return "another app";
290
+ const owner = workspaces.filter((path) => path !== self && isInsideProject(cwd, path)).toSorted((a, b) => b.length - a.length)[0];
291
+ if (owner) return `Metro for workspace ${basename(owner)}`;
292
+ return `a dev server in ${cwd.split(/[\\/]/).filter(Boolean).slice(-3).join("/")}`;
293
+ }
204
294
  function issueText(issue) {
205
295
  return `${issue.slot ? `${issue.slot}: ` : ""}${issue.message}; run \`${issue.remedy}\``;
206
296
  }
297
+ function toMinute(iso) {
298
+ const time = Date.parse(iso);
299
+ return (/* @__PURE__ */ new Date(time - time % 6e4)).toISOString();
300
+ }
207
301
  /**
208
302
  * Activity as status reports it: `lastActivityAt` rounded down to the minute, the precision its readers show, so a
209
303
  * new log record within the same minute does not change the payload.
@@ -213,7 +307,11 @@ function statusActivity(activity) {
213
307
  if (!Number.isFinite(at)) return activity;
214
308
  return {
215
309
  ...activity,
216
- lastActivityAt: (/* @__PURE__ */ new Date(at - at % 6e4)).toISOString()
310
+ lastActivityAt: toMinute(activity.lastActivityAt),
311
+ ...activity.recent ? { recent: Object.fromEntries(ACTIVITY_RECENCY_BASES.flatMap((basis) => {
312
+ const iso = activity.recent?.[basis];
313
+ return iso ? [[basis, toMinute(iso)]] : [];
314
+ })) } : {}
217
315
  };
218
316
  }
219
317
  function activityLabel(activity, now) {
@@ -335,4 +433,4 @@ function deviceLeaseLines(states, now) {
335
433
  return lines;
336
434
  }
337
435
  //#endregion
338
- export { withWebFacts as _, deviceLeaseStates as a, formatSpace as c, poolLine as d, remoteDeviceLine as f, unprovisionedWorktrees as g, tightVolumes as h, deviceLeaseLines as i, gitSummaryText as l, statusActivity as m, activityLabel as n, diskLine as o, remoteDeviceState as p, capacity as r, environmentState as s, RECENT_LAUNCH_MS as t, parseDfFree as u };
436
+ export { statusActivity as _, capacity as a, withWebFacts as b, diskLine as c, gitSummaryText as d, metroReverseTargets as f, remoteDeviceState as g, remoteDeviceLine as h, applyMachineMemory as i, environmentState as l, poolLine as m, activityLabel as n, deviceLeaseLines as o, parseDfFree as p, addReverseMissingIssue as r, deviceLeaseStates as s, RECENT_LAUNCH_MS as t, formatSpace as u, tightVolumes as v, unprovisionedWorktrees as y };