6f3e53a56a
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>
55 lines
1.9 KiB
JavaScript
55 lines
1.9 KiB
JavaScript
export function summarizePersonalMemoryObservation(observation) {
|
|
if (!observation || observation.skipped || !observation.enabled) {
|
|
return { savedPreviews: [], autoReviewed: 0, pendingReview: 0 };
|
|
}
|
|
const savedPreviews = (observation.results ?? [])
|
|
.filter((item) => item?.accepted && item?.candidate?.status === 'accepted')
|
|
.map((item) => ({
|
|
preview: String(item.candidate.content ?? '').slice(0, 60),
|
|
policyReason: String(item.candidate.policyReason ?? ''),
|
|
memoryType: String(item.candidate.memoryType ?? ''),
|
|
}))
|
|
.slice(0, 3);
|
|
return {
|
|
savedPreviews,
|
|
autoReviewed: Number(observation.autoReviewed ?? 0),
|
|
pendingReview: Number(observation.pendingReview ?? 0),
|
|
};
|
|
}
|
|
|
|
export function formatPersonalMemorySavedNotice(summary) {
|
|
if (!summary?.savedPreviews?.length) return null;
|
|
const preview = summary.savedPreviews[0]?.preview;
|
|
if (!preview) return null;
|
|
return `已记住:${preview}${preview.length >= 60 ? '…' : ''}`;
|
|
}
|
|
|
|
export function formatMemoryRecallNotice(count) {
|
|
const safeCount = Number(count ?? 0);
|
|
if (!Number.isFinite(safeCount) || safeCount <= 0) return null;
|
|
return `参考了你的 ${safeCount} 条记忆`;
|
|
}
|
|
|
|
const INTERNAL_MEMORY_PREVIEW_RES = [
|
|
/^\[Memory Context\]/i,
|
|
/^\[用户身份\]/,
|
|
/^【TKMind 路由提示】/,
|
|
/^【Memind 任务编排】/,
|
|
/^\[MindSpace 上下文\]/,
|
|
];
|
|
|
|
export function buildMemoryRecallPreviews(memories, { limit = 5, maxLength = 80 } = {}) {
|
|
if (!Array.isArray(memories)) return [];
|
|
const previews = [];
|
|
for (const item of memories) {
|
|
const raw = String(item?.text ?? item?.content ?? '').trim();
|
|
if (!raw) continue;
|
|
if (INTERNAL_MEMORY_PREVIEW_RES.some((pattern) => pattern.test(raw))) continue;
|
|
if (/\[Memory Context\]/i.test(raw)) continue;
|
|
const clipped = raw.slice(0, maxLength);
|
|
previews.push(clipped.length < raw.length ? `${clipped}…` : clipped);
|
|
if (previews.length >= limit) break;
|
|
}
|
|
return previews;
|
|
}
|