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) => - {step.order < run.steps.length ? : null}
)}
{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}
}