From ef50e0b6d8cca06aa53839a2d83445d3eb4d4164 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sun, 30 Aug 2026 14:38:51 -0500 Subject: [PATCH] fix(ai): omit empty Bedrock system blocks (#46294) --- packages/ai/src/protocols/bedrock-converse.ts | 9 +++- .../ai/test/provider/bedrock-converse.test.ts | 44 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/protocols/bedrock-converse.ts b/packages/ai/src/protocols/bedrock-converse.ts index 6e132baa1ff..006bd0b1226 100644 --- a/packages/ai/src/protocols/bedrock-converse.ts +++ b/packages/ai/src/protocols/bedrock-converse.ts @@ -410,7 +410,12 @@ const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* ( const lowerSystem = ( breakpoints: BedrockCache.Breakpoints, system: ReadonlyArray, -): BedrockSystemBlock[] => system.flatMap((part) => textWithCache(breakpoints, part.text, part.cache)) +) => { + const content = system + .filter((part) => part.text.length > 0) + .flatMap((part) => textWithCache(breakpoints, part.text, part.cache)) + return content.length === 0 ? undefined : content +} const fromRequest = Effect.fn("BedrockConverse.fromRequest")(function* (request: LLMRequest) { const toolChoice = request.toolChoice ? yield* lowerToolChoice(request.toolChoice) : undefined @@ -427,7 +432,7 @@ const fromRequest = Effect.fn("BedrockConverse.fromRequest")(function* (request: toolChoice, } })() - const system = request.system.length === 0 ? undefined : lowerSystem(breakpoints, request.system) + const system = lowerSystem(breakpoints, request.system) const messages = yield* lowerMessages(request, breakpoints) if (breakpoints.dropped > 0) { yield* Effect.logWarning( diff --git a/packages/ai/test/provider/bedrock-converse.test.ts b/packages/ai/test/provider/bedrock-converse.test.ts index 95ce1140a05..5c7fe2914de 100644 --- a/packages/ai/test/provider/bedrock-converse.test.ts +++ b/packages/ai/test/provider/bedrock-converse.test.ts @@ -125,6 +125,50 @@ describe("Bedrock Converse route", () => { }), ) + it.effect("omits empty initial system blocks", () => + Effect.gen(function* () { + const empty = yield* compileRequest(LLM.request({ model, system: "", prompt: "hello" })) + const cachedEmpty = yield* compileRequest( + LLM.request({ + model, + system: [{ type: "text", text: "", cache: new CacheHint({ type: "ephemeral" }) }], + prompt: "hello", + cache: "none", + }), + ) + + expect(empty.body.system).toBeUndefined() + expect(cachedEmpty.body.system).toBeUndefined() + }), + ) + + it.effect("omits empty system blocks while preserving order and cache hints", () => + Effect.gen(function* () { + const cache = new CacheHint({ type: "ephemeral" }) + const prepared = yield* compileRequest( + LLM.request({ + model, + system: [ + { type: "text", text: "", cache }, + { type: "text", text: "First." }, + { type: "text", text: " " }, + { type: "text", text: "" }, + { type: "text", text: "Second.", cache }, + ], + prompt: "hello", + cache: "none", + }), + ) + + expect(prepared.body.system).toEqual([ + { text: "First." }, + { text: " " }, + { text: "Second." }, + { cachePoint: { type: "default" } }, + ]) + }), + ) + it.effect("passes topK through additionalModelRequestFields as top_k", () => Effect.gen(function* () { const prepared = yield* compileRequest(