diff --git a/webui/src/pages/MemoryPage.svelte b/webui/src/pages/MemoryPage.svelte index 0299792..8e8a081 100644 --- a/webui/src/pages/MemoryPage.svelte +++ b/webui/src/pages/MemoryPage.svelte @@ -7,12 +7,23 @@ let memories = $state([]); let loading = $state(true); let error = $state(""); + let limit = $state(100); + let editingKey = $state(null); + let confirmingKey = $state(null); + let draftContent = $state(""); + let draftImportance = $state(0); + let saving = $state(false); + let deleting = $state(false); + let actionError = $state(""); + const knowledge = $derived(memories.filter((item) => item.category === "knowledge").length); + const timeline = $derived(memories.length - knowledge); + const hasMore = $derived(memories.length >= limit); async function load() { loading = true; error = ""; - const params = new URLSearchParams({ limit: "200" }); + const params = new URLSearchParams({ limit: String(limit) }); if (query.trim()) params.set("query", query.trim()); if (category) params.set("category", category); try { memories = (await api(`/api/memories?${params}`)).memories; } @@ -20,19 +31,146 @@ finally { loading = false; } } + function applyFilters() { + limit = 100; + editingKey = null; + confirmingKey = null; + actionError = ""; + load(); + } + + function loadMore() { + limit += 100; + load(); + } + + function startEdit(memory) { + confirmingKey = null; + actionError = ""; + editingKey = memory.key; + draftContent = memory.content; + draftImportance = Number(memory.importance); + } + + function cancelEdit() { + editingKey = null; + actionError = ""; + } + + async function saveEdit(key) { + saving = true; + actionError = ""; + try { + await api(`/api/memories/${encodeURIComponent(key)}`, { + method: "PUT", + body: JSON.stringify({ content: draftContent, importance: Number(draftImportance) }) + }); + editingKey = null; + await load(); + } catch (caught) { actionError = caught.message; } + finally { saving = false; } + } + + function startConfirm(memory) { + editingKey = null; + actionError = ""; + confirmingKey = memory.key; + } + + function cancelConfirm() { + confirmingKey = null; + actionError = ""; + } + + async function removeMemory(key) { + deleting = true; + actionError = ""; + try { + await api(`/api/memories/${encodeURIComponent(key)}`, { method: "DELETE" }); + confirmingKey = null; + await load(); + } catch (caught) { actionError = caught.message; } + finally { deleting = false; } + } + onMount(load);
-
{ event.preventDefault(); load(); }}> + { event.preventDefault(); applyFilters(); }}> - +
-
{memories.length}当前结果
{knowledge}Knowledge
{memories.length - knowledge}Timeline
+
{memories.length}总数
{knowledge}Knowledge
{timeline}Timeline
{#if loading}
加载中…
{:else if error}
{error}
- {:else}{#each memories as memory (memory.id)}

{memory.key}

{memory.content}

{formatTime(memory.updated_at)}{#if memory.session_id}{memory.session_id}{/if}重要度 {Number(memory.importance).toFixed(2)}
{memory.category}
{:else}
没有匹配的记忆
{/each}{/if} + {:else} + {#each memories as memory (memory.id)} +
+ {#if editingKey === memory.key} +

{memory.key}

{memory.category}
+ + + {#if actionError}

{actionError}

{/if} +
+ + +
+ {:else} +
+
+

{memory.key}

+

{memory.content}

+
重要度 {Number(memory.importance).toFixed(2)}更新 {formatTime(memory.updated_at)}{#if memory.session_id}{memory.session_id}{/if}
+
+
+ {memory.category} +
+ + +
+
+
+ {#if confirmingKey === memory.key} +
+ {#if memory.category === "timeline"} +

Timeline 是压缩后的历史上下文,删除后模型将永久失去该时段长期记忆且无法自动重建;原始消息仍保留在聊天历史,但不再进入模型上下文

+ {:else} +

删除后不可恢复,影响后续召回

+ {/if} + {#if actionError}

{actionError}

{/if} +
+ + +
+
+ {/if} + {/if} +
+ {:else}
没有匹配的记忆
{/each} + {#if hasMore}
{/if} + {/if}
+ +