docs: document status overview helpers

This commit is contained in:
Peter Steinberger
2026-06-04 13:07:17 -04:00
parent abb09b93cb
commit ea6d3232ca
4 changed files with 30 additions and 0 deletions
+6
View File
@@ -1,3 +1,6 @@
// Builds overview table rows for `openclaw status` and `openclaw status --all`.
// The row builders combine scan surfaces with health/session summaries while keeping rendering elsewhere.
import { formatCliCommand } from "../cli/command-format.js";
import type { HeartbeatEventPayload } from "../infra/heartbeat-events.js";
import type { PluginCompatibilityNotice } from "../plugins/status.js";
@@ -34,6 +37,7 @@ function readModelPricingHealth(params: {
if (params.health?.modelPricing) {
return params.health.modelPricing;
}
// Fast status can receive model pricing through the gateway probe before deep health is requested.
const probeHealth = params.surface.gatewayProbe?.health;
if (!probeHealth || typeof probeHealth !== "object") {
return undefined;
@@ -66,6 +70,7 @@ function buildModelPricingOverviewValue(params: {
return params.warn(`warning · optional pricing refresh degraded${detail}`);
}
/** Builds the default `openclaw status` overview rows from scan, health, memory, and session inputs. */
export function buildStatusCommandOverviewRows(
params: {
opts: {
@@ -181,6 +186,7 @@ export function buildStatusCommandOverviewRows(
});
}
/** Builds the expanded status-all overview rows, including config and security hints. */
export function buildStatusAllOverviewRows(params: {
surface: StatusOverviewSurface;
osLabel: string;
+7
View File
@@ -1,3 +1,6 @@
// Normalized status overview surface shared by text and JSON status outputs.
// It collects gateway/update/service fields into one shape before row or payload builders run.
import type { OpenClawConfig } from "../config/types.js";
import type { UpdateCheckResult } from "../infra/update-check.js";
import {
@@ -66,6 +69,7 @@ export type StatusOverviewSurface = {
nodeOnlyGateway?: NodeOnlyGatewayInfo | null;
};
/** Converts the full status scan result into the shared overview surface. */
export function buildStatusOverviewSurfaceFromScan(params: {
scan: Pick<
StatusScanResult,
@@ -107,6 +111,7 @@ export function buildStatusOverviewSurfaceFromScan(params: {
};
}
/** Converts the lighter status-all overview scan into the shared overview surface. */
export function buildStatusOverviewSurfaceFromOverview(params: {
overview: Pick<
StatusScanOverviewResult,
@@ -136,6 +141,7 @@ export function buildStatusOverviewSurfaceFromOverview(params: {
};
}
/** Builds overview rows from an already-normalized surface. */
export function buildStatusOverviewRowsFromSurface(params: {
surface: StatusOverviewSurface;
prefixRows?: StatusOverviewRow[];
@@ -189,6 +195,7 @@ export function buildStatusOverviewRowsFromSurface(params: {
});
}
/** Builds the gateway JSON payload from the gateway portion of an overview surface. */
export function buildStatusGatewayJsonPayloadFromSurface(params: {
surface: Pick<
StatusOverviewSurface,
+10
View File
@@ -1,3 +1,6 @@
// Small value formatters for status overview rows.
// These helpers keep terse row text consistent between compact and full status reports.
type AgentStatusLike = {
bootstrapPendingCount: number;
totalSessions: number;
@@ -26,11 +29,13 @@ function countActiveStatusAgents(params: {
activeThresholdMs?: number;
}) {
const activeThresholdMs = params.activeThresholdMs ?? 10 * 60_000;
// "Active" means a recent session update, not merely a configured agent.
return params.agentStatus.agents.filter(
(agent) => agent.lastActiveAgeMs != null && agent.lastActiveAgeMs <= activeThresholdMs,
).length;
}
/** Formats the status-all agents overview cell. */
export function buildStatusAllAgentsValue(params: {
agentStatus: AgentStatusLike;
activeThresholdMs?: number;
@@ -39,16 +44,19 @@ export function buildStatusAllAgentsValue(params: {
return `${params.agentStatus.agents.length} total · ${params.agentStatus.bootstrapPendingCount} bootstrapping · ${activeAgents} active · ${params.agentStatus.totalSessions} sessions`;
}
/** Formats the secrets diagnostics count for overview output. */
export function buildStatusSecretsValue(count: number) {
return count > 0 ? `${count} diagnostic${count === 1 ? "" : "s"}` : "none";
}
/** Formats queued system-event count for overview output. */
export function buildStatusEventsValue(params: { queuedSystemEvents: string[] }) {
return params.queuedSystemEvents.length > 0
? `${params.queuedSystemEvents.length} queued`
: "none";
}
/** Formats whether deep probe data was collected. */
export function buildStatusProbesValue(params: {
health?: unknown;
ok: (value: string) => string;
@@ -57,6 +65,7 @@ export function buildStatusProbesValue(params: {
return params.health ? params.ok("enabled") : params.muted("skipped (use --deep)");
}
/** Formats plugin compatibility notices as a compact count by notice and plugin. */
export function buildStatusPluginCompatibilityValue(params: {
notices: PluginCompatibilityNoticeLike[];
ok: (value: string) => string;
@@ -73,6 +82,7 @@ export function buildStatusPluginCompatibilityValue(params: {
);
}
/** Formats active session count, default model/context, and backing store summary. */
export function buildStatusSessionsOverviewValue(params: {
sessions: SummarySessionsLike;
formatKTokens: (value: number) => string;
+7
View File
@@ -1,3 +1,6 @@
// Formats update-restart sentinel state for status reports.
// The sentinel is written by update flows; status only turns it into operator-facing hints.
import type { RestartSentinelPayload } from "../infra/restart-sentinel.js";
import {
CONTROL_PLANE_UPDATE_HANDOFF_STARTED_REASON,
@@ -16,6 +19,7 @@ function readAfterVersion(payload: RestartSentinelPayload): string | null {
return typeof version === "string" && version.trim().length > 0 ? version : null;
}
/** Returns the one-line update restart status value, or null when no update sentinel applies. */
export function formatUpdateRestartStatusValue(
payload: RestartSentinelPayload | null | undefined,
opts: {
@@ -47,9 +51,11 @@ export function formatUpdateRestartStatusValue(
if (payload.status === "skipped") {
if (reason === CONTROL_PLANE_UPDATE_HANDOFF_STARTED_REASON) {
// Handoff already started in the control plane; gateway restart should not be duplicated.
return warn(`handoff running · gateway restart pending · run openclaw update status${age}`);
}
if (reason === CONTROL_PLANE_UPDATE_RESTART_HEALTH_PENDING_REASON) {
// Restart completed enough to defer, but health proof still needs a deep gateway check.
return warn(`restart pending health verification · run openclaw gateway status --deep${age}`);
}
return muted(`skipped · ${reason ?? "restart skipped"}${age}`);
@@ -59,6 +65,7 @@ export function formatUpdateRestartStatusValue(
return ok(`verified${version ? ` · gateway ${version}` : ""}${age}`);
}
/** Returns follow-up action lines for update restart failures or pending handoffs. */
export function formatUpdateRestartActionLines(
payload: RestartSentinelPayload | null | undefined,
): string[] {