fix: strip orphaned OpenAI reasoning blocks before responses API call (#55787)

Merged via squash.

Prepared head SHA: 263b952d88
Co-authored-by: suboss87 <11032439+suboss87@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
This commit is contained in:
Subash Natarajan
2026-04-19 13:27:03 +05:30
committed by GitHub
parent beb2fded6d
commit 6682b12563
3 changed files with 9 additions and 2 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}