Add event-driven reporting and durable failure recovery hooks

This commit is contained in:
aiagent
2026-10-19 03:13:33 -07:00
parent 579dece104
commit a4cf70d82b
18 changed files with 711 additions and 8 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ export type NodeMetric = { memory_used_percent?: number; memory_total_bytes?: nu
export type Mount = { mount_target: string; used_percent?: number; total_bytes?: number; available_bytes?: number }
export type SchedulerData = { count?: number; by_state?: Record<string, number>; queues?: { name: string; state: string; pend?: number; run?: number }[] }
export type Metrics = { sampled_at?: number; status?: string; message?: string; data?: { status?: string; message?: string; collected_at?: string; nodes?: Sample<NodeMetric>[]; storage?: Sample<Mount[]>[]; schedulers?: Record<string, Record<string, Sample<SchedulerData>>> } }
export type State = { config?: { title?: string }; title?: string; primary_session_id?: string; tasks: Task[]; sessions: Session[]; events: Event[]; requests: { id: string; name: string; status: string }[]; metrics?: Metrics; updated?: number }
export type State = { hooks?: { pending_notifications: number; active_firing: number; recent: { source: string; summary: string; status: string; severity: string }[] }; config?: { title?: string }; title?: string; primary_session_id?: string; tasks: Task[]; sessions: Session[]; events: Event[]; requests: { id: string; name: string; status: string }[]; metrics?: Metrics; updated?: number }
export const statusLabels: Record<string, string> = { queued: '排队', running: '进行中', waiting: '等待', blocked: '受阻', completed: '已完成', failed: '失败', cancelled: '已取消', claimed: '处理中', delivered: '已送达', uncertain: '待人工核查' }
export const phaseLabels: Record<string, string> = { planning: '规划', implementation: '实现', validation: '验证', integration: '集成', done: '完成' }
export function date(value?: string | number) { return value == null ? '暂无' : new Date(typeof value === 'number' ? value * 1000 : value).toLocaleString('zh-CN') }
+1
View File
@@ -15,6 +15,7 @@ export default function Overview() {
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">{stats.map(s => <Card key={s.label}><CardContent className="flex items-start justify-between pt-6"><div><p className="text-sm text-muted-foreground">{s.label}</p><p className="mt-2 text-3xl font-semibold tabular-nums">{s.value}</p></div><s.icon className="size-5 text-primary" /></CardContent></Card>)}</div>
<div className="grid gap-6 lg:grid-cols-2"><Panel title="当前阶段与阻塞" description="总控记录与需要关注的任务。">{lead ? <div className="mb-5 flex items-center gap-3"><span className="font-medium">{phaseLabels[lead.phase] || lead.phase}</span><Status value={lead.status} /></div> : <Empty>尚未登记总控阶段。</Empty>}{blocked.length ? <div className="space-y-3">{blocked.slice(0, 3).map(t => <p key={t.id} className="text-sm">{t.id} · {t.name}</p>)}</div> : <p className="text-sm text-muted-foreground">当前没有登记受阻任务。</p>}<Button variant="link" asChild className="mt-4 px-0"><Link to="/tasks">查看全部任务 <ArrowRight /></Link></Button></Panel>
<Panel title="等待你决定" description="待决策事项摘要。">{pending.length ? <div className="space-y-4">{pending.slice(0, 3).map(t => <div key={t.id}><p className="text-xs font-medium text-muted-foreground">{t.id} · {t.name}</p><p className="mt-1 line-clamp-3 whitespace-pre-wrap text-sm leading-6">{t.decision}</p></div>)}</div> : <Empty>当前没有登记待决策事项。</Empty>}<Button variant="link" asChild className="mt-4 px-0"><Link to="/decisions">查看方案与决策 <ArrowRight /></Link></Button></Panel></div>
{state.hooks && <Panel title="故障与恢复" description="重大事件触发汇报;重复状态不打扰。"><p className="text-sm text-muted-foreground">活动故障 {state.hooks.active_firing} · 待投递通知 {state.hooks.pending_notifications}</p>{state.hooks.recent.slice(0, 3).map((h, i) => <p className="mt-3 text-sm" key={i}>{h.status === 'resolved' ? '已恢复' : '故障'} · {h.summary}</p>)}</Panel>}
<Panel title="最近重要汇报" description="保留关键结论,详细讨论进入专门会话。"><Reports events={state.events.filter(e => /report|summary|handoff/.test(e.kind)).slice(0, 3)} compact /></Panel>
</div>
}