From 0d0d553e2397e34b0f1a77e4c449bb134c60d450 Mon Sep 17 00:00:00 2001 From: Dayuan Jiang <34411969+DayuanJiang@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:34:42 +0900 Subject: [PATCH] fix: correct anthropic beta header config for fine-grained tool streaming (#27) * fix: correct anthropic beta header config for fine-grained tool streaming - Use bedrock.anthropicBeta for Bedrock provider (not additionalModelRequestFields) - Use top-level headers for direct Anthropic API - Update @ai-sdk/amazon-bedrock to 3.0.62 - Add headers support to ModelConfig interface * fix: update @ai-sdk/amazon-bedrock to 3.0.62 for tool streaming support --- app/api/chat/route.ts | 3 ++- lib/ai-providers.ts | 33 ++++++++++++++----------- package-lock.json | 57 +++++++++++++++---------------------------- package.json | 2 +- 4 files changed, 42 insertions(+), 53 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index b71d9d2..e6c12ca 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -120,13 +120,14 @@ ${lastMessageText} console.log("Enhanced messages:", enhancedMessages); // Get AI model from environment configuration - const { model, providerOptions } = getAIModel(); + const { model, providerOptions, headers } = getAIModel(); const result = streamText({ model, system: systemMessage, messages: enhancedMessages, ...(providerOptions && { providerOptions }), + ...(headers && { headers }), tools: { // Client-side tool that will be executed on the client display_diagram: { diff --git a/lib/ai-providers.ts b/lib/ai-providers.ts index 13c359e..b2eda07 100644 --- a/lib/ai-providers.ts +++ b/lib/ai-providers.ts @@ -18,15 +18,19 @@ export type ProviderName = interface ModelConfig { model: any; providerOptions?: any; + headers?: Record; } -// Anthropic beta headers for fine-grained tool streaming -const ANTHROPIC_BETA_OPTIONS = { - anthropic: { - additionalModelRequestFields: { - anthropic_beta: ['fine-grained-tool-streaming-2025-05-14'] - } - } +// Bedrock provider options for Anthropic beta features +const BEDROCK_ANTHROPIC_BETA = { + bedrock: { + anthropicBeta: ['fine-grained-tool-streaming-2025-05-14'], + }, +}; + +// Direct Anthropic API headers for beta features +const ANTHROPIC_BETA_HEADERS = { + 'anthropic-beta': 'fine-grained-tool-streaming-2025-05-14', }; /** @@ -87,13 +91,14 @@ export function getAIModel(): ModelConfig { let model: any; let providerOptions: any = undefined; + let headers: Record | undefined = undefined; switch (provider) { case 'bedrock': model = bedrock(modelId); - // Add Anthropic beta headers if using Claude models via Bedrock + // Add Anthropic beta options if using Claude models via Bedrock if (modelId.includes('anthropic.claude')) { - providerOptions = ANTHROPIC_BETA_OPTIONS; + providerOptions = BEDROCK_ANTHROPIC_BETA; } break; @@ -112,7 +117,7 @@ export function getAIModel(): ModelConfig { case 'anthropic': model = anthropic(modelId); // Add beta headers for fine-grained tool streaming - providerOptions = ANTHROPIC_BETA_OPTIONS; + headers = ANTHROPIC_BETA_HEADERS; break; case 'google': @@ -140,10 +145,10 @@ export function getAIModel(): ModelConfig { ); } - // Log if provider options are being applied - if (providerOptions) { - console.log('[AI Provider] Applying provider-specific options'); + // Log if provider options or headers are being applied + if (providerOptions || headers) { + console.log('[AI Provider] Applying provider-specific options/headers'); } - return { model, providerOptions }; + return { model, providerOptions, headers }; } diff --git a/package-lock.json b/package-lock.json index 8a84335..4f43218 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "next-ai-draw-io", "version": "0.2.0", "dependencies": { - "@ai-sdk/amazon-bedrock": "^3.0.52", + "@ai-sdk/amazon-bedrock": "^3.0.62", "@ai-sdk/anthropic": "^2.0.44", "@ai-sdk/azure": "^2.0.69", "@ai-sdk/google": "^2.0.0", @@ -52,14 +52,14 @@ } }, "node_modules/@ai-sdk/amazon-bedrock": { - "version": "3.0.53", - "resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-3.0.53.tgz", - "integrity": "sha512-HyVLZbdGunqJbdCK2v/jofo9Z4lDAbngO2X/T57K+4wPZtCeUnv0f9F941RgU6XVJwdxjxITX1XEhhBP1qqGnw==", + "version": "3.0.62", + "resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-3.0.62.tgz", + "integrity": "sha512-vVtndaj5zfHmgw8NSqN4baFDbFDTBZP6qufhKfqSNLtygEm8+8PL9XQX9urgzSzU3zp+zi3AmNNemvKLkkqblg==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/anthropic": "2.0.43", + "@ai-sdk/anthropic": "2.0.50", "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.16", + "@ai-sdk/provider-utils": "3.0.18", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" @@ -71,14 +71,15 @@ "zod": "^3.25.76 || ^4.1.8" } }, - "node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/anthropic": { - "version": "2.0.43", - "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.43.tgz", - "integrity": "sha512-YQWYdoU6X1E16BS/KYCkage18q8sqj3FguCZ/RQs/wxS1551DVeD5DrWiYXxm5T293HzeAVJssQFEx67kc4LmA==", + "node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider-utils": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz", + "integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.16" + "@standard-schema/spec": "^1.0.0", + "eventsource-parser": "^3.0.6" }, "engines": { "node": ">=18" @@ -88,13 +89,13 @@ } }, "node_modules/@ai-sdk/anthropic": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.44.tgz", - "integrity": "sha512-o8TfNXRzO/KZkBrcx+CL9LQsPhx7PHyqzUGjza3TJaF9WxfH1S5UQLAmEw8F7lQoHNLU0IX03WT8o8R/4JbUxQ==", + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.50.tgz", + "integrity": "sha512-21PaHfoLmouOXXNINTsZJsMw+wE5oLR2He/1kq/sKokTVKyq7ObGT1LDk6ahwxaz/GoaNaGankMh+EgVcdv2Cw==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.17" + "@ai-sdk/provider-utils": "3.0.18" }, "engines": { "node": ">=18" @@ -104,9 +105,9 @@ } }, "node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider-utils": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.17.tgz", - "integrity": "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz", + "integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "2.0.0", @@ -494,7 +495,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -818,7 +818,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -841,7 +840,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2718,7 +2716,6 @@ "integrity": "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2729,7 +2726,6 @@ "integrity": "sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.0.0" } @@ -2786,7 +2782,6 @@ "integrity": "sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.48.0", "@typescript-eslint/types": "8.48.0", @@ -3329,7 +3324,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3361,7 +3355,6 @@ "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.90.tgz", "integrity": "sha512-bawNN10N2cXzFedbDdNUZo8KkcGp12VX1b+mCL5dfllh6WmLsIYYME7GVxsRJvHvPP7xRhuds5fn0jtLyxGnZw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@ai-sdk/gateway": "2.0.7", "@ai-sdk/provider": "2.0.0", @@ -3739,7 +3732,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -4482,7 +4474,6 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4668,7 +4659,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -7355,7 +7345,6 @@ "resolved": "https://registry.npmjs.org/next/-/next-15.2.3.tgz", "integrity": "sha512-x6eDkZxk2rPpu46E1ZVUWIBhYCLszmUY6fvHBFcbzJ9dD+qRX6vcHusaqqDlnY+VngKzKbAiG2iRCkPbmi8f7w==", "license": "MIT", - "peer": true, "dependencies": { "@next/env": "15.2.3", "@swc/counter": "0.1.3", @@ -7843,7 +7832,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -7853,7 +7841,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -8676,8 +8663,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.2.tgz", "integrity": "sha512-VCsK+fitIbQF7JlxXaibFhxrPq4E2hDcG8apzHUdWFMCQWD8uLdlHg4iSkZ53cgLCCcZ+FZK7vG8VjvLcnBgKw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tailwindcss-animate": { "version": "1.0.7", @@ -8751,7 +8737,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -8966,7 +8951,6 @@ "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9486,7 +9470,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index a1e1b9d..41dddf2 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@ai-sdk/amazon-bedrock": "^3.0.52", + "@ai-sdk/amazon-bedrock": "^3.0.62", "@ai-sdk/anthropic": "^2.0.44", "@ai-sdk/azure": "^2.0.69", "@ai-sdk/google": "^2.0.0",