Fix #4650: Re-run tool pairing and turn validation after history limiting
After limitHistoryTurns or compaction operations, the message history can end up with: 1. Orphaned tool_result blocks (tool_use IDs not in preceding message) 2. Consecutive assistant messages that violate API format requirements Root cause: sanitizeToolUseResultPairing and turn validation functions (validateGeminiTurns, validateAnthropicTurns) were only running BEFORE limitHistoryTurns, but history limiting can create new issues by cutting off tool_use blocks or creating consecutive assistant messages during compaction. Solution: Re-run both sanitizeToolUseResultPairing and turn validation AFTER limitHistoryTurns in both main code paths: - src/agents/pi-embedded-runner/run/attempt.ts - src/agents/pi-embedded-runner/compact.ts This ensures tool_use/tool_result pairing is maintained and consecutive assistant/user messages are properly merged after any history modification. Changes: - Added transcriptPolicy checks before applying repairs (respects config) - Re-run validateGeminiTurns after sanitizeToolUseResultPairing - Re-run validateAnthropicTurns after validateGeminiTurns - Added import for sanitizeToolUseResultPairing in compact.ts
This commit is contained in:
parent
41b2dd1f27
commit
22b5201d14
@ -35,6 +35,7 @@ import {
|
||||
validateAnthropicTurns,
|
||||
validateGeminiTurns,
|
||||
} from "../pi-embedded-helpers.js";
|
||||
import { sanitizeToolUseResultPairing } from "../session-transcript-repair.js";
|
||||
import {
|
||||
ensurePiCompactionReserveTokens,
|
||||
resolveCompactionReserveTokensFloor,
|
||||
@ -421,8 +422,19 @@ export async function compactEmbeddedPiSessionDirect(
|
||||
validated,
|
||||
getDmHistoryLimitFromSessionKey(params.sessionKey, params.config),
|
||||
);
|
||||
if (limited.length > 0) {
|
||||
session.agent.replaceMessages(limited);
|
||||
// Fix: Repair tool_use/tool_result pairings AFTER truncation (issue #4650)
|
||||
const repaired = transcriptPolicy.repairToolUseResultPairing
|
||||
? sanitizeToolUseResultPairing(limited)
|
||||
: limited;
|
||||
// Re-run turn validation after limiting (issue #4650) to merge consecutive assistant/user messages
|
||||
const revalidatedGemini = transcriptPolicy.validateGeminiTurns
|
||||
? validateGeminiTurns(repaired)
|
||||
: repaired;
|
||||
const revalidatedAnthropic = transcriptPolicy.validateAnthropicTurns
|
||||
? validateAnthropicTurns(revalidatedGemini)
|
||||
: revalidatedGemini;
|
||||
if (revalidatedAnthropic.length > 0) {
|
||||
session.agent.replaceMessages(revalidatedAnthropic);
|
||||
}
|
||||
const result = await session.compact(params.customInstructions);
|
||||
// Estimate tokens after compaction by summing token estimates for remaining messages
|
||||
|
||||
@ -536,11 +536,20 @@ export async function runEmbeddedAttempt(
|
||||
validated,
|
||||
getDmHistoryLimitFromSessionKey(params.sessionKey, params.config),
|
||||
);
|
||||
// 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);
|
||||
// Fix: Repair tool_use/tool_result pairings AFTER truncation (issue #4367, #4650)
|
||||
const repaired = transcriptPolicy.repairToolUseResultPairing
|
||||
? sanitizeToolUseResultPairing(limited)
|
||||
: limited;
|
||||
// Re-run turn validation after limiting (issue #4650) to merge consecutive assistant/user messages
|
||||
const revalidatedGemini = transcriptPolicy.validateGeminiTurns
|
||||
? validateGeminiTurns(repaired)
|
||||
: repaired;
|
||||
const revalidatedAnthropic = transcriptPolicy.validateAnthropicTurns
|
||||
? validateAnthropicTurns(revalidatedGemini)
|
||||
: revalidatedGemini;
|
||||
cacheTrace?.recordStage("session:limited", { messages: revalidatedAnthropic });
|
||||
if (revalidatedAnthropic.length > 0) {
|
||||
activeSession.agent.replaceMessages(revalidatedAnthropic);
|
||||
}
|
||||
} catch (err) {
|
||||
sessionManager.flushPendingToolResults?.();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user