Add User Model Service and Temporal Recall for MeMind V0.1.

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>
This commit is contained in:
john
2026-09-03 23:25:18 +08:00
parent bf66fdf493
commit 212ff3ff80
47 changed files with 4534 additions and 6 deletions
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env node
/**
* Smoke: context plan → temporal recall query
*
* Env: MEMIND_BASE_URL (default http://127.0.0.1:8081)
* MEMIND_USERNAME / MEMIND_PASSWORD
*/
const MEMIND_PORTAL = process.env.MEMIND_BASE_URL ?? 'http://127.0.0.1:8081';
const MEMIND_API = `${MEMIND_PORTAL.replace(/\/$/, '')}/api`;
const username = process.env.MEMIND_USERNAME ?? 'admin';
const password = process.env.MEMIND_PASSWORD ?? '981122';
async function login() {
const res = await fetch(`${MEMIND_PORTAL}/auth/login`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ username, password }),
});
const data = await res.json();
if (!res.ok) throw new Error(`login: ${JSON.stringify(data)}`);
return { token: data.sessionToken, user: data.user };
}
async function main() {
const { token, user } = await login();
const headers = {
'content-type': 'application/json',
cookie: `tkmind_user_session=${token}`,
};
const query = process.argv[2] ?? '我昨天有什么重要的事?';
const planRes = await fetch(`${MEMIND_API}/v1/context/plan`, {
method: 'POST',
headers,
body: JSON.stringify({ query, now: new Date().toISOString() }),
});
const planBody = await planRes.json();
if (!planRes.ok) throw new Error(`plan: ${JSON.stringify(planBody)}`);
console.log('plan:', {
query_type: planBody.plan.query_type,
temporal_mode: planBody.plan.temporal_mode,
sources: planBody.plan.sources,
retrievals: planBody.plan.retrievals?.map((r) => r.source),
});
const recallRes = await fetch(`${MEMIND_API}/v1/temporal-recall/query`, {
method: 'POST',
headers,
body: JSON.stringify({ plan: planBody.plan, limit: 10 }),
});
const recallBody = await recallRes.json();
if (!recallRes.ok) throw new Error(`recall: ${JSON.stringify(recallBody)}`);
console.log('recall stats:', recallBody.stats);
const sample = recallBody.items?.[0] ?? recallBody.groups?.[0]?.items?.[0];
if (sample) {
console.log('sample:', sample.source, sample.title?.slice(0, 60), 'score=', sample.recall_score);
} else {
console.log('no items (user may have no data in range)');
}
console.log(`smoke OK for user ${user.id}`);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});