143 lines
4.8 KiB
TypeScript
143 lines
4.8 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { toast } from "sonner";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import { getBackendBaseURL } from "@/core/config";
|
|
|
|
type ThreadMemoryTestPanelProps = {
|
|
threadId?: string;
|
|
};
|
|
|
|
export function ThreadMemoryTestPanel({ threadId }: ThreadMemoryTestPanelProps) {
|
|
const [memorySummary, setMemorySummary] = useState("");
|
|
const [memoryVersion, setMemoryVersion] = useState<number | null>(null);
|
|
const [loadingSummary, setLoadingSummary] = useState(false);
|
|
const [savingSummary, setSavingSummary] = useState(false);
|
|
const [deletingMemory, setDeletingMemory] = useState(false);
|
|
const [open, setOpen] = useState(true);
|
|
|
|
if (!threadId || threadId === "new") return null;
|
|
|
|
const handleLoadMemorySummary = async () => {
|
|
setLoadingSummary(true);
|
|
try {
|
|
const res = await fetch(
|
|
`${getBackendBaseURL()}/api/threads/${encodeURIComponent(threadId)}/memory-summary`,
|
|
);
|
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
const data = (await res.json()) as { summary: string; memoryVersion: number };
|
|
setMemorySummary(data.summary ?? "");
|
|
setMemoryVersion(data.memoryVersion ?? 0);
|
|
toast.success("已加载会话记忆");
|
|
} catch {
|
|
toast.error("加载会话记忆失败");
|
|
} finally {
|
|
setLoadingSummary(false);
|
|
}
|
|
};
|
|
|
|
const handleSaveMemorySummary = async () => {
|
|
if (memoryVersion == null) return;
|
|
setSavingSummary(true);
|
|
try {
|
|
const res = await fetch(
|
|
`${getBackendBaseURL()}/api/threads/${encodeURIComponent(threadId)}/memory-summary`,
|
|
{
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ summary: memorySummary, memoryVersion }),
|
|
},
|
|
);
|
|
if (res.status === 409) {
|
|
toast.error("记忆已更新,请先重新加载再保存");
|
|
return;
|
|
}
|
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
const data = (await res.json()) as { memoryVersion?: number };
|
|
if (typeof data.memoryVersion === "number") setMemoryVersion(data.memoryVersion);
|
|
toast.success("会话记忆已保存");
|
|
} catch {
|
|
toast.error("保存会话记忆失败");
|
|
} finally {
|
|
setSavingSummary(false);
|
|
}
|
|
};
|
|
|
|
const handleDeleteMemory = async () => {
|
|
setDeletingMemory(true);
|
|
try {
|
|
const res = await fetch(
|
|
`${getBackendBaseURL()}/api/threads/${encodeURIComponent(threadId)}/memory`,
|
|
{ method: "DELETE" },
|
|
);
|
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
setMemorySummary("");
|
|
setMemoryVersion(0);
|
|
toast.success("当前会话记忆已删除");
|
|
} catch {
|
|
toast.error("删除会话记忆失败");
|
|
} finally {
|
|
setDeletingMemory(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="fixed right-4 bottom-4 z-50 w-[380px] rounded-lg border border-ws-divider bg-ws-surface-elevated p-3 shadow-lg">
|
|
<div className="mb-2 flex items-center justify-between">
|
|
<div className="text-sm font-semibold">Thread Memory TestPanel</div>
|
|
<Button size="sm" variant="ghost" onClick={() => setOpen((v) => !v)}>
|
|
{open ? "收起" : "展开"}
|
|
</Button>
|
|
</div>
|
|
{open && (
|
|
<div className="space-y-2">
|
|
<div className="flex items-center gap-2">
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
onClick={() => {
|
|
void handleLoadMemorySummary();
|
|
}}
|
|
disabled={loadingSummary}
|
|
>
|
|
{loadingSummary ? "加载中..." : "查看记忆"}
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
onClick={() => {
|
|
void handleSaveMemorySummary();
|
|
}}
|
|
disabled={savingSummary || memoryVersion == null}
|
|
>
|
|
{savingSummary ? "保存中..." : "保存记忆"}
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
variant="destructive"
|
|
onClick={() => {
|
|
void handleDeleteMemory();
|
|
}}
|
|
disabled={deletingMemory}
|
|
>
|
|
{deletingMemory ? "删除中..." : "删除记忆"}
|
|
</Button>
|
|
</div>
|
|
<div className="text-xs text-ws-text-subtle-strong">
|
|
threadId: {threadId.slice(0, 8)}... | version:{" "}
|
|
{memoryVersion == null ? "-" : memoryVersion}
|
|
</div>
|
|
<Textarea
|
|
value={memorySummary}
|
|
onChange={(e) => setMemorySummary(e.target.value)}
|
|
placeholder="这里显示会话记忆总结,可编辑后保存"
|
|
className="min-h-32 bg-white/80"
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|