小橘 d1a2ee876a fix: hermesRun command and tester verdict via llmExtract
- Fix hermes invocation: 'hermes -q' → 'hermes chat -q' with proper flags
- Replace fragile string.includes('PASS') with llmExtract judge
  (previous false positive: matched '--pass-session-id' in usage text)

小橘 🍊(NEKO Team)
2026-04-23 12:20:11 +00:00

132 lines
3.2 KiB
JavaScript

import { execSync } from "node:child_process";
import { diskUsageMounts } from "./schema.ts";
const DF_CMD =
"df -B1 --output=source,target,fstype,size,used,avail,pcent";
/** fstype-based exclusions to avoid pseudo / volatile filesystem noise */
const EXCLUDED_FSTYPES = new Set([
"tmpfs",
"devtmpfs",
"proc",
"sysfs",
"cgroup2",
"cgroup",
]);
function round2(n) {
return Math.round(n * 100) / 100;
}
function parseUIntField(s) {
if (s === "-") return null;
const n = Number.parseInt(String(s), 10);
if (!Number.isFinite(n) || n < 0) return null;
return n;
}
function parsePcent(tok) {
if (!tok || typeof tok !== "string") return null;
const t = tok.trim();
if (!/^[\d.]+%$/.test(t)) return null;
const raw = Number.parseFloat(t.replace("%", ""));
return Number.isFinite(raw) ? round2(raw) : null;
}
/**
* Parse one `df --output=source,target,fstype,size,used,avail,pcent` data line.
* Mount may contain spaces; last five logical columns are fixed.
*/
function parseDfLine(line) {
const parts = line.trim().split(/\s+/);
if (parts.length < 7) return null;
const pcentTok = parts[parts.length - 1];
const availBytes = parseUIntField(parts[parts.length - 2]);
const usedBytes = parseUIntField(parts[parts.length - 3]);
const totalBytes = parseUIntField(parts[parts.length - 4]);
const fstype = parts[parts.length - 5];
const device = parts[0];
const mount = parts.slice(1, parts.length - 5).join(" ");
if (!device || !mount || !fstype) return null;
if (totalBytes === null || usedBytes === null || availBytes === null)
return null;
const pcentFromDf = parsePcent(pcentTok);
const computed =
totalBytes > 0 ? round2((usedBytes / totalBytes) * 100) : 0;
let usedPercent = computed;
if (pcentFromDf !== null) {
const diff = Math.abs(computed - pcentFromDf);
usedPercent = diff > 1 ? computed : pcentFromDf;
}
return {
device,
mount,
fstype,
totalBytes,
usedBytes,
availBytes,
usedPercent,
};
}
function parseDfOutput(text) {
const rows = [];
const lines = text.split("\n");
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed) continue;
if (/^Filesystem\s+/.test(trimmed) || trimmed.startsWith("Filesystem"))
continue;
const row = parseDfLine(line);
if (row && !EXCLUDED_FSTYPES.has(row.fstype)) rows.push(row);
}
return rows;
}
export async function compute(db, _peers) {
const ts = Date.now();
let mounts = [];
try {
const out = execSync(DF_CMD, {
encoding: "utf-8",
maxBuffer: 10 * 1024 * 1024,
});
mounts = parseDfOutput(out);
} catch {
mounts = [];
}
if (mounts.length > 0) {
await db.insert(diskUsageMounts).values(
mounts.map((m) => ({
ts,
device: m.device,
mount: m.mount,
fstype: m.fstype,
totalBytes: m.totalBytes,
usedBytes: m.usedBytes,
availBytes: m.availBytes,
usedPercent: m.usedPercent,
})),
);
}
return {
ts,
mounts: mounts.map((m) => ({
device: m.device,
mount: m.mount,
fstype: m.fstype,
totalBytes: m.totalBytes,
usedBytes: m.usedBytes,
availBytes: m.availBytes,
usedPercent: m.usedPercent,
})),
};
}