refactor: merge bedrock-apikey into bedrock with auth_mode credential
Consolidate two separate channel types (bedrock + bedrock-apikey) into
a single "AWS Bedrock" channel. Authentication mode is now distinguished
by credentials.auth_mode ("sigv4" | "apikey") instead of separate types.
Backend:
- Remove AccountTypeBedrockAPIKey constant
- IsBedrock() simplified; IsBedrockAPIKey() checks auth_mode
- Add IsAPIKeyOrBedrock() helper to eliminate repeated type checks
- Extend pool mode, quota scheduling, and billing to bedrock
- Add RetryableOnSameAccount to handleBedrockUpstreamErrors
- Add "bedrock" scope to Beta Policy for independent control
Frontend:
- Merge two buttons into one "AWS Bedrock" with auth mode radio
- Badge displays "Anthropic | AWS"
- Pool mode and quota limit UI available for bedrock
- Quota display in account list (usage bars, capacity badges, reset)
- Remove all bedrock-apikey type references
This commit is contained in:
@@ -323,35 +323,6 @@
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
@click="accountCategory = 'bedrock-apikey'"
|
||||
:class="[
|
||||
'flex items-center gap-3 rounded-lg border-2 p-3 text-left transition-all',
|
||||
accountCategory === 'bedrock-apikey'
|
||||
? 'border-amber-500 bg-amber-50 dark:bg-amber-900/20'
|
||||
: 'border-gray-200 hover:border-amber-300 dark:border-dark-600 dark:hover:border-amber-700'
|
||||
]"
|
||||
>
|
||||
<div
|
||||
:class="[
|
||||
'flex h-8 w-8 shrink-0 items-center justify-center rounded-lg',
|
||||
accountCategory === 'bedrock-apikey'
|
||||
? 'bg-amber-500 text-white'
|
||||
: 'bg-gray-100 text-gray-500 dark:bg-dark-600 dark:text-gray-400'
|
||||
]"
|
||||
>
|
||||
<Icon name="key" size="sm" />
|
||||
</div>
|
||||
<div>
|
||||
<span class="block text-sm font-medium text-gray-900 dark:text-white">{{
|
||||
t('admin.accounts.bedrockApiKeyLabel')
|
||||
}}</span>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">{{
|
||||
t('admin.accounts.bedrockApiKeyDesc')
|
||||
}}</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -956,7 +927,7 @@
|
||||
</div>
|
||||
|
||||
<!-- API Key input (only for apikey type, excluding Antigravity which has its own fields) -->
|
||||
<div v-if="form.type === 'apikey' && form.platform !== 'antigravity' && accountCategory !== 'bedrock-apikey'" class="space-y-4">
|
||||
<div v-if="form.type === 'apikey' && form.platform !== 'antigravity'" class="space-y-4">
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.baseUrl') }}</label>
|
||||
<input
|
||||
@@ -1341,34 +1312,75 @@
|
||||
|
||||
<!-- Bedrock credentials (only for Anthropic Bedrock type) -->
|
||||
<div v-if="form.platform === 'anthropic' && accountCategory === 'bedrock'" class="space-y-4">
|
||||
<!-- Auth Mode Radio -->
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockAccessKeyId') }}</label>
|
||||
<input
|
||||
v-model="bedrockAccessKeyId"
|
||||
type="text"
|
||||
required
|
||||
class="input font-mono"
|
||||
placeholder="AKIA..."
|
||||
/>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockAuthMode') }}</label>
|
||||
<div class="mt-2 flex gap-4">
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="bedrockAuthMode"
|
||||
type="radio"
|
||||
value="sigv4"
|
||||
class="mr-2 text-primary-600 focus:ring-primary-500"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{{ t('admin.accounts.bedrockAuthModeSigv4') }}</span>
|
||||
</label>
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="bedrockAuthMode"
|
||||
type="radio"
|
||||
value="apikey"
|
||||
class="mr-2 text-primary-600 focus:ring-primary-500"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{{ t('admin.accounts.bedrockAuthModeApikey') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockSecretAccessKey') }}</label>
|
||||
|
||||
<!-- SigV4 fields -->
|
||||
<template v-if="bedrockAuthMode === 'sigv4'">
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockAccessKeyId') }}</label>
|
||||
<input
|
||||
v-model="bedrockAccessKeyId"
|
||||
type="text"
|
||||
required
|
||||
class="input font-mono"
|
||||
placeholder="AKIA..."
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockSecretAccessKey') }}</label>
|
||||
<input
|
||||
v-model="bedrockSecretAccessKey"
|
||||
type="password"
|
||||
required
|
||||
class="input font-mono"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockSessionToken') }}</label>
|
||||
<input
|
||||
v-model="bedrockSessionToken"
|
||||
type="password"
|
||||
class="input font-mono"
|
||||
/>
|
||||
<p class="input-hint">{{ t('admin.accounts.bedrockSessionTokenHint') }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- API Key field -->
|
||||
<div v-if="bedrockAuthMode === 'apikey'">
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockApiKeyInput') }}</label>
|
||||
<input
|
||||
v-model="bedrockSecretAccessKey"
|
||||
v-model="bedrockApiKeyValue"
|
||||
type="password"
|
||||
required
|
||||
class="input font-mono"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockSessionToken') }}</label>
|
||||
<input
|
||||
v-model="bedrockSessionToken"
|
||||
type="password"
|
||||
class="input font-mono"
|
||||
/>
|
||||
<p class="input-hint">{{ t('admin.accounts.bedrockSessionTokenHint') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Shared: Region -->
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockRegion') }}</label>
|
||||
<select v-model="bedrockRegion" class="input">
|
||||
@@ -1408,6 +1420,8 @@
|
||||
</select>
|
||||
<p class="input-hint">{{ t('admin.accounts.bedrockRegionHint') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Shared: Force Global -->
|
||||
<div>
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
@@ -1488,142 +1502,62 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bedrock API Key credentials (only for Anthropic Bedrock API Key type) -->
|
||||
<div v-if="form.platform === 'anthropic' && accountCategory === 'bedrock-apikey'" class="space-y-4">
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockApiKeyInput') }}</label>
|
||||
<input
|
||||
v-model="bedrockApiKeyValue"
|
||||
type="password"
|
||||
required
|
||||
class="input font-mono"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.bedrockRegion') }}</label>
|
||||
<select v-model="bedrockApiKeyRegion" class="input">
|
||||
<optgroup label="US">
|
||||
<option value="us-east-1">us-east-1 (N. Virginia)</option>
|
||||
<option value="us-east-2">us-east-2 (Ohio)</option>
|
||||
<option value="us-west-1">us-west-1 (N. California)</option>
|
||||
<option value="us-west-2">us-west-2 (Oregon)</option>
|
||||
<option value="us-gov-east-1">us-gov-east-1 (GovCloud US-East)</option>
|
||||
<option value="us-gov-west-1">us-gov-west-1 (GovCloud US-West)</option>
|
||||
</optgroup>
|
||||
<optgroup label="Europe">
|
||||
<option value="eu-west-1">eu-west-1 (Ireland)</option>
|
||||
<option value="eu-west-2">eu-west-2 (London)</option>
|
||||
<option value="eu-west-3">eu-west-3 (Paris)</option>
|
||||
<option value="eu-central-1">eu-central-1 (Frankfurt)</option>
|
||||
<option value="eu-central-2">eu-central-2 (Zurich)</option>
|
||||
<option value="eu-south-1">eu-south-1 (Milan)</option>
|
||||
<option value="eu-south-2">eu-south-2 (Spain)</option>
|
||||
<option value="eu-north-1">eu-north-1 (Stockholm)</option>
|
||||
</optgroup>
|
||||
<optgroup label="Asia Pacific">
|
||||
<option value="ap-northeast-1">ap-northeast-1 (Tokyo)</option>
|
||||
<option value="ap-northeast-2">ap-northeast-2 (Seoul)</option>
|
||||
<option value="ap-northeast-3">ap-northeast-3 (Osaka)</option>
|
||||
<option value="ap-south-1">ap-south-1 (Mumbai)</option>
|
||||
<option value="ap-south-2">ap-south-2 (Hyderabad)</option>
|
||||
<option value="ap-southeast-1">ap-southeast-1 (Singapore)</option>
|
||||
<option value="ap-southeast-2">ap-southeast-2 (Sydney)</option>
|
||||
</optgroup>
|
||||
<optgroup label="Canada">
|
||||
<option value="ca-central-1">ca-central-1 (Canada)</option>
|
||||
</optgroup>
|
||||
<optgroup label="South America">
|
||||
<option value="sa-east-1">sa-east-1 (São Paulo)</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<p class="input-hint">{{ t('admin.accounts.bedrockRegionHint') }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
v-model="bedrockApiKeyForceGlobal"
|
||||
type="checkbox"
|
||||
class="rounded border-gray-300 text-primary-600 focus:ring-primary-500 dark:border-dark-500"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{{ t('admin.accounts.bedrockForceGlobal') }}</span>
|
||||
</label>
|
||||
<p class="input-hint mt-1">{{ t('admin.accounts.bedrockForceGlobalHint') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Model Restriction Section for Bedrock API Key -->
|
||||
<!-- Pool Mode Section for Bedrock -->
|
||||
<div class="border-t border-gray-200 pt-4 dark:border-dark-600">
|
||||
<label class="input-label">{{ t('admin.accounts.modelRestriction') }}</label>
|
||||
|
||||
<!-- Mode Toggle -->
|
||||
<div class="mb-4 flex gap-2">
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
<div>
|
||||
<label class="input-label mb-0">{{ t('admin.accounts.poolMode') }}</label>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t('admin.accounts.poolModeHint') }}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="modelRestrictionMode = 'whitelist'"
|
||||
@click="poolModeEnabled = !poolModeEnabled"
|
||||
:class="[
|
||||
'flex-1 rounded-lg px-4 py-2 text-sm font-medium transition-all',
|
||||
modelRestrictionMode === 'whitelist'
|
||||
? 'bg-primary-100 text-primary-700 dark:bg-primary-900/30 dark:text-primary-400'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-dark-600 dark:text-gray-400 dark:hover:bg-dark-500'
|
||||
'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2',
|
||||
poolModeEnabled ? 'bg-primary-600' : 'bg-gray-200 dark:bg-dark-600'
|
||||
]"
|
||||
>
|
||||
{{ t('admin.accounts.modelWhitelist') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@click="modelRestrictionMode = 'mapping'"
|
||||
:class="[
|
||||
'flex-1 rounded-lg px-4 py-2 text-sm font-medium transition-all',
|
||||
modelRestrictionMode === 'mapping'
|
||||
? 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-dark-600 dark:text-gray-400 dark:hover:bg-dark-500'
|
||||
]"
|
||||
>
|
||||
{{ t('admin.accounts.modelMapping') }}
|
||||
<span
|
||||
:class="[
|
||||
'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
|
||||
poolModeEnabled ? 'translate-x-5' : 'translate-x-0'
|
||||
]"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Whitelist Mode -->
|
||||
<div v-if="modelRestrictionMode === 'whitelist'">
|
||||
<ModelWhitelistSelector v-model="allowedModels" platform="anthropic" />
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t('admin.accounts.selectedModels', { count: allowedModels.length }) }}
|
||||
<span v-if="allowedModels.length === 0">{{ t('admin.accounts.supportsAllModels') }}</span>
|
||||
<div v-if="poolModeEnabled" class="rounded-lg bg-blue-50 p-3 dark:bg-blue-900/20">
|
||||
<p class="text-xs text-blue-700 dark:text-blue-400">
|
||||
<Icon name="exclamationCircle" size="sm" class="mr-1 inline" :stroke-width="2" />
|
||||
{{ t('admin.accounts.poolModeInfo') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Mapping Mode -->
|
||||
<div v-else class="space-y-3">
|
||||
<div v-for="(mapping, index) in modelMappings" :key="index" class="flex items-center gap-2">
|
||||
<input v-model="mapping.from" type="text" class="input flex-1" :placeholder="t('admin.accounts.fromModel')" />
|
||||
<span class="text-gray-400">→</span>
|
||||
<input v-model="mapping.to" type="text" class="input flex-1" :placeholder="t('admin.accounts.toModel')" />
|
||||
<button type="button" @click="modelMappings.splice(index, 1)" class="text-red-500 hover:text-red-700">
|
||||
<Icon name="trash" size="sm" />
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" @click="modelMappings.push({ from: '', to: '' })" class="btn btn-secondary text-sm">
|
||||
+ {{ t('admin.accounts.addMapping') }}
|
||||
</button>
|
||||
<!-- Bedrock Preset Mappings -->
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button
|
||||
v-for="preset in bedrockPresets"
|
||||
:key="preset.from"
|
||||
type="button"
|
||||
@click="addPresetMapping(preset.from, preset.to)"
|
||||
:class="['rounded-lg px-3 py-1 text-xs transition-colors', preset.color]"
|
||||
>
|
||||
+ {{ preset.label }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="poolModeEnabled" class="mt-3">
|
||||
<label class="input-label">{{ t('admin.accounts.poolModeRetryCount') }}</label>
|
||||
<input
|
||||
v-model.number="poolModeRetryCount"
|
||||
type="number"
|
||||
min="0"
|
||||
:max="MAX_POOL_MODE_RETRY_COUNT"
|
||||
step="1"
|
||||
class="input"
|
||||
/>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{
|
||||
t('admin.accounts.poolModeRetryCountHint', {
|
||||
default: DEFAULT_POOL_MODE_RETRY_COUNT,
|
||||
max: MAX_POOL_MODE_RETRY_COUNT
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- API Key 账号配额限制 -->
|
||||
<div v-if="form.type === 'apikey'" class="border-t border-gray-200 pt-4 dark:border-dark-600 space-y-4">
|
||||
<!-- API Key / Bedrock 账号配额限制 -->
|
||||
<div v-if="form.type === 'apikey' || form.type === 'bedrock'" class="border-t border-gray-200 pt-4 dark:border-dark-600 space-y-4">
|
||||
<div class="mb-3">
|
||||
<h3 class="input-label mb-0 text-base font-semibold">{{ t('admin.accounts.quotaLimit') }}</h3>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
@@ -3014,7 +2948,7 @@ interface TempUnschedRuleForm {
|
||||
// State
|
||||
const step = ref(1)
|
||||
const submitting = ref(false)
|
||||
const accountCategory = ref<'oauth-based' | 'apikey' | 'bedrock' | 'bedrock-apikey'>('oauth-based') // UI selection for account category
|
||||
const accountCategory = ref<'oauth-based' | 'apikey' | 'bedrock'>('oauth-based') // UI selection for account category
|
||||
const addMethod = ref<AddMethod>('oauth') // For oauth-based: 'oauth' or 'setup-token'
|
||||
const apiKeyBaseUrl = ref('https://api.anthropic.com')
|
||||
const apiKeyValue = ref('')
|
||||
@@ -3050,16 +2984,13 @@ const antigravityPresetMappings = computed(() => getPresetMappingsByPlatform('an
|
||||
const bedrockPresets = computed(() => getPresetMappingsByPlatform('bedrock'))
|
||||
|
||||
// Bedrock credentials
|
||||
const bedrockAuthMode = ref<'sigv4' | 'apikey'>('sigv4')
|
||||
const bedrockAccessKeyId = ref('')
|
||||
const bedrockSecretAccessKey = ref('')
|
||||
const bedrockSessionToken = ref('')
|
||||
const bedrockRegion = ref('us-east-1')
|
||||
const bedrockForceGlobal = ref(false)
|
||||
|
||||
// Bedrock API Key credentials
|
||||
const bedrockApiKeyValue = ref('')
|
||||
const bedrockApiKeyRegion = ref('us-east-1')
|
||||
const bedrockApiKeyForceGlobal = ref(false)
|
||||
const tempUnschedEnabled = ref(false)
|
||||
const tempUnschedRules = ref<TempUnschedRuleForm[]>([])
|
||||
const getModelMappingKey = createStableObjectKeyResolver<ModelMapping>('create-model-mapping')
|
||||
@@ -3343,7 +3274,8 @@ watch(
|
||||
bedrockSessionToken.value = ''
|
||||
bedrockRegion.value = 'us-east-1'
|
||||
bedrockForceGlobal.value = false
|
||||
bedrockApiKeyForceGlobal.value = false
|
||||
bedrockAuthMode.value = 'sigv4'
|
||||
bedrockApiKeyValue.value = ''
|
||||
// Reset Anthropic/Antigravity-specific settings when switching to other platforms
|
||||
if (newPlatform !== 'anthropic' && newPlatform !== 'antigravity') {
|
||||
interceptWarmupRequests.value = false
|
||||
@@ -3919,27 +3851,34 @@ const handleSubmit = async () => {
|
||||
appStore.showError(t('admin.accounts.pleaseEnterAccountName'))
|
||||
return
|
||||
}
|
||||
if (!bedrockAccessKeyId.value.trim()) {
|
||||
appStore.showError(t('admin.accounts.bedrockAccessKeyIdRequired'))
|
||||
return
|
||||
}
|
||||
if (!bedrockSecretAccessKey.value.trim()) {
|
||||
appStore.showError(t('admin.accounts.bedrockSecretAccessKeyRequired'))
|
||||
return
|
||||
}
|
||||
if (!bedrockRegion.value.trim()) {
|
||||
appStore.showError(t('admin.accounts.bedrockRegionRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
const credentials: Record<string, unknown> = {
|
||||
aws_access_key_id: bedrockAccessKeyId.value.trim(),
|
||||
aws_secret_access_key: bedrockSecretAccessKey.value.trim(),
|
||||
aws_region: bedrockRegion.value.trim(),
|
||||
auth_mode: bedrockAuthMode.value,
|
||||
aws_region: bedrockRegion.value.trim() || 'us-east-1',
|
||||
}
|
||||
if (bedrockSessionToken.value.trim()) {
|
||||
credentials.aws_session_token = bedrockSessionToken.value.trim()
|
||||
|
||||
if (bedrockAuthMode.value === 'sigv4') {
|
||||
if (!bedrockAccessKeyId.value.trim()) {
|
||||
appStore.showError(t('admin.accounts.bedrockAccessKeyIdRequired'))
|
||||
return
|
||||
}
|
||||
if (!bedrockSecretAccessKey.value.trim()) {
|
||||
appStore.showError(t('admin.accounts.bedrockSecretAccessKeyRequired'))
|
||||
return
|
||||
}
|
||||
credentials.aws_access_key_id = bedrockAccessKeyId.value.trim()
|
||||
credentials.aws_secret_access_key = bedrockSecretAccessKey.value.trim()
|
||||
if (bedrockSessionToken.value.trim()) {
|
||||
credentials.aws_session_token = bedrockSessionToken.value.trim()
|
||||
}
|
||||
} else {
|
||||
if (!bedrockApiKeyValue.value.trim()) {
|
||||
appStore.showError(t('admin.accounts.bedrockApiKeyRequired'))
|
||||
return
|
||||
}
|
||||
credentials.api_key = bedrockApiKeyValue.value.trim()
|
||||
}
|
||||
|
||||
if (bedrockForceGlobal.value) {
|
||||
credentials.aws_force_global = 'true'
|
||||
}
|
||||
@@ -3952,45 +3891,18 @@ const handleSubmit = async () => {
|
||||
credentials.model_mapping = modelMapping
|
||||
}
|
||||
|
||||
// Pool mode
|
||||
if (poolModeEnabled.value) {
|
||||
credentials.pool_mode = true
|
||||
credentials.pool_mode_retry_count = normalizePoolModeRetryCount(poolModeRetryCount.value)
|
||||
}
|
||||
|
||||
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
|
||||
|
||||
await createAccountAndFinish('anthropic', 'bedrock' as AccountType, credentials)
|
||||
return
|
||||
}
|
||||
|
||||
// For Bedrock API Key type, create directly
|
||||
if (form.platform === 'anthropic' && accountCategory.value === 'bedrock-apikey') {
|
||||
if (!form.name.trim()) {
|
||||
appStore.showError(t('admin.accounts.pleaseEnterAccountName'))
|
||||
return
|
||||
}
|
||||
if (!bedrockApiKeyValue.value.trim()) {
|
||||
appStore.showError(t('admin.accounts.bedrockApiKeyRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
const credentials: Record<string, unknown> = {
|
||||
api_key: bedrockApiKeyValue.value.trim(),
|
||||
aws_region: bedrockApiKeyRegion.value.trim() || 'us-east-1',
|
||||
}
|
||||
if (bedrockApiKeyForceGlobal.value) {
|
||||
credentials.aws_force_global = 'true'
|
||||
}
|
||||
|
||||
// Model mapping
|
||||
const modelMapping = buildModelMappingObject(
|
||||
modelRestrictionMode.value, allowedModels.value, modelMappings.value
|
||||
)
|
||||
if (modelMapping) {
|
||||
credentials.model_mapping = modelMapping
|
||||
}
|
||||
|
||||
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
|
||||
|
||||
await createAccountAndFinish('anthropic', 'bedrock-apikey' as AccountType, credentials)
|
||||
return
|
||||
}
|
||||
|
||||
// For Antigravity upstream type, create directly
|
||||
if (form.platform === 'antigravity' && antigravityAccountType.value === 'upstream') {
|
||||
if (!form.name.trim()) {
|
||||
@@ -4233,9 +4145,9 @@ const createAccountAndFinish = async (
|
||||
if (!applyTempUnschedConfig(credentials)) {
|
||||
return
|
||||
}
|
||||
// Inject quota limits for apikey accounts
|
||||
// Inject quota limits for apikey/bedrock accounts
|
||||
let finalExtra = extra
|
||||
if (type === 'apikey') {
|
||||
if (type === 'apikey' || type === 'bedrock') {
|
||||
const quotaExtra: Record<string, unknown> = { ...(extra || {}) }
|
||||
if (editQuotaLimit.value != null && editQuotaLimit.value > 0) {
|
||||
quotaExtra.quota_limit = editQuotaLimit.value
|
||||
|
||||
Reference in New Issue
Block a user