'use client'; import { AlertTriangle, ArrowRightCircle, Bot, CheckCircle2, ClipboardList, FileText, GitBranch, ListChecks, Sparkles, TerminalSquare, ThumbsUp, Users, Wrench, } from 'lucide-react'; import { TaskRuntimeStatusBadge, formatTaskRuntimeTime } from '@/components/task-runtime/TaskRuntimeShared'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent } from '@/components/ui/card'; import { pickAppText } from '@/lib/i18n/core'; import { useAppI18n } from '@/lib/i18n/provider'; import type { TaskRuntimeStatus } from '@/lib/task-runtime'; import type { TaskTimelineCard as TaskTimelineCardView, TaskTimelineCardType } from '@/types'; type Props = { card: TaskTimelineCardView; }; const RUNTIME_STATUSES = new Set(['queued', 'running', 'waiting', 'blocked', 'done', 'error', 'cancelled']); function isRuntimeStatus(status: string): status is TaskRuntimeStatus { return RUNTIME_STATUSES.has(status); } function iconForType(type: TaskTimelineCardType) { switch (type) { case 'task_created': return ClipboardList; case 'plan': return ListChecks; case 'skill': return Sparkles; case 'tool_call': return Wrench; case 'tool_result': return TerminalSquare; case 'next_step': return ArrowRightCircle; case 'agent_team': return Users; case 'agent_progress': return Bot; case 'agent_handoff': return GitBranch; case 'artifact': return FileText; case 'error': return AlertTriangle; case 'result': return CheckCircle2; case 'acceptance': return ThumbsUp; } } function detailsJson(details: Record): string { try { return JSON.stringify(details, null, 2); } catch { return String(details); } } function cardTypeLabel(type: TaskTimelineCardType, locale: 'zh-CN' | 'en-US') { const labels: Record = { task_created: ['任务', 'Task'], plan: ['计划', 'Plan'], skill: ['Skill', 'Skill'], tool_call: ['工具调用', 'Tool call'], tool_result: ['工具结果', 'Tool result'], next_step: ['下一步', 'Next step'], agent_team: ['Agent Team', 'Agent team'], agent_progress: ['Agent', 'Agent'], agent_handoff: ['交接', 'Handoff'], artifact: ['产物', 'Artifact'], error: ['异常', 'Error'], result: ['结果', 'Result'], acceptance: ['验收', 'Acceptance'], }; const label = labels[type]; return pickAppText(locale, label[0], label[1]); } function humanStatus(status: string, locale: 'zh-CN' | 'en-US') { const labels: Record = { open: ['已创建', 'Open'], running: ['执行中', 'Running'], awaiting_acceptance: ['等待验收', 'Awaiting acceptance'], needs_revision: ['需要修改', 'Needs revision'], closed: ['已完成', 'Closed'], abandoned: ['已放弃', 'Abandoned'], accept: ['接受', 'Accepted'], satisfied: ['接受', 'Accepted'], revise: ['请求修改', 'Revision requested'], abandon: ['放弃任务', 'Abandoned'], warning: ['提醒', 'Warning'], }; const label = labels[status]; return label ? pickAppText(locale, label[0], label[1]) : status; } export function TaskTimelineCard({ card }: Props) { const { locale } = useAppI18n(); const Icon = iconForType(card.type); return (

{card.title}

{cardTypeLabel(card.type, locale)}
{card.actorName ? {card.actorName} : null} {formatTaskRuntimeTime(card.createdAt, locale)} {card.runId ? {card.runId.slice(0, 8)} : null}
{card.status ? ( isRuntimeStatus(card.status) ? ( ) : ( {humanStatus(card.status, locale)} ) ) : null}
{card.summary ?

{card.summary}

: null} {card.details ? (
{pickAppText(locale, '详情 JSON', 'Details JSON')}
                  {detailsJson(card.details)}
                
) : null}
); }