import * as React from 'react' import { Ban, Braces, Clock3, Coins, RotateCw } from 'lucide-react' import { toast } from 'sonner' import { AppEmptyState } from '@/components/app/AppEmptyState' import { AppPage } from '@/components/app/AppPage' import { AppPageHeader } from '@/components/app/AppPageHeader' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Separator } from '@/components/ui/separator' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { StatusBadge } from '@/features/ai-platform/status' import { formatDateTime } from '@/lib/format' import { cn } from '@/lib/utils' import { cancelAgentRun, getAgentRun } from './api' import type { AgentRunDetail } from './types' function JsonBlock({ value }: { value: unknown }) { return
{JSON.stringify(value, null, 2)}
} export function AgentRunDetailPage({ publicId }: { publicId: string }) { const [run, setRun] = React.useState(null) const [selectedStepId, setSelectedStepId] = React.useState(null) const [error, setError] = React.useState('') const load = React.useCallback(async () => { try { const next = await getAgentRun(publicId); setRun(next); setSelectedStepId((current) => current ?? next.steps[0]?.id ?? null); setError('') } catch (reason) { setError(reason instanceof Error ? reason.message : '加载运行详情失败') } }, [publicId]) React.useEffect(() => { void load() }, [load]) React.useEffect(() => { if (!run || !['queued', 'running'].includes(run.status)) return const timer = window.setTimeout(() => void load(), 1200) return () => window.clearTimeout(timer) }, [load, run]) async function cancel() { try { setRun(await cancelAgentRun(publicId)); toast.success('取消请求已提交') } catch (reason) { toast.error(reason instanceof Error ? reason.message : '取消失败') } } if (error) return }> if (!run) return }>
const selected = run.steps.find((step) => step.id === selectedStepId) ?? null return {run.sandbox ? 草稿沙箱 : 发布 v{run.agent_version}}
} actions={<>{['queued', 'running'].includes(run.status) ? : null}} />}> {['queued', 'running'].includes(run.status) ? {run.progress_message || 'Agent 正在运行'}当前步骤:{run.current_step || '等待调度'}{run.retry_count ? `;已重试 ${run.retry_count} 次` : ''} : null} {run.error_message ? {run.error_code || '运行失败'}{run.error_message} : null}
执行脊柱{run.steps.length}/{run.total_steps} 个步骤已创建
    {run.steps.map((step) =>
  1. {step.order < run.steps.length ? : null}
  2. )}
{selected ? `${selected.order}. ${selected.name}` : '运行输入与最终输出'}{selected ? `${selected.code} · ${selected.model_display_name}(${selected.model_capability})` : '尚未生成步骤记录'}输入输出调用尝试{selected?.attempts.length ? selected.attempts.map((attempt) =>
{attempt.attempt_type}
{attempt.input_tokens + attempt.output_tokens} tokens · {attempt.duration_ms} ms
{attempt.validation_error ? 结构校验错误{attempt.validation_error} : null}
) : }
运行指标{selected ? <> : null}配置快照历史记录不受后续配置修改影响{run.final_output !== null ? 最终结构化输出 : null}
} function Metric({ icon: Icon, label, value }: { icon: typeof Clock3; label: string; value: string }) { return
{label}{value}
}