feat(错误处理): 添加序列化错误类型检查函数并更新错误格式化逻辑

添加 isSerializedError 类型检查函数用于判断序列化错误
更新 formatError 和 formatAiSdkError 函数以处理序列化错误类型
修改 ErrorBlock 组件使用新的类型检查函数替代 instanceof 检查
This commit is contained in:
icarus 2025-09-04 01:37:58 +08:00
parent cf5fbfbca3
commit c5afaa3629
3 changed files with 15 additions and 8 deletions

View File

@ -7,13 +7,13 @@ import { removeBlocksThunk } from '@renderer/store/thunk/messageThunk'
import { import {
isSerializedAiSdkAPICallError, isSerializedAiSdkAPICallError,
isSerializedAiSdkError, isSerializedAiSdkError,
isSerializedError,
SerializedAiSdkAPICallError, SerializedAiSdkAPICallError,
SerializedAiSdkError, SerializedAiSdkError,
SerializedError SerializedError
} from '@renderer/types/error' } from '@renderer/types/error'
import type { ErrorMessageBlock, Message } from '@renderer/types/newMessage' import type { ErrorMessageBlock, Message } from '@renderer/types/newMessage'
import { formatAiSdkError, formatError, safeToString } from '@renderer/utils/error' import { formatAiSdkError, formatError, safeToString } from '@renderer/utils/error'
import { AISDKError } from 'ai'
import { Alert as AntdAlert, Button, Modal } from 'antd' import { Alert as AntdAlert, Button, Modal } from 'antd'
import React, { useState } from 'react' import React, { useState } from 'react'
import { Trans, useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
@ -143,9 +143,9 @@ const ErrorDetailModal: React.FC<ErrorDetailModalProps> = ({ open, onClose, erro
const copyErrorDetails = () => { const copyErrorDetails = () => {
if (!error) return if (!error) return
let errorText: string let errorText: string
if (AISDKError.isInstance(error)) { if (isSerializedAiSdkError(error)) {
errorText = formatAiSdkError(error) errorText = formatAiSdkError(error)
} else if (error instanceof Error) { } else if (isSerializedError(error)) {
errorText = formatError(error) errorText = formatError(error)
} else { } else {
// fallback // fallback

View File

@ -6,6 +6,9 @@ export interface SerializedError {
stack: string | null stack: string | null
[key: string]: Serializable [key: string]: Serializable
} }
export const isSerializedError = (error: Record<string, unknown>): error is SerializedAiSdkError => {
return 'name' in error && 'message' in error && 'stack' in error
}
export interface SerializedAiSdkError extends SerializedError { export interface SerializedAiSdkError extends SerializedError {
readonly cause: string | null readonly cause: string | null
} }

View File

@ -1,6 +1,10 @@
import { loggerService } from '@logger' import { loggerService } from '@logger'
import { AiSdkErrorUnion } from '@renderer/types/aiCoreTypes' import {
import { SerializedAiSdkAPICallError, SerializedError } from '@renderer/types/error' isSerializedAiSdkAPICallError,
SerializedAiSdkAPICallError,
SerializedAiSdkError,
SerializedError
} from '@renderer/types/error'
import { AISDKError, APICallError } from 'ai' import { AISDKError, APICallError } from 'ai'
import { t } from 'i18next' import { t } from 'i18next'
import z from 'zod' import z from 'zod'
@ -199,16 +203,16 @@ function getCircularReplacer() {
} }
} }
export function formatError(error: Error): string { export function formatError(error: SerializedError): string {
return `${t('error.name')}: ${error.name}\n${t('error.message')}: ${error.message}\n${t('error.stack')}: ${error.stack}` return `${t('error.name')}: ${error.name}\n${t('error.message')}: ${error.message}\n${t('error.stack')}: ${error.stack}`
} }
export function formatAiSdkError(error: AiSdkErrorUnion): string { export function formatAiSdkError(error: SerializedAiSdkError): string {
let text = formatError(error) + '\n' let text = formatError(error) + '\n'
if (error.cause) { if (error.cause) {
text += `${t('error.cause')}: ${error.cause}\n` text += `${t('error.cause')}: ${error.cause}\n`
} }
if (APICallError.isInstance(error)) { if (isSerializedAiSdkAPICallError(error)) {
if (error.statusCode) { if (error.statusCode) {
text += `${t('error.statusCode')}: ${error.statusCode}\n` text += `${t('error.statusCode')}: ${error.statusCode}\n`
} }