






























@@ -100,16 +100,44 @@ describe("sendMessageSlack thread participation", () => {
100100clearSlackThreadParticipationCache();
101101const client = createSlackSendTestClient();
102102103-await sendMessageSlack("channel:C123", "hello thread", {
103+const result = await sendMessageSlack("channel:C123", "hello thread", {
104104token: "xoxb-test",
105105cfg: SLACK_TEST_CFG,
106106 client,
107107threadTs: "1712345678.123456",
108108});
109109110+expect(result.threadTs).toBe("1712345678.123456");
111+expect(result.receipt.threadId).toBe("1712345678.123456");
110112expect(hasSlackThreadParticipation("default", "C123", "1712345678.123456")).toBe(true);
111113});
112114115+it("records canonical Slack response thread participation instead of requested child thread", async () => {
116+clearSlackThreadParticipationCache();
117+const client = createSlackSendTestClient();
118+client.chat.postMessage.mockResolvedValueOnce({
119+ts: "1781932190.115869",
120+channel: "C123",
121+message: {
122+ts: "1781932190.115869",
123+thread_ts: "1781803536.235489",
124+},
125+});
126+127+const result = await sendMessageSlack("channel:C123", "hello thread", {
128+token: "xoxb-test",
129+cfg: SLACK_TEST_CFG,
130+ client,
131+threadTs: "1781932168.648159",
132+});
133+134+expect(postedMessage(client).thread_ts).toBe("1781932168.648159");
135+expect(result.threadTs).toBe("1781803536.235489");
136+expect(result.receipt.threadId).toBe("1781803536.235489");
137+expect(hasSlackThreadParticipation("default", "C123", "1781803536.235489")).toBe(true);
138+expect(hasSlackThreadParticipation("default", "C123", "1781932168.648159")).toBe(false);
139+});
140+113141it("does not record participation for unthreaded sends", async () => {
114142clearSlackThreadParticipationCache();
115143const client = createSlackSendTestClient();
@@ -174,6 +202,40 @@ describe("sendMessageSlack chunking", () => {
174202).toStrictEqual([]);
175203expect(postedTexts.join("")).toBe(message);
176204});
205+206+it("preserves the first canonical response thread across chunked sends", async () => {
207+clearSlackThreadParticipationCache();
208+const client = createSlackSendTestClient();
209+client.chat.postMessage
210+.mockResolvedValueOnce({
211+ts: "1781932190.115869",
212+channel: "C123",
213+message: {
214+ts: "1781932190.115869",
215+thread_ts: "1781803536.235489",
216+},
217+})
218+.mockResolvedValueOnce({
219+ts: "1781932191.000000",
220+channel: "C123",
221+});
222+const message = "a".repeat(8500);
223+224+const result = await sendMessageSlack("channel:C123", message, {
225+token: "xoxb-test",
226+cfg: SLACK_TEST_CFG,
227+ client,
228+threadTs: "1781932168.648159",
229+});
230+231+expect(client.chat.postMessage).toHaveBeenCalledTimes(2);
232+expect(postedMessage(client).thread_ts).toBe("1781932168.648159");
233+expect(postedMessage(client, 1).thread_ts).toBe("1781932168.648159");
234+expect(result.threadTs).toBe("1781803536.235489");
235+expect(result.receipt.threadId).toBe("1781803536.235489");
236+expect(hasSlackThreadParticipation("default", "C123", "1781803536.235489")).toBe(true);
237+expect(hasSlackThreadParticipation("default", "C123", "1781932168.648159")).toBe(false);
238+});
177239});
178240179241describe("sendMessageSlack blocks", () => {
@@ -202,6 +264,34 @@ describe("sendMessageSlack blocks", () => {
202264expect((receiptPart?.raw as Record<string, unknown> | undefined)?.channelId).toBe("C123");
203265});
204266267+it("uses canonical Slack response thread for block receipts and participation", async () => {
268+clearSlackThreadParticipationCache();
269+const client = createSlackSendTestClient();
270+client.chat.postMessage.mockResolvedValueOnce({
271+ts: "1781932190.115869",
272+channel: "C123",
273+message: {
274+ts: "1781932190.115869",
275+thread_ts: "1781803536.235489",
276+},
277+});
278+279+const result = await sendMessageSlack("channel:C123", "", {
280+token: "xoxb-test",
281+cfg: SLACK_TEST_CFG,
282+ client,
283+threadTs: "1781932168.648159",
284+blocks: [{ type: "divider" }],
285+});
286+287+expect(postedMessage(client).thread_ts).toBe("1781932168.648159");
288+expect(result.threadTs).toBe("1781803536.235489");
289+expect(result.receipt.threadId).toBe("1781803536.235489");
290+expect(result.receipt.parts[0]?.kind).toBe("card");
291+expect(hasSlackThreadParticipation("default", "C123", "1781803536.235489")).toBe(true);
292+expect(hasSlackThreadParticipation("default", "C123", "1781932168.648159")).toBe(false);
293+});
294+205295it("posts user-target block messages directly without conversations.open", async () => {
206296const client = createSlackSendTestClient();
207297client.conversations.open.mockRejectedValueOnce(new Error("missing_scope"));
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。