fix(agent): sanitize messages after orphan user repair

When repairing orphaned trailing user messages, buildSessionContext()
was called but messages bypassed the sanitization pipeline. This could
cause tool_result blocks without matching tool_use blocks, leading to
Anthropic API "unexpected tool_use_id" errors.

Apply full sanitization (sanitizeSessionHistory, validateTurns,
limitHistoryTurns) to rebuilt messages.
This commit is contained in:
Aswin Sreenivas 2026-01-29 22:20:28 +08:00
parent 5330595a5a
commit 5355b476f6

View File

@ -709,7 +709,28 @@ export async function runEmbeddedAttempt(
sessionManager.resetLeaf();
}
const sessionContext = sessionManager.buildSessionContext();
activeSession.agent.replaceMessages(sessionContext.messages);
// Re-sanitize the rebuilt messages to ensure tool_use/tool_result pairing is valid.
// Without this, Anthropic API rejects the request with "unexpected tool_use_id" errors.
const rebuiltSanitized = await sanitizeSessionHistory({
messages: sessionContext.messages,
modelApi: params.model.api,
modelId: params.modelId,
provider: params.provider,
sessionManager,
sessionId: params.sessionId,
policy: transcriptPolicy,
});
const rebuiltValidatedGemini = transcriptPolicy.validateGeminiTurns
? validateGeminiTurns(rebuiltSanitized)
: rebuiltSanitized;
const rebuiltValidated = transcriptPolicy.validateAnthropicTurns
? validateAnthropicTurns(rebuiltValidatedGemini)
: rebuiltValidatedGemini;
const rebuiltLimited = limitHistoryTurns(
rebuiltValidated,
getDmHistoryLimitFromSessionKey(params.sessionKey, params.config),
);
activeSession.agent.replaceMessages(rebuiltLimited);
log.warn(
`Removed orphaned user message to prevent consecutive user turns. ` +
`runId=${params.runId} sessionId=${params.sessionId}`,