Lumi/plugins/lumi_ai/backend/diagnostics.js
2026-06-11 06:35:43 +02:00

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 };