212ff3ff80
Introduce UMS ingest/snapshot pipeline, Context Planner with multi-source recall, runtime context injection, canonical user mapping, and session snapshot loading on auth/me. Co-authored-by: Cursor <cursoragent@cursor.com>
89 lines
2.9 KiB
JavaScript
89 lines
2.9 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { buildContextPlan } from '../temporal-recall-service/context-planner.mjs';
|
|
import { parseTimeScope } from '../temporal-recall-service/time-parser.mjs';
|
|
import { dedupeTimelineItems } from '../temporal-recall-service/dedupe.mjs';
|
|
import { formatTemporalRecallBlock } from '../temporal-recall-service/runtime-context.mjs';
|
|
|
|
test('parseTimeScope resolves yesterday', () => {
|
|
const now = new Date('2026-09-03T12:00:00+08:00');
|
|
const scope = parseTimeScope('我昨天有什么重要的事', now);
|
|
assert.equal(scope.relative_label, 'yesterday');
|
|
const startLocal = new Date(scope.mention_range.start);
|
|
assert.ok(startLocal.getTime() < now.getTime());
|
|
assert.ok(new Date(scope.mention_range.end).getTime() <= now.getTime());
|
|
});
|
|
|
|
test('buildContextPlan includes calendar for schedule questions', () => {
|
|
const plan = buildContextPlan({
|
|
query: '我今天有什么行程安排?',
|
|
user_id: 'user-1',
|
|
now: new Date('2026-09-03T12:00:00+08:00'),
|
|
});
|
|
assert.ok(plan.sources.calendar >= 0.5);
|
|
assert.ok(plan.retrievals.some((r) => r.source === 'calendar'));
|
|
});
|
|
|
|
test('buildContextPlan produces multi-source retrievals', () => {
|
|
const plan = buildContextPlan({
|
|
query: '我昨天有什么重要的事情安排吗?',
|
|
user_id: 'user-1',
|
|
now: new Date('2026-09-03T12:00:00+08:00'),
|
|
});
|
|
assert.equal(plan.query_type, 'personal_temporal_recall');
|
|
assert.equal(plan.context_needs.temporal_recall, 'REQUIRED');
|
|
assert.ok(plan.retrievals.length >= 2);
|
|
assert.ok(plan.sources.meinput > 0.5);
|
|
assert.ok(plan.sources.chat > 0.5);
|
|
});
|
|
|
|
test('dedupe merges similar items', () => {
|
|
const items = dedupeTimelineItems([
|
|
{
|
|
timeline_item_id: 'a',
|
|
title: '明天下午三点签合同',
|
|
content: '明天下午三点去签合同',
|
|
observed_time: '2026-09-02T10:00:00+08:00',
|
|
event_time: null,
|
|
source_ref: 'meinput:1',
|
|
recall_score: 0.8,
|
|
importance: 0.8,
|
|
confidence: 0.9,
|
|
},
|
|
{
|
|
timeline_item_id: 'b',
|
|
title: '明天下午三点去签合同',
|
|
content: '明天下午三点去跟张总签合同',
|
|
observed_time: '2026-09-02T10:05:00+08:00',
|
|
event_time: null,
|
|
source_ref: 'chat:1',
|
|
recall_score: 0.75,
|
|
importance: 0.75,
|
|
confidence: 0.85,
|
|
},
|
|
]);
|
|
assert.equal(items.length, 1);
|
|
assert.equal(items[0].merged_from?.length, 2);
|
|
});
|
|
|
|
test('formatTemporalRecallBlock renders grouped items', () => {
|
|
const block = formatTemporalRecallBlock({
|
|
groups: [
|
|
{
|
|
label: 'mentioned_or_planned',
|
|
items: [
|
|
{
|
|
source: 'meinput',
|
|
observed_time: '2026-09-02T10:00:00+08:00',
|
|
title: '明天下午三点签合同',
|
|
recall_score: 0.81,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
});
|
|
assert.match(block, /时间范围回忆/);
|
|
assert.match(block, /meinput/);
|
|
assert.match(block, /签合同/);
|
|
});
|