diff --git a/extensions/thread-ownership/index.test.ts b/extensions/thread-ownership/index.test.ts index 27bafe3fbc9..21f97fdce35 100644 --- a/extensions/thread-ownership/index.test.ts +++ b/extensions/thread-ownership/index.test.ts @@ -25,6 +25,7 @@ describe("thread-ownership plugin", () => { for (const key of Object.keys(hooks)) { delete hooks[key]; } + api.pluginConfig = {}; process.env.SLACK_FORWARDER_URL = "http://localhost:8750"; process.env.SLACK_BOT_USER_ID = "U999"; @@ -146,6 +147,32 @@ describe("thread-ownership plugin", () => { ); }); + it("canonicalizes configured ab-test channel allowlists before matching", async () => { + api.pluginConfig = { abTestChannels: ["channel:C123"] }; + register.register(api as unknown as OpenClawPluginApi); + vi.mocked(globalThis.fetch).mockResolvedValue( + new Response(JSON.stringify({ owner: "test-agent" }), { status: 200 }), + ); + + const result = await hooks.message_sending( + { + content: "hello", + replyToId: "1234.5678", + to: "channel:C123", + }, + { channelId: "slack", conversationId: "" }, + ); + + expect(result).toBeUndefined(); + expect(globalThis.fetch).toHaveBeenCalledWith( + "http://localhost:8750/api/v1/ownership/C123/1234.5678", + expect.objectContaining({ + method: "POST", + body: JSON.stringify({ agent_id: "test-agent" }), + }), + ); + }); + it("cancels when thread owned by another agent", async () => { vi.mocked(globalThis.fetch).mockResolvedValue( new Response(JSON.stringify({ owner: "other-agent" }), { status: 409 }), diff --git a/extensions/thread-ownership/index.ts b/extensions/thread-ownership/index.ts index ab75ed22992..1efa59ed9c7 100644 --- a/extensions/thread-ownership/index.ts +++ b/extensions/thread-ownership/index.ts @@ -72,9 +72,13 @@ export default definePluginEntry({ ).replace(/\/$/, ""); const abTestChannels = new Set( - pluginCfg.abTestChannels ?? + ( + pluginCfg.abTestChannels ?? process.env.THREAD_OWNERSHIP_CHANNELS?.split(",").filter(Boolean) ?? - [], + [] + ) + .map((entry) => resolveSlackConversationId(entry)) + .filter(Boolean), ); const { id: agentId, name: agentName } = resolveOwnershipAgent(api.config);