claude-memory-layer 1.0.40 → 1.0.41
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 +4305 -171
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +8753 -4293
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +1339 -40
- package/dist/hooks/post-tool-use.js.map +4 -4
- package/dist/hooks/semantic-daemon.js +1339 -40
- package/dist/hooks/semantic-daemon.js.map +4 -4
- package/dist/hooks/session-end.js +1339 -40
- package/dist/hooks/session-end.js.map +4 -4
- package/dist/hooks/session-start.js +1339 -40
- package/dist/hooks/session-start.js.map +4 -4
- package/dist/hooks/stop.js +1339 -40
- package/dist/hooks/stop.js.map +4 -4
- package/dist/hooks/user-prompt-submit.js +1341 -42
- package/dist/hooks/user-prompt-submit.js.map +4 -4
- package/dist/index.js +10080 -5605
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +4389 -159
- package/dist/mcp/index.js.map +4 -4
- package/dist/server/api/index.js +1592 -42
- package/dist/server/api/index.js.map +4 -4
- package/dist/server/index.js +1592 -42
- package/dist/server/index.js.map +4 -4
- package/dist/services/memory-service.js +1339 -40
- package/dist/services/memory-service.js.map +4 -4
- package/dist/ui/assets/js/bootstrap.js +2 -0
- package/dist/ui/assets/js/overview.js +137 -1
- package/dist/ui/assets/js/state.js +1 -0
- package/dist/ui/index.html +53 -0
- package/package.json +2 -2
|
@@ -77,8 +77,10 @@ function setupEventListeners() {
|
|
|
77
77
|
});
|
|
78
78
|
await loadKpiData();
|
|
79
79
|
await loadMemoryUsefulnessData();
|
|
80
|
+
await loadOperationsStatsData();
|
|
80
81
|
updateKpiCardsUI();
|
|
81
82
|
updateMemoryUsefulnessUI();
|
|
83
|
+
updateOperationsStatsUI();
|
|
82
84
|
renderKpiTrendChart();
|
|
83
85
|
});
|
|
84
86
|
});
|
|
@@ -10,6 +10,16 @@ async function loadMemoryUsefulnessData() {
|
|
|
10
10
|
.catch(() => null);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
function operationStatsWindowDays() {
|
|
14
|
+
return state.kpiWindow === '30d' ? 30 : 7;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function loadOperationsStatsData() {
|
|
18
|
+
state.operationsStats = await fetch(apiUrl(`${API_BASE}/stats/operations`, { windowDays: operationStatsWindowDays() }))
|
|
19
|
+
.then(r => r.ok ? r.json() : null)
|
|
20
|
+
.catch(() => null);
|
|
21
|
+
}
|
|
22
|
+
|
|
13
23
|
async function refreshData() {
|
|
14
24
|
const btn = document.getElementById('refresh-btn');
|
|
15
25
|
if(btn) btn.classList.add('loading');
|
|
@@ -19,7 +29,7 @@ async function refreshData() {
|
|
|
19
29
|
const kpiWindowAtStart = state.kpiWindow;
|
|
20
30
|
|
|
21
31
|
try {
|
|
22
|
-
const [stats, shared, mostAccessed, helpfulness, memoryUsefulness, retrievalTraces, retrievalReviewQueue, adherenceSummary] = await Promise.all([
|
|
32
|
+
const [stats, shared, mostAccessed, helpfulness, memoryUsefulness, retrievalTraces, retrievalReviewQueue, operationsStats, adherenceSummary] = await Promise.all([
|
|
23
33
|
fetch(apiUrl(`${API_BASE}/stats`)).then(r => r.json()).catch(() => null),
|
|
24
34
|
fetch(apiUrl(`${API_BASE}/stats/shared`)).then(r => r.json()).catch(() => null),
|
|
25
35
|
fetch(apiUrl(`${API_BASE}/stats/most-accessed`, { limit: 10 })).then(r => r.json()).catch(() => null),
|
|
@@ -27,6 +37,7 @@ async function refreshData() {
|
|
|
27
37
|
fetch(apiUrl(`${API_BASE}/stats/usefulness`, { window: state.kpiWindow })).then(r => r.json()).catch(() => null),
|
|
28
38
|
fetch(apiUrl(`${API_BASE}/stats/retrieval-traces`, { limit: 20 })).then(r => r.json()).catch(() => null),
|
|
29
39
|
fetch(apiUrl(`${API_BASE}/stats/retrieval-review-queue`, { limit: 10 })).then(r => r.json()).catch(() => null),
|
|
40
|
+
fetch(apiUrl(`${API_BASE}/stats/operations`, { windowDays: operationStatsWindowDays() })).then(r => r.ok ? r.json() : null).catch(() => null),
|
|
30
41
|
fetchAdherenceSummary().catch(() => null)
|
|
31
42
|
]);
|
|
32
43
|
|
|
@@ -45,6 +56,7 @@ async function refreshData() {
|
|
|
45
56
|
state.memoryUsefulness = memoryUsefulness;
|
|
46
57
|
state.retrievalTraces = retrievalTraces;
|
|
47
58
|
state.retrievalReviewQueue = retrievalReviewQueue;
|
|
59
|
+
state.operationsStats = operationsStats;
|
|
48
60
|
state.adherenceSummary = adherenceSummary;
|
|
49
61
|
|
|
50
62
|
await loadKpiData();
|
|
@@ -365,6 +377,130 @@ function updateMemoryUsageUI() {
|
|
|
365
377
|
updateTopAccessedEventsUI();
|
|
366
378
|
updateAdherenceSummaryUI();
|
|
367
379
|
updateRetrievalTraceUI();
|
|
380
|
+
updateOperationsStatsUI();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function operationCount(value) {
|
|
384
|
+
const count = Number(value || 0);
|
|
385
|
+
return Number.isFinite(count) && count > 0 ? count : 0;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function operationEmpty(message) {
|
|
389
|
+
return `<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">${escapeHtml(message)}</div>`;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function operationRows(rows, labelKey, countKey, emptyMessage, labelFormatter) {
|
|
393
|
+
const safeRows = Array.isArray(rows) ? rows : [];
|
|
394
|
+
if (safeRows.length === 0) return operationEmpty(emptyMessage);
|
|
395
|
+
return safeRows.map(row => {
|
|
396
|
+
const label = labelFormatter ? labelFormatter(row) : row?.[labelKey];
|
|
397
|
+
return `
|
|
398
|
+
<div class="shared-item">
|
|
399
|
+
<div class="shared-info" style="min-width:0;">
|
|
400
|
+
<span style="font-size:12px; color:var(--text-secondary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${escapeHtml(label || 'unknown')}</span>
|
|
401
|
+
</div>
|
|
402
|
+
<div class="shared-count">${formatNumber(operationCount(row?.[countKey]))}</div>
|
|
403
|
+
</div>
|
|
404
|
+
`;
|
|
405
|
+
}).join('');
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function updateOperationsStatsUI() {
|
|
409
|
+
const payload = state.operationsStats;
|
|
410
|
+
const summaryEl = document.getElementById('operations-stats-summary');
|
|
411
|
+
const facetsEl = document.getElementById('operations-facets-list');
|
|
412
|
+
const actionsEl = document.getElementById('operations-actions-list');
|
|
413
|
+
const leasesEl = document.getElementById('operations-leases-list');
|
|
414
|
+
const retentionEl = document.getElementById('operations-retention-list');
|
|
415
|
+
const governanceEl = document.getElementById('operations-governance-list');
|
|
416
|
+
const lessonsEl = document.getElementById('operations-lessons-list');
|
|
417
|
+
|
|
418
|
+
if (!summaryEl && !facetsEl && !actionsEl && !leasesEl && !retentionEl && !governanceEl && !lessonsEl) return;
|
|
419
|
+
|
|
420
|
+
if (!payload) {
|
|
421
|
+
if (summaryEl) summaryEl.innerHTML = '<span style="color:var(--text-muted);">Operation aggregates unavailable</span>';
|
|
422
|
+
if (facetsEl) facetsEl.innerHTML = operationEmpty('Operation aggregate data unavailable');
|
|
423
|
+
if (actionsEl) actionsEl.innerHTML = operationEmpty('Operation aggregate data unavailable');
|
|
424
|
+
if (leasesEl) leasesEl.innerHTML = operationEmpty('Operation aggregate data unavailable');
|
|
425
|
+
if (retentionEl) retentionEl.innerHTML = operationEmpty('Operation aggregate data unavailable');
|
|
426
|
+
if (governanceEl) governanceEl.innerHTML = operationEmpty('Operation aggregate data unavailable');
|
|
427
|
+
if (lessonsEl) lessonsEl.innerHTML = operationEmpty('Operation aggregate data unavailable');
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const available = payload.projection?.available !== false && payload.projection?.databaseExists !== false;
|
|
432
|
+
if (summaryEl) {
|
|
433
|
+
if (!available) {
|
|
434
|
+
summaryEl.innerHTML = '<span style="color:var(--text-muted);">Operation projections unavailable</span>';
|
|
435
|
+
} else {
|
|
436
|
+
summaryEl.innerHTML = `
|
|
437
|
+
<div style="display:flex; gap:10px; flex-wrap:wrap; font-size:13px; color:var(--text-secondary);">
|
|
438
|
+
<span><strong>${formatNumber(operationCount(payload.facets?.totalAssignments))} facets</strong></span>
|
|
439
|
+
<span><strong>${formatNumber(operationCount(payload.actions?.total))} actions</strong></span>
|
|
440
|
+
<span><strong>${formatNumber(operationCount(payload.leases?.totalActive))} active leases</strong></span>
|
|
441
|
+
<span><strong>${formatNumber(operationCount(payload.retention?.total))} retention decisions</strong></span>
|
|
442
|
+
<span><strong>${formatNumber(operationCount(payload.governanceAudit?.total))} audits</strong></span>
|
|
443
|
+
<span><strong>${formatNumber(operationCount(payload.lessons?.total))} lessons</strong></span>
|
|
444
|
+
</div>
|
|
445
|
+
`;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (!available) {
|
|
450
|
+
if (facetsEl) facetsEl.innerHTML = operationEmpty('No facet aggregates');
|
|
451
|
+
if (actionsEl) actionsEl.innerHTML = operationEmpty('No action status data');
|
|
452
|
+
if (leasesEl) leasesEl.innerHTML = operationEmpty('No active leases');
|
|
453
|
+
if (retentionEl) retentionEl.innerHTML = operationEmpty('No retention decisions');
|
|
454
|
+
if (governanceEl) governanceEl.innerHTML = operationEmpty('No governance audit activity');
|
|
455
|
+
if (lessonsEl) lessonsEl.innerHTML = operationEmpty('No lesson confidence data');
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (facetsEl) {
|
|
460
|
+
const distributions = Array.isArray(payload.facets?.distribution) ? payload.facets.distribution : [];
|
|
461
|
+
facetsEl.innerHTML = distributions.length === 0
|
|
462
|
+
? operationEmpty('No facet aggregates')
|
|
463
|
+
: distributions.map(item => {
|
|
464
|
+
const valueCount = Array.isArray(item?.values) ? item.values.reduce((sum, row) => sum + operationCount(row?.count), 0) : 0;
|
|
465
|
+
const otherCount = operationCount(item?.other);
|
|
466
|
+
const bucketCount = (Array.isArray(item?.values) ? item.values.length : 0) + (otherCount > 0 ? 1 : 0);
|
|
467
|
+
return `
|
|
468
|
+
<div class="shared-item">
|
|
469
|
+
<div class="shared-info" style="min-width:0;">
|
|
470
|
+
<span style="font-size:12px; color:var(--text-secondary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${escapeHtml(item?.dimension || 'unknown')}</span>
|
|
471
|
+
</div>
|
|
472
|
+
<div style="display:flex; flex-direction:column; align-items:flex-end; gap:2px; min-width:72px;">
|
|
473
|
+
<span style="font-size:15px; font-weight:700; color:var(--accent-primary);">${formatNumber(valueCount + otherCount)}</span>
|
|
474
|
+
<span style="font-size:10px; color:var(--text-muted);">${bucketCount} value buckets</span>
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
477
|
+
`;
|
|
478
|
+
}).join('');
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (actionsEl) actionsEl.innerHTML = operationRows(payload.actions?.byStatus, 'status', 'count', 'No action status data');
|
|
482
|
+
if (leasesEl) leasesEl.innerHTML = operationRows(payload.leases?.activeByTargetType, 'targetType', 'count', 'No active leases');
|
|
483
|
+
if (retentionEl) retentionEl.innerHTML = operationRows(payload.retention?.byDecision, 'decision', 'count', 'No retention decisions');
|
|
484
|
+
if (governanceEl) {
|
|
485
|
+
const days = Array.isArray(payload.governanceAudit?.operationsByDay) ? payload.governanceAudit.operationsByDay : [];
|
|
486
|
+
governanceEl.innerHTML = days.length === 0
|
|
487
|
+
? operationEmpty('No governance audit activity')
|
|
488
|
+
: days.map(day => {
|
|
489
|
+
const operations = (Array.isArray(day?.operations) ? day.operations : [])
|
|
490
|
+
.map(op => `${escapeHtml(op?.operation || 'unknown')}: ${formatNumber(operationCount(op?.count))}`)
|
|
491
|
+
.join(' · ');
|
|
492
|
+
return `
|
|
493
|
+
<div class="shared-item">
|
|
494
|
+
<div class="shared-info" style="flex-direction:column; align-items:flex-start; gap:2px; min-width:0;">
|
|
495
|
+
<span style="font-size:12px; color:var(--text-secondary);">${escapeHtml(day?.date || 'unknown')}</span>
|
|
496
|
+
<span style="font-size:10px; color:var(--text-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:220px;">${operations || 'no operations'}</span>
|
|
497
|
+
</div>
|
|
498
|
+
<div class="shared-count">${formatNumber(operationCount(day?.total))}</div>
|
|
499
|
+
</div>
|
|
500
|
+
`;
|
|
501
|
+
}).join('');
|
|
502
|
+
}
|
|
503
|
+
if (lessonsEl) lessonsEl.innerHTML = operationRows(payload.lessons?.confidenceBuckets, 'bucket', 'count', 'No lesson confidence data');
|
|
368
504
|
}
|
|
369
505
|
|
|
370
506
|
function adherenceWindowToMs(window) {
|
package/dist/ui/index.html
CHANGED
|
@@ -400,6 +400,59 @@
|
|
|
400
400
|
</div>
|
|
401
401
|
</div>
|
|
402
402
|
|
|
403
|
+
<!-- Memory Operations -->
|
|
404
|
+
<div class="card">
|
|
405
|
+
<div class="card-header">
|
|
406
|
+
<div class="card-title">
|
|
407
|
+
<i class="ri-stack-line"></i>
|
|
408
|
+
<span>Memory Operations</span>
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
<div id="operations-stats-summary" style="padding:8px 0; font-size:13px; color:var(--text-muted);">Loading operation aggregates...</div>
|
|
412
|
+
|
|
413
|
+
<div style="margin-top:16px;">
|
|
414
|
+
<div class="section-label">Facet Dimensions</div>
|
|
415
|
+
<div id="operations-facets-list" class="shared-list">
|
|
416
|
+
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
417
|
+
</div>
|
|
418
|
+
</div>
|
|
419
|
+
|
|
420
|
+
<div style="margin-top:16px;">
|
|
421
|
+
<div class="section-label">Action Statuses</div>
|
|
422
|
+
<div id="operations-actions-list" class="shared-list">
|
|
423
|
+
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
|
|
427
|
+
<div style="margin-top:16px;">
|
|
428
|
+
<div class="section-label">Active Lease Types</div>
|
|
429
|
+
<div id="operations-leases-list" class="shared-list">
|
|
430
|
+
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
431
|
+
</div>
|
|
432
|
+
</div>
|
|
433
|
+
|
|
434
|
+
<div style="margin-top:16px;">
|
|
435
|
+
<div class="section-label">Retention Decisions</div>
|
|
436
|
+
<div id="operations-retention-list" class="shared-list">
|
|
437
|
+
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
438
|
+
</div>
|
|
439
|
+
</div>
|
|
440
|
+
|
|
441
|
+
<div style="margin-top:16px;">
|
|
442
|
+
<div class="section-label">Governance Audit by Day</div>
|
|
443
|
+
<div id="operations-governance-list" class="shared-list">
|
|
444
|
+
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
445
|
+
</div>
|
|
446
|
+
</div>
|
|
447
|
+
|
|
448
|
+
<div style="margin-top:16px;">
|
|
449
|
+
<div class="section-label">Lesson Confidence</div>
|
|
450
|
+
<div id="operations-lessons-list" class="shared-list">
|
|
451
|
+
<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
|
|
452
|
+
</div>
|
|
453
|
+
</div>
|
|
454
|
+
</div>
|
|
455
|
+
|
|
403
456
|
</div>
|
|
404
457
|
|
|
405
458
|
</div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-memory-layer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.41",
|
|
4
4
|
"description": "Claude Code plugin that learns from conversations to provide personalized assistance",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"ops:heartbeat": "bash scripts/heartbeat-memory-orchestrator.sh",
|
|
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
|
-
"benchmark:replay": "tsx scripts/replay-retrieval-benchmark.ts",
|
|
32
|
+
"benchmark:replay": "tsx scripts/replay-retrieval-benchmark.ts --min-query-yield 1 --min-no-match-accuracy 1 --max-forbidden-hits 0 --max-failed-queries 0",
|
|
33
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
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
35
|
"benchmark:replay:promote-review": "tsx scripts/promote-retrieval-review-queue.ts",
|