From 9b95d65ea26fead2fb751e18821bd81774718228 Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Fri, 10 Apr 2026 19:48:25 -0500 Subject: [PATCH] fix: use target agent for bash wrapper --- .../reply/commands-bash-alias.test.ts | 22 +++++++++++++++++++ src/auto-reply/reply/commands-bash.ts | 6 ++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/auto-reply/reply/commands-bash-alias.test.ts b/src/auto-reply/reply/commands-bash-alias.test.ts index 6ca5efe81ec..bc9ef9b362e 100644 --- a/src/auto-reply/reply/commands-bash-alias.test.ts +++ b/src/auto-reply/reply/commands-bash-alias.test.ts @@ -3,10 +3,15 @@ import type { OpenClawConfig } from "../../config/config.js"; import { handleBashCommand } from "./commands-bash.js"; import type { HandleCommandsParams } from "./commands-types.js"; +const resolveSessionAgentIdMock = vi.hoisted(() => vi.fn(() => "main")); const handleBashChatCommandMock = vi.hoisted(() => vi.fn(async () => ({ text: "No active bash job" })), ); +vi.mock("../../agents/agent-scope.js", () => ({ + resolveSessionAgentId: resolveSessionAgentIdMock, +})); + vi.mock("./bash-command.js", () => ({ handleBashChatCommand: handleBashChatCommandMock, })); @@ -44,6 +49,7 @@ function buildBashParams(commandBodyNormalized: string): HandleCommandsParams { describe("handleBashCommand alias routing", () => { beforeEach(() => { vi.clearAllMocks(); + resolveSessionAgentIdMock.mockReturnValue("target"); }); it("routes !poll and !stop through the bash chat handler", async () => { @@ -54,4 +60,20 @@ describe("handleBashCommand alias routing", () => { } expect(handleBashChatCommandMock).toHaveBeenCalledTimes(2); }); + + it("uses the canonical target session agent for /bash routing", async () => { + const params = buildBashParams("/bash pwd"); + params.agentId = "main"; + params.sessionKey = "agent:target:whatsapp:direct:test-user"; + + const result = await handleBashCommand(params, true); + + expect(result?.shouldContinue).toBe(false); + expect(handleBashChatCommandMock).toHaveBeenCalledWith( + expect.objectContaining({ + agentId: "target", + sessionKey: "agent:target:whatsapp:direct:test-user", + }), + ); + }); }); diff --git a/src/auto-reply/reply/commands-bash.ts b/src/auto-reply/reply/commands-bash.ts index 83a0e8d19b4..90d5d68733b 100644 --- a/src/auto-reply/reply/commands-bash.ts +++ b/src/auto-reply/reply/commands-bash.ts @@ -1,3 +1,4 @@ +import { resolveSessionAgentId } from "../../agents/agent-scope.js"; import { handleBashChatCommand } from "./bash-command.js"; import { rejectUnauthorizedCommand } from "./command-gates.js"; import type { CommandHandler } from "./commands-types.js"; @@ -17,10 +18,13 @@ export const handleBashCommand: CommandHandler = async (params, allowTextCommand if (unauthorized) { return unauthorized; } + const agentId = params.sessionKey + ? resolveSessionAgentId({ sessionKey: params.sessionKey, config: params.cfg }) + : params.agentId; const reply = await handleBashChatCommand({ ctx: params.ctx, cfg: params.cfg, - agentId: params.agentId, + agentId, sessionKey: params.sessionKey, isGroup: params.isGroup, elevated: params.elevated,