mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-12 04:07:42 +08:00
feat: centralize DeepSeek SSE parsing, improve account identifier resolution, and simplify CORS configuration.
This commit is contained in:
@@ -31,22 +31,15 @@ func CollectStream(resp *http.Response, thinkingEnabled bool, closeBody bool) Co
|
||||
currentType = "thinking"
|
||||
}
|
||||
_ = deepseek.ScanSSELines(resp, func(line []byte) bool {
|
||||
chunk, done, ok := ParseDeepSeekSSELine(line)
|
||||
if !ok {
|
||||
result := ParseDeepSeekContentLine(line, thinkingEnabled, currentType)
|
||||
currentType = result.NextType
|
||||
if !result.Parsed {
|
||||
return true
|
||||
}
|
||||
if done {
|
||||
if result.Stop {
|
||||
return false
|
||||
}
|
||||
if _, hasErr := chunk["error"]; hasErr {
|
||||
return false
|
||||
}
|
||||
parts, finished, newType := ParseSSEChunkForContent(chunk, thinkingEnabled, currentType)
|
||||
currentType = newType
|
||||
if finished {
|
||||
return false
|
||||
}
|
||||
for _, p := range parts {
|
||||
for _, p := range result.Parts {
|
||||
if p.Type == "thinking" {
|
||||
thinking.WriteString(p.Text)
|
||||
} else {
|
||||
|
||||
49
internal/sse/line.go
Normal file
49
internal/sse/line.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package sse
|
||||
|
||||
import "fmt"
|
||||
|
||||
// LineResult is the normalized parse result for one DeepSeek SSE line.
|
||||
type LineResult struct {
|
||||
Parsed bool
|
||||
Stop bool
|
||||
ContentFilter bool
|
||||
ErrorMessage string
|
||||
Parts []ContentPart
|
||||
NextType string
|
||||
}
|
||||
|
||||
// ParseDeepSeekContentLine centralizes one-line DeepSeek SSE parsing for both
|
||||
// streaming and non-streaming handlers.
|
||||
func ParseDeepSeekContentLine(raw []byte, thinkingEnabled bool, currentType string) LineResult {
|
||||
chunk, done, parsed := ParseDeepSeekSSELine(raw)
|
||||
if !parsed {
|
||||
return LineResult{NextType: currentType}
|
||||
}
|
||||
if done {
|
||||
return LineResult{Parsed: true, Stop: true, NextType: currentType}
|
||||
}
|
||||
if errObj, hasErr := chunk["error"]; hasErr {
|
||||
return LineResult{
|
||||
Parsed: true,
|
||||
Stop: true,
|
||||
ErrorMessage: fmt.Sprintf("%v", errObj),
|
||||
NextType: currentType,
|
||||
}
|
||||
}
|
||||
if code, _ := chunk["code"].(string); code == "content_filter" {
|
||||
return LineResult{
|
||||
Parsed: true,
|
||||
Stop: true,
|
||||
ContentFilter: true,
|
||||
ErrorMessage: "content filtered by upstream",
|
||||
NextType: currentType,
|
||||
}
|
||||
}
|
||||
parts, finished, nextType := ParseSSEChunkForContent(chunk, thinkingEnabled, currentType)
|
||||
return LineResult{
|
||||
Parsed: true,
|
||||
Stop: finished,
|
||||
Parts: parts,
|
||||
NextType: nextType,
|
||||
}
|
||||
}
|
||||
37
internal/sse/line_test.go
Normal file
37
internal/sse/line_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package sse
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseDeepSeekContentLineDone(t *testing.T) {
|
||||
res := ParseDeepSeekContentLine([]byte("data: [DONE]"), false, "text")
|
||||
if !res.Parsed || !res.Stop {
|
||||
t.Fatalf("expected parsed stop result: %#v", res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDeepSeekContentLineError(t *testing.T) {
|
||||
res := ParseDeepSeekContentLine([]byte(`data: {"error":"boom"}`), false, "text")
|
||||
if !res.Parsed || !res.Stop {
|
||||
t.Fatalf("expected stop on error: %#v", res)
|
||||
}
|
||||
if res.ErrorMessage == "" {
|
||||
t.Fatalf("expected non-empty error message")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDeepSeekContentLineContentFilter(t *testing.T) {
|
||||
res := ParseDeepSeekContentLine([]byte(`data: {"code":"content_filter"}`), false, "text")
|
||||
if !res.Parsed || !res.Stop || !res.ContentFilter {
|
||||
t.Fatalf("expected content-filter stop result: %#v", res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDeepSeekContentLineContent(t *testing.T) {
|
||||
res := ParseDeepSeekContentLine([]byte(`data: {"p":"response/content","v":"hi"}`), false, "text")
|
||||
if !res.Parsed || res.Stop {
|
||||
t.Fatalf("expected parsed non-stop result: %#v", res)
|
||||
}
|
||||
if len(res.Parts) != 1 || res.Parts[0].Text != "hi" || res.Parts[0].Type != "text" {
|
||||
t.Fatalf("unexpected parts: %#v", res.Parts)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user