mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 11:55:47 -06:00
refactor(status): consolidate scan projections and lazy loaders (#119412)
This commit is contained in:
committed by
GitHub
parent
722dfb3d64
commit
5ffd2dfbc3
@@ -77,27 +77,12 @@ export function buildStatusOverviewSurfaceFromScan(
|
||||
export function buildStatusOverviewSurfaceFromOverview(
|
||||
params: { overview: StatusOverviewInput } & StatusOverviewServices,
|
||||
): StatusOverviewSurface {
|
||||
return {
|
||||
cfg: params.overview.cfg,
|
||||
update: params.overview.update,
|
||||
tailscaleMode: params.overview.tailscaleMode,
|
||||
tailscaleDns: params.overview.tailscaleDns,
|
||||
tailscaleHttpsUrl: params.overview.tailscaleHttpsUrl,
|
||||
...(params.overview.advertisedControlUiLinks
|
||||
? { advertisedControlUiLinks: params.overview.advertisedControlUiLinks }
|
||||
: {}),
|
||||
gatewayMode: params.overview.gatewaySnapshot.gatewayMode,
|
||||
remoteUrlMissing: params.overview.gatewaySnapshot.remoteUrlMissing,
|
||||
gatewayConnection: params.overview.gatewaySnapshot.gatewayConnection,
|
||||
gatewayReachable: params.overview.gatewaySnapshot.gatewayReachable,
|
||||
gatewayProbe: params.overview.gatewaySnapshot.gatewayProbe,
|
||||
gatewayProbeAuth: params.overview.gatewaySnapshot.gatewayProbeAuth,
|
||||
gatewayProbeAuthWarning: params.overview.gatewaySnapshot.gatewayProbeAuthWarning,
|
||||
gatewaySelf: params.overview.gatewaySnapshot.gatewaySelf,
|
||||
return buildStatusOverviewSurfaceFromScan({
|
||||
scan: { ...params.overview, ...params.overview.gatewaySnapshot },
|
||||
gatewayService: params.gatewayService,
|
||||
nodeService: params.nodeService,
|
||||
nodeOnlyGateway: params.nodeOnlyGateway,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/** Builds overview rows from an already-normalized surface. */
|
||||
|
||||
@@ -37,26 +37,6 @@ const statusCommandTextRuntimeLoader = createLazyImportLoader(
|
||||
);
|
||||
const statusNodeModeModuleLoader = createLazyImportLoader(() => import("./status.node-mode.js"));
|
||||
|
||||
function loadStatusScanModule() {
|
||||
return statusScanModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusScanFastJsonModule() {
|
||||
return statusScanFastJsonModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusAllModule() {
|
||||
return statusAllModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusCommandTextRuntime() {
|
||||
return statusCommandTextRuntimeLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusNodeModeModule() {
|
||||
return statusNodeModeModuleLoader.load();
|
||||
}
|
||||
|
||||
/** Extracts device-pairing recovery context from structured gateway errors or legacy message text. */
|
||||
function resolvePairingRecoveryContext(params: {
|
||||
error?: string | null;
|
||||
@@ -131,9 +111,9 @@ export async function statusCommand(
|
||||
) {
|
||||
if (opts.all && !opts.json) {
|
||||
// Human `--all` has a dedicated report path; JSON `--all` stays on the JSON schema.
|
||||
await loadStatusAllModule().then(({ statusAllCommand }) =>
|
||||
statusAllCommand(runtime, { timeoutMs: opts.timeoutMs }),
|
||||
);
|
||||
await statusAllModuleLoader
|
||||
.load()
|
||||
.then(({ statusAllCommand }) => statusAllCommand(runtime, { timeoutMs: opts.timeoutMs }));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -145,16 +125,21 @@ export async function statusCommand(
|
||||
includePluginCompatibility: opts.all === true,
|
||||
suppressHealthErrors: true,
|
||||
scanStatusJsonFast: async (scanOpts, runtimeForScan) =>
|
||||
await loadStatusScanFastJsonModule().then(({ scanStatusJsonFast }) =>
|
||||
scanStatusJsonFast(scanOpts, runtimeForScan),
|
||||
),
|
||||
await statusScanFastJsonModuleLoader
|
||||
.load()
|
||||
.then(({ scanStatusJsonFast }) => scanStatusJsonFast(scanOpts, runtimeForScan)),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const scan = await loadStatusScanModule().then(({ scanStatus }) =>
|
||||
scanStatus({ json: false, timeoutMs: opts.timeoutMs, all: opts.all, deep: opts.deep }, runtime),
|
||||
);
|
||||
const scan = await statusScanModuleLoader
|
||||
.load()
|
||||
.then(({ scanStatus }) =>
|
||||
scanStatus(
|
||||
{ json: false, timeoutMs: opts.timeoutMs, all: opts.all, deep: opts.deep },
|
||||
runtime,
|
||||
),
|
||||
);
|
||||
|
||||
const {
|
||||
cfg,
|
||||
@@ -250,7 +235,7 @@ export async function statusCommand(
|
||||
resolveMemoryVectorState,
|
||||
shortenText,
|
||||
theme,
|
||||
} = await loadStatusCommandTextRuntime();
|
||||
} = await statusCommandTextRuntimeLoader.load();
|
||||
const muted = (value: string) => (rich ? theme.muted(value) : value);
|
||||
const ok = (value: string) => (rich ? theme.success(value) : value);
|
||||
const warn = (value: string) => (rich ? theme.warn(value) : value);
|
||||
@@ -289,12 +274,14 @@ export async function statusCommand(
|
||||
runtime.log("");
|
||||
}
|
||||
|
||||
const nodeOnlyGateway = await loadStatusNodeModeModule().then(({ resolveNodeOnlyGatewayInfo }) =>
|
||||
resolveNodeOnlyGatewayInfo({
|
||||
daemon,
|
||||
node: nodeDaemon,
|
||||
}),
|
||||
);
|
||||
const nodeOnlyGateway = await statusNodeModeModuleLoader
|
||||
.load()
|
||||
.then(({ resolveNodeOnlyGatewayInfo }) =>
|
||||
resolveNodeOnlyGatewayInfo({
|
||||
daemon,
|
||||
node: nodeDaemon,
|
||||
}),
|
||||
);
|
||||
const pairingRecovery = resolvePairingRecoveryContext({
|
||||
error: gatewayProbe?.error ?? null,
|
||||
closeReason: gatewayProbe?.close?.reason ?? null,
|
||||
|
||||
@@ -16,10 +16,6 @@ const statusScanDepsRuntimeModuleLoader = createLazyImportLoader(
|
||||
() => import("./status.scan.deps.runtime.js"),
|
||||
);
|
||||
|
||||
function loadStatusScanDepsRuntimeModule() {
|
||||
return statusScanDepsRuntimeModuleLoader.load();
|
||||
}
|
||||
|
||||
/** Returns the owning agent database path for built-in memory. */
|
||||
export function resolveDefaultMemoryDatabasePath(agentId: string): string {
|
||||
return resolveOpenClawAgentSqlitePath({ agentId });
|
||||
@@ -32,7 +28,7 @@ export async function resolveStatusMemoryStatusSnapshot(params: {
|
||||
memoryPlugin: MemoryPluginStatus;
|
||||
requireDefaultDatabasePath?: (agentId: string) => string;
|
||||
}): Promise<MemoryStatusSnapshot | null> {
|
||||
const { getMemorySearchManager } = await loadStatusScanDepsRuntimeModule();
|
||||
const { getMemorySearchManager } = await statusScanDepsRuntimeModuleLoader.load();
|
||||
return await resolveSharedMemoryStatusSnapshot({
|
||||
cfg: params.cfg,
|
||||
agentStatus: params.agentStatus,
|
||||
|
||||
@@ -44,50 +44,6 @@ const commandSecretTargetsModuleLoader = createLazyImportLoader(
|
||||
() => import("../cli/command-secret-targets.js"),
|
||||
);
|
||||
|
||||
function loadStatusScanDepsRuntimeModule() {
|
||||
return statusScanDepsRuntimeModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusAgentLocalModule() {
|
||||
return statusAgentLocalModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusUpdateModule() {
|
||||
return statusUpdateModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusScanRuntimeModule() {
|
||||
return statusScanRuntimeModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadGatewayCallModule() {
|
||||
return gatewayCallModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadStatusSummaryModule() {
|
||||
return statusSummaryModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadChannelPluginIdsModule() {
|
||||
return channelPluginIdsModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadConfigModule() {
|
||||
return configModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadControlUiLinksModule() {
|
||||
return controlUiLinksModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadCommandConfigResolutionModule() {
|
||||
return commandConfigResolutionModuleLoader.load();
|
||||
}
|
||||
|
||||
function loadCommandSecretTargetsModule() {
|
||||
return commandSecretTargetsModuleLoader.load();
|
||||
}
|
||||
|
||||
async function resolveStatusChannelsStatus(params: {
|
||||
cfg: OpenClawConfig;
|
||||
gatewayReachable: boolean;
|
||||
@@ -99,7 +55,7 @@ async function resolveStatusChannelsStatus(params: {
|
||||
// Avoid a second gateway call after probe failure; channel tables can still summarize local config.
|
||||
return null;
|
||||
}
|
||||
const { callGateway } = await loadGatewayCallModule();
|
||||
const { callGateway } = await gatewayCallModuleLoader.load();
|
||||
return await callGateway({
|
||||
config: params.cfg,
|
||||
method: "channels.status",
|
||||
@@ -193,17 +149,17 @@ export async function collectStatusScanOverview(params: {
|
||||
commandName: params.commandName,
|
||||
allowMissingConfigFastPath: params.allowMissingConfigFastPath,
|
||||
readConfigSnapshot: async () =>
|
||||
(await loadConfigModule()).readBestEffortConfigSnapshot({
|
||||
(await configModuleLoader.load()).readBestEffortConfigSnapshot({
|
||||
observe: false,
|
||||
skipPluginValidation: params.skipConfigPluginValidation,
|
||||
}),
|
||||
resolveConfig: async (loadedConfig) =>
|
||||
await (
|
||||
await loadCommandConfigResolutionModule()
|
||||
await commandConfigResolutionModuleLoader.load()
|
||||
).resolveCommandConfigWithSecrets({
|
||||
config: loadedConfig,
|
||||
commandName: params.commandName,
|
||||
targetIds: (await loadCommandSecretTargetsModule()).getStatusCommandSecretTargetIds(
|
||||
targetIds: (await commandSecretTargetsModuleLoader.load()).getStatusCommandSecretTargetIds(
|
||||
loadedConfig,
|
||||
process.env,
|
||||
{ includeChannelTargets: params.includeChannelSecretTargets },
|
||||
@@ -215,7 +171,7 @@ export async function collectStatusScanOverview(params: {
|
||||
params.progress?.tick();
|
||||
const hasConfiguredChannels = params.resolveHasConfiguredChannels
|
||||
? await params.resolveHasConfiguredChannels(cfg, sourceConfig)
|
||||
: await loadChannelPluginIdsModule().then(({ hasConfiguredChannelsForReadOnlyScope }) =>
|
||||
: await channelPluginIdsModuleLoader.load().then(({ hasConfiguredChannelsForReadOnlyScope }) =>
|
||||
hasConfiguredChannelsForReadOnlyScope({
|
||||
config: cfg,
|
||||
activationSourceConfig: sourceConfig,
|
||||
@@ -239,18 +195,18 @@ export async function collectStatusScanOverview(params: {
|
||||
includeLocalStatusRpcFallback: params.includeLocalStatusRpcFallback,
|
||||
gatewayProbeTimeoutMs,
|
||||
getTailnetHostname: async (runner) => {
|
||||
return await loadStatusScanDepsRuntimeModule().then(({ getTailnetHostname }) =>
|
||||
getTailnetHostname(runner),
|
||||
);
|
||||
return await statusScanDepsRuntimeModuleLoader
|
||||
.load()
|
||||
.then(({ getTailnetHostname }) => getTailnetHostname(runner));
|
||||
},
|
||||
getUpdateCheckResult: async (updateParams) =>
|
||||
await loadStatusUpdateModule().then(({ getUpdateCheckResult }) =>
|
||||
getUpdateCheckResult(updateParams),
|
||||
),
|
||||
await statusUpdateModuleLoader
|
||||
.load()
|
||||
.then(({ getUpdateCheckResult }) => getUpdateCheckResult(updateParams)),
|
||||
getAgentLocalStatuses: async (bootstrapCfg) =>
|
||||
await loadStatusAgentLocalModule().then(({ getAgentLocalStatuses }) =>
|
||||
getAgentLocalStatuses(bootstrapCfg),
|
||||
),
|
||||
await statusAgentLocalModuleLoader
|
||||
.load()
|
||||
.then(({ getAgentLocalStatuses }) => getAgentLocalStatuses(bootstrapCfg)),
|
||||
});
|
||||
|
||||
if (params.labels?.checkingTailscale) {
|
||||
@@ -280,9 +236,9 @@ export async function collectStatusScanOverview(params: {
|
||||
const tailscaleHttpsUrl = await bootstrap.resolveTailscaleHttpsUrl();
|
||||
const advertisedControlUiLinks =
|
||||
params.includeAdvertisedControlUiLinks === true && cfg.gateway?.controlUi?.enabled !== false
|
||||
? await loadControlUiLinksModule().then(async ({ resolveAdvertisedControlUiLinks }) =>
|
||||
? await controlUiLinksModuleLoader.load().then(async ({ resolveAdvertisedControlUiLinks }) =>
|
||||
resolveAdvertisedControlUiLinks({
|
||||
port: (await loadConfigModule()).resolveGatewayPort(cfg),
|
||||
port: (await configModuleLoader.load()).resolveGatewayPort(cfg),
|
||||
bind: cfg.gateway?.bind,
|
||||
customBindHost: cfg.gateway?.customBindHost,
|
||||
basePath: cfg.gateway?.controlUi?.basePath,
|
||||
@@ -309,7 +265,9 @@ export async function collectStatusScanOverview(params: {
|
||||
params.progress?.tick();
|
||||
// Runtime channel helpers stay lazy because JSON fast paths can skip channel data entirely.
|
||||
const { collectChannelStatusIssues, buildChannelsTable } =
|
||||
await loadStatusScanRuntimeModule().then(({ statusScanRuntime }) => statusScanRuntime);
|
||||
await statusScanRuntimeModuleLoader
|
||||
.load()
|
||||
.then(({ statusScanRuntime }) => statusScanRuntime);
|
||||
const channelIssuesLocal = channelsStatusLocal
|
||||
? collectChannelStatusIssues(channelsStatusLocal)
|
||||
: [];
|
||||
@@ -367,7 +325,7 @@ export async function resolveStatusSummaryFromOverview(params: {
|
||||
if (params.overview.skipColdStartNetworkChecks) {
|
||||
return buildColdStartStatusSummary();
|
||||
}
|
||||
return await loadStatusSummaryModule().then(({ getStatusSummary }) =>
|
||||
return await statusSummaryModuleLoader.load().then(({ getStatusSummary }) =>
|
||||
getStatusSummary({
|
||||
config: params.overview.cfg,
|
||||
sourceConfig: params.overview.sourceConfig,
|
||||
|
||||
@@ -1,107 +1,48 @@
|
||||
// Normalized full status scan result shape.
|
||||
// Builders flatten the gateway snapshot so downstream text/JSON code reads one stable object.
|
||||
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { collectChannelStatusIssues as collectChannelStatusIssuesFn } from "../infra/channels-status-issues.js";
|
||||
import { resolveOsSummary } from "../infra/os-summary.js";
|
||||
import type { UpdateCheckResult } from "../infra/update-check.js";
|
||||
import type { PluginCompatibilityNotice } from "../plugins/status.js";
|
||||
import type { getStatusSummary as getStatusSummaryFn } from "../status/summary.js";
|
||||
import type { pickGatewaySelfPresence } from "./gateway-presence.js";
|
||||
import type { buildChannelsTable as buildChannelsTableFn } from "./status-all/channels.js";
|
||||
import type { getAgentLocalStatuses as getAgentLocalStatusesFn } from "./status.agent-local.js";
|
||||
import type {
|
||||
GatewayProbeSnapshot,
|
||||
MemoryPluginStatus,
|
||||
MemoryStatusSnapshot,
|
||||
} from "./status.scan.shared.js";
|
||||
import type { StatusScanOverviewResult } from "./status.scan-overview.ts";
|
||||
import type { MemoryPluginStatus, MemoryStatusSnapshot } from "./status.scan.shared.js";
|
||||
|
||||
export type StatusScanResult = {
|
||||
cfg: OpenClawConfig;
|
||||
sourceConfig: OpenClawConfig;
|
||||
secretDiagnostics: string[];
|
||||
osSummary: ReturnType<typeof resolveOsSummary>;
|
||||
tailscaleMode: string;
|
||||
tailscaleDns: string | null;
|
||||
tailscaleHttpsUrl: string | null;
|
||||
advertisedControlUiLinks?: { httpUrl: string; wsUrl: string };
|
||||
update: UpdateCheckResult;
|
||||
gatewayConnection: GatewayProbeSnapshot["gatewayConnection"];
|
||||
remoteUrlMissing: boolean;
|
||||
gatewayMode: "local" | "remote";
|
||||
gatewayProbeAuth: {
|
||||
token?: string;
|
||||
password?: string;
|
||||
type StatusScanGatewayResult = Omit<
|
||||
StatusScanOverviewResult["gatewaySnapshot"],
|
||||
"gatewayCallOverrides"
|
||||
>;
|
||||
|
||||
export type StatusScanResult = Omit<
|
||||
StatusScanOverviewResult,
|
||||
| "coldStart"
|
||||
| "hasConfiguredChannels"
|
||||
| "skipColdStartNetworkChecks"
|
||||
| "gatewaySnapshot"
|
||||
| "channelsStatus"
|
||||
> &
|
||||
StatusScanGatewayResult & {
|
||||
summary: Awaited<ReturnType<typeof getStatusSummaryFn>>;
|
||||
memory: MemoryStatusSnapshot | null;
|
||||
memoryPlugin: MemoryPluginStatus;
|
||||
pluginCompatibility: PluginCompatibilityNotice[];
|
||||
};
|
||||
gatewayProbeAuthWarning?: string;
|
||||
gatewayProbe: GatewayProbeSnapshot["gatewayProbe"];
|
||||
gatewayReachable: boolean;
|
||||
gatewaySelf: ReturnType<typeof pickGatewaySelfPresence>;
|
||||
channelIssues: ReturnType<typeof collectChannelStatusIssuesFn>;
|
||||
agentStatus: Awaited<ReturnType<typeof getAgentLocalStatusesFn>>;
|
||||
channels: Awaited<ReturnType<typeof buildChannelsTableFn>>;
|
||||
summary: Awaited<ReturnType<typeof getStatusSummaryFn>>;
|
||||
memory: MemoryStatusSnapshot | null;
|
||||
memoryPlugin: MemoryPluginStatus;
|
||||
pluginCompatibility: PluginCompatibilityNotice[];
|
||||
};
|
||||
|
||||
/** Flattens overview, gateway, channel, summary, memory, and compatibility inputs into a scan result. */
|
||||
export function buildStatusScanResult(params: {
|
||||
cfg: OpenClawConfig;
|
||||
sourceConfig: OpenClawConfig;
|
||||
secretDiagnostics: string[];
|
||||
osSummary: ReturnType<typeof resolveOsSummary>;
|
||||
tailscaleMode: string;
|
||||
tailscaleDns: string | null;
|
||||
tailscaleHttpsUrl: string | null;
|
||||
advertisedControlUiLinks?: { httpUrl: string; wsUrl: string };
|
||||
update: UpdateCheckResult;
|
||||
gatewaySnapshot: Pick<
|
||||
GatewayProbeSnapshot,
|
||||
| "gatewayConnection"
|
||||
| "remoteUrlMissing"
|
||||
| "gatewayMode"
|
||||
| "gatewayProbeAuth"
|
||||
| "gatewayProbeAuthWarning"
|
||||
| "gatewayProbe"
|
||||
| "gatewayReachable"
|
||||
| "gatewaySelf"
|
||||
>;
|
||||
channelIssues: ReturnType<typeof collectChannelStatusIssuesFn>;
|
||||
agentStatus: Awaited<ReturnType<typeof getAgentLocalStatusesFn>>;
|
||||
channels: Awaited<ReturnType<typeof buildChannelsTableFn>>;
|
||||
summary: Awaited<ReturnType<typeof getStatusSummaryFn>>;
|
||||
memory: MemoryStatusSnapshot | null;
|
||||
memoryPlugin: MemoryPluginStatus;
|
||||
pluginCompatibility: PluginCompatibilityNotice[];
|
||||
}): StatusScanResult {
|
||||
export function buildStatusScanResult(
|
||||
params: Omit<StatusScanResult, keyof StatusScanGatewayResult> & {
|
||||
gatewaySnapshot: StatusScanGatewayResult;
|
||||
},
|
||||
): StatusScanResult {
|
||||
const { gatewaySnapshot, advertisedControlUiLinks, ...result } = params;
|
||||
return {
|
||||
cfg: params.cfg,
|
||||
sourceConfig: params.sourceConfig,
|
||||
secretDiagnostics: params.secretDiagnostics,
|
||||
osSummary: params.osSummary,
|
||||
tailscaleMode: params.tailscaleMode,
|
||||
tailscaleDns: params.tailscaleDns,
|
||||
tailscaleHttpsUrl: params.tailscaleHttpsUrl,
|
||||
...(params.advertisedControlUiLinks
|
||||
? { advertisedControlUiLinks: params.advertisedControlUiLinks }
|
||||
: {}),
|
||||
update: params.update,
|
||||
gatewayConnection: params.gatewaySnapshot.gatewayConnection,
|
||||
remoteUrlMissing: params.gatewaySnapshot.remoteUrlMissing,
|
||||
gatewayMode: params.gatewaySnapshot.gatewayMode,
|
||||
gatewayProbeAuth: params.gatewaySnapshot.gatewayProbeAuth,
|
||||
gatewayProbeAuthWarning: params.gatewaySnapshot.gatewayProbeAuthWarning,
|
||||
gatewayProbe: params.gatewaySnapshot.gatewayProbe,
|
||||
gatewayReachable: params.gatewaySnapshot.gatewayReachable,
|
||||
gatewaySelf: params.gatewaySnapshot.gatewaySelf,
|
||||
channelIssues: params.channelIssues,
|
||||
agentStatus: params.agentStatus,
|
||||
channels: params.channels,
|
||||
summary: params.summary,
|
||||
memory: params.memory,
|
||||
memoryPlugin: params.memoryPlugin,
|
||||
pluginCompatibility: params.pluginCompatibility,
|
||||
...result,
|
||||
...(advertisedControlUiLinks ? { advertisedControlUiLinks } : {}),
|
||||
gatewayConnection: gatewaySnapshot.gatewayConnection,
|
||||
remoteUrlMissing: gatewaySnapshot.remoteUrlMissing,
|
||||
gatewayMode: gatewaySnapshot.gatewayMode,
|
||||
gatewayProbeAuth: gatewaySnapshot.gatewayProbeAuth,
|
||||
gatewayProbeAuthWarning: gatewaySnapshot.gatewayProbeAuthWarning,
|
||||
gatewayProbe: gatewaySnapshot.gatewayProbe,
|
||||
gatewayReachable: gatewaySnapshot.gatewayReachable,
|
||||
gatewaySelf: gatewaySnapshot.gatewaySelf,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user