fix: 兼容上游 SSE data: 后无空格格式,流式记账不再 0 消耗

火山方舟等上游流式返回 data:{...}(data: 后无空格),原解析只认
'data: '(带空格),导致 content 文本与 usage 全部漏解析:
- sseContentText 抽成 sseDataPayload,统一处理 data: 前缀
  (支持带/不带空格 + event:+data: 多行块)
- scanUsage 复用 sseDataPayload
- convert/stream.go parseLine 也支持 data:{ 无空格
- 新增回归测试覆盖无空格/带空格/多行块三种形态
This commit is contained in:
Sakurasan
2026-08-27 01:24:30 +08:00
parent d818cf3b4c
commit 79545aa48e
3 changed files with 77 additions and 21 deletions
+4 -3
View File
@@ -11,16 +11,17 @@ type sseState struct {
}
// parseLine 解析一行 SSE;返回是否 data 行及其内容、是否 [DONE]。
// data: 后可跟空格(标准)或紧贴 JSON(上游如火山方舟会省略空格)。
func (s *sseState) parseLine(line []byte) (isData bool, data string, done bool) {
str := strings.TrimRight(string(line), "\r\n")
switch {
case strings.HasPrefix(str, "event: "):
s.event = strings.TrimSpace(strings.TrimPrefix(str, "event: "))
return false, "", false
case str == "data: [DONE]":
case str == "data: [DONE]" || str == "data:[DONE]":
return true, "[DONE]", true
case strings.HasPrefix(str, "data: "):
return true, strings.TrimPrefix(str, "data: "), false
case strings.HasPrefix(str, "data:"):
return true, strings.TrimLeft(strings.TrimPrefix(str, "data:"), " "), false
default:
return false, "", false
}