fix(slack): keep thread session fork/history context after first turn (#23843)

* Slack thread sessions: keep forking and history context after first turn

* Update CHANGELOG.md
This commit is contained in:
Vincent Koc
2026-02-22 14:39:00 -05:00
committed by GitHub
parent 02772b029d
commit 5e73f33448
8 changed files with 120 additions and 14 deletions

View File

@@ -324,7 +324,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
expect(replies).toHaveBeenCalledTimes(2);
});
it("does not mark first thread turn when thread session already exists in store", async () => {
it("keeps loading thread history when thread session already exists in store", async () => {
const { storePath } = makeTmpStorePath();
const cfg = {
session: { store: storePath },
@@ -346,9 +346,19 @@ describe("slack prepareSlackMessage inbound contract", () => {
JSON.stringify({ [threadKeys.sessionKey]: { updatedAt: Date.now() } }, null, 2),
);
const replies = vi.fn().mockResolvedValue({
messages: [{ text: "starter", user: "U2", ts: "200.000" }],
});
const replies = vi
.fn()
.mockResolvedValueOnce({
messages: [{ text: "starter", user: "U2", ts: "200.000" }],
})
.mockResolvedValueOnce({
messages: [
{ text: "starter", user: "U2", ts: "200.000" },
{ text: "assistant follow-up", bot_id: "B1", ts: "200.500" },
{ text: "user follow-up", user: "U1", ts: "200.800" },
{ text: "current message", user: "U1", ts: "201.000" },
],
});
const slackCtx = createThreadSlackCtx({ cfg, replies });
slackCtx.resolveUserName = async () => ({ name: "Alice" });
slackCtx.resolveChannelName = async () => ({ name: "general", type: "channel" });
@@ -361,7 +371,10 @@ describe("slack prepareSlackMessage inbound contract", () => {
expect(prepared).toBeTruthy();
expect(prepared!.ctxPayload.IsFirstThreadTurn).toBeUndefined();
expect(prepared!.ctxPayload.ThreadHistoryBody).toBeUndefined();
expect(prepared!.ctxPayload.ThreadHistoryBody).toContain("assistant follow-up");
expect(prepared!.ctxPayload.ThreadHistoryBody).toContain("user follow-up");
expect(prepared!.ctxPayload.ThreadHistoryBody).not.toContain("current message");
expect(replies).toHaveBeenCalledTimes(2);
});
it("includes thread_ts and parent_user_id metadata in thread replies", async () => {

View File

@@ -521,7 +521,7 @@ export async function prepareSlackMessage(params: {
storePath,
sessionKey, // Thread-specific session key
});
if (threadInitialHistoryLimit > 0 && !threadSessionPreviousTimestamp) {
if (threadInitialHistoryLimit > 0) {
const threadHistory = await resolveSlackThreadHistory({
channelId: message.channel,
threadTs,