mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-23 10:00:08 +08:00
feat: amazon bedrock request use bedrock api key (#10727)
* feat: amazon bedrock request use bedrock api key * feat: ai-core/provider support bedrock api key * refactor: extract AWS Bedrock auth type and remove redundant state * feat: add bedrock reasoning support Add AWS Bedrock-specific reasoning parameter handling to support Extended Thinking feature for Claude models via Bedrock API. Changes: - Add `buildBedrockProviderOptions` function in options.ts to handle Bedrock-specific provider options - Add `getBedrockReasoningParams` function in reasoning.ts to generate reasoning config with budget tokens - Register 'bedrock' case in provider options switch to route to Bedrock-specific builder - Reuse `getAnthropicThinkingBudget` helper for consistent token budget calculation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add migration for Bedrock auth type and API key fields * refactor: replace any type with BedrockRuntimeClientConfig in AWS Bedrock client * fix: bug fix * fix: lint error * fix: bedrock reasoning * chore: bump persisted reducer version to 171 * Update src/renderer/src/store/migrate.ts --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: icarus <eurfelux@gmail.com>
This commit is contained in:
parent
49bd298d37
commit
abd5d3b96f
@ -113,9 +113,9 @@
|
|||||||
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
||||||
"@anthropic-ai/sdk": "^0.41.0",
|
"@anthropic-ai/sdk": "^0.41.0",
|
||||||
"@anthropic-ai/vertex-sdk": "patch:@anthropic-ai/vertex-sdk@npm%3A0.11.4#~/.yarn/patches/@anthropic-ai-vertex-sdk-npm-0.11.4-c19cb41edb.patch",
|
"@anthropic-ai/vertex-sdk": "patch:@anthropic-ai/vertex-sdk@npm%3A0.11.4#~/.yarn/patches/@anthropic-ai-vertex-sdk-npm-0.11.4-c19cb41edb.patch",
|
||||||
"@aws-sdk/client-bedrock": "^3.840.0",
|
"@aws-sdk/client-bedrock": "^3.910.0",
|
||||||
"@aws-sdk/client-bedrock-runtime": "^3.840.0",
|
"@aws-sdk/client-bedrock-runtime": "^3.910.0",
|
||||||
"@aws-sdk/client-s3": "^3.840.0",
|
"@aws-sdk/client-s3": "^3.910.0",
|
||||||
"@biomejs/biome": "2.2.4",
|
"@biomejs/biome": "2.2.4",
|
||||||
"@cherrystudio/ai-core": "workspace:^1.0.0-alpha.18",
|
"@cherrystudio/ai-core": "workspace:^1.0.0-alpha.18",
|
||||||
"@cherrystudio/embedjs": "^0.1.31",
|
"@cherrystudio/embedjs": "^0.1.31",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { BedrockClient, ListFoundationModelsCommand, ListInferenceProfilesCommand } from '@aws-sdk/client-bedrock'
|
import { BedrockClient, ListFoundationModelsCommand, ListInferenceProfilesCommand } from '@aws-sdk/client-bedrock'
|
||||||
import {
|
import {
|
||||||
BedrockRuntimeClient,
|
BedrockRuntimeClient,
|
||||||
|
type BedrockRuntimeClientConfig,
|
||||||
ConverseCommand,
|
ConverseCommand,
|
||||||
InvokeModelCommand,
|
InvokeModelCommand,
|
||||||
InvokeModelWithResponseStreamCommand
|
InvokeModelWithResponseStreamCommand
|
||||||
@ -11,6 +12,8 @@ import { DEFAULT_MAX_TOKENS } from '@renderer/config/constant'
|
|||||||
import { findTokenLimit, isReasoningModel } from '@renderer/config/models'
|
import { findTokenLimit, isReasoningModel } from '@renderer/config/models'
|
||||||
import {
|
import {
|
||||||
getAwsBedrockAccessKeyId,
|
getAwsBedrockAccessKeyId,
|
||||||
|
getAwsBedrockApiKey,
|
||||||
|
getAwsBedrockAuthType,
|
||||||
getAwsBedrockRegion,
|
getAwsBedrockRegion,
|
||||||
getAwsBedrockSecretAccessKey
|
getAwsBedrockSecretAccessKey
|
||||||
} from '@renderer/hooks/useAwsBedrock'
|
} from '@renderer/hooks/useAwsBedrock'
|
||||||
@ -75,32 +78,48 @@ export class AwsBedrockAPIClient extends BaseApiClient<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const region = getAwsBedrockRegion()
|
const region = getAwsBedrockRegion()
|
||||||
const accessKeyId = getAwsBedrockAccessKeyId()
|
const authType = getAwsBedrockAuthType()
|
||||||
const secretAccessKey = getAwsBedrockSecretAccessKey()
|
|
||||||
|
|
||||||
if (!region) {
|
if (!region) {
|
||||||
throw new Error('AWS region is required. Please configure AWS-Region in extra headers.')
|
throw new Error('AWS region is required. Please configure AWS region in settings.')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!accessKeyId || !secretAccessKey) {
|
// Build client configuration based on auth type
|
||||||
throw new Error('AWS credentials are required. Please configure AWS-Access-Key-ID and AWS-Secret-Access-Key.')
|
let clientConfig: BedrockRuntimeClientConfig
|
||||||
|
|
||||||
|
if (authType === 'iam') {
|
||||||
|
// IAM credentials authentication
|
||||||
|
const accessKeyId = getAwsBedrockAccessKeyId()
|
||||||
|
const secretAccessKey = getAwsBedrockSecretAccessKey()
|
||||||
|
|
||||||
|
if (!accessKeyId || !secretAccessKey) {
|
||||||
|
throw new Error('AWS credentials are required. Please configure Access Key ID and Secret Access Key.')
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig = {
|
||||||
|
region,
|
||||||
|
credentials: {
|
||||||
|
accessKeyId,
|
||||||
|
secretAccessKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// API Key authentication
|
||||||
|
const awsBedrockApiKey = getAwsBedrockApiKey()
|
||||||
|
|
||||||
|
if (!awsBedrockApiKey) {
|
||||||
|
throw new Error('AWS Bedrock API Key is required. Please configure API Key in settings.')
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig = {
|
||||||
|
region,
|
||||||
|
token: { token: awsBedrockApiKey },
|
||||||
|
authSchemePreference: ['httpBearerAuth']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = new BedrockRuntimeClient({
|
const client = new BedrockRuntimeClient(clientConfig)
|
||||||
region,
|
const bedrockClient = new BedrockClient(clientConfig)
|
||||||
credentials: {
|
|
||||||
accessKeyId,
|
|
||||||
secretAccessKey
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const bedrockClient = new BedrockClient({
|
|
||||||
region,
|
|
||||||
credentials: {
|
|
||||||
accessKeyId,
|
|
||||||
secretAccessKey
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.sdkInstance = { client, bedrockClient, region }
|
this.sdkInstance = { client, bedrockClient, region }
|
||||||
return this.sdkInstance
|
return this.sdkInstance
|
||||||
|
|||||||
@ -14,6 +14,8 @@ import {
|
|||||||
} from '@renderer/config/providers'
|
} from '@renderer/config/providers'
|
||||||
import {
|
import {
|
||||||
getAwsBedrockAccessKeyId,
|
getAwsBedrockAccessKeyId,
|
||||||
|
getAwsBedrockApiKey,
|
||||||
|
getAwsBedrockAuthType,
|
||||||
getAwsBedrockRegion,
|
getAwsBedrockRegion,
|
||||||
getAwsBedrockSecretAccessKey
|
getAwsBedrockSecretAccessKey
|
||||||
} from '@renderer/hooks/useAwsBedrock'
|
} from '@renderer/hooks/useAwsBedrock'
|
||||||
@ -192,9 +194,15 @@ export function providerToAiSdkConfig(
|
|||||||
|
|
||||||
// bedrock
|
// bedrock
|
||||||
if (aiSdkProviderId === 'bedrock') {
|
if (aiSdkProviderId === 'bedrock') {
|
||||||
|
const authType = getAwsBedrockAuthType()
|
||||||
extraOptions.region = getAwsBedrockRegion()
|
extraOptions.region = getAwsBedrockRegion()
|
||||||
extraOptions.accessKeyId = getAwsBedrockAccessKeyId()
|
|
||||||
extraOptions.secretAccessKey = getAwsBedrockSecretAccessKey()
|
if (authType === 'apiKey') {
|
||||||
|
extraOptions.apiKey = getAwsBedrockApiKey()
|
||||||
|
} else {
|
||||||
|
extraOptions.accessKeyId = getAwsBedrockAccessKeyId()
|
||||||
|
extraOptions.secretAccessKey = getAwsBedrockSecretAccessKey()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// google-vertex
|
// google-vertex
|
||||||
if (aiSdkProviderId === 'google-vertex' || aiSdkProviderId === 'google-vertex-anthropic') {
|
if (aiSdkProviderId === 'google-vertex' || aiSdkProviderId === 'google-vertex-anthropic') {
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import { getAiSdkProviderId } from '../provider/factory'
|
|||||||
import { buildGeminiGenerateImageParams } from './image'
|
import { buildGeminiGenerateImageParams } from './image'
|
||||||
import {
|
import {
|
||||||
getAnthropicReasoningParams,
|
getAnthropicReasoningParams,
|
||||||
|
getBedrockReasoningParams,
|
||||||
getCustomParameters,
|
getCustomParameters,
|
||||||
getGeminiReasoningParams,
|
getGeminiReasoningParams,
|
||||||
getOpenAIReasoningParams,
|
getOpenAIReasoningParams,
|
||||||
@ -127,6 +128,9 @@ export function buildProviderOptions(
|
|||||||
case 'google-vertex-anthropic':
|
case 'google-vertex-anthropic':
|
||||||
providerSpecificOptions = buildAnthropicProviderOptions(assistant, model, capabilities)
|
providerSpecificOptions = buildAnthropicProviderOptions(assistant, model, capabilities)
|
||||||
break
|
break
|
||||||
|
case 'bedrock':
|
||||||
|
providerSpecificOptions = buildBedrockProviderOptions(assistant, model, capabilities)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
// 对于其他 provider,使用通用的构建逻辑
|
// 对于其他 provider,使用通用的构建逻辑
|
||||||
providerSpecificOptions = {
|
providerSpecificOptions = {
|
||||||
@ -266,6 +270,32 @@ function buildXAIProviderOptions(
|
|||||||
return providerOptions
|
return providerOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build Bedrock providerOptions
|
||||||
|
*/
|
||||||
|
function buildBedrockProviderOptions(
|
||||||
|
assistant: Assistant,
|
||||||
|
model: Model,
|
||||||
|
capabilities: {
|
||||||
|
enableReasoning: boolean
|
||||||
|
enableWebSearch: boolean
|
||||||
|
enableGenerateImage: boolean
|
||||||
|
}
|
||||||
|
): Record<string, any> {
|
||||||
|
const { enableReasoning } = capabilities
|
||||||
|
let providerOptions: Record<string, any> = {}
|
||||||
|
|
||||||
|
if (enableReasoning) {
|
||||||
|
const reasoningParams = getBedrockReasoningParams(assistant, model)
|
||||||
|
providerOptions = {
|
||||||
|
...providerOptions,
|
||||||
|
...reasoningParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return providerOptions
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建通用的 providerOptions(用于其他 provider)
|
* 构建通用的 providerOptions(用于其他 provider)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -485,6 +485,34 @@ export function getXAIReasoningParams(assistant: Assistant, model: Model): Recor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Bedrock reasoning parameters
|
||||||
|
*/
|
||||||
|
export function getBedrockReasoningParams(assistant: Assistant, model: Model): Record<string, any> {
|
||||||
|
if (!isReasoningModel(model)) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reasoningEffort = assistant?.settings?.reasoning_effort
|
||||||
|
|
||||||
|
if (reasoningEffort === undefined) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only apply thinking budget for Claude reasoning models
|
||||||
|
if (!isSupportedThinkingTokenClaudeModel(model)) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const budgetTokens = getAnthropicThinkingBudget(assistant, model)
|
||||||
|
return {
|
||||||
|
reasoningConfig: {
|
||||||
|
type: 'enabled',
|
||||||
|
budgetTokens: budgetTokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取自定义参数
|
* 获取自定义参数
|
||||||
* 从 assistant 设置中提取自定义参数
|
* 从 assistant 设置中提取自定义参数
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
import store, { useAppSelector } from '@renderer/store'
|
import store, { useAppSelector } from '@renderer/store'
|
||||||
import { setAwsBedrockAccessKeyId, setAwsBedrockRegion, setAwsBedrockSecretAccessKey } from '@renderer/store/llm'
|
import {
|
||||||
|
setAwsBedrockAccessKeyId,
|
||||||
|
setAwsBedrockApiKey,
|
||||||
|
setAwsBedrockAuthType,
|
||||||
|
setAwsBedrockRegion,
|
||||||
|
setAwsBedrockSecretAccessKey
|
||||||
|
} from '@renderer/store/llm'
|
||||||
|
import type { AwsBedrockAuthType } from '@renderer/types'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
export function useAwsBedrockSettings() {
|
export function useAwsBedrockSettings() {
|
||||||
@ -8,8 +15,10 @@ export function useAwsBedrockSettings() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...settings,
|
...settings,
|
||||||
|
setAuthType: (authType: AwsBedrockAuthType) => dispatch(setAwsBedrockAuthType(authType)),
|
||||||
setAccessKeyId: (accessKeyId: string) => dispatch(setAwsBedrockAccessKeyId(accessKeyId)),
|
setAccessKeyId: (accessKeyId: string) => dispatch(setAwsBedrockAccessKeyId(accessKeyId)),
|
||||||
setSecretAccessKey: (secretAccessKey: string) => dispatch(setAwsBedrockSecretAccessKey(secretAccessKey)),
|
setSecretAccessKey: (secretAccessKey: string) => dispatch(setAwsBedrockSecretAccessKey(secretAccessKey)),
|
||||||
|
setApiKey: (apiKey: string) => dispatch(setAwsBedrockApiKey(apiKey)),
|
||||||
setRegion: (region: string) => dispatch(setAwsBedrockRegion(region))
|
setRegion: (region: string) => dispatch(setAwsBedrockRegion(region))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18,6 +27,10 @@ export function getAwsBedrockSettings() {
|
|||||||
return store.getState().llm.settings.awsBedrock
|
return store.getState().llm.settings.awsBedrock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAwsBedrockAuthType() {
|
||||||
|
return store.getState().llm.settings.awsBedrock.authType
|
||||||
|
}
|
||||||
|
|
||||||
export function getAwsBedrockAccessKeyId() {
|
export function getAwsBedrockAccessKeyId() {
|
||||||
return store.getState().llm.settings.awsBedrock.accessKeyId
|
return store.getState().llm.settings.awsBedrock.accessKeyId
|
||||||
}
|
}
|
||||||
@ -26,6 +39,10 @@ export function getAwsBedrockSecretAccessKey() {
|
|||||||
return store.getState().llm.settings.awsBedrock.secretAccessKey
|
return store.getState().llm.settings.awsBedrock.secretAccessKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAwsBedrockApiKey() {
|
||||||
|
return store.getState().llm.settings.awsBedrock.apiKey
|
||||||
|
}
|
||||||
|
|
||||||
export function getAwsBedrockRegion() {
|
export function getAwsBedrockRegion() {
|
||||||
return store.getState().llm.settings.awsBedrock.region
|
return store.getState().llm.settings.awsBedrock.region
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4260,6 +4260,12 @@
|
|||||||
"aws-bedrock": {
|
"aws-bedrock": {
|
||||||
"access_key_id": "AWS Access Key ID",
|
"access_key_id": "AWS Access Key ID",
|
||||||
"access_key_id_help": "Your AWS Access Key ID for accessing AWS Bedrock services",
|
"access_key_id_help": "Your AWS Access Key ID for accessing AWS Bedrock services",
|
||||||
|
"api_key": "Bedrock API Key",
|
||||||
|
"api_key_help": "Your AWS Bedrock API Key for authentication",
|
||||||
|
"auth_type": "Authentication Type",
|
||||||
|
"auth_type_api_key": "Bedrock API Key",
|
||||||
|
"auth_type_help": "Choose between IAM credentials or Bedrock API Key authentication",
|
||||||
|
"auth_type_iam": "IAM Credentials",
|
||||||
"description": "AWS Bedrock is Amazon's fully managed foundation model service that supports various advanced large language models",
|
"description": "AWS Bedrock is Amazon's fully managed foundation model service that supports various advanced large language models",
|
||||||
"region": "AWS Region",
|
"region": "AWS Region",
|
||||||
"region_help": "Your AWS service region, e.g., us-east-1",
|
"region_help": "Your AWS service region, e.g., us-east-1",
|
||||||
|
|||||||
@ -4260,6 +4260,12 @@
|
|||||||
"aws-bedrock": {
|
"aws-bedrock": {
|
||||||
"access_key_id": "AWS 访问密钥 ID",
|
"access_key_id": "AWS 访问密钥 ID",
|
||||||
"access_key_id_help": "您的 AWS 访问密钥 ID,用于访问 AWS Bedrock 服务",
|
"access_key_id_help": "您的 AWS 访问密钥 ID,用于访问 AWS Bedrock 服务",
|
||||||
|
"api_key": "Bedrock API 密钥",
|
||||||
|
"api_key_help": "您的 AWS Bedrock API 密钥,用于身份验证",
|
||||||
|
"auth_type": "认证方式",
|
||||||
|
"auth_type_api_key": "Bedrock API 密钥",
|
||||||
|
"auth_type_help": "选择使用 IAM 凭证或 Bedrock API 密钥进行身份验证",
|
||||||
|
"auth_type_iam": "IAM 凭证",
|
||||||
"description": "AWS Bedrock 是亚马逊提供的全托管基础模型服务,支持多种先进的大语言模型",
|
"description": "AWS Bedrock 是亚马逊提供的全托管基础模型服务,支持多种先进的大语言模型",
|
||||||
"region": "AWS 区域",
|
"region": "AWS 区域",
|
||||||
"region_help": "您的 AWS 服务区域,例如 us-east-1",
|
"region_help": "您的 AWS 服务区域,例如 us-east-1",
|
||||||
|
|||||||
@ -4260,6 +4260,12 @@
|
|||||||
"aws-bedrock": {
|
"aws-bedrock": {
|
||||||
"access_key_id": "AWS 存取密鑰 ID",
|
"access_key_id": "AWS 存取密鑰 ID",
|
||||||
"access_key_id_help": "您的 AWS 存取密鑰 ID,用於存取 AWS Bedrock 服務",
|
"access_key_id_help": "您的 AWS 存取密鑰 ID,用於存取 AWS Bedrock 服務",
|
||||||
|
"api_key": "Bedrock API 金鑰",
|
||||||
|
"api_key_help": "您的 AWS Bedrock API 金鑰,用於身份驗證",
|
||||||
|
"auth_type": "認證方式",
|
||||||
|
"auth_type_api_key": "Bedrock API 金鑰",
|
||||||
|
"auth_type_help": "選擇使用 IAM 憑證或 Bedrock API 金鑰進行身份驗證",
|
||||||
|
"auth_type_iam": "IAM 憑證",
|
||||||
"description": "AWS Bedrock 是亞馬遜提供的全托管基础模型服務,支持多種先進的大語言模型",
|
"description": "AWS Bedrock 是亞馬遜提供的全托管基础模型服務,支持多種先進的大語言模型",
|
||||||
"region": "AWS 區域",
|
"region": "AWS 區域",
|
||||||
"region_help": "您的 AWS 服務區域,例如 us-east-1",
|
"region_help": "您的 AWS 服務區域,例如 us-east-1",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { HStack } from '@renderer/components/Layout'
|
import { HStack } from '@renderer/components/Layout'
|
||||||
import { PROVIDER_URLS } from '@renderer/config/providers'
|
import { PROVIDER_URLS } from '@renderer/config/providers'
|
||||||
import { useAwsBedrockSettings } from '@renderer/hooks/useAwsBedrock'
|
import { useAwsBedrockSettings } from '@renderer/hooks/useAwsBedrock'
|
||||||
import { Alert, Input } from 'antd'
|
import { Alert, Input, Radio } from 'antd'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -10,14 +10,25 @@ import { SettingHelpLink, SettingHelpText, SettingHelpTextRow, SettingSubtitle }
|
|||||||
|
|
||||||
const AwsBedrockSettings: FC = () => {
|
const AwsBedrockSettings: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { accessKeyId, secretAccessKey, region, setAccessKeyId, setSecretAccessKey, setRegion } =
|
const {
|
||||||
useAwsBedrockSettings()
|
authType,
|
||||||
|
accessKeyId,
|
||||||
|
secretAccessKey,
|
||||||
|
apiKey,
|
||||||
|
region,
|
||||||
|
setAuthType,
|
||||||
|
setAccessKeyId,
|
||||||
|
setSecretAccessKey,
|
||||||
|
setApiKey,
|
||||||
|
setRegion
|
||||||
|
} = useAwsBedrockSettings()
|
||||||
|
|
||||||
const providerConfig = PROVIDER_URLS['aws-bedrock']
|
const providerConfig = PROVIDER_URLS['aws-bedrock']
|
||||||
const apiKeyWebsite = providerConfig?.websites?.apiKey
|
const apiKeyWebsite = providerConfig?.websites?.apiKey
|
||||||
|
|
||||||
const [localAccessKeyId, setLocalAccessKeyId] = useState(accessKeyId)
|
const [localAccessKeyId, setLocalAccessKeyId] = useState(accessKeyId)
|
||||||
const [localSecretAccessKey, setLocalSecretAccessKey] = useState(secretAccessKey)
|
const [localSecretAccessKey, setLocalSecretAccessKey] = useState(secretAccessKey)
|
||||||
|
const [localApiKey, setLocalApiKey] = useState(apiKey)
|
||||||
const [localRegion, setLocalRegion] = useState(region)
|
const [localRegion, setLocalRegion] = useState(region)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -25,39 +36,75 @@ const AwsBedrockSettings: FC = () => {
|
|||||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.title')}</SettingSubtitle>
|
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.title')}</SettingSubtitle>
|
||||||
<Alert type="info" style={{ marginTop: 5 }} message={t('settings.provider.aws-bedrock.description')} showIcon />
|
<Alert type="info" style={{ marginTop: 5 }} message={t('settings.provider.aws-bedrock.description')} showIcon />
|
||||||
|
|
||||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.access_key_id')}</SettingSubtitle>
|
{/* Authentication Type Selector */}
|
||||||
<Input
|
<SettingSubtitle style={{ marginTop: 15 }}>{t('settings.provider.aws-bedrock.auth_type')}</SettingSubtitle>
|
||||||
value={localAccessKeyId}
|
<Radio.Group value={authType} onChange={(e) => setAuthType(e.target.value)} style={{ marginTop: 5 }}>
|
||||||
placeholder="Access Key ID"
|
<Radio value="iam">{t('settings.provider.aws-bedrock.auth_type_iam')}</Radio>
|
||||||
onChange={(e) => setLocalAccessKeyId(e.target.value)}
|
<Radio value="apiKey">{t('settings.provider.aws-bedrock.auth_type_api_key')}</Radio>
|
||||||
onBlur={() => setAccessKeyId(localAccessKeyId)}
|
</Radio.Group>
|
||||||
style={{ marginTop: 5 }}
|
|
||||||
/>
|
|
||||||
<SettingHelpTextRow>
|
<SettingHelpTextRow>
|
||||||
<SettingHelpText>{t('settings.provider.aws-bedrock.access_key_id_help')}</SettingHelpText>
|
<SettingHelpText>{t('settings.provider.aws-bedrock.auth_type_help')}</SettingHelpText>
|
||||||
</SettingHelpTextRow>
|
</SettingHelpTextRow>
|
||||||
|
|
||||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.secret_access_key')}</SettingSubtitle>
|
{/* IAM Credentials Fields */}
|
||||||
<Input.Password
|
{authType === 'iam' && (
|
||||||
value={localSecretAccessKey}
|
<>
|
||||||
placeholder="Secret Access Key"
|
<SettingSubtitle style={{ marginTop: 15 }}>
|
||||||
onChange={(e) => setLocalSecretAccessKey(e.target.value)}
|
{t('settings.provider.aws-bedrock.access_key_id')}
|
||||||
onBlur={() => setSecretAccessKey(localSecretAccessKey)}
|
</SettingSubtitle>
|
||||||
style={{ marginTop: 5 }}
|
<Input
|
||||||
spellCheck={false}
|
value={localAccessKeyId}
|
||||||
/>
|
placeholder="Access Key ID"
|
||||||
{apiKeyWebsite && (
|
onChange={(e) => setLocalAccessKeyId(e.target.value)}
|
||||||
<SettingHelpTextRow style={{ justifyContent: 'space-between' }}>
|
onBlur={() => setAccessKeyId(localAccessKeyId)}
|
||||||
<HStack>
|
style={{ marginTop: 5 }}
|
||||||
<SettingHelpLink target="_blank" href={apiKeyWebsite}>
|
/>
|
||||||
{t('settings.provider.get_api_key')}
|
<SettingHelpTextRow>
|
||||||
</SettingHelpLink>
|
<SettingHelpText>{t('settings.provider.aws-bedrock.access_key_id_help')}</SettingHelpText>
|
||||||
</HStack>
|
</SettingHelpTextRow>
|
||||||
<SettingHelpText>{t('settings.provider.aws-bedrock.secret_access_key_help')}</SettingHelpText>
|
|
||||||
</SettingHelpTextRow>
|
<SettingSubtitle style={{ marginTop: 15 }}>
|
||||||
|
{t('settings.provider.aws-bedrock.secret_access_key')}
|
||||||
|
</SettingSubtitle>
|
||||||
|
<Input.Password
|
||||||
|
value={localSecretAccessKey}
|
||||||
|
placeholder="Secret Access Key"
|
||||||
|
onChange={(e) => setLocalSecretAccessKey(e.target.value)}
|
||||||
|
onBlur={() => setSecretAccessKey(localSecretAccessKey)}
|
||||||
|
style={{ marginTop: 5 }}
|
||||||
|
spellCheck={false}
|
||||||
|
/>
|
||||||
|
{apiKeyWebsite && (
|
||||||
|
<SettingHelpTextRow style={{ justifyContent: 'space-between' }}>
|
||||||
|
<HStack>
|
||||||
|
<SettingHelpLink target="_blank" href={apiKeyWebsite}>
|
||||||
|
{t('settings.provider.get_api_key')}
|
||||||
|
</SettingHelpLink>
|
||||||
|
</HStack>
|
||||||
|
<SettingHelpText>{t('settings.provider.aws-bedrock.secret_access_key_help')}</SettingHelpText>
|
||||||
|
</SettingHelpTextRow>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.region')}</SettingSubtitle>
|
{authType === 'apiKey' && (
|
||||||
|
<>
|
||||||
|
<SettingSubtitle style={{ marginTop: 15 }}>{t('settings.provider.aws-bedrock.api_key')}</SettingSubtitle>
|
||||||
|
<Input.Password
|
||||||
|
value={localApiKey}
|
||||||
|
placeholder="Bedrock API Key"
|
||||||
|
onChange={(e) => setLocalApiKey(e.target.value)}
|
||||||
|
onBlur={() => setApiKey(localApiKey)}
|
||||||
|
style={{ marginTop: 5 }}
|
||||||
|
spellCheck={false}
|
||||||
|
/>
|
||||||
|
<SettingHelpTextRow>
|
||||||
|
<SettingHelpText>{t('settings.provider.aws-bedrock.api_key_help')}</SettingHelpText>
|
||||||
|
</SettingHelpTextRow>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<SettingSubtitle style={{ marginTop: 15 }}>{t('settings.provider.aws-bedrock.region')}</SettingSubtitle>
|
||||||
<Input
|
<Input
|
||||||
value={localRegion}
|
value={localRegion}
|
||||||
placeholder="us-east-1"
|
placeholder="us-east-1"
|
||||||
|
|||||||
@ -230,8 +230,10 @@ vi.mock('@renderer/store/llm.ts', () => {
|
|||||||
location: ''
|
location: ''
|
||||||
},
|
},
|
||||||
awsBedrock: {
|
awsBedrock: {
|
||||||
|
authType: 'iam',
|
||||||
accessKeyId: '',
|
accessKeyId: '',
|
||||||
secretAccessKey: '',
|
secretAccessKey: '',
|
||||||
|
apiKey: '',
|
||||||
region: ''
|
region: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,7 +67,7 @@ const persistedReducer = persistReducer(
|
|||||||
{
|
{
|
||||||
key: 'cherry-studio',
|
key: 'cherry-studio',
|
||||||
storage,
|
storage,
|
||||||
version: 170,
|
version: 171,
|
||||||
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs', 'toolPermissions'],
|
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs', 'toolPermissions'],
|
||||||
migrate
|
migrate
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { createSlice } from '@reduxjs/toolkit'
|
|||||||
import { isLocalAi } from '@renderer/config/env'
|
import { isLocalAi } from '@renderer/config/env'
|
||||||
import { SYSTEM_MODELS } from '@renderer/config/models'
|
import { SYSTEM_MODELS } from '@renderer/config/models'
|
||||||
import { SYSTEM_PROVIDERS } from '@renderer/config/providers'
|
import { SYSTEM_PROVIDERS } from '@renderer/config/providers'
|
||||||
import type { Model, Provider } from '@renderer/types'
|
import type { AwsBedrockAuthType, Model, Provider } from '@renderer/types'
|
||||||
import { uniqBy } from 'lodash'
|
import { uniqBy } from 'lodash'
|
||||||
|
|
||||||
type LlmSettings = {
|
type LlmSettings = {
|
||||||
@ -25,8 +25,10 @@ type LlmSettings = {
|
|||||||
location: string
|
location: string
|
||||||
}
|
}
|
||||||
awsBedrock: {
|
awsBedrock: {
|
||||||
|
authType: AwsBedrockAuthType
|
||||||
accessKeyId: string
|
accessKeyId: string
|
||||||
secretAccessKey: string
|
secretAccessKey: string
|
||||||
|
apiKey: string
|
||||||
region: string
|
region: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,8 +70,10 @@ export const initialState: LlmState = {
|
|||||||
location: ''
|
location: ''
|
||||||
},
|
},
|
||||||
awsBedrock: {
|
awsBedrock: {
|
||||||
|
authType: 'iam',
|
||||||
accessKeyId: '',
|
accessKeyId: '',
|
||||||
secretAccessKey: '',
|
secretAccessKey: '',
|
||||||
|
apiKey: '',
|
||||||
region: ''
|
region: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,12 +201,18 @@ const llmSlice = createSlice({
|
|||||||
setVertexAIServiceAccountClientEmail: (state, action: PayloadAction<string>) => {
|
setVertexAIServiceAccountClientEmail: (state, action: PayloadAction<string>) => {
|
||||||
state.settings.vertexai.serviceAccount.clientEmail = action.payload
|
state.settings.vertexai.serviceAccount.clientEmail = action.payload
|
||||||
},
|
},
|
||||||
|
setAwsBedrockAuthType: (state, action: PayloadAction<AwsBedrockAuthType>) => {
|
||||||
|
state.settings.awsBedrock.authType = action.payload
|
||||||
|
},
|
||||||
setAwsBedrockAccessKeyId: (state, action: PayloadAction<string>) => {
|
setAwsBedrockAccessKeyId: (state, action: PayloadAction<string>) => {
|
||||||
state.settings.awsBedrock.accessKeyId = action.payload
|
state.settings.awsBedrock.accessKeyId = action.payload
|
||||||
},
|
},
|
||||||
setAwsBedrockSecretAccessKey: (state, action: PayloadAction<string>) => {
|
setAwsBedrockSecretAccessKey: (state, action: PayloadAction<string>) => {
|
||||||
state.settings.awsBedrock.secretAccessKey = action.payload
|
state.settings.awsBedrock.secretAccessKey = action.payload
|
||||||
},
|
},
|
||||||
|
setAwsBedrockApiKey: (state, action: PayloadAction<string>) => {
|
||||||
|
state.settings.awsBedrock.apiKey = action.payload
|
||||||
|
},
|
||||||
setAwsBedrockRegion: (state, action: PayloadAction<string>) => {
|
setAwsBedrockRegion: (state, action: PayloadAction<string>) => {
|
||||||
state.settings.awsBedrock.region = action.payload
|
state.settings.awsBedrock.region = action.payload
|
||||||
},
|
},
|
||||||
@ -242,8 +252,10 @@ export const {
|
|||||||
setVertexAILocation,
|
setVertexAILocation,
|
||||||
setVertexAIServiceAccountPrivateKey,
|
setVertexAIServiceAccountPrivateKey,
|
||||||
setVertexAIServiceAccountClientEmail,
|
setVertexAIServiceAccountClientEmail,
|
||||||
|
setAwsBedrockAuthType,
|
||||||
setAwsBedrockAccessKeyId,
|
setAwsBedrockAccessKeyId,
|
||||||
setAwsBedrockSecretAccessKey,
|
setAwsBedrockSecretAccessKey,
|
||||||
|
setAwsBedrockApiKey,
|
||||||
setAwsBedrockRegion,
|
setAwsBedrockRegion,
|
||||||
updateModel
|
updateModel
|
||||||
} = llmSlice.actions
|
} = llmSlice.actions
|
||||||
|
|||||||
@ -2794,6 +2794,17 @@ const migrateConfig = {
|
|||||||
logger.error('migrate 170 error', error as Error)
|
logger.error('migrate 170 error', error as Error)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'171': (state: RootState) => {
|
||||||
|
try {
|
||||||
|
addProvider(state, 'sophnet')
|
||||||
|
state.llm.providers = moveProvider(state.llm.providers, 'sophnet', 17)
|
||||||
|
state.settings.defaultPaintingProvider = 'cherryin'
|
||||||
|
return state
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('migrate 171 error', error as Error)
|
||||||
|
return state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,6 +73,17 @@ export function isServiceTier(tier: string): tier is ServiceTier {
|
|||||||
return isGroqServiceTier(tier) || isOpenAIServiceTier(tier)
|
return isGroqServiceTier(tier) || isOpenAIServiceTier(tier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const AwsBedrockAuthTypes = {
|
||||||
|
iam: 'iam',
|
||||||
|
apiKey: 'apiKey'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type AwsBedrockAuthType = keyof typeof AwsBedrockAuthTypes
|
||||||
|
|
||||||
|
export function isAwsBedrockAuthType(type: string): type is AwsBedrockAuthType {
|
||||||
|
return Object.hasOwn(AwsBedrockAuthTypes, type)
|
||||||
|
}
|
||||||
|
|
||||||
export type Provider = {
|
export type Provider = {
|
||||||
id: string
|
id: string
|
||||||
type: ProviderType
|
type: ProviderType
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user