import React, { useState, useEffect, useRef } from 'react'; import './AgentCard.css'; import MarkdownContent from './MarkdownContent'; function getPhaseBadgeClass(phase?: string): string { switch (phase) { case 'starting': return 'badge badge-starting'; case 'diverging': return 'badge badge-diverging'; case 'closing': return 'badge badge-closing'; case 'done': return 'badge badge-done'; default: return 'badge badge-default'; } } const PHASE_LABELS: Record = { starting: '启动', diverging: '辩论', closing: '收敛', done: '完成', }; type RetrievalLogItem = { query?: string; source_name?: string; source_id?: string; source?: string; adopted?: boolean; content?: any[]; content_ids?: string[]; }; type Props = { agentId: string; agentName?: string; dimension?: string; round: number; phase: string; content?: string; thinking?: string; dimensionOutput?: Record; retrievalLog?: RetrievalLogItem[]; retrievalCount?: number; referenceMap?: Record; streaming?: boolean; }; export default function AgentCard({ agentId, agentName, dimension, round, phase, content, thinking, dimensionOutput, retrievalLog, retrievalCount = 0, referenceMap, streaming = false, }: Props): JSX.Element { const [thinkingOpen, setThinkingOpen] = useState(false); const autoOpenedRef = useRef(false); useEffect(() => { if (streaming && thinking && thinking.length > 0 && !autoOpenedRef.current) { setThinkingOpen(true); autoOpenedRef.current = true; } }, [streaming, thinking]); const streamingPhase = streaming ? (content && content.length > 0 ? 'content' : 'thinking') : null; const hasThinking = thinking && thinking.trim().length > 0; const hasRetrieval = retrievalCount > 0 && retrievalLog && retrievalLog.length > 0; const hasDimOutput = dimensionOutput && Object.keys(dimensionOutput).length > 0; return (
{agentName || agentId}
{dimension && ( {dimension} )} 第 {round} 轮 {PHASE_LABELS[phase] || phase} {streaming && ( 生成中 )}
{(hasThinking || streamingPhase === 'thinking') && (
{thinkingOpen && (
{streaming ? ( {thinking} ) : ( )}
)}
)} {(content || streamingPhase === 'content') && (
分析内容
{streaming ? (
{content} {streamingPhase === 'content' && }
) : ( )}
)} {hasDimOutput && (
维度输出
{Object.entries(dimensionOutput).map(([key, value]) => (
{key}
))}
)} {hasRetrieval && (
检索信息 ({retrievalCount})
{retrievalLog.map((log, logIdx) => (
"{log.query}" {(log.source_name || log.source_id || log.source) && ( {log.source_name || log.source_id || log.source} )} {log.adopted !== undefined && ( {log.adopted ? '已采用' : '未采用'} )}
{log.content && log.content.map((item, itemIdx) => { const refNum = log.content_ids ? log.content_ids[itemIdx] : null; const refKey = refNum ? Object.entries(referenceMap || {}).find(([, v]) => v === refNum)?.[0] : null; return (
{refKey && [{refKey}]}
{typeof item === 'string' ? (item.length > 200 ? item.slice(0, 200) + '…' : item) : JSON.stringify(item).slice(0, 200)}
); })}
))}
)}
); }