diff --git a/CHANGELOG.md b/CHANGELOG.md index d02ab7c32e8..5058efea727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Control UI/cron: keep the runtime-only `last` delivery sentinel from being materialized into persisted cron delivery and failure-alert channel configs when jobs are created or edited. (#68829) Thanks @tianhaocui. +- OpenAI/Responses: strip orphaned reasoning blocks before outbound Responses API calls so compacted or restored histories no longer fail on standalone reasoning items. (#55787) Thanks @suboss87. ## 2026.4.19-beta.2 diff --git a/src/agents/pi-embedded-helpers/openai.ts b/src/agents/pi-embedded-helpers/openai.ts index 17cfa45e354..c96151b18b6 100644 --- a/src/agents/pi-embedded-helpers/openai.ts +++ b/src/agents/pi-embedded-helpers/openai.ts @@ -207,6 +207,7 @@ export function downgradeOpenAIFunctionCallReasoningPairs( * is incomplete, drop the block to keep history usable. */ export function downgradeOpenAIReasoningBlocks(messages: AgentMessage[]): AgentMessage[] { + let anyChanged = false; const out: AgentMessage[] = []; for (const msg of messages) { @@ -259,6 +260,7 @@ export function downgradeOpenAIReasoningBlocks(messages: AgentMessage[]): AgentM continue; } + anyChanged = true; if (nextContent.length === 0) { continue; } @@ -266,5 +268,5 @@ export function downgradeOpenAIReasoningBlocks(messages: AgentMessage[]): AgentM out.push({ ...assistantMsg, content: nextContent } as AgentMessage); } - return out; + return anyChanged ? out : messages; } diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index ea465367a33..ef5f969fa9a 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -72,6 +72,7 @@ import { import type { EmbeddedContextFile } from "../../pi-embedded-helpers.js"; import { downgradeOpenAIFunctionCallReasoningPairs, + downgradeOpenAIReasoningBlocks, isCloudCodeAssistFormatError, resolveBootstrapMaxChars, resolveBootstrapPromptTruncationWarningMode, @@ -1367,7 +1368,10 @@ export async function runEmbeddedAttempt( if (!Array.isArray(messages)) { return inner(model, context, options); } - const sanitized = downgradeOpenAIFunctionCallReasoningPairs(messages as AgentMessage[]); + // Strip orphaned reasoning blocks first, then fix function-call + // pairing — matches the call order in google.ts. + const reasoningSanitized = downgradeOpenAIReasoningBlocks(messages as AgentMessage[]); + const sanitized = downgradeOpenAIFunctionCallReasoningPairs(reasoningSanitized); if (sanitized === messages) { return inner(model, context, options); }