From f520d80c4b109c89539c7ef7cf101dbc48a630d0 Mon Sep 17 00:00:00 2001 From: Peter Xue Date: Mon, 8 Jun 2026 14:03:45 -0700 Subject: [PATCH 1/4] feat(bedrock): add AWS profile authentication support Add a new authentication mode for AWS Bedrock provider that allows users to authenticate using named AWS profiles (~/.aws/credentials) instead of static access keys. Uses fromNodeProviderChain for full AWS credential chain resolution (SSO, process credentials, etc). --- package.json | 1 + .../aiSdk/providerFactory.ts | 23 +- .../providers/aiSdkProvider.ts | 13 +- .../BedrockProviderSettingsDetail.vue | 254 ++++++++++-------- src/renderer/src/i18n/da-DK/settings.json | 5 + src/renderer/src/i18n/de-DE/settings.json | 5 + src/renderer/src/i18n/en-US/settings.json | 5 + src/renderer/src/i18n/es-ES/settings.json | 5 + src/renderer/src/i18n/fa-IR/settings.json | 5 + src/renderer/src/i18n/fr-FR/settings.json | 5 + src/renderer/src/i18n/he-IL/settings.json | 5 + src/renderer/src/i18n/id-ID/settings.json | 5 + src/renderer/src/i18n/it-IT/settings.json | 5 + src/renderer/src/i18n/ja-JP/settings.json | 5 + src/renderer/src/i18n/ko-KR/settings.json | 5 + src/renderer/src/i18n/ms-MY/settings.json | 5 + src/renderer/src/i18n/pl-PL/settings.json | 5 + src/renderer/src/i18n/pt-BR/settings.json | 5 + src/renderer/src/i18n/ru-RU/settings.json | 5 + src/renderer/src/i18n/tr-TR/settings.json | 5 + src/renderer/src/i18n/vi-VN/settings.json | 5 + src/renderer/src/i18n/zh-CN/settings.json | 5 + src/renderer/src/i18n/zh-HK/settings.json | 5 + src/renderer/src/i18n/zh-TW/settings.json | 5 + src/shared/contracts/domainSchemas.ts | 4 +- .../types/presenters/legacy.presenters.d.ts | 2 + .../presenters/llmprovider.presenter.d.ts | 2 + 27 files changed, 283 insertions(+), 116 deletions(-) diff --git a/package.json b/package.json index ee484f900..d9e702780 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,7 @@ "@ai-sdk/provider": "^3.0.10", "@aws-sdk/client-bedrock": "^3.1057.0", "@aws-sdk/client-s3": "^3.1062.0", + "@aws-sdk/credential-providers": "^3.1057.0", "@duckdb/node-api": "1.5.3-r.1", "@e2b/code-interpreter": "^1.5.1", "@electron-toolkit/preload": "^3.0.2", diff --git a/src/main/presenter/llmProviderPresenter/aiSdk/providerFactory.ts b/src/main/presenter/llmProviderPresenter/aiSdk/providerFactory.ts index 965cce318..4615531e6 100644 --- a/src/main/presenter/llmProviderPresenter/aiSdk/providerFactory.ts +++ b/src/main/presenter/llmProviderPresenter/aiSdk/providerFactory.ts @@ -12,6 +12,7 @@ import { createGoogleGenerativeAI } from '@ai-sdk/google' import { createVertex } from '@ai-sdk/google-vertex' import { createOpenAI } from '@ai-sdk/openai' import { createOpenAICompatible } from '@ai-sdk/openai-compatible' +import { fromNodeProviderChain } from '@aws-sdk/credential-providers' import { ProxyAgent } from 'undici' import { proxyConfig } from '../../proxyConfig' import { createReasoningMiddleware } from './middlewares/reasoningMiddleware' @@ -640,16 +641,26 @@ export function createAiSdkProviderContext( case 'aws-bedrock': { const bedrockProvider = params.provider as AWS_BEDROCK_PROVIDER - const provider = createAmazonBedrock({ + const credential = bedrockProvider.credential + const useProfileAuth = credential?.authMode === 'profile' && credential?.profile + + const bedrockOptions: Record = { apiKey: bedrockProvider.apiKey || undefined, baseURL: bedrockProvider.baseUrl || undefined, - region: bedrockProvider.credential?.region || process.env.AWS_REGION || 'us-east-1', - accessKeyId: bedrockProvider.credential?.accessKeyId || process.env.AWS_ACCESS_KEY_ID, - secretAccessKey: - bedrockProvider.credential?.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY, + region: credential?.region || process.env.AWS_REGION || 'us-east-1', headers: params.defaultHeaders, fetch - }) + } + + if (useProfileAuth) { + bedrockOptions.credentialProvider = fromNodeProviderChain({ profile: credential.profile }) + } else { + bedrockOptions.accessKeyId = credential?.accessKeyId || process.env.AWS_ACCESS_KEY_ID + bedrockOptions.secretAccessKey = + credential?.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY + } + + const provider = createAmazonBedrock(bedrockOptions as any) return { providerOptionsKey: 'bedrock', diff --git a/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts b/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts index bdf300957..a32d17551 100644 --- a/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts @@ -2208,10 +2208,15 @@ export class AiSdkProvider extends BaseLLMProvider { } case 'bedrock': { const provider = this.provider as AWS_BEDROCK_PROVIDER - const accessKeyId = provider.credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID - const secretAccessKey = - provider.credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY - const region = provider.credential?.region || process.env.BEDROCK_REGION + const credential = provider.credential + const region = credential?.region || process.env.BEDROCK_REGION + + if (credential?.authMode === 'profile') { + return credential.profile && region ? null : 'Missing AWS profile name or region' + } + + const accessKeyId = credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID + const secretAccessKey = credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY return accessKeyId && secretAccessKey && region ? null : 'Missing AWS Bedrock credentials' } case 'none': diff --git a/src/renderer/settings/components/BedrockProviderSettingsDetail.vue b/src/renderer/settings/components/BedrockProviderSettingsDetail.vue index 48ad90535..4fe560d34 100644 --- a/src/renderer/settings/components/BedrockProviderSettingsDetail.vue +++ b/src/renderer/settings/components/BedrockProviderSettingsDetail.vue @@ -2,61 +2,106 @@
+
- -
- -
+ + + + + + + +
+
- - (props.provider.credential?.authMode || 'accessKeys') const accessKeyId = ref(props.provider.credential?.accessKeyId || '') const secretAccessKey = ref(props.provider.credential?.secretAccessKey || '') const region = ref(props.provider.credential?.region || '') +const profile = ref(props.provider.credential?.profile || '') const showAccessKeyId = ref(false) const showSecretAccessKey = ref(false) const providerModels = ref([]) @@ -184,16 +229,14 @@ const showDeleteProviderDialog = ref(false) const isProviderReadyForOnboarding = ( provider: Pick ) => { - if (!provider.enable) { - return false - } - + if (!provider.enable) return false const credential = provider.credential - return Boolean( - credential?.accessKeyId?.trim() && - credential?.secretAccessKey?.trim() && - credential?.region?.trim() - ) + if (!credential?.region?.trim()) return false + + if (credential.authMode === 'profile') { + return Boolean(credential.profile?.trim()) + } + return Boolean(credential.accessKeyId?.trim() && credential.secretAccessKey?.trim()) } const maybeEmitProviderConfigured = (provider: AWS_BEDROCK_PROVIDER) => { @@ -206,43 +249,45 @@ const enabledModels = computed(() => { const enabledCustom = customModels.value.filter((m) => m.enabled) const enabledBuiltIn = providerModels.value.filter((m) => m.enabled) const uniqueModels = new Map() - const merged = [...enabledCustom, ...enabledBuiltIn] - merged.forEach((model) => { if (!uniqueModels.has(model.id)) { uniqueModels.set(model.id, model) } }) - return Array.from(uniqueModels.values()) }) +const buildCredential = () => ({ + authMode: authMode.value, + accessKeyId: accessKeyId.value, + secretAccessKey: secretAccessKey.value, + region: region.value, + profile: profile.value +}) + const initData = async () => { - console.log('initData for provider:', props.provider.id) const providerData = modelStore.allProviderModels.find((p) => p.providerId === props.provider.id) - if (providerData) { providerModels.value = providerData.models.sort( (a, b) => a.group.localeCompare(b.group) || a.providerId.localeCompare(b.providerId) ) } else { - providerModels.value = [] // Reset if provider data not found + providerModels.value = [] } - - // Fetch Credential if applicable - // no need } watch( () => props.provider, async () => { + authMode.value = props.provider.credential?.authMode || 'accessKeys' accessKeyId.value = props.provider.credential?.accessKeyId || '' secretAccessKey.value = props.provider.credential?.secretAccessKey || '' region.value = props.provider.credential?.region || '' - await initData() // Ensure initData completes + profile.value = props.provider.credential?.profile || '' + await initData() }, - { immediate: true } // Removed deep: true as provider object itself changes + { immediate: true } ) watch( @@ -253,56 +298,55 @@ watch( { deep: true } ) +const handleAuthModeChange = async (value: unknown) => { + if (!value || typeof value !== 'string') return + authMode.value = value as 'accessKeys' | 'profile' + const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, { + credential: buildCredential() + }) + maybeEmitProviderConfigured(result.updated as AWS_BEDROCK_PROVIDER) +} + const handleAccessKeyIdChange = async (value: string) => { + accessKeyId.value = value const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, { - credential: { - accessKeyId: value, - secretAccessKey: secretAccessKey.value, - region: region.value - } + credential: buildCredential() }) maybeEmitProviderConfigured(result.updated as AWS_BEDROCK_PROVIDER) } const handleSecretAccessKeyChange = async (value: string) => { + secretAccessKey.value = value const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, { - credential: { - accessKeyId: accessKeyId.value, - secretAccessKey: value, - region: region.value - } + credential: buildCredential() }) maybeEmitProviderConfigured(result.updated as AWS_BEDROCK_PROVIDER) } const handleRegionChange = async (value: string) => { + region.value = value const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, { - credential: { - accessKeyId: accessKeyId.value, - secretAccessKey: secretAccessKey.value, - region: value || undefined - } + credential: buildCredential() }) maybeEmitProviderConfigured(result.updated as AWS_BEDROCK_PROVIDER) } -const validateCredential = async () => { - if (!props.provider.enable) { - return - } +const handleProfileChange = async (value: string) => { + profile.value = value + const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, { + credential: buildCredential() + }) + maybeEmitProviderConfigured(result.updated as AWS_BEDROCK_PROVIDER) +} +const validateCredential = async () => { + if (!props.provider.enable) return try { const resp = await providerStore.checkProvider(props.provider.id) + checkResult.value = resp.isOk + showCheckModelDialog.value = true if (resp.isOk) { - console.log('验证成功') - checkResult.value = true - showCheckModelDialog.value = true - // 验证成功后刷新当前provider的模型列表 await modelStore.refreshProviderModels(props.provider.id) - } else { - console.log('验证失败', resp.errorMsg) - checkResult.value = false - showCheckModelDialog.value = true } } catch (error) { console.error('Failed to validate credential:', error) @@ -311,8 +355,10 @@ const validateCredential = async () => { } } -const handleVerifyCredential = async (updates: Partial) => { - const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, updates) +const handleVerifyCredential = async () => { + const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, { + credential: buildCredential() + }) maybeEmitProviderConfigured(result.updated as AWS_BEDROCK_PROVIDER) await validateCredential() } @@ -362,9 +408,7 @@ const confirmDisableAll = async () => { } } -// Handler for config changes const handleConfigChanged = async () => { - // 模型配置变更后重新初始化数据 await initData() } diff --git a/src/renderer/src/i18n/da-DK/settings.json b/src/renderer/src/i18n/da-DK/settings.json index badef0419..7fd0cabd7 100644 --- a/src/renderer/src/i18n/da-DK/settings.json +++ b/src/renderer/src/i18n/da-DK/settings.json @@ -741,6 +741,11 @@ "disabled": "Deaktiveret", "urlPlaceholder": "Indtast API-URL", "keyPlaceholder": "Indtast API-nøgle", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Indtast AWS Access Key ID", "secretAccessKeyPlaceholder": "Indtast AWS Secret Access Key", "regionPlaceholder": "Indtast AWS-region", diff --git a/src/renderer/src/i18n/de-DE/settings.json b/src/renderer/src/i18n/de-DE/settings.json index 037e26bfe..4189ecd4b 100644 --- a/src/renderer/src/i18n/de-DE/settings.json +++ b/src/renderer/src/i18n/de-DE/settings.json @@ -871,6 +871,11 @@ "disabled": "Deaktiviert", "urlPlaceholder": "API URL eingeben", "keyPlaceholder": "API Key eingeben", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "AWS Access Key ID eingeben", "secretAccessKeyPlaceholder": "AWS Secret Access Key eingeben", "regionPlaceholder": "AWS-Region eingeben", diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index 2e72d17d9..8bbf5ed68 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -871,6 +871,11 @@ "disabled": "Disabled", "urlPlaceholder": "Please enter API URL", "keyPlaceholder": "Please enter API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Please enter AWS Access Key ID", "secretAccessKeyPlaceholder": "Please enter AWS Secret Access Key", "regionPlaceholder": "Please enter AWS region", diff --git a/src/renderer/src/i18n/es-ES/settings.json b/src/renderer/src/i18n/es-ES/settings.json index 02420e6fc..035345c9d 100644 --- a/src/renderer/src/i18n/es-ES/settings.json +++ b/src/renderer/src/i18n/es-ES/settings.json @@ -871,6 +871,11 @@ "disabled": "Discapacitado", "urlPlaceholder": "Por favor ingrese API URL", "keyPlaceholder": "Por favor ingrese API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Por favor ingrese AWS ID de clave de acceso", "secretAccessKeyPlaceholder": "Ingrese AWS Clave de acceso secreta", "regionPlaceholder": "Por favor ingrese AWS región", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index e8a06a55a..4899d6c27 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -808,6 +808,11 @@ "disabled": "غیرفعال", "urlPlaceholder": "لطفاً نشانی API را وارد کنید", "keyPlaceholder": "لطفاً کلید API را وارد کنید", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "لطفاً AWS Access Key ID را وارد کنید", "secretAccessKeyPlaceholder": "لطفاً AWS Secret Access Key را وارد کنید", "regionPlaceholder": "لطفاً منطقه AWS را وارد کنید", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 1cd3e6fed..137721866 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -808,6 +808,11 @@ "disabled": "Désactivé", "urlPlaceholder": "Veuillez entrer l'URL de l'API", "keyPlaceholder": "Veuillez entrer la clé API", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Veuillez entrer l'AWS Access Key ID", "secretAccessKeyPlaceholder": "Veuillez entrer l'AWS Secret Access Key", "regionPlaceholder": "Veuillez entrer la région AWS", diff --git a/src/renderer/src/i18n/he-IL/settings.json b/src/renderer/src/i18n/he-IL/settings.json index 26cba9afe..8c087469c 100644 --- a/src/renderer/src/i18n/he-IL/settings.json +++ b/src/renderer/src/i18n/he-IL/settings.json @@ -808,6 +808,11 @@ "disabled": "מושבת", "urlPlaceholder": "אנא הזן כתובת API", "keyPlaceholder": "אנא הזן מפתח API", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "אנא הזן AWS Access Key ID", "secretAccessKeyPlaceholder": "אנא הזן AWS Secret Access Key", "regionPlaceholder": "אנא הזן אזור AWS", diff --git a/src/renderer/src/i18n/id-ID/settings.json b/src/renderer/src/i18n/id-ID/settings.json index 604651afa..12bea6563 100644 --- a/src/renderer/src/i18n/id-ID/settings.json +++ b/src/renderer/src/i18n/id-ID/settings.json @@ -871,6 +871,11 @@ "disabled": "Dinonaktifkan", "urlPlaceholder": "Silakan masukkan API URL", "keyPlaceholder": "Silakan masukkan API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Silakan masukkan ID Kunci Akses AWS", "secretAccessKeyPlaceholder": "Silakan masukkan Kunci Akses Rahasia AWS", "regionPlaceholder": "Silakan masukkan wilayah AWS", diff --git a/src/renderer/src/i18n/it-IT/settings.json b/src/renderer/src/i18n/it-IT/settings.json index 171b8810a..42e79bd40 100644 --- a/src/renderer/src/i18n/it-IT/settings.json +++ b/src/renderer/src/i18n/it-IT/settings.json @@ -871,6 +871,11 @@ "disabled": "Disattivato", "urlPlaceholder": "Inserisci API URL", "keyPlaceholder": "Inserisci API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Inserisci AWS Access Key ID", "secretAccessKeyPlaceholder": "Inserisci AWS Secret Access Key", "regionPlaceholder": "Inserisci regione AWS", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index e33db0abf..4949f51a9 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -808,6 +808,11 @@ "disabled": "無効", "urlPlaceholder": "API URLを入力してください", "keyPlaceholder": "API Keyを入力してください", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "AWS Access Key IDを入力してください", "secretAccessKeyPlaceholder": "AWS Secret Access Keyを入力してください", "regionPlaceholder": "AWSリージョンを入力してください", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index 0894c9634..c067d3c6f 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -808,6 +808,11 @@ "disabled": "비활성화됨", "urlPlaceholder": "API URL을 입력하세요", "keyPlaceholder": "API 키를 입력하세요", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "AWS Access Key ID를 입력하세요", "secretAccessKeyPlaceholder": "AWS Secret Access Key를 입력하세요", "regionPlaceholder": "AWS 리전을 입력하세요", diff --git a/src/renderer/src/i18n/ms-MY/settings.json b/src/renderer/src/i18n/ms-MY/settings.json index d8728b472..ae8528b24 100644 --- a/src/renderer/src/i18n/ms-MY/settings.json +++ b/src/renderer/src/i18n/ms-MY/settings.json @@ -871,6 +871,11 @@ "disabled": "Dilumpuhkan", "urlPlaceholder": "Sila masukkan API URL", "keyPlaceholder": "Sila masukkan API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Sila masukkan AWS Access Key ID", "secretAccessKeyPlaceholder": "Sila masukkan AWS Secret Access Key", "regionPlaceholder": "Sila masukkan kawasan AWS", diff --git a/src/renderer/src/i18n/pl-PL/settings.json b/src/renderer/src/i18n/pl-PL/settings.json index b1eafe756..050b69781 100644 --- a/src/renderer/src/i18n/pl-PL/settings.json +++ b/src/renderer/src/i18n/pl-PL/settings.json @@ -871,6 +871,11 @@ "disabled": "Niepełnosprawny", "urlPlaceholder": "Proszę wpisać API URL", "keyPlaceholder": "Proszę wpisać API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Wprowadź identyfikator klucza dostępu AWS", "secretAccessKeyPlaceholder": "Wprowadź tajny klucz dostępu AWS", "regionPlaceholder": "Wprowadź region AWS", diff --git a/src/renderer/src/i18n/pt-BR/settings.json b/src/renderer/src/i18n/pt-BR/settings.json index b4e3e2a71..d93f3ad3d 100644 --- a/src/renderer/src/i18n/pt-BR/settings.json +++ b/src/renderer/src/i18n/pt-BR/settings.json @@ -808,6 +808,11 @@ "disabled": "Desabilitado", "urlPlaceholder": "Por favor, insira a URL da API", "keyPlaceholder": "Por favor, insira a Chave da API", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Por favor, insira o ID da Chave de Acesso da AWS", "secretAccessKeyPlaceholder": "Por favor, insira a Chave de Acesso Secreta da AWS", "regionPlaceholder": "Por favor, insira a região da AWS", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 897b5fbe6..2530d0e85 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -808,6 +808,11 @@ "disabled": "Отключен", "urlPlaceholder": "Введите API URL", "keyPlaceholder": "Введите API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Введите AWS Access Key ID", "secretAccessKeyPlaceholder": "Введите AWS Secret Access Key", "regionPlaceholder": "Введите регион AWS", diff --git a/src/renderer/src/i18n/tr-TR/settings.json b/src/renderer/src/i18n/tr-TR/settings.json index 7d755587c..e93cfc21d 100644 --- a/src/renderer/src/i18n/tr-TR/settings.json +++ b/src/renderer/src/i18n/tr-TR/settings.json @@ -871,6 +871,11 @@ "disabled": "Engelli", "urlPlaceholder": "Lütfen API URL girin", "keyPlaceholder": "Lütfen API Key girin", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Lütfen AWS Erişim Anahtarı Kimliğini girin", "secretAccessKeyPlaceholder": "Lütfen AWS Gizli Erişim Anahtarını girin", "regionPlaceholder": "Lütfen AWS bölgesini girin", diff --git a/src/renderer/src/i18n/vi-VN/settings.json b/src/renderer/src/i18n/vi-VN/settings.json index 6f4d077dd..7a2fccb85 100644 --- a/src/renderer/src/i18n/vi-VN/settings.json +++ b/src/renderer/src/i18n/vi-VN/settings.json @@ -871,6 +871,11 @@ "disabled": "Đã tắt", "urlPlaceholder": "Vui lòng nhập API URL", "keyPlaceholder": "Vui lòng nhập API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "Vui lòng nhập ID khóa truy cập AWS", "secretAccessKeyPlaceholder": "Vui lòng nhập Khóa truy cập bí mật AWS", "regionPlaceholder": "Vui lòng nhập khu vực AWS", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index 9aa957fe3..1f9bcace8 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -871,6 +871,11 @@ "disabled": "已禁用", "urlPlaceholder": "请输入API URL", "keyPlaceholder": "请输入API Key", + "authMode": "认证方式", + "authModeAccessKeys": "访问密钥", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile 名称", + "profilePlaceholder": "请输入 AWS profile 名称(如 default)", "accessKeyIdPlaceholder": "请输入AWS Access Key ID", "secretAccessKeyPlaceholder": "请输入AWS Secret Access Key", "regionPlaceholder": "请输入AWS区域", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index ead2d5cbb..7fa5b20f0 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -808,6 +808,11 @@ "disabled": "已禁用", "urlPlaceholder": "請輸入API URL", "keyPlaceholder": "請輸入API Key", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "請輸入AWS Access Key ID", "secretAccessKeyPlaceholder": "請輸入AWS Secret Access Key", "regionPlaceholder": "請輸入AWS區域", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index ade181c17..eacb2099d 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -808,6 +808,11 @@ "disabled": "已停用", "urlPlaceholder": "請輸入 API URL", "keyPlaceholder": "請輸入 API 金鑰", + "authMode": "Authentication Mode", + "authModeAccessKeys": "Access Keys", + "authModeProfile": "AWS Profile", + "profileNameLabel": "AWS Profile Name", + "profilePlaceholder": "Please enter AWS profile name (e.g. default)", "accessKeyIdPlaceholder": "請輸入 AWS Access Key ID", "secretAccessKeyPlaceholder": "請輸入 AWS Secret Access Key", "regionPlaceholder": "請輸入 AWS 區域", diff --git a/src/shared/contracts/domainSchemas.ts b/src/shared/contracts/domainSchemas.ts index 76ec7606d..a15ffa2bc 100644 --- a/src/shared/contracts/domainSchemas.ts +++ b/src/shared/contracts/domainSchemas.ts @@ -100,9 +100,11 @@ export const LlmProviderSchema = z .optional(), credential: z .object({ + authMode: z.enum(['accessKeys', 'profile']).optional(), accessKeyId: z.string(), secretAccessKey: z.string(), - region: z.string().optional() + region: z.string().optional(), + profile: z.string().optional() }) .optional(), projectId: z.string().optional(), diff --git a/src/shared/types/presenters/legacy.presenters.d.ts b/src/shared/types/presenters/legacy.presenters.d.ts index 7d9f3dd38..9d8fc2f3e 100644 --- a/src/shared/types/presenters/legacy.presenters.d.ts +++ b/src/shared/types/presenters/legacy.presenters.d.ts @@ -1195,9 +1195,11 @@ export type VERTEX_PROVIDER = LLM_PROVIDER & { } export interface AwsBedrockCredential { + authMode?: 'accessKeys' | 'profile' accessKeyId: string secretAccessKey: string region?: string + profile?: string } export interface ILlmProviderPresenter { diff --git a/src/shared/types/presenters/llmprovider.presenter.d.ts b/src/shared/types/presenters/llmprovider.presenter.d.ts index 9bfd53646..d654c908c 100644 --- a/src/shared/types/presenters/llmprovider.presenter.d.ts +++ b/src/shared/types/presenters/llmprovider.presenter.d.ts @@ -133,9 +133,11 @@ export interface KeyStatus { } export interface AwsBedrockCredential { + authMode?: 'accessKeys' | 'profile' accessKeyId: string secretAccessKey: string region?: string + profile?: string } export type AWS_BEDROCK_PROVIDER = LLM_PROVIDER & { From bc8b9d8b830c6be28d2f8e64bd34718a0c894939 Mon Sep 17 00:00:00 2001 From: Peter Xue Date: Mon, 8 Jun 2026 14:14:50 -0700 Subject: [PATCH 2/4] fix(bedrock): use fetch-models for verification and support profile in model listing - Change checkStrategy from generate-text to fetch-models so verification no longer depends on a specific model ID - Support profile auth mode in fetchBedrockModels() via fromNodeProviderChain --- .../llmProviderPresenter/providerRegistry.ts | 6 +-- .../providers/aiSdkProvider.ts | 37 +++++++++++++------ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/main/presenter/llmProviderPresenter/providerRegistry.ts b/src/main/presenter/llmProviderPresenter/providerRegistry.ts index 19c05656e..6c3df9388 100644 --- a/src/main/presenter/llmProviderPresenter/providerRegistry.ts +++ b/src/main/presenter/llmProviderPresenter/providerRegistry.ts @@ -132,15 +132,11 @@ const PROVIDER_ID_REGISTRY = new Map([ runtimeKind: 'aws-bedrock', behaviorPreset: 'anthropic', modelSource: 'bedrock', - checkStrategy: 'generate-text', + checkStrategy: 'fetch-models', credentialStrategy: 'bedrock', keyStatusStrategy: 'none', routeStrategy: 'none', embeddingStrategy: 'none', - checkModelId: 'anthropic.claude-3-5-sonnet-20240620-v1:0', - checkPrompt: 'Hi', - checkTemperature: 0.2, - checkMaxTokens: 16, providerDbSourceId: 'amazon-bedrock' }) ], diff --git a/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts b/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts index a32d17551..31c34c6f2 100644 --- a/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts @@ -34,6 +34,7 @@ import { VERTEX_PROVIDER } from '@shared/presenter' import { BedrockClient, ListFoundationModelsCommand } from '@aws-sdk/client-bedrock' +import { fromNodeProviderChain } from '@aws-sdk/credential-providers' import { ProxyAgent } from 'undici' import { BaseLLMProvider, SUMMARY_TITLES_PROMPT } from '../baseProvider' import { @@ -1743,25 +1744,37 @@ export class AiSdkProvider extends BaseLLMProvider { private async fetchBedrockModels(): Promise { const provider = this.provider as AWS_BEDROCK_PROVIDER - const accessKeyId = provider.credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID - const secretAccessKey = - provider.credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY - const region = provider.credential?.region || process.env.BEDROCK_REGION + const credential = provider.credential + const region = credential?.region || process.env.BEDROCK_REGION + const useProfile = credential?.authMode === 'profile' && credential?.profile + + if (!useProfile) { + const accessKeyId = credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID + const secretAccessKey = credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY + if (!accessKeyId || !secretAccessKey || !region) { + return this.mapConfigDbModels(this.definition.providerDbSourceId).filter((model) => + model.id.startsWith('anthropic.') + ) + } + } - if (!accessKeyId || !secretAccessKey || !region) { + if (!region) { return this.mapConfigDbModels(this.definition.providerDbSourceId).filter((model) => model.id.startsWith('anthropic.') ) } try { - const client = new BedrockClient({ - credentials: { - accessKeyId, - secretAccessKey - }, - region - }) + const clientConfig: Record = { region } + if (useProfile) { + clientConfig.credentials = fromNodeProviderChain({ profile: credential.profile }) + } else { + clientConfig.credentials = { + accessKeyId: credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID, + secretAccessKey: credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY + } + } + const client = new BedrockClient(clientConfig as any) const response = await client.send(new ListFoundationModelsCommand({})) return ( response.modelSummaries From f709bde3f6538fd5a4e2aa934706a725d5f38a5e Mon Sep 17 00:00:00 2001 From: Peter Xue Date: Mon, 8 Jun 2026 14:24:53 -0700 Subject: [PATCH 3/4] fix(i18n): translate bedrock profile auth keys to all locales --- src/renderer/src/i18n/da-DK/settings.json | 10 +++++----- src/renderer/src/i18n/de-DE/settings.json | 10 +++++----- src/renderer/src/i18n/es-ES/settings.json | 10 +++++----- src/renderer/src/i18n/fa-IR/settings.json | 10 +++++----- src/renderer/src/i18n/fr-FR/settings.json | 10 +++++----- src/renderer/src/i18n/he-IL/settings.json | 10 +++++----- src/renderer/src/i18n/id-ID/settings.json | 10 +++++----- src/renderer/src/i18n/it-IT/settings.json | 10 +++++----- src/renderer/src/i18n/ja-JP/settings.json | 10 +++++----- src/renderer/src/i18n/ko-KR/settings.json | 10 +++++----- src/renderer/src/i18n/ms-MY/settings.json | 10 +++++----- src/renderer/src/i18n/pl-PL/settings.json | 10 +++++----- src/renderer/src/i18n/pt-BR/settings.json | 10 +++++----- src/renderer/src/i18n/ru-RU/settings.json | 10 +++++----- src/renderer/src/i18n/tr-TR/settings.json | 10 +++++----- src/renderer/src/i18n/vi-VN/settings.json | 10 +++++----- src/renderer/src/i18n/zh-HK/settings.json | 8 ++++---- src/renderer/src/i18n/zh-TW/settings.json | 8 ++++---- 18 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/renderer/src/i18n/da-DK/settings.json b/src/renderer/src/i18n/da-DK/settings.json index 7fd0cabd7..4706881e0 100644 --- a/src/renderer/src/i18n/da-DK/settings.json +++ b/src/renderer/src/i18n/da-DK/settings.json @@ -741,11 +741,11 @@ "disabled": "Deaktiveret", "urlPlaceholder": "Indtast API-URL", "keyPlaceholder": "Indtast API-nøgle", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Godkendelsesmetode", + "authModeAccessKeys": "Adgangsnøgler", + "authModeProfile": "AWS-profil", + "profileNameLabel": "AWS-profilnavn", + "profilePlaceholder": "Indtast venligst AWS-profilnavn (f.eks. default)", "accessKeyIdPlaceholder": "Indtast AWS Access Key ID", "secretAccessKeyPlaceholder": "Indtast AWS Secret Access Key", "regionPlaceholder": "Indtast AWS-region", diff --git a/src/renderer/src/i18n/de-DE/settings.json b/src/renderer/src/i18n/de-DE/settings.json index 4189ecd4b..5fc3b1f71 100644 --- a/src/renderer/src/i18n/de-DE/settings.json +++ b/src/renderer/src/i18n/de-DE/settings.json @@ -871,11 +871,11 @@ "disabled": "Deaktiviert", "urlPlaceholder": "API URL eingeben", "keyPlaceholder": "API Key eingeben", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Authentifizierungsmethode", + "authModeAccessKeys": "Zugriffsschlüssel", + "authModeProfile": "AWS-Profil", + "profileNameLabel": "AWS-Profilname", + "profilePlaceholder": "Bitte AWS-Profilnamen eingeben (z.B. default)", "accessKeyIdPlaceholder": "AWS Access Key ID eingeben", "secretAccessKeyPlaceholder": "AWS Secret Access Key eingeben", "regionPlaceholder": "AWS-Region eingeben", diff --git a/src/renderer/src/i18n/es-ES/settings.json b/src/renderer/src/i18n/es-ES/settings.json index 035345c9d..f2eccdfb0 100644 --- a/src/renderer/src/i18n/es-ES/settings.json +++ b/src/renderer/src/i18n/es-ES/settings.json @@ -871,11 +871,11 @@ "disabled": "Discapacitado", "urlPlaceholder": "Por favor ingrese API URL", "keyPlaceholder": "Por favor ingrese API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Método de autenticación", + "authModeAccessKeys": "Claves de acceso", + "authModeProfile": "Perfil de AWS", + "profileNameLabel": "Nombre del perfil de AWS", + "profilePlaceholder": "Ingrese el nombre del perfil de AWS (ej. default)", "accessKeyIdPlaceholder": "Por favor ingrese AWS ID de clave de acceso", "secretAccessKeyPlaceholder": "Ingrese AWS Clave de acceso secreta", "regionPlaceholder": "Por favor ingrese AWS región", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 4899d6c27..d0f4568f2 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -808,11 +808,11 @@ "disabled": "غیرفعال", "urlPlaceholder": "لطفاً نشانی API را وارد کنید", "keyPlaceholder": "لطفاً کلید API را وارد کنید", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "روش احراز هویت", + "authModeAccessKeys": "کلیدهای دسترسی", + "authModeProfile": "پروفایل AWS", + "profileNameLabel": "نام پروفایل AWS", + "profilePlaceholder": "لطفاً نام پروفایل AWS را وارد کنید (مثلاً default)", "accessKeyIdPlaceholder": "لطفاً AWS Access Key ID را وارد کنید", "secretAccessKeyPlaceholder": "لطفاً AWS Secret Access Key را وارد کنید", "regionPlaceholder": "لطفاً منطقه AWS را وارد کنید", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 137721866..21d06a6af 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -808,11 +808,11 @@ "disabled": "Désactivé", "urlPlaceholder": "Veuillez entrer l'URL de l'API", "keyPlaceholder": "Veuillez entrer la clé API", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Mode d'authentification", + "authModeAccessKeys": "Clés d'accès", + "authModeProfile": "Profil AWS", + "profileNameLabel": "Nom du profil AWS", + "profilePlaceholder": "Veuillez entrer le nom du profil AWS (ex. default)", "accessKeyIdPlaceholder": "Veuillez entrer l'AWS Access Key ID", "secretAccessKeyPlaceholder": "Veuillez entrer l'AWS Secret Access Key", "regionPlaceholder": "Veuillez entrer la région AWS", diff --git a/src/renderer/src/i18n/he-IL/settings.json b/src/renderer/src/i18n/he-IL/settings.json index 8c087469c..7370b4179 100644 --- a/src/renderer/src/i18n/he-IL/settings.json +++ b/src/renderer/src/i18n/he-IL/settings.json @@ -808,11 +808,11 @@ "disabled": "מושבת", "urlPlaceholder": "אנא הזן כתובת API", "keyPlaceholder": "אנא הזן מפתח API", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "שיטת אימות", + "authModeAccessKeys": "מפתחות גישה", + "authModeProfile": "פרופיל AWS", + "profileNameLabel": "שם פרופיל AWS", + "profilePlaceholder": "הזן את שם פרופיל AWS (למשל default)", "accessKeyIdPlaceholder": "אנא הזן AWS Access Key ID", "secretAccessKeyPlaceholder": "אנא הזן AWS Secret Access Key", "regionPlaceholder": "אנא הזן אזור AWS", diff --git a/src/renderer/src/i18n/id-ID/settings.json b/src/renderer/src/i18n/id-ID/settings.json index 12bea6563..5c49442c3 100644 --- a/src/renderer/src/i18n/id-ID/settings.json +++ b/src/renderer/src/i18n/id-ID/settings.json @@ -871,11 +871,11 @@ "disabled": "Dinonaktifkan", "urlPlaceholder": "Silakan masukkan API URL", "keyPlaceholder": "Silakan masukkan API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Metode autentikasi", + "authModeAccessKeys": "Kunci akses", + "authModeProfile": "Profil AWS", + "profileNameLabel": "Nama profil AWS", + "profilePlaceholder": "Masukkan nama profil AWS (contoh: default)", "accessKeyIdPlaceholder": "Silakan masukkan ID Kunci Akses AWS", "secretAccessKeyPlaceholder": "Silakan masukkan Kunci Akses Rahasia AWS", "regionPlaceholder": "Silakan masukkan wilayah AWS", diff --git a/src/renderer/src/i18n/it-IT/settings.json b/src/renderer/src/i18n/it-IT/settings.json index 42e79bd40..411edf8bc 100644 --- a/src/renderer/src/i18n/it-IT/settings.json +++ b/src/renderer/src/i18n/it-IT/settings.json @@ -871,11 +871,11 @@ "disabled": "Disattivato", "urlPlaceholder": "Inserisci API URL", "keyPlaceholder": "Inserisci API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Metodo di autenticazione", + "authModeAccessKeys": "Chiavi di accesso", + "authModeProfile": "Profilo AWS", + "profileNameLabel": "Nome del profilo AWS", + "profilePlaceholder": "Inserire il nome del profilo AWS (es. default)", "accessKeyIdPlaceholder": "Inserisci AWS Access Key ID", "secretAccessKeyPlaceholder": "Inserisci AWS Secret Access Key", "regionPlaceholder": "Inserisci regione AWS", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 4949f51a9..4a9c7fafe 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -808,11 +808,11 @@ "disabled": "無効", "urlPlaceholder": "API URLを入力してください", "keyPlaceholder": "API Keyを入力してください", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "認証方式", + "authModeAccessKeys": "アクセスキー", + "authModeProfile": "AWSプロファイル", + "profileNameLabel": "AWSプロファイル名", + "profilePlaceholder": "AWSプロファイル名を入力してください(例: default)", "accessKeyIdPlaceholder": "AWS Access Key IDを入力してください", "secretAccessKeyPlaceholder": "AWS Secret Access Keyを入力してください", "regionPlaceholder": "AWSリージョンを入力してください", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index c067d3c6f..16c7ab1b1 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -808,11 +808,11 @@ "disabled": "비활성화됨", "urlPlaceholder": "API URL을 입력하세요", "keyPlaceholder": "API 키를 입력하세요", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "인증 방식", + "authModeAccessKeys": "액세스 키", + "authModeProfile": "AWS 프로필", + "profileNameLabel": "AWS 프로필 이름", + "profilePlaceholder": "AWS 프로필 이름을 입력하세요 (예: default)", "accessKeyIdPlaceholder": "AWS Access Key ID를 입력하세요", "secretAccessKeyPlaceholder": "AWS Secret Access Key를 입력하세요", "regionPlaceholder": "AWS 리전을 입력하세요", diff --git a/src/renderer/src/i18n/ms-MY/settings.json b/src/renderer/src/i18n/ms-MY/settings.json index ae8528b24..4124b1480 100644 --- a/src/renderer/src/i18n/ms-MY/settings.json +++ b/src/renderer/src/i18n/ms-MY/settings.json @@ -871,11 +871,11 @@ "disabled": "Dilumpuhkan", "urlPlaceholder": "Sila masukkan API URL", "keyPlaceholder": "Sila masukkan API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Kaedah pengesahan", + "authModeAccessKeys": "Kunci akses", + "authModeProfile": "Profil AWS", + "profileNameLabel": "Nama profil AWS", + "profilePlaceholder": "Sila masukkan nama profil AWS (cth. default)", "accessKeyIdPlaceholder": "Sila masukkan AWS Access Key ID", "secretAccessKeyPlaceholder": "Sila masukkan AWS Secret Access Key", "regionPlaceholder": "Sila masukkan kawasan AWS", diff --git a/src/renderer/src/i18n/pl-PL/settings.json b/src/renderer/src/i18n/pl-PL/settings.json index 050b69781..594b69225 100644 --- a/src/renderer/src/i18n/pl-PL/settings.json +++ b/src/renderer/src/i18n/pl-PL/settings.json @@ -871,11 +871,11 @@ "disabled": "Niepełnosprawny", "urlPlaceholder": "Proszę wpisać API URL", "keyPlaceholder": "Proszę wpisać API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Metoda uwierzytelniania", + "authModeAccessKeys": "Klucze dostępu", + "authModeProfile": "Profil AWS", + "profileNameLabel": "Nazwa profilu AWS", + "profilePlaceholder": "Wprowadź nazwę profilu AWS (np. default)", "accessKeyIdPlaceholder": "Wprowadź identyfikator klucza dostępu AWS", "secretAccessKeyPlaceholder": "Wprowadź tajny klucz dostępu AWS", "regionPlaceholder": "Wprowadź region AWS", diff --git a/src/renderer/src/i18n/pt-BR/settings.json b/src/renderer/src/i18n/pt-BR/settings.json index d93f3ad3d..b3bc7ef0d 100644 --- a/src/renderer/src/i18n/pt-BR/settings.json +++ b/src/renderer/src/i18n/pt-BR/settings.json @@ -808,11 +808,11 @@ "disabled": "Desabilitado", "urlPlaceholder": "Por favor, insira a URL da API", "keyPlaceholder": "Por favor, insira a Chave da API", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Método de autenticação", + "authModeAccessKeys": "Chaves de acesso", + "authModeProfile": "Perfil AWS", + "profileNameLabel": "Nome do perfil AWS", + "profilePlaceholder": "Insira o nome do perfil AWS (ex. default)", "accessKeyIdPlaceholder": "Por favor, insira o ID da Chave de Acesso da AWS", "secretAccessKeyPlaceholder": "Por favor, insira a Chave de Acesso Secreta da AWS", "regionPlaceholder": "Por favor, insira a região da AWS", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 2530d0e85..1e04e318f 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -808,11 +808,11 @@ "disabled": "Отключен", "urlPlaceholder": "Введите API URL", "keyPlaceholder": "Введите API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Способ аутентификации", + "authModeAccessKeys": "Ключи доступа", + "authModeProfile": "Профиль AWS", + "profileNameLabel": "Имя профиля AWS", + "profilePlaceholder": "Введите имя профиля AWS (напр. default)", "accessKeyIdPlaceholder": "Введите AWS Access Key ID", "secretAccessKeyPlaceholder": "Введите AWS Secret Access Key", "regionPlaceholder": "Введите регион AWS", diff --git a/src/renderer/src/i18n/tr-TR/settings.json b/src/renderer/src/i18n/tr-TR/settings.json index e93cfc21d..026c3cfd6 100644 --- a/src/renderer/src/i18n/tr-TR/settings.json +++ b/src/renderer/src/i18n/tr-TR/settings.json @@ -871,11 +871,11 @@ "disabled": "Engelli", "urlPlaceholder": "Lütfen API URL girin", "keyPlaceholder": "Lütfen API Key girin", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Kimlik doğrulama yöntemi", + "authModeAccessKeys": "Erişim anahtarları", + "authModeProfile": "AWS Profili", + "profileNameLabel": "AWS Profil adı", + "profilePlaceholder": "Lütfen AWS profil adını girin (ör. default)", "accessKeyIdPlaceholder": "Lütfen AWS Erişim Anahtarı Kimliğini girin", "secretAccessKeyPlaceholder": "Lütfen AWS Gizli Erişim Anahtarını girin", "regionPlaceholder": "Lütfen AWS bölgesini girin", diff --git a/src/renderer/src/i18n/vi-VN/settings.json b/src/renderer/src/i18n/vi-VN/settings.json index 7a2fccb85..9975bc3b8 100644 --- a/src/renderer/src/i18n/vi-VN/settings.json +++ b/src/renderer/src/i18n/vi-VN/settings.json @@ -871,11 +871,11 @@ "disabled": "Đã tắt", "urlPlaceholder": "Vui lòng nhập API URL", "keyPlaceholder": "Vui lòng nhập API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", - "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "authMode": "Phương thức xác thực", + "authModeAccessKeys": "Khóa truy cập", + "authModeProfile": "Hồ sơ AWS", + "profileNameLabel": "Tên hồ sơ AWS", + "profilePlaceholder": "Vui lòng nhập tên hồ sơ AWS (ví dụ: default)", "accessKeyIdPlaceholder": "Vui lòng nhập ID khóa truy cập AWS", "secretAccessKeyPlaceholder": "Vui lòng nhập Khóa truy cập bí mật AWS", "regionPlaceholder": "Vui lòng nhập khu vực AWS", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 7fa5b20f0..ed4d7d802 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -808,11 +808,11 @@ "disabled": "已禁用", "urlPlaceholder": "請輸入API URL", "keyPlaceholder": "請輸入API Key", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", + "authMode": "認證方式", + "authModeAccessKeys": "存取金鑰", "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "profileNameLabel": "AWS Profile 名稱", + "profilePlaceholder": "請輸入 AWS profile 名稱(如 default)", "accessKeyIdPlaceholder": "請輸入AWS Access Key ID", "secretAccessKeyPlaceholder": "請輸入AWS Secret Access Key", "regionPlaceholder": "請輸入AWS區域", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index eacb2099d..e999fc3fc 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -808,11 +808,11 @@ "disabled": "已停用", "urlPlaceholder": "請輸入 API URL", "keyPlaceholder": "請輸入 API 金鑰", - "authMode": "Authentication Mode", - "authModeAccessKeys": "Access Keys", + "authMode": "認證方式", + "authModeAccessKeys": "存取金鑰", "authModeProfile": "AWS Profile", - "profileNameLabel": "AWS Profile Name", - "profilePlaceholder": "Please enter AWS profile name (e.g. default)", + "profileNameLabel": "AWS Profile 名稱", + "profilePlaceholder": "請輸入 AWS profile 名稱(如 default)", "accessKeyIdPlaceholder": "請輸入 AWS Access Key ID", "secretAccessKeyPlaceholder": "請輸入 AWS Secret Access Key", "regionPlaceholder": "請輸入 AWS 區域", From 2339607eae32b0524cd632798d1f00e6c6ae681e Mon Sep 17 00:00:00 2001 From: Peter Xue Date: Mon, 8 Jun 2026 16:43:14 -0700 Subject: [PATCH 4/4] fix(bedrock): address PR review feedback - Unify env var names: use AWS_REGION/AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY consistently (matches providerFactory.ts) - Validate authMode value before assignment in settings UI --- .../providers/aiSdkProvider.ts | 16 ++++++++-------- .../components/BedrockProviderSettingsDetail.vue | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts b/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts index 31c34c6f2..ac0e64ce0 100644 --- a/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts @@ -1745,12 +1745,12 @@ export class AiSdkProvider extends BaseLLMProvider { private async fetchBedrockModels(): Promise { const provider = this.provider as AWS_BEDROCK_PROVIDER const credential = provider.credential - const region = credential?.region || process.env.BEDROCK_REGION + const region = credential?.region || process.env.AWS_REGION const useProfile = credential?.authMode === 'profile' && credential?.profile if (!useProfile) { - const accessKeyId = credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID - const secretAccessKey = credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY + const accessKeyId = credential?.accessKeyId || process.env.AWS_ACCESS_KEY_ID + const secretAccessKey = credential?.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY if (!accessKeyId || !secretAccessKey || !region) { return this.mapConfigDbModels(this.definition.providerDbSourceId).filter((model) => model.id.startsWith('anthropic.') @@ -1770,8 +1770,8 @@ export class AiSdkProvider extends BaseLLMProvider { clientConfig.credentials = fromNodeProviderChain({ profile: credential.profile }) } else { clientConfig.credentials = { - accessKeyId: credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID, - secretAccessKey: credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY + accessKeyId: credential?.accessKeyId || process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: credential?.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY } } const client = new BedrockClient(clientConfig as any) @@ -2222,14 +2222,14 @@ export class AiSdkProvider extends BaseLLMProvider { case 'bedrock': { const provider = this.provider as AWS_BEDROCK_PROVIDER const credential = provider.credential - const region = credential?.region || process.env.BEDROCK_REGION + const region = credential?.region || process.env.AWS_REGION if (credential?.authMode === 'profile') { return credential.profile && region ? null : 'Missing AWS profile name or region' } - const accessKeyId = credential?.accessKeyId || process.env.BEDROCK_ACCESS_KEY_ID - const secretAccessKey = credential?.secretAccessKey || process.env.BEDROCK_SECRET_ACCESS_KEY + const accessKeyId = credential?.accessKeyId || process.env.AWS_ACCESS_KEY_ID + const secretAccessKey = credential?.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY return accessKeyId && secretAccessKey && region ? null : 'Missing AWS Bedrock credentials' } case 'none': diff --git a/src/renderer/settings/components/BedrockProviderSettingsDetail.vue b/src/renderer/settings/components/BedrockProviderSettingsDetail.vue index 4fe560d34..1bf5aa019 100644 --- a/src/renderer/settings/components/BedrockProviderSettingsDetail.vue +++ b/src/renderer/settings/components/BedrockProviderSettingsDetail.vue @@ -299,8 +299,8 @@ watch( ) const handleAuthModeChange = async (value: unknown) => { - if (!value || typeof value !== 'string') return - authMode.value = value as 'accessKeys' | 'profile' + if (value !== 'accessKeys' && value !== 'profile') return + authMode.value = value const result = await providerStore.updateAwsBedrockProviderConfig(props.provider.id, { credential: buildCredential() })