mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-05-21 04:40:18 +08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5816ca8ae3 | |||
| f6cee96394 | |||
| ecd5927769 | |||
| 1bac3922fb | |||
| 920b675ec2 | |||
| b5ace10066 | |||
| 6dcc3803b4 | |||
| 158a679b8b | |||
| c303cc8acf | |||
| 71dc459eb2 | |||
| 7fee0d8fa6 | |||
| 657b7c29c2 | |||
| 750e1060e8 | |||
| 3d25350cbf | |||
| 860d6ec8dd | |||
| 8371e9e683 | |||
| acbeb03917 | |||
| 7cee0de784 | |||
| 39ec987396 | |||
| 9b71a280ea | |||
| c5668165a8 | |||
| d9a7c78138 | |||
| c8a6aab5b2 | |||
| 49de0896b3 |
@@ -156,6 +156,7 @@ Claude Code / Codex / Gemini official channels at 38% / 2% / 9% of original pric
|
|||||||
**Core Capabilities**
|
**Core Capabilities**
|
||||||
|
|
||||||
- **Provider Management**: One-click switching between Claude Code, Codex, and Gemini API configurations
|
- **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
|
- **Speed Testing**: Measure API endpoint latency with visual quality indicators
|
||||||
- **Import/Export**: Backup and restore configs with auto-rotation (keep 10 most recent)
|
- **Import/Export**: Backup and restore configs with auto-rotation (keep 10 most recent)
|
||||||
- **i18n Support**: Complete Chinese/English localization (UI, errors, tray)
|
- **i18n Support**: Complete Chinese/English localization (UI, errors, tray)
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ Claude Code / Codex / Gemini 公式チャンネルが最安で元価格の 38% /
|
|||||||
**コア機能**
|
**コア機能**
|
||||||
|
|
||||||
- **プロバイダ管理**:Claude Code、Codex、Gemini の API 設定をワンクリックで切り替え
|
- **プロバイダ管理**:Claude Code、Codex、Gemini の API 設定をワンクリックで切り替え
|
||||||
|
- **AWS Bedrock 対応**:AWS Bedrock プロバイダプリセットを内蔵、AKSK および API Key 認証に対応、クロスリージョン推論(global/us/eu/apac)をサポート、Claude Code と OpenCode に対応
|
||||||
- **速度テスト**:エンドポイント遅延を計測し、品質を可視化
|
- **速度テスト**:エンドポイント遅延を計測し、品質を可視化
|
||||||
- **インポート/エクスポート**:設定をバックアップ・復元(最新 10 件を自動ローテーション)
|
- **インポート/エクスポート**:設定をバックアップ・復元(最新 10 件を自動ローテーション)
|
||||||
- **多言語対応**:UI/エラー/トレイを含む中国語・英語・日本語ローカライズ
|
- **多言語対応**:UI/エラー/トレイを含む中国語・英語・日本語ローカライズ
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ Claude Code / Codex / Gemini 官方渠道低至 3.8 / 0.2 / 0.9 折,充值更
|
|||||||
**核心功能**
|
**核心功能**
|
||||||
|
|
||||||
- **供应商管理**:一键切换 Claude Code、Codex 与 Gemini 的 API 配置
|
- **供应商管理**:一键切换 Claude Code、Codex 与 Gemini 的 API 配置
|
||||||
|
- **AWS Bedrock 支持**:内置 AWS Bedrock 供应商预设,支持 AKSK 和 API Key 两种认证方式,支持跨区域推理(global/us/eu/apac),覆盖 Claude Code 和 OpenCode
|
||||||
- **速度测试**:测量 API 端点延迟,可视化连接质量指示器
|
- **速度测试**:测量 API 端点延迟,可视化连接质量指示器
|
||||||
- **导入导出**:备份和恢复配置,自动轮换(保留最近 10 个)
|
- **导入导出**:备份和恢复配置,自动轮换(保留最近 10 个)
|
||||||
- **国际化支持**:完整的中英文本地化(UI、错误、托盘)
|
- **国际化支持**:完整的中英文本地化(UI、错误、托盘)
|
||||||
|
|||||||
@@ -198,8 +198,8 @@ export function ClaudeFormFields({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* API 格式选择(仅非官方供应商显示) */}
|
{/* API 格式选择(仅非官方、非云服务商显示) */}
|
||||||
{shouldShowModelSelector && (
|
{shouldShowModelSelector && category !== "cloud_provider" && (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<FormLabel htmlFor="apiFormat">
|
<FormLabel htmlFor="apiFormat">
|
||||||
{t("providerForm.apiFormat", { defaultValue: "API 格式" })}
|
{t("providerForm.apiFormat", { defaultValue: "API 格式" })}
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ import {
|
|||||||
import { OpenCodeFormFields } from "./OpenCodeFormFields";
|
import { OpenCodeFormFields } from "./OpenCodeFormFields";
|
||||||
import { OpenClawFormFields } from "./OpenClawFormFields";
|
import { OpenClawFormFields } from "./OpenClawFormFields";
|
||||||
import type { UniversalProviderPreset } from "@/config/universalProviderPresets";
|
import type { UniversalProviderPreset } from "@/config/universalProviderPresets";
|
||||||
import { applyTemplateValues } from "@/utils/providerConfigUtils";
|
import {
|
||||||
|
applyTemplateValues,
|
||||||
|
hasApiKeyField,
|
||||||
|
} from "@/utils/providerConfigUtils";
|
||||||
import { mergeProviderMeta } from "@/utils/providerMetaUtils";
|
import { mergeProviderMeta } from "@/utils/providerMetaUtils";
|
||||||
import { getCodexCustomTemplate } from "@/config/codexTemplates";
|
import { getCodexCustomTemplate } from "@/config/codexTemplates";
|
||||||
import CodexConfigEditor from "./CodexConfigEditor";
|
import CodexConfigEditor from "./CodexConfigEditor";
|
||||||
@@ -594,7 +597,8 @@ export function ProviderForm({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 非官方供应商必填校验:端点和 API Key
|
// 非官方供应商必填校验:端点和 API Key
|
||||||
if (category !== "official") {
|
// cloud_provider(如 Bedrock)通过模板变量处理认证,跳过通用校验
|
||||||
|
if (category !== "official" && category !== "cloud_provider") {
|
||||||
if (appId === "claude") {
|
if (appId === "claude") {
|
||||||
if (!baseUrl.trim()) {
|
if (!baseUrl.trim()) {
|
||||||
toast.error(
|
toast.error(
|
||||||
@@ -843,7 +847,8 @@ export function ProviderForm({
|
|||||||
);
|
);
|
||||||
}, [groupedPresets]);
|
}, [groupedPresets]);
|
||||||
|
|
||||||
const shouldShowSpeedTest = category !== "official";
|
const shouldShowSpeedTest =
|
||||||
|
category !== "official" && category !== "cloud_provider";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
shouldShowApiKeyLink: shouldShowClaudeApiKeyLink,
|
shouldShowApiKeyLink: shouldShowClaudeApiKeyLink,
|
||||||
@@ -1233,10 +1238,13 @@ export function ProviderForm({
|
|||||||
{appId === "claude" && (
|
{appId === "claude" && (
|
||||||
<ClaudeFormFields
|
<ClaudeFormFields
|
||||||
providerId={providerId}
|
providerId={providerId}
|
||||||
shouldShowApiKey={shouldShowApiKey(
|
shouldShowApiKey={
|
||||||
form.getValues("settingsConfig"),
|
hasApiKeyField(form.getValues("settingsConfig"), "claude") &&
|
||||||
isEditMode,
|
shouldShowApiKey(
|
||||||
)}
|
form.getValues("settingsConfig"),
|
||||||
|
isEditMode,
|
||||||
|
)
|
||||||
|
}
|
||||||
apiKey={apiKey}
|
apiKey={apiKey}
|
||||||
onApiKeyChange={handleApiKeyChange}
|
onApiKeyChange={handleApiKeyChange}
|
||||||
category={category}
|
category={category}
|
||||||
|
|||||||
@@ -531,4 +531,73 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
icon: "xiaomimimo",
|
icon: "xiaomimimo",
|
||||||
iconColor: "#000000",
|
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 ==========
|
// ========== Custom Template ==========
|
||||||
{
|
{
|
||||||
name: "OpenAI Compatible",
|
name: "OpenAI Compatible",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export const opencodeNpmPackages = [
|
|||||||
{ value: "@ai-sdk/openai", label: "OpenAI" },
|
{ value: "@ai-sdk/openai", label: "OpenAI" },
|
||||||
{ value: "@ai-sdk/openai-compatible", label: "OpenAI Compatible" },
|
{ value: "@ai-sdk/openai-compatible", label: "OpenAI Compatible" },
|
||||||
{ value: "@ai-sdk/anthropic", label: "Anthropic" },
|
{ value: "@ai-sdk/anthropic", label: "Anthropic" },
|
||||||
|
{ value: "@ai-sdk/amazon-bedrock", label: "Amazon Bedrock" },
|
||||||
{ value: "@ai-sdk/google", label: "Google (Gemini)" },
|
{ value: "@ai-sdk/google", label: "Google (Gemini)" },
|
||||||
] as const;
|
] 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": [
|
"@ai-sdk/anthropic": [
|
||||||
{
|
{
|
||||||
id: "claude-sonnet-4-5-20250929",
|
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",
|
name: "OpenAI Compatible",
|
||||||
websiteUrl: "",
|
websiteUrl: "",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export type ProviderCategory =
|
export type ProviderCategory =
|
||||||
| "official" // 官方
|
| "official" // 官方
|
||||||
| "cn_official" // 开源官方(原"国产官方")
|
| "cn_official" // 开源官方(原"国产官方")
|
||||||
|
| "cloud_provider" // 云服务商(AWS Bedrock 等)
|
||||||
| "aggregator" // 聚合网站
|
| "aggregator" // 聚合网站
|
||||||
| "third_party" // 第三方供应商
|
| "third_party" // 第三方供应商
|
||||||
| "custom" // 自定义
|
| "custom" // 自定义
|
||||||
|
|||||||
@@ -29,6 +29,16 @@ export const getApiKeyFromConfig = (
|
|||||||
): string => {
|
): string => {
|
||||||
try {
|
try {
|
||||||
const config = JSON.parse(jsonString);
|
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;
|
const env = config?.env;
|
||||||
|
|
||||||
if (!env) return "";
|
if (!env) return "";
|
||||||
@@ -112,6 +122,12 @@ export const hasApiKeyField = (
|
|||||||
): boolean => {
|
): boolean => {
|
||||||
try {
|
try {
|
||||||
const config = JSON.parse(jsonString);
|
const config = JSON.parse(jsonString);
|
||||||
|
|
||||||
|
// 检查顶层 apiKey 字段(用于 Bedrock API Key 等预设)
|
||||||
|
if (Object.prototype.hasOwnProperty.call(config, "apiKey")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const env = config?.env ?? {};
|
const env = config?.env ?? {};
|
||||||
|
|
||||||
if (appType === "gemini") {
|
if (appType === "gemini") {
|
||||||
@@ -144,6 +160,13 @@ export const setApiKeyInConfig = (
|
|||||||
const { createIfMissing = false, appType, apiKeyField } = options;
|
const { createIfMissing = false, appType, apiKeyField } = options;
|
||||||
try {
|
try {
|
||||||
const config = JSON.parse(jsonString);
|
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 (!config.env) {
|
||||||
if (!createIfMissing) return jsonString;
|
if (!createIfMissing) return jsonString;
|
||||||
config.env = {};
|
config.env = {};
|
||||||
|
|||||||
@@ -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");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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