feat: add memory settings page

This commit is contained in:
Henry Li
2026-02-03 18:18:56 +08:00
parent b8c325eb3a
commit 94acb15c0c
13 changed files with 411 additions and 17 deletions

View File

@@ -35,6 +35,8 @@ export const enUS: Translations = {
custom: "Custom",
notAvailableInDemoMode: "Not available in demo mode",
loading: "Loading...",
version: "Version",
lastUpdated: "Last updated",
code: "Code",
preview: "Preview",
cancel: "Cancel",
@@ -201,11 +203,47 @@ export const enUS: Translations = {
description: "Adjust how DeerFlow looks and behaves for you.",
sections: {
appearance: "Appearance",
memory: "Memory",
tools: "Tools",
skills: "Skills",
notification: "Notification",
acknowledge: "Acknowledge",
},
memory: {
title: "Memory",
description:
"DeerFlow automatically learns from your conversations in the background. These memories help DeerFlow understand you better and deliver a more personalized experience.",
empty: "No memory data to display.",
rawJson: "Raw JSON",
markdown: {
overview: "Overview",
userContext: "User context",
work: "Work",
personal: "Personal",
topOfMind: "Top of mind",
historyBackground: "History",
recentMonths: "Recent months",
earlierContext: "Earlier context",
longTermBackground: "Long-term background",
updatedAt: "Updated at",
facts: "Facts",
empty: "Empty",
table: {
category: "Category",
confidence: "Confidence",
confidenceLevel: {
veryHigh: "Very high",
high: "High",
normal: "Normal",
unknown: "Unknown",
},
content: "Content",
source: "Source",
createdAt: "CreatedAt",
view: "View",
},
},
},
appearance: {
themeTitle: "Theme",
themeDescription:

View File

@@ -24,6 +24,8 @@ export interface Translations {
custom: string;
notAvailableInDemoMode: string;
loading: string;
version: string;
lastUpdated: string;
code: string;
preview: string;
cancel: string;
@@ -149,11 +151,46 @@ export interface Translations {
description: string;
sections: {
appearance: string;
memory: string;
tools: string;
skills: string;
notification: string;
acknowledge: string;
};
memory: {
title: string;
description: string;
empty: string;
rawJson: string;
markdown: {
overview: string;
userContext: string;
work: string;
personal: string;
topOfMind: string;
historyBackground: string;
recentMonths: string;
earlierContext: string;
longTermBackground: string;
updatedAt: string;
facts: string;
empty: string;
table: {
category: string;
confidence: string;
confidenceLevel: {
veryHigh: string;
high: string;
normal: string;
unknown: string;
};
content: string;
source: string;
createdAt: string;
view: string;
};
};
};
appearance: {
themeTitle: string;
themeDescription: string;

View File

@@ -35,6 +35,8 @@ export const zhCN: Translations = {
custom: "自定义",
notAvailableInDemoMode: "在演示模式下不可用",
loading: "加载中...",
version: "版本",
lastUpdated: "最后更新",
code: "代码",
preview: "预览",
cancel: "取消",
@@ -197,11 +199,47 @@ export const zhCN: Translations = {
description: "根据你的偏好调整 DeerFlow 的界面和行为。",
sections: {
appearance: "外观",
memory: "记忆",
tools: "工具",
skills: "技能",
notification: "通知",
acknowledge: "致谢",
},
memory: {
title: "记忆",
description:
"DeerFlow 会在后台不断从你的对话中自动学习。这些记忆能帮助 DeerFlow 更好地理解你,并提供更个性化的体验。",
empty: "暂无可展示的记忆数据。",
rawJson: "原始 JSON",
markdown: {
overview: "概览",
userContext: "用户上下文",
work: "工作",
personal: "个人",
topOfMind: "近期关注Top of mind",
historyBackground: "历史背景",
recentMonths: "近几个月",
earlierContext: "更早上下文",
longTermBackground: "长期背景",
updatedAt: "更新于",
facts: "事实",
empty: "(空)",
table: {
category: "类别",
confidence: "置信度",
confidenceLevel: {
veryHigh: "极高",
high: "较高",
normal: "一般",
unknown: "未知",
},
content: "内容",
source: "来源",
createdAt: "创建时间",
view: "查看",
},
},
},
appearance: {
themeTitle: "主题",
themeDescription: "跟随系统或选择固定的界面模式。",

View File

@@ -0,0 +1,9 @@
import { getBackendBaseURL } from "../config";
import type { UserMemory } from "./types";
export async function loadMemory() {
const memory = await fetch(`${getBackendBaseURL()}/api/memory`);
const json = await memory.json();
return json as UserMemory;
}

View File

@@ -0,0 +1,11 @@
import { useQuery } from "@tanstack/react-query";
import { loadMemory } from "./api";
export function useMemory() {
const { data, isLoading, error } = useQuery({
queryKey: ["memory"],
queryFn: () => loadMemory(),
});
return { memory: data ?? null, isLoading, error };
}

View File

@@ -0,0 +1,2 @@
export * from "./api";
export * from "./types";

View File

@@ -0,0 +1,40 @@
export interface UserMemory {
version: string;
lastUpdated: string;
user: {
workContext: {
summary: string;
updatedAt: string;
};
personalContext: {
summary: string;
updatedAt: string;
};
topOfMind: {
summary: string;
updatedAt: string;
};
};
history: {
recentMonths: {
summary: string;
updatedAt: string;
};
earlierContext: {
summary: string;
updatedAt: string;
};
longTermBackground: {
summary: string;
updatedAt: string;
};
};
facts: {
id: string;
content: string;
category: string;
confidence: number;
createdAt: string;
source: string;
}[];
}

View File

@@ -1,7 +1,27 @@
import { formatDistanceToNow } from "date-fns";
import { enUS as dateFnsEnUS, zhCN as dateFnsZhCN } from "date-fns/locale";
export function formatTimeAgo(date: Date | string | number) {
import { detectLocale, type Locale } from "@/core/i18n";
import { getLocaleFromCookie } from "@/core/i18n/cookies";
function getDateFnsLocale(locale: Locale) {
switch (locale) {
case "zh-CN":
return dateFnsZhCN;
case "en-US":
default:
return dateFnsEnUS;
}
}
export function formatTimeAgo(date: Date | string | number, locale?: Locale) {
const effectiveLocale =
locale ??
(getLocaleFromCookie() as Locale | null) ??
// Fallback when cookie is missing (or on first render)
detectLocale();
return formatDistanceToNow(date, {
addSuffix: true,
locale: getDateFnsLocale(effectiveLocale),
});
}