feat: Add HTTP error handling and localized error messages

This commit is contained in:
kangfenmao 2025-02-08 23:01:27 +08:00
parent 220d11a414
commit e1a04030b5
9 changed files with 96 additions and 9 deletions

View File

@ -172,6 +172,17 @@
"render": { "render": {
"title": "Render Error", "title": "Render Error",
"description": "Failed to render formula. Please check if the formula format is correct" "description": "Failed to render formula. Please check if the formula format is correct"
},
"http": {
"400": "Request failed. Please check if the request parameters are correct. If you have changed the model settings, please reset them to the default settings",
"401": "Authentication failed. Please check if your API key is correct",
"403": "Access denied. Please check if your account is verified, or contact the service provider for more information",
"404": "Model not found or request path is incorrect",
"429": "Too many requests. Please try again later",
"500": "Server error. Please try again later",
"502": "Gateway error. Please try again later",
"503": "Service unavailable. Please try again later",
"504": "Gateway timeout. Please try again later"
} }
}, },
"export": { "export": {

View File

@ -167,6 +167,17 @@
"render": { "render": {
"title": "レンダリングエラー", "title": "レンダリングエラー",
"description": "数式のレンダリングに失敗しました。数式の形式が正しいか確認してください" "description": "数式のレンダリングに失敗しました。数式の形式が正しいか確認してください"
},
"http": {
"400": "リクエストに失敗しました。リクエストパラメータが正しいか確認してください。モデルの設定を変更した場合は、デフォルトの設定にリセットしてください",
"401": "認証に失敗しました。APIキーが正しいか確認してください",
"403": "アクセスが拒否されました。アカウントが実名認証されているか確認してください。またはサービスプロバイダーに問い合わせてください",
"404": "モデルが見つからないか、リクエストパスが間違っています",
"429": "リクエストが多すぎます。後でもう一度試してください",
"500": "サーバーエラーが発生しました。後でもう一度試してください",
"502": "ゲートウェイエラーが発生しました。後でもう一度試してください",
"503": "サービスが利用できません。後でもう一度試してください",
"504": "ゲートウェイタイムアウトが発生しました。後でもう一度試してください"
} }
}, },
"export": { "export": {

View File

@ -167,6 +167,17 @@
"render": { "render": {
"title": "Ошибка рендеринга", "title": "Ошибка рендеринга",
"description": "Не удалось рендерить формулу. Пожалуйста, проверьте, правильно ли формат формулы" "description": "Не удалось рендерить формулу. Пожалуйста, проверьте, правильно ли формат формулы"
},
"http": {
"400": "Не удалось выполнить запрос. Пожалуйста, проверьте, правильно ли настроены параметры запроса. Если вы изменили настройки модели, пожалуйста, сбросьте их до значений по умолчанию",
"401": "Не удалось пройти аутентификацию. Пожалуйста, проверьте, правильно ли настроен ваш ключ API",
"403": "Доступ запрещен. Пожалуйста, проверьте, правильно ли настроены ваши учетные данные или обратитесь к поставщику услуг для получения дополнительной информации",
"404": "Модель не найдена или путь запроса неверен",
"429": "Слишком много запросов. Пожалуйста, попробуйте позже",
"500": "Серверная ошибка. Пожалуйста, попробуйте позже",
"502": "Серверная ошибка. Пожалуйста, попробуйте позже",
"503": "Серверная ошибка. Пожалуйста, попробуйте позже",
"504": "Серверная ошибка. Пожалуйста, попробуйте позже"
} }
}, },
"export": { "export": {

View File

@ -173,6 +173,17 @@
"render": { "render": {
"title": "渲染错误", "title": "渲染错误",
"description": "渲染公式失败,请检查公式格式是否正确" "description": "渲染公式失败,请检查公式格式是否正确"
},
"http": {
"400": "请求错误,请检查请求参数是否正确。如果修改了模型设置,请重置到默认设置",
"401": "身份验证失败,请检查 API 密钥是否正确",
"403": "禁止访问,请检查是否实名认证,或联系服务商询问被禁止原因",
"404": "模型不存在或者请求路径错误",
"429": "请求过多,请稍后再试",
"500": "服务器错误,请稍后再试",
"502": "网关错误,请稍后再试",
"503": "服务不可用,请稍后再试",
"504": "网关超时,请稍后再试"
} }
}, },
"export": { "export": {

View File

@ -172,6 +172,17 @@
"render": { "render": {
"title": "渲染錯誤", "title": "渲染錯誤",
"description": "渲染公式失敗,請檢查公式格式是否正確" "description": "渲染公式失敗,請檢查公式格式是否正確"
},
"http": {
"400": "請求錯誤,請檢查請求參數是否正確。如果修改了模型設置,請重置到預設設置",
"401": "身份驗證失敗,請檢查 API 密鑰是否正確",
"403": "禁止訪問,請檢查是否實名認證,或聯繫服務商詢問被禁止原因",
"404": "模型不存在或者請求路徑錯誤",
"429": "請求過多,請稍後再試",
"500": "伺服器錯誤,請稍後再試",
"502": "網關錯誤,請稍後再試",
"503": "服務不可用,請稍後再試",
"504": "網關超時,請稍後再試"
} }
}, },
"export": { "export": {

View File

@ -1,21 +1,35 @@
import { Message } from '@renderer/types' import { Message } from '@renderer/types'
import { Alert } from 'antd' import { Alert as AntdAlert } from 'antd'
import { t } from 'i18next'
import { FC } from 'react' import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import Markdown from '../Markdown/Markdown' import Markdown from '../Markdown/Markdown'
const MessageError: FC<{ message: Message }> = ({ message }) => { const MessageError: FC<{ message: Message }> = ({ message }) => {
return ( return (
<> <>
<Alert <MessageErrorInfo message={message} />
description={t('error.chat.response')}
type="error"
style={{ marginBottom: 15, padding: 10, fontSize: 12 }}
/>
<Markdown message={message} /> <Markdown message={message} />
</> </>
) )
} }
const MessageErrorInfo: FC<{ message: Message }> = ({ message }) => {
const { t } = useTranslation()
const HTTP_ERROR_CODES = [400, 401, 403, 404, 429, 500, 502, 503, 504]
if (message.error && HTTP_ERROR_CODES.includes(message.error?.status)) {
return <Alert description={t(`error.http.${message.error.status}`)} type="error" />
}
return <Alert description={t('error.chat.response')} type="error" />
}
const Alert = styled(AntdAlert)`
margin-bottom: 15px;
padding: 10px;
font-size: 12px;
`
export default MessageError export default MessageError

View File

@ -2,7 +2,7 @@ import i18n from '@renderer/i18n'
import store from '@renderer/store' import store from '@renderer/store'
import { setGenerating } from '@renderer/store/runtime' import { setGenerating } from '@renderer/store/runtime'
import { Assistant, Message, Model, Provider, Suggestion } from '@renderer/types' import { Assistant, Message, Model, Provider, Suggestion } from '@renderer/types'
import { formatErrorMessage } from '@renderer/utils/error' import { formatErrorMessage, formatMessageError } from '@renderer/utils/error'
import { isEmpty } from 'lodash' import { isEmpty } from 'lodash'
import AiProvider from '../providers/AiProvider' import AiProvider from '../providers/AiProvider'
@ -85,6 +85,7 @@ export async function fetchChatCompletion({
} catch (error: any) { } catch (error: any) {
message.status = 'error' message.status = 'error'
message.content = formatErrorMessage(error) message.content = formatErrorMessage(error)
message.error = formatMessageError(error)
} }
timer && clearInterval(timer) timer && clearInterval(timer)

View File

@ -70,6 +70,7 @@ export type Message = {
} }
askId?: string askId?: string
useful?: boolean useful?: boolean
error?: Record<string, any>
} }
export type Metrics = { export type Metrics = {

View File

@ -43,6 +43,22 @@ export function formatErrorMessage(error: any): string {
} }
} }
export function formatMessageError(error: any): Record<string, any> {
try {
const detailedError = getErrorDetails(error)
delete detailedError?.headers
delete detailedError?.stack
delete detailedError?.request_id
return detailedError
} catch (e) {
try {
return { message: String(error) }
} catch {
return { message: 'Error: Unable to format error message' }
}
}
}
export function getErrorMessage(error: any): string { export function getErrorMessage(error: any): string {
return error?.message || error?.toString() || '' return error?.message || error?.toString() || ''
} }