Merge pull request #467 from AAEE86/main

fix(usage): prevent detail view from overriding active request status
This commit is contained in:
fawney19
2026-05-15 21:08:48 +08:00
committed by GitHub
3 changed files with 55 additions and 4 deletions

View File

@@ -350,6 +350,35 @@ describe('HorizontalRequestTimeline', () => {
expect(nodeDot?.classList.contains('status-success')).toBe(false) expect(nodeDot?.classList.contains('status-success')).toBe(false)
}) })
it('keeps emitted trace state active while the request lifecycle is still streaming', async () => {
const onTraceState = vi.fn()
const trace = buildTrace([
buildCandidate({
id: 'cand-stale-failed',
provider_id: 'provider-stale',
provider_name: 'Provider Stale',
key_id: 'key-stale',
key_name: 'Stale Key',
candidate_index: 0,
status: 'failed',
status_code: 503,
}),
])
trace.final_status = 'failed'
mountTimeline(trace, {
requestStatus: 'streaming',
overrideStatusCode: 200,
onTraceState,
})
await nextTick()
const lastCall = onTraceState.mock.calls.at(-1)?.[0]
expect(lastCall).toMatchObject({
finalStatus: 'streaming',
})
})
it('shows request path from request metadata', async () => { it('shows request path from request metadata', async () => {
const trace = buildTrace([ const trace = buildTrace([
buildCandidate({ buildCandidate({

View File

@@ -141,6 +141,25 @@ describe('usage status helpers', () => {
})).toBe('failed') })).toBe('failed')
}) })
it('keeps active request lifecycle status authoritative over detail status code inference', () => {
expect(resolveTimelineFinalStatus({
requestStatus: 'streaming',
statusCode: 200,
})).toBe('streaming')
expect(resolveTimelineFinalStatus({
requestStatus: 'streaming',
statusCode: 503,
traceFinalStatus: 'failed',
})).toBe('streaming')
expect(resolveTimelineFinalStatus({
requestStatus: 'pending',
statusCode: 200,
traceFinalStatus: 'success',
})).toBe('pending')
})
it('uses explicit has_fallback flag for transfer filtering', () => { it('uses explicit has_fallback flag for transfer filtering', () => {
expect(hasUsageFallback(buildUsageRecord({ has_fallback: true }))).toBe(true) expect(hasUsageFallback(buildUsageRecord({ has_fallback: true }))).toBe(true)
expect(hasUsageFallback(buildUsageRecord({ has_fallback: false }))).toBe(false) expect(hasUsageFallback(buildUsageRecord({ has_fallback: false }))).toBe(false)

View File

@@ -295,6 +295,9 @@ export function resolveTimelineFinalStatus(params: {
} }
return requestStatus return requestStatus
} }
if (requestStatus === 'pending' || requestStatus === 'streaming') {
return requestStatus
}
const traceStatus = normalizeTimelineFinalStatus(params.traceFinalStatus) const traceStatus = normalizeTimelineFinalStatus(params.traceFinalStatus)
if (traceStatus === 'success' || traceStatus === 'failed' || traceStatus === 'cancelled') { if (traceStatus === 'success' || traceStatus === 'failed' || traceStatus === 'cancelled') {
@@ -304,14 +307,14 @@ export function resolveTimelineFinalStatus(params: {
return traceStatus return traceStatus
} }
if (hasTerminalSuccessStatusCode !== undefined) {
return hasTerminalSuccessStatusCode ? 'success' : 'failed'
}
if (params.hasPendingCandidates) { if (params.hasPendingCandidates) {
return 'pending' return 'pending'
} }
if (hasTerminalSuccessStatusCode !== undefined) {
return hasTerminalSuccessStatusCode ? 'success' : 'failed'
}
if (traceStatus) { if (traceStatus) {
return traceStatus return traceStatus
} }