fix: honor slack reply threading

This commit is contained in:
Mauro Bolis
2026-01-09 14:59:36 +01:00
committed by Peter Steinberger
parent 014a4d51a6
commit 96149d1f71
7 changed files with 145 additions and 9 deletions

View File

@@ -283,6 +283,17 @@ describe("monitorSlackProvider tool results", () => {
it("threads replies when incoming message is in a thread", async () => {
replyMock.mockResolvedValue({ text: "thread reply" });
config = {
messages: {
responsePrefix: "PFX",
ackReaction: "👀",
ackReactionScope: "group-mentions",
},
slack: {
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
replyToMode: "first",
},
};
const controller = new AbortController();
const run = monitorSlackProvider({
@@ -315,6 +326,50 @@ describe("monitorSlackProvider tool results", () => {
expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "456" });
});
it("threads top-level replies when replyToMode is all", async () => {
replyMock.mockResolvedValue({ text: "thread reply" });
config = {
messages: {
responsePrefix: "PFX",
ackReaction: "👀",
ackReactionScope: "group-mentions",
},
slack: {
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
replyToMode: "all",
},
};
const controller = new AbortController();
const run = monitorSlackProvider({
botToken: "bot-token",
appToken: "app-token",
abortSignal: controller.signal,
});
await waitForEvent("message");
const handler = getSlackHandlers()?.get("message");
if (!handler) throw new Error("Slack message handler not registered");
await handler({
event: {
type: "message",
user: "U1",
text: "hello",
ts: "123",
channel: "C1",
channel_type: "im",
},
});
await flush();
controller.abort();
await run;
expect(sendMock).toHaveBeenCalledTimes(1);
expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "123" });
});
it("treats parent_user_id as a thread reply even when thread_ts matches ts", async () => {
replyMock.mockResolvedValue({ text: "thread reply" });
@@ -484,6 +539,17 @@ describe("monitorSlackProvider tool results", () => {
it("keeps replies in channel root when message is not threaded", async () => {
replyMock.mockResolvedValue({ text: "root reply" });
config = {
messages: {
responsePrefix: "PFX",
ackReaction: "👀",
ackReactionScope: "group-mentions",
},
slack: {
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
replyToMode: "first",
},
};
const controller = new AbortController();
const run = monitorSlackProvider({
@@ -515,6 +581,50 @@ describe("monitorSlackProvider tool results", () => {
expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: undefined });
});
it("forces thread replies when replyToId is set", async () => {
replyMock.mockResolvedValue({ text: "forced reply", replyToId: "555" });
config = {
messages: {
responsePrefix: "PFX",
ackReaction: "👀",
ackReactionScope: "group-mentions",
},
slack: {
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
replyToMode: "off",
},
};
const controller = new AbortController();
const run = monitorSlackProvider({
botToken: "bot-token",
appToken: "app-token",
abortSignal: controller.signal,
});
await waitForEvent("message");
const handler = getSlackHandlers()?.get("message");
if (!handler) throw new Error("Slack message handler not registered");
await handler({
event: {
type: "message",
user: "U1",
text: "hello",
ts: "789",
channel: "C1",
channel_type: "im",
},
});
await flush();
controller.abort();
await run;
expect(sendMock).toHaveBeenCalledTimes(1);
expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "555" });
});
it("reacts to mention-gated room messages when ackReaction is enabled", async () => {
replyMock.mockResolvedValue(undefined);
const client = getSlackClient();