Skip to content

Commit f5ccba2

Browse files
committed
fix: filter empty/whitespace text content blocks at provider boundaries
Skip empty and whitespace-only text content blocks at each provider's message conversion layer, preventing 400 errors from Anthropic, Bedrock, Venice, and other OpenAI-compatible APIs. - Anthropic: check .trim() instead of truthiness in convertMessageContentToBlocks - Bedrock (core): skip empty text in _convertMessageContentToBlocks - Bedrock (adapter): skip empty text parts in user message conversion - OpenAI adapter: filter empty text parts from assistant array content Fixes #9232, #9765, #9767, #10148, #10293, #10504, #10804, #11045, #11264, #11446, #11497, #11728
1 parent afa6bab commit f5ccba2

4 files changed

Lines changed: 15 additions & 6 deletions

File tree

core/llm/llms/Anthropic.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class Anthropic extends BaseLLM {
9090
): ContentBlockParam[] {
9191
const parts: ContentBlockParam[] = [];
9292
if (typeof content === "string") {
93-
if (content) {
93+
if (content.trim()) {
9494
parts.push({
9595
type: "text",
9696
text: content,
@@ -99,7 +99,7 @@ class Anthropic extends BaseLLM {
9999
} else {
100100
for (const part of content) {
101101
if (part.type === "text") {
102-
if (part.text) {
102+
if (part.text?.trim()) {
103103
parts.push({
104104
type: "text",
105105
text: part.text,

core/llm/llms/Bedrock.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,11 +538,15 @@ class Bedrock extends BaseLLM {
538538
): ContentBlock[] {
539539
const blocks: ContentBlock[] = [];
540540
if (typeof content === "string") {
541-
blocks.push({ text: content });
541+
if (content.trim()) {
542+
blocks.push({ text: content });
543+
}
542544
} else {
543545
for (const part of content) {
544546
if (part.type === "text") {
545-
blocks.push({ text: part.text });
547+
if (part.text?.trim()) {
548+
blocks.push({ text: part.text });
549+
}
546550
} else if (part.type === "imageUrl" && part.imageUrl) {
547551
const parsed = parseDataUrl(part.imageUrl.url);
548552
if (parsed) {

core/llm/openaiTypeConverters.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export function toChatMessage(
149149
typeof message.content === "string"
150150
? message.content || " " // LM Studio (and other providers) don't accept empty content
151151
: message.content
152-
.filter((part) => part.type === "text")
152+
.filter((part) => part.type === "text" && part.text?.trim())
153153
.map((part) => part as TextMessagePart),
154154
};
155155

packages/openai-adapters/src/apis/Bedrock.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,14 @@ export class BedrockApi implements BaseLlmApi {
203203
const content = message.content;
204204
if (content) {
205205
if (typeof content === "string") {
206-
currentBlocks.push({ text: content });
206+
if (content.trim()) {
207+
currentBlocks.push({ text: content });
208+
}
207209
} else {
208210
content.forEach((part) => {
211+
if (part.type === "text" && !part.text?.trim()) {
212+
return;
213+
}
209214
currentBlocks.push(this._oaiPartToBedrockPart(part));
210215
});
211216
}

0 commit comments

Comments
 (0)