From 7723e46c2697a1e89b697fb19685f6656d4931d1 Mon Sep 17 00:00:00 2001 From: AveryanAlex Date: Sun, 29 Mar 2026 00:23:54 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20emit=20reasoning=5Fcontent=20in=20Respon?= =?UTF-8?q?ses=E2=86=92Chat=20streaming=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../translator/response/openai-responses.ts | 17 ++++++++++++++--- tests/unit/responses-translation-fixes.test.mjs | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/open-sse/translator/response/openai-responses.ts b/open-sse/translator/response/openai-responses.ts index 41e40e4f66..745b643de8 100644 --- a/open-sse/translator/response/openai-responses.ts +++ b/open-sse/translator/response/openai-responses.ts @@ -602,10 +602,21 @@ export function openaiResponsesToOpenAIResponse(chunk, state) { return null; } - // Reasoning events (convert to content or skip) + // Reasoning events — emit as reasoning_content in Chat format if (eventType === "response.reasoning_summary_text.delta") { - // Optionally include reasoning as content, or skip - return null; + const reasoningDelta = data.delta || ""; + if (!reasoningDelta) return null; + return { + id: state.chatId, + object: "chat.completion.chunk", + created: state.created, + model: state.model || "gpt-4", + choices: [{ + index: 0, + delta: { reasoning_content: reasoningDelta }, + finish_reason: null, + }], + }; } // Ignore other events diff --git a/tests/unit/responses-translation-fixes.test.mjs b/tests/unit/responses-translation-fixes.test.mjs index 20c827f96a..8ecf34f4bd 100644 --- a/tests/unit/responses-translation-fixes.test.mjs +++ b/tests/unit/responses-translation-fixes.test.mjs @@ -342,7 +342,7 @@ test("Chat→Responses: deprecated function role message converted to function_c assert.equal(fcOutput.call_id, fcItem.call_id); }); -const { openaiToOpenAIResponsesResponse } = await import( +const { openaiToOpenAIResponsesResponse, openaiResponsesToOpenAIResponse } = await import( "../../open-sse/translator/response/openai-responses.ts" ); const { initState } = await import("../../open-sse/translator/index.ts"); @@ -388,3 +388,18 @@ test("Chat→Responses streaming: completed event includes accumulated output", const msgOutput = completedEvent.data.response.output.find((o) => o.type === "message"); assert.ok(msgOutput, "should have message output item"); }); + +test("Responses→Chat streaming: reasoning delta emits reasoning_content in Chat chunk", () => { + const state = { started: false, chatId: null, created: null, toolCallIndex: 0, finishReasonSent: false }; + + const chunk = { + type: "response.reasoning_summary_text.delta", + delta: "thinking step...", + item_id: "rs_1", + output_index: 0, + summary_index: 0, + }; + const result = openaiResponsesToOpenAIResponse(chunk, state); + assert.ok(result, "should return a chunk"); + assert.equal(result.choices[0].delta.reasoning_content, "thinking step..."); +});