feat(frontend): 记忆页面迁移到 Memory V2
前端记忆模块整体迁到后端 Memory V2 接口,修复调旧端点 /api/memory
返回 404 的问题。
- core/memory/{types,api,hooks}.ts 重写为 V2 数据模型与端点
(USER.md / MEMORY.md 条目增删改、配置读写、Hindsight 检索)
- memory-settings-page.tsx 重写:用户画像 + 工作笔记两区的条目
增删改、记忆设置面板(白名单字段)、Hindsight 检索面板
- 工作笔记按专家隔离,顶部专家下拉(默认助手 + useAgents 列出的
用户专家),专家列表取自 agents 注册表
- settings-dialog 记忆分区移到技能下方
- i18n(zh-CN/en-US/types)memory 文案整体替换
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
21a76f5e7c
commit
013aafde17
8 files changed
+1083
-1487
No files matched your search
@@ -1,84 +1,92 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
clearMemory,
|
||||
createMemoryFact,
|
||||
deleteMemoryFact,
|
||||
importMemory,
|
||||
loadMemory,
|
||||
updateMemoryFact,
|
||||
} from "./api";
|
||||
import type {
|
||||
MemoryFactInput,
|
||||
MemoryFactPatchInput,
|
||||
UserMemory,
|
||||
} from "./types";
|
||||
|
||||
export function useMemory() {
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: ["memory"],
|
||||
queryFn: () => loadMemory(),
|
||||
});
|
||||
return { memory: data ?? null, isLoading, error };
|
||||
}
|
||||
|
||||
export function useClearMemory() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: () => clearMemory(),
|
||||
onSuccess: (memory) => {
|
||||
queryClient.setQueryData<UserMemory>(["memory"], memory);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteMemoryFact() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (factId: string) => deleteMemoryFact(factId),
|
||||
onSuccess: (memory) => {
|
||||
queryClient.setQueryData<UserMemory>(["memory"], memory);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useImportMemory() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (memory: UserMemory) => importMemory(memory),
|
||||
onSuccess: (memory) => {
|
||||
queryClient.setQueryData<UserMemory>(["memory"], memory);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateMemoryFact() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (input: MemoryFactInput) => createMemoryFact(input),
|
||||
onSuccess: (memory) => {
|
||||
queryClient.setQueryData<UserMemory>(["memory"], memory);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateMemoryFact() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
factId,
|
||||
input,
|
||||
}: {
|
||||
factId: string;
|
||||
input: MemoryFactPatchInput;
|
||||
}) => updateMemoryFact(factId, input),
|
||||
onSuccess: (memory) => {
|
||||
queryClient.setQueryData<UserMemory>(["memory"], memory);
|
||||
},
|
||||
});
|
||||
}
|
||||
// Memory V2 React Query hooks。
|
||||
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
addMemoryEntry,
|
||||
deleteMemoryEntry,
|
||||
loadMemoryConfig,
|
||||
loadMemoryV2,
|
||||
patchMemoryConfig,
|
||||
replaceMemoryEntry,
|
||||
} from "./api";
|
||||
import type {
|
||||
MemoryTarget,
|
||||
MemoryV2ConfigResponse,
|
||||
MemoryV2Data,
|
||||
} from "./types";
|
||||
|
||||
const MEMORY_KEY = ["memory", "v2"] as const;
|
||||
const MEMORY_CONFIG_KEY = ["memory", "v2", "config"] as const;
|
||||
|
||||
/** 读取 builtin 本地记忆 (USER.md / MEMORY.md)。 */
|
||||
export function useMemory(agent?: string) {
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: [...MEMORY_KEY, agent ?? ""],
|
||||
queryFn: () => loadMemoryV2(agent),
|
||||
});
|
||||
return { memory: data ?? null, isLoading, error };
|
||||
}
|
||||
|
||||
/** 新增一条记忆条目。 */
|
||||
export function useAddMemoryEntry(agent?: string) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ target, content }: { target: MemoryTarget; content: string }) =>
|
||||
addMemoryEntry(target, content, agent),
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData<MemoryV2Data>([...MEMORY_KEY, agent ?? ""], data);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 替换一条记忆条目。 */
|
||||
export function useReplaceMemoryEntry(agent?: string) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
target,
|
||||
oldText,
|
||||
content,
|
||||
}: {
|
||||
target: MemoryTarget;
|
||||
oldText: string;
|
||||
content: string;
|
||||
}) => replaceMemoryEntry(target, oldText, content, agent),
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData<MemoryV2Data>([...MEMORY_KEY, agent ?? ""], data);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除一条记忆条目。 */
|
||||
export function useDeleteMemoryEntry(agent?: string) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ target, oldText }: { target: MemoryTarget; oldText: string }) =>
|
||||
deleteMemoryEntry(target, oldText, agent),
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData<MemoryV2Data>([...MEMORY_KEY, agent ?? ""], data);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 读取生效记忆配置 + 白名单。 */
|
||||
export function useMemoryConfig() {
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: MEMORY_CONFIG_KEY,
|
||||
queryFn: () => loadMemoryConfig(),
|
||||
});
|
||||
return { configResponse: data ?? null, isLoading, error };
|
||||
}
|
||||
|
||||
/** 写入 per-user 配置覆盖。 */
|
||||
export function usePatchMemoryConfig() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (overrides: Record<string, unknown>) => patchMemoryConfig(overrides),
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData<MemoryV2ConfigResponse>(MEMORY_CONFIG_KEY, data);
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user