fix: replay OpenAI reasoning for tool calls
This commit is contained in:
@@ -18,22 +18,6 @@ diff --git a/dist/providers/openai-codex-responses.js b/dist/providers/openai-co
|
|||||||
index 188a829..4555c9f 100644
|
index 188a829..4555c9f 100644
|
||||||
--- a/dist/providers/openai-codex-responses.js
|
--- a/dist/providers/openai-codex-responses.js
|
||||||
+++ b/dist/providers/openai-codex-responses.js
|
+++ b/dist/providers/openai-codex-responses.js
|
||||||
@@ -433,9 +433,15 @@ function convertMessages(model, context) {
|
|
||||||
}
|
|
||||||
else if (msg.role === "assistant") {
|
|
||||||
const output = [];
|
|
||||||
+ // OpenAI Responses rejects `reasoning` items that are not followed by a `message`.
|
|
||||||
+ // Tool-call-only turns (thinking + function_call) are valid assistant turns, but
|
|
||||||
+ // their stored reasoning items must not be replayed as standalone `reasoning` input.
|
|
||||||
+ const hasTextBlock = msg.content.some((b) => b.type === "text");
|
|
||||||
for (const block of msg.content) {
|
|
||||||
if (block.type === "thinking" && msg.stopReason !== "error") {
|
|
||||||
if (block.thinkingSignature) {
|
|
||||||
+ if (!hasTextBlock)
|
|
||||||
+ continue;
|
|
||||||
const reasoningItem = JSON.parse(block.thinkingSignature);
|
|
||||||
output.push(reasoningItem);
|
|
||||||
}
|
|
||||||
@@ -515,7 +521,7 @@ function convertTools(tools) {
|
@@ -515,7 +521,7 @@ function convertTools(tools) {
|
||||||
name: tool.name,
|
name: tool.name,
|
||||||
description: tool.description,
|
description: tool.description,
|
||||||
@@ -126,24 +110,3 @@ index 5d0813a..e0ef676 100644
|
|||||||
stream.push({
|
stream.push({
|
||||||
type: "toolcall_delta",
|
type: "toolcall_delta",
|
||||||
contentIndex: blockIndex(),
|
contentIndex: blockIndex(),
|
||||||
diff --git a/dist/providers/openai-responses.js b/dist/providers/openai-responses.js
|
|
||||||
index f07085c..f3b01ee 100644
|
|
||||||
--- a/dist/providers/openai-responses.js
|
|
||||||
+++ b/dist/providers/openai-responses.js
|
|
||||||
@@ -396,10 +396,16 @@ function convertMessages(model, context) {
|
|
||||||
}
|
|
||||||
else if (msg.role === "assistant") {
|
|
||||||
const output = [];
|
|
||||||
+ // OpenAI Responses rejects `reasoning` items that are not followed by a `message`.
|
|
||||||
+ // Tool-call-only turns (thinking + function_call) are valid assistant turns, but
|
|
||||||
+ // their stored reasoning items must not be replayed as standalone `reasoning` input.
|
|
||||||
+ const hasTextBlock = msg.content.some((b) => b.type === "text");
|
|
||||||
for (const block of msg.content) {
|
|
||||||
// Do not submit thinking blocks if the completion had an error (i.e. abort)
|
|
||||||
if (block.type === "thinking" && msg.stopReason !== "error") {
|
|
||||||
if (block.thinkingSignature) {
|
|
||||||
+ if (!hasTextBlock)
|
|
||||||
+ continue;
|
|
||||||
const reasoningItem = JSON.parse(block.thinkingSignature);
|
|
||||||
output.push(reasoningItem);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ function installFailingFetchCapture() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("openai-responses reasoning replay", () => {
|
describe("openai-responses reasoning replay", () => {
|
||||||
it("does not replay standalone reasoning for tool-call-only turns", async () => {
|
it("replays reasoning for tool-call-only turns", async () => {
|
||||||
const cap = installFailingFetchCapture();
|
const cap = installFailingFetchCapture();
|
||||||
try {
|
try {
|
||||||
const model = buildModel();
|
const model = buildModel();
|
||||||
@@ -142,7 +142,10 @@ describe("openai-responses reasoning replay", () => {
|
|||||||
.filter((t): t is string => typeof t === "string");
|
.filter((t): t is string => typeof t === "string");
|
||||||
|
|
||||||
expect(types).toContain("function_call");
|
expect(types).toContain("function_call");
|
||||||
expect(types).not.toContain("reasoning");
|
expect(types).toContain("reasoning");
|
||||||
|
expect(types.indexOf("reasoning")).toBeLessThan(
|
||||||
|
types.indexOf("function_call"),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
cap.restore();
|
cap.restore();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user