mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 01:11:23 +00:00
fix: remove orphaned tool_results during compaction pruning
When pruneHistoryForContextShare drops chunks of messages, it could drop an assistant message with tool_use blocks while leaving corresponding tool_result messages in the kept portion. These orphaned tool_results cause Anthropic's API to reject the session with 'unexpected tool_use_id'. Fix by calling repairToolUseResultPairing after each chunk drop to clean up any orphaned tool_results. This reuses existing battle-tested code from session-transcript-repair.ts. Fixes #9769, #9724, #9672
This commit is contained in:
@@ -2,6 +2,7 @@ import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
|
||||
import { estimateTokens, generateSummary } from "@mariozechner/pi-coding-agent";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "./defaults.js";
|
||||
import { repairToolUseResultPairing } from "./session-transcript-repair.js";
|
||||
|
||||
export const BASE_CHUNK_RATIO = 0.4;
|
||||
export const MIN_CHUNK_RATIO = 0.15;
|
||||
@@ -333,11 +334,27 @@ export function pruneHistoryForContextShare(params: {
|
||||
break;
|
||||
}
|
||||
const [dropped, ...rest] = chunks;
|
||||
const flatRest = rest.flat();
|
||||
|
||||
// After dropping a chunk, repair tool_use/tool_result pairing to handle
|
||||
// orphaned tool_results (whose tool_use was in the dropped chunk).
|
||||
// repairToolUseResultPairing drops orphaned tool_results, preventing
|
||||
// "unexpected tool_use_id" errors from Anthropic's API.
|
||||
const repairReport = repairToolUseResultPairing(flatRest);
|
||||
const repairedKept = repairReport.messages;
|
||||
|
||||
// Track orphaned tool_results as dropped (they were in kept but their tool_use was dropped)
|
||||
const orphanedCount = repairReport.droppedOrphanCount;
|
||||
|
||||
droppedChunks += 1;
|
||||
droppedMessages += dropped.length;
|
||||
droppedMessages += dropped.length + orphanedCount;
|
||||
droppedTokens += estimateMessagesTokens(dropped);
|
||||
// Note: We don't have the actual orphaned messages to add to droppedMessagesList
|
||||
// since repairToolUseResultPairing doesn't return them. This is acceptable since
|
||||
// the dropped messages are used for summarization, and orphaned tool_results
|
||||
// without their tool_use context aren't useful for summarization anyway.
|
||||
allDroppedMessages.push(...dropped);
|
||||
keptMessages = rest.flat();
|
||||
keptMessages = repairedKept;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user