mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 18:07:47 +08:00
Expose local scheduling failures in usage UI
This commit is contained in:
@@ -73,6 +73,43 @@ describe('request failure notice', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('includes scheduling failure provider and endpoint hints in metadata', () => {
|
||||
const notice = resolveRequestFailureNotice(buildRequestDetail({
|
||||
failure_summary: {
|
||||
status_code: 503,
|
||||
message: '没有可用提供商支持模型 gemma-4-31b-it 的同步请求',
|
||||
},
|
||||
scheduling_failure: {
|
||||
source: 'local_execution_runtime_miss',
|
||||
reason: 'all_candidates_skipped',
|
||||
reason_label: '所有候选均被跳过',
|
||||
title: '本地调度失败:所有候选均被跳过',
|
||||
message: '没有可用提供商支持模型 gemma-4-31b-it 的同步请求',
|
||||
status_code: 503,
|
||||
no_upstream_attempt: true,
|
||||
requested_model: 'gemma-4-31b-it',
|
||||
provider_hint: {
|
||||
id: 'provider-google-api',
|
||||
name: 'Google API',
|
||||
},
|
||||
endpoint_hint: {
|
||||
id: 'endpoint-gemini',
|
||||
api_format: 'gemini:generate_content',
|
||||
},
|
||||
} as NonNullable<RequestDetail['scheduling_failure']>,
|
||||
}))
|
||||
|
||||
expect(notice?.meta).toEqual([
|
||||
'Google API',
|
||||
'gemini:generate_content',
|
||||
'gemma-4-31b-it',
|
||||
'所有候选均被跳过',
|
||||
'all_candidates_skipped',
|
||||
'HTTP 503',
|
||||
'未进入上游执行',
|
||||
])
|
||||
})
|
||||
|
||||
it('falls back to the failure summary for upstream failures', () => {
|
||||
const notice = resolveRequestFailureNotice(buildRequestDetail({
|
||||
failure_summary: {
|
||||
|
||||
@@ -25,6 +25,11 @@ function uniqueMeta(values: Array<string | null | undefined>): string[] {
|
||||
return Array.from(new Set(values.map(value => value?.trim()).filter((value): value is string => Boolean(value))))
|
||||
}
|
||||
|
||||
function isUnknownProviderHint(value: string | null): boolean {
|
||||
const normalized = value?.trim().toLowerCase()
|
||||
return !normalized || ['unknown', 'unknow', 'pending'].includes(normalized)
|
||||
}
|
||||
|
||||
function schedulingFailureMessage(
|
||||
failure: RequestSchedulingFailure,
|
||||
fallbackDomain: RequestErrorDomain | null,
|
||||
@@ -37,6 +42,21 @@ function schedulingFailureMessage(
|
||||
?? nonEmptyString(failure.reason)
|
||||
}
|
||||
|
||||
function schedulingFailureProviderHint(failure: RequestSchedulingFailure): string | null {
|
||||
const name = nonEmptyString(failure.provider_hint?.name)
|
||||
if (name && !isUnknownProviderHint(name)) return name
|
||||
|
||||
const id = nonEmptyString(failure.provider_hint?.id)
|
||||
if (id && !isUnknownProviderHint(id)) return id
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function schedulingFailureEndpointHint(failure: RequestSchedulingFailure): string | null {
|
||||
return nonEmptyString(failure.endpoint_hint?.api_format)
|
||||
?? nonEmptyString(failure.endpoint_hint?.id)
|
||||
}
|
||||
|
||||
export function resolveRequestFailureNotice(detail: RequestDetail | null | undefined): RequestFailureNotice | null {
|
||||
if (!detail) return null
|
||||
|
||||
@@ -55,6 +75,9 @@ export function resolveRequestFailureNotice(detail: RequestDetail | null | undef
|
||||
message,
|
||||
isSchedulingFailure: true,
|
||||
meta: uniqueMeta([
|
||||
schedulingFailureProviderHint(schedulingFailure),
|
||||
schedulingFailureEndpointHint(schedulingFailure),
|
||||
nonEmptyString(schedulingFailure.requested_model),
|
||||
nonEmptyString(schedulingFailure.reason_summary),
|
||||
nonEmptyString(schedulingFailure.reason_label),
|
||||
nonEmptyString(schedulingFailure.reason),
|
||||
|
||||
Reference in New Issue
Block a user