From 2fa78150b8874215be87b27dddee2f96662a75c4 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Wed, 15 Jul 2026 11:48:30 -0300 Subject: [PATCH] refactor(sse): extract Claude chunk-merge helpers to fix complexity ratchet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mergeChunksToResponse() regressed both quality ratchets by +1 (complexity 2057>2056, cognitive 891>890). Split the Claude-format reconstruction into buildClaudeContentBlocks(), applyClaudeMessageDelta() and mergeClaudeChunks() — same behavior, verified by the existing bypass-response-claude-merge.test.ts (4/4 passing unchanged). --- open-sse/utils/bypassResponse.ts | 114 ++++++++++++++++++------------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/open-sse/utils/bypassResponse.ts b/open-sse/utils/bypassResponse.ts index 87f4b7c12c..0727d5ccf5 100644 --- a/open-sse/utils/bypassResponse.ts +++ b/open-sse/utils/bypassResponse.ts @@ -72,65 +72,85 @@ export function createOpenAIStreamingChunks(completeResponse) { ]; } +/** + * Reconstruct the Claude `content` array from the content_block_start/delta + * events emitted for a synthetic (one-shot) response. The translator always + * starts `message_start.message.content` empty and streams blocks in via + * separate events, so the blocks have to be replayed and merged by index. + */ +function buildClaudeContentBlocks(chunks) { + const blockMap = new Map(); + for (const chunk of chunks) { + if (chunk?.type === "content_block_start" && typeof chunk.index === "number") { + blockMap.set(chunk.index, { ...(chunk.content_block || {}) }); + } + if (chunk?.type === "content_block_delta" && typeof chunk.index === "number") { + const current = blockMap.get(chunk.index) || { type: "text", text: "" }; + if (chunk.delta?.type === "text_delta") { + current.type = current.type || "text"; + current.text = `${current.text || ""}${chunk.delta.text || ""}`; + } + blockMap.set(chunk.index, current); + } + } + return [...blockMap.entries()].sort((a, b) => a[0] - b[0]).map(([, block]) => block); +} + +/** Apply the trailing message_delta's usage/stop fields onto the merged message. */ +function applyClaudeMessageDelta(mergedMessage, messageStart, messageDelta) { + const startUsage = messageStart.message.usage; + const deltaUsage = messageDelta?.usage; + if (startUsage || deltaUsage) { + mergedMessage.usage = { + ...(startUsage || {}), + ...(deltaUsage || {}), + }; + } + if (messageDelta?.delta?.stop_reason !== undefined) { + mergedMessage.stop_reason = messageDelta.delta.stop_reason; + } + if (messageDelta?.delta?.stop_sequence !== undefined) { + mergedMessage.stop_sequence = messageDelta.delta.stop_sequence; + } +} + +/** + * Reconstruct the final Claude message from a synthetic bypass response's + * chunk stream — taking the raw `message_start.message` would return an + * empty `content: []`. Falls back to `fallback` (the raw last chunk) when + * the stream never completed or never carried a `message_start`. + */ +function mergeClaudeChunks(chunks, fallback) { + const messageStop = chunks.find((c) => c.type === "message_stop"); + if (!messageStop) return fallback; + + const messageStart = chunks.find((c) => c.type === "message_start"); + if (!messageStart?.message) return fallback; + + const messageDelta = chunks.find((c) => c.type === "message_delta"); + const mergedMessage = { + ...messageStart.message, + content: buildClaudeContentBlocks(chunks), + }; + applyClaudeMessageDelta(mergedMessage, messageStart, messageDelta); + return mergedMessage; +} + /** * Merge translated chunks into a final response object (for non-streaming * callers). For most formats the last chunk is already complete. Claude * format is chunk-oriented even for "one-shot" synthetic responses, so the - * final message has to be reconstructed from content_block_start/delta - * events — taking the raw message_start.message would return an empty - * `content: []` (the translator always starts it empty and streams blocks - * in via separate events). + * final message has to be reconstructed — see mergeClaudeChunks() above. */ export function mergeChunksToResponse(chunks, sourceFormat) { if (!chunks || chunks.length === 0) { return createOpenAIResponse("unknown"); } - let finalChunk = chunks[chunks.length - 1]; + const finalChunk = chunks[chunks.length - 1]; if (sourceFormat === FORMATS.CLAUDE) { - const messageStop = chunks.find((c) => c.type === "message_stop"); - if (messageStop) { - const messageDelta = chunks.find((c) => c.type === "message_delta"); - const messageStart = chunks.find((c) => c.type === "message_start"); - - if (messageStart?.message) { - finalChunk = { ...messageStart.message, content: [] }; - - const blockMap = new Map(); - for (const chunk of chunks) { - if (chunk?.type === "content_block_start" && typeof chunk.index === "number") { - blockMap.set(chunk.index, { ...(chunk.content_block || {}) }); - } - if (chunk?.type === "content_block_delta" && typeof chunk.index === "number") { - const current = blockMap.get(chunk.index) || { type: "text", text: "" }; - if (chunk.delta?.type === "text_delta") { - current.type = current.type || "text"; - current.text = `${current.text || ""}${chunk.delta.text || ""}`; - } - blockMap.set(chunk.index, current); - } - } - finalChunk.content = [...blockMap.entries()] - .sort((a, b) => a[0] - b[0]) - .map(([, block]) => block); - - const startUsage = messageStart.message.usage; - const deltaUsage = messageDelta?.usage; - if (startUsage || deltaUsage) { - finalChunk.usage = { - ...(startUsage || {}), - ...(deltaUsage || {}), - }; - } - if (messageDelta?.delta?.stop_reason !== undefined) { - finalChunk.stop_reason = messageDelta.delta.stop_reason; - } - if (messageDelta?.delta?.stop_sequence !== undefined) { - finalChunk.stop_sequence = messageDelta.delta.stop_sequence; - } - } - } + return mergeClaudeChunks(chunks, finalChunk); } return finalChunk;