ai-chatbot/components/protocol-debug-panel.tsx
Your Name 5a4e9fd582
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
feat: unify agent workflow protocol
2026-03-13 16:16:09 +08:00

102 lines
3.5 KiB
TypeScript

"use client";
import { useMemo } from "react";
type ProtocolDebugEvent = {
id: string;
at: number;
payload: Record<string, unknown>;
};
export function ProtocolDebugPanel({
enabled,
events,
onClear,
}: {
enabled: boolean;
events: ProtocolDebugEvent[];
onClear?: () => void;
}) {
if (!enabled) return null;
const groupedEvents = useMemo(() => {
const groups = new Map<string, ProtocolDebugEvent[]>();
for (const event of events) {
const key = String(event.payload.phase || event.payload.type || "unknown");
const list = groups.get(key) || [];
list.push(event);
groups.set(key, list);
}
return Array.from(groups.entries()).map(([phase, items]) => ({
phase,
items,
}));
}, [events]);
return (
<div className="mx-auto mt-2 w-full max-w-4xl px-2 md:px-4">
<details className="rounded-xl border border-border/60 bg-muted/30 p-3 text-xs">
<summary className="cursor-pointer select-none font-medium text-foreground">
Protocol Debug
</summary>
<div className="mt-3 space-y-2">
<div className="flex flex-wrap items-center justify-between gap-2 rounded-lg border border-border/60 bg-background px-3 py-2">
<div className="flex flex-wrap items-center gap-2">
<span className="rounded-md bg-muted px-2 py-1 text-[11px] text-muted-foreground">
总事件 {events.length}
</span>
<span className="rounded-md bg-muted px-2 py-1 text-[11px] text-muted-foreground">
阶段 {groupedEvents.length}
</span>
</div>
<button
type="button"
className="rounded-md border border-border px-2 py-1 text-[11px] text-foreground hover:bg-muted"
onClick={(event) => {
event.preventDefault();
onClear?.();
}}
>
清空
</button>
</div>
{events.length === 0 ? (
<div className="rounded-lg border border-dashed border-border/60 px-3 py-2 text-muted-foreground">
暂无协议调试事件
</div>
) : (
groupedEvents.map((group) => (
<details
key={group.phase}
className="overflow-hidden rounded-lg border border-border/60 bg-background"
open
>
<summary className="cursor-pointer border-b border-border/60 px-3 py-2 font-medium">
{group.phase}
{" · "}
{group.items.length} 条
</summary>
<div className="space-y-2 px-2 py-2">
{group.items.map((event) => (
<div
key={event.id}
className="overflow-hidden rounded-md border border-border/60"
>
<div className="border-b border-border/60 px-3 py-1.5 text-[11px] font-medium text-foreground">
{new Date(event.at).toLocaleTimeString()}
</div>
<pre className="overflow-x-auto px-3 py-2 whitespace-pre-wrap break-words text-[11px] leading-relaxed text-muted-foreground">
{JSON.stringify(event.payload, null, 2)}
</pre>
</div>
))}
</div>
</details>
))
)}
</div>
</details>
</div>
);
}