feat: add episodic history recall
Memind CI / Test, build, and release guards (pull_request) Successful in 4m37s

This commit is contained in:
john
2026-07-22 12:36:13 +08:00
parent 092ed16d82
commit 93d7bc0cd5
17 changed files with 1297 additions and 20 deletions
+54
View File
@@ -743,6 +743,13 @@ test('classifyWithRules routes memory recall to direct chat on fresh session', (
});
assert.equal(result.route, CHAT_INTENT_ROUTE.DIRECT_CHAT);
assert.match(result.reason, /记忆/);
const lastConversation = classifyWithRules({
text: '上次我们聊了什么?',
sessionId: '20260704_4',
sessionMessageCount: 0,
});
assert.equal(lastConversation.route, CHAT_INTENT_ROUTE.DIRECT_CHAT);
});
test('createChatIntentRouter fast-paths news lookup to agent without LLM', async () => {
@@ -1182,6 +1189,53 @@ test('agent memory canary injects only for configured user ids', async () => {
assert.equal(control.memories.length, 1);
});
test('agent memory recall prioritizes historical session evidence over personal memory', async () => {
const episodicCalls = [];
const router = createChatIntentRouter({
env: {
MEMORY_AGENT_RESOLVE_ENABLED: '1',
MEMORY_AGENT_INJECTION_MODE: 'active',
MEMORY_AGENT_RESOLVE_LIMIT: '3',
MEMORY_AGENT_RESOLVE_TIMEOUT_MS: '200',
},
memoryV2: {
async resolve() {
return {
source: 'pgvector',
memories: [{ id: 'personal-1', label: '偏好', text: '用户喜欢历史话题' }],
};
},
},
episodicMemoryService: {
async resolve(input) {
episodicCalls.push(input);
return {
source: 'episodic-index',
memories: [{
id: 'episodic:old-session',
label: '历史会话',
text: '会话“日本战国史”:用户与助手讨论过德川家康。',
}],
};
},
},
});
const result = await router.resolveAgentMemoryContext({
userId: 'user-1',
sessionId: 'current-session',
text: '我们之前聊过德川家康,你还记得吗?',
});
assert.equal(result.skipped, false);
assert.equal(result.injectionEnabled, true);
assert.equal(result.source, 'episodic+personal');
assert.equal(result.memories[0].id, 'episodic:old-session');
assert.equal(result.memories[1].id, 'personal-1');
assert.equal(episodicCalls.length, 1);
assert.equal(episodicCalls[0].sessionId, 'current-session');
});
test('active agent memory context is hidden from displayText but available to orchestration envelope', () => {
const enriched = applyAgentOrchestrationToUserMessage(
{