From d625f888a9f51eaaeb9fd816160e47409c9e2720 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 22 Feb 2026 08:54:06 +0000 Subject: [PATCH] test(core): dedupe command gating and trim announce reset overhead --- .../subagent-announce.format.e2e.test.ts | 4 +- src/auto-reply/reply/commands.test.ts | 138 +++++++++++------- 2 files changed, 88 insertions(+), 54 deletions(-) diff --git a/src/agents/subagent-announce.format.e2e.test.ts b/src/agents/subagent-announce.format.e2e.test.ts index 0982cbc237f..ab13b9dcb8e 100644 --- a/src/agents/subagent-announce.format.e2e.test.ts +++ b/src/agents/subagent-announce.format.e2e.test.ts @@ -143,10 +143,10 @@ vi.mock("../config/config.js", async (importOriginal) => { describe("subagent announce formatting", () => { beforeEach(() => { agentSpy - .mockReset() + .mockClear() .mockImplementation(async (_req: AgentCallRequest) => ({ runId: "run-main", status: "ok" })); sendSpy - .mockReset() + .mockClear() .mockImplementation(async (_req: AgentCallRequest) => ({ runId: "send-main", status: "ok" })); sessionsDeleteSpy.mockClear().mockImplementation((_req: AgentCallRequest) => undefined); embeddedRunMock.isEmbeddedPiRunActive.mockReset().mockReturnValue(false); diff --git a/src/auto-reply/reply/commands.test.ts b/src/auto-reply/reply/commands.test.ts index 9999dec880f..c0b9d4524db 100644 --- a/src/auto-reply/reply/commands.test.ts +++ b/src/auto-reply/reply/commands.test.ts @@ -137,28 +137,32 @@ function buildParams(commandBody: string, cfg: OpenClawConfig, ctxOverrides?: Pa } describe("handleCommands gating", () => { - it("blocks /bash when disabled or not elevated-allowlisted", async () => { - resetBashChatCommandForTests(); + it("blocks gated commands when disabled or not elevated-allowlisted", async () => { const cases = typedCases<{ name: string; - cfg: OpenClawConfig; + commandBody: string; + makeCfg: () => OpenClawConfig; applyParams?: (params: ReturnType) => void; expectedText: string; }>([ { name: "disabled bash command", - cfg: { - commands: { bash: false, text: true }, - whatsapp: { allowFrom: ["*"] }, - } as OpenClawConfig, + commandBody: "/bash echo hi", + makeCfg: () => + ({ + commands: { bash: false, text: true }, + whatsapp: { allowFrom: ["*"] }, + }) as OpenClawConfig, expectedText: "bash is disabled", }, { name: "missing elevated allowlist", - cfg: { - commands: { bash: true, text: true }, - whatsapp: { allowFrom: ["*"] }, - } as OpenClawConfig, + commandBody: "/bash echo hi", + makeCfg: () => + ({ + commands: { bash: true, text: true }, + whatsapp: { allowFrom: ["*"] }, + }) as OpenClawConfig, applyParams: (params: ReturnType) => { params.elevated = { enabled: true, @@ -168,55 +172,85 @@ describe("handleCommands gating", () => { }, expectedText: "elevated is not available", }, + { + name: "disabled config command", + commandBody: "/config show", + makeCfg: () => + ({ + commands: { config: false, debug: false, text: true }, + channels: { whatsapp: { allowFrom: ["*"] } }, + }) as OpenClawConfig, + expectedText: "/config is disabled", + }, + { + name: "disabled debug command", + commandBody: "/debug show", + makeCfg: () => + ({ + commands: { config: false, debug: false, text: true }, + channels: { whatsapp: { allowFrom: ["*"] } }, + }) as OpenClawConfig, + expectedText: "/debug is disabled", + }, + { + name: "inherited bash flag does not enable command", + commandBody: "/bash echo hi", + makeCfg: () => { + const inheritedCommands = Object.create({ + bash: true, + config: true, + debug: true, + }) as Record; + return { + commands: inheritedCommands as never, + channels: { whatsapp: { allowFrom: ["*"] } }, + } as OpenClawConfig; + }, + expectedText: "bash is disabled", + }, + { + name: "inherited config flag does not enable command", + commandBody: "/config show", + makeCfg: () => { + const inheritedCommands = Object.create({ + bash: true, + config: true, + debug: true, + }) as Record; + return { + commands: inheritedCommands as never, + channels: { whatsapp: { allowFrom: ["*"] } }, + } as OpenClawConfig; + }, + expectedText: "/config is disabled", + }, + { + name: "inherited debug flag does not enable command", + commandBody: "/debug show", + makeCfg: () => { + const inheritedCommands = Object.create({ + bash: true, + config: true, + debug: true, + }) as Record; + return { + commands: inheritedCommands as never, + channels: { whatsapp: { allowFrom: ["*"] } }, + } as OpenClawConfig; + }, + expectedText: "/debug is disabled", + }, ]); + for (const testCase of cases) { - const params = buildParams("/bash echo hi", testCase.cfg); + resetBashChatCommandForTests(); + const params = buildParams(testCase.commandBody, testCase.makeCfg()); testCase.applyParams?.(params); const result = await handleCommands(params); expect(result.shouldContinue, testCase.name).toBe(false); expect(result.reply?.text, testCase.name).toContain(testCase.expectedText); } }); - - it("blocks /config and /debug when disabled", async () => { - const cfg = { - commands: { config: false, debug: false, text: true }, - channels: { whatsapp: { allowFrom: ["*"] } }, - } as OpenClawConfig; - const cases = [ - { commandBody: "/config show", expectedText: "/config is disabled" }, - { commandBody: "/debug show", expectedText: "/debug is disabled" }, - ] as const; - for (const testCase of cases) { - const params = buildParams(testCase.commandBody, cfg); - const result = await handleCommands(params); - expect(result.shouldContinue).toBe(false); - expect(result.reply?.text).toContain(testCase.expectedText); - } - }); - - it("does not enable gated commands from inherited command flags", async () => { - const inheritedCommands = Object.create({ - bash: true, - config: true, - debug: true, - }) as Record; - const cfg = { - commands: inheritedCommands as never, - channels: { whatsapp: { allowFrom: ["*"] } }, - } as OpenClawConfig; - - const cases = [ - { commandBody: "/bash echo hi", expectedText: "bash is disabled" }, - { commandBody: "/config show", expectedText: "/config is disabled" }, - { commandBody: "/debug show", expectedText: "/debug is disabled" }, - ] as const; - for (const testCase of cases) { - const result = await handleCommands(buildParams(testCase.commandBody, cfg)); - expect(result.shouldContinue, testCase.commandBody).toBe(false); - expect(result.reply?.text, testCase.commandBody).toContain(testCase.expectedText); - } - }); }); describe("/approve command", () => {