mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
centralize openai responses alias handling
This commit is contained in:
@@ -694,8 +694,19 @@ const STANDARD_ROUTING_API_FORMATS = [
|
||||
'gemini:cli'
|
||||
]
|
||||
|
||||
function apiDataFormatId(apiFormat: string): string | null {
|
||||
function normalizeLegacyOpenAIFormatAlias(apiFormat: string): string {
|
||||
switch (apiFormat.trim().toLowerCase()) {
|
||||
case 'openai:cli':
|
||||
return 'openai:responses'
|
||||
case 'openai:compact':
|
||||
return 'openai:responses:compact'
|
||||
default:
|
||||
return apiFormat.trim().toLowerCase()
|
||||
}
|
||||
}
|
||||
|
||||
function apiDataFormatId(apiFormat: string): string | null {
|
||||
switch (normalizeLegacyOpenAIFormatAlias(apiFormat)) {
|
||||
case 'claude:chat':
|
||||
case 'claude:cli':
|
||||
return 'claude'
|
||||
@@ -706,8 +717,6 @@ function apiDataFormatId(apiFormat: string): string | null {
|
||||
return 'openai_chat'
|
||||
case 'openai:responses':
|
||||
case 'openai:responses:compact':
|
||||
case 'openai:cli':
|
||||
case 'openai:compact':
|
||||
return 'openai_responses'
|
||||
default:
|
||||
return null
|
||||
@@ -715,8 +724,8 @@ function apiDataFormatId(apiFormat: string): string | null {
|
||||
}
|
||||
|
||||
function requestConversionKind(clientApiFormat: string, providerApiFormat: string): string | null {
|
||||
const client = clientApiFormat.trim().toLowerCase()
|
||||
const provider = providerApiFormat.trim().toLowerCase()
|
||||
const client = normalizeLegacyOpenAIFormatAlias(clientApiFormat)
|
||||
const provider = normalizeLegacyOpenAIFormatAlias(providerApiFormat)
|
||||
if (client === provider) return null
|
||||
if (!STANDARD_ROUTING_API_FORMATS.includes(client) || !STANDARD_ROUTING_API_FORMATS.includes(provider)) {
|
||||
return null
|
||||
@@ -727,8 +736,6 @@ function requestConversionKind(clientApiFormat: string, providerApiFormat: strin
|
||||
return 'to_openai_chat'
|
||||
case 'openai:responses':
|
||||
return 'to_openai_responses'
|
||||
case 'openai:cli':
|
||||
return 'to_openai_responses'
|
||||
case 'claude:chat':
|
||||
case 'claude:cli':
|
||||
return 'to_claude'
|
||||
|
||||
@@ -1285,6 +1285,17 @@ function hasDefaultBodyRules(apiFormat: string): boolean {
|
||||
return (defaultBodyRulesByFormat.value[cacheKey]?.length || 0) > 0
|
||||
}
|
||||
|
||||
function normalizeLegacyOpenAIFormatAlias(apiFormat: string): string {
|
||||
switch (apiFormat.trim().toLowerCase()) {
|
||||
case 'openai:cli':
|
||||
return 'openai:responses'
|
||||
case 'openai:compact':
|
||||
return 'openai:responses:compact'
|
||||
default:
|
||||
return apiFormat.trim().toLowerCase()
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDefaultBodyRulesForFormat(apiFormat: string, force = false): Promise<BodyRule[]> {
|
||||
if (!apiFormat) return []
|
||||
const providerType = (props.provider?.provider_type || '').toLowerCase()
|
||||
@@ -1321,22 +1332,23 @@ async function preloadDefaultBodyRules(endpoints: ProviderEndpoint[]): Promise<v
|
||||
// 获取指定 API 格式的默认路径
|
||||
function getDefaultPath(apiFormat: string, baseUrl?: string): string {
|
||||
const providerType = (props.provider?.provider_type || '').toLowerCase()
|
||||
const normalizedApiFormat = normalizeLegacyOpenAIFormatAlias(apiFormat)
|
||||
if (providerType === 'vertex_ai') {
|
||||
if (apiFormat === 'gemini:chat') {
|
||||
if (normalizedApiFormat === 'gemini:chat') {
|
||||
return '/v1/publishers/google/models/{model}:{action}'
|
||||
}
|
||||
if (apiFormat === 'claude:chat') {
|
||||
if (normalizedApiFormat === 'claude:chat') {
|
||||
return '/v1/projects/{project_id}/locations/{region}/publishers/anthropic/models/{model}:{action}'
|
||||
}
|
||||
}
|
||||
|
||||
const format = apiFormats.value.find(f => f.value === apiFormat)
|
||||
const format = apiFormats.value.find(f => f.value === normalizedApiFormat)
|
||||
const defaultPath = format?.default_path || ''
|
||||
// Codex 端点使用 /responses 而非 /v1/responses
|
||||
const isCodex = providerType
|
||||
? providerType === 'codex'
|
||||
: (!!baseUrl && isCodexUrl(baseUrl))
|
||||
if ((apiFormat === 'openai:responses' || apiFormat === 'openai:cli') && isCodex) {
|
||||
if (normalizedApiFormat === 'openai:responses' && isCodex) {
|
||||
return '/responses'
|
||||
}
|
||||
return defaultPath
|
||||
@@ -2381,7 +2393,7 @@ function getCurrentUpstreamStreamPolicy(endpoint: ProviderEndpoint): string {
|
||||
|
||||
function isUpstreamStreamPolicyLocked(endpoint: ProviderEndpoint): boolean {
|
||||
return (props.provider?.provider_type || '').toLowerCase() === 'codex'
|
||||
&& (endpoint.api_format === 'openai:responses' || endpoint.api_format === 'openai:cli')
|
||||
&& normalizeLegacyOpenAIFormatAlias(endpoint.api_format) === 'openai:responses'
|
||||
}
|
||||
|
||||
// 获取上游流式按钮的样式类
|
||||
|
||||
@@ -124,6 +124,10 @@ function normalizeUsageStreamApiFormat(value: string | null | undefined): string
|
||||
switch (normalized) {
|
||||
case 'openai':
|
||||
return 'openai:chat'
|
||||
case 'openai:cli':
|
||||
return 'openai:responses'
|
||||
case 'openai:compact':
|
||||
return 'openai:responses:compact'
|
||||
case 'claude':
|
||||
return 'claude:chat'
|
||||
case 'gemini':
|
||||
@@ -138,8 +142,6 @@ function usageApiFormatDefaultsToNonStream(apiFormat: string): boolean {
|
||||
case 'openai:chat':
|
||||
case 'openai:responses':
|
||||
case 'openai:responses:compact':
|
||||
case 'openai:cli':
|
||||
case 'openai:compact':
|
||||
case 'openai:image':
|
||||
case 'claude:chat':
|
||||
case 'claude:cli':
|
||||
|
||||
Reference in New Issue
Block a user