mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 19:35:28 -06:00
4a285d529a
Surface active official external plugin version drift in gateway status diagnostics so users can see when a host/package update left npm or ClawHub plugins behind the running local gateway. The advisory uses the daemon service install records, compares against the running gateway version, gives detailed fix commands in deep status, and avoids local-state drift checks for remote gateway mode or explicit status probe URLs. Co-authored-by: Hussein Nourelddine <hussein@gptc.com.kw>
115 lines
2.8 KiB
TypeScript
115 lines
2.8 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { createCliRuntimeCapture } from "../test-runtime-capture.js";
|
|
import type { DaemonStatus } from "./status.gather.js";
|
|
|
|
const gatherDaemonStatus = vi.fn(
|
|
async (_opts?: unknown): Promise<DaemonStatus> => ({
|
|
service: {
|
|
label: "LaunchAgent",
|
|
loaded: true,
|
|
loadedText: "loaded",
|
|
notLoadedText: "not loaded",
|
|
},
|
|
rpc: {
|
|
ok: true,
|
|
url: "ws://127.0.0.1:18789",
|
|
},
|
|
extraServices: [],
|
|
}),
|
|
);
|
|
const printDaemonStatus = vi.fn();
|
|
|
|
const { runtimeErrors, defaultRuntime, resetRuntimeCapture } = createCliRuntimeCapture();
|
|
|
|
vi.mock("../../runtime.js", () => ({
|
|
defaultRuntime,
|
|
}));
|
|
|
|
vi.mock("../../../packages/terminal-core/src/theme.js", () => ({
|
|
colorize: (_rich: boolean, _color: unknown, text: string) => text,
|
|
isRich: () => false,
|
|
theme: { error: "error" },
|
|
}));
|
|
|
|
vi.mock("./status.gather.js", () => ({
|
|
gatherDaemonStatus: (opts: unknown) => gatherDaemonStatus(opts),
|
|
}));
|
|
|
|
vi.mock("./status.print.js", () => ({
|
|
printDaemonStatus: (...args: unknown[]) => printDaemonStatus(...args),
|
|
}));
|
|
|
|
const { runDaemonStatus } = await import("./status.js");
|
|
|
|
describe("runDaemonStatus", () => {
|
|
beforeEach(() => {
|
|
gatherDaemonStatus.mockClear();
|
|
printDaemonStatus.mockClear();
|
|
resetRuntimeCapture();
|
|
});
|
|
|
|
it("exits when require-rpc is set and the probe fails", async () => {
|
|
gatherDaemonStatus.mockResolvedValueOnce({
|
|
service: {
|
|
label: "LaunchAgent",
|
|
loaded: true,
|
|
loadedText: "loaded",
|
|
notLoadedText: "not loaded",
|
|
},
|
|
rpc: {
|
|
ok: false,
|
|
url: "ws://127.0.0.1:18789",
|
|
error: "gateway closed",
|
|
},
|
|
extraServices: [],
|
|
});
|
|
|
|
await expect(
|
|
runDaemonStatus({
|
|
rpc: {},
|
|
probe: true,
|
|
requireRpc: true,
|
|
json: false,
|
|
}),
|
|
).rejects.toThrow("__exit__:1");
|
|
|
|
expect(printDaemonStatus).toHaveBeenCalledTimes(1);
|
|
expect(printDaemonStatus).toHaveBeenCalledWith(expect.any(Object), {
|
|
json: false,
|
|
deep: false,
|
|
});
|
|
});
|
|
|
|
it("forwards require-rpc to daemon status gathering", async () => {
|
|
await runDaemonStatus({
|
|
rpc: {},
|
|
probe: true,
|
|
requireRpc: true,
|
|
json: false,
|
|
});
|
|
|
|
expect(gatherDaemonStatus).toHaveBeenCalledWith({
|
|
rpc: {},
|
|
probe: true,
|
|
requireRpc: true,
|
|
deep: false,
|
|
});
|
|
});
|
|
|
|
it("rejects require-rpc when probing is disabled", async () => {
|
|
await expect(
|
|
runDaemonStatus({
|
|
rpc: {},
|
|
probe: false,
|
|
requireRpc: true,
|
|
json: false,
|
|
}),
|
|
).rejects.toThrow("__exit__:1");
|
|
|
|
expect(gatherDaemonStatus).not.toHaveBeenCalled();
|
|
expect(runtimeErrors[0]).toBe(
|
|
"Gateway status failed: --require-rpc needs probing enabled. Remove --no-probe or drop --require-rpc.",
|
|
);
|
|
});
|
|
});
|