@monoes/monomindcli 2.7.4 → 2.7.5

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.
Files changed (89) hide show
  1. package/bin/cli.js +17 -1
  2. package/dist/src/commands/doctor-project-checks.d.ts +3 -0
  3. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  4. package/dist/src/commands/doctor-project-checks.js +81 -8
  5. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  6. package/dist/src/commands/doctor.d.ts.map +1 -1
  7. package/dist/src/commands/doctor.js +16 -2
  8. package/dist/src/commands/doctor.js.map +1 -1
  9. package/dist/src/commands/memory-crud.d.ts.map +1 -1
  10. package/dist/src/commands/memory-crud.js +15 -5
  11. package/dist/src/commands/memory-crud.js.map +1 -1
  12. package/dist/src/commands/security-misc.d.ts.map +1 -1
  13. package/dist/src/commands/security-misc.js +7 -2
  14. package/dist/src/commands/security-misc.js.map +1 -1
  15. package/dist/src/init/helpers-generator.d.ts.map +1 -1
  16. package/dist/src/init/helpers-generator.js +5 -0
  17. package/dist/src/init/helpers-generator.js.map +1 -1
  18. package/dist/src/mcp-client.d.ts.map +1 -1
  19. package/dist/src/mcp-client.js +0 -2
  20. package/dist/src/mcp-client.js.map +1 -1
  21. package/dist/src/mcp-tools/agent-tools.js +1 -1
  22. package/dist/src/mcp-tools/agent-tools.js.map +1 -1
  23. package/dist/src/mcp-tools/embeddings-tools.d.ts +2 -0
  24. package/dist/src/mcp-tools/embeddings-tools.d.ts.map +1 -1
  25. package/dist/src/mcp-tools/embeddings-tools.js +11 -1
  26. package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
  27. package/dist/src/mcp-tools/guidance-tools.js +17 -17
  28. package/dist/src/mcp-tools/guidance-tools.js.map +1 -1
  29. package/dist/src/mcp-tools/hive-mind-tools.d.ts +2 -0
  30. package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
  31. package/dist/src/mcp-tools/hive-mind-tools.js +14 -2
  32. package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
  33. package/dist/src/mcp-tools/index.d.ts +0 -1
  34. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  35. package/dist/src/mcp-tools/index.js +0 -1
  36. package/dist/src/mcp-tools/index.js.map +1 -1
  37. package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
  38. package/dist/src/mcp-tools/monograph-tools.js +1 -2
  39. package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
  40. package/dist/src/mcp-tools/neural-tools.js +1 -1
  41. package/dist/src/mcp-tools/neural-tools.js.map +1 -1
  42. package/dist/src/mcp-tools/swarm-tools.js +2 -2
  43. package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
  44. package/dist/src/mcp-tools/transfer-tools.d.ts +2 -0
  45. package/dist/src/mcp-tools/transfer-tools.d.ts.map +1 -1
  46. package/dist/src/mcp-tools/transfer-tools.js +11 -1
  47. package/dist/src/mcp-tools/transfer-tools.js.map +1 -1
  48. package/dist/src/ui/dashboard.html +44 -618
  49. package/dist/src/ui/server.mjs +0 -275
  50. package/dist/src/utils/cosine-similarity.d.ts +2 -2
  51. package/dist/src/utils/cosine-similarity.js +2 -2
  52. package/dist/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +1 -1
  54. package/dist/src/mcp-tools/coherence/causal-infer.d.ts +0 -15
  55. package/dist/src/mcp-tools/coherence/causal-infer.d.ts.map +0 -1
  56. package/dist/src/mcp-tools/coherence/causal-infer.js +0 -333
  57. package/dist/src/mcp-tools/coherence/causal-infer.js.map +0 -1
  58. package/dist/src/mcp-tools/coherence/coherence-check.d.ts +0 -15
  59. package/dist/src/mcp-tools/coherence/coherence-check.d.ts.map +0 -1
  60. package/dist/src/mcp-tools/coherence/coherence-check.js +0 -188
  61. package/dist/src/mcp-tools/coherence/coherence-check.js.map +0 -1
  62. package/dist/src/mcp-tools/coherence/consensus-verify.d.ts +0 -14
  63. package/dist/src/mcp-tools/coherence/consensus-verify.d.ts.map +0 -1
  64. package/dist/src/mcp-tools/coherence/consensus-verify.js +0 -305
  65. package/dist/src/mcp-tools/coherence/consensus-verify.js.map +0 -1
  66. package/dist/src/mcp-tools/coherence/memory-gate.d.ts +0 -16
  67. package/dist/src/mcp-tools/coherence/memory-gate.d.ts.map +0 -1
  68. package/dist/src/mcp-tools/coherence/memory-gate.js +0 -279
  69. package/dist/src/mcp-tools/coherence/memory-gate.js.map +0 -1
  70. package/dist/src/mcp-tools/coherence/quantum-topology.d.ts +0 -15
  71. package/dist/src/mcp-tools/coherence/quantum-topology.d.ts.map +0 -1
  72. package/dist/src/mcp-tools/coherence/quantum-topology.js +0 -400
  73. package/dist/src/mcp-tools/coherence/quantum-topology.js.map +0 -1
  74. package/dist/src/mcp-tools/coherence/spectral-analyze.d.ts +0 -14
  75. package/dist/src/mcp-tools/coherence/spectral-analyze.d.ts.map +0 -1
  76. package/dist/src/mcp-tools/coherence/spectral-analyze.js +0 -312
  77. package/dist/src/mcp-tools/coherence/spectral-analyze.js.map +0 -1
  78. package/dist/src/mcp-tools/coherence/types.d.ts +0 -430
  79. package/dist/src/mcp-tools/coherence/types.d.ts.map +0 -1
  80. package/dist/src/mcp-tools/coherence/types.js +0 -144
  81. package/dist/src/mcp-tools/coherence/types.js.map +0 -1
  82. package/dist/src/mcp-tools/coherence-tools.d.ts +0 -9
  83. package/dist/src/mcp-tools/coherence-tools.d.ts.map +0 -1
  84. package/dist/src/mcp-tools/coherence-tools.js +0 -25
  85. package/dist/src/mcp-tools/coherence-tools.js.map +0 -1
  86. package/dist/src/mcp-tools/daa-tools.d.ts +0 -13
  87. package/dist/src/mcp-tools/daa-tools.d.ts.map +0 -1
  88. package/dist/src/mcp-tools/daa-tools.js +0 -553
  89. package/dist/src/mcp-tools/daa-tools.js.map +0 -1
@@ -1874,22 +1874,6 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1874
1874
  return;
1875
1875
  }
1876
1876
 
1877
- // GET /api/adr-file?file=<name>&dir=<dir> — read a single ADR markdown file
1878
- if (req.method === 'GET' && url === '/api/adr-file') {
1879
- try {
1880
- const qs = new URL(req.url, 'http://localhost').searchParams;
1881
- const dir = qs.get('dir') || projectDir || process.cwd();
1882
- const fname = (qs.get('file') || '').replace(/[/\\]/g, '');
1883
- if (!fname || !fname.endsWith('.md')) { res.writeHead(400); res.end('{"error":"invalid file"}'); return; }
1884
- const fpath = path.join(path.resolve(dir), 'docs', 'adrs', fname);
1885
- if (!fs.existsSync(fpath)) { res.writeHead(404); res.end('{"error":"not found"}'); return; }
1886
- const content = fs.readFileSync(fpath, 'utf8');
1887
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
1888
- res.end(JSON.stringify({ file: fname, content }));
1889
- } catch (err) { res.writeHead(500); res.end(JSON.stringify({ error: err.message })); }
1890
- return;
1891
- }
1892
-
1893
1877
  // ------------------------------------------------------- GET /api/memory-files
1894
1878
  if (req.method === 'GET' && url === '/api/memory-files') {
1895
1879
  try {
@@ -6331,265 +6315,6 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
6331
6315
  return;
6332
6316
  }
6333
6317
 
6334
- // GET /api/second-brain-metrics — aggregated injection analytics from second-brain.jsonl
6335
- if (req.method === 'GET' && url === '/api/second-brain-metrics') {
6336
- try {
6337
- const metricsFile = path.join(projectDir || process.cwd(), '.monomind', 'metrics', 'second-brain.jsonl');
6338
- if (!fs.existsSync(metricsFile)) {
6339
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
6340
- res.end(JSON.stringify({ total: 0, injected: 0, hitRate: 0, methods: {}, avgScore: 0, sparkline: [], scores: [] }));
6341
- return;
6342
- }
6343
- const raw = fs.readFileSync(metricsFile, 'utf8');
6344
- const entries = raw.split('\n').filter(Boolean).map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
6345
- const total = entries.length;
6346
- const injectedCount = entries.filter(e => e.injected).length;
6347
- const hitRate = total > 0 ? injectedCount / total : 0;
6348
- // Method distribution
6349
- const methods = {};
6350
- for (const e of entries) { const m = e.method || 'unknown'; methods[m] = (methods[m] || 0) + 1; }
6351
- // Average top score (only for entries with hits)
6352
- const withScores = entries.filter(e => typeof e.topScore === 'number' && e.topScore !== null);
6353
- const avgScore = withScores.length > 0 ? withScores.reduce((s, e) => s + e.topScore, 0) / withScores.length : 0;
6354
- // Score distribution buckets
6355
- const scoreBuckets = [0, 0, 0, 0, 0]; // <0.3, 0.3-0.5, 0.5-0.7, 0.7-0.9, 0.9+
6356
- for (const e of withScores) {
6357
- const s = e.topScore;
6358
- if (s < 0.3) scoreBuckets[0]++;
6359
- else if (s < 0.5) scoreBuckets[1]++;
6360
- else if (s < 0.7) scoreBuckets[2]++;
6361
- else if (s < 0.9) scoreBuckets[3]++;
6362
- else scoreBuckets[4]++;
6363
- }
6364
- // Sparkline: group by hour for last 24h, then by day for older
6365
- const now = Date.now();
6366
- const h24 = now - 86400000;
6367
- const sparkline = [];
6368
- // Last 24 hours in 2h buckets
6369
- for (let t = h24; t < now; t += 7200000) {
6370
- const bucket = entries.filter(e => e.ts >= t && e.ts < t + 7200000);
6371
- const inj = bucket.filter(e => e.injected).length;
6372
- sparkline.push({ t, total: bucket.length, injected: inj });
6373
- }
6374
- // Top sources from recent entries (last 200)
6375
- const recentSlice = entries.slice(-200);
6376
- const misses = recentSlice.filter(e => !e.injected).length;
6377
- // Route overrides (misroute counts)
6378
- let routeOverrides = {};
6379
- try {
6380
- const overridesFile = path.join(projectDir || process.cwd(), '.monomind', 'metrics', 'route-overrides.json');
6381
- if (fs.existsSync(overridesFile)) routeOverrides = JSON.parse(fs.readFileSync(overridesFile, 'utf8'));
6382
- } catch {}
6383
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
6384
- res.end(JSON.stringify({ total, injected: injectedCount, hitRate: +hitRate.toFixed(3), methods, avgScore: +avgScore.toFixed(3), sparkline, scoreBuckets, recentMisses: misses, recentTotal: recentSlice.length, routeOverrides }));
6385
- } catch (err) {
6386
- res.writeHead(500, { 'Content-Type': 'application/json' });
6387
- res.end(JSON.stringify({ error: err.message }));
6388
- }
6389
- return;
6390
- }
6391
-
6392
- // POST /api/second-brain-route — show query router decision for a given query
6393
- if (req.method === 'POST' && url === '/api/second-brain-route') {
6394
- let body = '';
6395
- req.on('data', c => { body += c; if (body.length > 65536) { req.destroy(); return; } });
6396
- req.on('end', async () => {
6397
- try {
6398
- const { query } = JSON.parse(body || '{}');
6399
- if (!query) { res.writeHead(400, { 'Content-Type': 'application/json' }); res.end('{"error":"query required"}'); return; }
6400
- const routerMod = await import('../memory/query-router.js');
6401
- const route = routerMod.routeQuery(String(query).slice(0, 2000));
6402
- const overrides = routerMod.getRouteOverrides(true);
6403
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
6404
- res.end(JSON.stringify({ route, overrides }));
6405
- } catch (err) {
6406
- res.writeHead(500, { 'Content-Type': 'application/json' });
6407
- res.end(JSON.stringify({ error: err.message }));
6408
- }
6409
- });
6410
- return;
6411
- }
6412
-
6413
- // GET/PUT /api/second-brain-config — read/write Second Brain config (.monomind/second-brain.json)
6414
- if ((req.method === 'GET' || req.method === 'PUT') && url === '/api/second-brain-config') {
6415
- const configFile = path.join(projectDir || process.cwd(), '.monomind', 'second-brain.json');
6416
- if (req.method === 'GET') {
6417
- try {
6418
- let config = { relevanceFloor: 0.35, injectionLimit: 5 };
6419
- try { config = { ...config, ...JSON.parse(fs.readFileSync(configFile, 'utf8')) }; } catch {}
6420
- // Auto-tune suggestion: analyze telemetry to suggest optimal floor
6421
- let suggestion = null;
6422
- try {
6423
- const metricsFile = path.join(projectDir || process.cwd(), '.monomind', 'metrics', 'second-brain.jsonl');
6424
- if (fs.existsSync(metricsFile)) {
6425
- const entries = fs.readFileSync(metricsFile, 'utf8').split('\n').filter(Boolean)
6426
- .map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
6427
- const withScores = entries.filter(e => typeof e.topScore === 'number' && e.topScore !== null);
6428
- if (withScores.length >= 20) {
6429
- const scores = withScores.map(e => e.topScore).sort((a, b) => a - b);
6430
- const p25 = scores[Math.floor(scores.length * 0.25)];
6431
- const hitRate = entries.filter(e => e.injected).length / entries.length;
6432
- // If hit rate is very low (<30%), suggest lowering floor
6433
- // If hit rate is very high (>80%) with low avg scores, suggest raising
6434
- if (hitRate < 0.3 && p25 > 0.2) suggestion = { floor: +(p25 - 0.05).toFixed(2), reason: 'Low hit rate (' + (hitRate * 100).toFixed(0) + '%) — lowering floor may surface more relevant results' };
6435
- else if (hitRate > 0.8 && scores[Math.floor(scores.length * 0.1)] < 0.35) suggestion = { floor: 0.4, reason: 'High hit rate with low-quality matches — raising floor filters noise' };
6436
- }
6437
- }
6438
- } catch {}
6439
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
6440
- res.end(JSON.stringify({ config, suggestion }));
6441
- } catch (err) {
6442
- res.writeHead(500, { 'Content-Type': 'application/json' });
6443
- res.end(JSON.stringify({ error: err.message }));
6444
- }
6445
- return;
6446
- }
6447
- if (req.method === 'PUT') {
6448
- let body = '';
6449
- req.on('data', c => { body += c; if (body.length > 4096) { req.destroy(); return; } });
6450
- req.on('end', () => {
6451
- try {
6452
- const raw = JSON.parse(body || '{}');
6453
- const updates = {};
6454
- if (typeof raw.relevanceFloor === 'number' && raw.relevanceFloor >= 0 && raw.relevanceFloor <= 1) updates.relevanceFloor = raw.relevanceFloor;
6455
- if (typeof raw.injectionLimit === 'number' && raw.injectionLimit >= 1 && raw.injectionLimit <= 50) updates.injectionLimit = Math.floor(raw.injectionLimit);
6456
- if (Object.keys(updates).length === 0) { res.writeHead(400, { 'Content-Type': 'application/json' }); res.end('{"error":"no valid fields to update"}'); return; }
6457
- let config = {};
6458
- try { config = JSON.parse(fs.readFileSync(configFile, 'utf8')); } catch {}
6459
- config = { ...config, ...updates };
6460
- fs.mkdirSync(path.dirname(configFile), { recursive: true });
6461
- fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
6462
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
6463
- res.end(JSON.stringify({ ok: true, config }));
6464
- } catch (err) {
6465
- res.writeHead(500, { 'Content-Type': 'application/json' });
6466
- res.end(JSON.stringify({ error: err.message }));
6467
- }
6468
- });
6469
- return;
6470
- }
6471
- }
6472
-
6473
- // GET /api/second-brain-docs — document-level view from doc-metadata.jsonl
6474
- if (req.method === 'GET' && url === '/api/second-brain-docs') {
6475
- try {
6476
- const d = path.resolve(projectDir || process.cwd());
6477
- const metaFile = path.join(d, '.monomind', 'knowledge', 'doc-metadata.jsonl');
6478
- // Also check global brain
6479
- const globalDir = process.env.MONOMIND_GLOBAL_BRAIN_DIR || path.join(os.homedir(), '.monomind', 'global-brain');
6480
- const globalMetaFile = path.join(globalDir, '.monomind', 'knowledge', 'doc-metadata.jsonl');
6481
- const docs = [];
6482
- let totalSize = 0, totalChunks = 0;
6483
- for (const [file, scope] of [[metaFile, 'project'], [globalMetaFile, 'global']]) {
6484
- if (!fs.existsSync(file)) continue;
6485
- const latest = new Map();
6486
- for (const l of fs.readFileSync(file, 'utf8').split('\n')) {
6487
- if (!l.trim()) continue;
6488
- try {
6489
- const m = JSON.parse(l);
6490
- latest.set(m.filePath + ' ' + m.scope, m);
6491
- } catch {}
6492
- }
6493
- for (const m of latest.values()) {
6494
- if (m.chunkCount < 0) continue;
6495
- const exists = fs.existsSync(m.filePath);
6496
- docs.push({ ...m, brainScope: scope, exists, name: path.basename(m.filePath) });
6497
- totalSize += m.size || 0;
6498
- totalChunks += m.chunkCount || 0;
6499
- }
6500
- }
6501
- docs.sort((a, b) => (b.indexedAt || '').localeCompare(a.indexedAt || ''));
6502
- const globalCount = docs.filter(d => d.brainScope === 'global').length;
6503
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
6504
- res.end(JSON.stringify({ docs, totalDocs: docs.length, totalSize, totalChunks, globalCount, projectCount: docs.length - globalCount }));
6505
- } catch (err) {
6506
- res.writeHead(500, { 'Content-Type': 'application/json' });
6507
- res.end(JSON.stringify({ error: err.message }));
6508
- }
6509
- return;
6510
- }
6511
-
6512
- // GET /api/second-brain-ingest-stream — SSE stream tailing doc-metadata.jsonl for live ingest events
6513
- if (req.method === 'GET' && url === '/api/second-brain-ingest-stream') {
6514
- res.writeHead(200, {
6515
- 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive',
6516
- ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {})
6517
- });
6518
- res.write('data: {"type":"connected"}\n\n');
6519
- const metaFile = path.join(projectDir || process.cwd(), '.monomind', 'knowledge', 'doc-metadata.jsonl');
6520
- let lastSize = 0;
6521
- try { lastSize = fs.statSync(metaFile).size; } catch {}
6522
- function _sseTailFile(filePath, lastSizeRef, eventType, transform) {
6523
- try {
6524
- const stat = fs.statSync(filePath);
6525
- if (stat.size < lastSizeRef.v) { lastSizeRef.v = 0; }
6526
- if (stat.size > lastSizeRef.v) {
6527
- let fd;
6528
- try {
6529
- fd = fs.openSync(filePath, 'r');
6530
- const buf = Buffer.alloc(stat.size - lastSizeRef.v);
6531
- fs.readSync(fd, buf, 0, buf.length, lastSizeRef.v);
6532
- lastSizeRef.v = stat.size;
6533
- const lines = buf.toString('utf8').split('\n').filter(Boolean);
6534
- for (const l of lines) {
6535
- try { const parsed = JSON.parse(l); res.write('data: ' + JSON.stringify(transform(parsed)) + '\n\n'); } catch {}
6536
- }
6537
- } finally { if (fd !== undefined) fs.closeSync(fd); }
6538
- }
6539
- } catch {}
6540
- }
6541
- const metaSize = { v: lastSize };
6542
- const interval = setInterval(() => _sseTailFile(metaFile, metaSize, 'ingest', m => ({ type: 'ingest', doc: { ...m, name: path.basename(m.filePath || '') } })), 2000);
6543
- const metricsFile = path.join(projectDir || process.cwd(), '.monomind', 'metrics', 'second-brain.jsonl');
6544
- const metricsSize = { v: 0 };
6545
- try { metricsSize.v = fs.statSync(metricsFile).size; } catch {}
6546
- const metricsInterval = setInterval(() => _sseTailFile(metricsFile, metricsSize, 'injection', e => ({ type: 'injection', event: e })), 3000);
6547
- req.on('close', () => { clearInterval(interval); clearInterval(metricsInterval); });
6548
- return;
6549
- }
6550
-
6551
- // GET /api/second-brain-kg — knowledge graph triplets + stats for the KG explorer
6552
- if (req.method === 'GET' && url === '/api/second-brain-kg') {
6553
- try {
6554
- const qs = new URL(req.url, 'http://localhost').searchParams;
6555
- const query = (qs.get('q') || '').slice(0, 200);
6556
- const limit = Math.min(parseInt(qs.get('limit') || '50', 10), 200);
6557
- const monoDir = path.join(projectDir || process.cwd(), '.monomind');
6558
- const dbPath = path.join(monoDir, 'memory');
6559
- let stats = { nodes: 0, edges: 0 }, triplets = [], glossary = [];
6560
- try {
6561
- const kg = await import('../memory/memory-kg.js');
6562
- stats = await kg.kgStats({ dbPath });
6563
- glossary = await kg.kgGlossary({ dbPath, limit: 30 });
6564
- if (query) {
6565
- const searchResult = await kg.kgSearch({ query, limit, dbPath });
6566
- triplets = searchResult.triplets || searchResult || [];
6567
- } else {
6568
- const searchResult = await kg.kgSearch({ query: '*', limit, dbPath }).catch(() => null);
6569
- triplets = searchResult ? (searchResult.triplets || searchResult) : [];
6570
- }
6571
- } catch {}
6572
- // Also check palace kg.json as fallback
6573
- if (triplets.length === 0) {
6574
- try {
6575
- const palaceDir = path.join(monoDir, 'palace');
6576
- const kgData = JSON.parse(fs.readFileSync(path.join(palaceDir, 'kg.json'), 'utf8'));
6577
- if (Array.isArray(kgData)) {
6578
- triplets = kgData.slice(0, limit);
6579
- stats.nodes = new Set(kgData.flatMap(t => [t.subject || t.s, t.object || t.o])).size;
6580
- stats.edges = kgData.length;
6581
- }
6582
- } catch {}
6583
- }
6584
- res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
6585
- res.end(JSON.stringify({ stats, triplets, glossary }));
6586
- } catch (err) {
6587
- res.writeHead(500, { 'Content-Type': 'application/json' });
6588
- res.end(JSON.stringify({ error: err.message }));
6589
- }
6590
- return;
6591
- }
6592
-
6593
6318
  // GET /api/mastermind/metrics — aggregate system metrics from token-summary and swarm-activity
6594
6319
  if (req.method === 'GET' && url === '/api/mastermind/metrics') {
6595
6320
  try {
@@ -5,8 +5,8 @@
5
5
  * - memory/intelligence.ts (ReasoningBank.cosineSim)
6
6
  * - mcp-tools/neural-tools.ts (cosineSimilarity)
7
7
  * - mcp-tools/embeddings-tools.ts (cosineSimilarity)
8
- * - mcp-tools/coherence/types.ts (cosineSimilarity)
9
- * - mcp-tools/coherence/coherence-check.ts (cosineSimilarity)
8
+ * - mcp-tools/coherence/types.ts + coherence-check.ts (both since deleted
9
+ * along with the rest of the uncalled coherence_* family)
10
10
  *
11
11
  * This is the single canonical implementation. Accepts number[] or
12
12
  * Float32Array. Handles dimension mismatches gracefully (uses the shorter
@@ -5,8 +5,8 @@
5
5
  * - memory/intelligence.ts (ReasoningBank.cosineSim)
6
6
  * - mcp-tools/neural-tools.ts (cosineSimilarity)
7
7
  * - mcp-tools/embeddings-tools.ts (cosineSimilarity)
8
- * - mcp-tools/coherence/types.ts (cosineSimilarity)
9
- * - mcp-tools/coherence/coherence-check.ts (cosineSimilarity)
8
+ * - mcp-tools/coherence/types.ts + coherence-check.ts (both since deleted
9
+ * along with the rest of the uncalled coherence_* family)
10
10
  *
11
11
  * This is the single canonical implementation. Accepts number[] or
12
12
  * Float32Array. Handles dimension mismatches gracefully (uses the shorter