Skip to content

Commit 82d8269

Browse files
authored
Merge pull request #2098 from ksylvan/fix/codex-no-response
Fix Codex Empty Response bug
2 parents 99dcff0 + 78f9d7c commit 82d8269

2 files changed

Lines changed: 60 additions & 2 deletions

File tree

internal/plugins/ai/codex/codex.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,14 @@ func (c *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage, o
242242
if err := c.mapRequestError(stream.Err()); err != nil {
243243
return "", err
244244
}
245+
streamedText := builder.String()
245246
if completedResp != nil {
246-
return c.ExtractText(completedResp), nil
247+
if extractedText := c.ExtractText(completedResp); strings.TrimSpace(extractedText) != "" {
248+
return extractedText, nil
249+
}
247250
}
248251

249-
return builder.String(), nil
252+
return streamedText, nil
250253
}
251254

252255
// SendStream sends a request to Codex and streams the response text updates.

internal/plugins/ai/codex/codex_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,61 @@ func TestSendIncludesSourcesFromAnnotatedResponse(t *testing.T) {
429429
}
430430
}
431431

432+
func TestSendFallsBackToDeltaWhenCompletedResponseHasNoText(t *testing.T) {
433+
apiServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
434+
if r.URL.Path != "/responses" {
435+
http.NotFound(w, r)
436+
return
437+
}
438+
439+
w.Header().Set("Content-Type", "text/event-stream")
440+
flusher, ok := w.(http.Flusher)
441+
if !ok {
442+
t.Fatalf("response writer does not implement http.Flusher")
443+
}
444+
fmt.Fprintf(w, "data: %s\n\n", marshalJSON(t, map[string]any{
445+
"type": string(constant.ResponseOutputTextDelta("").Default()),
446+
"delta": "hello from delta",
447+
}))
448+
flusher.Flush()
449+
fmt.Fprintf(w, "data: %s\n\n", marshalJSON(t, map[string]any{
450+
"type": "response.completed",
451+
"response": map[string]any{
452+
"output": []any{
453+
map[string]any{
454+
"type": "message",
455+
"content": []any{
456+
map[string]any{
457+
"type": "output_text",
458+
"text": "",
459+
},
460+
},
461+
},
462+
},
463+
},
464+
}))
465+
flusher.Flush()
466+
fmt.Fprint(w, "data: [DONE]\n\n")
467+
}))
468+
defer apiServer.Close()
469+
470+
client := newConfiguredTestClient(t, apiServer.URL, "acct_delta_fallback", testJWT("acct_delta_fallback", time.Now().Add(time.Hour)))
471+
472+
message, err := client.Send(context.Background(), []*chat.ChatCompletionMessage{
473+
{Role: chat.ChatMessageRoleUser, Content: "Hello"},
474+
}, &domain.ChatOptions{
475+
Model: "gpt-5.4",
476+
Temperature: 0.7,
477+
})
478+
if err != nil {
479+
t.Fatalf("Send() error = %v", err)
480+
}
481+
482+
if message != "hello from delta" {
483+
t.Fatalf("Send() = %q, want %q", message, "hello from delta")
484+
}
485+
}
486+
432487
func TestSendStreamReadsCodexSSE(t *testing.T) {
433488
apiServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
434489
if r.URL.Path != "/responses" {

0 commit comments

Comments
 (0)