mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-18 12:14:32 +00:00
fix: restore status command typing after refactor
This commit is contained in:
@@ -109,8 +109,6 @@ export async function statusAllCommand(
|
||||
].join("\n");
|
||||
})();
|
||||
|
||||
const callOverrides = gatewayCallOverrides ?? {};
|
||||
|
||||
const health = nodeOnlyGateway
|
||||
? undefined
|
||||
: await resolveStatusGatewayHealthSafe({
|
||||
@@ -118,7 +116,7 @@ export async function statusAllCommand(
|
||||
timeoutMs: Math.min(8000, opts?.timeoutMs ?? 10_000),
|
||||
gatewayReachable,
|
||||
gatewayProbeError: gatewayProbe?.error ?? null,
|
||||
callOverrides,
|
||||
callOverrides: gatewayCallOverrides,
|
||||
});
|
||||
const channelsStatus = overview.channelsStatus;
|
||||
const channelIssues = overview.channelIssues;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { resolveGatewayPort } from "../../config/config.js";
|
||||
import type { OpenClawConfig } from "../../config/types.js";
|
||||
import { resolveControlUiLinks } from "../../gateway/control-ui-links.js";
|
||||
import { formatDurationPrecise } from "../../infra/format-time/format-duration.ts";
|
||||
import {
|
||||
@@ -16,23 +17,11 @@ export type StatusOverviewRow = {
|
||||
Value: string;
|
||||
};
|
||||
|
||||
type StatusUpdateLike = {
|
||||
installKind?: string | null;
|
||||
git?: {
|
||||
tag?: string | null;
|
||||
branch?: string | null;
|
||||
} | null;
|
||||
} & UpdateCheckResult;
|
||||
type UpdateConfigChannel = NonNullable<OpenClawConfig["update"]>["channel"];
|
||||
|
||||
export function resolveStatusUpdateChannelInfo(params: {
|
||||
updateConfigChannel?: string | null;
|
||||
update: {
|
||||
installKind?: string | null;
|
||||
git?: {
|
||||
tag?: string | null;
|
||||
branch?: string | null;
|
||||
} | null;
|
||||
};
|
||||
updateConfigChannel?: UpdateConfigChannel;
|
||||
update: UpdateCheckResult;
|
||||
}) {
|
||||
return resolveUpdateChannelDisplay({
|
||||
configChannel: normalizeUpdateChannel(params.updateConfigChannel),
|
||||
@@ -43,8 +32,8 @@ export function resolveStatusUpdateChannelInfo(params: {
|
||||
}
|
||||
|
||||
export function buildStatusUpdateSurface(params: {
|
||||
updateConfigChannel?: string | null;
|
||||
update: StatusUpdateLike;
|
||||
updateConfigChannel?: UpdateConfigChannel;
|
||||
update: UpdateCheckResult;
|
||||
}) {
|
||||
const channelInfo = resolveStatusUpdateChannelInfo({
|
||||
updateConfigChannel: params.updateConfigChannel,
|
||||
@@ -126,16 +115,7 @@ export function formatStatusServiceValue(params: {
|
||||
}
|
||||
|
||||
export function resolveStatusDashboardUrl(params: {
|
||||
cfg: {
|
||||
gateway?: {
|
||||
bind?: string;
|
||||
customBindHost?: string;
|
||||
controlUi?: {
|
||||
enabled?: boolean;
|
||||
basePath?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
cfg: Pick<OpenClawConfig, "gateway">;
|
||||
}): string | null {
|
||||
if (!(params.cfg.gateway?.controlUi?.enabled ?? true)) {
|
||||
return null;
|
||||
@@ -289,16 +269,7 @@ export function buildGatewayStatusSummaryParts(params: {
|
||||
}
|
||||
|
||||
export function buildStatusGatewaySurfaceValues(params: {
|
||||
cfg: {
|
||||
gateway?: {
|
||||
bind?: string;
|
||||
customBindHost?: string;
|
||||
controlUi?: {
|
||||
enabled?: boolean;
|
||||
basePath?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
cfg: Pick<OpenClawConfig, "gateway">;
|
||||
gatewayMode: "local" | "remote";
|
||||
remoteUrlMissing: boolean;
|
||||
gatewayConnection: {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { TableColumn } from "../../terminal/table.js";
|
||||
|
||||
type HeadingFn = (text: string) => string;
|
||||
|
||||
export function appendStatusSectionHeading(params: {
|
||||
@@ -26,12 +28,8 @@ export function appendStatusTableSection<Row extends Record<string, string>>(par
|
||||
heading: HeadingFn;
|
||||
title: string;
|
||||
width: number;
|
||||
renderTable: (input: {
|
||||
width: number;
|
||||
columns: Array<Record<string, unknown>>;
|
||||
rows: Row[];
|
||||
}) => string;
|
||||
columns: Array<Record<string, unknown>>;
|
||||
renderTable: (input: { width: number; columns: TableColumn[]; rows: Row[] }) => string;
|
||||
columns: readonly TableColumn[];
|
||||
rows: Row[];
|
||||
}) {
|
||||
appendStatusSectionHeading(params);
|
||||
@@ -39,7 +37,7 @@ export function appendStatusTableSection<Row extends Record<string, string>>(par
|
||||
params
|
||||
.renderTable({
|
||||
width: params.width,
|
||||
columns: params.columns,
|
||||
columns: [...params.columns],
|
||||
rows: params.rows,
|
||||
})
|
||||
.trimEnd(),
|
||||
|
||||
@@ -25,8 +25,20 @@ describe("status-json-payload", () => {
|
||||
resolveStatusUpdateChannelInfo({
|
||||
updateConfigChannel: "beta",
|
||||
update: {
|
||||
installKind: "npm",
|
||||
git: { tag: "v1.2.3", branch: "main" },
|
||||
root: "/tmp/openclaw",
|
||||
installKind: "package",
|
||||
packageManager: "npm",
|
||||
git: {
|
||||
root: "/tmp/openclaw",
|
||||
sha: null,
|
||||
tag: "v1.2.3",
|
||||
branch: "main",
|
||||
upstream: null,
|
||||
dirty: false,
|
||||
ahead: 0,
|
||||
behind: 0,
|
||||
fetchOk: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toEqual({
|
||||
@@ -37,7 +49,7 @@ describe("status-json-payload", () => {
|
||||
expect(mocks.normalizeUpdateChannel).toHaveBeenCalledWith("beta");
|
||||
expect(mocks.resolveUpdateChannelDisplay).toHaveBeenCalledWith({
|
||||
configChannel: "beta",
|
||||
installKind: "npm",
|
||||
installKind: "package",
|
||||
gitTag: "v1.2.3",
|
||||
gitBranch: "main",
|
||||
});
|
||||
@@ -48,7 +60,12 @@ describe("status-json-payload", () => {
|
||||
buildStatusJsonPayload({
|
||||
summary: { ok: true },
|
||||
updateConfigChannel: "stable",
|
||||
update: { installKind: "npm", git: null, version: "1.2.3" },
|
||||
update: {
|
||||
root: "/tmp/openclaw",
|
||||
installKind: "package",
|
||||
packageManager: "npm",
|
||||
registry: { latestVersion: "1.2.3" },
|
||||
},
|
||||
osSummary: { platform: "linux" },
|
||||
memory: null,
|
||||
memoryPlugin: { enabled: true },
|
||||
@@ -67,12 +84,24 @@ describe("status-json-payload", () => {
|
||||
health: { ok: true },
|
||||
usage: { providers: [] },
|
||||
lastHeartbeat: { status: "ok" },
|
||||
pluginCompatibility: [{ pluginId: "legacy", message: "warn" }],
|
||||
pluginCompatibility: [
|
||||
{
|
||||
pluginId: "legacy",
|
||||
code: "legacy-before-agent-start",
|
||||
severity: "warn",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
}),
|
||||
).toEqual({
|
||||
ok: true,
|
||||
os: { platform: "linux" },
|
||||
update: { installKind: "npm", git: null, version: "1.2.3" },
|
||||
update: {
|
||||
root: "/tmp/openclaw",
|
||||
installKind: "package",
|
||||
packageManager: "npm",
|
||||
registry: { latestVersion: "1.2.3" },
|
||||
},
|
||||
updateChannel: "stable",
|
||||
updateChannelSource: "config",
|
||||
memory: null,
|
||||
@@ -98,7 +127,14 @@ describe("status-json-payload", () => {
|
||||
lastHeartbeat: { status: "ok" },
|
||||
pluginCompatibility: {
|
||||
count: 1,
|
||||
warnings: [{ pluginId: "legacy", message: "warn" }],
|
||||
warnings: [
|
||||
{
|
||||
pluginId: "legacy",
|
||||
code: "legacy-before-agent-start",
|
||||
severity: "warn",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -108,7 +144,11 @@ describe("status-json-payload", () => {
|
||||
buildStatusJsonPayload({
|
||||
summary: { ok: true },
|
||||
updateConfigChannel: null,
|
||||
update: { installKind: "npm", git: null },
|
||||
update: {
|
||||
root: "/tmp/openclaw",
|
||||
installKind: "package",
|
||||
packageManager: "npm",
|
||||
},
|
||||
osSummary: { platform: "linux" },
|
||||
memory: null,
|
||||
memoryPlugin: null,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import type { UpdateCheckResult } from "../infra/update-check.js";
|
||||
import {
|
||||
buildGatewayStatusJsonPayload,
|
||||
resolveStatusUpdateChannelInfo,
|
||||
@@ -5,16 +7,12 @@ import {
|
||||
|
||||
export { resolveStatusUpdateChannelInfo } from "./status-all/format.js";
|
||||
|
||||
type UpdateConfigChannel = NonNullable<OpenClawConfig["update"]>["channel"];
|
||||
|
||||
export function buildStatusJsonPayload(params: {
|
||||
summary: Record<string, unknown>;
|
||||
updateConfigChannel?: string | null;
|
||||
update: {
|
||||
installKind?: string | null;
|
||||
git?: {
|
||||
tag?: string | null;
|
||||
branch?: string | null;
|
||||
} | null;
|
||||
} & Record<string, unknown>;
|
||||
updateConfigChannel?: UpdateConfigChannel | null;
|
||||
update: UpdateCheckResult;
|
||||
osSummary: unknown;
|
||||
memory: unknown;
|
||||
memoryPlugin: unknown;
|
||||
@@ -53,7 +51,7 @@ export function buildStatusJsonPayload(params: {
|
||||
pluginCompatibility?: Array<Record<string, unknown>> | null | undefined;
|
||||
}) {
|
||||
const channelInfo = resolveStatusUpdateChannelInfo({
|
||||
updateConfigChannel: params.updateConfigChannel,
|
||||
updateConfigChannel: params.updateConfigChannel ?? undefined,
|
||||
update: params.update,
|
||||
});
|
||||
return {
|
||||
|
||||
@@ -21,7 +21,11 @@ function createScan() {
|
||||
cfg: { update: { channel: "stable" }, gateway: {} },
|
||||
sourceConfig: { gateway: {} },
|
||||
summary: { ok: true },
|
||||
update: { installKind: "npm", git: null },
|
||||
update: {
|
||||
root: "/tmp/openclaw",
|
||||
installKind: "package",
|
||||
packageManager: "npm",
|
||||
},
|
||||
osSummary: { platform: "linux" },
|
||||
memory: null,
|
||||
memoryPlugin: { enabled: true },
|
||||
@@ -32,10 +36,17 @@ function createScan() {
|
||||
gatewayProbe: { connectLatencyMs: 42, error: null },
|
||||
gatewaySelf: { host: "gateway" },
|
||||
gatewayProbeAuthWarning: null,
|
||||
agentStatus: [{ id: "main" }],
|
||||
agentStatus: { agents: [{ id: "main" }], defaultId: "main" },
|
||||
secretDiagnostics: [],
|
||||
pluginCompatibility: [{ pluginId: "legacy", message: "warn" }],
|
||||
};
|
||||
pluginCompatibility: [
|
||||
{
|
||||
pluginId: "legacy",
|
||||
code: "legacy-before-agent-start",
|
||||
severity: "warn",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
} satisfies Parameters<typeof resolveStatusJsonOutput>[0]["scan"];
|
||||
}
|
||||
|
||||
describe("status-json-runtime", () => {
|
||||
@@ -74,7 +85,14 @@ describe("status-json-runtime", () => {
|
||||
usage: { providers: [] },
|
||||
health: { ok: true },
|
||||
lastHeartbeat: { status: "ok" },
|
||||
pluginCompatibility: [{ pluginId: "legacy", message: "warn" }],
|
||||
pluginCompatibility: [
|
||||
{
|
||||
pluginId: "legacy",
|
||||
code: "legacy-before-agent-start",
|
||||
severity: "warn",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
expect(result).toEqual({ built: true, input: expect.any(Object) });
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import type { UpdateCheckResult } from "../infra/update-check.js";
|
||||
import { buildStatusJsonPayload } from "./status-json-payload.ts";
|
||||
import {
|
||||
resolveStatusRuntimeDetails,
|
||||
@@ -9,13 +10,7 @@ type StatusJsonScanLike = {
|
||||
cfg: OpenClawConfig;
|
||||
sourceConfig: OpenClawConfig;
|
||||
summary: Record<string, unknown>;
|
||||
update: {
|
||||
installKind?: string | null;
|
||||
git?: {
|
||||
tag?: string | null;
|
||||
branch?: string | null;
|
||||
} | null;
|
||||
} & Record<string, unknown>;
|
||||
update: UpdateCheckResult;
|
||||
osSummary: unknown;
|
||||
memory: unknown;
|
||||
memoryPlugin: unknown;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { TableColumn } from "../terminal/table.js";
|
||||
import { appendStatusLinesSection, appendStatusTableSection } from "./status-all/text-report.js";
|
||||
|
||||
export async function buildStatusCommandReportLines(params: {
|
||||
@@ -5,7 +6,7 @@ export async function buildStatusCommandReportLines(params: {
|
||||
muted: (text: string) => string;
|
||||
renderTable: (input: {
|
||||
width: number;
|
||||
columns: Array<Record<string, unknown>>;
|
||||
columns: TableColumn[];
|
||||
rows: Array<Record<string, string>>;
|
||||
}) => string;
|
||||
width: number;
|
||||
@@ -15,13 +16,13 @@ export async function buildStatusCommandReportLines(params: {
|
||||
pluginCompatibilityLines: string[];
|
||||
pairingRecoveryLines: string[];
|
||||
securityAuditLines: string[];
|
||||
channelsColumns: Array<Record<string, unknown>>;
|
||||
channelsColumns: readonly TableColumn[];
|
||||
channelsRows: Array<Record<string, string>>;
|
||||
sessionsColumns: Array<Record<string, unknown>>;
|
||||
sessionsColumns: readonly TableColumn[];
|
||||
sessionsRows: Array<Record<string, string>>;
|
||||
systemEventsRows?: Array<Record<string, string>>;
|
||||
systemEventsTrailer?: string | null;
|
||||
healthColumns?: Array<Record<string, unknown>>;
|
||||
healthColumns?: readonly TableColumn[];
|
||||
healthRows?: Array<Record<string, string>>;
|
||||
usageLines?: string[];
|
||||
footerLines: string[];
|
||||
|
||||
@@ -59,10 +59,16 @@ describe("status.command-sections", () => {
|
||||
recent: [
|
||||
{
|
||||
key: "session-key-1234567890",
|
||||
kind: "chat",
|
||||
kind: "direct",
|
||||
updatedAt: 1,
|
||||
age: 5_000,
|
||||
model: "gpt-5.4",
|
||||
totalTokens: null,
|
||||
totalTokensFresh: false,
|
||||
remainingTokens: null,
|
||||
percentUsed: null,
|
||||
contextTokens: null,
|
||||
flags: [],
|
||||
},
|
||||
],
|
||||
verbose: true,
|
||||
@@ -76,7 +82,7 @@ describe("status.command-sections", () => {
|
||||
expect(verboseRows).toEqual([
|
||||
{
|
||||
Key: "session-",
|
||||
Kind: "chat",
|
||||
Kind: "direct",
|
||||
Age: "5000ms",
|
||||
Model: "gpt-5.4",
|
||||
Tokens: "12k",
|
||||
|
||||
@@ -1,67 +1,22 @@
|
||||
import type { HeartbeatEventPayload } from "../infra/heartbeat-events.js";
|
||||
import type { Tone } from "../memory-host-sdk/status.js";
|
||||
import type { TableColumn } from "../terminal/table.js";
|
||||
import type { HealthSummary } from "./health.js";
|
||||
import type { AgentLocalStatus } from "./status.agent-local.js";
|
||||
import type { MemoryStatusSnapshot, MemoryPluginStatus } from "./status.scan.shared.js";
|
||||
import type { SessionStatus, StatusSummary } from "./status.types.js";
|
||||
|
||||
type AgentStatusLike = {
|
||||
defaultId?: string | null;
|
||||
bootstrapPendingCount: number;
|
||||
totalSessions: number;
|
||||
agents: Array<{
|
||||
id: string;
|
||||
lastActiveAgeMs?: number | null;
|
||||
}>;
|
||||
agents: AgentLocalStatus[];
|
||||
};
|
||||
|
||||
type SummaryLike = {
|
||||
tasks: {
|
||||
total: number;
|
||||
active: number;
|
||||
failures: number;
|
||||
byStatus: {
|
||||
queued: number;
|
||||
running: number;
|
||||
};
|
||||
};
|
||||
taskAudit: {
|
||||
errors: number;
|
||||
warnings: number;
|
||||
};
|
||||
heartbeat: {
|
||||
agents: Array<{
|
||||
agentId: string;
|
||||
enabled?: boolean | null;
|
||||
everyMs?: number | null;
|
||||
every: string;
|
||||
}>;
|
||||
};
|
||||
sessions: {
|
||||
recent: Array<{
|
||||
key: string;
|
||||
kind: string;
|
||||
updatedAt?: number | null;
|
||||
age: number;
|
||||
model?: string | null;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
|
||||
type MemoryLike = {
|
||||
files: number;
|
||||
chunks: number;
|
||||
dirty?: boolean;
|
||||
sources?: string[];
|
||||
vector?: unknown;
|
||||
fts?: unknown;
|
||||
cache?: unknown;
|
||||
} | null;
|
||||
|
||||
type MemoryPluginLike = {
|
||||
enabled: boolean;
|
||||
reason?: string | null;
|
||||
slot?: string | null;
|
||||
};
|
||||
|
||||
type SessionsRecentLike = SummaryLike["sessions"]["recent"][number];
|
||||
type SummaryLike = Pick<StatusSummary, "tasks" | "taskAudit" | "heartbeat" | "sessions">;
|
||||
type MemoryLike = MemoryStatusSnapshot | null;
|
||||
type MemoryPluginLike = MemoryPluginStatus;
|
||||
type SessionsRecentLike = SessionStatus;
|
||||
|
||||
type PluginCompatibilityNoticeLike = {
|
||||
severity?: "warn" | "info" | null;
|
||||
@@ -71,7 +26,7 @@ type PairingRecoveryLike = {
|
||||
requestId?: string | null;
|
||||
};
|
||||
|
||||
export const statusHealthColumns = [
|
||||
export const statusHealthColumns: TableColumn[] = [
|
||||
{ key: "Item", header: "Item", minWidth: 10 },
|
||||
{ key: "Status", header: "Status", minWidth: 8 },
|
||||
{ key: "Detail", header: "Detail", flex: true, minWidth: 28 },
|
||||
@@ -165,9 +120,18 @@ export function buildStatusMemoryValue(params: {
|
||||
ok: (value: string) => string;
|
||||
warn: (value: string) => string;
|
||||
muted: (value: string) => string;
|
||||
resolveMemoryVectorState: (value: unknown) => { state: string; tone: Tone };
|
||||
resolveMemoryFtsState: (value: unknown) => { state: string; tone: Tone };
|
||||
resolveMemoryCacheSummary: (value: unknown) => { text: string; tone: Tone };
|
||||
resolveMemoryVectorState: (value: NonNullable<MemoryStatusSnapshot["vector"]>) => {
|
||||
state: string;
|
||||
tone: Tone;
|
||||
};
|
||||
resolveMemoryFtsState: (value: NonNullable<MemoryStatusSnapshot["fts"]>) => {
|
||||
state: string;
|
||||
tone: Tone;
|
||||
};
|
||||
resolveMemoryCacheSummary: (value: NonNullable<MemoryStatusSnapshot["cache"]>) => {
|
||||
text: string;
|
||||
tone: Tone;
|
||||
};
|
||||
}) {
|
||||
if (!params.memoryPlugin.enabled) {
|
||||
const suffix = params.memoryPlugin.reason ? ` (${params.memoryPlugin.reason})` : "";
|
||||
@@ -332,7 +296,7 @@ export function buildStatusSessionsRows(params: {
|
||||
return params.recent.map((sess) => ({
|
||||
Key: params.shortenText(sess.key, 32),
|
||||
Kind: sess.kind,
|
||||
Age: sess.updatedAt ? params.formatTimeAgo(sess.age) : "no activity",
|
||||
Age: sess.updatedAt && sess.age != null ? params.formatTimeAgo(sess.age) : "no activity",
|
||||
Model: sess.model ?? "unknown",
|
||||
Tokens: params.formatTokensCompact(sess),
|
||||
...(params.verbose
|
||||
|
||||
@@ -30,14 +30,44 @@ describe("status.scan-memory", () => {
|
||||
const requireDefaultStore = vi.fn((agentId: string) => `/tmp/${agentId}.sqlite`);
|
||||
await resolveStatusMemoryStatusSnapshot({
|
||||
cfg: { agents: {} },
|
||||
agentStatus: { agents: [{ id: "main" }] },
|
||||
agentStatus: {
|
||||
defaultId: "main",
|
||||
totalSessions: 0,
|
||||
bootstrapPendingCount: 0,
|
||||
agents: [
|
||||
{
|
||||
id: "main",
|
||||
workspaceDir: null,
|
||||
bootstrapPending: false,
|
||||
sessionsPath: "/tmp/main.json",
|
||||
sessionsCount: 0,
|
||||
lastUpdatedAt: null,
|
||||
lastActiveAgeMs: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
memoryPlugin: { enabled: true, slot: "memory-core" },
|
||||
requireDefaultStore,
|
||||
});
|
||||
|
||||
expect(mocks.resolveSharedMemoryStatusSnapshot).toHaveBeenCalledWith({
|
||||
cfg: { agents: {} },
|
||||
agentStatus: { agents: [{ id: "main" }] },
|
||||
agentStatus: {
|
||||
defaultId: "main",
|
||||
totalSessions: 0,
|
||||
bootstrapPendingCount: 0,
|
||||
agents: [
|
||||
{
|
||||
id: "main",
|
||||
workspaceDir: null,
|
||||
bootstrapPending: false,
|
||||
sessionsPath: "/tmp/main.json",
|
||||
sessionsCount: 0,
|
||||
lastUpdatedAt: null,
|
||||
lastActiveAgeMs: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
memoryPlugin: { enabled: true, slot: "memory-core" },
|
||||
resolveMemoryConfig: mocks.resolveMemorySearchConfig,
|
||||
getMemorySearchManager: mocks.getMemorySearchManager,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildStatusScanResult } from "./status.scan-result.ts";
|
||||
import { buildColdStartStatusSummary } from "./status.scan.bootstrap-shared.ts";
|
||||
|
||||
describe("buildStatusScanResult", () => {
|
||||
it("builds the full shared scan result shape", () => {
|
||||
@@ -8,53 +9,157 @@ describe("buildStatusScanResult", () => {
|
||||
cfg: { gateway: {} },
|
||||
sourceConfig: { gateway: {} },
|
||||
secretDiagnostics: ["diag"],
|
||||
osSummary: { platform: "linux", label: "linux" },
|
||||
osSummary: {
|
||||
platform: "linux",
|
||||
arch: "x64",
|
||||
release: "6.8.0",
|
||||
label: "linux 6.8.0 (x64)",
|
||||
},
|
||||
tailscaleMode: "serve",
|
||||
tailscaleDns: "box.tail.ts.net",
|
||||
tailscaleHttpsUrl: "https://box.tail.ts.net",
|
||||
update: { installKind: "npm", git: null },
|
||||
update: {
|
||||
root: "/tmp/openclaw",
|
||||
installKind: "package",
|
||||
packageManager: "npm",
|
||||
},
|
||||
gatewaySnapshot: {
|
||||
gatewayConnection: { url: "ws://127.0.0.1:18789", urlSource: "config" },
|
||||
gatewayConnection: {
|
||||
url: "ws://127.0.0.1:18789",
|
||||
urlSource: "config",
|
||||
message: "Gateway target: ws://127.0.0.1:18789",
|
||||
},
|
||||
remoteUrlMissing: false,
|
||||
gatewayMode: "local",
|
||||
gatewayProbeAuth: { token: "tok" },
|
||||
gatewayProbeAuthWarning: "warn",
|
||||
gatewayProbe: { connectLatencyMs: 42, error: null },
|
||||
gatewayProbe: {
|
||||
ok: true,
|
||||
url: "ws://127.0.0.1:18789",
|
||||
connectLatencyMs: 42,
|
||||
error: null,
|
||||
close: null,
|
||||
health: null,
|
||||
status: null,
|
||||
presence: null,
|
||||
configSnapshot: null,
|
||||
},
|
||||
gatewayReachable: true,
|
||||
gatewaySelf: { host: "gateway" },
|
||||
},
|
||||
channelIssues: [{ channel: "discord", accountId: "default", message: "warn" }],
|
||||
agentStatus: { agents: [{ id: "main" }], defaultId: "main" },
|
||||
channelIssues: [
|
||||
{
|
||||
channel: "discord",
|
||||
accountId: "default",
|
||||
kind: "runtime",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
agentStatus: {
|
||||
defaultId: "main",
|
||||
totalSessions: 0,
|
||||
bootstrapPendingCount: 0,
|
||||
agents: [
|
||||
{
|
||||
id: "main",
|
||||
workspaceDir: null,
|
||||
bootstrapPending: false,
|
||||
sessionsPath: "/tmp/main.json",
|
||||
sessionsCount: 0,
|
||||
lastUpdatedAt: null,
|
||||
lastActiveAgeMs: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
channels: { rows: [], details: [] },
|
||||
summary: { ok: true },
|
||||
memory: { agentId: "main" },
|
||||
summary: buildColdStartStatusSummary(),
|
||||
memory: { agentId: "main", backend: "builtin", provider: "sqlite" },
|
||||
memoryPlugin: { enabled: true, slot: "memory-core" },
|
||||
pluginCompatibility: [{ pluginId: "legacy", message: "warn" }],
|
||||
pluginCompatibility: [
|
||||
{
|
||||
pluginId: "legacy",
|
||||
code: "legacy-before-agent-start",
|
||||
severity: "warn",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
}),
|
||||
).toEqual({
|
||||
cfg: { gateway: {} },
|
||||
sourceConfig: { gateway: {} },
|
||||
secretDiagnostics: ["diag"],
|
||||
osSummary: { platform: "linux", label: "linux" },
|
||||
osSummary: {
|
||||
platform: "linux",
|
||||
arch: "x64",
|
||||
release: "6.8.0",
|
||||
label: "linux 6.8.0 (x64)",
|
||||
},
|
||||
tailscaleMode: "serve",
|
||||
tailscaleDns: "box.tail.ts.net",
|
||||
tailscaleHttpsUrl: "https://box.tail.ts.net",
|
||||
update: { installKind: "npm", git: null },
|
||||
gatewayConnection: { url: "ws://127.0.0.1:18789", urlSource: "config" },
|
||||
update: {
|
||||
root: "/tmp/openclaw",
|
||||
installKind: "package",
|
||||
packageManager: "npm",
|
||||
},
|
||||
gatewayConnection: {
|
||||
url: "ws://127.0.0.1:18789",
|
||||
urlSource: "config",
|
||||
message: "Gateway target: ws://127.0.0.1:18789",
|
||||
},
|
||||
remoteUrlMissing: false,
|
||||
gatewayMode: "local",
|
||||
gatewayProbeAuth: { token: "tok" },
|
||||
gatewayProbeAuthWarning: "warn",
|
||||
gatewayProbe: { connectLatencyMs: 42, error: null },
|
||||
gatewayProbe: {
|
||||
ok: true,
|
||||
url: "ws://127.0.0.1:18789",
|
||||
connectLatencyMs: 42,
|
||||
error: null,
|
||||
close: null,
|
||||
health: null,
|
||||
status: null,
|
||||
presence: null,
|
||||
configSnapshot: null,
|
||||
},
|
||||
gatewayReachable: true,
|
||||
gatewaySelf: { host: "gateway" },
|
||||
channelIssues: [{ channel: "discord", accountId: "default", message: "warn" }],
|
||||
agentStatus: { agents: [{ id: "main" }], defaultId: "main" },
|
||||
channelIssues: [
|
||||
{
|
||||
channel: "discord",
|
||||
accountId: "default",
|
||||
kind: "runtime",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
agentStatus: {
|
||||
defaultId: "main",
|
||||
totalSessions: 0,
|
||||
bootstrapPendingCount: 0,
|
||||
agents: [
|
||||
{
|
||||
id: "main",
|
||||
workspaceDir: null,
|
||||
bootstrapPending: false,
|
||||
sessionsPath: "/tmp/main.json",
|
||||
sessionsCount: 0,
|
||||
lastUpdatedAt: null,
|
||||
lastActiveAgeMs: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
channels: { rows: [], details: [] },
|
||||
summary: { ok: true },
|
||||
memory: { agentId: "main" },
|
||||
summary: buildColdStartStatusSummary(),
|
||||
memory: { agentId: "main", backend: "builtin", provider: "sqlite" },
|
||||
memoryPlugin: { enabled: true, slot: "memory-core" },
|
||||
pluginCompatibility: [{ pluginId: "legacy", message: "warn" }],
|
||||
pluginCompatibility: [
|
||||
{
|
||||
pluginId: "legacy",
|
||||
code: "legacy-before-agent-start",
|
||||
severity: "warn",
|
||||
message: "warn",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -57,7 +57,7 @@ export async function createStatusScanCoreBootstrap<TAgentStatus>(params: {
|
||||
hasConfiguredChannels: boolean;
|
||||
opts: { timeoutMs?: number; all?: boolean };
|
||||
getTailnetHostname: (
|
||||
runner: (cmd: string, args: string[]) => Promise<unknown>,
|
||||
runner: (cmd: string, args: string[]) => Promise<Awaited<ReturnType<typeof runExec>>>,
|
||||
) => Promise<string | null>;
|
||||
getUpdateCheckResult: (params: {
|
||||
timeoutMs: number;
|
||||
@@ -122,7 +122,7 @@ export async function createStatusScanBootstrap<TAgentStatus, TSummary>(params:
|
||||
hasConfiguredChannels: boolean;
|
||||
opts: { timeoutMs?: number; all?: boolean };
|
||||
getTailnetHostname: (
|
||||
runner: (cmd: string, args: string[]) => Promise<unknown>,
|
||||
runner: (cmd: string, args: string[]) => Promise<Awaited<ReturnType<typeof runExec>>>,
|
||||
) => Promise<string | null>;
|
||||
getUpdateCheckResult: (params: {
|
||||
timeoutMs: number;
|
||||
|
||||
@@ -38,7 +38,7 @@ describe("status.scan.config-shared", () => {
|
||||
it("skips read/resolve on fast-json cold-start outside tests", async () => {
|
||||
const readBestEffortConfig = vi.fn(async () => ({ channels: { telegram: {} } }));
|
||||
const resolveConfig = vi.fn(async () => ({
|
||||
resolvedConfig: { channels: { telegram: { token: "resolved" } } },
|
||||
resolvedConfig: { channels: { telegram: {} } },
|
||||
diagnostics: ["resolved"],
|
||||
}));
|
||||
|
||||
@@ -62,7 +62,7 @@ describe("status.scan.config-shared", () => {
|
||||
|
||||
it("still reads and resolves during tests even when the config path is missing", async () => {
|
||||
const sourceConfig = { channels: { telegram: {} } };
|
||||
const resolvedConfig = { channels: { telegram: { token: "resolved" } } };
|
||||
const resolvedConfig = { channels: { telegram: {} } };
|
||||
const readBestEffortConfig = vi.fn(async () => sourceConfig);
|
||||
const resolveConfig = vi.fn(async () => ({
|
||||
resolvedConfig,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { hasPotentialConfiguredChannels } from "../channels/config-presence.js";
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import type { getAgentLocalStatuses } from "./status.agent-local.js";
|
||||
import {
|
||||
resolveDefaultMemoryStorePath,
|
||||
resolveStatusMemoryStatusSnapshot,
|
||||
@@ -10,7 +12,11 @@ import {
|
||||
} from "./status.scan-overview.ts";
|
||||
import type { StatusScanResult } from "./status.scan-result.ts";
|
||||
import { buildStatusScanResult } from "./status.scan-result.ts";
|
||||
import { resolveMemoryPluginStatus } from "./status.scan.shared.js";
|
||||
import {
|
||||
type MemoryPluginStatus,
|
||||
type MemoryStatusSnapshot,
|
||||
resolveMemoryPluginStatus,
|
||||
} from "./status.scan.shared.js";
|
||||
let pluginRegistryModulePromise: Promise<typeof import("../cli/plugin-registry.js")> | undefined;
|
||||
|
||||
function loadPluginRegistryModule() {
|
||||
@@ -24,7 +30,12 @@ type StatusJsonScanPolicy = {
|
||||
resolveHasConfiguredChannels: (
|
||||
cfg: Parameters<typeof hasPotentialConfiguredChannels>[0],
|
||||
) => boolean;
|
||||
resolveMemory: Parameters<typeof scanStatusJsonCore>[0]["resolveMemory"];
|
||||
resolveMemory: (params: {
|
||||
cfg: OpenClawConfig;
|
||||
agentStatus: Awaited<ReturnType<typeof getAgentLocalStatuses>>;
|
||||
memoryPlugin: MemoryPluginStatus;
|
||||
runtime: RuntimeEnv;
|
||||
}) => Promise<MemoryStatusSnapshot | null>;
|
||||
};
|
||||
|
||||
export async function scanStatusJsonWithPolicy(
|
||||
|
||||
Reference in New Issue
Block a user