stim 1.1.0 → 1.3.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 +37 -0
- package/dist/{android-CC5bUer7.mjs → android-BW8i_YxU.mjs} +1 -1
- package/dist/android-BqVIJoG7.mjs +1368 -0
- package/dist/{android-DnZlT3aU.mjs → android-CqcW1hrP.mjs} +205 -58
- package/dist/{android-cas-DGlTStWu.mjs → android-cas-BR5YJBYv.mjs} +6 -6
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{app-install-oZIQRbdD.mjs → app-install-DIp9riNx.mjs} +29 -21
- package/dist/{build-slots-CgacA9zQ.mjs → build-slots-C3-R4XQr.mjs} +3 -3
- package/dist/{cache-manifest-oeH18ERr.mjs → cache-manifest-CXR-Y8pH.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +13 -13
- package/dist/collector-run.d.mts +4 -1
- package/dist/collector-run.mjs +36 -11
- package/dist/{config-D7uu8Gbq.mjs → config-CcefMY2Q.mjs} +94 -13
- package/dist/{deps-64wVnpZc.mjs → deps-Spz8ozgo.mjs} +2 -2
- package/dist/{dev-client-Bvky1hya.mjs → dev-client-BjisHDB5.mjs} +250 -10
- package/dist/{device-DJKv5Qej.mjs → device-BkiW-gkk.mjs} +19 -11
- package/dist/{device-lease-D-G3SgVe.mjs → device-lease-BJYybF-2.mjs} +107 -83
- package/dist/{device-pool-BlHXnYYs.mjs → device-pool-CPbLGfrB.mjs} +19 -13
- package/dist/{device-remote-CCgkG82J.mjs → device-remote-AkYCKS8U.mjs} +8 -8
- package/dist/{doctor-DlVxTtMq.mjs → doctor-Bmv86UUW.mjs} +18 -26
- package/dist/{doctor-BRF9aAJ3.mjs → doctor-fAMXC4vl.mjs} +10 -10
- package/dist/{error-diagnostics-B5IJwv3-.mjs → error-diagnostics-DHC31rXA.mjs} +65 -55
- package/dist/{exec-bsN9MJXb.mjs → exec-CyylIdq9.mjs} +4 -2
- package/dist/{gc-DhXdgSdt.mjs → gc-GGu-8ULN.mjs} +90 -67
- package/dist/{guide-DrhrDBo5.mjs → guide-92CPA21s.mjs} +414 -47
- package/dist/{ios-CK1Vrk6Q.mjs → ios-BSXFeO5H.mjs} +200 -59
- package/dist/{ios-BZxKPuqP.mjs → ios-Deh5js5V.mjs} +147 -40
- package/dist/{ios-device-CdSm0GDw.mjs → ios-device-CWOM_S44.mjs} +2 -2
- package/dist/{ios-device-CYbuRNXR.mjs → ios-device-D3pzTKQE.mjs} +1 -1
- package/dist/{logs-Dxoy16Qv.mjs → logs-DPNF4C9s.mjs} +9 -6
- package/dist/{logs-query-oqn47Ffx.mjs → logs-query-R-Cqc6Qv.mjs} +22 -5
- package/dist/{metro-B01H3EuD.mjs → metro-CORqXyTL.mjs} +3 -3
- package/dist/{ndjson-DcAtEx_K.mjs → ndjson-BZwI1NBv.mjs} +5 -2
- package/dist/{ownership-D8HmSv2E.mjs → ownership-8O073GIC.mjs} +3 -3
- package/dist/{ownership-B9QIdQOw.mjs → ownership-BpCKiRlQ.mjs} +4 -4
- package/dist/{ownership-claim-CeJLEpjD.mjs → ownership-claim-Bf2CAfw3.mjs} +4 -3
- package/dist/{project-COj6nzzh.mjs → project-fKmuIaMI.mjs} +2 -2
- package/dist/{reclaim-BPvN2HlP.mjs → reclaim-iW9Cad7k.mjs} +80 -73
- package/dist/{reload-DYZEBbZy.mjs → reload-DazHDSFA.mjs} +32 -24
- package/dist/{server-bare-BYHqEeyw.mjs → server-bare-DEzPZLvf.mjs} +7 -2
- package/dist/server-expo-44em5Pmg.mjs +2 -0
- package/dist/{server-expo-BEMr_m6p.mjs → server-expo-DizT4OMk.mjs} +5 -5
- package/dist/{settings-BSwrY4FZ.mjs → settings-DEJf6_kJ.mjs} +26 -5
- package/dist/slot-launch-cci0xvmC.mjs +19 -0
- package/dist/{start-ByCylYtB.mjs → start-mObjQH2W.mjs} +12 -12
- package/dist/{state-IYEY-zi8.mjs → state-B3XA2wp2.mjs} +9 -9
- package/dist/{stats-wqxPm7Tv.mjs → stats-BR-kwj0B.mjs} +1 -1
- package/dist/{stats-DZ4Q5J-7.mjs → stats-CaaQr4yN.mjs} +3 -3
- package/dist/{status-Dia0XTqG.mjs → status-BxQNqu9t.mjs} +86 -25
- package/dist/{stop-D6o5zAdm.mjs → stop-CrHGcjrV.mjs} +2 -2
- package/dist/{stop-BApyaF21.mjs → stop-DimGXEKY.mjs} +93 -42
- package/dist/supervisor-run.d.mts +1 -2
- package/dist/supervisor-run.mjs +5 -5
- package/dist/{remote-cache-DOi5-zLj.mjs → teardown-ClFp1Aax.mjs} +889 -830
- package/dist/{workspace-process-lock-CxOO9-pf.mjs → workspace-process-lock-3NcQnZ0X.mjs} +1 -1
- package/dist/{worktree-DxEmUI_n.mjs → worktree-DxTgN1CJ.mjs} +16 -16
- package/dist/{worktree-Dx3ZC5lS.mjs → worktree-Eq6TLH8N.mjs} +7 -3
- package/dist/{xcode-CDB6fytw.mjs → xcode-D7sAp-Zy.mjs} +256 -103
- package/package.json +5 -5
- package/shim/bundle-response.cjs +5 -0
- package/dist/android-xmyGBNy5.mjs +0 -665
- package/dist/build-lock-vE45ZzJZ.mjs +0 -645
- package/dist/server-expo-rb0k-0w7.mjs +0 -2
|
@@ -1,8 +1,27 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
2
|
import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-C7IlIzd7.mjs";
|
|
3
3
|
import { mkdtempSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
|
+
//#region src/host-memory.ts
|
|
7
|
+
function readHostMemoryPressure(exec = getExecutor(), platform = process.platform) {
|
|
8
|
+
if (platform !== "darwin") return null;
|
|
9
|
+
try {
|
|
10
|
+
switch (exec.runFile("/usr/sbin/sysctl", ["-n", "kern.memorystatus_vm_pressure_level"], { timeoutMs: 2e3 }).trim()) {
|
|
11
|
+
case "1": return "normal";
|
|
12
|
+
case "2": return "warning";
|
|
13
|
+
case "4": return "critical";
|
|
14
|
+
default: return null;
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function hostMemoryPressureAdvice(pressure) {
|
|
21
|
+
if (pressure === null || pressure === "normal") return null;
|
|
22
|
+
return `macOS reports ${pressure} host memory pressure. Simulator processes can stall even when the device is Booted. Free memory before retrying: use \`stim stop\` only in workspaces you own, and ask before closing other apps or devices. For parallel iOS work, consider a reviewed SimSlim profile (\`stim guide lifecycle simslim\`). This observation does not establish an OOM crash.`;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
6
25
|
//#region src/sim/ios.ts
|
|
7
26
|
function parseSimctlList(jsonOutput, { includeUnavailable = false } = {}) {
|
|
8
27
|
const parsed = JSON.parse(jsonOutput);
|
|
@@ -42,8 +61,16 @@ function parseSimctlList(jsonOutput, { includeUnavailable = false } = {}) {
|
|
|
42
61
|
}
|
|
43
62
|
return sims;
|
|
44
63
|
}
|
|
45
|
-
function listAllIosSims({ timeoutMs, includeUnavailable = false } = {}) {
|
|
46
|
-
return parseSimctlList(getExecutor().
|
|
64
|
+
function listAllIosSims({ timeoutMs = 3e4, includeUnavailable = false } = {}) {
|
|
65
|
+
return parseSimctlList(getExecutor().runFile("xcrun", [
|
|
66
|
+
"simctl",
|
|
67
|
+
"list",
|
|
68
|
+
"devices",
|
|
69
|
+
"--json"
|
|
70
|
+
], {
|
|
71
|
+
timeoutMs,
|
|
72
|
+
killSignal: "SIGKILL"
|
|
73
|
+
}), { includeUnavailable });
|
|
47
74
|
}
|
|
48
75
|
function parseRuntimeVersion(runtimeId) {
|
|
49
76
|
const m = runtimeId.match(/iOS-(\d+)(?:-(\d+))?$/);
|
|
@@ -57,25 +84,25 @@ const IOS_BOOT_TIMEOUT_MS = 6e5;
|
|
|
57
84
|
const BOOTSTATUS_ATTEMPT_MS = 24e4;
|
|
58
85
|
const BOOTSTATUS_ATTEMPT_FLOOR_MS = 1e3;
|
|
59
86
|
const BOOT_STATE_LIST_TIMEOUT_MS = 3e4;
|
|
60
|
-
function
|
|
61
|
-
|
|
87
|
+
function iosSimulatorFailureAdvice(exec = getExecutor()) {
|
|
88
|
+
return hostMemoryPressureAdvice(readHostMemoryPressure(exec)) ?? "The simulator may be unresponsive. Check Activity Monitor for memory pressure and free host memory before retrying.";
|
|
89
|
+
}
|
|
90
|
+
function bootstatusTimeout(command) {
|
|
91
|
+
const e = /* @__PURE__ */ new Error(`${command} timed out`);
|
|
62
92
|
e.code = "ETIMEDOUT";
|
|
63
93
|
return e;
|
|
64
94
|
}
|
|
65
|
-
async function
|
|
95
|
+
async function awaitBootCommand(args, attemptMs, onLine) {
|
|
96
|
+
const command = `xcrun ${args.join(" ")}`;
|
|
66
97
|
const lines = [];
|
|
67
98
|
const reader = createLineReader((raw) => {
|
|
68
99
|
const line = stripAnsi(raw).trim();
|
|
69
100
|
if (!line) return;
|
|
101
|
+
onLine(line);
|
|
70
102
|
lines.push(line);
|
|
71
103
|
if (lines.length > 10) lines.shift();
|
|
72
104
|
});
|
|
73
|
-
const child = getExecutor().spawn("xcrun", [
|
|
74
|
-
"simctl",
|
|
75
|
-
"bootstatus",
|
|
76
|
-
udid,
|
|
77
|
-
"-b"
|
|
78
|
-
], { stdio: [
|
|
105
|
+
const child = getExecutor().spawn("xcrun", args, { stdio: [
|
|
79
106
|
"ignore",
|
|
80
107
|
"pipe",
|
|
81
108
|
"pipe"
|
|
@@ -86,52 +113,124 @@ async function awaitBootstatus(udid, attemptMs) {
|
|
|
86
113
|
const attempt = new Promise((resolve) => {
|
|
87
114
|
timer = setTimeout(() => resolve("timeout"), attemptMs);
|
|
88
115
|
});
|
|
116
|
+
const exited = new Promise((resolve) => child.once("exit", () => resolve()));
|
|
89
117
|
const result = await Promise.race([waitForChild(child), attempt]);
|
|
90
118
|
clearTimeout(timer);
|
|
91
119
|
reader.flush();
|
|
92
120
|
if (result === "timeout") {
|
|
93
|
-
|
|
94
|
-
|
|
121
|
+
try {
|
|
122
|
+
child.kill("SIGKILL");
|
|
123
|
+
} catch {}
|
|
124
|
+
const stopped = await Promise.race([exited.then(() => true), new Promise((resolve) => {
|
|
125
|
+
timer = setTimeout(() => resolve(false), 1e4);
|
|
126
|
+
})]);
|
|
127
|
+
clearTimeout(timer);
|
|
128
|
+
if (!stopped) {
|
|
129
|
+
child.stdout?.destroy?.();
|
|
130
|
+
child.stderr?.destroy?.();
|
|
131
|
+
child.unref();
|
|
132
|
+
throw new Error(`Timed out waiting for ${command}; its process could not be confirmed stopped. Inspect pid ${child.pid ?? "unknown"} before retrying.`);
|
|
133
|
+
}
|
|
134
|
+
throw bootstatusTimeout(command);
|
|
95
135
|
}
|
|
96
136
|
if (result.error) throw result.error;
|
|
97
137
|
if (result.code === 0) return;
|
|
98
138
|
const detail = lines.length ? `: ${lines.join(" | ")}` : "";
|
|
99
|
-
throw new Error(
|
|
139
|
+
throw new Error(`${command} failed with exit code ${result.code ?? "unknown"}${detail}`);
|
|
100
140
|
}
|
|
101
|
-
async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = BOOTSTATUS_ATTEMPT_MS } = {}) {
|
|
141
|
+
async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = BOOTSTATUS_ATTEMPT_MS, label = udid, out = () => {} } = {}) {
|
|
102
142
|
const exec = getExecutor();
|
|
143
|
+
const started = Date.now();
|
|
144
|
+
const deadline = started + timeoutMs;
|
|
145
|
+
let worst = null;
|
|
146
|
+
let unknown = 0;
|
|
147
|
+
let sampledAt = started;
|
|
148
|
+
let longestGapMs = 0;
|
|
149
|
+
let phase = "requesting boot";
|
|
150
|
+
const ranks = {
|
|
151
|
+
normal: 0,
|
|
152
|
+
warning: 1,
|
|
153
|
+
critical: 2
|
|
154
|
+
};
|
|
155
|
+
const sample = () => {
|
|
156
|
+
const now = Date.now();
|
|
157
|
+
longestGapMs = Math.max(longestGapMs, now - sampledAt);
|
|
158
|
+
sampledAt = now;
|
|
159
|
+
const pressure = readHostMemoryPressure(exec);
|
|
160
|
+
if (pressure === null) unknown++;
|
|
161
|
+
else if (worst === null || ranks[pressure] > ranks[worst]) worst = pressure;
|
|
162
|
+
return pressure;
|
|
163
|
+
};
|
|
164
|
+
const recovery = "Stop unused slots in workspaces you own with `stim stop --slot <name>`, reduce concurrent builds, and retry after pressure falls. Ask before closing other agents' devices or apps. Repeated reboots under unchanged pressure may stall again.";
|
|
165
|
+
const coverage = () => longestGapMs > 3e4 ? ` Observations were delayed: longest gap ${Math.round(longestGapMs / 1e3)}s. Pressure during gaps is unobserved; blocking CLI work can also delay progress and timeout handling.` : "";
|
|
166
|
+
const report = () => {
|
|
167
|
+
const pressure = sample();
|
|
168
|
+
out(`Simulator ${label} is still booting after ${Math.round((Date.now() - started) / 1e3)}s. Last boot output: ${phase}. Memory pressure: ${pressure ?? "unknown"}; highest observed: ${worst ?? "unknown"}. Boot deadline: ${Math.round(timeoutMs / 1e3)}s.${coverage()}${pressure === "warning" || pressure === "critical" ? ` Boot may be delayed or stalled. ${recovery}` : ""}`);
|
|
169
|
+
};
|
|
170
|
+
const onLine = (line) => {
|
|
171
|
+
phase = line.slice(0, 240);
|
|
172
|
+
};
|
|
173
|
+
sample();
|
|
174
|
+
const monitor = setInterval(report, 15e3);
|
|
175
|
+
monitor.unref();
|
|
103
176
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (remaining > 0) try {
|
|
112
|
-
await awaitBootstatus(udid, Math.min(Math.max(remaining, BOOTSTATUS_ATTEMPT_FLOOR_MS), attemptMs));
|
|
113
|
-
break;
|
|
177
|
+
try {
|
|
178
|
+
await awaitBootCommand([
|
|
179
|
+
"simctl",
|
|
180
|
+
"boot",
|
|
181
|
+
udid
|
|
182
|
+
], Math.max(1, deadline - Date.now()), onLine);
|
|
183
|
+
phase = "waiting for boot completion";
|
|
114
184
|
} catch (e) {
|
|
115
|
-
if (e?.
|
|
185
|
+
if (!String(e?.message || e).includes("Booted")) throw e;
|
|
116
186
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
187
|
+
for (;;) {
|
|
188
|
+
const remaining = deadline - Date.now();
|
|
189
|
+
if (remaining > 0) try {
|
|
190
|
+
await awaitBootCommand([
|
|
191
|
+
"simctl",
|
|
192
|
+
"bootstatus",
|
|
193
|
+
udid,
|
|
194
|
+
"-b"
|
|
195
|
+
], Math.min(Math.max(remaining, BOOTSTATUS_ATTEMPT_FLOOR_MS), attemptMs), onLine);
|
|
196
|
+
break;
|
|
197
|
+
} catch (e) {
|
|
198
|
+
if (e?.code !== "ETIMEDOUT") throw e;
|
|
199
|
+
}
|
|
200
|
+
let state;
|
|
201
|
+
try {
|
|
202
|
+
state = listAllIosSims({ timeoutMs: BOOT_STATE_LIST_TIMEOUT_MS }).find((s) => s.udid === udid)?.state ?? null;
|
|
203
|
+
} catch {
|
|
204
|
+
state = void 0;
|
|
205
|
+
}
|
|
206
|
+
const waited = Math.round((timeoutMs - Math.max(0, deadline - Date.now())) / 1e3);
|
|
207
|
+
if (state !== "Booting" && state !== "Booted" && state !== void 0) throw new Error(`Simulator ${udid} reports "${state ?? "missing"}" after ${waited}s of boot wait.`);
|
|
208
|
+
if (deadline - Date.now() <= 0) throw new Error(`Simulator ${udid} did not finish booting within ${Math.round(timeoutMs / 1e3)}s.`);
|
|
122
209
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
210
|
+
} catch (error) {
|
|
211
|
+
sample();
|
|
212
|
+
throw new Error(`${error?.message || error} Last boot output: ${phase}. Highest observed memory pressure: ${worst ?? "unknown"}; unavailable samples: ${unknown}.${coverage()} ${recovery} These observations do not establish an OOM crash.`, { cause: error });
|
|
213
|
+
} finally {
|
|
214
|
+
clearInterval(monitor);
|
|
127
215
|
}
|
|
128
|
-
exec.
|
|
216
|
+
exec.runFileQuiet("open", ["-a", "Simulator"], {
|
|
217
|
+
timeoutMs: 5e3,
|
|
218
|
+
killSignal: "SIGKILL"
|
|
219
|
+
});
|
|
129
220
|
}
|
|
130
221
|
function shutdownIosSim(udid) {
|
|
131
222
|
getExecutor().runQuiet(`xcrun simctl shutdown ${udid}`);
|
|
132
223
|
}
|
|
133
224
|
function listIosDeviceTypes() {
|
|
134
|
-
const out = getExecutor().
|
|
225
|
+
const out = getExecutor().runFile("xcrun", [
|
|
226
|
+
"simctl",
|
|
227
|
+
"list",
|
|
228
|
+
"devicetypes",
|
|
229
|
+
"--json"
|
|
230
|
+
], {
|
|
231
|
+
timeoutMs: 3e4,
|
|
232
|
+
killSignal: "SIGKILL"
|
|
233
|
+
});
|
|
135
234
|
return (JSON.parse(out).devicetypes || []).map((dt) => ({
|
|
136
235
|
identifier: dt.identifier,
|
|
137
236
|
name: dt.name
|
|
@@ -367,7 +466,15 @@ function deleteParkedIosSim(udid) {
|
|
|
367
466
|
], { timeoutMs: PARKED_DELETE_TIMEOUT_MS });
|
|
368
467
|
}
|
|
369
468
|
function listIosRuntimes() {
|
|
370
|
-
const out = getExecutor().
|
|
469
|
+
const out = getExecutor().runFile("xcrun", [
|
|
470
|
+
"simctl",
|
|
471
|
+
"list",
|
|
472
|
+
"runtimes",
|
|
473
|
+
"--json"
|
|
474
|
+
], {
|
|
475
|
+
timeoutMs: 3e4,
|
|
476
|
+
killSignal: "SIGKILL"
|
|
477
|
+
});
|
|
371
478
|
return (JSON.parse(out).runtimes || []).filter((r) => r.isAvailable && r.platform === "iOS").map((r) => ({
|
|
372
479
|
identifier: r.identifier,
|
|
373
480
|
name: r.name,
|
|
@@ -379,4 +486,4 @@ function listIosRuntimes() {
|
|
|
379
486
|
}));
|
|
380
487
|
}
|
|
381
488
|
//#endregion
|
|
382
|
-
export {
|
|
489
|
+
export { shutdownIosSim as C, readHostMemoryPressure as E, sanitizeDeviceLabel as S, hostMemoryPressureAdvice as T, renameIosSim as _, deleteIosSim as a, resolveIosCreation as b, iosRuntimeMatches as c, listIosDeviceTypes as d, listIosRuntimes as f, parseRuntimeVersion as g, parkedSimName as h, createOwnedIosSim as i, iosSimulatorFailureAdvice as l, ownedSimName as m, bootIosSim as n, deleteParkedIosSim as o, listUserApps as p, clearAppDataContainer as r, findAppDataContainer as s, IOS_BOOT_TIMEOUT_MS as t, listAllIosSims as u, resetIosKeychain as v, uninstallIosApp as w, resolveOwnedIosSim as x, resetIosPrivacy as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { r as INSTALL_ERROR } from "./app-install-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { r as INSTALL_ERROR } from "./app-install-DIp9riNx.mjs";
|
|
3
3
|
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { V as validateDeviceSlot } from "./config-CcefMY2Q.mjs";
|
|
2
|
+
import { n as SOURCES, t as LEVELS } from "./ndjson-BZwI1NBv.mjs";
|
|
3
|
+
import { D as workspaceLogsDir, p as readWorkspaceState } from "./state-B3XA2wp2.mjs";
|
|
4
|
+
import { a as findProjectRoot } from "./project-fKmuIaMI.mjs";
|
|
4
5
|
import { _ as launchErrorPreview } from "./command-output-8wHMEde0.mjs";
|
|
5
|
-
import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-
|
|
6
|
-
import { a as followLogs, i as fileSizes, n as buildCriteria, o as parseSince, r as compileGrep, s as queryLogs } from "./logs-query-
|
|
6
|
+
import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-DHC31rXA.mjs";
|
|
7
|
+
import { a as followLogs, i as fileSizes, n as buildCriteria, o as parseSince, r as compileGrep, s as queryLogs } from "./logs-query-R-Cqc6Qv.mjs";
|
|
7
8
|
import chalk from "chalk";
|
|
8
9
|
//#region src/commands/logs.ts
|
|
9
10
|
const LEVEL_WIDTH = 5;
|
|
@@ -68,7 +69,7 @@ const LEVEL_COLOURS = {
|
|
|
68
69
|
fatal: chalk.bgRed
|
|
69
70
|
};
|
|
70
71
|
function logsCommand(program) {
|
|
71
|
-
program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build). Prints and exits; nothing matching is a successful, empty result. Use --follow to stream.").option("--source <s...>", "Only these sources: metro, client, device, build, or all").option("--level <l>", `Minimum level: ${LEVELS.join(", ")}`).option("--since <d>", "Only records newer than this, e.g. 30s, 5m, 2h").option("--grep <re>", "Only records whose message matches this regular expression").option("--tail <n>", "Only the last n matching records").option("--errors", "Errors and fatals since the last marker, from metro, client and build, plus confirmed native app-crash reports. Add --source device or --source all for general device errors.").option("--follow", "Keep streaming new records until interrupted").option("--json", "Emit the raw records, one per line (valid NDJSON; zero matches is zero bytes, exit 0)").action(async (opts) => {
|
|
72
|
+
program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build). Prints and exits; nothing matching is a successful, empty result. Use --follow to stream.").option("--slot <name>", "Only records attributed to this device slot", validateDeviceSlot).option("--source <s...>", "Only these sources: metro, client, device, build, or all").option("--level <l>", `Minimum level: ${LEVELS.join(", ")}`).option("--since <d>", "Only records newer than this, e.g. 30s, 5m, 2h").option("--grep <re>", "Only records whose message matches this regular expression").option("--tail <n>", "Only the last n matching records").option("--errors", "Errors and fatals since the last marker, from metro, client and build, plus confirmed native app-crash reports. Add --source device or --source all for general device errors.").option("--follow", "Keep streaming new records until interrupted").option("--json", "Emit the raw records, one per line (valid NDJSON; zero matches is zero bytes, exit 0)").action(async (opts) => {
|
|
72
73
|
const root = findProjectRoot(process.cwd());
|
|
73
74
|
if (!root) {
|
|
74
75
|
console.error(chalk.red("Not in a React Native project (no package.json found)."));
|
|
@@ -102,6 +103,7 @@ function logsCommand(program) {
|
|
|
102
103
|
if (compiled.error) fail(compiled.error);
|
|
103
104
|
}
|
|
104
105
|
const query = {
|
|
106
|
+
slot: opts.slot,
|
|
105
107
|
dir,
|
|
106
108
|
sources,
|
|
107
109
|
minLevel,
|
|
@@ -148,6 +150,7 @@ function logsCommand(program) {
|
|
|
148
150
|
return;
|
|
149
151
|
}
|
|
150
152
|
const criteria = buildCriteria({
|
|
153
|
+
slot: opts.slot,
|
|
151
154
|
sources,
|
|
152
155
|
minLevel,
|
|
153
156
|
since: opts.since,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as parseNdjsonLine, i as levelRank, o as parseNdjsonText } from "./ndjson-
|
|
1
|
+
import { a as parseNdjsonLine, i as levelRank, o as parseNdjsonText } from "./ndjson-BZwI1NBv.mjs";
|
|
2
2
|
import { closeSync, openSync, readFileSync, readSync, readdirSync, statSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { StringDecoder } from "string_decoder";
|
|
@@ -47,6 +47,7 @@ function markerWindow(records) {
|
|
|
47
47
|
}
|
|
48
48
|
function recordMatches(record, criteria = {}) {
|
|
49
49
|
if (!record) return false;
|
|
50
|
+
if (criteria.slot !== void 0 && (record.slot ?? "default") !== criteria.slot) return false;
|
|
50
51
|
const { sources, minLevel, grep, sinceTs, errorsOnly, markerTs, bundleMarkerTs } = criteria;
|
|
51
52
|
if (sources && sources.length > 0 && !sources.includes(record.src) && !(criteria.includeNativeCrashes && record.src === "device" && record.event === "native_crash")) return false;
|
|
52
53
|
if (minLevel && levelRank(record.level) < levelRank(minLevel)) return false;
|
|
@@ -71,8 +72,9 @@ function recordMatches(record, criteria = {}) {
|
|
|
71
72
|
}
|
|
72
73
|
return true;
|
|
73
74
|
}
|
|
74
|
-
function buildCriteria({ sources, minLevel, since, grep, errorsOnly, markerTs, bundleMarkerTs, now } = {}) {
|
|
75
|
+
function buildCriteria({ slot, sources, minLevel, since, grep, errorsOnly, markerTs, bundleMarkerTs, now } = {}) {
|
|
75
76
|
const criteria = {
|
|
77
|
+
...slot === void 0 ? {} : { slot },
|
|
76
78
|
errorsOnly: Boolean(errorsOnly),
|
|
77
79
|
includeNativeCrashes: Boolean(errorsOnly && !sources?.length)
|
|
78
80
|
};
|
|
@@ -160,14 +162,25 @@ function includeBareErrorContext(all, matched, launchTs, sinceTs) {
|
|
|
160
162
|
}
|
|
161
163
|
return sortByTs([...matched, ...renderedContext]);
|
|
162
164
|
}
|
|
163
|
-
function
|
|
164
|
-
const
|
|
165
|
+
function launchMarkersBySlot(records) {
|
|
166
|
+
const markers = /* @__PURE__ */ new Map();
|
|
167
|
+
for (const record of records) {
|
|
168
|
+
if (record.marker !== true || record.src === "metro") continue;
|
|
169
|
+
const ts = tsOf(record);
|
|
170
|
+
const slot = record.slot ?? "default";
|
|
171
|
+
if (ts !== null && ts > (markers.get(slot) ?? -Infinity)) markers.set(slot, ts);
|
|
172
|
+
}
|
|
173
|
+
return markers;
|
|
174
|
+
}
|
|
175
|
+
function queryLogs({ slot, dir, sources, minLevel, since, grep, tail, errorsOnly, errorContext, now } = {}) {
|
|
176
|
+
const all = readLogRecords(dir).filter((record) => slot === void 0 || (record.slot ?? "default") === slot);
|
|
165
177
|
if (all.length === 0) return [];
|
|
166
178
|
const { launchTs, bundleTs } = errorsOnly ? markerWindow(all) : {
|
|
167
179
|
launchTs: null,
|
|
168
180
|
bundleTs: null
|
|
169
181
|
};
|
|
170
182
|
const criteria = buildCriteria({
|
|
183
|
+
slot,
|
|
171
184
|
sources,
|
|
172
185
|
minLevel,
|
|
173
186
|
since,
|
|
@@ -177,7 +190,11 @@ function queryLogs({ dir, sources, minLevel, since, grep, tail, errorsOnly, erro
|
|
|
177
190
|
markerTs: launchTs === null ? void 0 : launchTs,
|
|
178
191
|
bundleMarkerTs: bundleTs === null ? void 0 : bundleTs
|
|
179
192
|
});
|
|
180
|
-
|
|
193
|
+
const slotMarkers = launchMarkersBySlot(all);
|
|
194
|
+
let matched = all.filter((record) => recordMatches(record, {
|
|
195
|
+
...criteria,
|
|
196
|
+
markerTs: record.src === "metro" || record.src === "client" ? criteria.markerTs : slotMarkers.get(record.slot ?? "default")
|
|
197
|
+
}));
|
|
181
198
|
if (typeof tail === "number" && tail >= 0 && matched.length > tail) matched = matched.slice(matched.length - tail);
|
|
182
199
|
return errorContext ? includeBareErrorContext(all, attachExpoErrorContext(all, matched), launchTs, criteria.sinceTs) : matched;
|
|
183
200
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { E as inspectProcessIdentity, M as isOnMountedVolume, N as listMountedVolumes, g as loadConfig, n as allMetroPorts, r as claimMetroPort, v as removeProject } from "./config-
|
|
3
|
-
import { p as readWorkspaceState } from "./state-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { E as inspectProcessIdentity, M as isOnMountedVolume, N as listMountedVolumes, g as loadConfig, n as allMetroPorts, r as claimMetroPort, v as removeProject } from "./config-CcefMY2Q.mjs";
|
|
3
|
+
import { p as readWorkspaceState } from "./state-B3XA2wp2.mjs";
|
|
4
4
|
import { existsSync, readlinkSync, realpathSync } from "fs";
|
|
5
5
|
import { sep } from "path";
|
|
6
6
|
import { request } from "http";
|
|
@@ -49,7 +49,7 @@ function formatNdjsonLine(record) {
|
|
|
49
49
|
return null;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
function createNdjsonWriter(file, { truncate = false } = {}) {
|
|
52
|
+
function createNdjsonWriter(file, { truncate = false, fields = {} } = {}) {
|
|
53
53
|
let fd = null;
|
|
54
54
|
let freshFile = truncate;
|
|
55
55
|
let written = 0;
|
|
@@ -66,7 +66,10 @@ function createNdjsonWriter(file, { truncate = false } = {}) {
|
|
|
66
66
|
dropped += 1;
|
|
67
67
|
return false;
|
|
68
68
|
}
|
|
69
|
-
const line = formatNdjsonLine(
|
|
69
|
+
const line = formatNdjsonLine({
|
|
70
|
+
...stamp(record),
|
|
71
|
+
...fields
|
|
72
|
+
});
|
|
70
73
|
if (line === null) {
|
|
71
74
|
dropped += 1;
|
|
72
75
|
lastError = /* @__PURE__ */ new TypeError("record could not be serialized to JSON");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as sameProcessRecord, E as inspectProcessIdentity } from "./config-
|
|
2
|
-
import { _ as writeWorkspaceState, m as withWorkspaceStateLock, p as readWorkspaceState } from "./state-
|
|
3
|
-
import { r as pidExists } from "./metro-
|
|
1
|
+
import { D as sameProcessRecord, E as inspectProcessIdentity } from "./config-CcefMY2Q.mjs";
|
|
2
|
+
import { _ as writeWorkspaceState, m as withWorkspaceStateLock, p as readWorkspaceState } from "./state-B3XA2wp2.mjs";
|
|
3
|
+
import { r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
4
4
|
import { realpathSync } from "node:fs";
|
|
5
5
|
//#region src/collector/state.ts
|
|
6
6
|
function collectorRoot(root) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { E as inspectProcessIdentity, T as captureProcessToken, u as getConfigDir } from "./config-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { E as inspectProcessIdentity, T as captureProcessToken, u as getConfigDir } from "./config-CcefMY2Q.mjs";
|
|
3
3
|
import { t as createLineReader } from "./process-output-C7IlIzd7.mjs";
|
|
4
|
-
import { r as pidExists } from "./metro-
|
|
5
|
-
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-
|
|
4
|
+
import { r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
5
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-3NcQnZ0X.mjs";
|
|
6
6
|
import { closeSync, mkdirSync, openSync, readFileSync, unlinkSync } from "node:fs";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
8
8
|
import { basename, join, resolve, sep } from "node:path";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as inspectProcessIdentity, w as captureProcessIdentity } from "./config-
|
|
1
|
+
import { E as inspectProcessIdentity, w as captureProcessIdentity } from "./config-CcefMY2Q.mjs";
|
|
2
2
|
import { d as quotedPath } from "./command-output-8wHMEde0.mjs";
|
|
3
3
|
import { lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
@@ -60,15 +60,16 @@ function isClaimUnavailable(err) {
|
|
|
60
60
|
* competing run no protection at all.
|
|
61
61
|
*/
|
|
62
62
|
function claimFailure(err, retryCommand) {
|
|
63
|
+
const retry = retryCommand === null ? "retry the same Stim command" : `run \`${retryCommand}\` again`;
|
|
63
64
|
if (isClaimRefusal(err)) return {
|
|
64
65
|
code: CLAIM_REFUSED,
|
|
65
66
|
message: err.message,
|
|
66
|
-
remedy: `Run \`${err.removeCommand}\`, then
|
|
67
|
+
remedy: `Run \`${err.removeCommand}\`, then ${retry}.`
|
|
67
68
|
};
|
|
68
69
|
if (isClaimUnavailable(err)) return {
|
|
69
70
|
code: CLAIM_UNAVAILABLE,
|
|
70
71
|
message: err.message,
|
|
71
|
-
remedy: `Reinstall Stim so the unique-pid native module for this platform is present, then
|
|
72
|
+
remedy: `Reinstall Stim so the unique-pid native module for this platform is present, then ${retry}.`
|
|
72
73
|
};
|
|
73
74
|
return null;
|
|
74
75
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as findEnclosingWorktreeRoot, f as getProject } from "./config-
|
|
2
|
-
import { g as repoRoot } from "./worktree-
|
|
1
|
+
import { c as findEnclosingWorktreeRoot, f as getProject } from "./config-CcefMY2Q.mjs";
|
|
2
|
+
import { g as repoRoot } from "./worktree-Eq6TLH8N.mjs";
|
|
3
3
|
import { existsSync, readFileSync, readdirSync, realpathSync } from "fs";
|
|
4
4
|
import { basename, dirname, join, resolve } from "path";
|
|
5
5
|
import { createRequire } from "module";
|