claude-memory-layer 1.0.32 → 1.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1110 -72
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +414 -25
- package/dist/core/index.js.map +2 -2
- package/dist/hooks/post-tool-use.js +416 -27
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +416 -27
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +416 -27
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +416 -27
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +416 -27
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +504 -34
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +416 -27
- package/dist/index.js.map +2 -2
- package/dist/mcp/index.js +407 -32
- package/dist/mcp/index.js.map +2 -2
- package/dist/server/api/index.js +850 -44
- package/dist/server/api/index.js.map +3 -3
- package/dist/server/index.js +1073 -64
- package/dist/server/index.js.map +3 -3
- package/dist/services/memory-service.js +416 -27
- package/dist/services/memory-service.js.map +2 -2
- package/dist/ui/assets/js/bootstrap.js +2 -0
- package/dist/ui/assets/js/overview.js +166 -3
- package/dist/ui/assets/js/state.js +3 -0
- package/dist/ui/index.html +20 -0
- package/dist/ui/style.css +193 -0
- package/package.json +5 -1
|
@@ -76,7 +76,9 @@ function setupEventListeners() {
|
|
|
76
76
|
b.classList.toggle('active', b.dataset.kpiWindow === window);
|
|
77
77
|
});
|
|
78
78
|
await loadKpiData();
|
|
79
|
+
await loadMemoryUsefulnessData();
|
|
79
80
|
updateKpiCardsUI();
|
|
81
|
+
updateMemoryUsefulnessUI();
|
|
80
82
|
renderKpiTrendChart();
|
|
81
83
|
});
|
|
82
84
|
});
|
|
@@ -4,28 +4,51 @@ async function loadKpiData() {
|
|
|
4
4
|
.catch(() => null);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
async function loadMemoryUsefulnessData() {
|
|
8
|
+
state.memoryUsefulness = await fetch(apiUrl(`${API_BASE}/stats/usefulness`, { window: state.kpiWindow }))
|
|
9
|
+
.then(r => r.json())
|
|
10
|
+
.catch(() => null);
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
async function refreshData() {
|
|
8
14
|
const btn = document.getElementById('refresh-btn');
|
|
9
15
|
if(btn) btn.classList.add('loading');
|
|
16
|
+
const refreshRequestId = (state.refreshRequestId || 0) + 1;
|
|
17
|
+
state.refreshRequestId = refreshRequestId;
|
|
18
|
+
const projectAtStart = state.currentProject;
|
|
19
|
+
const kpiWindowAtStart = state.kpiWindow;
|
|
10
20
|
|
|
11
21
|
try {
|
|
12
|
-
const [stats, shared, mostAccessed, helpfulness, retrievalTraces, adherenceSummary] = await Promise.all([
|
|
22
|
+
const [stats, shared, mostAccessed, helpfulness, memoryUsefulness, retrievalTraces, retrievalReviewQueue, adherenceSummary] = await Promise.all([
|
|
13
23
|
fetch(apiUrl(`${API_BASE}/stats`)).then(r => r.json()).catch(() => null),
|
|
14
24
|
fetch(apiUrl(`${API_BASE}/stats/shared`)).then(r => r.json()).catch(() => null),
|
|
15
25
|
fetch(apiUrl(`${API_BASE}/stats/most-accessed`, { limit: 10 })).then(r => r.json()).catch(() => null),
|
|
16
26
|
fetch(apiUrl(`${API_BASE}/stats/helpfulness`, { limit: 5 })).then(r => r.json()).catch(() => null),
|
|
27
|
+
fetch(apiUrl(`${API_BASE}/stats/usefulness`, { window: state.kpiWindow })).then(r => r.json()).catch(() => null),
|
|
17
28
|
fetch(apiUrl(`${API_BASE}/stats/retrieval-traces`, { limit: 20 })).then(r => r.json()).catch(() => null),
|
|
29
|
+
fetch(apiUrl(`${API_BASE}/stats/retrieval-review-queue`, { limit: 10 })).then(r => r.json()).catch(() => null),
|
|
18
30
|
fetchAdherenceSummary().catch(() => null)
|
|
19
31
|
]);
|
|
20
32
|
|
|
33
|
+
if (
|
|
34
|
+
refreshRequestId !== state.refreshRequestId ||
|
|
35
|
+
projectAtStart !== state.currentProject ||
|
|
36
|
+
kpiWindowAtStart !== state.kpiWindow
|
|
37
|
+
) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
21
41
|
state.stats = stats;
|
|
22
42
|
state.sharedStats = shared;
|
|
23
43
|
state.mostAccessed = mostAccessed;
|
|
24
44
|
state.helpfulness = helpfulness;
|
|
45
|
+
state.memoryUsefulness = memoryUsefulness;
|
|
25
46
|
state.retrievalTraces = retrievalTraces;
|
|
47
|
+
state.retrievalReviewQueue = retrievalReviewQueue;
|
|
26
48
|
state.adherenceSummary = adherenceSummary;
|
|
27
49
|
|
|
28
50
|
await loadKpiData();
|
|
51
|
+
if (refreshRequestId !== state.refreshRequestId) return;
|
|
29
52
|
|
|
30
53
|
updateStatsUI();
|
|
31
54
|
updateSharedUI();
|
|
@@ -336,6 +359,7 @@ function updateTopAccessedEventsUI() {
|
|
|
336
359
|
|
|
337
360
|
function updateMemoryUsageUI() {
|
|
338
361
|
updateGraduationBars();
|
|
362
|
+
updateMemoryUsefulnessUI();
|
|
339
363
|
updateHelpfulnessUI();
|
|
340
364
|
updateMostHelpfulList();
|
|
341
365
|
updateTopAccessedEventsUI();
|
|
@@ -431,6 +455,78 @@ function updateGraduationBars() {
|
|
|
431
455
|
}).join('');
|
|
432
456
|
}
|
|
433
457
|
|
|
458
|
+
function updateMemoryUsefulnessUI() {
|
|
459
|
+
const scoreEl = document.getElementById('memory-usefulness-score');
|
|
460
|
+
const summaryEl = document.getElementById('memory-usefulness-summary');
|
|
461
|
+
const breakdownEl = document.getElementById('memory-usefulness-breakdown');
|
|
462
|
+
const diagnosticsEl = document.getElementById('memory-usefulness-diagnostics');
|
|
463
|
+
if (!scoreEl || !summaryEl || !breakdownEl) return;
|
|
464
|
+
|
|
465
|
+
const payload = state.memoryUsefulness;
|
|
466
|
+
if (!payload || payload.error || !payload.score) {
|
|
467
|
+
scoreEl.textContent = '-';
|
|
468
|
+
scoreEl.className = 'memory-usefulness-score score-unknown';
|
|
469
|
+
summaryEl.innerHTML = '<span style="color:var(--text-muted);">No usefulness telemetry yet.</span>';
|
|
470
|
+
breakdownEl.innerHTML = '';
|
|
471
|
+
if (diagnosticsEl) diagnosticsEl.innerHTML = '';
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const score = payload.score || {};
|
|
476
|
+
const counts = payload.counts || {};
|
|
477
|
+
const label = score.label || 'unknown';
|
|
478
|
+
const confidencePct = ((score.confidence || 0) * 100).toFixed(0);
|
|
479
|
+
scoreEl.textContent = Number(score.value || 0).toFixed(1).replace(/\.0$/, '');
|
|
480
|
+
scoreEl.className = `memory-usefulness-score score-${label}`;
|
|
481
|
+
|
|
482
|
+
summaryEl.innerHTML = `
|
|
483
|
+
<span class="usefulness-pill usefulness-${escapeHtml(label)}">${escapeHtml(label)}</span>
|
|
484
|
+
<span><strong>${formatNumber(counts.retrievalQueries || 0)}</strong> queries</span>
|
|
485
|
+
<span><strong>${formatNumber(counts.rewrittenQueries || 0)}</strong> rewritten</span>
|
|
486
|
+
<span><strong>${formatNumber(counts.promptCount || 0)}</strong> prompts</span>
|
|
487
|
+
<span><strong>${formatNumber(counts.totalEvaluated || 0)}</strong> evaluated</span>
|
|
488
|
+
<span title="How many input signals were available for the composite score"><strong>${confidencePct}%</strong> confidence</span>
|
|
489
|
+
`;
|
|
490
|
+
|
|
491
|
+
const components = payload.components || [];
|
|
492
|
+
breakdownEl.innerHTML = components.map((component) => {
|
|
493
|
+
const valuePct = `${((component.value || 0) * 100).toFixed(1)}%`;
|
|
494
|
+
const availableClass = component.available ? '' : ' unavailable';
|
|
495
|
+
const availableText = component.available ? valuePct : 'n/a';
|
|
496
|
+
const width = Math.max(0, Math.min(100, (component.value || 0) * 100));
|
|
497
|
+
return `
|
|
498
|
+
<div class="usefulness-component${availableClass}">
|
|
499
|
+
<div class="usefulness-component-row">
|
|
500
|
+
<span>${escapeHtml(component.label || component.key)}</span>
|
|
501
|
+
<strong>${availableText}</strong>
|
|
502
|
+
</div>
|
|
503
|
+
<div class="usefulness-bar-track"><div class="usefulness-bar-fill" style="width:${width}%;"></div></div>
|
|
504
|
+
</div>
|
|
505
|
+
`;
|
|
506
|
+
}).join('');
|
|
507
|
+
|
|
508
|
+
const diagnostics = (payload.diagnostics || []).slice(0, 3);
|
|
509
|
+
if (!diagnosticsEl) return;
|
|
510
|
+
if (diagnostics.length === 0) {
|
|
511
|
+
diagnosticsEl.innerHTML = '<div class="usefulness-diagnostics-empty">No immediate improvement actions.</div>';
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
diagnosticsEl.innerHTML = `
|
|
516
|
+
<div class="usefulness-diagnostics-title">Top improvement actions</div>
|
|
517
|
+
${diagnostics.map((diagnostic) => `
|
|
518
|
+
<div class="usefulness-diagnostic usefulness-diagnostic-${escapeHtml(diagnostic.severity || 'info')}">
|
|
519
|
+
<div class="usefulness-diagnostic-header">
|
|
520
|
+
<span class="usefulness-diagnostic-severity">${escapeHtml(diagnostic.severity || 'info')}</span>
|
|
521
|
+
<strong>${escapeHtml(diagnostic.title || diagnostic.key || 'Improve memory usefulness')}</strong>
|
|
522
|
+
</div>
|
|
523
|
+
<div class="usefulness-diagnostic-detail">${escapeHtml(diagnostic.detail || '')}</div>
|
|
524
|
+
<div class="usefulness-diagnostic-action">${escapeHtml(diagnostic.action || '')}</div>
|
|
525
|
+
</div>
|
|
526
|
+
`).join('')}
|
|
527
|
+
`;
|
|
528
|
+
}
|
|
529
|
+
|
|
434
530
|
function updateHelpfulnessUI() {
|
|
435
531
|
const container = document.getElementById('helpfulness-summary');
|
|
436
532
|
if (!container) return;
|
|
@@ -490,7 +586,68 @@ function updateMostHelpfulList() {
|
|
|
490
586
|
}
|
|
491
587
|
|
|
492
588
|
|
|
589
|
+
function updateRetrievalReviewQueueUI() {
|
|
590
|
+
const summaryEl = document.getElementById('retrieval-review-summary');
|
|
591
|
+
const listEl = document.getElementById('retrieval-review-list');
|
|
592
|
+
if (!summaryEl || !listEl) return;
|
|
593
|
+
|
|
594
|
+
const payload = state.retrievalReviewQueue;
|
|
595
|
+
if (payload?.error) {
|
|
596
|
+
summaryEl.innerHTML = '<span style="color:var(--warning, #FEB019);">Retrieval review queue is temporarily unavailable.</span>';
|
|
597
|
+
listEl.innerHTML = '<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Unable to load bad retrieval cases right now.</div>';
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
const summary = payload?.summary;
|
|
601
|
+
const items = payload?.items || [];
|
|
602
|
+
|
|
603
|
+
if (!summary || !Number.isFinite(summary.reviewItems) || summary.reviewItems === 0) {
|
|
604
|
+
summaryEl.innerHTML = '<span style="color:var(--text-muted);">No retrieval traces need review.</span>';
|
|
605
|
+
listEl.innerHTML = '<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">No bad retrieval cases in the current scan</div>';
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
summaryEl.innerHTML = `
|
|
610
|
+
<div style="display:flex; gap:14px; flex-wrap:wrap; font-size:12px;">
|
|
611
|
+
<span><strong>${formatNumber(summary.reviewItems)}</strong> review items</span>
|
|
612
|
+
<span><strong>${formatNumber(summary.rewrittenNoSelection || 0)}</strong> rewritten no-selection</span>
|
|
613
|
+
<span><strong>${formatNumber(summary.candidateNoSelection || 0)}</strong> candidate no-selection</span>
|
|
614
|
+
<span><strong>${formatNumber(summary.emptyCandidateSet || 0)}</strong> empty candidates</span>
|
|
615
|
+
</div>
|
|
616
|
+
`;
|
|
617
|
+
|
|
618
|
+
listEl.innerHTML = items.slice(0, 10).map((item) => {
|
|
619
|
+
const ts = item.createdAt ? new Date(item.createdAt).toLocaleString() : '-';
|
|
620
|
+
const severityColor = item.severity === 'warn' ? 'var(--warning, #FEB019)' : 'var(--accent-primary)';
|
|
621
|
+
const rewriteKind = item.queryRewriteKind || (item.rewritten ? 'rewritten' : 'none');
|
|
622
|
+
const rewriteBadge = rewriteKind && rewriteKind !== 'none'
|
|
623
|
+
? `<span class="event-type-badge" title="Safe rewrite classification">${escapeHtml(rewriteKind)}</span>`
|
|
624
|
+
: '';
|
|
625
|
+
const candidateIds = (item.candidateEventIds || []).slice(0, 3)
|
|
626
|
+
.map((id) => `<span class="event-type-badge">${escapeHtml((id || '').slice(0, 8))}...</span>`)
|
|
627
|
+
.join(' ');
|
|
628
|
+
const selectedIds = (item.selectedEventIds || []).slice(0, 3)
|
|
629
|
+
.map((id) => `<span class="event-type-badge">${escapeHtml((id || '').slice(0, 8))}...</span>`)
|
|
630
|
+
.join(' ');
|
|
631
|
+
return `
|
|
632
|
+
<div class="shared-item" style="align-items:flex-start; border-left:2px solid ${severityColor};">
|
|
633
|
+
<div class="shared-info" style="align-items:flex-start; flex-direction:column; gap:4px;">
|
|
634
|
+
<span style="font-size:12px; color:var(--text-secondary);"><strong>${escapeHtml(item.title || 'Retrieval trace needs review')}</strong></span>
|
|
635
|
+
<span style="font-size:11px; color:var(--text-muted);">Trace ${escapeHtml((item.traceId || '').slice(0, 18))} · ${ts} · reason=${escapeHtml(item.reason || 'unknown')} · strategy=${escapeHtml(item.strategy || 'auto')} ${rewriteBadge}</span>
|
|
636
|
+
<span style="font-size:11px; color:var(--text-muted);">${escapeHtml(item.detail || '')}</span>
|
|
637
|
+
<span style="font-size:11px; color:var(--text-secondary);"><strong>Action:</strong> ${escapeHtml(item.action || '')}</span>
|
|
638
|
+
<span style="font-size:11px; color:var(--text-muted);">candidates: ${candidateIds || '-'} · selected: ${selectedIds || '-'}</span>
|
|
639
|
+
</div>
|
|
640
|
+
<div style="display:flex; flex-direction:column; align-items:flex-end; gap:2px; min-width:68px;">
|
|
641
|
+
<span style="font-size:13px; font-weight:600; color:${severityColor};">${Number(item.selectedCount || 0)}/${Number(item.candidateCount || 0)}</span>
|
|
642
|
+
<span style="font-size:10px; color:var(--text-muted);">sel/cand</span>
|
|
643
|
+
</div>
|
|
644
|
+
</div>
|
|
645
|
+
`;
|
|
646
|
+
}).join('');
|
|
647
|
+
}
|
|
648
|
+
|
|
493
649
|
function updateRetrievalTraceUI() {
|
|
650
|
+
updateRetrievalReviewQueueUI();
|
|
494
651
|
const summaryEl = document.getElementById('retrieval-trace-summary');
|
|
495
652
|
const listEl = document.getElementById('retrieval-trace-list');
|
|
496
653
|
if (!summaryEl || !listEl) return;
|
|
@@ -506,12 +663,14 @@ function updateRetrievalTraceUI() {
|
|
|
506
663
|
}
|
|
507
664
|
|
|
508
665
|
const selectionRate = ((stats.selectionRate || 0) * 100).toFixed(1);
|
|
666
|
+
const rewriteRate = ((stats.rewriteRate || 0) * 100).toFixed(1);
|
|
509
667
|
summaryEl.innerHTML = `
|
|
510
668
|
<div style="display:flex; gap:14px; flex-wrap:wrap; font-size:12px;">
|
|
511
669
|
<span><strong>${formatNumber(stats.totalQueries)}</strong> queries</span>
|
|
512
670
|
<span><strong>${Number(stats.avgCandidateCount || 0).toFixed(1)}</strong> avg candidates</span>
|
|
513
671
|
<span><strong>${Number(stats.avgSelectedCount || 0).toFixed(1)}</strong> avg selected</span>
|
|
514
672
|
<span><strong>${selectionRate}%</strong> selection rate</span>
|
|
673
|
+
<span title="Share of retrieval queries enriched with previous prompt/assistant context"><strong>${rewriteRate}%</strong> rewrite rate</span>
|
|
515
674
|
</div>
|
|
516
675
|
`;
|
|
517
676
|
|
|
@@ -520,6 +679,10 @@ function updateRetrievalTraceUI() {
|
|
|
520
679
|
const confidence = t.confidence || 'n/a';
|
|
521
680
|
const selected = Number(t.selectedCount || 0);
|
|
522
681
|
const candidates = Number(t.candidateCount || 0);
|
|
682
|
+
const rewriteKind = t.queryRewriteKind || (t.rewritten ? 'rewritten' : 'none');
|
|
683
|
+
const rewriteBadge = rewriteKind && rewriteKind !== 'none'
|
|
684
|
+
? `<span class="event-type-badge" title="Query was enriched before retrieval">${escapeHtml(rewriteKind)}</span>`
|
|
685
|
+
: '';
|
|
523
686
|
const selectedDetails = (t.selectedDetails || []).slice(0, 2);
|
|
524
687
|
const candidateDetails = (t.candidateDetails || []).slice(0, 3);
|
|
525
688
|
const selectedIdsHtml = selectedDetails.length > 0
|
|
@@ -536,8 +699,8 @@ function updateRetrievalTraceUI() {
|
|
|
536
699
|
return `
|
|
537
700
|
<div class="shared-item" style="align-items:flex-start;">
|
|
538
701
|
<div class="shared-info" style="align-items:flex-start; flex-direction:column; gap:4px;">
|
|
539
|
-
<span style="font-size:12px; color:var(--text-secondary);"><strong>
|
|
540
|
-
<span style="font-size:11px; color:var(--text-muted);">${ts} · strategy=${escapeHtml(t.strategy || 'auto')} · conf=${escapeHtml(confidence)}</span>
|
|
702
|
+
<span style="font-size:12px; color:var(--text-secondary);"><strong>Trace:</strong> ${escapeHtml((t.traceId || '').slice(0, 12)) || '-'}</span>
|
|
703
|
+
<span style="font-size:11px; color:var(--text-muted);">${ts} · strategy=${escapeHtml(t.strategy || 'auto')} · conf=${escapeHtml(confidence)} ${rewriteBadge}</span>
|
|
541
704
|
<span style="font-size:11px; color:var(--text-muted);">selected IDs: ${selectedIdsHtml}</span>
|
|
542
705
|
<span style="font-size:11px; color:var(--text-muted);">candidates: ${candidateDetails.map((d) => `<span class=\"event-type-badge\" style=\"cursor:pointer;\" onclick=\"openDetailModal('${d.eventId}')\">${escapeHtml((d.eventId || '').slice(0, 8))}...</span>`).join(' ') || '-'}</span>
|
|
543
706
|
${scoreBreakdownHtml}
|
|
@@ -11,7 +11,9 @@ const state = {
|
|
|
11
11
|
sharedStats: null,
|
|
12
12
|
mostAccessed: null,
|
|
13
13
|
helpfulness: null,
|
|
14
|
+
memoryUsefulness: null,
|
|
14
15
|
retrievalTraces: null,
|
|
16
|
+
retrievalReviewQueue: null,
|
|
15
17
|
adherenceSummary: null,
|
|
16
18
|
adherenceWindow: '24h',
|
|
17
19
|
userPromptSearchQuery: '',
|
|
@@ -22,6 +24,7 @@ const state = {
|
|
|
22
24
|
currentSort: 'recent',
|
|
23
25
|
currentView: 'overview',
|
|
24
26
|
currentProject: '', // empty = global
|
|
27
|
+
refreshRequestId: 0,
|
|
25
28
|
projects: [],
|
|
26
29
|
events: [],
|
|
27
30
|
isLoading: false,
|
package/dist/ui/index.html
CHANGED
|
@@ -340,6 +340,18 @@
|
|
|
340
340
|
<div id="graduation-bars"></div>
|
|
341
341
|
</div>
|
|
342
342
|
|
|
343
|
+
<div style="margin-top:20px;">
|
|
344
|
+
<div class="section-label">Memory Usefulness Score</div>
|
|
345
|
+
<div class="memory-usefulness-panel">
|
|
346
|
+
<div class="memory-usefulness-header">
|
|
347
|
+
<div class="memory-usefulness-score score-unknown" id="memory-usefulness-score">-</div>
|
|
348
|
+
<div id="memory-usefulness-summary" class="memory-usefulness-summary">Loading...</div>
|
|
349
|
+
</div>
|
|
350
|
+
<div id="memory-usefulness-breakdown" class="memory-usefulness-breakdown"></div>
|
|
351
|
+
<div id="memory-usefulness-diagnostics" class="memory-usefulness-diagnostics"></div>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
|
|
343
355
|
<div style="margin-top:20px;">
|
|
344
356
|
<div class="section-label">Helpfulness</div>
|
|
345
357
|
<div id="helpfulness-summary" style="padding:8px 0; font-size:13px; color:var(--text-muted);">Loading...</div>
|
|
@@ -378,6 +390,14 @@
|
|
|
378
390
|
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
379
391
|
</div>
|
|
380
392
|
</div>
|
|
393
|
+
|
|
394
|
+
<div style="margin-top:20px;">
|
|
395
|
+
<div class="section-label">Bad Retrieval Review Queue</div>
|
|
396
|
+
<div id="retrieval-review-summary" style="padding:8px 0; font-size:13px; color:var(--text-muted);">Loading...</div>
|
|
397
|
+
<div id="retrieval-review-list" class="shared-list">
|
|
398
|
+
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
381
401
|
</div>
|
|
382
402
|
|
|
383
403
|
</div>
|
package/dist/ui/style.css
CHANGED
|
@@ -676,6 +676,199 @@ body {
|
|
|
676
676
|
text-align: right;
|
|
677
677
|
}
|
|
678
678
|
|
|
679
|
+
/* Memory Usefulness */
|
|
680
|
+
.memory-usefulness-panel {
|
|
681
|
+
padding: 12px;
|
|
682
|
+
border: 1px solid var(--border-subtle);
|
|
683
|
+
border-radius: 12px;
|
|
684
|
+
background: rgba(255,255,255,0.03);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
.memory-usefulness-header {
|
|
688
|
+
display: flex;
|
|
689
|
+
align-items: center;
|
|
690
|
+
gap: 12px;
|
|
691
|
+
margin-bottom: 12px;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
.memory-usefulness-score {
|
|
695
|
+
min-width: 62px;
|
|
696
|
+
font-size: 30px;
|
|
697
|
+
font-weight: 800;
|
|
698
|
+
line-height: 1;
|
|
699
|
+
letter-spacing: -1px;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
.memory-usefulness-score.score-excellent,
|
|
703
|
+
.memory-usefulness-score.score-good {
|
|
704
|
+
color: var(--success);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
.memory-usefulness-score.score-watch {
|
|
708
|
+
color: var(--warning);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
.memory-usefulness-score.score-low {
|
|
712
|
+
color: var(--error);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
.memory-usefulness-score.score-unknown {
|
|
716
|
+
color: var(--text-muted);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.memory-usefulness-summary {
|
|
720
|
+
display: flex;
|
|
721
|
+
flex-wrap: wrap;
|
|
722
|
+
gap: 6px 10px;
|
|
723
|
+
font-size: 12px;
|
|
724
|
+
color: var(--text-secondary);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
.usefulness-pill {
|
|
728
|
+
padding: 2px 7px;
|
|
729
|
+
border-radius: 999px;
|
|
730
|
+
font-size: 10px;
|
|
731
|
+
font-weight: 800;
|
|
732
|
+
text-transform: uppercase;
|
|
733
|
+
letter-spacing: 0.4px;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
.usefulness-excellent,
|
|
737
|
+
.usefulness-good {
|
|
738
|
+
background: rgba(52, 211, 153, 0.14);
|
|
739
|
+
color: #34D399;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.usefulness-watch {
|
|
743
|
+
background: rgba(254, 176, 25, 0.14);
|
|
744
|
+
color: #FEB019;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.usefulness-low {
|
|
748
|
+
background: rgba(255, 69, 96, 0.14);
|
|
749
|
+
color: #FF4560;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.usefulness-unknown {
|
|
753
|
+
background: rgba(148, 163, 184, 0.14);
|
|
754
|
+
color: #94A3B8;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.memory-usefulness-breakdown {
|
|
758
|
+
display: flex;
|
|
759
|
+
flex-direction: column;
|
|
760
|
+
gap: 8px;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.memory-usefulness-diagnostics {
|
|
764
|
+
margin-top: 12px;
|
|
765
|
+
display: flex;
|
|
766
|
+
flex-direction: column;
|
|
767
|
+
gap: 8px;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
.usefulness-diagnostics-title {
|
|
771
|
+
font-size: 11px;
|
|
772
|
+
font-weight: 800;
|
|
773
|
+
color: var(--text-secondary);
|
|
774
|
+
text-transform: uppercase;
|
|
775
|
+
letter-spacing: 0.4px;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
.usefulness-diagnostic {
|
|
779
|
+
padding: 10px;
|
|
780
|
+
border: 1px solid var(--border-subtle);
|
|
781
|
+
border-radius: 10px;
|
|
782
|
+
background: rgba(255,255,255,0.025);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.usefulness-diagnostic-warn {
|
|
786
|
+
border-color: rgba(254, 176, 25, 0.32);
|
|
787
|
+
background: rgba(254, 176, 25, 0.06);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
.usefulness-diagnostic-info {
|
|
791
|
+
border-color: rgba(0, 240, 255, 0.24);
|
|
792
|
+
background: rgba(0, 240, 255, 0.04);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.usefulness-diagnostic-header {
|
|
796
|
+
display: flex;
|
|
797
|
+
align-items: center;
|
|
798
|
+
gap: 8px;
|
|
799
|
+
font-size: 12px;
|
|
800
|
+
color: var(--text-primary);
|
|
801
|
+
margin-bottom: 5px;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.usefulness-diagnostic-severity {
|
|
805
|
+
padding: 1px 6px;
|
|
806
|
+
border-radius: 999px;
|
|
807
|
+
font-size: 9px;
|
|
808
|
+
font-weight: 800;
|
|
809
|
+
text-transform: uppercase;
|
|
810
|
+
color: var(--bg-primary);
|
|
811
|
+
background: var(--warning);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
.usefulness-diagnostic-info .usefulness-diagnostic-severity {
|
|
815
|
+
background: var(--accent-secondary);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
.usefulness-diagnostic-detail,
|
|
819
|
+
.usefulness-diagnostic-action,
|
|
820
|
+
.usefulness-diagnostics-empty {
|
|
821
|
+
font-size: 11px;
|
|
822
|
+
line-height: 1.45;
|
|
823
|
+
color: var(--text-muted);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.usefulness-diagnostic-action {
|
|
827
|
+
margin-top: 5px;
|
|
828
|
+
color: var(--text-secondary);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.usefulness-diagnostic-action::before {
|
|
832
|
+
content: 'Action: ';
|
|
833
|
+
color: var(--accent-secondary);
|
|
834
|
+
font-weight: 700;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.usefulness-component {
|
|
838
|
+
opacity: 1;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
.usefulness-component.unavailable {
|
|
842
|
+
opacity: 0.45;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
.usefulness-component-row {
|
|
846
|
+
display: flex;
|
|
847
|
+
justify-content: space-between;
|
|
848
|
+
gap: 10px;
|
|
849
|
+
font-size: 11px;
|
|
850
|
+
color: var(--text-secondary);
|
|
851
|
+
margin-bottom: 4px;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.usefulness-component-row strong {
|
|
855
|
+
color: var(--text-primary);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.usefulness-bar-track {
|
|
859
|
+
height: 5px;
|
|
860
|
+
background: rgba(255,255,255,0.05);
|
|
861
|
+
border-radius: 999px;
|
|
862
|
+
overflow: hidden;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.usefulness-bar-fill {
|
|
866
|
+
height: 100%;
|
|
867
|
+
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
|
|
868
|
+
border-radius: 999px;
|
|
869
|
+
transition: width 0.5s;
|
|
870
|
+
}
|
|
871
|
+
|
|
679
872
|
/* Endless Mode */
|
|
680
873
|
.endless-card {
|
|
681
874
|
background: linear-gradient(135deg, rgba(16, 16, 24, 0.6) 0%, rgba(20, 20, 30, 0.6) 100%);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-memory-layer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"description": "Claude Code plugin that learns from conversations to provide personalized assistance",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"ops:health": "npm run ops:sync-gap:report && npm run ops:sync-gap:heal && npm run ops:review:resolve",
|
|
31
31
|
"ops:projects:clean-unknown": "node scripts/delete-unknown-projects.js",
|
|
32
32
|
"benchmark:replay": "tsx scripts/replay-retrieval-benchmark.ts",
|
|
33
|
+
"eval:retrieval-replay": "tsx scripts/replay-retrieval-benchmark.ts --fixture benchmarks/replay/golden-memory-usefulness-v1.json --format markdown --no-per-query --min-query-yield 1 --min-no-match-accuracy 1 --max-forbidden-hits 0 --max-failed-queries 0",
|
|
34
|
+
"eval:retrieval-replay:report": "tsx scripts/replay-retrieval-benchmark.ts --fixture benchmarks/replay/golden-memory-usefulness-v1.json --format markdown --no-per-query",
|
|
35
|
+
"benchmark:replay:promote-review": "tsx scripts/promote-retrieval-review-queue.ts",
|
|
36
|
+
"benchmark:replay:validate-promotion": "tsx scripts/validate-replay-promotion-candidates.ts",
|
|
33
37
|
"benchmark:qrels": "tsx scripts/generate-session-qrels.ts",
|
|
34
38
|
"postinstall": "node scripts/postinstall-embedding-backend.cjs"
|
|
35
39
|
},
|