'use client';
import { AlertCircle, Bot, BrainCircuit, Loader2, ServerCog, Square } from 'lucide-react';
import type { ProcessEvent, ProcessRun } from '@/types';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { ScrollArea } from '@/components/ui/scroll-area';
import { appActorTypeLabel, appEventKindLabel, appStatusLabel } from '@/lib/i18n/common';
import { pickAppText } from '@/lib/i18n/core';
import { useAppI18n } from '@/lib/i18n/provider';
import { cn } from '@/lib/utils';
function statusTone(status: string) {
if (status === 'done') return 'bg-emerald-500/10 text-emerald-300 border-emerald-500/20';
if (status === 'error') return 'bg-rose-500/10 text-rose-300 border-rose-500/20';
if (status === 'cancelled') return 'bg-zinc-500/10 text-zinc-300 border-zinc-500/20';
if (status === 'waiting') return 'bg-amber-500/10 text-amber-300 border-amber-500/20';
return 'bg-sky-500/10 text-sky-300 border-sky-500/20';
}
function actorIcon(run: ProcessRun) {
if (run.actor_type === 'mcp') return ;
if (run.actor_type === 'system') return ;
return ;
}
export function ProcessLane({
runs,
events,
selectedRunId,
onSelectRun,
onCancelRun,
}: {
runs: ProcessRun[];
events: ProcessEvent[];
selectedRunId: string | null;
onSelectRun: (runId: string) => void;
onCancelRun: (runId: string) => void;
}) {
const { locale } = useAppI18n();
const sortedRuns = [...runs].sort((a, b) => {
const at = new Date(a.started_at).getTime();
const bt = new Date(b.started_at).getTime();
return bt - at;
});
if (sortedRuns.length === 0) {
return null;
}
return (
{pickAppText(locale, '执行过程', 'Execution')}
{pickAppText(locale, '智能体、A2A、MCP 的实时过程', 'Live process stream for agents, A2A, and MCP')}
{pickAppText(locale, `${sortedRuns.length} 个任务`, `${sortedRuns.length} tasks`)}
{sortedRuns.map((run) => {
const runEvents = events
.filter((event) => event.run_id === run.run_id)
.slice(-5)
.reverse();
const isSelected = run.run_id === selectedRunId;
const canCancel =
!run.parent_run_id &&
run.actor_type !== 'mcp' &&
(run.status === 'running' || run.status === 'waiting');
return (
onSelectRun(run.run_id)}
>
{actorIcon(run)}
{run.actor_name}
{run.title}
{appStatusLabel(run.status, locale)}
{canCancel && (
)}
{appActorTypeLabel(run.actor_type, locale)}
{run.source && {run.source}}
{run.parent_run_id && {pickAppText(locale, '子任务', 'Subtask')}}
{run.summary && (
{run.summary}
)}
{runEvents.length === 0 && run.status === 'running' && (
{pickAppText(locale, '等待首个事件...', 'Waiting for the first event...')}
)}
{runEvents.map((event) => (
{appEventKindLabel(event.kind, locale)}
{event.status && {appStatusLabel(event.status, locale)}}
{event.text || pickAppText(locale, '结构化更新', 'Structured update')}
))}
{run.status === 'error' && (
{pickAppText(locale, '此任务执行失败。', 'This task failed.')}
)}
);
})}
);
}