mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-14 21:25:09 +08:00
feat: implement error handling for empty upstream responses in chat streams and update UI to display stream-level errors
This commit is contained in:
@@ -133,7 +133,9 @@ export default function ChatPanel({
|
||||
)}
|
||||
|
||||
<div className="text-sm leading-7 text-foreground whitespace-pre-wrap">
|
||||
{streamingContent || response?.choices?.[0]?.message?.content || (response?.error && <span className="text-destructive font-medium">{response.error}</span>) || (loading && <span className="text-muted-foreground italic">{t('apiTester.generating')}</span>)}
|
||||
{response?.success === false
|
||||
? <span className="text-destructive font-medium">{response.error || t('apiTester.requestFailed')}</span>
|
||||
: (streamingContent || response?.choices?.[0]?.message?.content || (loading && <span className="text-muted-foreground italic">{t('apiTester.generating')}</span>))}
|
||||
{isStreaming && <span className="inline-block w-1.5 h-4 bg-primary ml-1 align-middle animate-pulse" />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -63,6 +63,28 @@ export function useChatStreamClient({
|
||||
}
|
||||
}, [attachedFiles, t])
|
||||
|
||||
const extractStreamError = useCallback((json) => {
|
||||
const error = json?.error
|
||||
if (!error || typeof error !== 'object') {
|
||||
return null
|
||||
}
|
||||
|
||||
const message = typeof error.message === 'string' && error.message.trim()
|
||||
? error.message.trim()
|
||||
: t('apiTester.requestFailed')
|
||||
const rawStatus = Number(json?.status_code ?? error.status_code ?? error.http_status)
|
||||
const statusCode = Number.isFinite(rawStatus) && rawStatus > 0
|
||||
? rawStatus
|
||||
: (error.code === 'content_filter' ? 400 : 429)
|
||||
|
||||
return {
|
||||
message,
|
||||
statusCode,
|
||||
code: typeof error.code === 'string' ? error.code : '',
|
||||
type: typeof error.type === 'string' ? error.type : '',
|
||||
}
|
||||
}, [t])
|
||||
|
||||
const runTest = useCallback(async () => {
|
||||
if (!effectiveKey) {
|
||||
onMessage('error', t('apiTester.missingApiKey'))
|
||||
@@ -141,7 +163,9 @@ export function useChatStreamClient({
|
||||
let buffer = ''
|
||||
let accumulatedThinking = ''
|
||||
let accumulatedContent = ''
|
||||
let streamError = null
|
||||
|
||||
streamLoop:
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) break
|
||||
@@ -159,6 +183,11 @@ export function useChatStreamClient({
|
||||
|
||||
try {
|
||||
const json = JSON.parse(dataStr)
|
||||
const errorPayload = extractStreamError(json)
|
||||
if (errorPayload) {
|
||||
streamError = errorPayload
|
||||
break streamLoop
|
||||
}
|
||||
const choice = json.choices?.[0]
|
||||
if (choice?.delta) {
|
||||
const delta = choice.delta
|
||||
@@ -177,6 +206,23 @@ export function useChatStreamClient({
|
||||
}
|
||||
}
|
||||
|
||||
if (streamError) {
|
||||
await reader.cancel().catch(() => {})
|
||||
setStreamingContent('')
|
||||
setStreamingThinking('')
|
||||
setResponse({
|
||||
success: false,
|
||||
status_code: streamError.statusCode,
|
||||
error: streamError.message,
|
||||
code: streamError.code,
|
||||
type: streamError.type,
|
||||
})
|
||||
onMessage('error', streamError.message)
|
||||
setLoading(false)
|
||||
setIsStreaming(false)
|
||||
return
|
||||
}
|
||||
|
||||
setResponse({
|
||||
success: true,
|
||||
status_code: res.status,
|
||||
@@ -214,6 +260,7 @@ export function useChatStreamClient({
|
||||
attachedFiles,
|
||||
effectiveKey,
|
||||
extractErrorMessage,
|
||||
extractStreamError,
|
||||
message,
|
||||
model,
|
||||
onMessage,
|
||||
|
||||
Reference in New Issue
Block a user