refactor: centralize SSE stream parsing logic into a new sse package and update the PoW solver to honor context cancellation during module acquisition.

This commit is contained in:
CJACK
2026-02-17 04:40:01 +08:00
parent 23d5ac7fa2
commit 07de35a093
6 changed files with 107 additions and 46 deletions

View File

@@ -1,7 +1,6 @@
package claude
import (
"bufio"
"encoding/json"
"fmt"
"io"
@@ -220,20 +219,6 @@ func (h *Handler) handleClaudeStreamRealtime(w http.ResponseWriter, r *http.Requ
if !canFlush {
config.Logger.Warn("[claude_stream] response writer does not support flush; streaming may be buffered")
}
lines := make(chan []byte, 128)
done := make(chan error, 1)
go func() {
scanner := bufio.NewScanner(resp.Body)
buf := make([]byte, 0, 64*1024)
scanner.Buffer(buf, 2*1024*1024)
for scanner.Scan() {
b := append([]byte{}, scanner.Bytes()...)
lines <- b
}
close(lines)
done <- scanner.Err()
}()
send := func(event string, v any) {
b, _ := json.Marshal(v)
_, _ = w.Write([]byte("event: "))
@@ -276,10 +261,11 @@ func (h *Handler) handleClaudeStreamRealtime(w http.ResponseWriter, r *http.Requ
},
})
currentType := "text"
initialType := "text"
if thinkingEnabled {
currentType = "thinking"
initialType = "thinking"
}
parsedLines, done := sse.StartParsedLinePump(r.Context(), resp.Body, thinkingEnabled, initialType)
bufferToolContent := len(toolNames) > 0
hasContent := false
lastContent := time.Now()
@@ -412,7 +398,7 @@ func (h *Handler) handleClaudeStreamRealtime(w http.ResponseWriter, r *http.Requ
return
}
send("ping", map[string]any{"type": "ping"})
case line, ok := <-lines:
case parsed, ok := <-parsedLines:
if !ok {
if err := <-done; err != nil {
sendError(err.Error())
@@ -421,9 +407,6 @@ func (h *Handler) handleClaudeStreamRealtime(w http.ResponseWriter, r *http.Requ
finalize("end_turn")
return
}
parsed := sse.ParseDeepSeekContentLine(line, thinkingEnabled, currentType)
currentType = parsed.NextType
if !parsed.Parsed {
continue
}

View File

@@ -1,7 +1,6 @@
package openai
import (
"bufio"
"context"
"encoding/json"
"fmt"
@@ -189,29 +188,16 @@ func (h *Handler) handleStream(w http.ResponseWriter, r *http.Request, resp *htt
config.Logger.Warn("[stream] response writer does not support flush; streaming may be buffered")
}
lines := make(chan []byte, 128)
done := make(chan error, 1)
go func() {
scanner := bufio.NewScanner(resp.Body)
buf := make([]byte, 0, 64*1024)
scanner.Buffer(buf, 2*1024*1024)
for scanner.Scan() {
b := append([]byte{}, scanner.Bytes()...)
lines <- b
}
close(lines)
done <- scanner.Err()
}()
created := time.Now().Unix()
firstChunkSent := false
bufferToolContent := len(toolNames) > 0
var toolSieve toolStreamSieveState
toolCallsEmitted := false
currentType := "text"
initialType := "text"
if thinkingEnabled {
currentType = "thinking"
initialType = "thinking"
}
parsedLines, done := sse.StartParsedLinePump(r.Context(), resp.Body, thinkingEnabled, initialType)
thinking := strings.Builder{}
text := strings.Builder{}
lastContent := time.Now()
@@ -321,7 +307,7 @@ func (h *Handler) handleStream(w http.ResponseWriter, r *http.Request, resp *htt
_, _ = w.Write([]byte(": keep-alive\n\n"))
_ = rc.Flush()
}
case line, ok := <-lines:
case parsed, ok := <-parsedLines:
if !ok {
// Ensure scanner completion is observed only after all queued
// SSE lines are drained, avoiding early finalize races.
@@ -329,8 +315,6 @@ func (h *Handler) handleStream(w http.ResponseWriter, r *http.Request, resp *htt
finalize("stop")
return
}
parsed := sse.ParseDeepSeekContentLine(line, thinkingEnabled, currentType)
currentType = parsed.NextType
if !parsed.Parsed {
continue
}