feat: add AgentRunGraphSummary and related functionality for graph summary retrieval

This commit is contained in:
mlogclub
2026-04-12 14:08:16 +08:00
parent e2d2a951a9
commit c3ac4c3e28
5 changed files with 211 additions and 0 deletions
+115
View File
@@ -13,6 +13,13 @@ import { ListPagination } from "@/components/list-pagination"
import { OptionCombobox } from "@/components/option-combobox"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
Drawer,
DrawerContent,
@@ -32,8 +39,10 @@ import {
} from "@/components/ui/table"
import {
fetchAgentRunLog,
fetchAgentRunGraphSummary,
fetchAgentRunLogs,
fetchAIAgentsAll,
type AgentRunGraphSummary,
type AgentRunLog,
type AIAgent,
type PageResult,
@@ -119,6 +128,7 @@ export default function DashboardAgentRunLogsPage() {
const [page, setPage] = useState(1)
const [limit, setLimit] = useState(20)
const [loading, setLoading] = useState(true)
const [summaryLoading, setSummaryLoading] = useState(true)
const [detailLoading, setDetailLoading] = useState(false)
const [detailOpen, setDetailOpen] = useState(false)
const [activeLog, setActiveLog] = useState<AgentRunLog | null>(null)
@@ -126,6 +136,17 @@ export default function DashboardAgentRunLogsPage() {
results: [],
page: { page: 1, limit: 20, total: 0 },
})
const [graphSummary, setGraphSummary] = useState<AgentRunGraphSummary>({
triageCount: 0,
triagePrepareTicket: 0,
triagePrepareTicketReady: 0,
triageHandoff: 0,
triageContinueAnswering: 0,
analyzeCount: 0,
prepareDraftCount: 0,
createTicketCount: 0,
handoffCount: 0,
})
const [aiAgents, setAiAgents] = useState<AIAgent[]>([])
const activeTraceData = useMemo(
() => safeParseJSON(activeLog?.traceData ?? ""),
@@ -176,6 +197,23 @@ export default function DashboardAgentRunLogsPage() {
void loadData()
}, [loadData])
useEffect(() => {
async function loadGraphSummary() {
setSummaryLoading(true)
try {
const data = await fetchAgentRunGraphSummary({
aiAgentId: aiAgentId === "all" ? undefined : aiAgentId,
})
setGraphSummary(data)
} catch (error) {
toast.error(error instanceof Error ? error.message : "加载 Graph 摘要失败")
} finally {
setSummaryLoading(false)
}
}
void loadGraphSummary()
}, [aiAgentId])
useEffect(() => {
async function loadAIAgents() {
try {
@@ -294,6 +332,57 @@ export default function DashboardAgentRunLogsPage() {
</Button>
</div>
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
<SummaryCard
title="统一分流"
description="triage_service_request 调用次数"
value={graphSummary.triageCount}
loading={summaryLoading}
/>
<SummaryCard
title="推荐建单"
description="triage 推荐 prepare_ticket 次数"
value={graphSummary.triagePrepareTicket}
loading={summaryLoading}
/>
<SummaryCard
title="草稿就绪"
description="triage 推荐建单且 ticketDraft 已就绪"
value={graphSummary.triagePrepareTicketReady}
loading={summaryLoading}
/>
<SummaryCard
title="推荐转人工"
description="triage 推荐 handoff_to_human 次数"
value={graphSummary.triageHandoff}
loading={summaryLoading}
/>
<SummaryCard
title="继续解答"
description="triage 推荐 continue_answering 次数"
value={graphSummary.triageContinueAnswering}
loading={summaryLoading}
/>
<SummaryCard
title="风险分析"
description="analyze_conversation 调用次数"
value={graphSummary.analyzeCount}
loading={summaryLoading}
/>
<SummaryCard
title="工单草稿"
description="prepare_ticket_draft 调用次数"
value={graphSummary.prepareDraftCount}
loading={summaryLoading}
/>
<SummaryCard
title="最终动作"
description={`建单 ${graphSummary.createTicketCount} / 转人工 ${graphSummary.handoffCount}`}
value={graphSummary.createTicketCount + graphSummary.handoffCount}
loading={summaryLoading}
/>
</div>
<div className="overflow-hidden rounded-lg border bg-background">
<Table>
<TableHeader className="bg-muted/40">
@@ -521,6 +610,32 @@ export default function DashboardAgentRunLogsPage() {
)
}
function SummaryCard({
title,
description,
value,
loading,
}: {
title: string
description: string
value: number
loading: boolean
}) {
return (
<Card size="sm">
<CardHeader>
<CardTitle>{title}</CardTitle>
<CardDescription>{description}</CardDescription>
</CardHeader>
<CardContent>
<div className="text-2xl font-semibold tracking-tight">
{loading ? "--" : value}
</div>
</CardContent>
</Card>
)
}
function safeParseJSON(value: string) {
if (!value.trim()) {
return null
+18
View File
@@ -416,6 +416,18 @@ export type AgentRunLog = {
createdAt: string
}
export type AgentRunGraphSummary = {
triageCount: number
triagePrepareTicket: number
triagePrepareTicketReady: number
triageHandoff: number
triageContinueAnswering: number
analyzeCount: number
prepareDraftCount: number
createTicketCount: number
handoffCount: number
}
export type AdminAgentProfile = {
id: number
userId: number
@@ -895,6 +907,12 @@ export function fetchAgentRunLog(id: number) {
return request<AgentRunLog>(`/api/console/agent-run-log/${id}`)
}
export function fetchAgentRunGraphSummary(params?: { aiAgentId?: string }) {
return request<AgentRunGraphSummary>(
`/api/console/agent-run-log/graph/summary${toQueryString(params)}`
)
}
export function updateSkillDefinitionStatus(id: number, status: number) {
return request<void>("/api/console/skill-definition/update_status", {
method: "POST",