修复接续流的增量bug

This commit is contained in:
CJACK
2026-04-06 02:01:41 +08:00
parent a608a4bd95
commit 4d36afea4c
9 changed files with 140 additions and 21 deletions

View File

@@ -54,9 +54,11 @@ func CollectStream(resp *http.Response, thinkingEnabled bool, closeBody bool) Co
}
for _, p := range result.Parts {
if p.Type == "thinking" {
thinking.WriteString(p.Text)
trimmed := TrimContinuationOverlap(thinking.String(), p.Text)
thinking.WriteString(trimmed)
} else {
text.WriteString(p.Text)
trimmed := TrimContinuationOverlap(text.String(), p.Text)
text.WriteString(trimmed)
}
}
return true

View File

@@ -0,0 +1,33 @@
package sse
import (
"io"
"net/http"
"strings"
"testing"
)
func TestCollectStreamDedupesContinueSnapshotReplay(t *testing.T) {
body := strings.Join([]string{
`data: {"v":{"response":{"fragments":[{"id":2,"type":"THINK","content":"我们","references":[],"stage_id":1}]}}}`,
``,
`data: {"p":"response/fragments/-1/content","o":"APPEND","v":"被"}`,
``,
`data: {"v":"问到"}`,
``,
`data: {"p":"response/status","v":"INCOMPLETE"}`,
``,
`data: {"v":{"response":{"fragments":[{"id":2,"type":"THINK","content":"我们被问到继续","references":[],"stage_id":1}]}}}`,
``,
`data: {"v":"分析"}`,
``,
`data: {"p":"response/status","v":"FINISHED"}`,
``,
}, "\n")
resp := &http.Response{Body: io.NopCloser(strings.NewReader(body))}
got := CollectStream(resp, true, true)
if got.Thinking != "我们被问到继续分析" {
t.Fatalf("unexpected thinking after dedupe: %q", got.Thinking)
}
}

22
internal/sse/dedupe.go Normal file
View File

@@ -0,0 +1,22 @@
package sse
import "strings"
// TrimContinuationOverlap removes the already-seen prefix when DeepSeek
// continue rounds resend the full fragment snapshot instead of only the new
// suffix. Non-overlapping chunks are returned unchanged.
func TrimContinuationOverlap(existing, incoming string) string {
if incoming == "" {
return ""
}
if existing == "" {
return incoming
}
if strings.HasPrefix(incoming, existing) {
return incoming[len(existing):]
}
if strings.HasPrefix(existing, incoming) {
return ""
}
return incoming
}

View File

@@ -0,0 +1,30 @@
package sse
import "testing"
func TestTrimContinuationOverlapReturnsSuffixForSnapshotReplay(t *testing.T) {
existing := "我们被问到:题目"
incoming := "我们被问到:题目继续分析"
got := TrimContinuationOverlap(existing, incoming)
if got != "继续分析" {
t.Fatalf("expected suffix only, got %q", got)
}
}
func TestTrimContinuationOverlapDropsStaleShorterSnapshot(t *testing.T) {
existing := "我们被问到:题目继续分析"
incoming := "我们被问到:题目"
got := TrimContinuationOverlap(existing, incoming)
if got != "" {
t.Fatalf("expected stale snapshot to be dropped, got %q", got)
}
}
func TestTrimContinuationOverlapPreservesNormalIncrement(t *testing.T) {
existing := "我们"
incoming := "被"
got := TrimContinuationOverlap(existing, incoming)
if got != "被" {
t.Fatalf("expected normal increment unchanged, got %q", got)
}
}