fix(account): preserve combined model restrictions

This commit is contained in:
wucm667 committed 2026-05-14 15:00:28 +08:00
1 parent 18790386a7
commit 827764d7bd
4 files changed
+125 -93

No files matched your search

@@ -4,7 +4,7 @@ vi.mock('@/api/admin/accounts', () => ({
getAntigravityDefaultModelMapping: vi.fn()
}))
import { buildModelMappingObject, getModelsByPlatform } from '../useModelWhitelist'
import { buildModelMappingObject, getModelsByPlatform, splitModelMappingObject } from '../useModelWhitelist'
describe('useModelWhitelist', () => {
it('openai 模型列表包含 GPT-5.4 官方快照', () => {
@@ -73,4 +73,34 @@ describe('useModelWhitelist', () => {
'gpt-5.4-mini': 'gpt-5.4-mini'
})
})
it('combined 模式会同时保留白名单身份映射和模型映射', () => {
const mapping = buildModelMappingObject(
'combined',
['gpt-5.4', 'claude-*'],
[
{ from: 'gpt-latest', to: 'gpt-5.4' },
{ from: 'gpt-5.4', to: 'gpt-5.4-mini' }
]
)
expect(mapping).toEqual({
'gpt-5.4': 'gpt-5.4-mini',
'gpt-latest': 'gpt-5.4'
})
})
it('splitModelMappingObject 会把身份映射还原成白名单,其余保留为映射', () => {
const parsed = splitModelMappingObject({
'gpt-5.4': 'gpt-5.4',
'gpt-latest': 'gpt-5.4',
' ': 'gpt-empty',
broken: 123
})
expect(parsed).toEqual({
allowedModels: ['gpt-5.4'],
modelMappings: [{ from: 'gpt-latest', to: 'gpt-5.4' }]
})
})
})
+43 -6
View File
@@ -395,23 +395,60 @@ export function isValidWildcardPattern(pattern: string): boolean {
return starIndex === pattern.length - 1 && pattern.lastIndexOf('*') === starIndex
}
export type ModelRestrictionMode = 'whitelist' | 'mapping' | 'combined'
export interface ModelMappingEntry {
from: string
to: string
}
export function splitModelMappingObject(
modelMapping?: Record<string, unknown> | null
): { allowedModels: string[]; modelMappings: ModelMappingEntry[] } {
const allowedModels: string[] = []
const modelMappings: ModelMappingEntry[] = []
if (!modelMapping || typeof modelMapping !== 'object') {
return { allowedModels, modelMappings }
}
for (const [rawFrom, rawTo] of Object.entries(modelMapping)) {
if (typeof rawTo !== 'string') continue
const from = rawFrom.trim()
const to = rawTo.trim()
if (!from || !to) continue
if (from === to) {
allowedModels.push(from)
} else {
modelMappings.push({ from, to })
}
}
return { allowedModels, modelMappings }
}
export function buildModelMappingObject(
mode: 'whitelist' | 'mapping',
mode: ModelRestrictionMode,
allowedModels: string[],
modelMappings: { from: string; to: string }[]
modelMappings: ModelMappingEntry[]
): Record<string, string> | null {
const mapping: Record<string, string> = {}
if (mode === 'whitelist') {
if (mode === 'whitelist' || mode === 'combined') {
for (const model of allowedModels) {
const normalizedModel = model.trim()
if (!normalizedModel) continue
// whitelist 模式的本意是"精确模型列表",如果用户输入了通配符(如 claude-*),
// 写入 model_mapping 会导致 GetMappedModel() 把真实模型映射成 "claude-*",从而转发失败。
// 因此这里跳过包含通配符的条目。
if (!model.includes('*')) {
mapping[model] = model
if (!normalizedModel.includes('*')) {
mapping[normalizedModel] = normalizedModel
}
}
} else {
}
if (mode === 'mapping' || mode === 'combined') {
for (const m of modelMappings) {
const from = m.from.trim()
const to = m.to.trim()