






























@@ -409,7 +409,7 @@ describe("dispatchPreparedSlackMessage preview fallback", () => {
409409expect(deliverRepliesMock).toHaveBeenCalledTimes(1);
410410});
411411412-it("posts pending native stream text when finalize fails before the SDK buffer flushes", async () => {
412+it("routes pending native stream text through chunked sender when finalize fails before the SDK buffer flushes", async () => {
413413mockedNativeStreaming = true;
414414const session = {
415415channel: "C123",
@@ -425,17 +425,18 @@ describe("dispatchPreparedSlackMessage preview fallback", () => {
425425426426await dispatchPreparedSlackMessage(createPreparedSlackMessage());
427427428-expect(deliverRepliesMock).not.toHaveBeenCalled();
429-expect(postMessageMock).toHaveBeenCalledTimes(1);
430-expect(postMessageMock).toHaveBeenCalledWith({
431-channel: "C123",
432-thread_ts: THREAD_TS,
433-text: FINAL_REPLY_TEXT,
434-});
428+expect(postMessageMock).not.toHaveBeenCalled();
429+expect(deliverRepliesMock).toHaveBeenCalledTimes(1);
430+expect(deliverRepliesMock).toHaveBeenCalledWith(
431+expect.objectContaining({
432+replyThreadTs: THREAD_TS,
433+replies: [expect.objectContaining({ text: FINAL_REPLY_TEXT })],
434+}),
435+);
435436expect(session.stopped).toBe(true);
436437});
437438438-it("posts all pending native stream text when an append flush fails", async () => {
439+it("routes all pending native stream text through chunked sender when an append flush fails", async () => {
439440mockedNativeStreaming = true;
440441mockedDispatchSequence = [
441442{ kind: "block", payload: { text: "first buffered" } },
@@ -456,13 +457,87 @@ describe("dispatchPreparedSlackMessage preview fallback", () => {
456457457458await dispatchPreparedSlackMessage(createPreparedSlackMessage());
458459459-expect(deliverRepliesMock).not.toHaveBeenCalled();
460-expect(postMessageMock).toHaveBeenCalledTimes(1);
461-expect(postMessageMock).toHaveBeenCalledWith({
460+expect(postMessageMock).not.toHaveBeenCalled();
461+expect(deliverRepliesMock).toHaveBeenCalledTimes(1);
462+expect(deliverRepliesMock).toHaveBeenCalledWith(
463+expect.objectContaining({
464+replyThreadTs: THREAD_TS,
465+replies: [expect.objectContaining({ text: "first buffered\nsecond flushes" })],
466+}),
467+);
468+expect(stopSlackStreamMock).not.toHaveBeenCalled();
469+});
470+471+it("forwards oversized pending stream text to the chunked sender intact (chunking is the sender's responsibility)", async () => {
472+mockedNativeStreaming = true;
473+// SLACK_TEXT_LIMIT mocks to 4000; use > 1 message worth of content.
474+const oversized = "x".repeat(8500);
475+const session = {
462476channel: "C123",
463-thread_ts: THREAD_TS,
464-text: "first buffered\nsecond flushes",
477+threadTs: THREAD_TS,
478+stopped: false,
479+delivered: false,
480+pendingText: oversized,
481+};
482+startSlackStreamMock.mockResolvedValueOnce(session);
483+stopSlackStreamMock.mockRejectedValueOnce(
484+new TestSlackStreamNotDeliveredError(oversized, "team_not_found"),
485+);
486+487+await dispatchPreparedSlackMessage(createPreparedSlackMessage());
488+489+expect(postMessageMock).not.toHaveBeenCalled();
490+expect(deliverRepliesMock).toHaveBeenCalledTimes(1);
491+expect(deliverRepliesMock).toHaveBeenCalledWith(
492+expect.objectContaining({
493+replyThreadTs: THREAD_TS,
494+textLimit: 4000,
495+replies: [expect.objectContaining({ text: oversized })],
496+}),
497+);
498+expect(session.stopped).toBe(true);
499+});
500+501+it("routes full pendingText (earlier buffered + failing chunk) through chunked sender on non-benign append failure", async () => {
502+mockedNativeStreaming = true;
503+mockedDispatchSequence = [
504+{ kind: "block", payload: { text: "first buffered" } },
505+{ kind: "final", payload: { text: "second payload" } },
506+];
507+const session = {
508+channel: "C123",
509+threadTs: THREAD_TS,
510+stopped: false,
511+delivered: false,
512+pendingText: "first buffered",
513+};
514+startSlackStreamMock.mockResolvedValueOnce(session);
515+// Non-benign error (plain Error, NOT SlackStreamNotDeliveredError).
516+// appendSlackStream mutates pendingText BEFORE throwing so the full
517+// buffer (earlier chunk + current chunk) must be preserved and routed
518+// through the chunked fallback - not dropped or partially re-sent.
519+appendSlackStreamMock.mockImplementationOnce(async () => {
520+session.pendingText += "\nsecond payload";
521+throw new Error("network socket closed");
465522});
523+524+await dispatchPreparedSlackMessage(createPreparedSlackMessage());
525+526+// Chunked fallback sent the FULL pendingText, not just the failing
527+// payload (so the earlier buffered chunk is not dropped).
528+expect(deliverRepliesMock).toHaveBeenCalledTimes(1);
529+expect(deliverRepliesMock).toHaveBeenCalledWith(
530+expect.objectContaining({
531+replyThreadTs: THREAD_TS,
532+replies: [expect.objectContaining({ text: "first buffered\nsecond payload" })],
533+}),
534+);
535+// Session was marked fallback-delivered by deliverPendingStreamFallback,
536+// so finalize skips stopSlackStream.
537+expect(session.pendingText).toBe("");
538+expect(session.stopped).toBe(true);
466539expect(stopSlackStreamMock).not.toHaveBeenCalled();
540+// No raw postMessage path was invoked.
541+expect(postMessageMock).not.toHaveBeenCalled();
467542});
468543});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。