Skip to content

Commit 7845220

Browse files
authored
fix(frontend): multiple fixes for Task page (#118)
* fix: clarification format supports Markdown * fix: fix error message display * fix: missing task data when switching tasks
1 parent b6c1a5f commit 7845220

File tree

7 files changed

+315
-350
lines changed

7 files changed

+315
-350
lines changed

frontend/src/app/task/[id]/page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,6 @@ function TaskDetailContent() {
374374
showProcessView={true}
375375
isVirtual
376376
taskStatus={state.currentTask?.status}
377-
isPlanning={isPlanning}
378377
/>
379378
)}
380379
</>

frontend/src/components/chat/ChatMessage.tsx

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,27 @@ export interface ChatMessageProps {
6060
showProcessView?: boolean;
6161
isVirtual?: boolean;
6262
taskStatus?: string;
63-
isPlanning?: boolean;
6463
}
6564

66-
function GeneratingIndicator({latestTitle, taskStatus, isPlanning}: {latestTitle?: string, taskStatus?: string, isPlanning?: boolean}) {
65+
function GeneratingIndicator({latestTitle, taskStatus, errorMessage}: {latestTitle?: string, taskStatus?: string, errorMessage?: string}) {
6766
const { t } = useI18n();
67+
68+
if (taskStatus === 'failed' && errorMessage) {
69+
return (
70+
<div className="py-3 text-sm leading-relaxed text-red-500">
71+
<span>{errorMessage}</span>
72+
</div>
73+
);
74+
}
75+
6876
const displayTitle = taskStatus === 'paused'
6977
? t("common.taskPaused")
70-
: (isPlanning ? t("common.planning") : (latestTitle ? `${latestTitle} ` : t("common.planning")));
78+
: (latestTitle ? `${latestTitle} ` : t("common.planning"));
7179

7280
return (
7381
<div className="py-3 text-sm leading-relaxed text-muted-foreground flex items-center">
7482
<span>{displayTitle}</span>
75-
{taskStatus !== 'paused' && (
83+
{!["failed", "paused"].includes(taskStatus || "") && (
7684
<span className="ml-1 inline-flex items-end gap-1">
7785
<span className="dot" />
7886
<span className="dot" />
@@ -117,7 +125,6 @@ export function ChatMessage({
117125
traceEvents,
118126
showProcessView,
119127
taskStatus,
120-
isPlanning,
121128
}: ChatMessageProps) {
122129
const isUser = role === "user";
123130
const { t } = useI18n();
@@ -132,27 +139,7 @@ export function ChatMessage({
132139
if (!e) return "";
133140
const type = e.event_type || "";
134141
const action = (typeof e.data?.action === "string" ? (e.data!.action as string) : "") || type;
135-
const map: Record<string, string> = {
136-
"dag_step_start": "agent.logs.event.actions.stepStart",
137-
"dag_step_end": "agent.logs.event.actions.stepCompleted",
138-
"dag_step_failed": "agent.logs.event.actions.stepFailed",
139-
"llm_call_start": "agent.logs.event.actions.llmStart",
140-
"llm_call_end": "agent.logs.event.actions.llmCompleted",
141-
"llm_call_failed": "agent.logs.event.actions.llmFailed",
142-
"tool_execution_start": "agent.logs.event.actions.toolStart",
143-
"tool_execution_end": "agent.logs.event.actions.toolCompleted",
144-
"tool_execution_failed": "agent.logs.event.actions.toolFailed",
145-
"task_start_memory_retrieve": "agent.logs.event.actions.memoryQuery",
146-
"task_end_memory_retrieve": "agent.logs.event.actions.memoryQueryCompleted",
147-
"task_start_memory_generate": "agent.logs.event.actions.memoryGenerateStart",
148-
"task_end_memory_generate": "agent.logs.event.actions.memoryGenerateCompleted",
149-
"task_start_memory_store": "agent.logs.event.actions.memoryStoreStart",
150-
"task_end_memory_store": "agent.logs.event.actions.memoryStoreCompleted",
151-
"action_start_compact": "agent.logs.event.actions.compactStart",
152-
"action_end_compact": "agent.logs.event.actions.compactCompleted",
153-
};
154-
const key = map[action] || map[type];
155-
return key ? t(key) : (action || t("common.executing"));
142+
return t(`agent.logs.event.actions.${e.event_type}`) || action || t("common.executing");
156143
};
157144

158145
const latestTitle = getEventTitle(
@@ -161,6 +148,17 @@ export function ChatMessage({
161148
: undefined
162149
);
163150

151+
let errorMessage = "";
152+
if (taskStatus === "failed" && Array.isArray(traceEvents)) {
153+
for (let i = traceEvents.length - 1; i >= 0; i--) {
154+
const event = traceEvents[i];
155+
if (['trace_error', 'task_failed', 'react_task_failed', 'dag_step_failed', 'agent_error'].includes(event.event_type || '')) {
156+
errorMessage = (event.data?.error as string) || (event.data?.message as string) || "";
157+
if (errorMessage) break;
158+
}
159+
}
160+
}
161+
164162
return (
165163
<div className="w-full space-y-2 animate-fade-in">
166164
{shouldShowProcess && !isUser && (
@@ -215,7 +213,7 @@ export function ChatMessage({
215213
<div className="text-sm leading-relaxed">{content}</div>
216214
)
217215
) : (
218-
!isUser && <GeneratingIndicator latestTitle={latestTitle} taskStatus={taskStatus} isPlanning={isPlanning} />
216+
!isUser && <GeneratingIndicator latestTitle={latestTitle} taskStatus={taskStatus} errorMessage={errorMessage} />
219217
)}
220218
</div>
221219
</div>

frontend/src/components/log/log-event.tsx

Lines changed: 8 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
import { useState } from "react"
44
import { Card } from "@/components/ui/card"
55
import { Badge } from "@/components/ui/badge"
6-
import { Button } from "@/components/ui/button"
76
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
87
import { JSONSyntaxHighlighter } from "@/components/ui/json-syntax-highlighter"
9-
import { ChevronDown, ChevronRight, Clock, Bot, Wrench, Play, CheckCircle, XCircle, Info, Brain, Search, Sparkles } from "lucide-react"
8+
import { ChevronDown, ChevronRight, Bot, Wrench, Play, CheckCircle, XCircle, Info, Brain, Search, Sparkles } from "lucide-react"
109
import { MessagesPreview } from "./messages-preview"
1110
import { useI18n } from "@/contexts/i18n-context"
1211

@@ -25,49 +24,12 @@ interface LogEventProps {
2524
// Common log summary component
2625
function LogSummary({ event }: LogEventProps) {
2726
const data = event.data as Record<string, any> || {}
28-
const action = data.action || event.event_type || null
2927
const stepName = data.step_name || data.name || ''
3028
const { t } = useI18n()
3129

3230
// Select icon and color based on action type
3331
const getActionConfig = () => {
3432
const configs: Record<string, { icon: React.ReactNode, color: string, labelKey: string }> = {
35-
"步骤开始": { icon: <Play className="h-4 w-4" />, color: "text-blue-500", labelKey: "agent.logs.event.labels.start" },
36-
"步骤完成": { icon: <CheckCircle className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.completed" },
37-
"步骤失败": { icon: <XCircle className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.failed" },
38-
"LLM调用开始": { icon: <Bot className="h-4 w-4" />, color: "text-purple-500", labelKey: "agent.logs.event.labels.llmCall" },
39-
"LLM调用完成": { icon: <Bot className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.llmCompleted" },
40-
"LLM调用失败": { icon: <Bot className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.llmFailed" },
41-
"工具调用开始": { icon: <Wrench className="h-4 w-4" />, color: "text-orange-500", labelKey: "agent.logs.event.labels.toolCall" },
42-
"工具调用完成": { icon: <Wrench className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.toolCompleted" },
43-
"工具调用失败": { icon: <Wrench className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.toolFailed" },
44-
"记忆生成开始": { icon: <Brain className="h-4 w-4" />, color: "text-purple-500", labelKey: "agent.logs.event.labels.memoryGenerate" },
45-
"记忆生成完成": { icon: <Brain className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.memoryGenerate" },
46-
"记忆存储开始": { icon: <Brain className="h-4 w-4" />, color: "text-orange-500", labelKey: "agent.logs.event.labels.memoryStore" },
47-
"记忆存储完成": { icon: <Brain className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.memoryStore" },
48-
"记忆查询": { icon: <Search className="h-4 w-4" />, color: "text-blue-500", labelKey: "agent.logs.event.labels.memoryQuery" },
49-
"记忆查询完成": { icon: <Search className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.memoryQuery" },
50-
"上下文压缩开始": { icon: <span className="text-lg">🗜️</span>, color: "text-blue-500", labelKey: "agent.logs.event.labels.compactStart" },
51-
"上下文压缩完成": { icon: <span className="text-lg">🗜️</span>, color: "text-green-500", labelKey: "agent.logs.event.labels.compactCompleted" },
52-
// English action strings (i18n-en)
53-
"Step Start": { icon: <Play className="h-4 w-4" />, color: "text-blue-500", labelKey: "agent.logs.event.labels.start" },
54-
"Step Completed": { icon: <CheckCircle className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.completed" },
55-
"Step Failed": { icon: <XCircle className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.failed" },
56-
"LLM Call Start": { icon: <Bot className="h-4 w-4" />, color: "text-purple-500", labelKey: "agent.logs.event.labels.llmCall" },
57-
"LLM Call Completed": { icon: <Bot className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.llmCompleted" },
58-
"LLM Call Failed": { icon: <Bot className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.llmFailed" },
59-
"Tool Call Start": { icon: <Wrench className="h-4 w-4" />, color: "text-orange-500", labelKey: "agent.logs.event.labels.toolCall" },
60-
"Tool Call Completed": { icon: <Wrench className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.toolCompleted" },
61-
"Tool Call Failed": { icon: <Wrench className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.toolFailed" },
62-
"Memory Generate Start": { icon: <Brain className="h-4 w-4" />, color: "text-purple-500", labelKey: "agent.logs.event.labels.memoryGenerate" },
63-
"Memory Generate Completed": { icon: <Brain className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.memoryGenerate" },
64-
"Memory Store Start": { icon: <Brain className="h-4 w-4" />, color: "text-orange-500", labelKey: "agent.logs.event.labels.memoryStore" },
65-
"Memory Store Completed": { icon: <Brain className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.memoryStore" },
66-
"Memory Query": { icon: <Search className="h-4 w-4" />, color: "text-blue-500", labelKey: "agent.logs.event.labels.memoryQuery" },
67-
"Memory Query Completed": { icon: <Search className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.memoryQuery" },
68-
"Context Compact Start": { icon: <span className="text-lg">🗜️</span>, color: "text-blue-500", labelKey: "agent.logs.event.labels.compactStart" },
69-
"Context Compact Completed": { icon: <span className="text-lg">🗜️</span>, color: "text-green-500", labelKey: "agent.logs.event.labels.compactCompleted" },
70-
// Event type keys (stable codes)
7133
"dag_step_start": { icon: <Play className="h-4 w-4" />, color: "text-blue-500", labelKey: "agent.logs.event.labels.start" },
7234
"dag_step_end": { icon: <CheckCircle className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.completed" },
7335
"dag_step_failed": { icon: <XCircle className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.failed" },
@@ -89,76 +51,14 @@ function LogSummary({ event }: LogEventProps) {
8951
"skill_select_end": { icon: <Sparkles className="h-4 w-4" />, color: "text-green-500", labelKey: "agent.logs.event.labels.skillSelectEnd" },
9052
}
9153

92-
const config = configs[action]
54+
const config = configs[event.event_type]
9355
if (!config) {
9456
console.log('🔴🔴🔴 Unknown action 🔴🔴🔴', event)
9557
return { icon: <Info className="h-4 w-4" />, color: "text-red-500", labelKey: "agent.logs.event.labels.unknown" }
9658
}
9759
return config
9860
}
9961

100-
const getActionText = (act: string) => {
101-
const map: Record<string, string> = {
102-
"步骤开始": "agent.logs.event.actions.stepStart",
103-
"步骤完成": "agent.logs.event.actions.stepCompleted",
104-
"步骤失败": "agent.logs.event.actions.stepFailed",
105-
"LLM调用开始": "agent.logs.event.actions.llmStart",
106-
"LLM调用完成": "agent.logs.event.actions.llmCompleted",
107-
"LLM调用失败": "agent.logs.event.actions.llmFailed",
108-
"工具调用开始": "agent.logs.event.actions.toolStart",
109-
"工具调用完成": "agent.logs.event.actions.toolCompleted",
110-
"工具调用失败": "agent.logs.event.actions.toolFailed",
111-
"记忆生成开始": "agent.logs.event.actions.memoryGenerateStart",
112-
"记忆生成完成": "agent.logs.event.actions.memoryGenerateCompleted",
113-
"记忆存储开始": "agent.logs.event.actions.memoryStoreStart",
114-
"记忆存储完成": "agent.logs.event.actions.memoryStoreCompleted",
115-
"记忆查询": "agent.logs.event.actions.memoryQuery",
116-
"记忆查询完成": "agent.logs.event.actions.memoryQueryCompleted",
117-
"上下文压缩开始": "agent.logs.event.actions.compactStart",
118-
"上下文压缩完成": "agent.logs.event.actions.compactCompleted",
119-
// English action strings (i18n-en)
120-
"Step Start": "agent.logs.event.actions.stepStart",
121-
"Step Completed": "agent.logs.event.actions.stepCompleted",
122-
"Step Failed": "agent.logs.event.actions.stepFailed",
123-
"LLM Call Start": "agent.logs.event.actions.llmStart",
124-
"LLM Call Completed": "agent.logs.event.actions.llmCompleted",
125-
"LLM Call Failed": "agent.logs.event.actions.llmFailed",
126-
"Tool Call Start": "agent.logs.event.actions.toolStart",
127-
"Tool Call Completed": "agent.logs.event.actions.toolCompleted",
128-
"Tool Call Failed": "agent.logs.event.actions.toolFailed",
129-
"Memory Generate Start": "agent.logs.event.actions.memoryGenerateStart",
130-
"Memory Generate Completed": "agent.logs.event.actions.memoryGenerateCompleted",
131-
"Memory Store Start": "agent.logs.event.actions.memoryStoreStart",
132-
"Memory Store Completed": "agent.logs.event.actions.memoryStoreCompleted",
133-
"Memory Query": "agent.logs.event.actions.memoryQuery",
134-
"Memory Query Completed": "agent.logs.event.actions.memoryQueryCompleted",
135-
"Context Compact Start": "agent.logs.event.actions.compactStart",
136-
"Context Compact Completed": "agent.logs.event.actions.compactCompleted",
137-
// Event type keys (stable codes)
138-
"dag_step_start": "agent.logs.event.actions.stepStart",
139-
"dag_step_end": "agent.logs.event.actions.stepCompleted",
140-
"dag_step_failed": "agent.logs.event.actions.stepFailed",
141-
"llm_call_start": "agent.logs.event.actions.llmStart",
142-
"llm_call_end": "agent.logs.event.actions.llmCompleted",
143-
"llm_call_failed": "agent.logs.event.actions.llmFailed",
144-
"tool_execution_start": "agent.logs.event.actions.toolStart",
145-
"tool_execution_end": "agent.logs.event.actions.toolCompleted",
146-
"tool_execution_failed": "agent.logs.event.actions.toolFailed",
147-
"task_start_memory_retrieve": "agent.logs.event.actions.memoryQuery",
148-
"task_end_memory_retrieve": "agent.logs.event.actions.memoryQueryCompleted",
149-
"task_start_memory_generate": "agent.logs.event.actions.memoryGenerateStart",
150-
"task_end_memory_generate": "agent.logs.event.actions.memoryGenerateCompleted",
151-
"task_start_memory_store": "agent.logs.event.actions.memoryStoreStart",
152-
"task_end_memory_store": "agent.logs.event.actions.memoryStoreCompleted",
153-
"action_start_compact": "agent.logs.event.actions.compactStart",
154-
"action_end_compact": "agent.logs.event.actions.compactCompleted",
155-
"skill_select_start": "agent.logs.event.actions.skillSelectStart",
156-
"skill_select_end": "agent.logs.event.actions.skillSelectEnd",
157-
}
158-
const key = map[act]
159-
return key ? t(key) : act
160-
}
161-
16262
const config = getActionConfig()
16363
const { formatTime } = require('@/lib/time-utils')
16464

@@ -168,7 +68,7 @@ function LogSummary({ event }: LogEventProps) {
16868
<div className="flex items-center justify-between">
16969
<div className="flex items-center gap-2">
17070
<span className={config.color}>{config.icon}</span>
171-
<span className="text-sm font-medium">{getActionText(action)}</span>
71+
<span className="text-sm font-medium">{t(`agent.logs.event.actions.${event.event_type}`)}</span>
17272
</div>
17373
<div className="flex items-center gap-2">
17474
<Badge variant="outline" className="text-xs border-muted-foreground/30">
@@ -562,17 +462,16 @@ export function LogEvent({ event }: LogEventProps) {
562462
// Select details component based on action type
563463
const getDetailsComponent = () => {
564464
const type = event.event_type || ''
565-
const actLower = typeof action === 'string' ? action.toLowerCase() : ''
566465

567-
if (actLower.includes('llm调用') || actLower.includes('llm') || type.includes('llm_call')) {
466+
if (type.includes('llm_call')) {
568467
return <LLMCallDetails data={data} />
569-
} else if (actLower.includes('工具调用') || actLower.includes('tool') || type.includes('tool_execution')) {
468+
} else if (type.includes('tool_execution')) {
570469
return <ToolCallDetails data={data} />
571-
} else if (actLower.includes('上下文压缩') || actLower.includes('compact') || type.includes('compact')) {
470+
} else if (type.includes('compact')) {
572471
return <CompactDetails data={data} />
573-
} else if (actLower.includes('记忆查询') || actLower.includes('memory query') || type.includes('memory_retrieve')) {
472+
} else if (type.includes('memory_retrieve')) {
574473
return <MemoryQueryDetails data={data} />
575-
} else if (actLower.includes('skill') || type.includes('skill_select')) {
474+
} else if (type.includes('skill_select')) {
576475
return <SkillSelectDetails data={data} />
577476
} else {
578477
return <GenericDetails data={data} />

0 commit comments

Comments
 (0)