fix: show errors in execution details

This commit is contained in:
Iams4kura
2026-08-26 11:33:12 +08:00
committed by ulleo
parent a2d1a9d423
commit 6396042795
5 changed files with 124 additions and 9 deletions
+2 -1
View File
@@ -7,6 +7,7 @@ const props = defineProps<{
recordId?: number
duration?: number | undefined
totalTokens?: number | undefined
error?: string
}>()
const chatConfig = useChatConfigStore()
const showLogBtn = chatConfig.getShowLog
@@ -28,7 +29,7 @@ function getLogList() {
{{ $t('parameter.execution_details') }}
</div>
</div>
<ExecutionDetails ref="executionDetailsRef"></ExecutionDetails>
<ExecutionDetails ref="executionDetailsRef" :error="error"></ExecutionDetails>
</template>
<style scoped lang="less">
+27 -7
View File
@@ -17,6 +17,10 @@ import LogChooseTable from './execution-component/LogChooseTable.vue'
import LogGeneratePicture from './execution-component/LogGeneratePicture.vue'
import LogWithAi from '@/views/chat/execution-component/LogWithAi.vue'
defineProps<{
error?: string
}>()
const { t } = useI18n()
const logHistory = ref<ChatLogHistory>({})
const dialogFormVisible = ref(false)
@@ -113,13 +117,29 @@ defineExpose({
</div>
</div>
<div v-if="expandIds.includes(index)" class="content">
<LogTerm v-if="ele.operate_key === 'FILTER_TERMS'" :item="ele" />
<LogSQLSample v-else-if="ele.operate_key === 'FILTER_SQL_EXAMPLE'" :item="ele" />
<LogCustomPrompt v-else-if="ele.operate_key === 'FILTER_CUSTOM_PROMPT'" :item="ele" />
<LogChooseTable v-else-if="ele.operate_key === 'CHOOSE_TABLE'" :item="ele" />
<LogDataQuery v-else-if="ele.operate_key === 'EXECUTE_SQL'" :item="ele" />
<LogGeneratePicture v-else-if="ele.operate_key === 'GENERATE_PICTURE'" :item="ele" />
<LogWithAi v-else :item="ele" />
<LogTerm v-if="ele.operate_key === 'FILTER_TERMS'" :item="ele" :error="error" />
<LogSQLSample
v-else-if="ele.operate_key === 'FILTER_SQL_EXAMPLE'"
:item="ele"
:error="error"
/>
<LogCustomPrompt
v-else-if="ele.operate_key === 'FILTER_CUSTOM_PROMPT'"
:item="ele"
:error="error"
/>
<LogChooseTable
v-else-if="ele.operate_key === 'CHOOSE_TABLE'"
:item="ele"
:error="error"
/>
<LogDataQuery v-else-if="ele.operate_key === 'EXECUTE_SQL'" :item="ele" :error="error" />
<LogGeneratePicture
v-else-if="ele.operate_key === 'GENERATE_PICTURE'"
:item="ele"
:error="error"
/>
<LogWithAi v-else :item="ele" :error="error" />
</div>
</div>
</div>
@@ -51,7 +51,7 @@ const recordsBeforeCurrentQuestion = computed(() =>
<template v-if="item.error">
{{ error }}
</template>
<div class="item-list flex-gap-fallback flex-col">
<div v-else class="item-list flex-gap-fallback flex-col">
<div class="inner-title">{{ t('chat.log_system') }}</div>
<div class="inner-item flex-gap-fallback flex-col">
<div class="inner-item-title">
+3
View File
@@ -244,6 +244,7 @@
:record-id="message.record?.id"
:duration="message.record?.duration"
:total-tokens="message.record?.total_tokens"
:error="message.record?.error"
/>
<ChatToolBar v-if="!message.isTyping" :message="message">
<div class="tool-btns">
@@ -339,6 +340,7 @@
:record-id="message.record?.id"
:duration="message.record?.duration"
:total-tokens="message.record?.total_tokens"
:error="message.record?.error"
/>
<ChatToolBar v-if="!message.isTyping" :message="message" />
</template>
@@ -366,6 +368,7 @@
:record-id="message.record?.id"
:duration="message.record?.duration"
:total-tokens="message.record?.total_tokens"
:error="message.record?.error"
/>
<ChatToolBar v-if="!message.isTyping" :message="message" />
</template>
+91
View File
@@ -0,0 +1,91 @@
"""Regression tests for error messages in chat execution details."""
import re
import unittest
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[1]
CHAT_DIR = PROJECT_ROOT / "frontend" / "src" / "views" / "chat"
COMPONENT_DIR = CHAT_DIR / "execution-component"
LOG_COMPONENTS = (
"LogChooseTable",
"LogCustomPrompt",
"LogDataQuery",
"LogGeneratePicture",
"LogSQLSample",
"LogTerm",
"LogWithAi",
)
def read_source(path: Path) -> str:
return path.read_text(encoding="utf-8")
class ExecutionErrorDetailsTestCase(unittest.TestCase):
"""Ensure the record error reaches every failed execution step."""
def test_chat_view_passes_record_error_to_token_time(self) -> None:
source = read_source(CHAT_DIR / "index.vue")
token_time_tags = re.findall(r"<ChatTokenTime\b.*?/>", source, re.DOTALL)
self.assertGreater(len(token_time_tags), 0)
for tag in token_time_tags:
with self.subTest(tag=tag):
self.assertIn(':error="message.record?.error"', tag)
def test_token_time_forwards_error_to_execution_details(self) -> None:
source = read_source(CHAT_DIR / "ChatTokenTime.vue")
self.assertRegex(
source,
re.compile(r"defineProps<\{.*?error\?: string.*?\}>\(\)", re.DOTALL),
)
execution_details_tag = re.search(
r"<ExecutionDetails\b.*?</ExecutionDetails>", source, re.DOTALL
)
self.assertIsNotNone(execution_details_tag)
self.assertIn(':error="error"', execution_details_tag.group(0))
def test_execution_details_forwards_error_to_log_components(self) -> None:
source = read_source(CHAT_DIR / "ExecutionDetails.vue")
self.assertRegex(
source,
re.compile(r"defineProps<\{.*?error\?: string.*?\}>\(\)", re.DOTALL),
)
for component in LOG_COMPONENTS:
with self.subTest(component=component):
component_tag = re.search(rf"<{component}\b.*?/>", source, re.DOTALL)
self.assertIsNotNone(component_tag)
self.assertIn(':error="error"', component_tag.group(0))
def test_log_components_render_the_forwarded_error(self) -> None:
for component in LOG_COMPONENTS:
with self.subTest(component=component):
source = read_source(COMPONENT_DIR / f"{component}.vue")
error_branch = re.search(
r'<template v-if="item\.error">\s*(.*?)\s*</template>',
source,
re.DOTALL,
)
self.assertIsNotNone(error_branch)
self.assertIn("{{ error }}", error_branch.group(1))
def test_ai_log_skips_normal_content_after_an_error(self) -> None:
source = read_source(COMPONENT_DIR / "LogWithAi.vue")
self.assertRegex(
source,
re.compile(
r'<template v-if="item\.error">.*?</template>\s*'
r'<div v-else class="item-list flex-gap-fallback flex-col">',
re.DOTALL,
),
)
if __name__ == "__main__":
unittest.main()