@cachly-dev/mcp-server 0.10.67 → 0.10.69
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/src/ckg.d.ts +1 -0
- package/dist/src/ckg.js +20 -0
- package/dist/src/ckg.js.map +1 -1
- package/dist/src/handlers/brain.js +77 -5
- package/dist/src/handlers/brain.js.map +1 -1
- package/dist/src/handlers/fedbrain.js +3 -1
- package/dist/src/handlers/fedbrain.js.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/tools.d.ts +7 -0
- package/dist/src/tools.js +5 -0
- package/dist/src/tools.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/src/ckg.d.ts
CHANGED
|
@@ -40,3 +40,4 @@ export declare function ckgUpsertPersonNode(redis: Redis, handle: string, domain
|
|
|
40
40
|
/** Upsert a File node; returns the node id ("file:{slug}"). */
|
|
41
41
|
export declare function ckgUpsertFileNode(redis: Redis, filePath: string): Promise<string>;
|
|
42
42
|
export declare function ckgUpdateEdge(redis: Redis, from: string, edgeType: string, to: string, success: boolean, partial?: boolean): Promise<void>;
|
|
43
|
+
export declare function ckgRecordCollaboration(redis: Redis, fileId: string, personId: string): Promise<void>;
|
package/dist/src/ckg.js
CHANGED
|
@@ -66,4 +66,24 @@ export async function ckgUpdateEdge(redis, from, edgeType, to, success, partial
|
|
|
66
66
|
await redis.sadd(`cachly:ckg:idx:from:${from}`, key);
|
|
67
67
|
await redis.sadd(`cachly:ckg:idx:to:${to}`, key);
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Phase 3: Collaboration graph. When `personId` touches `fileId`, record a
|
|
71
|
+
* bidirectional `collaborates` edge to every *other* person who has touched the
|
|
72
|
+
* same file. Builds the person↔person graph organically — "who works with whom".
|
|
73
|
+
* Bounded: only the first MAX_CO_TOUCHERS prior touchers are linked, so a hot file
|
|
74
|
+
* touched by hundreds of people can't blow up the write path.
|
|
75
|
+
*/
|
|
76
|
+
const MAX_CO_TOUCHERS = 25;
|
|
77
|
+
export async function ckgRecordCollaboration(redis, fileId, personId) {
|
|
78
|
+
const touchersKey = `cachly:ckg:file:touchers:${fileId}`;
|
|
79
|
+
const priorTouchers = await redis.smembers(touchersKey);
|
|
80
|
+
for (const other of priorTouchers.slice(0, MAX_CO_TOUCHERS)) {
|
|
81
|
+
if (other === personId)
|
|
82
|
+
continue;
|
|
83
|
+
// Symmetric edges so traversal works from either node.
|
|
84
|
+
await ckgUpdateEdge(redis, personId, 'collaborates', other, true);
|
|
85
|
+
await ckgUpdateEdge(redis, other, 'collaborates', personId, true);
|
|
86
|
+
}
|
|
87
|
+
await redis.sadd(touchersKey, personId);
|
|
88
|
+
}
|
|
69
89
|
//# sourceMappingURL=ckg.js.map
|
package/dist/src/ckg.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ckg.js","sourceRoot":"","sources":["../../src/ckg.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ckg.js","sourceRoot":"","sources":["../../src/ckg.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { calculateConfidence, confidenceBadge, STRUCTURED_TEMPLATES, CONFIDENCE_WARN_VALUE, CONFIDENCE_STALE_VALUE, CONFIDENCE_WARN_DAYS } from '../confidence.js';
|
|
3
|
-
import { ckgSlug, extractProblemConcept, ckgUpsertNode, ckgUpdateEdge, ckgUpsertPersonNode, ckgUpsertFileNode } from '../ckg.js';
|
|
3
|
+
import { ckgSlug, extractProblemConcept, ckgUpsertNode, ckgUpdateEdge, ckgUpsertPersonNode, ckgUpsertFileNode, ckgRecordCollaboration } from '../ckg.js';
|
|
4
4
|
import { safeJsonParse, scanKeys } from '../utils.js';
|
|
5
5
|
import { keywordSearch, tokenize, splitMultiQuery, levenshtein, indexVocab as _indexVocab } from '../search.js';
|
|
6
6
|
import { rerankByQuality } from '../rerank.js';
|
|
7
7
|
import { computeEmbedding, hasEmbedProvider } from '../embeddings.js';
|
|
8
8
|
// ── Changelog (shown once per version in session_start) ──────────────────────
|
|
9
|
-
const MCP_VERSION = '0.10.
|
|
9
|
+
const MCP_VERSION = '0.10.69';
|
|
10
10
|
const WHATS_NEW = {
|
|
11
|
+
'0.10.69': [
|
|
12
|
+
`📁 **Personalized context-aware recall (Phase 3)** — pass \`context_files\` to \`smart_recall\``,
|
|
13
|
+
` 🎯 Lessons learned on your current files bubble up — even when the query doesn't name the file`,
|
|
14
|
+
` 🏷️ \`📁 context match\` badge on every file-boosted result so you know WHY it ranked up`,
|
|
15
|
+
` ✅ Works alongside keyword, semantic, CKG, and governance signals — a 6th ranking dimension`,
|
|
16
|
+
],
|
|
17
|
+
'0.10.68': [
|
|
18
|
+
`🤝 **Collaboration graph (Phase 3)** — person↔person edges from shared files`,
|
|
19
|
+
` 👥 \`brain_who_knows\` now shows who the top expert frequently works with`,
|
|
20
|
+
` 🚌 Bus-factor insight: "ask X and Y together — they solved this on shared files"`,
|
|
21
|
+
` 🛡️ Stability: every network call in the agent hot path is now timeout-bounded`,
|
|
22
|
+
],
|
|
11
23
|
'0.10.64': [
|
|
12
24
|
`📈 **The three decisive metrics, now measurable**`,
|
|
13
25
|
` ⏱️ \`brain_metrics()\` — time-to-first-recall, recall-lift, team-knowledge-reuse in one view`,
|
|
@@ -360,6 +372,8 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
360
372
|
for (const fp of file_paths.slice(0, 8)) {
|
|
361
373
|
const fileId = await ckgUpsertFileNode(redis, fp);
|
|
362
374
|
await ckgUpdateEdge(redis, personId, 'touched', fileId, true);
|
|
375
|
+
// Phase 3: link this author to everyone else who touched the same file.
|
|
376
|
+
await ckgRecordCollaboration(redis, fileId, personId);
|
|
363
377
|
}
|
|
364
378
|
}
|
|
365
379
|
catch { /* non-critical */ }
|
|
@@ -519,7 +533,10 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
519
533
|
return `🔍 **Partial matches for \`${topic}\`:**\n\n${results.join('\n\n')}`;
|
|
520
534
|
}
|
|
521
535
|
case 'smart_recall': {
|
|
522
|
-
const { instance_id, query, threshold = 0.78, author: requester = '', } = args;
|
|
536
|
+
const { instance_id, query, threshold = 0.78, author: requester = '', context_files: rawContextFiles = [], } = args;
|
|
537
|
+
const contextFiles = Array.isArray(rawContextFiles)
|
|
538
|
+
? rawContextFiles.filter((f) => typeof f === 'string')
|
|
539
|
+
: [];
|
|
523
540
|
const redis = await getConnection(instance_id);
|
|
524
541
|
// ── Layer 1: Keyword search across ALL brain data (always works, no embedding) ──
|
|
525
542
|
const rawMatches = await keywordSearch(redis, ['cachly:ctx:*', 'cachly:lesson:best:*', 'cachly:idx:*'], query, 10);
|
|
@@ -674,6 +691,26 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
674
691
|
}
|
|
675
692
|
}
|
|
676
693
|
catch { /* non-critical — keyword + semantic always available */ }
|
|
694
|
+
// ── Layer 4: File-context personalization ────────────────────────────────
|
|
695
|
+
// When the caller provides the files they are currently working on, lessons
|
|
696
|
+
// that were learned in the context of those files get a score boost. This
|
|
697
|
+
// surfaces file-specific institutional knowledge even when the query words
|
|
698
|
+
// don't mention the file name — the structural advantage of a graph brain.
|
|
699
|
+
if (contextFiles.length > 0) {
|
|
700
|
+
const ctxSet = new Set(contextFiles.map(f => f.replace(/\\/g, '/')));
|
|
701
|
+
for (const r of hybridMap.values()) {
|
|
702
|
+
if (!r.key.startsWith('cachly:lesson:best:'))
|
|
703
|
+
continue;
|
|
704
|
+
const ld = safeJsonParse(r.content, {});
|
|
705
|
+
const fps = Array.isArray(ld.file_paths)
|
|
706
|
+
? ld.file_paths.filter((f) => typeof f === 'string').map(f => f.replace(/\\/g, '/'))
|
|
707
|
+
: [];
|
|
708
|
+
if (fps.some(f => ctxSet.has(f))) {
|
|
709
|
+
r.hybridScore *= 1.15;
|
|
710
|
+
r.contextBoost = true;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
677
714
|
// Filter private lessons — they are only accessible via exact recall_best_solution
|
|
678
715
|
const hybridResults = [...hybridMap.values()]
|
|
679
716
|
.filter(r => {
|
|
@@ -694,6 +731,11 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
694
731
|
if (crossAuthorThisCall > 0) {
|
|
695
732
|
lines.push(`> 👥 **Team knowledge reuse** — ${crossAuthorThisCall} of these lesson${crossAuthorThisCall !== 1 ? 's were' : ' was'} written by a teammate. This is the value only a shared brain delivers.\n`);
|
|
696
733
|
}
|
|
734
|
+
// File-context personalization banner
|
|
735
|
+
const ctxBoosted = hybridResults.filter(r => r.contextBoost).length;
|
|
736
|
+
if (ctxBoosted > 0) {
|
|
737
|
+
lines.push(`> 📁 **Personalized** — ${ctxBoosted} lesson${ctxBoosted !== 1 ? 's' : ''} boosted because ${ctxBoosted !== 1 ? 'they match' : 'it matches'} your current file context (${contextFiles.slice(0, 3).join(', ')}${contextFiles.length > 3 ? ', …' : ''})\n`);
|
|
738
|
+
}
|
|
697
739
|
// Show sub-query info if multi-topic was detected
|
|
698
740
|
const subQueries = splitMultiQuery(query);
|
|
699
741
|
if (subQueries.length > 1) {
|
|
@@ -751,13 +793,14 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
751
793
|
if (ld.author)
|
|
752
794
|
authorBadge = ` · 👤 ${ld.author}`;
|
|
753
795
|
}
|
|
796
|
+
const contextBadge = r.contextBoost ? ` · 📁 context match` : '';
|
|
754
797
|
const scorePart = r.matchType === 'hybrid'
|
|
755
798
|
? `BM25: ${(r.bm25Score ?? 0).toFixed(2)}, sem: ${((r.semScore ?? 0) * 100).toFixed(0)}%, 🔀 hybrid`
|
|
756
799
|
: r.matchType === 'semantic'
|
|
757
800
|
? `sem: ${((r.semScore ?? 0) * 100).toFixed(0)}%, 🎯 semantic`
|
|
758
801
|
: `BM25: ${(r.bm25Score ?? 0).toFixed(2)}, matched: ${r.matchedWords?.join(', ')}`;
|
|
759
802
|
const preview = r.content.slice(0, 400).replace(/\n/g, ' ');
|
|
760
|
-
lines.push(`**${label}**${authorBadge} _(${scorePart})_`);
|
|
803
|
+
lines.push(`**${label}**${authorBadge}${contextBadge} _(${scorePart})_`);
|
|
761
804
|
lines.push(`> ${preview}${r.content.length > 400 ? '…' : ''}\n`);
|
|
762
805
|
}
|
|
763
806
|
}
|
|
@@ -1941,7 +1984,8 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
1941
1984
|
}
|
|
1942
1985
|
// Step 3: Sort by expertise score (lesson count × avg confidence)
|
|
1943
1986
|
const ranked = [...personScores.entries()]
|
|
1944
|
-
.map(([, s]) => ({
|
|
1987
|
+
.map(([id, s]) => ({
|
|
1988
|
+
id,
|
|
1945
1989
|
handle: s.handle,
|
|
1946
1990
|
lessonCount: s.lessonCount,
|
|
1947
1991
|
avgConfidence: s.totalConfidence / s.lessonCount,
|
|
@@ -1950,6 +1994,31 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
1950
1994
|
}))
|
|
1951
1995
|
.sort((a, b) => (b.lessonCount * b.avgConfidence) - (a.lessonCount * a.avgConfidence))
|
|
1952
1996
|
.slice(0, safeLimit);
|
|
1997
|
+
// Step 4: For the top expert, find frequent collaborators (person↔person edges).
|
|
1998
|
+
const topCollaborators = [];
|
|
1999
|
+
const topExpert = ranked[0];
|
|
2000
|
+
if (topExpert) {
|
|
2001
|
+
try {
|
|
2002
|
+
const edgeKeys = await redis.smembers(`cachly:ckg:idx:from:${topExpert.id}`);
|
|
2003
|
+
const collabs = [];
|
|
2004
|
+
for (const ek of edgeKeys) {
|
|
2005
|
+
const er = await redis.get(ek);
|
|
2006
|
+
if (!er)
|
|
2007
|
+
continue;
|
|
2008
|
+
const edge = safeJsonParse(er, null);
|
|
2009
|
+
if (!edge || edge.edgeType !== 'collaborates')
|
|
2010
|
+
continue;
|
|
2011
|
+
const pr = await redis.get(`cachly:ckg:node:${edge.to}`);
|
|
2012
|
+
const pn = pr ? safeJsonParse(pr, null) : null;
|
|
2013
|
+
if (pn?.handle)
|
|
2014
|
+
collabs.push({ handle: pn.handle, trials: edge.trials });
|
|
2015
|
+
}
|
|
2016
|
+
collabs.sort((a, b) => b.trials - a.trials);
|
|
2017
|
+
for (const c of collabs.slice(0, 3))
|
|
2018
|
+
topCollaborators.push(c.handle);
|
|
2019
|
+
}
|
|
2020
|
+
catch { /* non-critical */ }
|
|
2021
|
+
}
|
|
1953
2022
|
const lines = [
|
|
1954
2023
|
`## 👥 Who Knows About \`${topic}\`?`,
|
|
1955
2024
|
``,
|
|
@@ -1963,6 +2032,9 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
1963
2032
|
const recency = daysSince < 1 ? 'today' : daysSince < 7 ? `${daysSince}d ago` : daysSince < 30 ? `${Math.floor(daysSince / 7)}w ago` : `${Math.floor(daysSince / 30)}mo ago`;
|
|
1964
2033
|
lines.push(`${medal} **${p.handle}** — ${p.lessonCount} lesson${p.lessonCount !== 1 ? 's' : ''} · ${conf}% confidence · last active ${recency}`, ` _domains: ${p.domains}_`, ``);
|
|
1965
2034
|
}
|
|
2035
|
+
if (topCollaborators.length > 0 && topExpert) {
|
|
2036
|
+
lines.push(`🤝 **${topExpert.handle}** frequently works with: ${topCollaborators.map(h => `**${h}**`).join(', ')}`, ` _(ask them together — they've solved structurally similar things on shared files)_`, ``);
|
|
2037
|
+
}
|
|
1966
2038
|
lines.push(`---`, `_Attribution grows with every \`learn_from_attempts(author="...", ...)\` call._`);
|
|
1967
2039
|
return lines.join('\n');
|
|
1968
2040
|
}
|