From f084fb0a96593881cac153dc1d62173d674c02e1 Mon Sep 17 00:00:00 2001 From: herjarsa Date: Fri, 26 Jun 2026 15:03:25 +0200 Subject: [PATCH 1/2] fix: recognize Claude API format in detectMalformedNonStream detectMalformedNonStream() only recognized OpenAI Chat Completions and Responses API shapes. When a Claude passthrough response (type:message + content:[]) reached this check, the function fell through both branches and returned 'empty_choices', causing chatCore to reject valid Claude responses with a 502. Added Claude API format recognition between the Responses API and Chat Completions checks: type:'message' + content array with text/tool_use/ tool_result blocks. Matches the same pattern used by the other two format detectors. This fixes 5 pre-existing test failures in upstream/main: - chatCore normalizes native Claude Code messages for native Claude OAuth passthrough - chatCore keeps Claude normalization for non-Claude-Code Claude passthrough - chatCore normalizes native Claude Code messages before CC-compatible relay transforms - chatCore restores prefixed Claude passthrough tool names in upstream responses - chatCore records Claude prompt cache and cache usage metadata in call logs --- open-sse/utils/diagnostics.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/open-sse/utils/diagnostics.ts b/open-sse/utils/diagnostics.ts index 8c58358c80e3..6e366d1e64d7 100644 --- a/open-sse/utils/diagnostics.ts +++ b/open-sse/utils/diagnostics.ts @@ -200,6 +200,29 @@ export function detectMalformedNonStream(resp: unknown): MalformedReason | null return null; } + // ── Claude API shape (native passthrough: type:"message" + content:[]) ── + if (body.type === "message") { + const content = body.content; + if (!Array.isArray(content) || content.length === 0) return "empty_choices"; + + const hasOutput = content.some((block: Record) => { + if ( + block.type === "text" && + typeof block.text === "string" && + (block.text as string).length > 0 + ) + return true; + if (block.type === "tool_use") return true; + if (block.type === "tool_result") return true; + return false; + }); + + if (!hasOutput) return "empty_choices"; + const stopReason = body.stop_reason; + if (stopReason === null) return "no_terminal"; + return null; + } + // ── Chat Completions shape ── const choices = body.choices; if (!Array.isArray(choices) || choices.length === 0) return "empty_choices"; From 33c964dbff1e2c17b90a6170b394792565835d75 Mon Sep 17 00:00:00 2001 From: herjarsa Date: Fri, 26 Jun 2026 16:10:47 +0200 Subject: [PATCH 2/2] fix(diagnostics): add defensive null/type check for Claude content array blocks Gemini Code Assist review: block elements in content array may be null or non-object, causing runtime crash on property access. Adds null guard and removes redundant type assertion. --- open-sse/utils/diagnostics.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/open-sse/utils/diagnostics.ts b/open-sse/utils/diagnostics.ts index 6e366d1e64d7..289f006a7698 100644 --- a/open-sse/utils/diagnostics.ts +++ b/open-sse/utils/diagnostics.ts @@ -206,11 +206,8 @@ export function detectMalformedNonStream(resp: unknown): MalformedReason | null if (!Array.isArray(content) || content.length === 0) return "empty_choices"; const hasOutput = content.some((block: Record) => { - if ( - block.type === "text" && - typeof block.text === "string" && - (block.text as string).length > 0 - ) + if (block === null || typeof block !== "object") return false; + if (block.type === "text" && typeof block.text === "string" && block.text.length > 0) return true; if (block.type === "tool_use") return true; if (block.type === "tool_result") return true;