diff --git a/src/cli/daemon-cli/status.gather.test.ts b/src/cli/daemon-cli/status.gather.test.ts index 97da67108016..1096a46eb5eb 100644 --- a/src/cli/daemon-cli/status.gather.test.ts +++ b/src/cli/daemon-cli/status.gather.test.ts @@ -491,54 +491,6 @@ describe("gatherDaemonStatus", () => { expect(inspectWindowsGatewayFirewall).not.toHaveBeenCalled(); }); - it("preserves probe build identity in deep JSON output", async () => { - const status = await gatherStatus({ deep: true }); - const writeJson = vi.spyOn(defaultRuntime, "writeJson").mockImplementation(() => {}); - try { - printDaemonStatus(status, { json: true, deep: true }); - expect(writeJson).toHaveBeenCalledOnce(); - expect(writeJson.mock.calls[0]?.[0]).toMatchObject({ - rpc: { - server: { - version: "2026.5.6", - buildId: "build-2026.5.6", - connId: "conn-1", - }, - }, - }); - } finally { - writeJson.mockRestore(); - } - }); - - it("keeps deep JSON compatible when the Gateway omits build identity", async () => { - callGatewayStatusProbe.mockResolvedValueOnce({ - ok: true, - url: "ws://127.0.0.1:19001", - error: null, - server: { version: "2026.5.6", connId: "conn-1" }, - }); - - const status = await gatherStatus({ deep: true }); - const writeJson = vi.spyOn(defaultRuntime, "writeJson").mockImplementation(() => {}); - try { - printDaemonStatus(status, { json: true, deep: true }); - expect(writeJson).toHaveBeenCalledOnce(); - const serialized = JSON.stringify(writeJson.mock.calls[0]?.[0]); - if (!serialized) { - throw new Error("expected terminal JSON output"); - } - const parsed = JSON.parse(serialized) as { - rpc?: { server?: Record }; - }; - const server = parsed.rpc?.server; - expect(server).toEqual({ version: "2026.5.6", connId: "conn-1" }); - expect(server).not.toHaveProperty("buildId"); - } finally { - writeJson.mockRestore(); - } - }); - it("batches daemon and CLI port status inspection when ports differ", async () => { await gatherStatus(); diff --git a/src/cli/daemon-cli/status.print.test.ts b/src/cli/daemon-cli/status.print.test.ts index 6586b98b065f..f28495e36f53 100644 --- a/src/cli/daemon-cli/status.print.test.ts +++ b/src/cli/daemon-cli/status.print.test.ts @@ -10,6 +10,7 @@ import { printDaemonStatus } from "./status.print.js"; const runtime = vi.hoisted(() => ({ log: vi.fn<(line: string) => void>(), error: vi.fn<(line: string) => void>(), + writeJson: vi.fn<(value: unknown) => void>(), })); const resolveControlUiLinksMock = vi.hoisted(() => vi.fn((_opts?: unknown) => ({ httpUrl: "http://127.0.0.1:18789" })), @@ -100,6 +101,7 @@ describe("printDaemonStatus", () => { beforeEach(() => { runtime.log.mockReset(); runtime.error.mockReset(); + runtime.writeJson.mockReset(); renderGatewayServiceCleanupHintsMock.mockReset().mockReturnValue([]); resolveControlUiLinksMock.mockClear(); isSystemdUnavailableDetailMock.mockReset().mockReturnValue(false); @@ -107,6 +109,35 @@ describe("printDaemonStatus", () => { isWSLEnvMock.mockClear(); }); + it("preserves Gateway server metadata while sanitizing JSON output", () => { + const servers = [ + { version: "2026.5.6", buildId: "build-2026.5.6", connId: "conn-1" }, + { version: "2026.5.6", connId: "conn-1" }, + ]; + for (const server of servers) { + printDaemonStatus( + { + service: { + label: "LaunchAgent", + loaded: true, + loadedText: "loaded", + notLoadedText: "not loaded", + command: { programArguments: ["node"], environment: { OPENCLAW_STATE_DIR: "/tmp" } }, + }, + rpc: { ok: true, server }, + extraServices: [], + }, + { json: true, deep: true }, + ); + } + + expect( + runtime.writeJson.mock.calls.map( + ([payload]) => (payload as { rpc?: { server?: unknown } }).rpc?.server, + ), + ).toEqual(servers); + }); + it("prints host desktop state and auth type", () => { printDaemonStatus( {