diff --git a/src/api/providers/__tests__/anthropic.spec.ts b/src/api/providers/__tests__/anthropic.spec.ts index e41d5e3a25..3a92061eb6 100644 --- a/src/api/providers/__tests__/anthropic.spec.ts +++ b/src/api/providers/__tests__/anthropic.spec.ts @@ -58,6 +58,7 @@ vitest.mock("../../transform/ai-sdk", () => ({ // Import mocked modules import { convertToolsForAiSdk, mapToolChoice } from "../../transform/ai-sdk" +import { sanitizeMessagesForProvider } from "../../transform/sanitize-messages" import { Anthropic } from "@anthropic-ai/sdk" // Helper: create a mock provider function @@ -399,6 +400,51 @@ describe("AnthropicHandler", () => { expect(endChunk).toBeDefined() }) + it("should strip reasoning_details and reasoning_content from messages before sending to API", async () => { + // Override the identity mock with the real implementation for this test + const { sanitizeMessagesForProvider: realSanitize } = await vi.importActual< + typeof import("../../transform/sanitize-messages") + >("../../transform/sanitize-messages") + vi.mocked(sanitizeMessagesForProvider).mockImplementation(realSanitize) + + setupStreamTextMock([{ type: "text-delta", text: "test" }]) + + // Simulate messages with extra legacy fields that survive JSON deserialization + const messagesWithExtraFields = [ + { + role: "user", + content: [{ type: "text" as const, text: "Hello" }], + }, + { + role: "assistant", + content: [{ type: "text" as const, text: "Hi" }], + reasoning_details: [{ type: "thinking", thinking: "some reasoning" }], + reasoning_content: "some reasoning content", + }, + { + role: "user", + content: [{ type: "text" as const, text: "Follow up" }], + }, + ] as any + + const stream = handler.createMessage(systemPrompt, messagesWithExtraFields) + + for await (const _chunk of stream) { + // Consume stream + } + + // Verify streamText was called exactly once + expect(mockStreamText).toHaveBeenCalledTimes(1) + const callArgs = mockStreamText.mock.calls[0]![0] + for (const msg of callArgs.messages) { + expect(msg).not.toHaveProperty("reasoning_details") + expect(msg).not.toHaveProperty("reasoning_content") + } + // Verify the rest of the message is preserved + expect(callArgs.messages[1].role).toBe("assistant") + expect(callArgs.messages[1].content).toEqual([{ type: "text", text: "Hi" }]) + }) + it("should pass system prompt via system param when no systemProviderOptions", async () => { setupStreamTextMock([{ type: "text-delta", text: "test" }])