Unverified 提交 938595aa authored 作者: Samrat Jha's avatar Samrat Jha 提交者: GitHub

Add support for Amazon Bedrock provider (#1185)

- follows existing patterns for AI SDK to provide Bedrock integration - Uses Bedrock's API token feature for authentication which provides a standard experience - bedrock provided models match the Anthropic provided models (for now) **Disclaimer**: The contributing docs are extremely sparse. I don't actually know how to build this and get this running in Electron ## Testing - AWS Bedrock provider is available for selection <img width="994" height="496" alt="image" src="https://github.com/user-attachments/assets/3cb21fed-9826-40e5-8019-b2b5df5e873b" /> - The provider settings also show the right models and offer the right env variable to use <img width="949" height="862" alt="image" src="https://github.com/user-attachments/assets/8c23d5c8-d84d-4bf7-856a-8dc8d9d6c4b4" /> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds AWS Bedrock as a provider so users can run Claude models via Bedrock with API token authentication. The settings now list Bedrock with supported models and a new env var. - New Features - New provider: bedrock using @ai-sdk/amazon-bedrock, wired into model client and schemas. - Models: Claude 4 Sonnet, Claude 3.7 Sonnet, Claude 3.5 Sonnet (Bedrock model IDs). - Settings: shows AWS Bedrock with correct models and env var AWS_BEARER_TOKEN_BEDROCK. - Default region: us-east-1. - Migration - Set AWS_BEARER_TOKEN_BEDROCK with your Bedrock API token. - Select AWS Bedrock in settings and pick a model. <!-- End of auto-generated description by cubic. --> Co-authored-by: 's avatarSamrat Jha <samratj@amazon.com> Co-authored-by: 's avatarWill Chen <willchen90@gmail.com>
上级 4db6d63b
......@@ -9,6 +9,7 @@
"version": "0.20.0-beta.1",
"license": "MIT",
"dependencies": {
"@ai-sdk/amazon-bedrock": "^3.0.15",
"@ai-sdk/anthropic": "^2.0.4",
"@ai-sdk/azure": "^2.0.17",
"@ai-sdk/google": "^2.0.6",
......@@ -129,10 +130,47 @@
"node": ">=20"
}
},
"node_modules/@ai-sdk/amazon-bedrock": {
"version": "3.0.15",
"resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-3.0.15.tgz",
"integrity": "sha512-gRzjgyeaavYO4Vq4/yILZxinGrXTN1AGaEYAvFQ7fn1CP4kAreLEVDTh2du85WTQHxFck7f3OGKRWXNqQZ7OCA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/anthropic": "2.0.11",
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.7",
"@smithy/eventstream-codec": "^4.0.1",
"@smithy/util-utf8": "^4.0.0",
"aws4fetch": "^1.0.20"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4"
}
},
"node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.7.tgz",
"integrity": "sha512-o3BS5/t8KnBL3ubP8k3w77AByOypLm+pkIL/DCw0qKkhDbvhCy+L3hRTGPikpdb8WHcylAeKsjgwOxhj4cqTUA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.5"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4"
}
},
"node_modules/@ai-sdk/anthropic": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.9.tgz",
"integrity": "sha512-1kQgL2A3PeqfEcHHmqy4NxRc8rbgLS71bHBuvDFfDz3VAAyndkilPMCLNDSP2mJVGAej2EMWJ1sShRAxzn70jA==",
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.11.tgz",
"integrity": "sha512-NCHWE/BnHm9CBw2M17kPwe4bKEUBtntzY26uvoZmWZfCvu2muYBR03pN2pdYmRRZlhpKk1kAOwPOzs9OW8ZC9Q=="
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
......@@ -373,6 +411,82 @@
"node": ">=6.0.0"
}
},
"node_modules/@aws-crypto/crc32": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
"integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/util": "^5.2.0",
"@aws-sdk/types": "^3.222.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-crypto/util": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
"integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "^3.222.0",
"@smithy/util-utf8": "^2.0.0",
"tslib": "^2.6.2"
}
},
"node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
"integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
"integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^2.2.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
"integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/util-buffer-from": "^2.2.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@aws-sdk/types": {
"version": "3.862.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.862.0.tgz",
"integrity": "sha512-Bei+RL0cDxxV+lW2UezLbCYYNeJm6Nzee0TpW0FfyTRBhH9C1XQh4+x+IClriXvgBnRquTMMYsmJfvx8iyLKrg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^4.3.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
......@@ -6100,6 +6214,83 @@
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
"node_modules/@smithy/eventstream-codec": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.5.tgz",
"integrity": "sha512-miEUN+nz2UTNoRYRhRqVTJCx7jMeILdAurStT2XoS+mhokkmz1xAPp95DFW9Gxt4iF2VBqpeF9HbTQ3kY1viOA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/crc32": "5.2.0",
"@smithy/types": "^4.3.2",
"@smithy/util-hex-encoding": "^4.0.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/is-array-buffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz",
"integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/types": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.2.tgz",
"integrity": "sha512-QO4zghLxiQ5W9UZmX2Lo0nta2PuE1sSrXUYDoaB6HMR762C0P7v/HEPHf6ZdglTVssJG1bsrSBxdc3quvDSihw==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/util-buffer-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz",
"integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^4.0.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/util-hex-encoding": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz",
"integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/util-utf8": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz",
"integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/util-buffer-from": "^4.0.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@standard-schema/spec": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
......@@ -7875,6 +8066,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/aws4fetch": {
"version": "1.0.20",
"resolved": "https://registry.npmjs.org/aws4fetch/-/aws4fetch-1.0.20.tgz",
"integrity": "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
......
......@@ -85,6 +85,7 @@
"vitest": "^3.1.1"
},
"dependencies": {
"@ai-sdk/amazon-bedrock": "^3.0.15",
"@ai-sdk/anthropic": "^2.0.4",
"@ai-sdk/azure": "^2.0.17",
"@ai-sdk/google": "^2.0.6",
......
......@@ -253,6 +253,32 @@ export const MODEL_OPTIONS: Record<string, ModelOption[]> = {
temperature: 0,
},
],
bedrock: [
{
name: "us.anthropic.claude-sonnet-4-20250514-v1:0",
displayName: "Claude 4 Sonnet",
description: "Excellent coder",
maxOutputTokens: 16_000,
contextWindow: 200_000,
temperature: 0,
},
{
name: "us.anthropic.claude-3-7-sonnet-20250219-v1:0",
displayName: "Claude 3.7 Sonnet",
description: "Excellent coder",
maxOutputTokens: 16_000,
contextWindow: 200_000,
temperature: 0,
},
{
name: "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
displayName: "Claude 3.5 Sonnet",
description: "Good coder, excellent at following instructions",
maxOutputTokens: 8_000,
contextWindow: 200_000,
temperature: 0,
},
],
};
export const PROVIDER_TO_ENV_VAR: Record<string, string> = {
......@@ -261,6 +287,7 @@ export const PROVIDER_TO_ENV_VAR: Record<string, string> = {
google: "GEMINI_API_KEY",
openrouter: "OPENROUTER_API_KEY",
azure: "AZURE_API_KEY",
bedrock: "AWS_BEARER_TOKEN_BEDROCK",
};
export const CLOUD_PROVIDERS: Record<
......@@ -317,6 +344,12 @@ export const CLOUD_PROVIDERS: Record<
gatewayPrefix: "",
secondary: true,
},
bedrock: {
displayName: "AWS Bedrock",
hasFreeTier: false,
websiteUrl: "https://console.aws.amazon.com/bedrock/",
gatewayPrefix: "bedrock/",
},
};
const LOCAL_PROVIDERS: Record<
......
......@@ -5,6 +5,7 @@ import { createVertex as createGoogleVertex } from "@ai-sdk/google-vertex";
import { azure } from "@ai-sdk/azure";
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { createAmazonBedrock } from "@ai-sdk/amazon-bedrock";
import type {
LargeLanguageModel,
UserSettings,
......@@ -342,6 +343,21 @@ function getRegularModelClient(
backupModelClients: [],
};
}
case "bedrock": {
// AWS Bedrock supports API key authentication using AWS_BEARER_TOKEN_BEDROCK
// See: https://sdk.vercel.ai/providers/ai-sdk-providers/amazon-bedrock#api-key-authentication
const provider = createAmazonBedrock({
apiKey: apiKey,
region: getEnvVar("AWS_REGION") || "us-east-1",
});
return {
modelClient: {
model: provider(model.name),
builtinProviderId: providerId,
},
backupModelClients: [],
};
}
default: {
// Handle custom providers
if (providerConfig.type === "custom") {
......
......@@ -36,6 +36,7 @@ const providers = [
"ollama",
"lmstudio",
"azure",
"bedrock",
] as const;
export const cloudProviders = providers.filter(
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论