openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
142 lines (141 loc) • 7.23 kB
JavaScript
import { n as asNullableRecord } from "./record-coerce-DHZ4bFlT.js";
import { n as isRich, r as theme, t as colorize } from "./theme-vjDs9tao.js";
import { t as formatChannelStatusState } from "./status-state-DzEZ8yAJ.js";
//#region src/commands/health-format.ts
/** Formatting helpers for `openclaw health` failures and channel summaries. */
const formatKv = (line, rich) => {
const idx = line.indexOf(": ");
if (idx <= 0) return colorize(rich, theme.muted, line);
const key = line.slice(0, idx);
const value = line.slice(idx + 2);
const valueColor = key === "Gateway target" || key === "Config" ? theme.command : key === "Source" ? theme.muted : theme.info;
return `${colorize(rich, theme.muted, `${key}:`)} ${colorize(rich, valueColor, value)}`;
};
/** Formats thrown health errors with rich detail lines when terminal color is enabled. */
function formatHealthCheckFailure(err, opts = {}) {
const rich = opts.rich ?? isRich();
const raw = String(err);
const message = err instanceof Error ? err.message : raw;
if (!rich) return `Health check failed: ${raw}`;
const lines = message.split("\n").map((l) => l.trimEnd()).filter(Boolean);
const detailsIdx = lines.findIndex((l) => l.startsWith("Gateway target: "));
const summaryLines = (detailsIdx >= 0 ? lines.slice(0, detailsIdx) : lines).map((l) => l.trim()).filter(Boolean);
const detailLines = detailsIdx >= 0 ? lines.slice(detailsIdx) : [];
const summary = summaryLines.length > 0 ? summaryLines.join(" ") : message;
const out = [`${colorize(rich, theme.error.bold, "Health check failed")}: ${summary}`];
for (const line of detailLines) out.push(` ${formatKv(line, rich)}`);
return out.join("\n");
}
const formatProbeLine = (probe, opts = {}) => {
const record = asNullableRecord(probe);
if (!record) return null;
const ok = typeof record.ok === "boolean" ? record.ok : void 0;
if (ok === void 0) return null;
const elapsedMs = typeof record.elapsedMs === "number" ? record.elapsedMs : null;
const status = typeof record.status === "number" ? record.status : null;
const error = typeof record.error === "string" ? record.error : null;
const bot = asNullableRecord(record.bot);
const botUsername = bot && typeof bot.username === "string" ? bot.username : null;
const webhook = asNullableRecord(record.webhook);
const webhookUrl = webhook && typeof webhook.url === "string" ? webhook.url : null;
const usernames = /* @__PURE__ */ new Set();
if (botUsername) usernames.add(botUsername);
for (const extra of opts.botUsernames ?? []) if (extra) usernames.add(extra);
if (ok) {
let label = "ok";
if (usernames.size > 0) label += ` (@${Array.from(usernames).join(", @")})`;
if (elapsedMs != null) label += ` (${elapsedMs}ms)`;
if (webhookUrl) label += ` - webhook ${webhookUrl}`;
return label;
}
let label = `failed (${status ?? "unknown"})`;
if (error) label += ` - ${error}`;
return label;
};
const formatAccountProbeTiming = (summary) => {
const probe = asNullableRecord(summary.probe);
if (!probe) return null;
const elapsedMs = typeof probe.elapsedMs === "number" ? Math.round(probe.elapsedMs) : null;
const ok = typeof probe.ok === "boolean" ? probe.ok : null;
if (elapsedMs == null && ok !== true) return null;
const accountId = summary.accountId || "default";
const botRecord = asNullableRecord(probe.bot);
const botUsername = botRecord && typeof botRecord.username === "string" ? botRecord.username : null;
return `${botUsername ? `@${botUsername}` : accountId}:${accountId}:${elapsedMs != null ? `${elapsedMs}ms` : "ok"}`;
};
const isProbeFailure = (summary) => {
const probe = asNullableRecord(summary.probe);
if (!probe) return false;
return (typeof probe.ok === "boolean" ? probe.ok : null) === false;
};
/** Formats one terse health line per channel, optionally including every account. */
const formatHealthChannelLines = (summary, opts = {}) => {
const channels = summary.channels ?? {};
const channelOrder = summary.channelOrder?.length > 0 ? summary.channelOrder : Object.keys(channels);
const accountMode = opts.accountMode ?? "default";
const lines = [];
for (const channelId of channelOrder) {
const channelSummary = channels[channelId];
if (!channelSummary) continue;
const label = summary.channelLabels?.[channelId] ?? channelId;
const accountSummaries = channelSummary.accounts ?? {};
const accountIds = opts.accountIdsByChannel?.[channelId];
const filteredSummaries = accountIds && accountIds.length > 0 ? accountIds.map((accountId) => accountSummaries[accountId]).filter((entry) => Boolean(entry)) : void 0;
const listSummaries = accountMode === "all" ? Object.values(accountSummaries) : filteredSummaries ?? (channelSummary.accounts ? Object.values(accountSummaries) : []);
const baseSummary = filteredSummaries && filteredSummaries.length > 0 ? filteredSummaries[0] : channelSummary;
const botUsernames = listSummaries ? listSummaries.map((account) => {
const probeRecord = asNullableRecord(account.probe);
const bot = probeRecord ? asNullableRecord(probeRecord.bot) : null;
return bot && typeof bot.username === "string" ? bot.username : null;
}).filter((value) => Boolean(value)) : [];
const statusState = typeof baseSummary.statusState === "string" ? baseSummary.statusState : null;
if (statusState) {
if (statusState === "linked") {
const authAgeMs = typeof baseSummary.authAgeMs === "number" ? baseSummary.authAgeMs : null;
const authLabel = authAgeMs != null ? ` (auth age ${Math.round(authAgeMs / 6e4)}m)` : "";
lines.push(`${label}: ${formatChannelStatusState(statusState)}${authLabel}`);
} else lines.push(`${label}: ${formatChannelStatusState(statusState)}`);
continue;
}
const linked = typeof baseSummary.linked === "boolean" ? baseSummary.linked : null;
if (linked !== null) {
if (linked) {
const authAgeMs = typeof baseSummary.authAgeMs === "number" ? baseSummary.authAgeMs : null;
const authLabel = authAgeMs != null ? ` (auth age ${Math.round(authAgeMs / 6e4)}m)` : "";
lines.push(`${label}: linked${authLabel}`);
} else lines.push(`${label}: not linked`);
continue;
}
const configured = typeof baseSummary.configured === "boolean" ? baseSummary.configured : null;
if (configured === false) {
lines.push(`${label}: not configured`);
continue;
}
const accountTimings = accountMode === "all" ? listSummaries.map((account) => formatAccountProbeTiming(account)).filter((value) => Boolean(value)) : [];
const failedSummary = listSummaries.find((summaryLocal) => isProbeFailure(summaryLocal));
if (failedSummary) {
const failureLine = formatProbeLine(failedSummary.probe, { botUsernames });
if (failureLine) {
lines.push(`${label}: ${failureLine}`);
continue;
}
}
if (accountTimings.length > 0) {
lines.push(`${label}: ok (${accountTimings.join(", ")})`);
continue;
}
const probeLine = formatProbeLine(baseSummary.probe, { botUsernames });
if (probeLine) {
lines.push(`${label}: ${probeLine}`);
continue;
}
if (configured === true) {
lines.push(`${label}: configured`);
continue;
}
lines.push(`${label}: unknown`);
}
return lines;
};
//#endregion
export { formatHealthCheckFailure as n, formatHealthChannelLines as t };