mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix(agents): clear pending tool call state on interruption regardless of provider
When `allowSyntheticToolResults` is false (OpenAI, OpenRouter, and most third-party providers), the guard never cleared its pending tool call map when a user message arrived during in-flight tool execution. This left orphaned tool_use blocks in the transcript with no matching tool_result, causing the provider API to reject all subsequent requests with 400 errors and permanently breaking the session. The fix removes the `allowSyntheticToolResults` gate around the flush calls. `flushPendingToolResults()` already handles both cases correctly: it only inserts synthetic results when allowed, and always clears the pending map. The gate was preventing the map from being cleared at all for providers that disable synthetic results. Fixes #32098 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Peter Steinberger
parent
21d6d878ce
commit
1dcea837a2
@@ -171,7 +171,7 @@ export function installSessionToolResultGuard(
|
||||
allowedToolNames: opts?.allowedToolNames,
|
||||
});
|
||||
if (sanitized.length === 0) {
|
||||
if (allowSyntheticToolResults && pending.size > 0) {
|
||||
if (pending.size > 0) {
|
||||
flushPendingToolResults();
|
||||
}
|
||||
return undefined;
|
||||
@@ -215,15 +215,18 @@ export function installSessionToolResultGuard(
|
||||
? extractToolCallsFromAssistant(nextMessage as Extract<AgentMessage, { role: "assistant" }>)
|
||||
: [];
|
||||
|
||||
if (allowSyntheticToolResults) {
|
||||
// If previous tool calls are still pending, flush before non-tool results.
|
||||
if (pending.size > 0 && (toolCalls.length === 0 || nextRole !== "assistant")) {
|
||||
flushPendingToolResults();
|
||||
}
|
||||
// If new tool calls arrive while older ones are pending, flush the old ones first.
|
||||
if (pending.size > 0 && toolCalls.length > 0) {
|
||||
flushPendingToolResults();
|
||||
}
|
||||
// Always clear pending tool call state before appending non-tool-result messages.
|
||||
// flushPendingToolResults() only inserts synthetic results when allowSyntheticToolResults
|
||||
// is true; it always clears the pending map. Without this, providers that disable
|
||||
// synthetic results (e.g. OpenAI) accumulate stale pending state when a user message
|
||||
// interrupts in-flight tool calls, leaving orphaned tool_use blocks in the transcript
|
||||
// that cause API 400 errors on subsequent requests.
|
||||
if (pending.size > 0 && (toolCalls.length === 0 || nextRole !== "assistant")) {
|
||||
flushPendingToolResults();
|
||||
}
|
||||
// If new tool calls arrive while older ones are pending, flush the old ones first.
|
||||
if (pending.size > 0 && toolCalls.length > 0) {
|
||||
flushPendingToolResults();
|
||||
}
|
||||
|
||||
const finalMessage = applyBeforeWriteHook(persistMessage(nextMessage));
|
||||
|
||||
Reference in New Issue
Block a user