prism-mcp-server 6.2.0 β 6.2.1
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/README.md +1 -1
- package/dist/dashboard/ui.js +71 -53
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -396,7 +396,7 @@ Soft/hard delete (Art. 17), full export in JSON, Markdown, or Obsidian vault `.z
|
|
|
396
396
|
## π What's New
|
|
397
397
|
|
|
398
398
|
### v6.2 β The "Synthesize & Prune" Phase β
|
|
399
|
-
> **Current stable release (v6.2.
|
|
399
|
+
> **Current stable release (v6.2.1).** The Mind Palace becomes self-organizing.
|
|
400
400
|
|
|
401
401
|
- πΈοΈ **Edge Synthesis ("The Dream Procedure")** β Automated background linker discovers semantically similar but disconnected memory nodes via cosine similarity (β₯ 0.7 threshold). Batch-limited to 50 sources Γ 3 neighbors. New `session_synthesize_edges` tool for on-demand graph enrichment.
|
|
402
402
|
- βοΈ **Graph Pruning (Soft-Prune)** β Configurable strength-based pruning soft-deletes weak links. Includes per-project cooldown, backpressure guards, and sweep budget controls. Enable with `PRISM_GRAPH_PRUNING_ENABLED=true`.
|
package/dist/dashboard/ui.js
CHANGED
|
@@ -1322,6 +1322,17 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
1322
1322
|
<div class="toast-fixed" id="fixedToast"></div>
|
|
1323
1323
|
|
|
1324
1324
|
<script>
|
|
1325
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1326
|
+
// COMPATIBILITY RULE: This entire <script> block MUST use ES5 only.
|
|
1327
|
+
// - Use 'var' (NEVER 'const' or 'let')
|
|
1328
|
+
// - Use 'function(){}' (NEVER '=>' arrow functions)
|
|
1329
|
+
// - NO optional chaining '?.'
|
|
1330
|
+
// - NO template literals (backticks) β use string concatenation
|
|
1331
|
+
// - NO destructuring, spread, or other ES6+ syntax
|
|
1332
|
+
// This HTML is served as a raw template literal; mixing ES6 in the
|
|
1333
|
+
// inline script causes SyntaxError in some browser/context combos.
|
|
1334
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1335
|
+
|
|
1325
1336
|
// βββ TABS & SEARCH (v6.0) βββ
|
|
1326
1337
|
function switchMainTab(tabId) {
|
|
1327
1338
|
document.getElementById('mtab-project').classList.toggle('active', tabId === 'project');
|
|
@@ -1337,14 +1348,14 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
1337
1348
|
}
|
|
1338
1349
|
}
|
|
1339
1350
|
|
|
1340
|
-
|
|
1341
|
-
|
|
1351
|
+
var searchTimeout = null;
|
|
1352
|
+
var searchAbortController = null;
|
|
1342
1353
|
|
|
1343
1354
|
async function performSearch() {
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1355
|
+
var input = document.getElementById('searchInput');
|
|
1356
|
+
var boost = document.getElementById('searchContextBoost');
|
|
1357
|
+
var resultsDiv = document.getElementById('searchResults');
|
|
1358
|
+
var query = input.value.trim();
|
|
1348
1359
|
|
|
1349
1360
|
if (!query) {
|
|
1350
1361
|
if (searchAbortController) searchAbortController.abort();
|
|
@@ -1354,17 +1365,17 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
1354
1365
|
|
|
1355
1366
|
resultsDiv.innerHTML = '<div class="loading" style="padding:2rem;"><span class="spinner"></span> Searching neural memory via embeddings...</div>';
|
|
1356
1367
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
if (project) url +=
|
|
1360
|
-
if (boost.checked) url +=
|
|
1368
|
+
var project = document.getElementById('projectSelect').value;
|
|
1369
|
+
var url = '/api/search?q=' + encodeURIComponent(query);
|
|
1370
|
+
if (project) url += '&project=' + encodeURIComponent(project);
|
|
1371
|
+
if (boost.checked) url += '&boost=true';
|
|
1361
1372
|
|
|
1362
1373
|
if (searchAbortController) searchAbortController.abort();
|
|
1363
1374
|
searchAbortController = new AbortController();
|
|
1364
1375
|
|
|
1365
1376
|
try {
|
|
1366
|
-
|
|
1367
|
-
|
|
1377
|
+
var res = await fetch(url, { signal: searchAbortController.signal });
|
|
1378
|
+
var data = await res.json();
|
|
1368
1379
|
if (data.error) throw new Error(data.error);
|
|
1369
1380
|
|
|
1370
1381
|
if (!data.results || data.results.length === 0) {
|
|
@@ -1373,55 +1384,58 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
1373
1384
|
}
|
|
1374
1385
|
|
|
1375
1386
|
// Extract searchable terms for highlighting (length > 2)
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
? new RegExp(
|
|
1387
|
+
var queryTerms = query.split(/\\s+/).filter(function(w) { return w.length > 2; });
|
|
1388
|
+
var termRegex = queryTerms.length > 0
|
|
1389
|
+
? new RegExp('(' + queryTerms.map(function(w) { return w.replace(/[.*+?^$()|[\\]\\\\{}]/g, '\\\\$&'); }).join('|') + ')', 'gi')
|
|
1379
1390
|
: null;
|
|
1380
1391
|
|
|
1381
1392
|
function highlight(text) {
|
|
1382
|
-
|
|
1393
|
+
var escaped = escapeHtml(text || '');
|
|
1383
1394
|
if (termRegex) {
|
|
1384
1395
|
escaped = escaped.replace(termRegex, '<mark style="background: rgba(168, 85, 247, 0.4); color: inherit; padding: 0 0.1rem; border-radius: 2px;">$1</mark>');
|
|
1385
1396
|
}
|
|
1386
1397
|
return escaped;
|
|
1387
1398
|
}
|
|
1388
1399
|
|
|
1389
|
-
resultsDiv.innerHTML = data.results.map(r
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
<
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
<span class="badge
|
|
1404
|
-
|
|
1405
|
-
</span>
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1400
|
+
resultsDiv.innerHTML = data.results.map(function(r) {
|
|
1401
|
+
var isGraduated = r.importance >= 7;
|
|
1402
|
+
var opacity = isGraduated ? 1 : 0.8;
|
|
1403
|
+
var borderStyle = isGraduated ? 'border-left: 3px solid var(--accent-purple); padding-left: 0.8rem;' : '';
|
|
1404
|
+
var decisionsHtml = '';
|
|
1405
|
+
if (r.decisions && r.decisions.length > 0) {
|
|
1406
|
+
decisionsHtml = '<ul class="tag-list" style="margin-top:0.75rem;">' +
|
|
1407
|
+
r.decisions.map(function(d) { return '<li class="tag">π‘ ' + highlight(d) + '</li>'; }).join('') +
|
|
1408
|
+
'</ul>';
|
|
1409
|
+
}
|
|
1410
|
+
return '<div class="entry" style="opacity: ' + opacity + '; ' + borderStyle + '">' +
|
|
1411
|
+
'<div class="entry-meta" style="justify-content:space-between; margin-bottom:0.5rem;">' +
|
|
1412
|
+
'<span>π ' + escapeHtml(r.project) + ' β’ π ' + new Date(r.session_date || r.created_at || Date.now()).toLocaleDateString() + '</span>' +
|
|
1413
|
+
'<div style="display:flex; gap:0.5rem; font-size:0.75rem;">' +
|
|
1414
|
+
'<span class="badge" title="Similarity Score (Semantic Match)" style="background:rgba(6,182,212,0.1); color:var(--accent-cyan); border:1px solid rgba(6,182,212,0.3);">' +
|
|
1415
|
+
'π― ' + (r.similarity * 100).toFixed(1) + '%' +
|
|
1416
|
+
'</span>' +
|
|
1417
|
+
'<span class="badge badge-purple" title="Ebbinghaus Importance (Recency/Reinforcement)">' +
|
|
1418
|
+
'β ' + (r.importance || 0).toFixed(1) +
|
|
1419
|
+
'</span>' +
|
|
1420
|
+
'</div>' +
|
|
1421
|
+
'</div>' +
|
|
1422
|
+
'<div class="entry-summary" style="font-size:0.9rem; line-height: 1.5;">' + highlight(r.summary) + '</div>' +
|
|
1423
|
+
decisionsHtml +
|
|
1424
|
+
'</div>';
|
|
1413
1425
|
}).join('');
|
|
1414
1426
|
} catch (err) {
|
|
1415
1427
|
if (err.name === 'AbortError') return; // Ignore aborted fetches
|
|
1416
|
-
resultsDiv.innerHTML =
|
|
1428
|
+
resultsDiv.innerHTML = '<div style="padding:1rem; color:var(--accent-rose);">β Failed to search memory: ' + escapeHtml(err.message) + '</div>';
|
|
1417
1429
|
}
|
|
1418
1430
|
}
|
|
1419
1431
|
|
|
1420
|
-
document.getElementById('searchInput')
|
|
1432
|
+
var _searchInput = document.getElementById('searchInput');
|
|
1433
|
+
if (_searchInput) _searchInput.addEventListener('input', function() {
|
|
1421
1434
|
clearTimeout(searchTimeout);
|
|
1422
1435
|
searchTimeout = setTimeout(performSearch, 300);
|
|
1423
1436
|
});
|
|
1424
|
-
document.getElementById('searchContextBoost')
|
|
1437
|
+
var _searchBoost = document.getElementById('searchContextBoost');
|
|
1438
|
+
if (_searchBoost) _searchBoost.addEventListener('change', performSearch);
|
|
1425
1439
|
|
|
1426
1440
|
|
|
1427
1441
|
// Role icon map
|
|
@@ -1451,9 +1465,9 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
1451
1465
|
// Auto-load project list on page load
|
|
1452
1466
|
(async function() {
|
|
1453
1467
|
try {
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1468
|
+
var res = await fetch('/api/projects');
|
|
1469
|
+
var data = await res.json();
|
|
1470
|
+
var select = document.getElementById('projectSelect');
|
|
1457
1471
|
if (data.projects && data.projects.length > 0) {
|
|
1458
1472
|
select.innerHTML = '<option value="">β Select a project β</option>' +
|
|
1459
1473
|
data.projects.map(function(p) { return '<option value="' + p + '">' + p + '</option>'; }).join('');
|
|
@@ -2318,25 +2332,27 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
2318
2332
|
}
|
|
2319
2333
|
|
|
2320
2334
|
async function triggerEdgeSynthesis() {
|
|
2321
|
-
|
|
2335
|
+
var gpf = document.getElementById('graphProjectFilter');
|
|
2336
|
+
var ps = document.getElementById('projectSelect');
|
|
2337
|
+
var project = (gpf ? gpf.value : '') || (ps ? ps.value : '');
|
|
2322
2338
|
if (!project) {
|
|
2323
2339
|
alert("Please select an active project first.");
|
|
2324
2340
|
return;
|
|
2325
2341
|
}
|
|
2326
2342
|
|
|
2327
|
-
|
|
2328
|
-
|
|
2343
|
+
var btn = document.querySelector('button[onclick="triggerEdgeSynthesis()"]');
|
|
2344
|
+
var status = document.getElementById('synthesisStatus');
|
|
2329
2345
|
if (btn) { btn.disabled = true; btn.style.opacity = '0.5'; }
|
|
2330
2346
|
if (status) status.textContent = 'running...';
|
|
2331
2347
|
|
|
2332
2348
|
try {
|
|
2333
|
-
|
|
2349
|
+
var res = await fetch('/api/graph/synthesize', {
|
|
2334
2350
|
method: 'POST',
|
|
2335
2351
|
headers: { 'Content-Type': 'application/json' },
|
|
2336
2352
|
body: JSON.stringify({ project: project, randomize_selection: true, max_entries: 50 })
|
|
2337
2353
|
});
|
|
2338
2354
|
|
|
2339
|
-
|
|
2355
|
+
var data = await res.json();
|
|
2340
2356
|
if (res.ok && data.success) {
|
|
2341
2357
|
if (status) status.textContent = 'β
Created ' + data.newLinks + ' links (Scanned: ' + data.entriesScanned + ')';
|
|
2342
2358
|
setTimeout(loadGraph, 1000); // Reload graph to show new edges
|
|
@@ -2360,7 +2376,9 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
2360
2376
|
async function triggerTestMe() {
|
|
2361
2377
|
var input = document.getElementById('nodeEditorInput');
|
|
2362
2378
|
var oldId = input.dataset.oldId;
|
|
2363
|
-
var
|
|
2379
|
+
var _gpf = document.getElementById('graphProjectFilter');
|
|
2380
|
+
var _ps = document.getElementById('projectSelect');
|
|
2381
|
+
var project = (_gpf ? _gpf.value : '') || (_ps ? _ps.value : '');
|
|
2364
2382
|
|
|
2365
2383
|
if (!oldId || !project) return;
|
|
2366
2384
|
|
|
@@ -2410,7 +2428,7 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
2410
2428
|
'<div class="testme-ans" style="display:none; font-size:0.75rem; color:var(--text-secondary); margin-top:0.4rem; padding-top:0.4rem; border-top:1px dashed var(--border-subtle);">' +
|
|
2411
2429
|
escapeHtml(qa.a) +
|
|
2412
2430
|
'</div>' +
|
|
2413
|
-
'<button onclick="this.previousElementSibling.style.display
|
|
2431
|
+
'<button onclick="this.previousElementSibling.style.display='block'; this.style.display='none'" style="background:transparent; border:none; color:var(--accent-purple); font-size:0.7rem; cursor:pointer; padding:0; margin-top:0.3rem;">Show Answer</button>';
|
|
2414
2432
|
|
|
2415
2433
|
container.appendChild(card);
|
|
2416
2434
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prism-mcp-server",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.1",
|
|
4
4
|
"mcpName": "io.github.dcostenco/prism-mcp",
|
|
5
5
|
"description": "The Mind Palace for AI Agents β persistent memory (SQLite/Supabase), behavioral learning & IDE rules sync, multimodal VLM image captioning, pluggable LLM providers (OpenAI/Anthropic/Gemini/Ollama), OpenTelemetry distributed tracing, GDPR export, multi-agent Hivemind sync, time travel, visual Mind Palace dashboard. Zero-config local mode.",
|
|
6
6
|
"module": "index.ts",
|