fix: fix intercept_warmup_requests config not being saved
Extract applyInterceptWarmup utility to unify all credential building call sites: - Fix upstream account creation missing intercept_warmup_requests write - Fix apikey edit mode missing else-branch to clear the setting - Add backend unit test for IsInterceptWarmupEnabled - Add frontend unit test for credentialsBuilder
This commit is contained in:
66
backend/internal/service/account_intercept_warmup_test.go
Normal file
66
backend/internal/service/account_intercept_warmup_test.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//go:build unit
|
||||||
|
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccount_IsInterceptWarmupEnabled(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
credentials map[string]any
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil credentials",
|
||||||
|
credentials: nil,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty map",
|
||||||
|
credentials: map[string]any{},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "field not present",
|
||||||
|
credentials: map[string]any{"access_token": "tok"},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "field is true",
|
||||||
|
credentials: map[string]any{"intercept_warmup_requests": true},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "field is false",
|
||||||
|
credentials: map[string]any{"intercept_warmup_requests": false},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "field is string true",
|
||||||
|
credentials: map[string]any{"intercept_warmup_requests": "true"},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "field is int 1",
|
||||||
|
credentials: map[string]any{"intercept_warmup_requests": 1},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "field is nil",
|
||||||
|
credentials: map[string]any{"intercept_warmup_requests": nil},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
a := &Account{Credentials: tt.credentials}
|
||||||
|
result := a.IsInterceptWarmupEnabled()
|
||||||
|
require.Equal(t, tt.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2196,6 +2196,7 @@ import Icon from '@/components/icons/Icon.vue'
|
|||||||
import ProxySelector from '@/components/common/ProxySelector.vue'
|
import ProxySelector from '@/components/common/ProxySelector.vue'
|
||||||
import GroupSelector from '@/components/common/GroupSelector.vue'
|
import GroupSelector from '@/components/common/GroupSelector.vue'
|
||||||
import ModelWhitelistSelector from '@/components/account/ModelWhitelistSelector.vue'
|
import ModelWhitelistSelector from '@/components/account/ModelWhitelistSelector.vue'
|
||||||
|
import { applyInterceptWarmup } from '@/components/account/credentialsBuilder'
|
||||||
import { formatDateTimeLocalInput, parseDateTimeLocalInput } from '@/utils/format'
|
import { formatDateTimeLocalInput, parseDateTimeLocalInput } from '@/utils/format'
|
||||||
import { createStableObjectKeyResolver } from '@/utils/stableObjectKey'
|
import { createStableObjectKeyResolver } from '@/utils/stableObjectKey'
|
||||||
import OAuthAuthorizationFlow from './OAuthAuthorizationFlow.vue'
|
import OAuthAuthorizationFlow from './OAuthAuthorizationFlow.vue'
|
||||||
@@ -3010,6 +3011,8 @@ const handleSubmit = async () => {
|
|||||||
credentials.model_mapping = antigravityModelMapping
|
credentials.model_mapping = antigravityModelMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
|
||||||
|
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
try {
|
try {
|
||||||
const extra = mixedScheduling.value ? { mixed_scheduling: true } : undefined
|
const extra = mixedScheduling.value ? { mixed_scheduling: true } : undefined
|
||||||
@@ -3059,10 +3062,7 @@ const handleSubmit = async () => {
|
|||||||
credentials.custom_error_codes = [...selectedErrorCodes.value]
|
credentials.custom_error_codes = [...selectedErrorCodes.value]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add intercept warmup requests setting
|
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
|
||||||
if (interceptWarmupRequests.value) {
|
|
||||||
credentials.intercept_warmup_requests = true
|
|
||||||
}
|
|
||||||
if (!applyTempUnschedConfig(credentials)) {
|
if (!applyTempUnschedConfig(credentials)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -3606,6 +3606,7 @@ const handleAntigravityExchange = async (authCode: string) => {
|
|||||||
if (!tokenInfo) return
|
if (!tokenInfo) return
|
||||||
|
|
||||||
const credentials = antigravityOAuth.buildCredentials(tokenInfo)
|
const credentials = antigravityOAuth.buildCredentials(tokenInfo)
|
||||||
|
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
|
||||||
// Antigravity 只使用映射模式
|
// Antigravity 只使用映射模式
|
||||||
const antigravityModelMapping = buildModelMappingObject(
|
const antigravityModelMapping = buildModelMappingObject(
|
||||||
'mapping',
|
'mapping',
|
||||||
@@ -3677,10 +3678,8 @@ const handleAnthropicExchange = async (authCode: string) => {
|
|||||||
extra.cache_ttl_override_target = cacheTTLOverrideTarget.value
|
extra.cache_ttl_override_target = cacheTTLOverrideTarget.value
|
||||||
}
|
}
|
||||||
|
|
||||||
const credentials = {
|
const credentials: Record<string, unknown> = { ...tokenInfo }
|
||||||
...tokenInfo,
|
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
|
||||||
...(interceptWarmupRequests.value ? { intercept_warmup_requests: true } : {})
|
|
||||||
}
|
|
||||||
await createAccountAndFinish(form.platform, addMethod.value as AccountType, credentials, extra)
|
await createAccountAndFinish(form.platform, addMethod.value as AccountType, credentials, extra)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
oauth.error.value = error.response?.data?.detail || t('admin.accounts.oauth.authFailed')
|
oauth.error.value = error.response?.data?.detail || t('admin.accounts.oauth.authFailed')
|
||||||
@@ -3779,11 +3778,8 @@ const handleCookieAuth = async (sessionKey: string) => {
|
|||||||
|
|
||||||
const accountName = keys.length > 1 ? `${form.name} #${i + 1}` : form.name
|
const accountName = keys.length > 1 ? `${form.name} #${i + 1}` : form.name
|
||||||
|
|
||||||
// Merge interceptWarmupRequests into credentials
|
const credentials: Record<string, unknown> = { ...tokenInfo }
|
||||||
const credentials: Record<string, unknown> = {
|
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
|
||||||
...tokenInfo,
|
|
||||||
...(interceptWarmupRequests.value ? { intercept_warmup_requests: true } : {})
|
|
||||||
}
|
|
||||||
if (tempUnschedEnabled.value) {
|
if (tempUnschedEnabled.value) {
|
||||||
credentials.temp_unschedulable_enabled = true
|
credentials.temp_unschedulable_enabled = true
|
||||||
credentials.temp_unschedulable_rules = tempUnschedPayload
|
credentials.temp_unschedulable_rules = tempUnschedPayload
|
||||||
|
|||||||
@@ -1162,6 +1162,7 @@ import Icon from '@/components/icons/Icon.vue'
|
|||||||
import ProxySelector from '@/components/common/ProxySelector.vue'
|
import ProxySelector from '@/components/common/ProxySelector.vue'
|
||||||
import GroupSelector from '@/components/common/GroupSelector.vue'
|
import GroupSelector from '@/components/common/GroupSelector.vue'
|
||||||
import ModelWhitelistSelector from '@/components/account/ModelWhitelistSelector.vue'
|
import ModelWhitelistSelector from '@/components/account/ModelWhitelistSelector.vue'
|
||||||
|
import { applyInterceptWarmup } from '@/components/account/credentialsBuilder'
|
||||||
import { formatDateTimeLocalInput, parseDateTimeLocalInput } from '@/utils/format'
|
import { formatDateTimeLocalInput, parseDateTimeLocalInput } from '@/utils/format'
|
||||||
import { createStableObjectKeyResolver } from '@/utils/stableObjectKey'
|
import { createStableObjectKeyResolver } from '@/utils/stableObjectKey'
|
||||||
import {
|
import {
|
||||||
@@ -1789,9 +1790,7 @@ const handleSubmit = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add intercept warmup requests setting
|
// Add intercept warmup requests setting
|
||||||
if (interceptWarmupRequests.value) {
|
applyInterceptWarmup(newCredentials, interceptWarmupRequests.value, 'edit')
|
||||||
newCredentials.intercept_warmup_requests = true
|
|
||||||
}
|
|
||||||
if (!applyTempUnschedConfig(newCredentials)) {
|
if (!applyTempUnschedConfig(newCredentials)) {
|
||||||
submitting.value = false
|
submitting.value = false
|
||||||
return
|
return
|
||||||
@@ -1808,6 +1807,9 @@ const handleSubmit = async () => {
|
|||||||
newCredentials.api_key = editApiKey.value.trim()
|
newCredentials.api_key = editApiKey.value.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add intercept warmup requests setting
|
||||||
|
applyInterceptWarmup(newCredentials, interceptWarmupRequests.value, 'edit')
|
||||||
|
|
||||||
if (!applyTempUnschedConfig(newCredentials)) {
|
if (!applyTempUnschedConfig(newCredentials)) {
|
||||||
submitting.value = false
|
submitting.value = false
|
||||||
return
|
return
|
||||||
@@ -1819,11 +1821,7 @@ const handleSubmit = async () => {
|
|||||||
const currentCredentials = (props.account.credentials as Record<string, unknown>) || {}
|
const currentCredentials = (props.account.credentials as Record<string, unknown>) || {}
|
||||||
const newCredentials: Record<string, unknown> = { ...currentCredentials }
|
const newCredentials: Record<string, unknown> = { ...currentCredentials }
|
||||||
|
|
||||||
if (interceptWarmupRequests.value) {
|
applyInterceptWarmup(newCredentials, interceptWarmupRequests.value, 'edit')
|
||||||
newCredentials.intercept_warmup_requests = true
|
|
||||||
} else {
|
|
||||||
delete newCredentials.intercept_warmup_requests
|
|
||||||
}
|
|
||||||
if (!applyTempUnschedConfig(newCredentials)) {
|
if (!applyTempUnschedConfig(newCredentials)) {
|
||||||
submitting.value = false
|
submitting.value = false
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
import { applyInterceptWarmup } from '../credentialsBuilder'
|
||||||
|
|
||||||
|
describe('applyInterceptWarmup', () => {
|
||||||
|
it('create + enabled=true: should set intercept_warmup_requests to true', () => {
|
||||||
|
const creds: Record<string, unknown> = { access_token: 'tok' }
|
||||||
|
applyInterceptWarmup(creds, true, 'create')
|
||||||
|
expect(creds.intercept_warmup_requests).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('create + enabled=false: should not add the field', () => {
|
||||||
|
const creds: Record<string, unknown> = { access_token: 'tok' }
|
||||||
|
applyInterceptWarmup(creds, false, 'create')
|
||||||
|
expect('intercept_warmup_requests' in creds).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('edit + enabled=true: should set intercept_warmup_requests to true', () => {
|
||||||
|
const creds: Record<string, unknown> = { api_key: 'sk' }
|
||||||
|
applyInterceptWarmup(creds, true, 'edit')
|
||||||
|
expect(creds.intercept_warmup_requests).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('edit + enabled=false + field exists: should delete the field', () => {
|
||||||
|
const creds: Record<string, unknown> = { api_key: 'sk', intercept_warmup_requests: true }
|
||||||
|
applyInterceptWarmup(creds, false, 'edit')
|
||||||
|
expect('intercept_warmup_requests' in creds).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('edit + enabled=false + field absent: should not throw', () => {
|
||||||
|
const creds: Record<string, unknown> = { api_key: 'sk' }
|
||||||
|
applyInterceptWarmup(creds, false, 'edit')
|
||||||
|
expect('intercept_warmup_requests' in creds).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not affect other fields', () => {
|
||||||
|
const creds: Record<string, unknown> = {
|
||||||
|
api_key: 'sk',
|
||||||
|
base_url: 'url',
|
||||||
|
intercept_warmup_requests: true
|
||||||
|
}
|
||||||
|
applyInterceptWarmup(creds, false, 'edit')
|
||||||
|
expect(creds.api_key).toBe('sk')
|
||||||
|
expect(creds.base_url).toBe('url')
|
||||||
|
expect('intercept_warmup_requests' in creds).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
11
frontend/src/components/account/credentialsBuilder.ts
Normal file
11
frontend/src/components/account/credentialsBuilder.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export function applyInterceptWarmup(
|
||||||
|
credentials: Record<string, unknown>,
|
||||||
|
enabled: boolean,
|
||||||
|
mode: 'create' | 'edit'
|
||||||
|
): void {
|
||||||
|
if (enabled) {
|
||||||
|
credentials.intercept_warmup_requests = true
|
||||||
|
} else if (mode === 'edit') {
|
||||||
|
delete credentials.intercept_warmup_requests
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user