feat: improve error handling
This commit is contained in:
@ -54,6 +54,9 @@
|
|||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error('Error getting feedback:', e)
|
console.error('Error getting feedback:', e)
|
||||||
|
if (e.message.includes('Failed to fetch')) {
|
||||||
|
e.message += `\n${t('error.requestBlockedByCORS')}`
|
||||||
|
}
|
||||||
error.value = t('modelFeedback.error', [e.message])
|
error.value = t('modelFeedback.error', [e.message])
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
@ -82,10 +85,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<p v-if="error" class="text-red-500">{{ error }}</p>
|
<div v-if="!feedback.length && !error">
|
||||||
<div v-if="!feedback.length && !error">{{ $t('modelFeedback.waiting') }}</div>
|
{{ $t('modelFeedback.waiting') }}
|
||||||
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div v-if="error" class="text-red-500">{{ error }}</div>
|
<div v-if="error" class="text-red-500 whitespace-pre-wrap">
|
||||||
|
{{ error }}
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="(feedback, index) in feedback"
|
v-for="(feedback, index) in feedback"
|
||||||
class="flex flex-col gap-2"
|
class="flex flex-col gap-2"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { ButtonProps } from '@nuxt/ui'
|
||||||
import type { ResearchStep } from '~/lib/deep-research'
|
import type { ResearchStep } from '~/lib/deep-research'
|
||||||
|
|
||||||
export type TreeNodeStatus = Exclude<ResearchStep['type'], 'complete'>
|
export type TreeNodeStatus = Exclude<ResearchStep['type'], 'complete'>
|
||||||
@ -24,38 +25,43 @@
|
|||||||
(e: 'select', value: TreeNode): void
|
(e: 'select', value: TreeNode): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const icon = computed(() => {
|
const theme = computed(() => {
|
||||||
const result = { name: '', pulse: false }
|
const result = {
|
||||||
|
icon: '',
|
||||||
|
pulse: false,
|
||||||
|
color: 'info' as ButtonProps['color'],
|
||||||
|
}
|
||||||
if (!props.node.status) return result
|
if (!props.node.status) return result
|
||||||
|
|
||||||
switch (props.node.status) {
|
switch (props.node.status) {
|
||||||
case 'generating_query':
|
case 'generating_query':
|
||||||
result.name = 'i-lucide-clipboard-list'
|
result.icon = 'i-lucide-clipboard-list'
|
||||||
result.pulse = true
|
result.pulse = true
|
||||||
break
|
break
|
||||||
case 'generated_query':
|
case 'generated_query':
|
||||||
// FIXME: 因为 deepResearch 有并发限制,这个 case 是为了明确区分状态。
|
// FIXME: 因为 deepResearch 有并发限制,这个 case 是为了明确区分状态。
|
||||||
// 但是目前进入这个状态之后再进入 searching 状态,图标不会更新成 search,不知道原因
|
// 但是目前进入这个状态之后再进入 searching 状态,图标不会更新成 search,不知道原因
|
||||||
// 暂时禁用了这个 case
|
// 暂时禁用了这个 case
|
||||||
// result.name = 'i-lucide-pause'
|
// result.name = 'i-lucide-pause'
|
||||||
// result.pulse = true
|
// result.pulse = true
|
||||||
// break
|
// break
|
||||||
case 'searching':
|
case 'searching':
|
||||||
result.name = 'i-lucide-search'
|
result.icon = 'i-lucide-search'
|
||||||
result.pulse = true
|
result.pulse = true
|
||||||
break
|
break
|
||||||
case 'search_complete':
|
case 'search_complete':
|
||||||
result.name = 'i-lucide-search-check'
|
result.icon = 'i-lucide-search-check'
|
||||||
break
|
break
|
||||||
case 'processing_serach_result':
|
case 'processing_serach_result':
|
||||||
result.name = 'i-lucide-brain'
|
result.icon = 'i-lucide-brain'
|
||||||
result.pulse = true
|
result.pulse = true
|
||||||
break
|
break
|
||||||
case 'processed_search_result':
|
case 'processed_search_result':
|
||||||
result.name = 'i-lucide-circle-check-big'
|
result.icon = 'i-lucide-circle-check-big'
|
||||||
break
|
break
|
||||||
case 'error':
|
case 'error':
|
||||||
result.name = 'i-lucide-octagon-x'
|
result.icon = 'i-lucide-octagon-x'
|
||||||
|
result.color = 'error'
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@ -66,10 +72,10 @@
|
|||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<UIcon name="i-lucide-circle-dot" />
|
<UIcon name="i-lucide-circle-dot" />
|
||||||
<UButton
|
<UButton
|
||||||
:class="['max-w-90 shrink-0', icon.pulse && 'animate-pulse']"
|
:class="['max-w-90 shrink-0', theme.pulse && 'animate-pulse']"
|
||||||
:icon="icon.name"
|
:icon="theme.icon"
|
||||||
size="sm"
|
size="sm"
|
||||||
:color="selectedNode?.id === node.id ? 'primary' : 'info'"
|
:color="selectedNode?.id === node.id ? 'primary' : theme.color"
|
||||||
:variant="selectedNode?.id === node.id ? 'soft' : 'outline'"
|
:variant="selectedNode?.id === node.id ? 'soft' : 'outline'"
|
||||||
@click="emit('select', node)"
|
@click="emit('select', node)"
|
||||||
>
|
>
|
||||||
|
@ -73,5 +73,8 @@
|
|||||||
"error": "Generate report failed: {0}",
|
"error": "Generate report failed: {0}",
|
||||||
"downloadingFonts": "Downloading necessary fonts, this may take some time...",
|
"downloadingFonts": "Downloading necessary fonts, this may take some time...",
|
||||||
"downloadFontFailed": "Download font failed"
|
"downloadFontFailed": "Download font failed"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"requestBlockedByCORS": "The current API provider may not allow cross-origin requests. Please try a different service provider or contact the provider for support."
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -73,5 +73,8 @@
|
|||||||
"error": "生成报告失败:{0}",
|
"error": "生成报告失败:{0}",
|
||||||
"downloadingFonts": "正在下载必要字体,可能需要较长时间...",
|
"downloadingFonts": "正在下载必要字体,可能需要较长时间...",
|
||||||
"downloadFontFailed": "下载字体失败"
|
"downloadFontFailed": "下载字体失败"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"requestBlockedByCORS": "当前 API 服务可能不允许接口跨域,请换一个服务试试,或者向服务方反馈。"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -110,6 +110,9 @@ export function generateSearchQueries({
|
|||||||
model: useAiModel(),
|
model: useAiModel(),
|
||||||
system: systemPrompt(),
|
system: systemPrompt(),
|
||||||
prompt,
|
prompt,
|
||||||
|
onError({ error }) {
|
||||||
|
throw error
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +162,9 @@ function processSearchResult({
|
|||||||
abortSignal: AbortSignal.timeout(60_000),
|
abortSignal: AbortSignal.timeout(60_000),
|
||||||
system: systemPrompt(),
|
system: systemPrompt(),
|
||||||
prompt,
|
prompt,
|
||||||
|
onError({ error }) {
|
||||||
|
throw error
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +193,9 @@ export function writeFinalReport({
|
|||||||
model: useAiModel(),
|
model: useAiModel(),
|
||||||
system: systemPrompt(),
|
system: systemPrompt(),
|
||||||
prompt: _prompt,
|
prompt: _prompt,
|
||||||
|
onError({ error }) {
|
||||||
|
throw error
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,9 @@ export function generateFeedback({
|
|||||||
model: useAiModel(),
|
model: useAiModel(),
|
||||||
system: systemPrompt(),
|
system: systemPrompt(),
|
||||||
prompt,
|
prompt,
|
||||||
|
onError({ error }) {
|
||||||
|
throw error
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return parseStreamingJson(
|
return parseStreamingJson(
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* So I wrote this script to override the encodings in `@tavily/core` to `o200k_base`
|
* So I wrote this script to override the encodings in `@tavily/core` to `o200k_base`
|
||||||
* and clean up unused js-tiktoken encodings in the build output,
|
* and clean up unused js-tiktoken encodings in the build output,
|
||||||
* making the build output smaller by about 2 MB.
|
* making the build output smaller by about 3 MB.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
|
Reference in New Issue
Block a user