@4pm/cli 1.4.0 → 1.4.2
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/dist/index.js +122 -28
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28794,6 +28794,7 @@ var WORKER_TOOL_CATALOG = [
|
|
|
28794
28794
|
var WORKER_TOOL_PREREQUISITE_IDS = WORKER_TOOL_CATALOG.filter(
|
|
28795
28795
|
(t) => t.installPackage === null
|
|
28796
28796
|
).map((t) => t.id);
|
|
28797
|
+
var WORKER_TOOL_BUNDLED_GLOBALS = ["npm", "corepack"];
|
|
28797
28798
|
|
|
28798
28799
|
// vendor/@4pm/constants/ws.ts
|
|
28799
28800
|
var WsChannel = {
|
|
@@ -33308,9 +33309,47 @@ async function readCgroup(file) {
|
|
|
33308
33309
|
return null;
|
|
33309
33310
|
}
|
|
33310
33311
|
}
|
|
33312
|
+
function parseKv(text) {
|
|
33313
|
+
const map = /* @__PURE__ */ new Map();
|
|
33314
|
+
if (!text) return map;
|
|
33315
|
+
for (const line of text.split("\n")) {
|
|
33316
|
+
const [k, v] = line.trim().split(/\s+/);
|
|
33317
|
+
if (k && v !== void 0) {
|
|
33318
|
+
const n = Number(v);
|
|
33319
|
+
if (Number.isFinite(n)) map.set(k, n);
|
|
33320
|
+
}
|
|
33321
|
+
}
|
|
33322
|
+
return map;
|
|
33323
|
+
}
|
|
33324
|
+
function parsePressureSome(text) {
|
|
33325
|
+
if (!text) return void 0;
|
|
33326
|
+
const some = text.split("\n").find((l) => l.startsWith("some "));
|
|
33327
|
+
const m = some?.match(/avg10=([\d.]+)/);
|
|
33328
|
+
const n = m ? Number(m[1]) : NaN;
|
|
33329
|
+
return Number.isFinite(n) ? clampPct(n) : void 0;
|
|
33330
|
+
}
|
|
33331
|
+
function parseIoStat(text) {
|
|
33332
|
+
if (!text) return null;
|
|
33333
|
+
let rBytes = 0;
|
|
33334
|
+
let wBytes = 0;
|
|
33335
|
+
for (const line of text.split("\n")) {
|
|
33336
|
+
const r = line.match(/\brbytes=(\d+)/);
|
|
33337
|
+
const w = line.match(/\bwbytes=(\d+)/);
|
|
33338
|
+
if (r) rBytes += Number(r[1]);
|
|
33339
|
+
if (w) wBytes += Number(w[1]);
|
|
33340
|
+
}
|
|
33341
|
+
return { rBytes, wBytes };
|
|
33342
|
+
}
|
|
33343
|
+
function parseMaybeMax(text) {
|
|
33344
|
+
if (text === null) return null;
|
|
33345
|
+
if (text === "max") return null;
|
|
33346
|
+
const n = Number(text);
|
|
33347
|
+
return Number.isFinite(n) ? n : null;
|
|
33348
|
+
}
|
|
33311
33349
|
function createWorkerMetricsSampler(diskPath) {
|
|
33312
33350
|
const cgroupV2 = existsSync4(`${CGROUP}/cpu.stat`) && existsSync4(`${CGROUP}/memory.current`);
|
|
33313
|
-
let
|
|
33351
|
+
let cgPrev = null;
|
|
33352
|
+
let osPrev = null;
|
|
33314
33353
|
async function cgroupCpuCount() {
|
|
33315
33354
|
const raw = await readCgroup("cpu.max");
|
|
33316
33355
|
if (raw) {
|
|
@@ -33322,22 +33361,6 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33322
33361
|
}
|
|
33323
33362
|
return cpus().length;
|
|
33324
33363
|
}
|
|
33325
|
-
async function cgroupCpuPct(cpuCount) {
|
|
33326
|
-
const stat2 = await readCgroup("cpu.stat");
|
|
33327
|
-
const m = stat2?.match(/usage_usec\s+(\d+)/);
|
|
33328
|
-
const usageUsec = m ? Number(m[1]) : NaN;
|
|
33329
|
-
const now = Date.now();
|
|
33330
|
-
if (!Number.isFinite(usageUsec)) return 0;
|
|
33331
|
-
if (!prev) {
|
|
33332
|
-
prev = { busy: usageUsec, ref: now };
|
|
33333
|
-
return 0;
|
|
33334
|
-
}
|
|
33335
|
-
const dUsage = usageUsec - prev.busy;
|
|
33336
|
-
const dWall = (now - prev.ref) * 1e3;
|
|
33337
|
-
prev = { busy: usageUsec, ref: now };
|
|
33338
|
-
if (dWall <= 0) return 0;
|
|
33339
|
-
return clampPct(dUsage / (dWall * cpuCount) * 100);
|
|
33340
|
-
}
|
|
33341
33364
|
function osCpuPct() {
|
|
33342
33365
|
let busy = 0;
|
|
33343
33366
|
let total = 0;
|
|
@@ -33346,13 +33369,13 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33346
33369
|
busy += t.user + t.nice + t.sys + t.irq;
|
|
33347
33370
|
total += t.user + t.nice + t.sys + t.irq + t.idle;
|
|
33348
33371
|
}
|
|
33349
|
-
if (!
|
|
33350
|
-
|
|
33372
|
+
if (!osPrev) {
|
|
33373
|
+
osPrev = { busy, total };
|
|
33351
33374
|
return 0;
|
|
33352
33375
|
}
|
|
33353
|
-
const dBusy = busy -
|
|
33354
|
-
const dTotal = total -
|
|
33355
|
-
|
|
33376
|
+
const dBusy = busy - osPrev.busy;
|
|
33377
|
+
const dTotal = total - osPrev.total;
|
|
33378
|
+
osPrev = { busy, total };
|
|
33356
33379
|
if (dTotal <= 0) return 0;
|
|
33357
33380
|
return clampPct(dBusy / dTotal * 100);
|
|
33358
33381
|
}
|
|
@@ -33366,9 +33389,74 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33366
33389
|
return { usedGb: 0, totalGb: 0 };
|
|
33367
33390
|
}
|
|
33368
33391
|
}
|
|
33392
|
+
async function cgroupExtended(cpuCount, now) {
|
|
33393
|
+
const [cpuStatRaw, memStatRaw, ioStatRaw, cpuPsi, memPsi, ioPsi, swapCurRaw, swapMaxRaw, memEventsRaw, pidsCurRaw, pidsMaxRaw] = await Promise.all([
|
|
33394
|
+
readCgroup("cpu.stat"),
|
|
33395
|
+
readCgroup("memory.stat"),
|
|
33396
|
+
readCgroup("io.stat"),
|
|
33397
|
+
readCgroup("cpu.pressure"),
|
|
33398
|
+
readCgroup("memory.pressure"),
|
|
33399
|
+
readCgroup("io.pressure"),
|
|
33400
|
+
readCgroup("memory.swap.current"),
|
|
33401
|
+
readCgroup("memory.swap.max"),
|
|
33402
|
+
readCgroup("memory.events"),
|
|
33403
|
+
readCgroup("pids.current"),
|
|
33404
|
+
readCgroup("pids.max")
|
|
33405
|
+
]);
|
|
33406
|
+
const cpuStat = parseKv(cpuStatRaw);
|
|
33407
|
+
const usageUsec = cpuStat.get("usage_usec") ?? NaN;
|
|
33408
|
+
const nrThrottled = cpuStat.get("nr_throttled") ?? 0;
|
|
33409
|
+
const nrPeriods = cpuStat.get("nr_periods") ?? 0;
|
|
33410
|
+
const io = parseIoStat(ioStatRaw);
|
|
33411
|
+
const extra = {};
|
|
33412
|
+
extra.cpuPressurePct = parsePressureSome(cpuPsi);
|
|
33413
|
+
extra.memPressurePct = parsePressureSome(memPsi);
|
|
33414
|
+
extra.ioPressurePct = parsePressureSome(ioPsi);
|
|
33415
|
+
const memStat = parseKv(memStatRaw);
|
|
33416
|
+
if (memStat.has("anon")) extra.memAnonMb = Math.round(memStat.get("anon") / MB);
|
|
33417
|
+
if (memStat.has("file")) extra.memCacheMb = Math.round(memStat.get("file") / MB);
|
|
33418
|
+
if (swapCurRaw !== null) extra.swapUsedMb = Math.round(Number(swapCurRaw) / MB);
|
|
33419
|
+
if (swapMaxRaw !== null) {
|
|
33420
|
+
const max = parseMaybeMax(swapMaxRaw);
|
|
33421
|
+
extra.swapTotalMb = max === null ? null : Math.round(max / MB);
|
|
33422
|
+
}
|
|
33423
|
+
const memEvents = parseKv(memEventsRaw);
|
|
33424
|
+
if (memEvents.has("oom_kill")) extra.oomKills = memEvents.get("oom_kill");
|
|
33425
|
+
if (pidsCurRaw !== null) {
|
|
33426
|
+
const n = Number(pidsCurRaw);
|
|
33427
|
+
if (Number.isFinite(n)) extra.pidsCurrent = n;
|
|
33428
|
+
}
|
|
33429
|
+
if (pidsMaxRaw !== null) extra.pidsMax = parseMaybeMax(pidsMaxRaw);
|
|
33430
|
+
let cpuPct = 0;
|
|
33431
|
+
if (Number.isFinite(usageUsec)) {
|
|
33432
|
+
if (cgPrev) {
|
|
33433
|
+
const dWallUsec = (now - cgPrev.wallMs) * 1e3;
|
|
33434
|
+
if (dWallUsec > 0) cpuPct = clampPct((usageUsec - cgPrev.usageUsec) / (dWallUsec * cpuCount) * 100);
|
|
33435
|
+
const dPeriods = nrPeriods - cgPrev.nrPeriods;
|
|
33436
|
+
if (dPeriods > 0) extra.cpuThrottledPct = clampPct((nrThrottled - cgPrev.nrThrottled) / dPeriods * 100);
|
|
33437
|
+
if (io) {
|
|
33438
|
+
const dSec = (now - cgPrev.wallMs) / 1e3;
|
|
33439
|
+
if (dSec > 0) {
|
|
33440
|
+
extra.diskReadMbps = round1((io.rBytes - cgPrev.ioR) / MB / dSec);
|
|
33441
|
+
extra.diskWriteMbps = round1((io.wBytes - cgPrev.ioW) / MB / dSec);
|
|
33442
|
+
}
|
|
33443
|
+
}
|
|
33444
|
+
}
|
|
33445
|
+
cgPrev = {
|
|
33446
|
+
usageUsec,
|
|
33447
|
+
nrThrottled,
|
|
33448
|
+
nrPeriods,
|
|
33449
|
+
ioR: io?.rBytes ?? 0,
|
|
33450
|
+
ioW: io?.wBytes ?? 0,
|
|
33451
|
+
wallMs: now
|
|
33452
|
+
};
|
|
33453
|
+
}
|
|
33454
|
+
return { cpuPct, extra };
|
|
33455
|
+
}
|
|
33369
33456
|
return {
|
|
33370
33457
|
async sample() {
|
|
33371
|
-
const
|
|
33458
|
+
const now = Date.now();
|
|
33459
|
+
const at = new Date(now).toISOString();
|
|
33372
33460
|
const { usedGb: diskUsedGb, totalGb: diskTotalGb } = await disk();
|
|
33373
33461
|
const base = { platform: platform(), arch: arch(), diskUsedGb, diskTotalGb, at };
|
|
33374
33462
|
if (cgroupV2) {
|
|
@@ -33377,14 +33465,15 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33377
33465
|
const memTotalBytes = memMaxRaw && memMaxRaw !== "max" ? Number(memMaxRaw) : totalmem();
|
|
33378
33466
|
const memUsedBytes = memCurRaw ? Number(memCurRaw) : totalmem() - freemem();
|
|
33379
33467
|
const cpuCount = await cgroupCpuCount();
|
|
33380
|
-
const cpuPct = await
|
|
33468
|
+
const { cpuPct, extra } = await cgroupExtended(cpuCount, now);
|
|
33381
33469
|
return {
|
|
33382
33470
|
...base,
|
|
33383
33471
|
source: "cgroup",
|
|
33384
33472
|
cpuCount,
|
|
33385
33473
|
cpuPct,
|
|
33386
33474
|
memUsedMb: Math.round(memUsedBytes / MB),
|
|
33387
|
-
memTotalMb: Math.round(memTotalBytes / MB)
|
|
33475
|
+
memTotalMb: Math.round(memTotalBytes / MB),
|
|
33476
|
+
...extra
|
|
33388
33477
|
};
|
|
33389
33478
|
}
|
|
33390
33479
|
const total = totalmem();
|
|
@@ -36413,9 +36502,11 @@ async function listExtras() {
|
|
|
36413
36502
|
} catch {
|
|
36414
36503
|
return [];
|
|
36415
36504
|
}
|
|
36416
|
-
const catalogPkgs = new Set(
|
|
36417
|
-
|
|
36418
|
-
|
|
36505
|
+
const catalogPkgs = new Set(WORKER_TOOL_BUNDLED_GLOBALS);
|
|
36506
|
+
for (const t of WORKER_TOOL_CATALOG) {
|
|
36507
|
+
catalogPkgs.add(t.id);
|
|
36508
|
+
if (t.installPackage) catalogPkgs.add(t.installPackage);
|
|
36509
|
+
}
|
|
36419
36510
|
return Object.entries(deps).filter(([name]) => !catalogPkgs.has(name)).map(([name, info]) => ({
|
|
36420
36511
|
id: name,
|
|
36421
36512
|
label: name,
|
|
@@ -36453,6 +36544,9 @@ function resolvePackage(name, op) {
|
|
|
36453
36544
|
if (WORKER_TOOL_PREREQUISITE_IDS.includes(name)) {
|
|
36454
36545
|
return { error: `"${name}" is a prerequisite and cannot be ${op}ed from here.` };
|
|
36455
36546
|
}
|
|
36547
|
+
if (WORKER_TOOL_BUNDLED_GLOBALS.includes(name)) {
|
|
36548
|
+
return { error: `"${name}" ships with Node and cannot be ${op}ed from here.` };
|
|
36549
|
+
}
|
|
36456
36550
|
if (!NPM_NAME.test(name)) return { error: `Invalid package name: "${name}".` };
|
|
36457
36551
|
return { pkg: name };
|
|
36458
36552
|
}
|