From 2ddf257c6f2c54386c7290609596acd851d9df95 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sun, 30 Aug 2026 14:39:46 -0500 Subject: [PATCH] fix(ai): filter empty Anthropic messages (#46291) --- .../ai/src/protocols/anthropic-messages.ts | 6 ++-- .../test/provider/anthropic-messages.test.ts | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/protocols/anthropic-messages.ts b/packages/ai/src/protocols/anthropic-messages.ts index e312d0f2224..6388d4184f4 100644 --- a/packages/ai/src/protocols/anthropic-messages.ts +++ b/packages/ai/src/protocols/anthropic-messages.ts @@ -831,6 +831,7 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* ( const content: AnthropicUserBlock[] = [] for (const part of message.content) { if (part.type === "text") { + if (part.text.trim().length === 0) continue content.push({ type: "text", text: part.text, cache_control: cacheControl(breakpoints, part.cache) }) continue } @@ -840,7 +841,7 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* ( } return yield* ProviderShared.unsupportedContent("Anthropic Messages", "user", ["text", "media"]) } - messages.push({ role: "user", content }) + if (content.length > 0) messages.push({ role: "user", content }) continue } @@ -848,6 +849,7 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* ( const content: AnthropicAssistantBlock[] = [] for (const part of message.content) { if (part.type === "text") { + if (part.text.trim().length === 0) continue content.push({ type: "text", text: part.text, cache_control: cacheControl(breakpoints, part.cache) }) continue } @@ -891,7 +893,7 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* ( `Anthropic Messages assistant messages only support text, reasoning, and tool-call content for now`, ) } - messages.push({ role: "assistant", content }) + if (content.length > 0) messages.push({ role: "assistant", content }) continue } diff --git a/packages/ai/test/provider/anthropic-messages.test.ts b/packages/ai/test/provider/anthropic-messages.test.ts index f5fa21ca68d..b5696462f81 100644 --- a/packages/ai/test/provider/anthropic-messages.test.ts +++ b/packages/ai/test/provider/anthropic-messages.test.ts @@ -84,6 +84,38 @@ describe("Anthropic Messages route", () => { }), ) + it.effect("filters whitespace-only text and removes empty messages", () => + Effect.gen(function* () { + const prepared = yield* compileRequest( + LLM.request({ + model, + messages: [ + Message.user(" \n\t"), + Message.user([]), + Message.user([ + { type: "text", text: "" }, + { type: "text", text: " Keep this spacing. " }, + { type: "text", text: " \n\t" }, + ]), + Message.assistant(" \n\t"), + Message.assistant([]), + Message.assistant([{ type: "reasoning", text: "" }]), + Message.assistant([ + { type: "text", text: "" }, + { type: "reasoning", text: "", providerMetadata: { anthropic: { signature: "sig_1" } } }, + ]), + ], + cache: "none", + }), + ) + + expect(prepared.body.messages).toEqual([ + { role: "user", content: [{ type: "text", text: " Keep this spacing. " }] }, + { role: "assistant", content: [{ type: "thinking", thinking: "", signature: "sig_1" }] }, + ]) + }), + ) + it.effect("lowers adaptive thinking settings with effort", () => Effect.gen(function* () { const prepared = yield* compileRequest(