90 lines
2.7 KiB
JavaScript
90 lines
2.7 KiB
JavaScript
const fs = require("fs");
|
|
const path = require("path");
|
|
const { resolveData } = require("./paths");
|
|
|
|
const LOG_FILE = "assistant-panel.log";
|
|
|
|
class AssistantPanelDiagnostics {
|
|
constructor(templatePath) {
|
|
this.templatePath = path.resolve(templatePath);
|
|
this.state = {
|
|
panel_endpoint_status: null,
|
|
panel_html_length: 0,
|
|
panel_html_error: null,
|
|
panel_template_path: this.templatePath,
|
|
missing_locals: [],
|
|
mount_error: null,
|
|
updated_at: null
|
|
};
|
|
}
|
|
|
|
templateCheck(requiredLocals = [], locals = {}) {
|
|
const missing = requiredLocals.filter((key) => locals[key] === undefined || locals[key] === null);
|
|
let error = null;
|
|
try {
|
|
fs.accessSync(this.templatePath, fs.constants.R_OK);
|
|
} catch {
|
|
error = "Assistant panel template is missing or unreadable.";
|
|
}
|
|
this.update({ missing_locals: missing, panel_html_error: error });
|
|
return { valid: !error && missing.length === 0, missing, error };
|
|
}
|
|
|
|
rendered(html) {
|
|
const content = String(html || "");
|
|
const marker = 'data-assistant-panel-id="lumi_ai"';
|
|
const error = !content.trim()
|
|
? "Assistant panel rendered empty HTML."
|
|
: !content.includes(marker)
|
|
? `Assistant panel HTML is missing ${marker}.`
|
|
: null;
|
|
this.update({
|
|
panel_endpoint_status: error ? 500 : 200,
|
|
panel_html_length: content.length,
|
|
panel_html_error: error
|
|
});
|
|
return { valid: !error, error, length: content.length };
|
|
}
|
|
|
|
renderFailed(error) {
|
|
this.update({
|
|
panel_endpoint_status: 500,
|
|
panel_html_length: 0,
|
|
panel_html_error: error?.message || String(error)
|
|
}, "render_failure");
|
|
}
|
|
|
|
frontend(report = {}) {
|
|
this.update({
|
|
panel_endpoint_status: numberOrNull(report.panel_endpoint_status) ?? this.state.panel_endpoint_status,
|
|
panel_html_length: numberOrNull(report.panel_html_length) ?? this.state.panel_html_length,
|
|
panel_html_error: report.panel_html_error || this.state.panel_html_error,
|
|
mount_error: report.mount_error || null
|
|
}, report.mount_error ? "mount_failure" : null);
|
|
}
|
|
|
|
snapshot() {
|
|
return { ...this.state };
|
|
}
|
|
|
|
update(values, event = null) {
|
|
this.state = { ...this.state, ...values, updated_at: new Date().toISOString() };
|
|
if (event || values.panel_html_error || values.mount_error) {
|
|
this.log(event || "diagnostic", values);
|
|
}
|
|
}
|
|
|
|
log(event, details) {
|
|
const target = resolveData("logs", LOG_FILE);
|
|
const line = JSON.stringify({ at: new Date().toISOString(), event, ...details });
|
|
fs.appendFileSync(target, `${line}\n`, "utf8");
|
|
}
|
|
}
|
|
|
|
function numberOrNull(value) {
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) ? parsed : null;
|
|
}
|
|
|
|
module.exports = { AssistantPanelDiagnostics, LOG_FILE };
|