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:
Keith Yu
2026-02-24 21:11:18 +08:00
committed by GitHub
parent e1e2bdef2a
commit 8ea9638b9d
12 changed files with 387 additions and 9 deletions
@@ -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}