style: format health/status files

This commit is contained in:
Peter Steinberger
2026-01-17 01:25:10 +00:00
parent fa2b92bb00
commit e16ce1a0a1
5 changed files with 35 additions and 41 deletions

View File

@@ -13,10 +13,7 @@ import {
resolveHeartbeatSummaryForAgent, resolveHeartbeatSummaryForAgent,
} from "../infra/heartbeat-runner.js"; } from "../infra/heartbeat-runner.js";
import type { RuntimeEnv } from "../runtime.js"; import type { RuntimeEnv } from "../runtime.js";
import { import { buildChannelAccountBindings, resolvePreferredAccountId } from "../routing/bindings.js";
buildChannelAccountBindings,
resolvePreferredAccountId,
} from "../routing/bindings.js";
import { normalizeAgentId } from "../routing/session-key.js"; import { normalizeAgentId } from "../routing/session-key.js";
import { theme } from "../terminal/theme.js"; import { theme } from "../terminal/theme.js";
@@ -158,10 +155,7 @@ const isAccountEnabled = (account: unknown): boolean => {
const asRecord = (value: unknown): Record<string, unknown> | null => const asRecord = (value: unknown): Record<string, unknown> | null =>
value && typeof value === "object" ? (value as Record<string, unknown>) : null; value && typeof value === "object" ? (value as Record<string, unknown>) : null;
const formatProbeLine = ( const formatProbeLine = (probe: unknown, opts: { botUsernames?: string[] } = {}): string | null => {
probe: unknown,
opts: { botUsernames?: string[] } = {},
): string | null => {
const record = asRecord(probe); const record = asRecord(probe);
if (!record) return null; if (!record) return null;
const ok = typeof record.ok === "boolean" ? record.ok : undefined; const ok = typeof record.ok === "boolean" ? record.ok : undefined;
@@ -203,7 +197,8 @@ const formatAccountProbeTiming = (summary: ChannelAccountHealthSummary): string
const accountId = summary.accountId || "default"; const accountId = summary.accountId || "default";
const botRecord = asRecord(probe.bot); const botRecord = asRecord(probe.bot);
const botUsername = botRecord && typeof botRecord.username === "string" ? botRecord.username : null; const botUsername =
botRecord && typeof botRecord.username === "string" ? botRecord.username : null;
const handle = botUsername ? `@${botUsername}` : accountId; const handle = botUsername ? `@${botUsername}` : accountId;
const timing = elapsedMs != null ? `${elapsedMs}ms` : "ok"; const timing = elapsedMs != null ? `${elapsedMs}ms` : "ok";
@@ -268,11 +263,9 @@ export const formatHealthChannelLines = (
const listSummaries = const listSummaries =
accountMode === "all" accountMode === "all"
? Object.values(accountSummaries) ? Object.values(accountSummaries)
: filteredSummaries ?? (channelSummary.accounts ? Object.values(accountSummaries) : []); : (filteredSummaries ?? (channelSummary.accounts ? Object.values(accountSummaries) : []));
const baseSummary = const baseSummary =
filteredSummaries && filteredSummaries.length > 0 filteredSummaries && filteredSummaries.length > 0 ? filteredSummaries[0] : channelSummary;
? filteredSummaries[0]
: channelSummary;
const botUsernames = listSummaries const botUsernames = listSummaries
? listSummaries ? listSummaries
.map((account) => { .map((account) => {
@@ -285,8 +278,7 @@ export const formatHealthChannelLines = (
const linked = typeof baseSummary.linked === "boolean" ? baseSummary.linked : null; const linked = typeof baseSummary.linked === "boolean" ? baseSummary.linked : null;
if (linked !== null) { if (linked !== null) {
if (linked) { if (linked) {
const authAgeMs = const authAgeMs = typeof baseSummary.authAgeMs === "number" ? baseSummary.authAgeMs : null;
typeof baseSummary.authAgeMs === "number" ? baseSummary.authAgeMs : null;
const authLabel = authAgeMs != null ? ` (auth age ${Math.round(authAgeMs / 60000)}m)` : ""; const authLabel = authAgeMs != null ? ` (auth age ${Math.round(authAgeMs / 60000)}m)` : "";
lines.push(`${label}: linked${authLabel}`); lines.push(`${label}: linked${authLabel}`);
} else { } else {
@@ -431,7 +423,8 @@ export async function getHealthSnapshot(params?: {
} }
} }
const probeRecord = probe && typeof probe === "object" ? (probe as Record<string, unknown>) : null; const probeRecord =
probe && typeof probe === "object" ? (probe as Record<string, unknown>) : null;
const bot = const bot =
probeRecord && typeof probeRecord.bot === "object" probeRecord && typeof probeRecord.bot === "object"
? (probeRecord.bot as { username?: string | null }) ? (probeRecord.bot as { username?: string | null })
@@ -637,14 +630,15 @@ export async function healthCommand(
} }
return byChannel; return byChannel;
})(); })();
const channelLines = Object.keys(accountIdsByChannel).length > 0 const channelLines =
? formatHealthChannelLines(summary, { Object.keys(accountIdsByChannel).length > 0
accountMode: opts.verbose ? "all" : "default", ? formatHealthChannelLines(summary, {
accountIdsByChannel, accountMode: opts.verbose ? "all" : "default",
}) accountIdsByChannel,
: formatHealthChannelLines(summary, { })
accountMode: opts.verbose ? "all" : "default", : formatHealthChannelLines(summary, {
}); accountMode: opts.verbose ? "all" : "default",
});
for (const line of channelLines) { for (const line of channelLines) {
runtime.log(styleHealthChannelLine(line)); runtime.log(styleHealthChannelLine(line));
} }
@@ -690,7 +684,9 @@ export async function healthCommand(
runtime.log(info(`Heartbeat interval: ${heartbeatParts.join(", ")}`)); runtime.log(info(`Heartbeat interval: ${heartbeatParts.join(", ")}`));
} }
if (displayAgents.length === 0) { if (displayAgents.length === 0) {
runtime.log(info(`Session store: ${summary.sessions.path} (${summary.sessions.count} entries)`)); runtime.log(
info(`Session store: ${summary.sessions.path} (${summary.sessions.count} entries)`),
);
if (summary.sessions.recent.length > 0) { if (summary.sessions.recent.length > 0) {
for (const r of summary.sessions.recent) { for (const r of summary.sessions.recent) {
runtime.log( runtime.log(

View File

@@ -226,7 +226,7 @@ export async function statusCommand(
const storeLabel = const storeLabel =
summary.sessions.paths.length > 1 summary.sessions.paths.length > 1
? `${summary.sessions.paths.length} stores` ? `${summary.sessions.paths.length} stores`
: summary.sessions.paths[0] ?? "unknown"; : (summary.sessions.paths[0] ?? "unknown");
const overviewRows = [ const overviewRows = [
{ Item: "Dashboard", Value: dashboard }, { Item: "Dashboard", Value: dashboard },

View File

@@ -385,8 +385,9 @@ describe("statusCommand", () => {
const payload = JSON.parse((runtime.log as vi.Mock).mock.calls.at(-1)?.[0]); const payload = JSON.parse((runtime.log as vi.Mock).mock.calls.at(-1)?.[0]);
expect(payload.sessions.count).toBe(2); expect(payload.sessions.count).toBe(2);
expect(payload.sessions.paths.length).toBe(2); expect(payload.sessions.paths.length).toBe(2);
expect(payload.sessions.recent.some((sess: { key?: string }) => sess.key === "agent:ops:main")) expect(
.toBe(true); payload.sessions.recent.some((sess: { key?: string }) => sess.key === "agent:ops:main"),
).toBe(true);
if (originalAgents) mocks.listAgentsForGateway.mockImplementation(originalAgents); if (originalAgents) mocks.listAgentsForGateway.mockImplementation(originalAgents);
if (originalResolveStorePath) if (originalResolveStorePath)

View File

@@ -463,10 +463,7 @@ function isObjectSchema(schema: JsonSchemaObject): boolean {
} }
function mergeObjectSchema(base: JsonSchemaObject, extension: JsonSchemaObject): JsonSchemaObject { function mergeObjectSchema(base: JsonSchemaObject, extension: JsonSchemaObject): JsonSchemaObject {
const mergedRequired = new Set<string>([ const mergedRequired = new Set<string>([...(base.required ?? []), ...(extension.required ?? [])]);
...(base.required ?? []),
...(extension.required ?? []),
]);
const merged: JsonSchemaObject = { const merged: JsonSchemaObject = {
...base, ...base,
...extension, ...extension,
@@ -598,12 +595,17 @@ function applyPluginSchemas(schema: ConfigSchema, plugins: PluginUiMetadata[]):
for (const plugin of plugins) { for (const plugin of plugins) {
if (!plugin.configSchema) continue; if (!plugin.configSchema) continue;
const entrySchema = entryBase ? cloneSchema(entryBase) : ({ type: "object" } as JsonSchemaObject); const entrySchema = entryBase
? cloneSchema(entryBase)
: ({ type: "object" } as JsonSchemaObject);
const entryObject = asSchemaObject(entrySchema) ?? ({ type: "object" } as JsonSchemaObject); const entryObject = asSchemaObject(entrySchema) ?? ({ type: "object" } as JsonSchemaObject);
const baseConfigSchema = asSchemaObject(entryObject.properties?.config); const baseConfigSchema = asSchemaObject(entryObject.properties?.config);
const pluginSchema = asSchemaObject(plugin.configSchema); const pluginSchema = asSchemaObject(plugin.configSchema);
const nextConfigSchema = const nextConfigSchema =
baseConfigSchema && pluginSchema && isObjectSchema(baseConfigSchema) && isObjectSchema(pluginSchema) baseConfigSchema &&
pluginSchema &&
isObjectSchema(baseConfigSchema) &&
isObjectSchema(pluginSchema)
? mergeObjectSchema(baseConfigSchema, pluginSchema) ? mergeObjectSchema(baseConfigSchema, pluginSchema)
: cloneSchema(plugin.configSchema); : cloneSchema(plugin.configSchema);
@@ -683,10 +685,7 @@ export function buildConfigSchema(params?: {
const mergedHints = applySensitiveHints( const mergedHints = applySensitiveHints(
applyChannelHints(applyPluginHints(base.uiHints, plugins), channels), applyChannelHints(applyPluginHints(base.uiHints, plugins), channels),
); );
const mergedSchema = applyChannelSchemas( const mergedSchema = applyChannelSchemas(applyPluginSchemas(base.schema, plugins), channels);
applyPluginSchemas(base.schema, plugins),
channels,
);
return { return {
...base, ...base,
schema: mergedSchema, schema: mergedSchema,

View File

@@ -56,9 +56,7 @@ function resolveAccountConfig(
const direct = accounts[accountId] as TelegramAccountConfig | undefined; const direct = accounts[accountId] as TelegramAccountConfig | undefined;
if (direct) return direct; if (direct) return direct;
const normalized = normalizeAccountId(accountId); const normalized = normalizeAccountId(accountId);
const matchKey = Object.keys(accounts).find( const matchKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized);
(key) => normalizeAccountId(key) === normalized,
);
return matchKey ? (accounts[matchKey] as TelegramAccountConfig | undefined) : undefined; return matchKey ? (accounts[matchKey] as TelegramAccountConfig | undefined) : undefined;
} }