feat(memory-v2): close Phase A with auto-review, product events, and H5 recall UI.
Add candidate auto-review pipeline, shadow audit tooling, admin metrics page, and user-visible memory recall hints in chat with phase-a readiness checks. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+33
-15
@@ -16,6 +16,7 @@ import {
|
||||
listSessions,
|
||||
loadSessionDetail,
|
||||
readConfig,
|
||||
fetchMemoryRecallHint,
|
||||
rememberUserMemory,
|
||||
rememberProjectContext,
|
||||
uploadMindSpaceAsset,
|
||||
@@ -40,6 +41,7 @@ import type {
|
||||
CapabilityMap,
|
||||
ChatFileAttachment,
|
||||
ChatState,
|
||||
MemoryRecallBadge,
|
||||
Message,
|
||||
MindSpaceChatContext,
|
||||
PortalUser,
|
||||
@@ -78,6 +80,7 @@ import {
|
||||
isRelayServerErrorMessage,
|
||||
pushMessage,
|
||||
} from '../utils/message';
|
||||
import { formatMemoryHintNotice, formatUserMemorySyncNotice, buildMemoryRecallBadge, resolveMessageRecallKey } from '../utils/memoryFeedback';
|
||||
import {
|
||||
appendSessionLists,
|
||||
prependUnique,
|
||||
@@ -358,6 +361,7 @@ export function useTKMindChat(
|
||||
const [sessionsHasMore, setSessionsHasMore] = useState(false);
|
||||
const [sessionSearchQuery, setSessionSearchQueryState] = useState('');
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
const [memoryRecallByMessageId, setMemoryRecallByMessageId] = useState<Record<string, MemoryRecallBadge>>({});
|
||||
const [messageHistoryLoadingMore, setMessageHistoryLoadingMore] = useState(false);
|
||||
const [messageHistoryHasMore, setMessageHistoryHasMore] = useState(false);
|
||||
const [messageHistoryTotal, setMessageHistoryTotal] = useState(0);
|
||||
@@ -585,21 +589,8 @@ export function useTKMindChat(
|
||||
}
|
||||
}, [canUseProjectMemory]);
|
||||
|
||||
const formatUserMemoryNotice = useCallback((result: {
|
||||
analyzed: number;
|
||||
memories: number;
|
||||
totalMemories: number;
|
||||
syncedToSession: boolean;
|
||||
}) => {
|
||||
const fragments = [];
|
||||
if (result.memories > 0) {
|
||||
fragments.push(`新增 ${result.memories} 条长期记忆`);
|
||||
} else if (result.analyzed > 0) {
|
||||
fragments.push('已分析最近对话,暂无新的长期记忆');
|
||||
} else {
|
||||
fragments.push('没有新的用户对话可提炼');
|
||||
}
|
||||
fragments.push(`当前累计 ${result.totalMemories} 条`);
|
||||
const formatUserMemoryNotice = useCallback((result: Parameters<typeof formatUserMemorySyncNotice>[0]) => {
|
||||
const fragments = [formatUserMemorySyncNotice(result)];
|
||||
if (result.syncedToSession) {
|
||||
fragments.push('已同步到当前会话');
|
||||
}
|
||||
@@ -1022,6 +1013,30 @@ export function useTKMindChat(
|
||||
}
|
||||
void (async () => {
|
||||
await syncSessionMessages(sessionId);
|
||||
if (canUseLongTermMemory) {
|
||||
try {
|
||||
const hint = await fetchMemoryRecallHint(sessionId);
|
||||
const memoryNotice = formatMemoryHintNotice(hint);
|
||||
if (memoryNotice) setNotice(memoryNotice);
|
||||
const recallBadge = buildMemoryRecallBadge(hint);
|
||||
if (recallBadge) {
|
||||
const currentMessages = messagesRef.current;
|
||||
const lastAssistantIndex = currentMessages.findLastIndex(
|
||||
(message) => message.role === 'assistant',
|
||||
);
|
||||
if (lastAssistantIndex >= 0) {
|
||||
const target = currentMessages[lastAssistantIndex];
|
||||
const recallKey = resolveMessageRecallKey(target, lastAssistantIndex);
|
||||
setMemoryRecallByMessageId((prev) => ({
|
||||
...prev,
|
||||
[recallKey]: recallBadge,
|
||||
}));
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Memory hint is best-effort UX feedback.
|
||||
}
|
||||
}
|
||||
const recentContext = messagesRef.current
|
||||
.filter((message) => getDisplayText(message).trim())
|
||||
.slice(-6)
|
||||
@@ -1172,6 +1187,7 @@ export function useTKMindChat(
|
||||
setMessageHistoryTotal(0);
|
||||
setMessageHistoryLoadingMore(false);
|
||||
setMessages([]);
|
||||
setMemoryRecallByMessageId({});
|
||||
setChatState('connecting');
|
||||
}, [clearActiveRequestMissingTimer]);
|
||||
|
||||
@@ -1886,6 +1902,7 @@ export function useTKMindChat(
|
||||
setMessageHistoryTotal(0);
|
||||
setMessageHistoryLoadingMore(false);
|
||||
setMessages([]);
|
||||
setMemoryRecallByMessageId({});
|
||||
setSession(null);
|
||||
setError(null);
|
||||
setPendingTool(null);
|
||||
@@ -2042,6 +2059,7 @@ export function useTKMindChat(
|
||||
sessionsHasMore,
|
||||
sessionSearchQuery,
|
||||
messages,
|
||||
memoryRecallByMessageId,
|
||||
messageHistoryLoadingMore,
|
||||
messageHistoryHasMore,
|
||||
messageHistoryTotal,
|
||||
|
||||
Reference in New Issue
Block a user