feat: 实现 GlobalModel 别名匹配系统

主要更改:
- GlobalModel 支持 model_aliases 配置,允许使用正则表达式定义别名规则
- Provider Key 的 allowed_models 现在可以通过别名规则匹配 GlobalModel
- 新增 ModelAliasesTab 组件用于管理模型别名配置
- Provider 详情页新增别名映射预览功能,展示 Key 白名单与 GlobalModel 别名的匹配关系
- 路由预览 API 返回 Key 的 allowed_models 信息

安全特性:
- 使用 regex 库的原生超时保护(100ms)防止 ReDoS 攻击
- 别名规则数量限制(50 条/模型)和长度限制(200 字符)
- 别名映射预览 API 添加超时保护和结果截断

其他改进:
- GlobalModel 更新/删除时使用行级锁防止并发竞态
- 缓存失效逻辑优化,支持异步清理和正则缓存清空
- 路由 Tab 布局重构,使用 flexbox 替代绝对定位
This commit is contained in:
fawney19
2026-01-13 16:04:15 +08:00
parent 9fea71a70c
commit 85decd7487
21 changed files with 3845 additions and 2308 deletions

View File

@@ -95,3 +95,50 @@ export async function testModel(data: TestModelRequest): Promise<TestModelRespon
const response = await client.post('/api/admin/provider-query/test-model', data)
return response.data
}
/**
* 别名映射预览相关类型
*/
export interface AliasMatchedModel {
allowed_model: string
alias_pattern: string
}
export interface AliasMatchingGlobalModel {
global_model_id: string
global_model_name: string
display_name: string
is_active: boolean
matched_models: AliasMatchedModel[]
}
export interface AliasMatchingKey {
key_id: string
key_name: string
masked_key: string
is_active: boolean
allowed_models: string[]
matching_global_models: AliasMatchingGlobalModel[]
}
export interface ProviderAliasMappingPreviewResponse {
provider_id: string
provider_name: string
keys: AliasMatchingKey[]
total_keys: number
total_matches: number
// 截断提示
truncated: boolean
truncated_keys: number
truncated_models: number
}
/**
* 获取 Provider 别名映射预览
*/
export async function getProviderAliasMappingPreview(
providerId: string
): Promise<ProviderAliasMappingPreviewResponse> {
const response = await client.get(`/api/admin/providers/${providerId}/alias-mapping-preview`)
return response.data
}

View File

@@ -641,6 +641,7 @@ export interface RoutingKeyInfo {
health_score: number
is_active: boolean
api_formats: string[]
allowed_models?: string[] | null // 允许的模型列表null 表示不限制
circuit_breaker_open: boolean
circuit_breaker_formats: string[]
}