diff --git a/packages/ai/src/protocols/anthropic-messages.ts b/packages/ai/src/protocols/anthropic-messages.ts index 51967866a2b..e312d0f2224 100644 --- a/packages/ai/src/protocols/anthropic-messages.ts +++ b/packages/ai/src/protocols/anthropic-messages.ts @@ -1019,10 +1019,11 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques ) // Anthropic rejects tool_choice when tools are absent; "none" is only meaningful with tools present. const toolChoice = tools === undefined || !request.toolChoice ? undefined : yield* lowerToolChoice(request.toolChoice) + const systemParts = request.system.filter((part) => part.text.length > 0) const system = - request.system.length === 0 + systemParts.length === 0 ? undefined - : request.system.map((part) => ({ + : systemParts.map((part) => ({ type: "text" as const, text: part.text, cache_control: cacheControl(breakpoints, part.cache), diff --git a/packages/ai/test/provider/anthropic-messages.test.ts b/packages/ai/test/provider/anthropic-messages.test.ts index 93fe120480f..f5fa21ca68d 100644 --- a/packages/ai/test/provider/anthropic-messages.test.ts +++ b/packages/ai/test/provider/anthropic-messages.test.ts @@ -74,6 +74,16 @@ describe("Anthropic Messages route", () => { }), ) + it.effect("omits empty system text while preserving whitespace", () => + Effect.gen(function* () { + const empty = yield* compileRequest(LLMRequest.update(request, { system: [{ type: "text", text: "" }] })) + const whitespace = yield* compileRequest(LLMRequest.update(request, { system: [{ type: "text", text: " " }] })) + + expect(empty.body.system).toBeUndefined() + expect(whitespace.body.system).toEqual([{ type: "text", text: " " }]) + }), + ) + it.effect("lowers adaptive thinking settings with effort", () => Effect.gen(function* () { const prepared = yield* compileRequest(