stim 1.13.0 → 1.15.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 +2 -0
- package/dist/{activity-DfVKZTEB.mjs → activity-B2-kb7k0.mjs} +281 -41
- package/dist/{android-BHfAu2mf.mjs → android-CYmq0jNi.mjs} +2 -2
- package/dist/{android-CD8pr8Q2.mjs → android-Cu_L4RpL.mjs} +524 -412
- package/dist/{android-qx_31wJo.mjs → android-Db2eEMaf.mjs} +152 -65
- package/dist/android-cas-PnKfAdB2.mjs +167 -0
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{app-install-CDFY2nUL.mjs → app-install-CAAplXAt.mjs} +162 -173
- package/dist/{budget-E5o91NR1.mjs → budget-CMiqghig.mjs} +1048 -77
- package/dist/{build-plan-BTa93o_r.mjs → build-plan-aeGMFX7e.mjs} +193 -650
- package/dist/build-progress-C2Jv1AtA.mjs +872 -0
- package/dist/build-slots-Df1ApSuH.mjs +127 -0
- package/dist/{cache-manifest-DWPF4RKJ.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{chrome-B5hWgQJS.mjs → chrome-BrcVWQyD.mjs} +4 -4
- package/dist/cli-0cX5s4NM.mjs +45 -0
- package/dist/cli.mjs +6 -42
- package/dist/client-C2IS36Qf.mjs +1333 -0
- package/dist/collector-run.mjs +8 -7
- package/dist/{command-output-BIL7rlX7.mjs → command-output-CliHHn7a.mjs} +1 -1
- package/dist/{config-0jCcMM0E.mjs → config-D0DbpZtM.mjs} +29 -29
- package/dist/{created-devices-Cd558h31.mjs → created-devices-BwVb3liH.mjs} +2 -2
- package/dist/{dependency-state-DNN0yfx6.mjs → dependency-state-BmsjKZ2H.mjs} +2 -2
- package/dist/{deps-2Wo81np9.mjs → deps-BFlKbOIp.mjs} +3 -3
- package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
- package/dist/dev-client-CjzLoNs0.mjs +80 -0
- package/dist/{device-Cf7vl-so.mjs → device-BZ1IyS5A.mjs} +7 -7
- package/dist/device-capacity-DMuKC7nx.mjs +136 -0
- package/dist/device-host-worker.d.mts +1 -0
- package/dist/device-host-worker.mjs +769 -0
- package/dist/device-ios-DMQBUPus.mjs +381 -0
- package/dist/{device-lease-CL9dZf73.mjs → device-lease-W5Pi1q38.mjs} +43 -36
- package/dist/{device-pool-MuoiyRcu.mjs → device-pool-B2r38YjS.mjs} +4 -4
- package/dist/{device-remote-DT9ngZiD.mjs → device-remote-9ulPsdhY.mjs} +68 -162
- package/dist/{doctor-D2iysNNH.mjs → doctor-BcE5xsBn.mjs} +191 -99
- package/dist/{error-diagnostics-BoiOhck8.mjs → error-diagnostics-Cb0P1WLS.mjs} +12 -11
- package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
- package/dist/{gc-eA-PRBX8.mjs → gc-BuL1Genr.mjs} +430 -102
- package/dist/{android-cas-B9Kv9aIy.mjs → gradle-CmdOBq1d.mjs} +8 -294
- package/dist/{guide-BfZ0OmiP.mjs → guide-cCSGRFd3.mjs} +2052 -240
- package/dist/{guide-status-BaMYu55M.mjs → guide-status-CIoWK6mG.mjs} +3 -3
- package/dist/hosted-macos-DwowNU7W.mjs +447 -0
- package/dist/idle-shutdown-B5LPaNyY.mjs +122 -0
- package/dist/in-use-CndPMilN.mjs +110 -0
- package/dist/{ios-CmEzZiOj.mjs → ios-3CtCRhwr.mjs} +201 -10
- package/dist/{ios-CcfCeZ19.mjs → ios-Chob8ny7.mjs} +560 -259
- package/dist/{ios-device-BW-t_Lkv.mjs → ios-device-DERmMmk-.mjs} +12 -7
- package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
- package/dist/{launch-verify-CuJaBpEa.mjs → launch-verify-CLlofxRt.mjs} +42 -11
- package/dist/{logs-DcSRbC2t.mjs → logs-h9h6MUvE.mjs} +95 -13
- package/dist/machine-usage-D_YYMzfR.mjs +283 -0
- package/dist/machines-CYtOCqcj.mjs +259 -0
- package/dist/macos-BwtbUtTN.mjs +468 -0
- package/dist/macos-run.d.mts +5 -0
- package/dist/macos-run.mjs +2 -0
- package/dist/{merge-state-ytFQCeh4.mjs → merge-state-BnxLNQiM.mjs} +22 -12
- package/dist/{metro-BPeY1YMh.mjs → metro-Di8EN2Tb.mjs} +20 -120
- package/dist/{named-ports-n7tnJsI8.mjs → named-ports-Dj_XBNaL.mjs} +8 -64
- package/dist/native-run-DFDoIRbY.mjs +147 -0
- package/dist/{native-runtime-CiiFHt0e.mjs → native-runtime-i6OkVg-w.mjs} +11 -6
- package/dist/offload-worker.d.mts +121 -0
- package/dist/offload-worker.mjs +601 -0
- package/dist/{ownership-Bz2kETAS.mjs → ownership-BkYxUtuj.mjs} +3 -2
- package/dist/{page-BTu7I60K.mjs → page-QF_Ke10s.mjs} +7 -2
- package/dist/{ports-C5UutqpJ.mjs → ports-DddwttKM.mjs} +3 -3
- package/dist/prebuild-BvxDlD6C.mjs +213 -0
- package/dist/process-identity-BmRm1qV0.mjs +12 -0
- package/dist/{project-DGeclhvO.mjs → project-CV3tDFHl.mjs} +9 -18
- package/dist/pull-request-pxnDCQzn.mjs +322 -0
- package/dist/pull-requests.d.mts +120 -0
- package/dist/pull-requests.mjs +2 -0
- package/dist/recordings-GEXp4iBT.mjs +37 -0
- package/dist/{reload-C-cV5yy_.mjs → reload-ChPiwvot.mjs} +70 -22
- package/dist/{remote-cache--aehr4Pr.mjs → remote-cache-CO2elm_b.mjs} +4 -4
- package/dist/run-B-xqRrsg.mjs +119 -0
- package/dist/{server-bare-Bq8BpSIo.mjs → server-bare-X7PUgizL.mjs} +60 -13
- package/dist/{server-expo-DUCg52-K.mjs → server-expo-DhtX6bom.mjs} +6 -10
- package/dist/server-expo-KJeD109I.mjs +2 -0
- package/dist/{settings-xB0Frkg6.mjs → settings-CduVcoxj.mjs} +77 -26
- package/dist/{settings-ssVBToDR.mjs → settings-DbL6uhH8.mjs} +16 -10
- package/dist/settings.schema.json +357 -2
- package/dist/{simslim-Bbg9UWrt.mjs → simslim-Ciluxlq4.mjs} +8 -132
- package/dist/slot-launch-BY0BrOLh.mjs +65 -0
- package/dist/{spawn-claims-PT8aQpCa.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
- package/dist/spawn-entry-DncpJvWL.mjs +16 -0
- package/dist/stage-CzaiwFsI.mjs +143 -0
- package/dist/start-CPO4wRg7.mjs +2 -0
- package/dist/{start-BZhItkiL.mjs → start-CUD9nasA.mjs} +108 -61
- package/dist/state-B4PQFXMW.d.mts +12 -0
- package/dist/state-BxCgeTQu.mjs +41 -0
- package/dist/{state-DwAU2_-D.mjs → state-CaeaHbDA.mjs} +7 -4
- package/dist/{state-l1pYwOre.mjs → state-DFm77wRn.mjs} +67 -5
- package/dist/stats-DBLLFmKd.mjs +66 -0
- package/dist/{status-TJlL0HWo.mjs → status-DYXxNOT0.mjs} +425 -260
- package/dist/{status-sszP4XKU.mjs → status-l84Gbvp2.mjs} +122 -20
- package/dist/stdout-reader-C8yjre1x.mjs +23 -0
- package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
- package/dist/stim-footprint.swift +32 -0
- package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
- package/dist/{stop-BZ2qMiBP.mjs → stop-Bad61z_2.mjs} +128 -19
- package/dist/stop-Bvf1MflS.mjs +48 -0
- package/dist/{stop-DskDKNTU.mjs → stop-CceYh1yG.mjs} +2 -2
- package/dist/stop-cause-CZ_Mr-v9.mjs +665 -0
- package/dist/supervisor-run.d.mts +44 -12
- package/dist/supervisor-run.mjs +276 -33
- package/dist/support-CDQbDkL5.mjs +315 -0
- package/dist/support-WLOzVKUv.mjs +176 -0
- package/dist/teardown-BYuQafiA.mjs +718 -0
- package/dist/{xcode-LM6A8cNZ.mjs → toolchain-DmeYjXD9.mjs} +363 -13
- package/dist/warm-progress-DVHLN4uC.mjs +463 -0
- package/dist/{idle-DxLi5OkN.mjs → watchman-Bx0wceoF.mjs} +55 -8
- package/dist/{web-sWXd5iek.mjs → web-k6w8-HnE.mjs} +39 -22
- package/dist/web-run.mjs +326 -13
- package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
- package/dist/workspace-state-CL2V2Ons.mjs +371 -0
- package/dist/worktree-BT_uULFx.mjs +2 -0
- package/dist/{worktree-DeBQSVtR.mjs → worktree-C0c5Udwa.mjs} +55 -54
- package/dist/{worktree-D4Do_XiQ.mjs → worktree-qXKzADSC.mjs} +161 -255
- package/package.json +10 -5
- package/shim/bundle-response.cjs +55 -10
- package/shim/bundle-response.d.cts +1 -0
- package/shim/expo-metro-config.cjs +10 -2
- package/dist/build-progress-l7d-X-ZP.mjs +0 -247
- package/dist/in-use-wYEaKQM9.mjs +0 -249
- package/dist/ownership-PUP4Dwai.mjs +0 -1138
- package/dist/server-expo-BeYwP_Xy.mjs +0 -2
- package/dist/slot-launch-BIWEW-wI.mjs +0 -19
- package/dist/start-Rw2GD3nV.mjs +0 -2
- package/dist/stats-CaSwmsSZ.mjs +0 -62
- package/dist/stats-D8rUTPHd.mjs +0 -368
- package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
- package/dist/worktree-3cBa-bQt.mjs +0 -2
- package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { n as TOOL_ERROR_PREFIX } from "./ios-device-
|
|
3
|
-
import { i as INSTALL_ERROR } from "./app-install-
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { n as TOOL_ERROR_PREFIX } from "./ios-device-Ee7sDXfp.mjs";
|
|
3
|
+
import { i as INSTALL_ERROR } from "./app-install-CAAplXAt.mjs";
|
|
4
4
|
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
@@ -38,12 +38,17 @@ function parseDevicectlDevices(payload) {
|
|
|
38
38
|
transportType: text(connection.transportType),
|
|
39
39
|
platform: text(hardware.platform),
|
|
40
40
|
reality: text(hardware.reality),
|
|
41
|
-
tunnelState: text(connection.tunnelState)
|
|
41
|
+
tunnelState: text(connection.tunnelState),
|
|
42
|
+
model: text(hardware.marketingName)
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
45
|
return out;
|
|
45
46
|
}
|
|
46
47
|
function listIosDevices({ exec = null } = {}) {
|
|
48
|
+
return readIosDevices({ exec }) ?? [];
|
|
49
|
+
}
|
|
50
|
+
/** devicectl's device list, or null when devicectl failed or did not answer within `timeoutMs`. */
|
|
51
|
+
function readIosDevices({ exec = null, timeoutMs = DEVICECTL_TIMEOUT_MS } = {}) {
|
|
47
52
|
const executor = exec || getExecutor();
|
|
48
53
|
const dir = mkdtempSync(join(tmpdir(), "stim-devicectl-"));
|
|
49
54
|
const out = join(dir, "devices.json");
|
|
@@ -54,10 +59,10 @@ function listIosDevices({ exec = null } = {}) {
|
|
|
54
59
|
"devices",
|
|
55
60
|
"-j",
|
|
56
61
|
out
|
|
57
|
-
], { timeoutMs
|
|
62
|
+
], { timeoutMs });
|
|
58
63
|
return parseDevicectlDevices(readFileSync(out, "utf-8"));
|
|
59
64
|
} catch {
|
|
60
|
-
return
|
|
65
|
+
return null;
|
|
61
66
|
} finally {
|
|
62
67
|
rmSync(dir, {
|
|
63
68
|
recursive: true,
|
|
@@ -507,4 +512,4 @@ function localNetworkPending(records, { since = 0, pid = null, lanOrigin }) {
|
|
|
507
512
|
return false;
|
|
508
513
|
}
|
|
509
514
|
//#endregion
|
|
510
|
-
export { iosPoolCandidates as a,
|
|
515
|
+
export { iosPoolCandidates as a, isWirelessIosDevice as c, readIosDevices as d, resolveIosPhysicalDevice as f, iosDeviceProcess as i, listIosDevices as l, installIosDeviceApp as n, iosPoolNoCandidatesRefusal as o, verifyIosDeviceReleaseLaunch as p, iosDeviceBounds as r, isReachable as s, awaitIosDeviceLaunch as t, localNetworkPending as u };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
2
|
import { o as readNdjsonGenerations } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
-
import { s as isAppLaunchError } from "./command-output-
|
|
4
|
-
import { t as DEV_MENU_LAUNCH_ARGS } from "./ios-device-
|
|
5
|
-
import {
|
|
3
|
+
import { s as isAppLaunchError } from "./command-output-CliHHn7a.mjs";
|
|
4
|
+
import { t as DEV_MENU_LAUNCH_ARGS } from "./ios-device-Ee7sDXfp.mjs";
|
|
5
|
+
import { f as deviceShellArg, n as ANDROID_DISABLE_AUTO_LAUNCH_EXTRA, s as androidAppProcess } from "./app-install-CAAplXAt.mjs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
//#region src/engine/app-readiness.ts
|
|
8
8
|
const APP_READINESS_TIMEOUT_MS = 3e4;
|
|
@@ -121,7 +121,12 @@ function nativeLaunchFailure({ readCrashes, since, platform, processAlive, mode,
|
|
|
121
121
|
waitedMs
|
|
122
122
|
} : null;
|
|
123
123
|
}
|
|
124
|
-
async function verifyLaunch({ slot, logsDir, since, metroPort = null, platform = null, mode = null, requireBundleResponse, timeoutMs = VERIFY_TIMEOUT_MS, stabilityMs = STABILITY_WINDOW_MS, pollMs = VERIFY_POLL_MS, readRecords = null, readDeviceRecords = null, readClientRecords = null, readNativeCrashes = null, processAlive = null, onReadinessPending = null, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)) } = {}) {
|
|
124
|
+
async function verifyLaunch({ slot, appPid, platformShared, logsDir, since, metroPort = null, platform = null, mode = null, requireBundleResponse, timeoutMs = VERIFY_TIMEOUT_MS, stabilityMs = STABILITY_WINDOW_MS, pollMs = VERIFY_POLL_MS, readRecords = null, readDeviceRecords = null, readClientRecords = null, readNativeCrashes = null, processAlive = null, onReadinessPending = null, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)) } = {}) {
|
|
125
|
+
const delivered = (record) => deliveryOwner(record, {
|
|
126
|
+
slot,
|
|
127
|
+
appPid,
|
|
128
|
+
platformShared
|
|
129
|
+
}) === "this";
|
|
125
130
|
const read = readRecords || (() => readMetroRecords(logsDir));
|
|
126
131
|
const readDevice = readDeviceRecords || (() => readNdjson(logsDir, "device.ndjson"));
|
|
127
132
|
const readClient = readClientRecords || (() => readNdjson(logsDir, "client.ndjson"));
|
|
@@ -136,10 +141,10 @@ async function verifyLaunch({ slot, logsDir, since, metroPort = null, platform =
|
|
|
136
141
|
let runtimeStartedAt = null;
|
|
137
142
|
let nextCrashCheck = startedAt + 1e3;
|
|
138
143
|
while (true) {
|
|
139
|
-
const metroRecords = read().filter((record) => after(record, since)
|
|
140
|
-
const bundleRecords = metroRecords.filter((record) => !requireBundleResponse || String(record.event).startsWith("bundle_response_"));
|
|
144
|
+
const metroRecords = read().filter((record) => after(record, since));
|
|
145
|
+
const bundleRecords = metroRecords.filter((record) => (!requireBundleResponse || String(record.event).startsWith("bundle_response_")) && delivered(record));
|
|
141
146
|
const deviceRecords = readDevice().filter((record) => after(record, since) && (slot === void 0 || (record.slot ?? "default") === slot));
|
|
142
|
-
const clientRecords = readClient().filter((record) => after(record, since) &&
|
|
147
|
+
const clientRecords = readClient().filter((record) => after(record, since) && !platformShared);
|
|
143
148
|
if (now() >= nextCrashCheck) {
|
|
144
149
|
nextCrashCheck = now() + 2e3;
|
|
145
150
|
const crash = nativeLaunchFailure({
|
|
@@ -238,6 +243,11 @@ async function verifyLaunch({ slot, logsDir, since, metroPort = null, platform =
|
|
|
238
243
|
}
|
|
239
244
|
if ((!proof || runtimeWaiting) && now() >= bundleDeadline) return bundleTimeoutOutcome({
|
|
240
245
|
requested: findBundleRequest(deviceRecords, since, metroPort, platform) ?? activity,
|
|
246
|
+
unattributed: metroRecords.find((record) => record.event === "bundle_response_finished" && deliveryOwner(record, {
|
|
247
|
+
slot,
|
|
248
|
+
appPid,
|
|
249
|
+
platformShared
|
|
250
|
+
}) === "unknown" && isBundleProof(record, since, platform)) ?? null,
|
|
241
251
|
processAlive,
|
|
242
252
|
deviceRecords,
|
|
243
253
|
platform,
|
|
@@ -247,7 +257,12 @@ async function verifyLaunch({ slot, logsDir, since, metroPort = null, platform =
|
|
|
247
257
|
await sleep(Math.min(pollMs, Math.max(0, (runtimeWaiting ? bundleDeadline : proof && pendingAt !== null ? readinessDeadline : stabilityDeadline ?? bundleDeadline) - now())));
|
|
248
258
|
}
|
|
249
259
|
}
|
|
250
|
-
function
|
|
260
|
+
function deliveryOwner(record, { slot, appPid, platformShared }) {
|
|
261
|
+
if (slot === void 0) return "this";
|
|
262
|
+
if (typeof record.clientPid === "number" && appPid) return record.clientPid === appPid ? "this" : "other";
|
|
263
|
+
return platformShared ? "unknown" : "this";
|
|
264
|
+
}
|
|
265
|
+
function bundleTimeoutOutcome({ requested, unattributed, processAlive, deviceRecords, platform, mode, waitedMs }) {
|
|
251
266
|
if (processAlive?.() === false) return {
|
|
252
267
|
verified: false,
|
|
253
268
|
fatal: true,
|
|
@@ -256,13 +271,21 @@ function bundleTimeoutOutcome({ requested, processAlive, deviceRecords, platform
|
|
|
256
271
|
mode,
|
|
257
272
|
waitedMs
|
|
258
273
|
};
|
|
259
|
-
|
|
274
|
+
if (requested) return {
|
|
260
275
|
verified: false,
|
|
261
276
|
timedOut: true,
|
|
262
277
|
requested: true,
|
|
263
278
|
record: requested,
|
|
264
279
|
mode,
|
|
265
280
|
waitedMs
|
|
281
|
+
};
|
|
282
|
+
return unattributed ? {
|
|
283
|
+
verified: false,
|
|
284
|
+
timedOut: true,
|
|
285
|
+
unattributed: true,
|
|
286
|
+
record: unattributed,
|
|
287
|
+
mode,
|
|
288
|
+
waitedMs
|
|
266
289
|
} : {
|
|
267
290
|
verified: false,
|
|
268
291
|
timedOut: true,
|
|
@@ -316,6 +339,14 @@ function readCollectorRecords(logsDir) {
|
|
|
316
339
|
function readNdjson(logsDir, name) {
|
|
317
340
|
return logsDir ? readNdjsonGenerations(join(logsDir, name)) : [];
|
|
318
341
|
}
|
|
342
|
+
function unattributedLaunchLines({ platform, metroPort, slot = "default", siblings }) {
|
|
343
|
+
const others = siblings.length === 1 ? `Slot ${siblings[0]} also runs` : `Slots ${siblings.join(", ")} also run`;
|
|
344
|
+
return [
|
|
345
|
+
`UNVERIFIED: Metro delivered ${platform === "ios" ? "an iOS" : "an Android"} bundle on port ${metroPort}, but not provably to this device`,
|
|
346
|
+
`${others} ${platform} on this workspace's Metro, and this bundle delivery could not be matched to this device.`,
|
|
347
|
+
`Check this device directly: its screen through your device tool, or \`stim logs --slot ${slot} --source device\`. A slot stops counting as a sibling after \`stim stop --slot <name>\`.`
|
|
348
|
+
];
|
|
349
|
+
}
|
|
319
350
|
function unverifiedLaunchLines({ platform, metroPort, waitedMs = VERIFY_TIMEOUT_MS, bundleId = null, udid = null, serial = null, devClientUrl: url = null, mode = null, remote = false, physical = false, devClient = false, lanOrigin = null, metroOrigin = null, localNetworkPending = false, component = null }) {
|
|
320
351
|
const seconds = Math.round(Number(waitedMs || 0) / 1e3);
|
|
321
352
|
const localNetwork = localNetworkPending && platform === "ios" && physical;
|
|
@@ -375,4 +406,4 @@ function unverifiedLaunchLines({ platform, metroPort, waitedMs = VERIFY_TIMEOUT_
|
|
|
375
406
|
return lines;
|
|
376
407
|
}
|
|
377
408
|
//#endregion
|
|
378
|
-
export { VERIFY_TIMEOUT_MS as a, readMetroRecords as c,
|
|
409
|
+
export { VERIFY_TIMEOUT_MS as a, readMetroRecords as c, verifyAndroidReleaseLaunch as d, verifyLaunch as f, RELEASE_VERIFY_WAIT_MS as i, unattributedLaunchLines as l, APP_READINESS_TIMEOUT_MS as m, LAUNCH_FATAL as n, isBundleProof as o, verifyReleaseLaunch as p, LAUNCH_UNVERIFIED as r, readCollectorRecords as s, LAUNCH_BUNDLING as t, unverifiedLaunchLines as u };
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { H as
|
|
1
|
+
import { H as projectDeviceSlots, V as parseDeviceSlotOption, _ as loadConfig$1, g as isPathPrefix } from "./config-D0DbpZtM.mjs";
|
|
2
|
+
import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
2
3
|
import { n as SOURCES, t as LEVELS } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { i as findCommandWorkspace } from "./project-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import { C as workspaceLogsDir, r as readWorkspaceState$1 } from "./workspace-state-CL2V2Ons.mjs";
|
|
5
|
+
import { i as findCommandWorkspace } from "./project-CV3tDFHl.mjs";
|
|
6
|
+
import { o as readAgentDeviceRecords, t as agentDeviceLiveness } from "./activity-B2-kb7k0.mjs";
|
|
7
|
+
import { f as refuseNoProject, l as phaseLine, v as launchErrorPreview } from "./command-output-CliHHn7a.mjs";
|
|
8
|
+
import { a as pullHostedMacosLogs, t as connectHost } from "./hosted-macos-DwowNU7W.mjs";
|
|
9
|
+
import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-Cb0P1WLS.mjs";
|
|
10
|
+
import { t as watchStdoutReader } from "./stdout-reader-C8yjre1x.mjs";
|
|
8
11
|
import { closeSync, fstatSync, openSync, readFileSync, readSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
9
|
-
import { attachExpoErrorContext, buildCriteria, compileGrep, fileSizes, followLogs, logFiles, parseSince, queryLogs, readLogRecords, recordMatches, sortByTs } from "@stim-cli/core/state";
|
|
10
12
|
import { join, relative, resolve, sep } from "node:path";
|
|
13
|
+
import { attachExpoErrorContext, buildCriteria, compileGrep, fileSizes, followLogs, logFiles, parseSince, queryLogs, readLogRecords, readMacosRecord, recordMatches, sortByTs } from "@stim-cli/core/state";
|
|
11
14
|
import { homedir } from "node:os";
|
|
12
15
|
import chalk from "chalk";
|
|
13
16
|
//#region src/devices/agent-actions.ts
|
|
@@ -17,6 +20,8 @@ function object(value) {
|
|
|
17
20
|
}
|
|
18
21
|
function parseAgentEvents(lines) {
|
|
19
22
|
const events = [];
|
|
23
|
+
const started = [];
|
|
24
|
+
const finished = [];
|
|
20
25
|
let session = null;
|
|
21
26
|
let unknownVersion = null;
|
|
22
27
|
for (const line of lines) {
|
|
@@ -37,9 +42,14 @@ function parseAgentEvents(lines) {
|
|
|
37
42
|
}
|
|
38
43
|
if (typeof entry.session === "string") session ??= entry.session;
|
|
39
44
|
const { kind, command, summary } = entry;
|
|
45
|
+
const requestId = typeof entry.requestId === "string" ? entry.requestId : null;
|
|
46
|
+
if (kind === "request.started" && requestId && Number.isFinite(ts)) started.push([requestId, ts]);
|
|
40
47
|
if (kind !== "action.recorded" && kind !== "request.finished") continue;
|
|
41
48
|
const failed = kind === "request.finished" && entry.status === "error";
|
|
42
|
-
if (kind === "request.finished" && !failed)
|
|
49
|
+
if (kind === "request.finished" && !failed) {
|
|
50
|
+
if (requestId) finished.push(requestId);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
43
53
|
if (!Number.isFinite(ts) || typeof entry.session !== "string" || typeof command !== "string") continue;
|
|
44
54
|
if (typeof summary !== "string") continue;
|
|
45
55
|
events.push({
|
|
@@ -49,11 +59,14 @@ function parseAgentEvents(lines) {
|
|
|
49
59
|
command,
|
|
50
60
|
summary,
|
|
51
61
|
failed,
|
|
52
|
-
details: object(entry.details)
|
|
62
|
+
details: object(entry.details),
|
|
63
|
+
requestId
|
|
53
64
|
});
|
|
54
65
|
}
|
|
55
66
|
return {
|
|
56
67
|
events,
|
|
68
|
+
started,
|
|
69
|
+
finished,
|
|
57
70
|
session,
|
|
58
71
|
unknownVersion
|
|
59
72
|
};
|
|
@@ -103,9 +116,10 @@ function spanDevice(spans, ts) {
|
|
|
103
116
|
for (const span of spans) if (span.from <= ts) device = span.deviceId;
|
|
104
117
|
return device;
|
|
105
118
|
}
|
|
106
|
-
function agentRecord(event, deviceId, target) {
|
|
119
|
+
function agentRecord(event, deviceId, target, startedAt) {
|
|
107
120
|
return {
|
|
108
121
|
ts: event.ts,
|
|
122
|
+
...startedAt !== void 0 && startedAt <= event.ts ? { startedAt } : {},
|
|
109
123
|
src: "agent",
|
|
110
124
|
level: event.failed ? "error" : "info",
|
|
111
125
|
msg: event.summary,
|
|
@@ -221,7 +235,8 @@ function createAgentActionReader({ targets, sinceTs = -Infinity, home = homedir(
|
|
|
221
235
|
closes: [],
|
|
222
236
|
runner: null,
|
|
223
237
|
session: null,
|
|
224
|
-
unknownReported: false
|
|
238
|
+
unknownReported: false,
|
|
239
|
+
started: /* @__PURE__ */ new Map()
|
|
225
240
|
};
|
|
226
241
|
cursors.set(name, cursor);
|
|
227
242
|
try {
|
|
@@ -234,8 +249,13 @@ function createAgentActionReader({ targets, sinceTs = -Infinity, home = homedir(
|
|
|
234
249
|
cursor.offset = chunk.next;
|
|
235
250
|
lines.push(...chunk.text.split("\n"));
|
|
236
251
|
const parsed = parseAgentEvents(lines);
|
|
252
|
+
for (const [requestId, at] of parsed.started) cursor.started.set(requestId, at);
|
|
237
253
|
cursor.session ??= parsed.session;
|
|
238
254
|
const session = cursor.session;
|
|
255
|
+
const matched = new Map(parsed.events.flatMap((event) => event.requestId && cursor.started.has(event.requestId) ? [[event.requestId, cursor.started.get(event.requestId)]] : []));
|
|
256
|
+
const failed = parsed.events.flatMap((event) => event.failed && event.requestId ? [event.requestId] : []);
|
|
257
|
+
for (const requestId of [...parsed.finished, ...failed]) cursor.started.delete(requestId);
|
|
258
|
+
for (const requestId of [...cursor.started.keys()].slice(0, -64)) cursor.started.delete(requestId);
|
|
239
259
|
if (!parsed.events.length && !parsed.unknownVersion) continue;
|
|
240
260
|
const runnerPath = join(dir, "runner.log");
|
|
241
261
|
let runnerSize = -1;
|
|
@@ -267,13 +287,69 @@ function createAgentActionReader({ targets, sinceTs = -Infinity, home = homedir(
|
|
|
267
287
|
if (event.ts < sinceTs) continue;
|
|
268
288
|
const deviceId = deviceAt(event.ts);
|
|
269
289
|
const target = deviceId ? byId.get(deviceId) : void 0;
|
|
270
|
-
|
|
290
|
+
const startedAt = event.requestId ? matched.get(event.requestId) : void 0;
|
|
291
|
+
if (target && deviceId) out.push(agentRecord(event, deviceId, target, startedAt));
|
|
271
292
|
}
|
|
272
293
|
}
|
|
273
294
|
return out.toSorted((a, b) => a.ts - b.ts);
|
|
274
295
|
};
|
|
275
296
|
}
|
|
276
297
|
//#endregion
|
|
298
|
+
//#region src/device-host/hosted-logs-sync.ts
|
|
299
|
+
function warning(machine, error) {
|
|
300
|
+
const message = error.message.replace(/\.$/, "");
|
|
301
|
+
const hint = message.includes("refused device-host.logs.query") ? ` If ${machine} runs an older stim-server, update it.` : "";
|
|
302
|
+
return phaseLine("device", `Could not read the app's logs from ${machine}: ${message}. Showing the logs already copied here.${hint}`);
|
|
303
|
+
}
|
|
304
|
+
async function syncHostedMacosLogs(root, placement) {
|
|
305
|
+
let host;
|
|
306
|
+
try {
|
|
307
|
+
host = await connectHost(placement.machine);
|
|
308
|
+
await pullHostedMacosLogs(root, placement, host);
|
|
309
|
+
return true;
|
|
310
|
+
} catch (error) {
|
|
311
|
+
process.stderr.write(`${warning(placement.machine, error)}\n`);
|
|
312
|
+
return false;
|
|
313
|
+
} finally {
|
|
314
|
+
host?.connection.close();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function followHostedMacosLogs(root, { failing = false, intervalMs = 500, retryMs = 5e3 } = {}) {
|
|
318
|
+
let host;
|
|
319
|
+
let retryAt = 0;
|
|
320
|
+
let stopped = false;
|
|
321
|
+
let running = false;
|
|
322
|
+
const tick = async () => {
|
|
323
|
+
if (running || stopped || Date.now() < retryAt) return;
|
|
324
|
+
running = true;
|
|
325
|
+
try {
|
|
326
|
+
const placement = readMacosRecord(root)?.host;
|
|
327
|
+
if (!placement) {
|
|
328
|
+
host?.connection.close();
|
|
329
|
+
host = void 0;
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
host ??= await connectHost(placement.machine);
|
|
333
|
+
await pullHostedMacosLogs(root, placement, host);
|
|
334
|
+
failing = false;
|
|
335
|
+
} catch (error) {
|
|
336
|
+
host?.connection.close();
|
|
337
|
+
host = void 0;
|
|
338
|
+
if (!failing) process.stderr.write(`${warning(readMacosRecord(root)?.host?.machine ?? "the host", error)}\n`);
|
|
339
|
+
failing = true;
|
|
340
|
+
retryAt = Date.now() + retryMs;
|
|
341
|
+
} finally {
|
|
342
|
+
running = false;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
const timer = setInterval(() => void tick(), intervalMs);
|
|
346
|
+
return () => {
|
|
347
|
+
stopped = true;
|
|
348
|
+
clearInterval(timer);
|
|
349
|
+
host?.connection.close();
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
//#endregion
|
|
277
353
|
//#region src/commands/logs.ts
|
|
278
354
|
const LEVEL_WIDTH = 5;
|
|
279
355
|
const SRC_WIDTH = 6;
|
|
@@ -359,7 +435,7 @@ const LEVEL_COLOURS = {
|
|
|
359
435
|
fatal: chalk.bgRed
|
|
360
436
|
};
|
|
361
437
|
function logsCommand(program) {
|
|
362
|
-
program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build, agent
|
|
438
|
+
program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build, agent actions). Prints and exits; an existing timeline with nothing matching is a successful, empty result. Use --follow to stream.").option("--slot <name>", "Only this device slot's records, plus the shared Metro and app client records once it has launched", parseDeviceSlotOption).option("--source <s...>", "Only these sources: metro, client, device, build, agent, 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 and stim web browser errors. 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) => {
|
|
363
439
|
const root = findCommandWorkspace(process.cwd());
|
|
364
440
|
if (!root) {
|
|
365
441
|
refuseNoProject({ json: false });
|
|
@@ -393,6 +469,8 @@ function logsCommand(program) {
|
|
|
393
469
|
if (compiled.error) fail(compiled.error);
|
|
394
470
|
}
|
|
395
471
|
requireLogsWorkspace(root, dir);
|
|
472
|
+
const hosted = readMacosRecord(root)?.host;
|
|
473
|
+
const hostedReachable = hosted ? await syncHostedMacosLogs(root, hosted) : true;
|
|
396
474
|
const query = {
|
|
397
475
|
slot: opts.slot,
|
|
398
476
|
dir,
|
|
@@ -469,11 +547,15 @@ function logsCommand(program) {
|
|
|
469
547
|
const agentTimer = readAgent ? setInterval(() => {
|
|
470
548
|
for (const record of readAgent()) if (recordMatches(record, criteria)) emit(record);
|
|
471
549
|
}, 500) : null;
|
|
550
|
+
const stopHosted = hosted ? followHostedMacosLogs(root, { failing: !hostedReachable }) : null;
|
|
472
551
|
const finish = () => {
|
|
473
552
|
stop();
|
|
553
|
+
stopHosted?.();
|
|
554
|
+
stopReader();
|
|
474
555
|
if (agentTimer) clearInterval(agentTimer);
|
|
475
556
|
process.exit(0);
|
|
476
557
|
};
|
|
558
|
+
const stopReader = watchStdoutReader(finish);
|
|
477
559
|
process.on("SIGINT", finish);
|
|
478
560
|
process.on("SIGTERM", finish);
|
|
479
561
|
});
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { compiledHelper, configDir } from "@stim-cli/core";
|
|
4
|
+
import { MACHINE_OWNER_KINDS } from "@stim-cli/core/state";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
//#region src/footprint.ts
|
|
7
|
+
const SOURCE = "stim-footprint.swift";
|
|
8
|
+
const COMPILE_TIMEOUT_MS = 12e4;
|
|
9
|
+
const READ_TIMEOUT_MS = 5e3;
|
|
10
|
+
function helperSource() {
|
|
11
|
+
const here = fileURLToPath(import.meta.url);
|
|
12
|
+
if (basename(dirname(here)) === "src") return fileURLToPath(new URL(`../helper/${SOURCE}`, import.meta.url));
|
|
13
|
+
return join(dirname(here), SOURCE);
|
|
14
|
+
}
|
|
15
|
+
async function buildHelper() {
|
|
16
|
+
const exec = getExecutor();
|
|
17
|
+
if (!exec.runFileQuiet("xcode-select", ["-p"], { timeoutMs: READ_TIMEOUT_MS })) return null;
|
|
18
|
+
const source = helperSource();
|
|
19
|
+
try {
|
|
20
|
+
return await compiledHelper({
|
|
21
|
+
dir: join(configDir(), "helpers"),
|
|
22
|
+
name: "stim-footprint",
|
|
23
|
+
inputs: [source],
|
|
24
|
+
version: "",
|
|
25
|
+
compile: async (output) => {
|
|
26
|
+
await exec.runFileAsync("xcrun", [
|
|
27
|
+
"swiftc",
|
|
28
|
+
"-O",
|
|
29
|
+
"-swift-version",
|
|
30
|
+
"5",
|
|
31
|
+
"-o",
|
|
32
|
+
output,
|
|
33
|
+
source
|
|
34
|
+
], { timeoutMs: COMPILE_TIMEOUT_MS });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const RETRY_BACKOFF_INITIAL_MS = 1e4;
|
|
42
|
+
const RETRY_BACKOFF_MAX_MS = 6e5;
|
|
43
|
+
let built = null;
|
|
44
|
+
let failure = null;
|
|
45
|
+
/** The `stim-footprint` helper, compiled on first use. A success is kept for the process's life; a failure retries after a doubling backoff instead of being pinned forever. */
|
|
46
|
+
function footprintHelper() {
|
|
47
|
+
const home = configDir();
|
|
48
|
+
if (built?.home === home) return built.promise;
|
|
49
|
+
if (failure?.home === home && Date.now() < failure.nextRetryAt) return Promise.resolve(null);
|
|
50
|
+
const promise = buildHelper().then((helper) => {
|
|
51
|
+
if (helper === null) {
|
|
52
|
+
const backoffMs = failure?.home === home ? Math.min(failure.backoffMs * 2, RETRY_BACKOFF_MAX_MS) : RETRY_BACKOFF_INITIAL_MS;
|
|
53
|
+
failure = {
|
|
54
|
+
home,
|
|
55
|
+
nextRetryAt: Date.now() + backoffMs,
|
|
56
|
+
backoffMs
|
|
57
|
+
};
|
|
58
|
+
if (built?.promise === promise) built = null;
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return helper;
|
|
62
|
+
});
|
|
63
|
+
built = {
|
|
64
|
+
home,
|
|
65
|
+
promise
|
|
66
|
+
};
|
|
67
|
+
return promise;
|
|
68
|
+
}
|
|
69
|
+
/** Parses the helper's `<pid> <bytes>` lines into footprint bytes by pid. */
|
|
70
|
+
function parseFootprints(output) {
|
|
71
|
+
const footprints = /* @__PURE__ */ new Map();
|
|
72
|
+
for (const line of output.split("\n")) {
|
|
73
|
+
const match = /^(\d+) (\d+)$/.exec(line.trim());
|
|
74
|
+
if (match) footprints.set(Number(match[1]), Number(match[2]));
|
|
75
|
+
}
|
|
76
|
+
return footprints;
|
|
77
|
+
}
|
|
78
|
+
/** Every readable process's physical footprint in bytes, or null when the helper is unavailable or fails. */
|
|
79
|
+
async function readFootprints() {
|
|
80
|
+
const helper = await footprintHelper();
|
|
81
|
+
const output = helper ? getExecutor().runFileQuiet(helper, [], { timeoutMs: READ_TIMEOUT_MS }) : null;
|
|
82
|
+
return output === null ? null : parseFootprints(output);
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/machine-usage.ts
|
|
86
|
+
const SHARED = [
|
|
87
|
+
{
|
|
88
|
+
name: "CoreSimulator services",
|
|
89
|
+
pattern: /\/CoreSimulator\.framework\/|\/Simulator\.app\/Contents\/MacOS\//
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "adb server",
|
|
93
|
+
pattern: /(^|\/)adb\s.*\bfork-server\b/
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "Android emulator services",
|
|
97
|
+
pattern: /\/emulator\/netsimd(\s|$)/
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "Gradle daemon",
|
|
101
|
+
pattern: /\borg\.gradle\.launcher\.daemon\.bootstrap\.GradleDaemon\b/
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "Kotlin daemon",
|
|
105
|
+
pattern: /\bKotlinCompileDaemon\b/
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "Watchman",
|
|
109
|
+
pattern: /(^|\/)watchman(\s|$)/
|
|
110
|
+
}
|
|
111
|
+
];
|
|
112
|
+
const STIM_SERVER_COMMAND = /(^|[\s/])stim-server(\.mjs)?(\s|$)/;
|
|
113
|
+
const LAUNCHD_SIM = /^launchd_sim\s.*\/Devices\/([^/\s]+)\//;
|
|
114
|
+
const MAX_DEPTH = 64;
|
|
115
|
+
const EMULATOR = /(?:^|\/)(?:qemu-system-[^\s/]+|emulator)(?:\s.*)?\s(?:-avd\s+|@)(\S+)/;
|
|
116
|
+
function emulatorAvd(command) {
|
|
117
|
+
return EMULATOR.exec(command)?.[1] ?? null;
|
|
118
|
+
}
|
|
119
|
+
function workspaceOwner(kind, env, name, id) {
|
|
120
|
+
return {
|
|
121
|
+
kind,
|
|
122
|
+
name,
|
|
123
|
+
workspace: env.path,
|
|
124
|
+
id,
|
|
125
|
+
owned: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function rank(owner) {
|
|
129
|
+
return MACHINE_OWNER_KINDS.indexOf(owner.kind);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Attributes every process in `processes` to at most one owner: the owner of its nearest ancestor (itself included)
|
|
133
|
+
* that is a root. Roots are each booted simulator's `launchd_sim`, each emulator launcher and qemu process, and each
|
|
134
|
+
* workspace's verified supervisor and Metro, running build and Chrome. Only a process under none of those falls back
|
|
135
|
+
* to stim-server or a machine-wide service in `SHARED`, so a `simctl` a workspace's log collector runs stays with the
|
|
136
|
+
* workspace. An emulator counts in the workspace that records its AVD whenever its process runs, including while adb
|
|
137
|
+
* does not list it. A process with no root ancestor is left out. `footprints` holds physical footprint bytes by pid,
|
|
138
|
+
* or is null when they could not be read, and the owners' `memoryMb` then sums resident sizes. A process missing from
|
|
139
|
+
* `footprints`, another user's or one that exited between the two reads, counts its resident size.
|
|
140
|
+
*/
|
|
141
|
+
function attributeMachineUsage({ processes, footprints, environments, roots, simNames }) {
|
|
142
|
+
const owners = /* @__PURE__ */ new Map();
|
|
143
|
+
const rootOf = /* @__PURE__ */ new Map();
|
|
144
|
+
const fallbackOf = /* @__PURE__ */ new Map();
|
|
145
|
+
const claim = (pid, key, owner, into = rootOf) => {
|
|
146
|
+
if (!owners.has(key)) owners.set(key, owner);
|
|
147
|
+
into.set(pid, key);
|
|
148
|
+
};
|
|
149
|
+
const sims = /* @__PURE__ */ new Map();
|
|
150
|
+
const emulators = /* @__PURE__ */ new Map();
|
|
151
|
+
for (const env of environments) for (const device of [{
|
|
152
|
+
slot: "default",
|
|
153
|
+
ios: env.ios,
|
|
154
|
+
android: env.android
|
|
155
|
+
}, ...env.slots ?? []]) {
|
|
156
|
+
const slot = device.slot === "default" ? {} : { slot: device.slot };
|
|
157
|
+
if (device.ios?.state === "Booted") sims.set(device.ios.udid.toUpperCase(), {
|
|
158
|
+
kind: "simulator",
|
|
159
|
+
name: device.ios.name ?? device.ios.udid,
|
|
160
|
+
workspace: env.path,
|
|
161
|
+
...slot,
|
|
162
|
+
id: device.ios.udid,
|
|
163
|
+
owned: device.ios.owned
|
|
164
|
+
});
|
|
165
|
+
if (device.android?.name && !device.android.physical) emulators.set(device.android.name, {
|
|
166
|
+
kind: "emulator",
|
|
167
|
+
name: device.android.name,
|
|
168
|
+
workspace: env.path,
|
|
169
|
+
...slot,
|
|
170
|
+
id: device.android.name,
|
|
171
|
+
owned: device.android.owned
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
for (const p of processes) {
|
|
175
|
+
const shared = SHARED.find(({ pattern }) => pattern.test(p.command));
|
|
176
|
+
if (shared) {
|
|
177
|
+
const owner = {
|
|
178
|
+
kind: "shared",
|
|
179
|
+
name: shared.name,
|
|
180
|
+
workspace: null,
|
|
181
|
+
id: null,
|
|
182
|
+
owned: false
|
|
183
|
+
};
|
|
184
|
+
claim(p.pid, `shared:${shared.name}`, owner, fallbackOf);
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (STIM_SERVER_COMMAND.test(p.command)) {
|
|
188
|
+
claim(p.pid, "server", {
|
|
189
|
+
kind: "server",
|
|
190
|
+
name: "stim-server",
|
|
191
|
+
workspace: null,
|
|
192
|
+
id: null,
|
|
193
|
+
owned: false
|
|
194
|
+
}, fallbackOf);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const udid = LAUNCHD_SIM.exec(p.command)?.[1]?.toUpperCase();
|
|
198
|
+
if (udid) {
|
|
199
|
+
const owner = sims.get(udid) ?? {
|
|
200
|
+
kind: "simulator",
|
|
201
|
+
name: simNames[udid] ?? udid,
|
|
202
|
+
workspace: null,
|
|
203
|
+
id: udid,
|
|
204
|
+
owned: false
|
|
205
|
+
};
|
|
206
|
+
claim(p.pid, `simulator:${udid}`, owner);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const avd = emulatorAvd(p.command);
|
|
210
|
+
if (avd) {
|
|
211
|
+
const owner = emulators.get(avd) ?? {
|
|
212
|
+
kind: "emulator",
|
|
213
|
+
name: avd,
|
|
214
|
+
workspace: null,
|
|
215
|
+
id: avd,
|
|
216
|
+
owned: false
|
|
217
|
+
};
|
|
218
|
+
claim(p.pid, `emulator:${avd}`, owner);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const present = new Set(processes.map((p) => p.pid));
|
|
222
|
+
const byPath = new Map(environments.map((env) => [env.path, env]));
|
|
223
|
+
for (const root of roots) {
|
|
224
|
+
const env = byPath.get(root.path);
|
|
225
|
+
if (!env) continue;
|
|
226
|
+
const metroPids = [root.supervisorPid, env.metro?.running ? env.metro.pid : null];
|
|
227
|
+
for (const pid of metroPids) if (pid && present.has(pid)) {
|
|
228
|
+
const port = env.metro?.port ?? null;
|
|
229
|
+
claim(pid, `metro:${env.path}`, workspaceOwner("metro", env, port ? `Metro :${port}` : "Metro", port ? String(port) : null));
|
|
230
|
+
}
|
|
231
|
+
if (root.build && present.has(root.build.pid)) {
|
|
232
|
+
const label = root.build.platform === "ios" ? "iOS build" : "Android build";
|
|
233
|
+
claim(root.build.pid, `build:${env.path}`, workspaceOwner("build", env, label, root.build.platform));
|
|
234
|
+
}
|
|
235
|
+
for (const pid of root.macosPids ?? []) if (present.has(pid)) claim(pid, `macos:${env.path}`, workspaceOwner("macos", env, env.macos?.product ?? "macOS app", null));
|
|
236
|
+
for (const pid of root.browserPids) if (present.has(pid)) claim(pid, `browser:${env.path}`, workspaceOwner("browser", env, "Chrome", null));
|
|
237
|
+
}
|
|
238
|
+
const parentOf = new Map(processes.map((p) => [p.pid, p.ppid]));
|
|
239
|
+
const totals = /* @__PURE__ */ new Map();
|
|
240
|
+
for (const p of processes) {
|
|
241
|
+
let pid = p.pid;
|
|
242
|
+
let key;
|
|
243
|
+
let fallback;
|
|
244
|
+
for (let depth = 0; pid !== void 0 && pid > 1 && depth < MAX_DEPTH; depth++) {
|
|
245
|
+
key = rootOf.get(pid);
|
|
246
|
+
if (key) break;
|
|
247
|
+
fallback ??= fallbackOf.get(pid);
|
|
248
|
+
pid = parentOf.get(pid);
|
|
249
|
+
}
|
|
250
|
+
key ??= fallback;
|
|
251
|
+
if (!key) continue;
|
|
252
|
+
const total = totals.get(key) ?? {
|
|
253
|
+
rssKb: 0,
|
|
254
|
+
memoryKb: 0,
|
|
255
|
+
cpu: 0,
|
|
256
|
+
processes: 0
|
|
257
|
+
};
|
|
258
|
+
total.rssKb += p.rssKb;
|
|
259
|
+
const footprint = footprints?.get(p.pid);
|
|
260
|
+
total.memoryKb += footprint === void 0 ? p.rssKb : footprint / 1024;
|
|
261
|
+
total.cpu += p.cpuPercent;
|
|
262
|
+
total.processes += 1;
|
|
263
|
+
totals.set(key, total);
|
|
264
|
+
}
|
|
265
|
+
const list = [];
|
|
266
|
+
for (const [key, owner] of owners) {
|
|
267
|
+
const total = totals.get(key);
|
|
268
|
+
if (total) list.push({
|
|
269
|
+
...owner,
|
|
270
|
+
cpuPercent: Math.round(total.cpu),
|
|
271
|
+
residentMb: Math.round(total.rssKb / 1024),
|
|
272
|
+
memoryMb: Math.round(total.memoryKb / 1024),
|
|
273
|
+
processes: total.processes
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
list.sort((x, y) => rank(x) - rank(y) || (x.workspace ?? "~").localeCompare(y.workspace ?? "~") || x.name.localeCompare(y.name));
|
|
277
|
+
return {
|
|
278
|
+
memorySource: footprints ? "footprint" : "rss",
|
|
279
|
+
owners: list
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
//#endregion
|
|
283
|
+
export { attributeMachineUsage as n, readFootprints as r, STIM_SERVER_COMMAND as t };
|