diff --git a/src/auto-reply/reply/commands-diagnostics.test.ts b/src/auto-reply/reply/commands-diagnostics.test.ts index 0bc65611664..2fe20a74838 100644 --- a/src/auto-reply/reply/commands-diagnostics.test.ts +++ b/src/auto-reply/reply/commands-diagnostics.test.ts @@ -13,6 +13,54 @@ type ExecCall = { params: unknown; }; +type ExecDefaults = { + accountId?: string; + approvalFollowup?: () => Promise; + approvalFollowupMode?: string; + approvalFollowupText?: string; + approvalWarningText?: string; + ask?: string; + currentChannelId?: string; + host?: string; + messageProvider?: string; + security?: string; + trigger?: string; +}; + +type ExecParams = { + ask?: string; + command?: string; + security?: string; +}; + +type DiagnosticsSession = { + accountId?: string; + agentHarnessId?: string; + channel?: string; + sessionFile?: string; + sessionId?: string; + sessionKey?: string; +}; + +function requireExecCall(execCalls: ExecCall[], index = 0) { + const call = execCalls[index]; + if (!call) { + throw new Error(`expected exec call #${index + 1}`); + } + return { + defaults: call.defaults as ExecDefaults, + params: call.params as ExecParams, + }; +} + +function requireDiagnosticsSessions(call: PluginCommandContext | undefined) { + const sessions = call?.diagnosticsSessions as DiagnosticsSession[] | undefined; + if (!sessions) { + throw new Error("expected diagnostics sessions"); + } + return sessions; +} + function buildDiagnosticsParams( commandBodyNormalized: string, overrides: Partial = {}, @@ -241,24 +289,21 @@ describe("diagnostics command", () => { expect(result?.shouldContinue).toBe(false); expect(result?.reply).toBeUndefined(); expect(execCalls).toHaveLength(1); - expect(execCalls[0]?.defaults).toMatchObject({ - host: "gateway", - security: "allowlist", - ask: "always", - trigger: "diagnostics", - approvalFollowupMode: "direct", - approvalWarningText: expect.stringContaining( - "Diagnostics can include sensitive local logs and host-level runtime metadata.", - ), - }); - expect( - String((execCalls[0]?.defaults as { approvalWarningText?: string }).approvalWarningText), - ).toContain("https://docs.openclaw.ai/gateway/diagnostics"); - expect(execCalls[0]?.params).toMatchObject({ - security: "allowlist", - ask: "always", - }); - const command = (execCalls[0]?.params as { command?: string }).command ?? ""; + const execCall = requireExecCall(execCalls); + expect(execCall.defaults.host).toBe("gateway"); + expect(execCall.defaults.security).toBe("allowlist"); + expect(execCall.defaults.ask).toBe("always"); + expect(execCall.defaults.trigger).toBe("diagnostics"); + expect(execCall.defaults.approvalFollowupMode).toBe("direct"); + expect(execCall.defaults.approvalWarningText).toContain( + "Diagnostics can include sensitive local logs and host-level runtime metadata.", + ); + expect(execCall.defaults.approvalWarningText).toContain( + "https://docs.openclaw.ai/gateway/diagnostics", + ); + expect(execCall.params.security).toBe("allowlist"); + expect(execCall.params.ask).toBe("always"); + const command = execCall.params.command ?? ""; expect(command).toContain("gateway"); expect(command).toContain("diagnostics"); expect(command).toContain("export"); @@ -298,11 +343,10 @@ describe("diagnostics command", () => { await handleDiagnosticsCommand(params, true); expect(execCalls).toHaveLength(1); - expect(execCalls[0]?.defaults).toMatchObject({ - messageProvider: "telegram", - currentChannelId: "telegram:8460800771", - accountId: "account-1", - }); + const execCall = requireExecCall(execCalls); + expect(execCall.defaults.messageProvider).toBe("telegram"); + expect(execCall.defaults.currentChannelId).toBe("telegram:8460800771"); + expect(execCall.defaults.accountId).toBe("account-1"); }); it("falls back to a visible reply when approval cannot be queued", async () => { @@ -353,20 +397,14 @@ describe("diagnostics command", () => { expect(calls[0]?.diagnosticsPreviewOnly).toBe(true); expect(calls[0]?.senderIsOwner).toBe(true); expect(calls[0]?.sessionFile).toBe("/tmp/session.jsonl"); - expect(calls[0]?.diagnosticsSessions).toEqual([ - expect.objectContaining({ - agentHarnessId: "codex", - sessionId: "session-1", - sessionFile: "/tmp/session.jsonl", - channel: "whatsapp", - accountId: "account-1", - }), - ]); - const defaults = execCalls[0]?.defaults as { - approvalWarningText?: string; - approvalFollowupText?: string; - approvalFollowup?: () => Promise; - }; + const diagnosticsSessions = requireDiagnosticsSessions(calls[0]); + expect(diagnosticsSessions).toHaveLength(1); + expect(diagnosticsSessions[0]?.agentHarnessId).toBe("codex"); + expect(diagnosticsSessions[0]?.sessionId).toBe("session-1"); + expect(diagnosticsSessions[0]?.sessionFile).toBe("/tmp/session.jsonl"); + expect(diagnosticsSessions[0]?.channel).toBe("whatsapp"); + expect(diagnosticsSessions[0]?.accountId).toBe("account-1"); + const { defaults } = requireExecCall(execCalls); expect(defaults.approvalWarningText).toContain("OpenAI Codex harness:"); expect(defaults.approvalWarningText).toContain( "Approving diagnostics will also send this thread's feedback bundle to OpenAI servers.", @@ -413,23 +451,19 @@ describe("diagnostics command", () => { expect(result?.shouldContinue).toBe(false); expect(result?.reply).toBeUndefined(); expect(calls).toHaveLength(1); - expect(calls[0]?.diagnosticsSessions).toEqual([ - expect.objectContaining({ - sessionKey: "agent:main:telegram:direct:user-1", - sessionId: "telegram-session", - sessionFile: "/tmp/telegram.jsonl", - channel: "whatsapp", - }), - expect.objectContaining({ - sessionKey: "agent:main:discord:channel:123", - sessionId: "discord-session", - sessionFile: "/tmp/discord.jsonl", - channel: "discord", - }), - ]); - expect( - (execCalls[0]?.defaults as { approvalWarningText?: string }).approvalWarningText, - ).toContain("OpenAI Codex harness:"); + const diagnosticsSessions = requireDiagnosticsSessions(calls[0]); + expect(diagnosticsSessions).toHaveLength(2); + expect(diagnosticsSessions[0]?.sessionKey).toBe("agent:main:telegram:direct:user-1"); + expect(diagnosticsSessions[0]?.sessionId).toBe("telegram-session"); + expect(diagnosticsSessions[0]?.sessionFile).toBe("/tmp/telegram.jsonl"); + expect(diagnosticsSessions[0]?.channel).toBe("whatsapp"); + expect(diagnosticsSessions[1]?.sessionKey).toBe("agent:main:discord:channel:123"); + expect(diagnosticsSessions[1]?.sessionId).toBe("discord-session"); + expect(diagnosticsSessions[1]?.sessionFile).toBe("/tmp/discord.jsonl"); + expect(diagnosticsSessions[1]?.channel).toBe("discord"); + expect(requireExecCall(execCalls).defaults.approvalWarningText).toContain( + "OpenAI Codex harness:", + ); }); it("omits the Codex section for ordinary sessions without Codex targets", async () => { @@ -458,9 +492,9 @@ describe("diagnostics command", () => { true, ); - expect( - (execCalls[0]?.defaults as { approvalWarningText?: string }).approvalWarningText, - ).not.toContain("OpenAI Codex harness:"); + expect(requireExecCall(execCalls).defaults.approvalWarningText).not.toContain( + "OpenAI Codex harness:", + ); }); it("routes group diagnostics details privately before starting collection", async () => { @@ -494,17 +528,14 @@ describe("diagnostics command", () => { expect(result?.reply?.text).not.toContain("codex-thread-1"); expect(privateReplies).toHaveLength(0); expect(execCalls).toHaveLength(1); - expect(execCalls[0]?.defaults).toMatchObject({ - messageProvider: "telegram", - currentChannelId: "owner-dm", - accountId: "account-1", - }); - expect( - (execCalls[0]?.defaults as { approvalWarningText?: string }).approvalWarningText, - ).toContain("Approving diagnostics will also send this thread's feedback bundle"); - expect( - (execCalls[0]?.defaults as { approvalWarningText?: string }).approvalWarningText, - ).not.toContain("To send:"); + const { defaults } = requireExecCall(execCalls); + expect(defaults.messageProvider).toBe("telegram"); + expect(defaults.currentChannelId).toBe("owner-dm"); + expect(defaults.accountId).toBe("account-1"); + expect(defaults.approvalWarningText).toContain( + "Approving diagnostics will also send this thread's feedback bundle", + ); + expect(defaults.approvalWarningText).not.toContain("To send:"); expect(calls[0]?.diagnosticsPrivateRouted).toBe(true); });