fix(combo/fusion): flatten Anthropic-style tool messages in panel calls

flattenToolHistory only recognized OpenAI-style tool calls. Anthropic-compatible clients (Claude Code, /v1/messages) send tool invocations and results as tool_use/tool_result blocks inside the message content array. Since panel calls strip the tools definitions (#1859), the panel expert models received structured tool history without schemas, causing them to fail or misbehave (leading to empty responses and 503 errors).

Extend flattenToolHistory to recognize and flatten tool_use and tool_result blocks in the content array into prose text, keeping panel expert execution robust and independent of the client API format.

PR decolua/9router#1910

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
warelik
2026-06-20 15:19:31 +07:00
committed by decolua
co-authored by Cursor
parent 707a91555d
commit 86162eeb8f
2 changed files with 54 additions and 0 deletions
+31
View File
@@ -182,4 +182,35 @@ describe("fusion combo", () => {
expect(judgeBody.messages[1].tool_calls).toBeDefined();
expect(judgeBody.messages[2].role).toBe("tool");
});
it("flattens Anthropic-style tool_use and tool_result blocks in arrays", async () => {
const handleSingleModel = vi.fn(async () => okResponse("ans"));
await handleFusionChat({
body: {
messages: [
{ role: "user", content: "do it" },
{ role: "assistant", content: [{ type: "text", text: "ok" }, { type: "tool_use", id: "t1", name: "run" }] },
{ role: "user", content: [{ type: "tool_result", tool_use_id: "t1", content: "done" }] }
],
tools: [{ name: "run", description: "d" }]
},
models: ["p/a", "p/b"],
handleSingleModel,
log,
judgeModel: "p/judge"
});
const panelCalls = handleSingleModel.mock.calls.filter(([,, isPanel]) => isPanel === true);
expect(panelCalls.length).toBe(2);
const panelBody = panelCalls[0][0];
expect(panelBody.tools).toBeUndefined();
expect(panelBody.messages.length).toBe(3);
// Flattened tool_use
expect(panelBody.messages[1].content).toBe("ok\n[Called tools: run]");
// Flattened tool_result
expect(panelBody.messages[2].content).toBe("[Tool result: done]");
});
});