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:
@@ -893,6 +893,96 @@ export async function patchMemoryV2Config(patch: Record<string, unknown>) {
|
||||
export async function fetchMemoryV2Runtime() {
|
||||
return adminFetch<MemoryV2RuntimeState>('/admin-api/memory-v2/runtime');
|
||||
}
|
||||
|
||||
export type MemoryV2ProductMetrics = {
|
||||
window: { since: string; sinceMs: number; untilMs: number };
|
||||
userId: string | null;
|
||||
events: {
|
||||
memory_candidate_saved: number;
|
||||
memory_promoted: number;
|
||||
memory_resolved_injected: number;
|
||||
memory_recall_hit: number;
|
||||
};
|
||||
sources: Record<string, string>;
|
||||
};
|
||||
|
||||
export type MemoryV2ShadowAuditSummary = {
|
||||
falseStoreRate: number | null;
|
||||
autoAcceptRate: number | null;
|
||||
resolveHitRate: number | null;
|
||||
suspiciousCandidateCount: number;
|
||||
pgvectorLagUserCount: number;
|
||||
};
|
||||
|
||||
export type MemoryV2MetricsResponse = {
|
||||
metrics: MemoryV2ProductMetrics;
|
||||
audit: MemoryV2ShadowAuditSummary;
|
||||
candidateCounts: Record<string, number>;
|
||||
};
|
||||
|
||||
export type MemoryV2CandidateRow = {
|
||||
id: string;
|
||||
userId: string;
|
||||
sessionId: string | null;
|
||||
memoryType: string;
|
||||
content: string;
|
||||
importance: number;
|
||||
confidence: number;
|
||||
status: string;
|
||||
policyReason: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
};
|
||||
|
||||
export async function fetchMemoryV2Metrics(params?: { since?: string; userId?: string }) {
|
||||
const query = new URLSearchParams();
|
||||
if (params?.since) query.set('since', params.since);
|
||||
if (params?.userId) query.set('userId', params.userId);
|
||||
const suffix = query.toString() ? `?${query.toString()}` : '';
|
||||
return adminFetch<MemoryV2MetricsResponse>(`/admin-api/memory-v2/metrics${suffix}`);
|
||||
}
|
||||
|
||||
export async function fetchMemoryV2Candidates(params?: {
|
||||
status?: string;
|
||||
userId?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}) {
|
||||
const query = new URLSearchParams();
|
||||
if (params?.status) query.set('status', params.status);
|
||||
if (params?.userId) query.set('userId', params.userId);
|
||||
if (params?.limit != null) query.set('limit', String(params.limit));
|
||||
if (params?.offset != null) query.set('offset', String(params.offset));
|
||||
const suffix = query.toString() ? `?${query.toString()}` : '';
|
||||
return adminFetch<{ items: MemoryV2CandidateRow[]; status: string; limit: number; offset: number }>(
|
||||
`/admin-api/memory-v2/candidates${suffix}`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function runMemoryV2CandidateAutoReview(params?: { userId?: string; limit?: number }) {
|
||||
return adminFetch<{
|
||||
ok: true;
|
||||
scanned: number;
|
||||
accepted: number;
|
||||
rejected: number;
|
||||
pending: number;
|
||||
samples?: Array<{ id: string; action: string; reason: string }>;
|
||||
}>('/admin-api/memory-v2/candidates/auto-review', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
userId: params?.userId,
|
||||
limit: params?.limit ?? 200,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function reviewMemoryV2Candidate(id: string, status: 'accepted' | 'rejected') {
|
||||
return adminFetch<{ ok: true; updated: boolean }>(`/admin-api/memory-v2/candidates/${encodeURIComponent(id)}/review`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ status }),
|
||||
});
|
||||
}
|
||||
|
||||
export type GoalRunRuntimeState = {
|
||||
enabled: boolean;
|
||||
canaryUserIds: string[];
|
||||
|
||||
Reference in New Issue
Block a user