






















@@ -13,6 +13,7 @@ const finalizeSlackPreviewEditMock = vi.fn(async () => {});
1313const postMessageMock = vi.fn(async () => ({ ok: true, ts: "171234.999" }));
1414const chatUpdateMock = vi.fn(async () => ({ ok: true, ts: "171234.999" }));
1515const recordInboundSessionMock = vi.fn(async () => undefined);
16+const recordSlackThreadParticipationMock = vi.fn();
1617const updateLastRouteMock = vi.fn(async () => {});
1718const appendSlackStreamMock = vi.fn(async () => {});
1819const startSlackStreamMock = vi.fn(async () => ({
@@ -830,7 +831,7 @@ vi.mock("../../limits.js", () => ({
830831}));
831832832833vi.mock("../../sent-thread-cache.js", () => ({
833-recordSlackThreadParticipation: () => {},
834+recordSlackThreadParticipation: recordSlackThreadParticipationMock,
834835}));
835836836837vi.mock("../../stream-mode.js", () => ({
@@ -1228,6 +1229,7 @@ describe("dispatchPreparedSlackMessage preview fallback", () => {
12281229postMessageMock.mockClear();
12291230chatUpdateMock.mockClear();
12301231recordInboundSessionMock.mockReset();
1232+recordSlackThreadParticipationMock.mockReset();
12311233updateLastRouteMock.mockReset();
12321234appendSlackStreamMock.mockReset();
12331235startSlackStreamMock.mockReset();
@@ -3506,6 +3508,67 @@ describe("dispatchPreparedSlackMessage preview fallback", () => {
35063508expect(session.stopped).toBe(true);
35073509});
350835103511+it("routes pending native stream text through chunked sender for unexpected finalize failures", async () => {
3512+mockedNativeStreaming = true;
3513+const session = {
3514+channel: "C123",
3515+threadTs: THREAD_TS,
3516+stopped: false,
3517+delivered: false,
3518+pendingText: FINAL_REPLY_TEXT,
3519+};
3520+startSlackStreamMock.mockResolvedValueOnce(session);
3521+stopSlackStreamMock.mockRejectedValueOnce(
3522+new TestSlackStreamNotDeliveredError(
3523+FINAL_REPLY_TEXT,
3524+"method_not_supported_for_channel_type",
3525+),
3526+);
3527+3528+await dispatchPreparedSlackMessage(createPreparedSlackMessage());
3529+3530+expect(postMessageMock).not.toHaveBeenCalled();
3531+expect(deliverRepliesMock).toHaveBeenCalledTimes(1);
3532+expect(deliverRepliesMock).toHaveBeenCalledWith(
3533+expect.objectContaining({
3534+replyThreadTs: THREAD_TS,
3535+replies: [expect.objectContaining({ text: FINAL_REPLY_TEXT })],
3536+}),
3537+);
3538+expect(session.stopped).toBe(true);
3539+});
3540+3541+it("fails dispatch when an unexpected finalize fallback cannot deliver a buffered tail", async () => {
3542+mockedNativeStreaming = true;
3543+const session = {
3544+channel: "C123",
3545+threadTs: THREAD_TS,
3546+stopped: false,
3547+delivered: true,
3548+pendingText: "buffered tail",
3549+};
3550+startSlackStreamMock.mockResolvedValueOnce(session);
3551+stopSlackStreamMock.mockRejectedValueOnce(
3552+new TestSlackStreamNotDeliveredError(
3553+"buffered tail",
3554+"method_not_supported_for_channel_type",
3555+),
3556+);
3557+deliverRepliesMock.mockRejectedValueOnce(new Error("fallback send failed"));
3558+3559+await expect(dispatchPreparedSlackMessage(createPreparedSlackMessage())).rejects.toThrowError(
3560+"slack-stream not delivered: method_not_supported_for_channel_type",
3561+);
3562+3563+expectDeliverReplyCall(0, "buffered tail");
3564+expect(recordSlackThreadParticipationMock).toHaveBeenCalledWith(
3565+expect.any(String),
3566+"C123",
3567+THREAD_TS,
3568+expect.any(Object),
3569+);
3570+});
3571+35093572it("routes all pending native stream text through chunked sender when an append flush fails", async () => {
35103573mockedNativeStreaming = true;
35113574mockedDispatchSequence = [
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。