mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:40:44 +00:00
fix: preserve thinking turns during transcript repair
This commit is contained in:
@@ -380,6 +380,40 @@ describe("sanitizeToolCallInputs", () => {
|
||||
expect(types).toEqual(["text", "toolUse"]);
|
||||
});
|
||||
|
||||
it("preserves assistant turns that include thinking blocks", () => {
|
||||
const input = castAgentMessages([
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{
|
||||
type: "thinking",
|
||||
thinking: "Let me check the gateway config.",
|
||||
thinkingSignature: "sig_gateway",
|
||||
},
|
||||
{
|
||||
type: "toolCall",
|
||||
id: "call_gateway",
|
||||
name: "gateway",
|
||||
arguments: {
|
||||
action: "config.get",
|
||||
path: "channels.telegram",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const out = sanitizeToolCallInputs(input, { allowedToolNames: ["read"] });
|
||||
|
||||
expect(out).toBe(input);
|
||||
const assistant = out[0] as Extract<AgentMessage, { role: "assistant" }>;
|
||||
const types = Array.isArray(assistant.content)
|
||||
? assistant.content.map((block) => (block as { type?: unknown }).type)
|
||||
: [];
|
||||
expect(types).toEqual(["thinking", "toolCall"]);
|
||||
expect((assistant.content?.[1] as { name?: unknown })?.name).toBe("gateway");
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "trims leading whitespace from tool names",
|
||||
|
||||
@@ -17,6 +17,14 @@ type RawToolCallBlock = {
|
||||
arguments?: unknown;
|
||||
};
|
||||
|
||||
function isThinkingLikeBlock(block: unknown): boolean {
|
||||
if (!block || typeof block !== "object") {
|
||||
return false;
|
||||
}
|
||||
const type = (block as { type?: unknown }).type;
|
||||
return type === "thinking" || type === "redacted_thinking";
|
||||
}
|
||||
|
||||
function isRawToolCallBlock(block: unknown): block is RawToolCallBlock {
|
||||
if (!block || typeof block !== "object") {
|
||||
return false;
|
||||
@@ -239,6 +247,14 @@ export function repairToolCallInputs(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Preserve provider-owned thinking turns verbatim. Anthropic replays can
|
||||
// reject any historical assistant turn whose signed thinking block no
|
||||
// longer matches the original response, including sibling tool calls.
|
||||
if (msg.content.some((block) => isThinkingLikeBlock(block))) {
|
||||
out.push(msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
const nextContent: typeof msg.content = [];
|
||||
let droppedInMessage = 0;
|
||||
let messageChanged = false;
|
||||
|
||||
Reference in New Issue
Block a user