gMAS / web_ui /frontend /src /components /execution /ResultViewer.tsx
Артём Боярских
chore: initial commit
3193174
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
import { ScrollArea } from "@/components/ui/scroll-area";
import { CheckCircle2, XCircle, Clock, Zap } from "lucide-react";
import type { StreamEvent } from "@/types/execution";
interface ResultViewerProps {
status: string;
finalAnswer: string | null;
totalTokens: number;
totalTime: number;
events: StreamEvent[];
error: string | null;
}
export function ResultViewer({
status,
finalAnswer,
totalTokens,
totalTime,
events,
error,
}: ResultViewerProps) {
const agentOutputs = events.filter((e) => e.event_type === "agent_output");
return (
<ScrollArea className="h-full">
<div className="space-y-3 p-3">
{/* Status summary */}
<div className="flex items-center gap-2">
{status === "completed" && <CheckCircle2 className="h-4 w-4 text-green-500" />}
{status === "error" && <XCircle className="h-4 w-4 text-red-500" />}
{status === "running" && <Clock className="h-4 w-4 text-blue-500 animate-pulse" />}
<span className="text-sm font-medium capitalize">{status}</span>
{totalTokens > 0 && (
<Badge variant="secondary" className="text-xs gap-1">
<Zap className="h-3 w-3" />
{totalTokens} tokens
</Badge>
)}
{totalTime > 0 && (
<Badge variant="secondary" className="text-xs gap-1">
<Clock className="h-3 w-3" />
{totalTime.toFixed(1)}s
</Badge>
)}
</div>
{error && (
<div className="rounded-md border border-red-200 bg-red-50 dark:bg-red-950 p-3">
<p className="text-sm text-red-700 dark:text-red-300">{error}</p>
</div>
)}
{/* Final answer */}
{finalAnswer && (
<Card>
<CardHeader className="py-3 px-4">
<CardTitle className="text-sm">Final Answer</CardTitle>
</CardHeader>
<CardContent className="px-4 pb-4 pt-0">
<p className="text-sm whitespace-pre-wrap">{finalAnswer}</p>
</CardContent>
</Card>
)}
{/* Agent outputs */}
{agentOutputs.length > 0 && (
<>
<Separator />
<h4 className="text-sm font-medium">Agent Responses</h4>
{agentOutputs.map((event, i) => (
<Card key={i}>
<CardHeader className="py-2 px-4">
<div className="flex items-center justify-between">
<CardTitle className="text-xs font-medium">
{event.agent_name || event.agent_id}
</CardTitle>
{event.tokens_used && (
<span className="text-[10px] text-muted-foreground">
{event.tokens_used} tokens
</span>
)}
</div>
</CardHeader>
<CardContent className="px-4 pb-3 pt-0">
<p className="text-xs whitespace-pre-wrap text-muted-foreground">
{event.content?.slice(0, 500)}
{(event.content?.length ?? 0) > 500 ? "..." : ""}
</p>
</CardContent>
</Card>
))}
</>
)}
</div>
</ScrollArea>
);
}