mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-03-22 15:08:22 +08:00
feat: Add AWS Bedrock Provider Support (AKSK & API Key) (#1047)
* Add AWS Bedrock provider integration design document Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add AWS Bedrock provider implementation plan Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Update implementation plan: add OpenCode Bedrock support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add cloud_provider category to ProviderCategory type Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add AWS Bedrock (AKSK) Claude Code provider preset with tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add AWS Bedrock (API Key) Claude Code provider preset with tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add AWS Bedrock OpenCode provider preset with @ai-sdk/amazon-bedrock Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add AWS Bedrock provider feature summary for PR Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove internal planning documents Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add AWS Bedrock support to README (EN/ZH/JA) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add AWS Bedrock UI merge design document Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add AWS Bedrock UI merge implementation plan Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: skip optional template values in validation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: support isSecret template fields and hide base URL for Bedrock Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Bedrock validation, cleanup, and isBedrock prop in ProviderForm Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: extend TemplateValueConfig and merge Bedrock presets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: mask Bedrock API Key as secret and support GovCloud regions - Add isSecret: true to BEDROCK_API_KEY template value - Update region regex to support multi-segment regions (us-gov-west-1) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: replace AWS icon with updated logo Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: replace AWS icon with updated logo Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: replace AWS icon with new PNG image Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address code review findings - Fix AWS icon: use SVG with embedded <image> instead of raw <img> tag - Hide duplicate ApiKeySection for Bedrock (auth via template fields only) - Guard settingsConfig cleanup against unresolved template placeholders Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove planning documents Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: address PR review - split Bedrock into two presets, restore SVG icon Based on maintainer review feedback on PR #1047: 1. Split merged "AWS Bedrock" back into two separate presets: - "AWS Bedrock (AKSK)": uses AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - "AWS Bedrock (API Key)": uses top-level apiKey field via standard UI input 2. Restore aws.svg to pure vector SVG (was PNG-in-SVG) 3. Remove all Bedrock-specific logic from shared components: - Remove isBedrock prop from ClaudeFormFields - Remove Bedrock validation/cleanup blocks from ProviderForm - Remove optional/isSecret from TemplateValueConfig - Remove optional skip from useTemplateValues 4. Add cloud_provider category handling: - Skip API Key/Base URL required validation - Hide Speed Test and Base URL for cloud_provider - Hide API format selector for cloud_provider (always Anthropic) - Show API Key input only when config has apiKey field 5. Fix providerConfigUtils to support top-level apiKey: - getApiKeyFromConfig: check config.apiKey before env fields - setApiKeyInConfig: write to config.apiKey when present - hasApiKeyField: detect top-level apiKey property 6. Add OpenClaw Bedrock preset (bedrock-converse-stream protocol) 7. Update model IDs: - Sonnet: global.anthropic.claude-sonnet-4-6 - Opus: global.anthropic.claude-opus-4-6-v1 - Haiku: global.anthropic.claude-haiku-4-5-20251001-v1:0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(test): align Bedrock API Key test assertions with preset implementation The API Key preset was refactored to use standard UI input (apiKey: "") instead of template variables, but the tests were not updated accordingly. --------- Co-authored-by: root <root@ip-10-0-11-189.ap-northeast-1.compute.internal> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jason <farion1231@gmail.com>
This commit is contained in:
@@ -156,6 +156,7 @@ Claude Code / Codex / Gemini official channels at 38% / 2% / 9% of original pric
|
||||
**Core Capabilities**
|
||||
|
||||
- **Provider Management**: One-click switching between Claude Code, Codex, and Gemini API configurations
|
||||
- **AWS Bedrock Support**: Built-in AWS Bedrock provider presets with AKSK and API Key authentication, cross-region inference support (global/us/eu/apac), covering Claude Code and OpenCode
|
||||
- **Speed Testing**: Measure API endpoint latency with visual quality indicators
|
||||
- **Import/Export**: Backup and restore configs with auto-rotation (keep 10 most recent)
|
||||
- **i18n Support**: Complete Chinese/English localization (UI, errors, tray)
|
||||
|
||||
@@ -156,6 +156,7 @@ Claude Code / Codex / Gemini 公式チャンネルが最安で元価格の 38% /
|
||||
**コア機能**
|
||||
|
||||
- **プロバイダ管理**:Claude Code、Codex、Gemini の API 設定をワンクリックで切り替え
|
||||
- **AWS Bedrock 対応**:AWS Bedrock プロバイダプリセットを内蔵、AKSK および API Key 認証に対応、クロスリージョン推論(global/us/eu/apac)をサポート、Claude Code と OpenCode に対応
|
||||
- **速度テスト**:エンドポイント遅延を計測し、品質を可視化
|
||||
- **インポート/エクスポート**:設定をバックアップ・復元(最新 10 件を自動ローテーション)
|
||||
- **多言語対応**:UI/エラー/トレイを含む中国語・英語・日本語ローカライズ
|
||||
|
||||
@@ -157,6 +157,7 @@ Claude Code / Codex / Gemini 官方渠道低至 3.8 / 0.2 / 0.9 折,充值更
|
||||
**核心功能**
|
||||
|
||||
- **供应商管理**:一键切换 Claude Code、Codex 与 Gemini 的 API 配置
|
||||
- **AWS Bedrock 支持**:内置 AWS Bedrock 供应商预设,支持 AKSK 和 API Key 两种认证方式,支持跨区域推理(global/us/eu/apac),覆盖 Claude Code 和 OpenCode
|
||||
- **速度测试**:测量 API 端点延迟,可视化连接质量指示器
|
||||
- **导入导出**:备份和恢复配置,自动轮换(保留最近 10 个)
|
||||
- **国际化支持**:完整的中英文本地化(UI、错误、托盘)
|
||||
|
||||
@@ -198,8 +198,8 @@ export function ClaudeFormFields({
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* API 格式选择(仅非官方供应商显示) */}
|
||||
{shouldShowModelSelector && (
|
||||
{/* API 格式选择(仅非官方、非云服务商显示) */}
|
||||
{shouldShowModelSelector && category !== "cloud_provider" && (
|
||||
<div className="space-y-2">
|
||||
<FormLabel htmlFor="apiFormat">
|
||||
{t("providerForm.apiFormat", { defaultValue: "API 格式" })}
|
||||
|
||||
@@ -40,7 +40,10 @@ import {
|
||||
import { OpenCodeFormFields } from "./OpenCodeFormFields";
|
||||
import { OpenClawFormFields } from "./OpenClawFormFields";
|
||||
import type { UniversalProviderPreset } from "@/config/universalProviderPresets";
|
||||
import { applyTemplateValues } from "@/utils/providerConfigUtils";
|
||||
import {
|
||||
applyTemplateValues,
|
||||
hasApiKeyField,
|
||||
} from "@/utils/providerConfigUtils";
|
||||
import { mergeProviderMeta } from "@/utils/providerMetaUtils";
|
||||
import { getCodexCustomTemplate } from "@/config/codexTemplates";
|
||||
import CodexConfigEditor from "./CodexConfigEditor";
|
||||
@@ -594,7 +597,8 @@ export function ProviderForm({
|
||||
}
|
||||
|
||||
// 非官方供应商必填校验:端点和 API Key
|
||||
if (category !== "official") {
|
||||
// cloud_provider(如 Bedrock)通过模板变量处理认证,跳过通用校验
|
||||
if (category !== "official" && category !== "cloud_provider") {
|
||||
if (appId === "claude") {
|
||||
if (!baseUrl.trim()) {
|
||||
toast.error(
|
||||
@@ -843,7 +847,8 @@ export function ProviderForm({
|
||||
);
|
||||
}, [groupedPresets]);
|
||||
|
||||
const shouldShowSpeedTest = category !== "official";
|
||||
const shouldShowSpeedTest =
|
||||
category !== "official" && category !== "cloud_provider";
|
||||
|
||||
const {
|
||||
shouldShowApiKeyLink: shouldShowClaudeApiKeyLink,
|
||||
@@ -1233,10 +1238,13 @@ export function ProviderForm({
|
||||
{appId === "claude" && (
|
||||
<ClaudeFormFields
|
||||
providerId={providerId}
|
||||
shouldShowApiKey={shouldShowApiKey(
|
||||
form.getValues("settingsConfig"),
|
||||
isEditMode,
|
||||
)}
|
||||
shouldShowApiKey={
|
||||
hasApiKeyField(form.getValues("settingsConfig"), "claude") &&
|
||||
shouldShowApiKey(
|
||||
form.getValues("settingsConfig"),
|
||||
isEditMode,
|
||||
)
|
||||
}
|
||||
apiKey={apiKey}
|
||||
onApiKeyChange={handleApiKeyChange}
|
||||
category={category}
|
||||
|
||||
@@ -531,4 +531,73 @@ export const providerPresets: ProviderPreset[] = [
|
||||
icon: "xiaomimimo",
|
||||
iconColor: "#000000",
|
||||
},
|
||||
{
|
||||
name: "AWS Bedrock (AKSK)",
|
||||
websiteUrl: "https://aws.amazon.com/bedrock/",
|
||||
settingsConfig: {
|
||||
env: {
|
||||
ANTHROPIC_BASE_URL:
|
||||
"https://bedrock-runtime.${AWS_REGION}.amazonaws.com",
|
||||
AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}",
|
||||
AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}",
|
||||
AWS_REGION: "${AWS_REGION}",
|
||||
ANTHROPIC_MODEL: "global.anthropic.claude-opus-4-6-v1",
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL:
|
||||
"global.anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL:
|
||||
"global.anthropic.claude-sonnet-4-6",
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: "global.anthropic.claude-opus-4-6-v1",
|
||||
CLAUDE_CODE_USE_BEDROCK: "1",
|
||||
},
|
||||
},
|
||||
category: "cloud_provider",
|
||||
templateValues: {
|
||||
AWS_REGION: {
|
||||
label: "AWS Region",
|
||||
placeholder: "us-west-2",
|
||||
editorValue: "us-west-2",
|
||||
},
|
||||
AWS_ACCESS_KEY_ID: {
|
||||
label: "Access Key ID",
|
||||
placeholder: "AKIA...",
|
||||
editorValue: "",
|
||||
},
|
||||
AWS_SECRET_ACCESS_KEY: {
|
||||
label: "Secret Access Key",
|
||||
placeholder: "your-secret-key",
|
||||
editorValue: "",
|
||||
},
|
||||
},
|
||||
icon: "aws",
|
||||
iconColor: "#FF9900",
|
||||
},
|
||||
{
|
||||
name: "AWS Bedrock (API Key)",
|
||||
websiteUrl: "https://aws.amazon.com/bedrock/",
|
||||
settingsConfig: {
|
||||
apiKey: "",
|
||||
env: {
|
||||
ANTHROPIC_BASE_URL:
|
||||
"https://bedrock-runtime.${AWS_REGION}.amazonaws.com",
|
||||
AWS_REGION: "${AWS_REGION}",
|
||||
ANTHROPIC_MODEL: "global.anthropic.claude-opus-4-6-v1",
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL:
|
||||
"global.anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL:
|
||||
"global.anthropic.claude-sonnet-4-6",
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: "global.anthropic.claude-opus-4-6-v1",
|
||||
CLAUDE_CODE_USE_BEDROCK: "1",
|
||||
},
|
||||
},
|
||||
category: "cloud_provider",
|
||||
templateValues: {
|
||||
AWS_REGION: {
|
||||
label: "AWS Region",
|
||||
placeholder: "us-west-2",
|
||||
editorValue: "us-west-2",
|
||||
},
|
||||
},
|
||||
icon: "aws",
|
||||
iconColor: "#FF9900",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1054,6 +1054,41 @@ export const openclawProviderPresets: OpenClawProviderPreset[] = [
|
||||
},
|
||||
},
|
||||
|
||||
// ========== Cloud Providers ==========
|
||||
{
|
||||
name: "AWS Bedrock",
|
||||
websiteUrl: "https://aws.amazon.com/bedrock/",
|
||||
settingsConfig: {
|
||||
// 请将 us-west-2 替换为你的 AWS Region
|
||||
baseUrl: "https://bedrock-runtime.us-west-2.amazonaws.com",
|
||||
apiKey: "",
|
||||
api: "bedrock-converse-stream",
|
||||
models: [
|
||||
{
|
||||
id: "anthropic.claude-opus-4-6-20250514-v1:0",
|
||||
name: "Claude Opus 4.6",
|
||||
contextWindow: 200000,
|
||||
cost: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
||||
},
|
||||
{
|
||||
id: "anthropic.claude-sonnet-4-6",
|
||||
name: "Claude Sonnet 4.6",
|
||||
contextWindow: 200000,
|
||||
cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
||||
},
|
||||
{
|
||||
id: "anthropic.claude-haiku-4-5-20251022-v1:0",
|
||||
name: "Claude Haiku 4.5",
|
||||
contextWindow: 200000,
|
||||
cost: { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
||||
},
|
||||
],
|
||||
},
|
||||
category: "cloud_provider",
|
||||
icon: "aws",
|
||||
iconColor: "#FF9900",
|
||||
},
|
||||
|
||||
// ========== Custom Template ==========
|
||||
{
|
||||
name: "OpenAI Compatible",
|
||||
|
||||
@@ -21,6 +21,7 @@ export const opencodeNpmPackages = [
|
||||
{ value: "@ai-sdk/openai", label: "OpenAI" },
|
||||
{ value: "@ai-sdk/openai-compatible", label: "OpenAI Compatible" },
|
||||
{ value: "@ai-sdk/anthropic", label: "Anthropic" },
|
||||
{ value: "@ai-sdk/amazon-bedrock", label: "Amazon Bedrock" },
|
||||
{ value: "@ai-sdk/google", label: "Google (Gemini)" },
|
||||
] as const;
|
||||
|
||||
@@ -315,6 +316,50 @@ export const OPENCODE_PRESET_MODEL_VARIANTS: Record<
|
||||
},
|
||||
},
|
||||
],
|
||||
"@ai-sdk/amazon-bedrock": [
|
||||
{
|
||||
id: "global.anthropic.claude-opus-4-6-v1",
|
||||
name: "Claude Opus 4.6",
|
||||
contextLimit: 1000000,
|
||||
outputLimit: 128000,
|
||||
modalities: { input: ["text", "image", "pdf"], output: ["text"] },
|
||||
},
|
||||
{
|
||||
id: "global.anthropic.claude-sonnet-4-6",
|
||||
name: "Claude Sonnet 4.6",
|
||||
contextLimit: 200000,
|
||||
outputLimit: 64000,
|
||||
modalities: { input: ["text", "image", "pdf"], output: ["text"] },
|
||||
},
|
||||
{
|
||||
id: "global.anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
name: "Claude Haiku 4.5",
|
||||
contextLimit: 200000,
|
||||
outputLimit: 64000,
|
||||
modalities: { input: ["text", "image", "pdf"], output: ["text"] },
|
||||
},
|
||||
{
|
||||
id: "us.amazon.nova-pro-v1:0",
|
||||
name: "Amazon Nova Pro",
|
||||
contextLimit: 300000,
|
||||
outputLimit: 5000,
|
||||
modalities: { input: ["text", "image"], output: ["text"] },
|
||||
},
|
||||
{
|
||||
id: "us.meta.llama4-maverick-17b-instruct-v1:0",
|
||||
name: "Meta Llama 4 Maverick",
|
||||
contextLimit: 131072,
|
||||
outputLimit: 131072,
|
||||
modalities: { input: ["text"], output: ["text"] },
|
||||
},
|
||||
{
|
||||
id: "us.deepseek.r1-v1:0",
|
||||
name: "DeepSeek R1",
|
||||
contextLimit: 131072,
|
||||
outputLimit: 131072,
|
||||
modalities: { input: ["text"], output: ["text"] },
|
||||
},
|
||||
],
|
||||
"@ai-sdk/anthropic": [
|
||||
{
|
||||
id: "claude-sonnet-4-5-20250929",
|
||||
@@ -1089,6 +1134,54 @@ export const opencodeProviderPresets: OpenCodeProviderPreset[] = [
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "AWS Bedrock",
|
||||
websiteUrl: "https://aws.amazon.com/bedrock/",
|
||||
settingsConfig: {
|
||||
npm: "@ai-sdk/amazon-bedrock",
|
||||
name: "AWS Bedrock",
|
||||
options: {
|
||||
region: "${region}",
|
||||
accessKeyId: "${accessKeyId}",
|
||||
secretAccessKey: "${secretAccessKey}",
|
||||
},
|
||||
models: {
|
||||
"global.anthropic.claude-opus-4-6-v1": { name: "Claude Opus 4.6" },
|
||||
"global.anthropic.claude-sonnet-4-6": {
|
||||
name: "Claude Sonnet 4.6",
|
||||
},
|
||||
"global.anthropic.claude-haiku-4-5-20251001-v1:0": {
|
||||
name: "Claude Haiku 4.5",
|
||||
},
|
||||
"us.amazon.nova-pro-v1:0": { name: "Amazon Nova Pro" },
|
||||
"us.meta.llama4-maverick-17b-instruct-v1:0": {
|
||||
name: "Meta Llama 4 Maverick",
|
||||
},
|
||||
"us.deepseek.r1-v1:0": { name: "DeepSeek R1" },
|
||||
},
|
||||
},
|
||||
category: "cloud_provider",
|
||||
icon: "aws",
|
||||
iconColor: "#FF9900",
|
||||
templateValues: {
|
||||
region: {
|
||||
label: "AWS Region",
|
||||
placeholder: "us-west-2",
|
||||
defaultValue: "us-west-2",
|
||||
editorValue: "us-west-2",
|
||||
},
|
||||
accessKeyId: {
|
||||
label: "Access Key ID",
|
||||
placeholder: "AKIA...",
|
||||
editorValue: "",
|
||||
},
|
||||
secretAccessKey: {
|
||||
label: "Secret Access Key",
|
||||
placeholder: "your-secret-key",
|
||||
editorValue: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OpenAI Compatible",
|
||||
websiteUrl: "",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export type ProviderCategory =
|
||||
| "official" // 官方
|
||||
| "cn_official" // 开源官方(原"国产官方")
|
||||
| "cloud_provider" // 云服务商(AWS Bedrock 等)
|
||||
| "aggregator" // 聚合网站
|
||||
| "third_party" // 第三方供应商
|
||||
| "custom" // 自定义
|
||||
|
||||
@@ -29,6 +29,16 @@ export const getApiKeyFromConfig = (
|
||||
): string => {
|
||||
try {
|
||||
const config = JSON.parse(jsonString);
|
||||
|
||||
// 优先检查顶层 apiKey 字段(用于 Bedrock API Key 等预设)
|
||||
if (
|
||||
typeof config?.apiKey === "string" &&
|
||||
config.apiKey &&
|
||||
!config.apiKey.includes("${")
|
||||
) {
|
||||
return config.apiKey;
|
||||
}
|
||||
|
||||
const env = config?.env;
|
||||
|
||||
if (!env) return "";
|
||||
@@ -112,6 +122,12 @@ export const hasApiKeyField = (
|
||||
): boolean => {
|
||||
try {
|
||||
const config = JSON.parse(jsonString);
|
||||
|
||||
// 检查顶层 apiKey 字段(用于 Bedrock API Key 等预设)
|
||||
if (Object.prototype.hasOwnProperty.call(config, "apiKey")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const env = config?.env ?? {};
|
||||
|
||||
if (appType === "gemini") {
|
||||
@@ -144,6 +160,13 @@ export const setApiKeyInConfig = (
|
||||
const { createIfMissing = false, appType, apiKeyField } = options;
|
||||
try {
|
||||
const config = JSON.parse(jsonString);
|
||||
|
||||
// 优先检查顶层 apiKey 字段(用于 Bedrock API Key 等预设)
|
||||
if (Object.prototype.hasOwnProperty.call(config, "apiKey")) {
|
||||
config.apiKey = apiKey;
|
||||
return JSON.stringify(config, null, 2);
|
||||
}
|
||||
|
||||
if (!config.env) {
|
||||
if (!createIfMissing) return jsonString;
|
||||
config.env = {};
|
||||
|
||||
78
tests/config/claudeProviderPresets.test.ts
Normal file
78
tests/config/claudeProviderPresets.test.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { providerPresets } from "@/config/claudeProviderPresets";
|
||||
|
||||
describe("AWS Bedrock Provider Presets", () => {
|
||||
const bedrockAksk = providerPresets.find(
|
||||
(p) => p.name === "AWS Bedrock (AKSK)",
|
||||
);
|
||||
|
||||
it("should include AWS Bedrock (AKSK) preset", () => {
|
||||
expect(bedrockAksk).toBeDefined();
|
||||
});
|
||||
|
||||
it("AKSK preset should have required AWS env variables", () => {
|
||||
const env = (bedrockAksk!.settingsConfig as any).env;
|
||||
expect(env).toHaveProperty("AWS_ACCESS_KEY_ID");
|
||||
expect(env).toHaveProperty("AWS_SECRET_ACCESS_KEY");
|
||||
expect(env).toHaveProperty("AWS_REGION");
|
||||
expect(env).toHaveProperty("CLAUDE_CODE_USE_BEDROCK", "1");
|
||||
});
|
||||
|
||||
it("AKSK preset should have template values for AWS credentials", () => {
|
||||
expect(bedrockAksk!.templateValues).toBeDefined();
|
||||
expect(bedrockAksk!.templateValues!.AWS_ACCESS_KEY_ID).toBeDefined();
|
||||
expect(bedrockAksk!.templateValues!.AWS_SECRET_ACCESS_KEY).toBeDefined();
|
||||
expect(bedrockAksk!.templateValues!.AWS_REGION).toBeDefined();
|
||||
expect(bedrockAksk!.templateValues!.AWS_REGION.editorValue).toBe(
|
||||
"us-west-2",
|
||||
);
|
||||
});
|
||||
|
||||
it("AKSK preset should have correct base URL template", () => {
|
||||
const env = (bedrockAksk!.settingsConfig as any).env;
|
||||
expect(env.ANTHROPIC_BASE_URL).toContain("bedrock-runtime");
|
||||
expect(env.ANTHROPIC_BASE_URL).toContain("${AWS_REGION}");
|
||||
});
|
||||
|
||||
it("AKSK preset should have cloud_provider category", () => {
|
||||
expect(bedrockAksk!.category).toBe("cloud_provider");
|
||||
});
|
||||
|
||||
it("AKSK preset should have Bedrock model as default", () => {
|
||||
const env = (bedrockAksk!.settingsConfig as any).env;
|
||||
expect(env.ANTHROPIC_MODEL).toContain("anthropic.claude");
|
||||
});
|
||||
|
||||
const bedrockApiKey = providerPresets.find(
|
||||
(p) => p.name === "AWS Bedrock (API Key)",
|
||||
);
|
||||
|
||||
it("should include AWS Bedrock (API Key) preset", () => {
|
||||
expect(bedrockApiKey).toBeDefined();
|
||||
});
|
||||
|
||||
it("API Key preset should have apiKey field and AWS env variables", () => {
|
||||
const config = bedrockApiKey!.settingsConfig as any;
|
||||
expect(config).toHaveProperty("apiKey", "");
|
||||
expect(config.env).toHaveProperty("AWS_REGION");
|
||||
expect(config.env).toHaveProperty("CLAUDE_CODE_USE_BEDROCK", "1");
|
||||
});
|
||||
|
||||
it("API Key preset should NOT have AKSK env variables", () => {
|
||||
const env = (bedrockApiKey!.settingsConfig as any).env;
|
||||
expect(env).not.toHaveProperty("AWS_ACCESS_KEY_ID");
|
||||
expect(env).not.toHaveProperty("AWS_SECRET_ACCESS_KEY");
|
||||
});
|
||||
|
||||
it("API Key preset should have template values for region only", () => {
|
||||
expect(bedrockApiKey!.templateValues).toBeDefined();
|
||||
expect(bedrockApiKey!.templateValues!.AWS_REGION).toBeDefined();
|
||||
expect(bedrockApiKey!.templateValues!.AWS_REGION.editorValue).toBe(
|
||||
"us-west-2",
|
||||
);
|
||||
});
|
||||
|
||||
it("API Key preset should have cloud_provider category", () => {
|
||||
expect(bedrockApiKey!.category).toBe("cloud_provider");
|
||||
});
|
||||
});
|
||||
68
tests/config/opencodeProviderPresets.test.ts
Normal file
68
tests/config/opencodeProviderPresets.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
opencodeProviderPresets,
|
||||
opencodeNpmPackages,
|
||||
OPENCODE_PRESET_MODEL_VARIANTS,
|
||||
} from "@/config/opencodeProviderPresets";
|
||||
|
||||
describe("AWS Bedrock OpenCode Provider Presets", () => {
|
||||
it("should include @ai-sdk/amazon-bedrock in npm packages", () => {
|
||||
const bedrockPkg = opencodeNpmPackages.find(
|
||||
(p) => p.value === "@ai-sdk/amazon-bedrock",
|
||||
);
|
||||
expect(bedrockPkg).toBeDefined();
|
||||
expect(bedrockPkg!.label).toBe("Amazon Bedrock");
|
||||
});
|
||||
|
||||
it("should include Bedrock model variants", () => {
|
||||
const variants = OPENCODE_PRESET_MODEL_VARIANTS["@ai-sdk/amazon-bedrock"];
|
||||
expect(variants).toBeDefined();
|
||||
expect(variants.length).toBeGreaterThan(0);
|
||||
|
||||
const opusModel = variants.find((v) =>
|
||||
v.id.includes("anthropic.claude-opus-4-6"),
|
||||
);
|
||||
expect(opusModel).toBeDefined();
|
||||
});
|
||||
|
||||
const bedrockPreset = opencodeProviderPresets.find(
|
||||
(p) => p.name === "AWS Bedrock",
|
||||
);
|
||||
|
||||
it("should include AWS Bedrock preset", () => {
|
||||
expect(bedrockPreset).toBeDefined();
|
||||
});
|
||||
|
||||
it("Bedrock preset should use @ai-sdk/amazon-bedrock npm package", () => {
|
||||
expect(bedrockPreset!.settingsConfig.npm).toBe(
|
||||
"@ai-sdk/amazon-bedrock",
|
||||
);
|
||||
});
|
||||
|
||||
it("Bedrock preset should have region in options", () => {
|
||||
expect(bedrockPreset!.settingsConfig.options).toHaveProperty("region");
|
||||
});
|
||||
|
||||
it("Bedrock preset should have cloud_provider category", () => {
|
||||
expect(bedrockPreset!.category).toBe("cloud_provider");
|
||||
});
|
||||
|
||||
it("Bedrock preset should have template values for AWS credentials", () => {
|
||||
expect(bedrockPreset!.templateValues).toBeDefined();
|
||||
expect(bedrockPreset!.templateValues!.region).toBeDefined();
|
||||
expect(bedrockPreset!.templateValues!.region.editorValue).toBe(
|
||||
"us-west-2",
|
||||
);
|
||||
expect(bedrockPreset!.templateValues!.accessKeyId).toBeDefined();
|
||||
expect(bedrockPreset!.templateValues!.secretAccessKey).toBeDefined();
|
||||
});
|
||||
|
||||
it("Bedrock preset should include Claude models", () => {
|
||||
const models = bedrockPreset!.settingsConfig.models;
|
||||
expect(models).toBeDefined();
|
||||
const modelIds = Object.keys(models!);
|
||||
expect(
|
||||
modelIds.some((id) => id.includes("anthropic.claude")),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user