Hide admin memory details and fix memory config

This commit is contained in:
wuyang6
2026-05-13 14:29:06 +08:00
parent af07bc77ed
commit 7282a18116
2 changed files with 57 additions and 196 deletions
+42 -160
View File
@@ -4,7 +4,6 @@ import {
ActivityIcon,
DatabaseIcon,
RefreshCwIcon,
SaveIcon,
Trash2Icon,
UserPlusIcon,
UsersIcon,
@@ -68,19 +67,6 @@ type MemoryEvent = {
updated_at: string;
};
type UserMemory = {
content: string;
line_count: number;
updated_at?: string | null;
};
type SkillMemory = {
skill: string;
content: string;
line_count: number;
updated_at?: string | null;
};
const TOKEN_KEY = "zk-admin-token";
export default function AdminPage() {
@@ -168,10 +154,6 @@ function AdminDashboard({
const [accounts, setAccounts] = useState<AccountRow[]>([]);
const [selectedAccountId, setSelectedAccountId] = useState("");
const [events, setEvents] = useState<MemoryEvent[]>([]);
const [userMemory, setUserMemory] = useState<UserMemory | null>(null);
const [skillMemories, setSkillMemories] = useState<SkillMemory[]>([]);
const [selectedSkill, setSelectedSkill] = useState("");
const [memoryDraft, setMemoryDraft] = useState("");
const [newAccountId, setNewAccountId] = useState("");
const [notice, setNotice] = useState("");
@@ -179,10 +161,6 @@ function AdminDashboard({
() => accounts.find((item) => item.account_id === selectedAccountId),
[accounts, selectedAccountId],
);
const selectedSkillMemory = useMemo(
() => skillMemories.find((item) => item.skill === selectedSkill),
[skillMemories, selectedSkill],
);
// biome-ignore lint/correctness/useExhaustiveDependencies: 首次进入后台时加载一次即可,后续由刷新按钮触发。
useEffect(() => {
@@ -195,14 +173,6 @@ function AdminDashboard({
loadAccountMemory(selectedAccountId);
}, [selectedAccountId]);
useEffect(() => {
if (selectedSkillMemory) {
setMemoryDraft(selectedSkillMemory.content);
} else if (userMemory) {
setMemoryDraft(userMemory.content);
}
}, [selectedSkillMemory, userMemory]);
async function refresh() {
const [summaryPayload, accountPayload] = await Promise.all([
adminFetch<AdminSummary>(token, "/summary"),
@@ -217,25 +187,11 @@ function AdminDashboard({
}
async function loadAccountMemory(accountId: string) {
const [memoryPayload, userPayload, skillPayload] = await Promise.all([
adminFetch<{ events: MemoryEvent[] }>(
token,
`/memory?account_id=${encodeURIComponent(accountId)}`,
),
adminFetch<UserMemory>(
token,
`/memory/user?account_id=${encodeURIComponent(accountId)}`,
),
adminFetch<SkillMemory[]>(
token,
`/memory/skills?account_id=${encodeURIComponent(accountId)}`,
),
]);
const memoryPayload = await adminFetch<{ events: MemoryEvent[] }>(
token,
`/memory?account_id=${encodeURIComponent(accountId)}`,
);
setEvents(memoryPayload.events ?? []);
setUserMemory(userPayload);
setSkillMemories(skillPayload);
setSelectedSkill("");
setMemoryDraft(userPayload.content);
}
async function createAccount() {
@@ -264,34 +220,6 @@ function AdminDashboard({
await refresh();
}
async function saveMemory() {
if (!selectedAccountId) return;
if (selectedSkill) {
await adminFetch(
token,
`/memory/skills/${encodeURIComponent(selectedSkill)}`,
{
method: "PUT",
body: JSON.stringify({
account_id: selectedAccountId,
content: memoryDraft,
}),
},
);
setNotice(`已保存 ${selectedSkill} 记忆`);
} else {
await adminFetch(token, "/memory/user", {
method: "PUT",
body: JSON.stringify({
account_id: selectedAccountId,
content: memoryDraft,
}),
});
setNotice("已保存用户记忆");
}
await loadAccountMemory(selectedAccountId);
}
function logout() {
localStorage.removeItem(TOKEN_KEY);
onLogout();
@@ -403,54 +331,8 @@ function AdminDashboard({
/>
</div>
<div className="grid gap-4 xl:grid-cols-[1fr_360px]">
<div className="rounded-lg border bg-card">
<div className="flex items-center justify-between border-b p-3">
<div>
<div className="font-medium"></div>
<div className="text-muted-foreground text-xs">
Skill Skill
</div>
</div>
<Button size="sm" onClick={saveMemory}>
<SaveIcon className="size-4" />
</Button>
</div>
<div className="flex gap-2 border-b p-3">
<Button
variant={selectedSkill ? "outline" : "secondary"}
size="sm"
onClick={() => {
setSelectedSkill("");
setMemoryDraft(userMemory?.content ?? "");
}}
>
</Button>
<div className="flex min-w-0 flex-1 gap-2 overflow-x-auto">
{skillMemories.map((item) => (
<Button
key={item.skill}
variant={
selectedSkill === item.skill ? "secondary" : "outline"
}
size="sm"
onClick={() => setSelectedSkill(item.skill)}
>
{item.skill}
</Button>
))}
</div>
</div>
<textarea
className="min-h-[420px] w-full resize-y bg-transparent p-4 font-mono text-sm outline-none"
value={memoryDraft}
onChange={(event) => setMemoryDraft(event.target.value)}
/>
</div>
<div className="grid gap-4">
<div className="grid gap-4 xl:grid-cols-[360px_1fr]">
<div className="grid gap-4 content-start">
<div className="rounded-lg border bg-card">
<div className="flex items-center gap-2 border-b p-3 font-medium">
<ActivityIcon className="size-4" />
@@ -476,42 +358,6 @@ function AdminDashboard({
</div>
</div>
<div className="rounded-lg border bg-card">
<div className="border-b p-3 font-medium"></div>
<div className="max-h-[360px] overflow-y-auto p-2">
{events.length ? (
events.map((event) => (
<div
key={event.id}
className="mb-2 rounded-md border bg-muted/20 p-2 text-xs"
>
<div className="flex items-center justify-between gap-2">
<span className="font-medium">{event.status}</span>
<span className="text-muted-foreground">
P{event.priority}
</span>
</div>
<div className="mt-1 truncate text-muted-foreground">
{event.session_id}
</div>
<div className="mt-1">
{event.signals.join(" / ") || "无信号"}
</div>
{event.error ? (
<div className="mt-1 text-destructive">
{event.error}
</div>
) : null}
</div>
))
) : (
<p className="p-4 text-center text-muted-foreground text-sm">
</p>
)}
</div>
</div>
{selectedAccountId ? (
<Button
variant="destructive"
@@ -522,6 +368,42 @@ function AdminDashboard({
</Button>
) : null}
</div>
<div className="rounded-lg border bg-card">
<div className="border-b p-3 font-medium"></div>
<div className="max-h-[520px] overflow-y-auto p-2">
{events.length ? (
events.map((event) => (
<div
key={event.id}
className="mb-2 rounded-md border bg-muted/20 p-2 text-xs"
>
<div className="flex items-center justify-between gap-2">
<span className="font-medium">{event.status}</span>
<span className="text-muted-foreground">
P{event.priority}
</span>
</div>
<div className="mt-1 truncate text-muted-foreground">
{event.session_id}
</div>
<div className="mt-1">
{event.signals.join(" / ") || "无信号"}
</div>
{event.error ? (
<div className="mt-1 text-destructive">
{event.error}
</div>
) : null}
</div>
))
) : (
<p className="p-4 text-center text-muted-foreground text-sm">
</p>
)}
</div>
</div>
</div>
</section>
</div>