fix(cli): suppress systemd hints for live gateway (#85336)

* fix(cli): suppress systemd hints for live gateway

* test(cli): type systemd hint mock
This commit is contained in:
Peter Steinberger
2026-05-22 13:52:21 +01:00
committed by GitHub
parent fc47c1f55e
commit a00c58363a
3 changed files with 49 additions and 3 deletions

View File

@@ -9,6 +9,8 @@ const runtime = vi.hoisted(() => ({
const resolveControlUiLinksMock = vi.hoisted(() =>
vi.fn((_opts?: unknown) => ({ httpUrl: "http://127.0.0.1:18789" })),
);
const isSystemdUnavailableDetailMock = vi.hoisted(() => vi.fn(() => false));
const renderSystemdUnavailableHintsMock = vi.hoisted(() => vi.fn<() => string[]>(() => []));
vi.mock("../../runtime.js", () => ({
defaultRuntime: runtime,
@@ -46,8 +48,8 @@ vi.mock("../../daemon/restart-logs.js", () => ({
}));
vi.mock("../../daemon/systemd-hints.js", () => ({
isSystemdUnavailableDetail: () => false,
renderSystemdUnavailableHints: () => [],
isSystemdUnavailableDetail: isSystemdUnavailableDetailMock,
renderSystemdUnavailableHints: renderSystemdUnavailableHintsMock,
}));
vi.mock("../../infra/wsl.js", () => ({
@@ -87,6 +89,8 @@ describe("printDaemonStatus", () => {
runtime.log.mockReset();
runtime.error.mockReset();
resolveControlUiLinksMock.mockClear();
isSystemdUnavailableDetailMock.mockReset().mockReturnValue(false);
renderSystemdUnavailableHintsMock.mockReset().mockReturnValue([]);
});
it("prints stale gateway pid guidance when runtime does not own the listener", () => {
@@ -506,4 +510,43 @@ describe("printDaemonStatus", () => {
expectMockLineContains(runtime.log, "ai.openclaw.gateway.rescue");
expect(runtime.error).not.toHaveBeenCalled();
});
it("does not print systemd user-service hints when a gateway responds", () => {
const platform = vi.spyOn(process, "platform", "get").mockReturnValue("linux");
isSystemdUnavailableDetailMock.mockReturnValue(true);
renderSystemdUnavailableHintsMock.mockReturnValue(["run loginctl enable-linger"]);
try {
printDaemonStatus(
{
service: {
label: "systemd user",
loaded: false,
loadedText: "not loaded",
notLoadedText: "not loaded",
runtime: { status: "unknown", detail: "systemd user services unavailable" },
},
rpc: {
ok: true,
url: "ws://127.0.0.1:18789",
server: { version: "2026.5.12" },
},
port: {
port: 18789,
status: "busy",
listeners: [],
hints: [],
},
extraServices: [],
},
{ json: false },
);
} finally {
platform.mockRestore();
}
const errors = runtime.error.mock.calls.map(([line]) => line).join("\n");
expect(errors).not.toContain("systemd user services unavailable");
expect(errors).not.toContain("run loginctl enable-linger");
});
});

View File

@@ -320,7 +320,9 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
}
const systemdUnavailable =
process.platform === "linux" && isSystemdUnavailableDetail(service.runtime?.detail);
process.platform === "linux" &&
rpc?.ok !== true &&
isSystemdUnavailableDetail(service.runtime?.detail);
if (systemdUnavailable) {
const container = Boolean(
resolveDaemonContainerContext(service.command?.environment ?? process.env),