({ run }: AgentRunCardProps)
| 40 | }; |
| 41 | |
| 42 | export function AgentRunCard({ run }: AgentRunCardProps) { |
| 43 | const normalizedBlocks = run.thinkingBlocks |
| 44 | .map((b) => b.trim()) |
| 45 | .filter((b) => b.length > 0); |
| 46 | const liveStream = run.streamingText.trim(); |
| 47 | |
| 48 | // Get model name from agent config or default provider |
| 49 | const { agentConfigs } = useAgentStore(); |
| 50 | const { providers, selectedModelId } = useSettingsStore(); |
| 51 | const agentConfig = agentConfigs.find((c) => c.agentType === run.agentType); |
| 52 | const modelName = agentConfig?.modelId |
| 53 | ?? selectedModelId |
| 54 | ?? providers.find((p) => p.isDefault)?.model |
| 55 | ?? null; |
| 56 | |
| 57 | const duration = formatDuration(run.startedAt, run.completedAt); |
| 58 | const isRunning = run.status === 'running'; |
| 59 | |
| 60 | const events = useMemo<TimelineEventItem[]>(() => { |
| 61 | const list: TimelineEventItem[] = []; |
| 62 | |
| 63 | // Thinking blocks (collapsed, from previous iterations) |
| 64 | normalizedBlocks.forEach((block, i) => { |
| 65 | list.push({ kind: 'thinking', key: `${run.id}-thinking-${i}`, content: block }); |
| 66 | }); |
| 67 | |
| 68 | // Tool calls |
| 69 | run.toolCalls.forEach((tool) => { |
| 70 | if (tool.status === 'failed') { |
| 71 | list.push({ kind: 'tool_failed', key: `${run.id}-${tool.id}-failed`, tool }); |
| 72 | } else { |
| 73 | list.push({ kind: 'tool_execution', key: `${run.id}-${tool.id}-exec`, tool }); |
| 74 | } |
| 75 | }); |
| 76 | |
| 77 | // Live streaming text — show as result (markdown rendered) while generating |
| 78 | if (run.status === 'running' && liveStream.length > 0) { |
| 79 | list.push({ kind: 'result', key: `${run.id}-streaming`, content: liveStream }); |
| 80 | } |
| 81 | |
| 82 | // Final output |
| 83 | if (run.status === 'completed' && run.output) { |
| 84 | list.push({ kind: 'result', key: `${run.id}-result`, content: run.output }); |
| 85 | } |
| 86 | |
| 87 | if (run.status === 'failed' && run.error) { |
| 88 | list.push({ kind: 'result', key: `${run.id}-result-failed`, content: run.error }); |
| 89 | } |
| 90 | |
| 91 | return list; |
| 92 | }, [ |
| 93 | run.id, |
| 94 | run.output, |
| 95 | run.error, |
| 96 | run.status, |
| 97 | run.toolCalls, |
| 98 | normalizedBlocks, |
| 99 | liveStream, |
nothing calls this directly
no test coverage detected