fix(translator): keep tool-result images, restore Kiro tool names, preserve thinking display

Forward images inside tool_result to OpenAI and Kiro upstreams via following user messages, restore original client tool names on Kiro responses via _toolNameMap, and preserve thinking display settings across translations.
This commit is contained in:
Manan Santoki
2026-09-17 18:11:20 +07:00
parent 0c6ab4f99b
commit f4f06f290c
12 changed files with 328 additions and 23 deletions

View File

@@ -415,6 +415,28 @@ export function anchorClaudeCache(body) {
// - Add thinking block for Anthropic endpoint (provider === "claude")
// - Fix tool_use/tool_result ordering
// - Apply cloaking (billing header + fake user ID) for OAuth tokens
export function hoistToolResultImages(body) {
if (!Array.isArray(body?.messages)) return body;
let touched = false;
const messages = body.messages.map((msg) => {
if (msg?.role !== ROLE.USER || !Array.isArray(msg.content)) return msg;
const hoisted = [];
const content = msg.content.map((block) => {
if (block?.type !== CLAUDE_BLOCK.TOOL_RESULT || !Array.isArray(block.content)) return block;
const images = block.content.filter((c) => c?.type === CLAUDE_BLOCK.IMAGE);
if (!images.length) return block;
const rest = block.content.filter((c) => c?.type !== CLAUDE_BLOCK.IMAGE);
hoisted.push({ type: CLAUDE_BLOCK.TEXT, text: `[Image from tool result ${block.tool_use_id}]` }, ...images);
return { ...block, content: rest.length ? rest : [{ type: CLAUDE_BLOCK.TEXT, text: "(image attached below)" }] };
});
if (!hoisted.length) return msg;
touched = true;
// tool_result blocks must lead a user message; the hoisted image follows them.
return { ...msg, content: [...content, ...hoisted] };
});
return touched ? { ...body, messages } : body;
}
export function prepareClaudeRequest(body, provider = null, apiKey = null, connectionId = null, rawHeaders = null, sessionId = null) {
// quirk: MiniMax's Claude-compatible endpoint rejects Anthropic's output_config (400 invalid params)
if (PROVIDERS[provider]?.quirks?.dropOutputConfig) {
@@ -608,6 +630,14 @@ export function prepareClaudeRequest(body, provider = null, apiKey = null, conne
}
}
// Anthropic itself reads images inside tool_result; other Anthropic-compatible
// endpoints (OpenCode Go, Kimi, DeepSeek, GLM, MiniMax) accept image blocks
// only as user content and silently drop them inside a tool result. Move a
// tool's screenshot out of the result and into the same user turn.
if (provider !== "claude" && !provider?.startsWith("anthropic-compatible")) {
body = hoistToolResultImages(body);
}
// Apply cloaking for OAuth tokens (billing header + fake user ID)
// session_id in user_id must match X-Claude-Code-Session-Id for fingerprint consistency
if ((provider === "claude" || provider?.startsWith("anthropic-compatible")) && apiKey) {