From c555c00cb37b9f1142ae575c9bd81ace6dcda477 Mon Sep 17 00:00:00 2001 From: spiceoogway Date: Fri, 30 Jan 2026 00:10:57 -0500 Subject: [PATCH] fix: repair tool_use/tool_result pairings after history truncation (fixes #4367) The message processing pipeline had a synchronization bug where limitHistoryTurns() truncated conversation history AFTER repairToolUseResultPairing() had already fixed tool_use/tool_result pairings. This could split assistant messages (with tool_use) from their corresponding tool_result blocks, creating orphaned tool_result blocks that the Anthropic API rejects. This fix calls sanitizeToolUseResultPairing() AFTER limitHistoryTurns() to repair any pairings broken by truncation, ensuring the transcript remains valid before being sent to the LLM API. Changes: - Added import for sanitizeToolUseResultPairing from session-transcript-repair.js - Call sanitizeToolUseResultPairing() on the limited message array - Updated variable name from 'limited' to 'repaired' for clarity --- src/agents/pi-embedded-runner/run/attempt.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index e83c3ae4a..622bdb7f4 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -52,6 +52,7 @@ import { import { DEFAULT_BOOTSTRAP_FILENAME } from "../../workspace.js"; import { buildSystemPromptReport } from "../../system-prompt-report.js"; import { resolveDefaultModelForAgent } from "../../model-selection.js"; +import { sanitizeToolUseResultPairing } from "../../session-transcript-repair.js"; import { isAbortError } from "../abort.js"; import { buildEmbeddedExtensionPaths } from "../extensions.js"; @@ -535,9 +536,11 @@ export async function runEmbeddedAttempt( validated, getDmHistoryLimitFromSessionKey(params.sessionKey, params.config), ); - cacheTrace?.recordStage("session:limited", { messages: limited }); - if (limited.length > 0) { - activeSession.agent.replaceMessages(limited); + // Fix: Repair tool_use/tool_result pairings AFTER truncation (issue #4367) + const repaired = sanitizeToolUseResultPairing(limited); + cacheTrace?.recordStage("session:limited", { messages: repaired }); + if (repaired.length > 0) { + activeSession.agent.replaceMessages(repaired); } } catch (err) { sessionManager.flushPendingToolResults?.();