



















@@ -0,0 +1,73 @@
1+import { describe, expect, it } from "vitest";
2+import {
3+MAX_LIVE_CHAT_BUFFER_CHARS,
4+resolveMergedAssistantText,
5+} from "./live-chat-projector.js";
6+7+describe("server chat stream text merge", () => {
8+it.each([
9+{
10+name: "repeated digits",
11+chunks: ["1", "1", "1"],
12+expected: "111",
13+},
14+{
15+name: "repeated CJK punctuation",
16+chunks: ["。", "。", "。"],
17+expected: "。。。",
18+},
19+{
20+name: "repeated markdown emphasis tokens",
21+chunks: ["**", "**"],
22+expected: "****",
23+},
24+{
25+name: "repeated markdown table separators",
26+chunks: ["|", "|", "|"],
27+expected: "|||",
28+},
29+])("appends incremental deltas without collapsing $name", ({ chunks, expected }) => {
30+const merged = chunks.reduce(
31+(previousText, nextDelta) =>
32+resolveMergedAssistantText({
33+ previousText,
34+nextText: nextDelta,
35+ nextDelta,
36+}),
37+"",
38+);
39+40+expect(merged).toBe(expected);
41+});
42+43+it("keeps cumulative snapshots from duplicating already-buffered text", () => {
44+expect(
45+resolveMergedAssistantText({
46+previousText: "Hello",
47+nextText: "Hello world",
48+nextDelta: " world",
49+}),
50+).toBe("Hello world");
51+});
52+53+it("keeps non-prefix incremental segments after tool calls", () => {
54+expect(
55+resolveMergedAssistantText({
56+previousText: "Before tool call",
57+nextText: "After tool call",
58+nextDelta: "\nAfter tool call",
59+}),
60+).toBe("Before tool call\nAfter tool call");
61+});
62+63+it("caps merged live text while preserving the newest assistant output", () => {
64+const result = resolveMergedAssistantText({
65+previousText: "a".repeat(MAX_LIVE_CHAT_BUFFER_CHARS - 2),
66+nextText: "",
67+nextDelta: "bbbb",
68+});
69+70+expect(result).toHaveLength(MAX_LIVE_CHAT_BUFFER_CHARS);
71+expect(result.endsWith("bbbb")).toBe(true);
72+});
73+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。