stim 1.8.0 → 1.10.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.
- package/README.md +23 -155
- package/dist/{android-DWssqHQ8.mjs → android-787HhP5w.mjs} +168 -39
- package/dist/{android-BRgBYzU0.mjs → android-DBkeHwpm.mjs} +250 -200
- package/dist/{android-DeYdjjBP.mjs → android-DPov-fv2.mjs} +2 -2
- package/dist/{android-cas-SWIjzeuL.mjs → android-cas-CITmIeWY.mjs} +22 -14
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/app-install-CrJ6t_bv.mjs +819 -0
- package/dist/budget-BP4jZZL4.mjs +620 -0
- package/dist/build-progress-BXx-ZBe4.mjs +512 -0
- package/dist/{cache-manifest-CYJi8-Hx.mjs → cache-manifest-Pubfp8wV.mjs} +4 -4
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +22 -19
- package/dist/collector-run.d.mts +7 -1
- package/dist/collector-run.mjs +10 -9
- package/dist/{command-output-B3ycpsYv.mjs → command-output-D5z2_bcF.mjs} +11 -2
- package/dist/{config-B7iyKWkL.mjs → config-BEq0Qw_a.mjs} +134 -121
- package/dist/{dependency-state-D0M7oKA7.mjs → dependency-state-r9UesA9a.mjs} +2 -2
- package/dist/{deps-oCXVNEqQ.mjs → deps-DP4eWqea.mjs} +8 -5
- package/dist/{detached-entry-Bpo6ZY_I.mjs → detached-entry-DJHoca49.mjs} +1 -1
- package/dist/{device-BUoZyMoR.mjs → dev-client-92U593KT.mjs} +1090 -660
- package/dist/{device-RdujjHLB.mjs → device-DhTZe7L4.mjs} +13 -20
- package/dist/{build-lock-CgtsB6TV.mjs → device-lease-CbEaIk7b.mjs} +481 -27
- package/dist/{device-pool-BxRwdufO.mjs → device-pool-Di8Q-9Ro.mjs} +7 -7
- package/dist/{device-remote-ByN8P6CB.mjs → device-remote-Dy1jGj3U.mjs} +645 -119
- package/dist/{doctor-BMt156qe.mjs → doctor-B-inAJmt.mjs} +137 -113
- package/dist/{error-diagnostics-D1Kaf-eT.mjs → error-diagnostics-xxWKNO3-.mjs} +22 -17
- package/dist/exec-DK8KaVHK.mjs +133 -0
- package/dist/{gc-v2YcoJvm.mjs → gc-ChPFZMRC.mjs} +836 -813
- package/dist/{guide-BTAlD1_y.mjs → guide-DwmaD_Wa.mjs} +953 -209
- package/dist/guide-status-CWvti2Lg.mjs +125 -0
- package/dist/idle-DpRLp5lj.mjs +157 -0
- package/dist/{build-slots-C-oAHRT1.mjs → in-use-CjUluqIX.mjs} +102 -8
- package/dist/{ios-BcCiI4TS.mjs → ios-B2Fpqvlb.mjs} +60 -71
- package/dist/{ios-BP04pY5f.mjs → ios-Dd-hYJBh.mjs} +241 -234
- package/dist/{ios-device-CFXA46ez.mjs → ios-device-BiOsSVzd.mjs} +3 -2
- package/dist/{ios-device-CauFJiYx.mjs → ios-device-CtRdEVjx.mjs} +149 -52
- package/dist/launch-verify-CQS_Kg-C.mjs +365 -0
- package/dist/{logs-CakdBTtm.mjs → logs-MARIy6m9.mjs} +20 -15
- package/dist/metro-BWLOJ_Wr.mjs +409 -0
- package/dist/{named-ports-DzMOlmaX.mjs → named-ports-DiTfSz6p.mjs} +4 -4
- package/dist/{ndjson-BZwI1NBv.mjs → ndjson-CDY9IkVC.mjs} +23 -43
- package/dist/{ndjson-DvHSsNU9.d.mts → ndjson-Du3j0AQ9.d.mts} +1 -0
- package/dist/{ownership-Cp52QAK1.mjs → ownership-D2xbLVoz.mjs} +2 -3
- package/dist/{teardown-BJqEzPo_.mjs → ownership-DZjdx8Gq.mjs} +664 -612
- package/dist/{ports-BIbJaKNW.mjs → ports-CLSSFOuz.mjs} +3 -3
- package/dist/{process-output-Dl5uKE03.mjs → process-output-Fpl8PYi8.mjs} +1 -1
- package/dist/{project-DDZWf_16.mjs → project-BXZzOABt.mjs} +8 -3
- package/dist/{reload-BdypPbjM.mjs → reload-DoETJ3rl.mjs} +11 -13
- package/dist/{server-bare-BQkyxa_b.mjs → server-bare-DVbb7kXH.mjs} +2 -2
- package/dist/{server-expo-BVAA1OqJ.mjs → server-expo-BvOCeakp.mjs} +8 -7
- package/dist/server-expo-DBVTdult.mjs +2 -0
- package/dist/{settings-BXXorVM2.mjs → settings-DOugPlPz.mjs} +59 -159
- package/dist/settings-EWYNwe72.mjs +378 -0
- package/dist/settings.schema.json +1064 -0
- package/dist/simslim-Ca3487H6.mjs +436 -0
- package/dist/{slot-launch-ZUUe0TQP.mjs → slot-launch-C5cg0fmk.mjs} +4 -4
- package/dist/spawn-claims-CUleC2cM.mjs +49 -0
- package/dist/{start-CmxtOKjU.mjs → start-F9gv5dcC.mjs} +159 -114
- package/dist/start-VoFsPSes.mjs +2 -0
- package/dist/{state-DZobzxLW.mjs → state-WGdIbi_d.mjs} +5 -3
- package/dist/{stats-BYcZ6n1h.mjs → stats-BAgJaLA4.mjs} +66 -5
- package/dist/{stats-CLg5RuDS.mjs → stats-DBYJ5bxL.mjs} +4 -4
- package/dist/status-DLCD-o3s.mjs +764 -0
- package/dist/status-Dr4fRkym.mjs +216 -0
- package/dist/{guide-status-Craq9z0t.mjs → stim-installations-CINXy_su.mjs} +3 -122
- package/dist/{stop-C8JW6kKp.mjs → stop-Dj4pfmyv.mjs} +111 -31
- package/dist/{stop-B1kOpYei.mjs → stop-ZvOeTmKb.mjs} +2 -2
- package/dist/supervisor-run.d.mts +11 -2
- package/dist/supervisor-run.mjs +228 -42
- package/dist/{workspace-process-lock-BYfZz_S-.mjs → workspace-process-lock-BXA96myD.mjs} +14 -9
- package/dist/workspaces-BTUyFfkv.mjs +1003 -0
- package/dist/worktree-4aZg2NnI.mjs +2 -0
- package/dist/{worktree-CFLA-6MX.mjs → worktree-BMS7GeqB.mjs} +523 -61
- package/dist/{worktree-FG_ZKKdb.mjs → worktree-BlizKDpZ.mjs} +200 -54
- package/dist/{xcode-B6YaWeg0.mjs → xcode-B2tBkf0m.mjs} +66 -57
- package/package.json +6 -6
- package/skill/SKILL.md +2 -0
- package/dist/app-install-BDbsSgCl.mjs +0 -1175
- package/dist/dev-client-BmT-ioFI.mjs +0 -797
- package/dist/device-lease-Ffz_M5t0.mjs +0 -359
- package/dist/exec-B29XNuhP.mjs +0 -77
- package/dist/logs-query-BGL-Pl12.mjs +0 -290
- package/dist/metro-C7bcJ0uo.mjs +0 -233
- package/dist/ownership-wolE-0Do.mjs +0 -470
- package/dist/public-http-probe-CyMDrQ3c.mjs +0 -61
- package/dist/reclaim-KJ-0uWEF.mjs +0 -361
- package/dist/server-expo-YDDG3eP7.mjs +0 -2
- package/dist/spawn-entry-nCE6m770.mjs +0 -14
- package/dist/status-DdkLki47.mjs +0 -426
- package/dist/workspace-state-BT5E3SA2.mjs +0 -146
- package/dist/{metro-store-CDDZHtPl.mjs → metro-store-DzeWkfqW.mjs} +1 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { H as projectDeviceSlots } from "./config-BEq0Qw_a.mjs";
|
|
2
|
+
import { a as formatElapsed, o as formatLongDuration, r as clockTime, u as plural } from "./command-output-D5z2_bcF.mjs";
|
|
3
|
+
import { sep } from "path";
|
|
4
|
+
//#region src/status.ts
|
|
5
|
+
const IOS_SIM_MB = 1500;
|
|
6
|
+
const ANDROID_EMULATOR_MB = 2500;
|
|
7
|
+
const METRO_MB = 700;
|
|
8
|
+
function remoteDeviceState(record, ledger, root) {
|
|
9
|
+
if (!record) return null;
|
|
10
|
+
const claim = ledger.claims.get(record.sessionId);
|
|
11
|
+
return {
|
|
12
|
+
platform: record.platform,
|
|
13
|
+
backend: "eas",
|
|
14
|
+
sessionId: record.sessionId,
|
|
15
|
+
state: !ledger.safe ? "unknown" : claim?.workspaceRoot === root ? "claimed" : "unclaimed",
|
|
16
|
+
startedAt: record.startedAt,
|
|
17
|
+
webPreviewUrl: record.webPreviewUrl
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function poolLine({ platform, parked, max }) {
|
|
21
|
+
if (parked <= 0) return null;
|
|
22
|
+
const what = plural(parked, `parked ${platform === "ios" ? "iOS simulator" : "Android emulator"}`);
|
|
23
|
+
return max > 0 ? `pool: ${what} (max ${max})` : `pool: ${what} (parking off; gc --delete removes them)`;
|
|
24
|
+
}
|
|
25
|
+
function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, androidRuntime = null, androidRuntimes = {}, supervisor = null, logs = null, remote = null, idleStop = null } = {}) {
|
|
26
|
+
const ios = project.platforms?.ios;
|
|
27
|
+
const android = project.platforms?.android;
|
|
28
|
+
const sim = ios ? simsByUdid[ios.deviceUdid] : null;
|
|
29
|
+
const simBooted = Boolean(sim && sim.state === "Booted");
|
|
30
|
+
const metroRunning = Boolean(metro?.metro);
|
|
31
|
+
const androidDetected = androidRuntime ? Boolean(androidRuntime.serial) : Boolean(android?.serial);
|
|
32
|
+
let live = simBooted || metroRunning || androidDetected || Boolean(remote);
|
|
33
|
+
let memoryMb = 0;
|
|
34
|
+
if (simBooted) memoryMb += IOS_SIM_MB;
|
|
35
|
+
if (androidDetected) memoryMb += ANDROID_EMULATOR_MB;
|
|
36
|
+
if (metroRunning) memoryMb += METRO_MB;
|
|
37
|
+
const warnings = [];
|
|
38
|
+
if (metro?.notOurs) warnings.push(`port ${project.metroPort}: ${metro.notOurs}`);
|
|
39
|
+
if (ios && !sim && simsAvailable) warnings.push(`recorded sim ${ios.deviceUdid} no longer exists`);
|
|
40
|
+
if (simBooted && project.metroPort && !metroRunning) warnings.push("simulator is booted with no Metro serving it");
|
|
41
|
+
if (androidRuntime && android?.avdName) {
|
|
42
|
+
const recordedSerial = android.consolePort ? `emulator-${android.consolePort}` : android.serial;
|
|
43
|
+
if (androidRuntime.serial && recordedSerial && androidRuntime.serial !== recordedSerial) warnings.push(`owned AVD ${android.avdName} changed serial (${recordedSerial} -> ${androidRuntime.serial}); rerun your \`stim android\` command in this workspace to restore Metro forwarding, then reopen agent-device on ${androidRuntime.serial}`);
|
|
44
|
+
if (androidRuntime.state === "missing") warnings.push(`recorded AVD ${android.avdName} no longer exists`);
|
|
45
|
+
if (androidRuntime.state === "not-detected") warnings.push(`owned AVD ${android.avdName} is not detected by adb; rerun your \`stim android\` command in this workspace to reconnect`);
|
|
46
|
+
if (androidRuntime.error) warnings.push(`could not check owned AVD ${android.avdName}: ${androidRuntime.error}`);
|
|
47
|
+
}
|
|
48
|
+
if (supervisor && supervisor.alive === false) warnings.push(`stale supervisor record for ${project.__path}`);
|
|
49
|
+
const slots = [];
|
|
50
|
+
for (const { slot, platforms } of projectDeviceSlots(project).slice(1)) {
|
|
51
|
+
const deviceState = environmentState({
|
|
52
|
+
...project,
|
|
53
|
+
platforms,
|
|
54
|
+
deviceSlots: void 0
|
|
55
|
+
}, {
|
|
56
|
+
simsByUdid,
|
|
57
|
+
simsAvailable,
|
|
58
|
+
metro,
|
|
59
|
+
androidRuntime: androidRuntimes[slot]
|
|
60
|
+
});
|
|
61
|
+
slots.push({
|
|
62
|
+
slot,
|
|
63
|
+
ios: deviceState.ios,
|
|
64
|
+
android: deviceState.android
|
|
65
|
+
});
|
|
66
|
+
memoryMb += deviceState.memoryMb - (metroRunning ? METRO_MB : 0);
|
|
67
|
+
live ||= deviceState.live;
|
|
68
|
+
warnings.push(...deviceState.warnings.map((warning) => `${slot}: ${warning}`));
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
path: project.__path,
|
|
72
|
+
...slots.length ? { slots } : {},
|
|
73
|
+
live,
|
|
74
|
+
memoryMb,
|
|
75
|
+
warnings,
|
|
76
|
+
ios: ios ? {
|
|
77
|
+
name: sim?.name ?? null,
|
|
78
|
+
udid: ios.deviceUdid,
|
|
79
|
+
owned: Boolean(ios.owned),
|
|
80
|
+
state: sim?.state ?? (simsAvailable ? "missing" : "unknown")
|
|
81
|
+
} : null,
|
|
82
|
+
android: android ? {
|
|
83
|
+
name: android.avdName ?? android.serial,
|
|
84
|
+
owned: Boolean(android.owned),
|
|
85
|
+
physical: Boolean(android.serial && !android.avdName),
|
|
86
|
+
...androidRuntime ? {
|
|
87
|
+
serial: androidRuntime.serial,
|
|
88
|
+
state: androidRuntime.state
|
|
89
|
+
} : {}
|
|
90
|
+
} : null,
|
|
91
|
+
metro: project.metroPort ? {
|
|
92
|
+
port: project.metroPort,
|
|
93
|
+
running: metroRunning,
|
|
94
|
+
pid: metro?.metro?.pid ?? null,
|
|
95
|
+
...idleStop && !metroRunning ? { idleStop } : {}
|
|
96
|
+
} : null,
|
|
97
|
+
supervisor: supervisor ? {
|
|
98
|
+
pid: supervisor.pid ?? null,
|
|
99
|
+
mode: supervisor.mode ?? null,
|
|
100
|
+
startedAt: supervisor.startedAt ?? null,
|
|
101
|
+
healthy: Boolean(supervisor.healthy)
|
|
102
|
+
} : null,
|
|
103
|
+
logs: logs ? {
|
|
104
|
+
dir: logs.dir,
|
|
105
|
+
errorsSinceMarker: logs.errorsSinceMarker ?? 0
|
|
106
|
+
} : null,
|
|
107
|
+
worktree: worktrees.find((w) => w.path === project.__path) ?? null,
|
|
108
|
+
remoteDevices: remote ? [remote] : []
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function activityLabel(activity, now) {
|
|
112
|
+
if (!activity) return null;
|
|
113
|
+
if (activity.state === "driven") {
|
|
114
|
+
const since = Date.parse(activity.driver?.since ?? "");
|
|
115
|
+
const duration = Number.isFinite(since) ? ` for ${formatLongDuration(Math.max(0, now - since))}` : "";
|
|
116
|
+
return `driven by ${activity.driver?.tool ?? "an unknown tool"}${duration}`;
|
|
117
|
+
}
|
|
118
|
+
if (activity.state === "unknown") return `activity unknown (${activity.basis.join(", ")})`;
|
|
119
|
+
if (activity.state === "active") return "active";
|
|
120
|
+
const last = Date.parse(activity.lastActivityAt ?? "");
|
|
121
|
+
return Number.isFinite(last) ? `idle ${formatLongDuration(Math.max(0, now - last))}` : "idle (no recorded activity)";
|
|
122
|
+
}
|
|
123
|
+
function remoteDeviceLine(remote) {
|
|
124
|
+
const claim = remote.state === "claimed" ? "" : ` (${remote.state})`;
|
|
125
|
+
const watch = remote.webPreviewUrl ? ` -- watch: ${remote.webPreviewUrl}` : "";
|
|
126
|
+
return `remote ${remote.platform ?? "?"}: EAS session ${remote.sessionId} billable${claim}${watch}`;
|
|
127
|
+
}
|
|
128
|
+
function capacity(states, totalMemoryMb) {
|
|
129
|
+
const committedMb = states.reduce((n, s) => n + s.memoryMb, 0);
|
|
130
|
+
return {
|
|
131
|
+
liveCount: states.filter((s) => s.live).length,
|
|
132
|
+
committedMb,
|
|
133
|
+
totalMemoryMb,
|
|
134
|
+
overCapacity: Boolean(totalMemoryMb && committedMb > totalMemoryMb * .6)
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function parseDfFree(output) {
|
|
138
|
+
const lines = String(output || "").trim().split("\n");
|
|
139
|
+
if (lines.length < 2) return null;
|
|
140
|
+
const lastLine = lines[lines.length - 1];
|
|
141
|
+
if (lastLine === void 0) return null;
|
|
142
|
+
const m = /\s(\d+)\s+(\d+)\s+(\d+)\s+(\d+)%/.exec(lastLine);
|
|
143
|
+
if (!m) return null;
|
|
144
|
+
const totalKb = Number(m[1]);
|
|
145
|
+
const availableKb = Number(m[3]);
|
|
146
|
+
if (!Number.isFinite(totalKb) || !Number.isFinite(availableKb) || totalKb <= 0) return null;
|
|
147
|
+
return {
|
|
148
|
+
availableMb: Math.round(availableKb / 1024),
|
|
149
|
+
totalMb: Math.round(totalKb / 1024)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function diskIsTight(disk) {
|
|
153
|
+
return Boolean(disk && disk.availableMb < 25600);
|
|
154
|
+
}
|
|
155
|
+
function formatSpace(mb) {
|
|
156
|
+
if (!Number.isFinite(mb)) return "?";
|
|
157
|
+
if (mb >= 1048576) return `${(mb / 1048576).toFixed(1)} TB`;
|
|
158
|
+
if (mb >= 1024) return `${Math.round(mb / 1024)} GB`;
|
|
159
|
+
return `${Math.round(mb)} MB`;
|
|
160
|
+
}
|
|
161
|
+
function diskLine(volumes) {
|
|
162
|
+
const usable = (volumes || []).filter((v) => Boolean(v && v.disk));
|
|
163
|
+
if (usable.length === 0) return null;
|
|
164
|
+
if (usable.length === 1) {
|
|
165
|
+
const first = usable[0];
|
|
166
|
+
if (!first) return null;
|
|
167
|
+
const { disk } = first;
|
|
168
|
+
return `${formatSpace(disk.availableMb)} free of ${formatSpace(disk.totalMb)} on disk.`;
|
|
169
|
+
}
|
|
170
|
+
return `${usable.map((v) => `${formatSpace(v.disk.availableMb)} free on ${v.volume}`).join(", ")}.`;
|
|
171
|
+
}
|
|
172
|
+
function tightVolumes(volumes) {
|
|
173
|
+
return (volumes || []).filter((v) => v && diskIsTight(v.disk));
|
|
174
|
+
}
|
|
175
|
+
function unprovisionedWorktrees(worktrees, projectPaths) {
|
|
176
|
+
return worktrees.filter((w) => {
|
|
177
|
+
const inside = w.path.endsWith(sep) ? w.path : w.path + sep;
|
|
178
|
+
return !projectPaths.some((p) => p === w.path || p.startsWith(inside));
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function deviceLeaseStates(entries, { root, now }) {
|
|
182
|
+
return entries.map((entry) => {
|
|
183
|
+
const lease = entry.lease;
|
|
184
|
+
return {
|
|
185
|
+
path: entry.path,
|
|
186
|
+
platform: entry.platform,
|
|
187
|
+
...lease?.slot ? { slot: lease.slot } : {},
|
|
188
|
+
id: entry.id,
|
|
189
|
+
deviceName: lease?.deviceName ?? null,
|
|
190
|
+
holder: lease?.holder ?? null,
|
|
191
|
+
grantedAt: lease?.grantedAt ?? null,
|
|
192
|
+
expiresAt: lease?.expiresAt ?? null,
|
|
193
|
+
mine: Boolean(lease && root && lease.holder === root),
|
|
194
|
+
expired: Boolean(lease && Date.parse(lease.expiresAt) <= now),
|
|
195
|
+
parsed: Boolean(lease)
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function deviceLeaseLines(states, now) {
|
|
200
|
+
if (states.length === 0) return [];
|
|
201
|
+
const lines = [`Device leases (${states.length}):`];
|
|
202
|
+
for (const state of states) {
|
|
203
|
+
const device = `${state.platform}${state.slot ? ` [${state.slot}]` : ""} ${state.id ?? state.path}${state.deviceName ? ` (${state.deviceName})` : ""}`;
|
|
204
|
+
if (!state.parsed || state.expiresAt === null) {
|
|
205
|
+
lines.push(` ${device} -- unreadable lease file, so nothing may take the device: ${state.path}`);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const when = clockTime(state.expiresAt);
|
|
209
|
+
const remaining = Date.parse(state.expiresAt) - now;
|
|
210
|
+
const expiry = state.expired ? `expired at ${when}` : `until ${when} (${formatElapsed(remaining)} left)`;
|
|
211
|
+
lines.push(` ${device} -- ${state.holder} ${expiry}${state.mine ? " [this workspace]" : ""}`);
|
|
212
|
+
}
|
|
213
|
+
return lines;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
export { diskLine as a, parseDfFree as c, remoteDeviceState as d, tightVolumes as f, deviceLeaseStates as i, poolLine as l, capacity as n, environmentState as o, unprovisionedWorktrees as p, deviceLeaseLines as r, formatSpace as s, activityLabel as t, remoteDeviceLine as u };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import {
|
|
3
|
-
import { accessSync, constants, mkdirSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
2
|
+
import { accessSync, constants, realpathSync, statSync } from "node:fs";
|
|
4
3
|
import { delimiter, join, resolve } from "node:path";
|
|
5
4
|
//#region src/diagnostics/stim-installations.ts
|
|
6
5
|
const VERSION_OUTPUT_LIMIT = 4096;
|
|
@@ -150,122 +149,4 @@ async function inspectStimVersions(runningVersion, { pathValue = process.env.PAT
|
|
|
150
149
|
return analyzeStimVersions(runningVersion, canonicalPath(runningPath), installations);
|
|
151
150
|
}
|
|
152
151
|
//#endregion
|
|
153
|
-
|
|
154
|
-
const DAY_MS = 864e5;
|
|
155
|
-
const DOCTOR_STALE_MS = 7 * DAY_MS;
|
|
156
|
-
const UPDATE_CHECK_INTERVAL_MS = DAY_MS;
|
|
157
|
-
const UPDATE_CHECK_TIMEOUT_MS = 2e3;
|
|
158
|
-
const LATEST_URL = "https://registry.npmjs.org/stim/latest";
|
|
159
|
-
const PLATFORMS = ["ios", "android"];
|
|
160
|
-
function recordDoctorRun(projectRoot, platform, version, now = /* @__PURE__ */ new Date()) {
|
|
161
|
-
const run = {
|
|
162
|
-
at: now.toISOString(),
|
|
163
|
-
version
|
|
164
|
-
};
|
|
165
|
-
try {
|
|
166
|
-
upsertProject(projectRoot, (existing) => {
|
|
167
|
-
const doctorRuns = { ...existing.doctorRuns };
|
|
168
|
-
for (const target of platform ? [platform] : PLATFORMS) doctorRuns[target] = run;
|
|
169
|
-
return { doctorRuns };
|
|
170
|
-
});
|
|
171
|
-
} catch {}
|
|
172
|
-
}
|
|
173
|
-
function doctorDueReason(record, running, now) {
|
|
174
|
-
const at = record ? Date.parse(record.at) : NaN;
|
|
175
|
-
if (!record || Number.isNaN(at)) return "never run";
|
|
176
|
-
if (record.version !== running) return `last run with stim ${record.version}`;
|
|
177
|
-
const age = now.getTime() - at;
|
|
178
|
-
if (age > DOCTOR_STALE_MS) return `last run ${Math.floor(age / DAY_MS)} days ago`;
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
function updateCacheFile() {
|
|
182
|
-
return join(getConfigDir(), "update-check.json");
|
|
183
|
-
}
|
|
184
|
-
function readUpdateCache() {
|
|
185
|
-
try {
|
|
186
|
-
const parsed = JSON.parse(readFileSync(updateCacheFile(), "utf-8"));
|
|
187
|
-
if (typeof parsed?.checkedAt !== "string") return null;
|
|
188
|
-
return {
|
|
189
|
-
checkedAt: parsed.checkedAt,
|
|
190
|
-
latest: typeof parsed.latest === "string" ? parsed.latest : null
|
|
191
|
-
};
|
|
192
|
-
} catch {
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
function writeUpdateCache(cache) {
|
|
197
|
-
const target = updateCacheFile();
|
|
198
|
-
const tmp = `${target}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
199
|
-
try {
|
|
200
|
-
mkdirSync(getConfigDir(), { recursive: true });
|
|
201
|
-
writeFileSync(tmp, `${JSON.stringify(cache)}\n`);
|
|
202
|
-
renameSync(tmp, target);
|
|
203
|
-
} catch {
|
|
204
|
-
try {
|
|
205
|
-
unlinkSync(tmp);
|
|
206
|
-
} catch {}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
async function fetchLatest(fetchImpl) {
|
|
210
|
-
const res = await fetchImpl(LATEST_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) });
|
|
211
|
-
if (!res.ok) return null;
|
|
212
|
-
const body = await res.json();
|
|
213
|
-
return typeof body.version === "string" ? body.version : null;
|
|
214
|
-
}
|
|
215
|
-
async function checkForUpdate(running, { now = /* @__PURE__ */ new Date(), fetch: fetchImpl = fetch } = {}) {
|
|
216
|
-
if (process.env.STIM_NO_UPDATE_CHECK) return null;
|
|
217
|
-
const cached = readUpdateCache();
|
|
218
|
-
const checkedAt = cached ? Date.parse(cached.checkedAt) : NaN;
|
|
219
|
-
let latest = cached?.latest ?? null;
|
|
220
|
-
if (Number.isNaN(checkedAt) || now.getTime() - checkedAt > UPDATE_CHECK_INTERVAL_MS) {
|
|
221
|
-
try {
|
|
222
|
-
latest = await fetchLatest(fetchImpl);
|
|
223
|
-
} catch {
|
|
224
|
-
latest = null;
|
|
225
|
-
}
|
|
226
|
-
writeUpdateCache({
|
|
227
|
-
checkedAt: now.toISOString(),
|
|
228
|
-
latest
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
if (!latest) return null;
|
|
232
|
-
const comparison = compareStimVersions(latest, running);
|
|
233
|
-
return comparison !== null && comparison > 0 ? latest : null;
|
|
234
|
-
}
|
|
235
|
-
function renderGuideStatus({ running, doctor, latest }) {
|
|
236
|
-
const lines = [];
|
|
237
|
-
if (doctor.length) {
|
|
238
|
-
const named = doctor.map((due) => `${due.platform} (${due.reason})`).join(" and ");
|
|
239
|
-
const command = doctor.length === 1 ? `stim doctor --platform ${doctor[0]?.platform}` : "stim doctor";
|
|
240
|
-
lines.push(` Doctor is due for ${named}.`, ` Run before native work: ${command}`);
|
|
241
|
-
}
|
|
242
|
-
if (latest) lines.push(` stim ${latest} is available (running ${running}): npm install -g stim@latest`);
|
|
243
|
-
if (!lines.length) return null;
|
|
244
|
-
return ["STATUS", ...lines].join("\n");
|
|
245
|
-
}
|
|
246
|
-
async function guideStatus({ projectRoot, running, now = /* @__PURE__ */ new Date(), fetch: fetchImpl = fetch }) {
|
|
247
|
-
const doctor = [];
|
|
248
|
-
if (projectRoot) {
|
|
249
|
-
let runs = null;
|
|
250
|
-
try {
|
|
251
|
-
runs = getProject(projectRoot)?.doctorRuns ?? {};
|
|
252
|
-
} catch {}
|
|
253
|
-
if (runs) for (const platform of PLATFORMS) {
|
|
254
|
-
const reason = doctorDueReason(runs[platform], running, now);
|
|
255
|
-
if (reason) doctor.push({
|
|
256
|
-
platform,
|
|
257
|
-
reason
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return renderGuideStatus({
|
|
262
|
-
running,
|
|
263
|
-
doctor,
|
|
264
|
-
latest: await checkForUpdate(running, {
|
|
265
|
-
now,
|
|
266
|
-
fetch: fetchImpl
|
|
267
|
-
})
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
//#endregion
|
|
271
|
-
export { inspectStimVersions as i, recordDoctorRun as n, compareStimVersions as r, guideStatus as t };
|
|
152
|
+
export { inspectStimVersions as n, compareStimVersions as t };
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { B as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as clearRemoteSession, i as clearManagedMetroTunnel, l as readRemoteSession, o as clearWorkspaceSupervisor, s as readMetroTunnel } from "./state-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { i as endRecordedSession } from "./device-remote-ByN8P6CB.mjs";
|
|
12
|
-
import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-wolE-0Do.mjs";
|
|
1
|
+
import { B as parseDeviceSlotKey, D as process_identity_exports, H as projectDeviceSlots, T as withConfigLock, V as parseDeviceSlotOption, W as validateDeviceSlot, a as clearSupervisor, f as getProject, w as upsertProject, z as deviceSlotPlatforms } from "./config-BEq0Qw_a.mjs";
|
|
2
|
+
import { O as workspaceDir, _ as withWorkspaceStateLock, c as signalProcessTree, i as pidExists, m as readWorkspaceState, p as clearWorkspaceStateKeys, s as resolveProjectMetro, t as killMetroTree, y as writeWorkspaceState } from "./metro-BWLOJ_Wr.mjs";
|
|
3
|
+
import { o as findProjectRoot } from "./project-BXZzOABt.mjs";
|
|
4
|
+
import { a as clearRemoteSession, i as clearManagedMetroTunnel, l as readRemoteSession, o as clearWorkspaceSupervisor, s as readMetroTunnel } from "./state-WGdIbi_d.mjs";
|
|
5
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BXA96myD.mjs";
|
|
6
|
+
import { f as refuseNoProject, l as phaseLine, p as releasedLeaseFact, u as plural } from "./command-output-D5z2_bcF.mjs";
|
|
7
|
+
import { u as releaseWorkspaceLeases } from "./device-lease-CbEaIk7b.mjs";
|
|
8
|
+
import { d as teardownOwnedAvd, f as teardownOwnedIosSim, i as stopTunnel, t as resolveSupervisorTarget } from "./ownership-DZjdx8Gq.mjs";
|
|
9
|
+
import { n as verifyCollectorOwnership } from "./ownership-D2xbLVoz.mjs";
|
|
10
|
+
import { i as endRecordedSession, z as resolveEasCliBin } from "./device-remote-Dy1jGj3U.mjs";
|
|
13
11
|
import chalk from "chalk";
|
|
14
12
|
//#region src/commands/stop.ts
|
|
15
13
|
const DEFAULT_WAIT_MS = 1e4;
|
|
@@ -143,7 +141,7 @@ async function runStop(options) {
|
|
|
143
141
|
result.summary = summarize(root, result.outcomes, result.ok);
|
|
144
142
|
return result;
|
|
145
143
|
}
|
|
146
|
-
async function stopWorkspace({ root, project = void 0, state = void 0, collectors = void 0, signalCollector = (pid) => signalProcessTree(pid), verifyCollector = verifyCollectorOwnership, clearCollectors = clearCollectorState, isAlive = pidExists, killGroup = killMetroTree, inspectIdentity = process_identity_exports.inspectProcessIdentity, waitForDeath = void 0, waitMs = DEFAULT_WAIT_MS, resolveMetro = resolveProjectMetro, teardownIos = teardownOwnedIosSim, teardownAvd = teardownOwnedAvd, remoteDevice = void 0, teardownRemoteSession = defaultTeardownRemoteSession, metroTunnel = void 0, stopMetroTunnel = stopTunnel, releaseLeases = releaseWorkspaceLeases, freePort = defaultFreePort, clearRegistration = defaultClearRegistration, clearState = clearSupervisorState, report = (line) => console.error(line) }) {
|
|
144
|
+
async function stopWorkspace({ root, project = void 0, state = void 0, collectors = void 0, signalCollector = (pid) => signalProcessTree(pid), verifyCollector = verifyCollectorOwnership, clearCollectors = clearCollectorState, isAlive = pidExists, killGroup = killMetroTree, signalServer = (pid) => signalProcessTree(pid), inspectIdentity = process_identity_exports.inspectProcessIdentity, waitForDeath = void 0, waitMs = DEFAULT_WAIT_MS, resolveMetro = resolveProjectMetro, teardownIos = teardownOwnedIosSim, teardownAvd = teardownOwnedAvd, remoteDevice = void 0, teardownRemoteSession = defaultTeardownRemoteSession, metroTunnel = void 0, stopMetroTunnel = stopTunnel, releaseLeases = releaseWorkspaceLeases, freePort = defaultFreePort, clearRegistration = defaultClearRegistration, clearState = clearSupervisorState, report = (line) => console.error(line) }) {
|
|
147
145
|
const proj = project === void 0 ? getProject(root) : project;
|
|
148
146
|
const sup = state === void 0 ? readSupervisorState(root) : state;
|
|
149
147
|
const collectorRecords = collectors === void 0 ? readCollectorState(root) : collectors;
|
|
@@ -172,6 +170,7 @@ async function stopWorkspace({ root, project = void 0, state = void 0, collector
|
|
|
172
170
|
};
|
|
173
171
|
let ok = true;
|
|
174
172
|
let stillHolding = null;
|
|
173
|
+
let keepPort = null;
|
|
175
174
|
const target = resolveSupervisorTarget({
|
|
176
175
|
state: sup,
|
|
177
176
|
record: proj?.supervisor ?? null,
|
|
@@ -232,10 +231,17 @@ async function stopWorkspace({ root, project = void 0, state = void 0, collector
|
|
|
232
231
|
};
|
|
233
232
|
else if (reservedPort === null) report(chalk.dim(phaseLine("metro", "no port reserved")));
|
|
234
233
|
else {
|
|
235
|
-
|
|
234
|
+
const metro = await stopMetro(reservedPort, root, {
|
|
235
|
+
server: sup,
|
|
236
|
+
supervisorGone: target.status === "stale",
|
|
237
|
+
signalServer,
|
|
238
|
+
inspectIdentity,
|
|
239
|
+
waiter,
|
|
236
240
|
resolveMetro,
|
|
237
241
|
report
|
|
238
242
|
});
|
|
243
|
+
outcomes.metro = metro.outcome;
|
|
244
|
+
keepPort = metro.keepPort;
|
|
239
245
|
if (outcomes.metro.status === "refused" || outcomes.metro.status === "failed") {
|
|
240
246
|
ok = false;
|
|
241
247
|
stillHolding = outcomes.metro.reason;
|
|
@@ -254,6 +260,15 @@ async function stopWorkspace({ root, project = void 0, state = void 0, collector
|
|
|
254
260
|
return;
|
|
255
261
|
}
|
|
256
262
|
if (reservedPort !== null) {
|
|
263
|
+
if (keepPort) {
|
|
264
|
+
outcomes.port = {
|
|
265
|
+
status: "kept",
|
|
266
|
+
port: reservedPort,
|
|
267
|
+
reason: keepPort
|
|
268
|
+
};
|
|
269
|
+
report(chalk.dim(phaseLine("port", `keeping reservation ${reservedPort} -- ${keepPort}`)));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
257
272
|
if (freePort(root, reservedPort) === false) {
|
|
258
273
|
ok = false;
|
|
259
274
|
outcomes.port = {
|
|
@@ -334,8 +349,12 @@ async function stopWorkspace({ root, project = void 0, state = void 0, collector
|
|
|
334
349
|
reason: stillHolding
|
|
335
350
|
};
|
|
336
351
|
report(chalk.yellow(phaseLine("port", `keeping reservation ${reservedPort ?? "(none)"} -- ${stillHolding}`)));
|
|
337
|
-
const
|
|
338
|
-
|
|
352
|
+
const serverIsDown = [
|
|
353
|
+
"none",
|
|
354
|
+
"already-stopped",
|
|
355
|
+
"stopped"
|
|
356
|
+
].includes(outcomes.supervisor.status) && !["refused", "failed"].includes(outcomes.metro.status);
|
|
357
|
+
if (tunnelHolding && serverIsDown) {
|
|
339
358
|
clearState(root, sup);
|
|
340
359
|
await clearRegistration(root, proj?.supervisor ?? null);
|
|
341
360
|
}
|
|
@@ -476,21 +495,76 @@ async function stopSupervisor(target, { killGroup, waiter, report }) {
|
|
|
476
495
|
reason
|
|
477
496
|
};
|
|
478
497
|
}
|
|
479
|
-
async function stopMetro(port, root, { resolveMetro, report }) {
|
|
498
|
+
async function stopMetro(port, root, { server, supervisorGone, signalServer, inspectIdentity, waiter, resolveMetro, report }) {
|
|
499
|
+
const serverPid = numberOrNull(server?.serverPid);
|
|
500
|
+
const serverProcessToken = server?.serverProcessToken;
|
|
501
|
+
const serverRecord = {
|
|
502
|
+
pid: serverPid,
|
|
503
|
+
processToken: serverProcessToken
|
|
504
|
+
};
|
|
505
|
+
const identity = supervisorGone && serverPid && typeof serverProcessToken === "string" ? inspectIdentity(serverRecord) : null;
|
|
506
|
+
if (identity === "unknown") {
|
|
507
|
+
const reason = `the identity of dev server pid ${serverPid} left by the supervisor could not be verified`;
|
|
508
|
+
report(chalk.yellow(phaseLine("metro", `refusing to signal it: ${reason}`)));
|
|
509
|
+
return {
|
|
510
|
+
outcome: {
|
|
511
|
+
status: "refused",
|
|
512
|
+
port,
|
|
513
|
+
pid: serverPid,
|
|
514
|
+
reason
|
|
515
|
+
},
|
|
516
|
+
keepPort: null
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
if (identity === "same") {
|
|
520
|
+
report(chalk.dim(phaseLine("metro", `sending SIGTERM to dev server pid ${serverPid} left by the supervisor`)));
|
|
521
|
+
let signalled = false;
|
|
522
|
+
try {
|
|
523
|
+
signalled = signalServer(serverPid);
|
|
524
|
+
} catch {}
|
|
525
|
+
if (signalled ? await waiter(serverPid, serverProcessToken) : ["gone", "different"].includes(inspectIdentity(serverRecord))) {
|
|
526
|
+
report(chalk.green(phaseLine("metro", `dev server pid ${serverPid}`)));
|
|
527
|
+
return {
|
|
528
|
+
outcome: {
|
|
529
|
+
status: "stopped",
|
|
530
|
+
port,
|
|
531
|
+
pid: serverPid
|
|
532
|
+
},
|
|
533
|
+
keepPort: null
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
const reason = `dev server pid ${serverPid} left by the supervisor did not exit`;
|
|
537
|
+
report(chalk.red(phaseLine("metro", reason)));
|
|
538
|
+
return {
|
|
539
|
+
outcome: {
|
|
540
|
+
status: "failed",
|
|
541
|
+
port,
|
|
542
|
+
pid: serverPid,
|
|
543
|
+
reason
|
|
544
|
+
},
|
|
545
|
+
keepPort: null
|
|
546
|
+
};
|
|
547
|
+
}
|
|
480
548
|
const resolution = await resolveMetro(port, root);
|
|
481
549
|
if (resolution.missing) {
|
|
482
550
|
report(chalk.dim(phaseLine("metro", `nothing listening on port ${port}`)));
|
|
483
551
|
return {
|
|
484
|
-
|
|
485
|
-
|
|
552
|
+
outcome: {
|
|
553
|
+
status: "missing",
|
|
554
|
+
port
|
|
555
|
+
},
|
|
556
|
+
keepPort: null
|
|
486
557
|
};
|
|
487
558
|
}
|
|
488
559
|
const reason = resolution.notOurs || "no recorded Stim supervisor owns this server; stop it with the tool that started it";
|
|
489
560
|
report(chalk.yellow(phaseLine("metro", `leaving port ${port} alone: ${reason}`)));
|
|
490
561
|
return {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
562
|
+
outcome: {
|
|
563
|
+
status: "not-managed",
|
|
564
|
+
port,
|
|
565
|
+
reason
|
|
566
|
+
},
|
|
567
|
+
keepPort: resolution.metro ? `a dev server from this project still answers on port ${port}` : null
|
|
494
568
|
};
|
|
495
569
|
}
|
|
496
570
|
const OCCUPANCY_HINT = "often a UI-test runner or device tool still attached";
|
|
@@ -521,7 +595,7 @@ function shutDownDevices(project, { teardownIos, teardownAvd, report }) {
|
|
|
521
595
|
} else device[iosKey] = reportDevice(iosUdid, teardownIos(iosUdid, {
|
|
522
596
|
del: false,
|
|
523
597
|
label: iosName
|
|
524
|
-
}), report);
|
|
598
|
+
}), report, "ios");
|
|
525
599
|
}
|
|
526
600
|
const android = platforms.android;
|
|
527
601
|
if (android?.avdName) {
|
|
@@ -533,12 +607,15 @@ function shutDownDevices(project, { teardownIos, teardownAvd, report }) {
|
|
|
533
607
|
reason: "Stim does not own this device"
|
|
534
608
|
};
|
|
535
609
|
report(chalk.dim(phaseLine("device", `${android.avdName} is not Stim-owned, leaving it running`)));
|
|
536
|
-
} else device[androidKey] = reportDevice(android.avdName, teardownAvd(android.avdName, { del: false }), report);
|
|
610
|
+
} else device[androidKey] = reportDevice(android.avdName, teardownAvd(android.avdName, { del: false }), report, "android");
|
|
537
611
|
}
|
|
538
612
|
}
|
|
539
613
|
return device;
|
|
540
614
|
}
|
|
541
|
-
function
|
|
615
|
+
function deviceShutdownRemedy(kind, label) {
|
|
616
|
+
return kind === "ios" ? `check it with \`xcrun simctl list devices\`, then \`xcrun simctl shutdown ${label}\` yourself -- if it will not respond, \`stim gc --delete\` reclaims it` : `check it with \`adb devices\`, then \`adb -s <serial> emu kill\` yourself -- if it will not respond, \`stim gc --delete\` reclaims it`;
|
|
617
|
+
}
|
|
618
|
+
function reportDevice(label, r, report, kind) {
|
|
542
619
|
if (r.status === "torn-down") {
|
|
543
620
|
report(chalk.green(phaseLine("device", `shut down ${r.label ?? label}`)));
|
|
544
621
|
return {
|
|
@@ -563,11 +640,14 @@ function reportDevice(label, r, report) {
|
|
|
563
640
|
reason
|
|
564
641
|
};
|
|
565
642
|
}
|
|
566
|
-
|
|
643
|
+
const remedy = deviceShutdownRemedy(kind, r.label ?? label);
|
|
644
|
+
report(chalk.red(phaseLine("device", `failed to shut down ${r.label ?? label}: ${r.reason}`)));
|
|
645
|
+
report(chalk.dim(phaseLine("", remedy)));
|
|
567
646
|
return {
|
|
568
647
|
status: "failed",
|
|
569
|
-
label,
|
|
570
|
-
reason: r.reason
|
|
648
|
+
label: r.label ?? label,
|
|
649
|
+
reason: r.reason,
|
|
650
|
+
remedy
|
|
571
651
|
};
|
|
572
652
|
}
|
|
573
653
|
function summarize(root, outcomes, ok) {
|
|
@@ -617,11 +697,11 @@ async function defaultClearRegistration(root, expected) {
|
|
|
617
697
|
}
|
|
618
698
|
}
|
|
619
699
|
function stopCommand(program) {
|
|
620
|
-
program.command("stop").description("The inverse of `start`: halt this workspace's supervisor, shut the owned device down (never deleted), and free the reserved port. Non-destructive -- the device stays assigned, so coming back costs a boot. Acts on the current workspace.").option("--slot <name>", "Stop only this device slot, keeping the shared server running",
|
|
700
|
+
program.command("stop").description("The inverse of `start`: halt this workspace's supervisor, shut the owned device down (never deleted), and free the reserved port. Non-destructive -- the device stays assigned, so coming back costs a boot. Acts on the current workspace.").option("--slot <name>", "Stop only this device slot, keeping the shared server running", parseDeviceSlotOption).option("--json", "print the per-step outcomes as JSON").action(async (opts) => {
|
|
621
701
|
const root = findProjectRoot(process.cwd());
|
|
622
702
|
if (!root) {
|
|
623
|
-
|
|
624
|
-
|
|
703
|
+
refuseNoProject({ json: Boolean(opts.json) });
|
|
704
|
+
return;
|
|
625
705
|
}
|
|
626
706
|
const { ok, outcomes, summary } = await withWorkspaceProcessLock(workspaceDir(root), "native-run", () => runStop({
|
|
627
707
|
root,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as resolveSupervisorTarget } from "./ownership-
|
|
2
|
-
import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-
|
|
1
|
+
import { t as resolveSupervisorTarget } from "./ownership-DZjdx8Gq.mjs";
|
|
2
|
+
import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-Dj4pfmyv.mjs";
|
|
3
3
|
export { clearCollectorState, clearSupervisorState, stopCommand as default, readCollectorState, readSupervisorState, resolveCollectorTargets, resolveSupervisorTarget, runStop };
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { t as NdjsonWriter } from "./ndjson-
|
|
1
|
+
import { t as NdjsonWriter } from "./ndjson-Du3j0AQ9.mjs";
|
|
2
|
+
import "@stim-cli/core/state";
|
|
3
|
+
//#region src/supervisor/idle-stop.d.ts
|
|
4
|
+
interface IdleProbe {
|
|
5
|
+
lastActivityAt(): number;
|
|
6
|
+
blocker(): string | null;
|
|
7
|
+
}
|
|
2
8
|
import * as import__stim_cli_core_process_identity from "@stim-cli/core/process-identity";
|
|
3
9
|
//#endregion
|
|
4
10
|
//#region src/supervisor/state.d.ts
|
|
@@ -15,6 +21,7 @@ interface ParsedSupervisorArgs {
|
|
|
15
21
|
port?: number;
|
|
16
22
|
tunnel?: boolean;
|
|
17
23
|
resetCache?: boolean;
|
|
24
|
+
idleStopMinutes?: number;
|
|
18
25
|
error?: string;
|
|
19
26
|
}
|
|
20
27
|
declare function parseArgs(argv: string[]): ParsedSupervisorArgs;
|
|
@@ -43,6 +50,8 @@ interface RunSupervisorOptions {
|
|
|
43
50
|
port: number;
|
|
44
51
|
tunnel?: boolean;
|
|
45
52
|
resetCache?: boolean;
|
|
53
|
+
idleStopMinutes?: number;
|
|
54
|
+
idleProbe?: IdleProbe;
|
|
46
55
|
isExpo?: (projectRoot: string) => boolean;
|
|
47
56
|
startBare?: ServerStarter | null;
|
|
48
57
|
startExpo?: ServerStarter | null;
|
|
@@ -51,7 +60,7 @@ interface RunSupervisorOptions {
|
|
|
51
60
|
attachSignals?: boolean;
|
|
52
61
|
stderr?: (line: string) => void;
|
|
53
62
|
}
|
|
54
|
-
declare function runSupervisor({ root, port, tunnel, resetCache, isExpo, startBare, startExpo, now, onExit, attachSignals, stderr }: RunSupervisorOptions): Promise<{
|
|
63
|
+
declare function runSupervisor({ root, port, tunnel, resetCache, idleStopMinutes, idleProbe, isExpo, startBare, startExpo, now, onExit, attachSignals, stderr }: RunSupervisorOptions): Promise<{
|
|
55
64
|
mode: string;
|
|
56
65
|
server: ServerHandle | undefined;
|
|
57
66
|
shutdown: (code: number, event: string, msg: string) => Promise<void>;
|