59 lines
2.4 KiB
JavaScript
59 lines
2.4 KiB
JavaScript
const fs = require("fs");
|
|
const path = require("path");
|
|
const AdmZip = require("adm-zip");
|
|
const { resolveData, ensureDataDirs } = require("./paths");
|
|
|
|
function redact(value) {
|
|
if (Array.isArray(value)) return value.map(redact);
|
|
if (!value || typeof value !== "object") return value;
|
|
const output = {};
|
|
for (const [key, item] of Object.entries(value)) {
|
|
output[key] = /token|secret|password|cookie|authorization|session/i.test(key) ? "[REDACTED]" : redact(item);
|
|
}
|
|
return output;
|
|
}
|
|
function createDiagnostic(input) {
|
|
return redact({
|
|
timestamp: new Date().toISOString(),
|
|
severity: "error",
|
|
can_retry: true,
|
|
requires_admin_action: true,
|
|
should_auto_resume: false,
|
|
platform: process.platform,
|
|
...input
|
|
});
|
|
}
|
|
function persistDiagnostic(input) {
|
|
ensureDataDirs();
|
|
const diagnostic = createDiagnostic(input);
|
|
fs.writeFileSync(resolveData("diagnostics", "latest_runtime_diagnostic.json"), `${JSON.stringify(diagnostic, null, 2)}\n`);
|
|
fs.appendFileSync(resolveData("diagnostics", "runtime_diagnostics.jsonl"), `${JSON.stringify(diagnostic)}\n`);
|
|
return diagnostic;
|
|
}
|
|
function getLatestDiagnostic() {
|
|
try { return JSON.parse(fs.readFileSync(resolveData("diagnostics", "latest_runtime_diagnostic.json"), "utf8")); }
|
|
catch { return null; }
|
|
}
|
|
function createDiagnosticsBundle({ config, runtimeState, manifest, metrics }) {
|
|
ensureDataDirs();
|
|
const destination = resolveData("diagnostics", `lumi-ai-diagnostics-${Date.now()}.zip`);
|
|
const zip = new AdmZip();
|
|
const addJson = (name, value) => zip.addFile(name, Buffer.from(`${JSON.stringify(redact(value), null, 2)}\n`));
|
|
addJson("config.json", config);
|
|
addJson("runtime_state.json", runtimeState);
|
|
addJson("latest_runtime_diagnostic.json", getLatestDiagnostic());
|
|
addJson("runtime_manifest.json", manifest);
|
|
addJson("metrics_summary.json", metrics);
|
|
for (const name of ["runtime-selftest.log"]) {
|
|
const file = resolveData("logs", name);
|
|
if (fs.existsSync(file)) zip.addLocalFile(file, "logs");
|
|
}
|
|
const logs = fs.readdirSync(resolveData("logs")).filter((name) => name.startsWith("runtime-")).sort().slice(-2);
|
|
for (const name of logs) zip.addLocalFile(resolveData("logs", name), "logs");
|
|
zip.writeZip(destination);
|
|
return destination;
|
|
}
|
|
function tail(value, length = 4000) { return String(value || "").slice(-length); }
|
|
|
|
module.exports = { redact, createDiagnostic, persistDiagnostic, getLatestDiagnostic, createDiagnosticsBundle, tail };
|