mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 18:59:50 +08:00
fix(provider): split partial model fetch warnings from errors
This commit is contained in:
@@ -357,8 +357,8 @@ async function applyAutoMatchFromKey(key: AutoMatchKey) {
|
||||
const result = await fetchCachedModels(props.providerId, key.id, true)
|
||||
if (!props.open) return
|
||||
|
||||
if (result.error && result.models.length > 0) {
|
||||
showWarning(`部分格式获取失败: ${result.error}`)
|
||||
if (result.warning) {
|
||||
showWarning(`部分格式获取失败: ${result.warning}`)
|
||||
}
|
||||
|
||||
if (result.models.length === 0) {
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
<Input
|
||||
:model-value="getDisplayedPath(endpoint)"
|
||||
:placeholder="getEndpointDefaultPath(endpoint) || '留空使用默认'"
|
||||
:disabled="isFixedProvider"
|
||||
@update:model-value="(v) => updateEndpointField(endpoint.id, 'path', v)"
|
||||
/>
|
||||
<p
|
||||
@@ -1878,9 +1877,6 @@ function getEndpointDefaultPath(endpoint: ProviderEndpoint): string {
|
||||
}
|
||||
|
||||
function getDisplayedPath(endpoint: ProviderEndpoint): string {
|
||||
if (isFixedProvider.value) {
|
||||
return getDefaultPath(endpoint.api_format, endpoint.base_url)
|
||||
}
|
||||
return getEndpointEditState(endpoint.id)?.path ?? (endpoint.custom_path || '')
|
||||
}
|
||||
|
||||
@@ -3217,13 +3213,13 @@ async function saveEndpoint(endpoint: ProviderEndpoint) {
|
||||
|
||||
savingEndpointId.value = endpoint.id
|
||||
try {
|
||||
// 仅提交变更字段,避免 fixed provider 因 base_url/custom_path 被锁定而更新失败
|
||||
// 仅提交变更字段;fixed provider 锁定 base_url,但允许覆盖 custom_path。
|
||||
const payload: Record<string, unknown> = {}
|
||||
|
||||
if (!isFixedProvider.value) {
|
||||
if (state.url !== endpoint.base_url) payload.base_url = state.url
|
||||
if (state.path !== (endpoint.custom_path || '')) payload.custom_path = state.path || null
|
||||
}
|
||||
if (state.path !== (endpoint.custom_path || '')) payload.custom_path = state.path || null
|
||||
|
||||
if (hasRulesChanges(endpoint)) payload.header_rules = rulesToHeaderRules(state.rules)
|
||||
if (hasResponseHeaderRulesChanges(endpoint)) {
|
||||
|
||||
@@ -295,9 +295,8 @@ async function fetchUpstreamModels() {
|
||||
.filter((m: UpstreamModel) => !existingModelIds.value.has(m.id))
|
||||
.map((m: UpstreamModel) => m.id)
|
||||
hasQueried.value = true
|
||||
// 如果有部分失败,显示警告提示
|
||||
if (result.error) {
|
||||
showWarning(result.error, '部分格式获取失败')
|
||||
if (result.warning) {
|
||||
showWarning(result.warning, '部分格式获取失败')
|
||||
}
|
||||
} else if (result.error) {
|
||||
errorMessage.value = result.error
|
||||
|
||||
@@ -691,8 +691,8 @@ async function fetchUpstreamModels(forceRefresh = false) {
|
||||
// 获取上游模型后,从自定义模型列表中移除已变成已知的模型
|
||||
const upstreamIds = new Set(result.models.map((m: UpstreamModel) => m.id))
|
||||
allCustomModels.value = allCustomModels.value.filter(m => !upstreamIds.has(m))
|
||||
if (result.error) {
|
||||
showWarning(result.error, '部分格式获取失败')
|
||||
if (result.warning) {
|
||||
showWarning(result.warning, '部分格式获取失败')
|
||||
}
|
||||
} else if (result.error) {
|
||||
showError(result.error, '获取上游模型失败')
|
||||
|
||||
@@ -564,12 +564,11 @@ async function fetchUpstreamModels() {
|
||||
const mergedCustom = new Set([...allCustomNames.value, ...customFromSelected])
|
||||
allCustomNames.value = Array.from(mergedCustom).filter(name => !upstreamIds.has(name))
|
||||
}
|
||||
if (result.warning) {
|
||||
showWarning(result.warning, '部分格式获取失败')
|
||||
}
|
||||
if (result.error) {
|
||||
if (result.models.length > 0) {
|
||||
showWarning(result.error, '部分格式获取失败')
|
||||
} else {
|
||||
showError(result.error, '获取上游模型失败')
|
||||
}
|
||||
showError(result.error, '获取上游模型失败')
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
showError(parseApiError(err, '获取上游模型列表失败'), '错误')
|
||||
|
||||
@@ -94,7 +94,7 @@ describe('endpoint default paths', () => {
|
||||
})).toBe('/responses')
|
||||
})
|
||||
|
||||
it('drops /v1 from Claude Messages defaults for v1 and unversioned api roots', () => {
|
||||
it('keeps /v1 for Claude Messages defaults unless base URL already ends with v1', () => {
|
||||
expect(getDefaultEndpointPath({
|
||||
apiFormat: 'claude:messages',
|
||||
providerType: 'custom',
|
||||
@@ -107,13 +107,13 @@ describe('endpoint default paths', () => {
|
||||
providerType: 'custom',
|
||||
baseUrl: 'https://proxy.example.com/api',
|
||||
apiFormats,
|
||||
})).toBe('/messages')
|
||||
})).toBe('/v1/messages')
|
||||
|
||||
expect(getDefaultEndpointPath({
|
||||
apiFormat: 'claude:messages',
|
||||
providerType: 'custom',
|
||||
baseUrl: 'https://proxy.example.com/anthropic',
|
||||
apiFormats,
|
||||
})).toBe('/messages')
|
||||
})).toBe('/v1/messages')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -69,7 +69,7 @@ function openAiCompatibleBaseIncludesApiRoot(baseUrl?: string | null): boolean {
|
||||
}
|
||||
|
||||
function v1CompatibleBaseIncludesApiRoot(baseUrl?: string | null): boolean {
|
||||
return baseUrlEndsWithV1Root(baseUrl) || baseUrlHasPathApiRoot(baseUrl)
|
||||
return baseUrlEndsWithV1Root(baseUrl)
|
||||
}
|
||||
|
||||
function stripV1PrefixForApiRoot(path: string): string {
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { UpstreamModel } from '@/api/endpoints/types'
|
||||
|
||||
export type { UpstreamModel }
|
||||
|
||||
type FetchResult = { models: UpstreamModel[]; error?: string; fromCache?: boolean }
|
||||
type FetchResult = { models: UpstreamModel[]; error?: string; warning?: string; fromCache?: boolean }
|
||||
|
||||
// 进行中的请求(用于去重并发请求)
|
||||
const pendingRequests = new Map<string, Promise<FetchResult>>()
|
||||
@@ -54,14 +54,14 @@ export function useUpstreamModelsCache() {
|
||||
const response = await adminApi.queryProviderModels(providerId, apiKeyId, forceRefresh)
|
||||
|
||||
if (response.success && response.data?.models) {
|
||||
const partialWarning = response.data.warning ?? response.data.error
|
||||
return {
|
||||
models: response.data.models,
|
||||
// 传递部分格式获取失败的 warning(后端 success=true 但仍可能附带 error)
|
||||
error: response.data.error ? parseUpstreamModelError(response.data.error) : undefined,
|
||||
warning: partialWarning ? parseUpstreamModelError(partialWarning) : undefined,
|
||||
fromCache: response.data.from_cache
|
||||
}
|
||||
} else {
|
||||
const rawError = response.data?.error || '获取上游模型失败'
|
||||
const rawError = response.data?.error || response.data?.warning || '获取上游模型失败'
|
||||
return { models: [], error: parseUpstreamModelError(rawError) }
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
|
||||
Reference in New Issue
Block a user