fix: emit Responses API lifecycle events in mock OpenAI server (#22702)

This commit is contained in:
Danielle Maywood
2026-03-06 12:35:44 +00:00
committed by GitHub
parent c805c8c02c
commit f9891416c0
2 changed files with 43 additions and 2 deletions
+42 -1
View File
@@ -11,6 +11,7 @@ import (
"time"
"github.com/google/uuid"
"github.com/openai/openai-go/v3/responses"
)
// OpenAIHandler handles OpenAI API requests and returns a response.
@@ -306,6 +307,17 @@ func writeChatCompletionsStreaming(w http.ResponseWriter, r *http.Request, chunk
}
}
// writeSSEEvent marshals v as JSON and writes it as an SSE data
// frame. Returns any write error.
func writeSSEEvent(w http.ResponseWriter, v interface{}) error {
data, err := json.Marshal(v)
if err != nil {
return err
}
_, err = fmt.Fprintf(w, "data: %s\n\n", data)
return err
}
func writeResponsesAPIStreaming(w http.ResponseWriter, r *http.Request, chunks <-chan OpenAIChunk) {
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
@@ -329,7 +341,23 @@ func writeResponsesAPIStreaming(w http.ResponseWriter, r *http.Request, chunks <
return
case chunk, ok = <-chunks:
if !ok {
_, _ = fmt.Fprintf(w, "data: [DONE]\n\n")
// Emit Responses API lifecycle events so
// the fantasy client closes open text
// blocks and persists the step content.
for outputIndex, itemID := range itemIDs {
_ = writeSSEEvent(w, responses.ResponseTextDoneEvent{
ItemID: itemID,
OutputIndex: int64(outputIndex),
})
_ = writeSSEEvent(w, responses.ResponseOutputItemDoneEvent{
OutputIndex: int64(outputIndex),
Item: responses.ResponseOutputItemUnion{
ID: itemID,
Type: "message",
},
})
}
_ = writeSSEEvent(w, responses.ResponseCompletedEvent{})
flusher.Flush()
return
}
@@ -344,6 +372,19 @@ func writeResponsesAPIStreaming(w http.ResponseWriter, r *http.Request, chunks <
if !found {
itemID = fmt.Sprintf("msg_%s", uuid.New().String()[:8])
itemIDs[outputIndex] = itemID
// Emit response.output_item.added so the
// fantasy client triggers TextStart.
if err := writeSSEEvent(w, responses.ResponseOutputItemAddedEvent{
OutputIndex: int64(outputIndex),
Item: responses.ResponseOutputItemUnion{
ID: itemID,
Type: "message",
},
}); err != nil {
return
}
flusher.Flush()
}
chunkData := map[string]interface{}{
+1 -1
View File
@@ -490,6 +490,7 @@ require (
github.com/fsnotify/fsnotify v1.9.0
github.com/go-git/go-git/v5 v5.16.5
github.com/mark3labs/mcp-go v0.38.0
github.com/openai/openai-go/v3 v3.15.0
github.com/sergi/go-diff v1.4.0
gonum.org/v1/gonum v0.17.0
)
@@ -574,7 +575,6 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/openai/openai-go v1.12.0 // indirect
github.com/openai/openai-go/v2 v2.7.1 // indirect
github.com/openai/openai-go/v3 v3.15.0 // indirect
github.com/package-url/packageurl-go v0.1.3 // indirect
github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect