From 5d7e54751a07bf9c28b5af8c3e9a2eed12bc0b5f Mon Sep 17 00:00:00 2001 From: bonerush <96404351+bonerush@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:27:25 +0800 Subject: [PATCH] fix: reorder tool and user messages for OpenAI API compatibility (#168) (#177) Fixes #168 OpenAI requires that an assistant message with tool_calls be immediately followed by tool messages. Previously, convertInternalUserMessage output user content before tool results, causing 400 errors. Now tool messages are pushed first. --- src/services/api/openai/convertMessages.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/services/api/openai/convertMessages.ts b/src/services/api/openai/convertMessages.ts index 051b43d69..3869120eb 100644 --- a/src/services/api/openai/convertMessages.ts +++ b/src/services/api/openai/convertMessages.ts @@ -92,6 +92,15 @@ function convertInternalUserMessage( } } + // CRITICAL: tool messages must come BEFORE any user message in the result. + // OpenAI API requires that a tool message immediately follows the assistant + // message with tool_calls. If we emit a user message first, the API will + // reject the request with "insufficient tool messages following tool_calls". + // See: https://github.com/anthropics/claude-code/issues/xxx + for (const tr of toolResults) { + result.push(convertToolResult(tr)) + } + // 如果有图片,构建多模态 content 数组 if (imageParts.length > 0) { const multiContent: Array<{ type: 'text'; text: string } | { type: 'image_url'; image_url: { url: string } }> = [] @@ -109,10 +118,6 @@ function convertInternalUserMessage( content: textParts.join('\n'), } satisfies ChatCompletionUserMessageParam) } - - for (const tr of toolResults) { - result.push(convertToolResult(tr)) - } } return result