diff --git a/packages/types/src/providers/bedrock.ts b/packages/types/src/providers/bedrock.ts index 9ea52bced8..d9571da5bd 100644 --- a/packages/types/src/providers/bedrock.ts +++ b/packages/types/src/providers/bedrock.ts @@ -520,6 +520,16 @@ export const BEDROCK_REGIONS = [ { value: "us-gov-west-1", label: "us-gov-west-1" }, ].sort((a, b) => a.value.localeCompare(b.value)) +// Older Claude 3 models on Bedrock that do NOT support the fine-grained-tool-streaming beta. +// Sending this beta flag to these models causes Bedrock to reject the request with +// "invalid beta flag". See: https://github.com/RooCodeInc/Roo-Code/issues/11715 +export const BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS = [ + "anthropic.claude-3-haiku-20240307-v1:0", + "anthropic.claude-3-opus-20240229-v1:0", + "anthropic.claude-3-sonnet-20240229-v1:0", + "anthropic.claude-3-5-sonnet-20240620-v1:0", +] as const + export const BEDROCK_1M_CONTEXT_MODEL_IDS = [ "anthropic.claude-sonnet-4-20250514-v1:0", "anthropic.claude-sonnet-4-5-20250929-v1:0", diff --git a/src/api/providers/__tests__/bedrock.spec.ts b/src/api/providers/__tests__/bedrock.spec.ts index 975e38af12..ce53bfb737 100644 --- a/src/api/providers/__tests__/bedrock.spec.ts +++ b/src/api/providers/__tests__/bedrock.spec.ts @@ -38,6 +38,7 @@ import { AwsBedrockHandler } from "../bedrock" import { ConverseStreamCommand, BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime" import { BEDROCK_1M_CONTEXT_MODEL_IDS, + BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS, BEDROCK_SERVICE_TIER_MODEL_IDS, bedrockModels, ApiProviderError, @@ -843,6 +844,68 @@ describe("AwsBedrockHandler", () => { expect(commandArg.additionalModelRequestFields.anthropic_beta).not.toContain("context-1m-2025-08-07") }) + it("should NOT include fine-grained-tool-streaming beta for older Claude 3 models", async () => { + // Test with Claude 3 Haiku - the model from the original bug report + for (const unsupportedModelId of BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS) { + const handler = new AwsBedrockHandler({ + apiModelId: unsupportedModelId, + awsAccessKey: "test", + awsSecretKey: "test", + awsRegion: "us-east-1", + }) + + const messages: Anthropic.Messages.MessageParam[] = [ + { + role: "user", + content: "Test message", + }, + ] + + mockConverseStreamCommand.mockClear() + + const generator = handler.createMessage("", messages) + await generator.next() + + expect(mockConverseStreamCommand).toHaveBeenCalled() + const commandArg = mockConverseStreamCommand.mock.calls[0][0] as any + + // Older Claude 3 models should NOT have fine-grained-tool-streaming beta + if (commandArg.additionalModelRequestFields?.anthropic_beta) { + expect(commandArg.additionalModelRequestFields.anthropic_beta).not.toContain( + "fine-grained-tool-streaming-2025-05-14", + ) + } + } + }) + + it("should still include fine-grained-tool-streaming beta for newer Claude models", async () => { + const handler = new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test", + awsSecretKey: "test", + awsRegion: "us-east-1", + }) + + const messages: Anthropic.Messages.MessageParam[] = [ + { + role: "user", + content: "Test message", + }, + ] + + const generator = handler.createMessage("", messages) + await generator.next() + + expect(mockConverseStreamCommand).toHaveBeenCalled() + const commandArg = mockConverseStreamCommand.mock.calls[0][0] as any + + // Newer Claude models should still have the beta + expect(commandArg.additionalModelRequestFields).toBeDefined() + expect(commandArg.additionalModelRequestFields.anthropic_beta).toContain( + "fine-grained-tool-streaming-2025-05-14", + ) + }) + it("should enable 1M context window with cross-region inference for Claude Sonnet 4", () => { const handler = new AwsBedrockHandler({ apiModelId: BEDROCK_1M_CONTEXT_MODEL_IDS[0], diff --git a/src/api/providers/bedrock.ts b/src/api/providers/bedrock.ts index 3ceb251003..94e0ebb19c 100644 --- a/src/api/providers/bedrock.ts +++ b/src/api/providers/bedrock.ts @@ -27,6 +27,7 @@ import { BEDROCK_DEFAULT_CONTEXT, AWS_INFERENCE_PROFILE_MAPPING, BEDROCK_1M_CONTEXT_MODEL_IDS, + BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS, BEDROCK_GLOBAL_INFERENCE_MODEL_IDS, BEDROCK_SERVICE_TIER_MODEL_IDS, BEDROCK_SERVICE_TIER_PRICING, @@ -436,9 +437,14 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH anthropicBetas.push("context-1m-2025-08-07") } - // Add fine-grained tool streaming beta for Claude models - // This enables proper tool use streaming for Anthropic models on Bedrock - if (baseModelId.includes("claude")) { + // Add fine-grained tool streaming beta for Claude models that support it. + // Older Claude 3 models (Haiku, Opus, Sonnet, and original 3.5 Sonnet) do not + // support this beta flag and Bedrock rejects the request with "invalid beta flag". + // See: https://github.com/RooCodeInc/Roo-Code/issues/11715 + if ( + baseModelId.includes("claude") && + !BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS.includes(baseModelId as any) + ) { anthropicBetas.push("fine-grained-tool-streaming-2025-05-14") }