mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-11 19:57:41 +08:00
修复接续流的增量bug
This commit is contained in:
@@ -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
|
||||
|
||||
33
internal/sse/consumer_test.go
Normal file
33
internal/sse/consumer_test.go
Normal 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
22
internal/sse/dedupe.go
Normal 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
|
||||
}
|
||||
30
internal/sse/dedupe_test.go
Normal file
30
internal/sse/dedupe_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user