fix: preserve SSE event boundaries for Responses streams
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -21,6 +22,21 @@ import (
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
func writeResponsesSSEChunk(w io.Writer, chunk []byte) {
|
||||
if w == nil || len(chunk) == 0 {
|
||||
return
|
||||
}
|
||||
_, _ = w.Write(chunk)
|
||||
switch {
|
||||
case bytes.HasSuffix(chunk, []byte("\n\n")):
|
||||
return
|
||||
case bytes.HasSuffix(chunk, []byte("\n")):
|
||||
_, _ = w.Write([]byte("\n"))
|
||||
default:
|
||||
_, _ = w.Write([]byte("\n\n"))
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAIResponsesAPIHandler contains the handlers for OpenAIResponses API endpoints.
|
||||
// It holds a pool of clients to interact with the backend service.
|
||||
type OpenAIResponsesAPIHandler struct {
|
||||
@@ -230,11 +246,7 @@ func (h *OpenAIResponsesAPIHandler) handleStreamingResponse(c *gin.Context, rawJ
|
||||
handlers.WriteUpstreamHeaders(c.Writer.Header(), upstreamHeaders)
|
||||
|
||||
// Write first chunk logic (matching forwardResponsesStream)
|
||||
if bytes.HasPrefix(chunk, []byte("event:")) {
|
||||
_, _ = c.Writer.Write([]byte("\n"))
|
||||
}
|
||||
_, _ = c.Writer.Write(chunk)
|
||||
_, _ = c.Writer.Write([]byte("\n"))
|
||||
writeResponsesSSEChunk(c.Writer, chunk)
|
||||
flusher.Flush()
|
||||
|
||||
// Continue
|
||||
@@ -247,11 +259,7 @@ func (h *OpenAIResponsesAPIHandler) handleStreamingResponse(c *gin.Context, rawJ
|
||||
func (h *OpenAIResponsesAPIHandler) forwardResponsesStream(c *gin.Context, flusher http.Flusher, cancel func(error), data <-chan []byte, errs <-chan *interfaces.ErrorMessage) {
|
||||
h.ForwardStream(c, flusher, cancel, data, errs, handlers.StreamForwardOptions{
|
||||
WriteChunk: func(chunk []byte) {
|
||||
if bytes.HasPrefix(chunk, []byte("event:")) {
|
||||
_, _ = c.Writer.Write([]byte("\n"))
|
||||
}
|
||||
_, _ = c.Writer.Write(chunk)
|
||||
_, _ = c.Writer.Write([]byte("\n"))
|
||||
writeResponsesSSEChunk(c.Writer, chunk)
|
||||
},
|
||||
WriteTerminalError: func(errMsg *interfaces.ErrorMessage) {
|
||||
if errMsg == nil {
|
||||
|
||||
Reference in New Issue
Block a user