@graphmemory/server 1.3.0 → 1.3.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.
Files changed (39) hide show
  1. package/dist/api/index.js +4 -4
  2. package/dist/api/rest/code.js +2 -1
  3. package/dist/api/rest/docs.js +2 -1
  4. package/dist/api/rest/embed.js +8 -1
  5. package/dist/api/rest/index.js +4 -3
  6. package/dist/api/rest/knowledge.js +4 -2
  7. package/dist/api/rest/skills.js +2 -1
  8. package/dist/api/rest/tasks.js +2 -1
  9. package/dist/api/rest/validation.js +41 -40
  10. package/dist/api/rest/websocket.js +24 -7
  11. package/dist/api/tools/knowledge/add-attachment.js +2 -1
  12. package/dist/api/tools/skills/add-attachment.js +2 -1
  13. package/dist/api/tools/tasks/add-attachment.js +2 -1
  14. package/dist/cli/index.js +5 -4
  15. package/dist/cli/indexer.js +2 -1
  16. package/dist/graphs/attachment-types.js +5 -0
  17. package/dist/graphs/code.js +34 -8
  18. package/dist/graphs/docs.js +5 -3
  19. package/dist/graphs/file-index.js +5 -3
  20. package/dist/graphs/knowledge.js +11 -4
  21. package/dist/graphs/skill.js +12 -5
  22. package/dist/graphs/task.js +12 -5
  23. package/dist/lib/defaults.js +78 -0
  24. package/dist/lib/embedder.js +11 -12
  25. package/dist/lib/embedding-codec.js +3 -5
  26. package/dist/lib/graph-persistence.js +68 -0
  27. package/dist/lib/mirror-watcher.js +4 -3
  28. package/dist/lib/parsers/docs.js +2 -1
  29. package/dist/lib/parsers/languages/typescript.js +34 -17
  30. package/dist/lib/project-manager.js +7 -1
  31. package/dist/lib/search/bm25.js +5 -4
  32. package/dist/lib/search/code.js +2 -1
  33. package/dist/lib/search/docs.js +2 -1
  34. package/dist/lib/search/file-index.js +2 -1
  35. package/dist/lib/search/files.js +3 -2
  36. package/dist/lib/search/knowledge.js +2 -1
  37. package/dist/lib/search/skills.js +2 -1
  38. package/dist/lib/search/tasks.js +2 -1
  39. package/package.json +5 -2
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.BM25Index = void 0;
8
8
  exports.tokenize = tokenize;
9
9
  exports.rrfFuse = rrfFuse;
10
+ const defaults_1 = require("../../lib/defaults");
10
11
  // ---------------------------------------------------------------------------
11
12
  // Tokenizer
12
13
  // ---------------------------------------------------------------------------
@@ -56,8 +57,8 @@ class BM25Index {
56
57
  textExtractor;
57
58
  constructor(textExtractor, opts) {
58
59
  this.textExtractor = textExtractor;
59
- this.k1 = opts?.k1 ?? 1.2;
60
- this.b = opts?.b ?? 0.75;
60
+ this.k1 = opts?.k1 ?? defaults_1.BM25_K1;
61
+ this.b = opts?.b ?? defaults_1.BM25_B;
61
62
  }
62
63
  get size() {
63
64
  return this.docs.size;
@@ -129,7 +130,7 @@ class BM25Index {
129
130
  continue;
130
131
  const docFreq = this.df.get(term) ?? 0;
131
132
  // IDF: log((N - df + 0.5) / (df + 0.5) + 1)
132
- const idf = Math.log((N - docFreq + 0.5) / (docFreq + 0.5) + 1);
133
+ const idf = Math.log((N - docFreq + defaults_1.BM25_IDF_OFFSET) / (docFreq + defaults_1.BM25_IDF_OFFSET) + 1);
133
134
  // TF saturation: (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * dl/avgdl))
134
135
  const tfNorm = (tf * (this.k1 + 1)) / (tf + this.k1 * (1 - this.b + this.b * doc.length / avgDl));
135
136
  docScore += idf * tfNorm;
@@ -151,7 +152,7 @@ exports.BM25Index = BM25Index;
151
152
  *
152
153
  * Nodes appearing in only one list get rank = Infinity for the other → only 1/(k+rank) from one source.
153
154
  */
154
- function rrfFuse(vectorScores, bm25Scores, k = 60) {
155
+ function rrfFuse(vectorScores, bm25Scores, k = defaults_1.RRF_K) {
155
156
  // Build ranked lists (sorted desc by score, rank starts at 1)
156
157
  const vectorRank = buildRankMap(vectorScores);
157
158
  const bm25Rank = buildRankMap(bm25Scores);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.searchCode = searchCode;
4
4
  const embedder_1 = require("../../lib/embedder");
5
5
  const bm25_1 = require("../../lib/search/bm25");
6
+ const defaults_1 = require("../../lib/defaults");
6
7
  /**
7
8
  * Semantic search over the code graph.
8
9
  *
@@ -12,7 +13,7 @@ const bm25_1 = require("../../lib/search/bm25");
12
13
  * 4. De-duplicate, re-filter, sort, cap at `maxResults`.
13
14
  */
14
15
  function searchCode(graph, queryEmbedding, options = {}) {
15
- const { topK = 5, bfsDepth = 1, maxResults = 20, minScore = 0.3, bfsDecay = 0.8, includeBody = false, queryText, bm25Index, searchMode = 'hybrid', rrfK = 60 } = options;
16
+ const { topK = defaults_1.SEARCH_TOP_K, bfsDepth = defaults_1.SEARCH_BFS_DEPTH, maxResults = defaults_1.SEARCH_MAX_RESULTS, minScore = defaults_1.SEARCH_MIN_SCORE_CODE, bfsDecay = defaults_1.SEARCH_BFS_DECAY, includeBody = false, queryText, bm25Index, searchMode = 'hybrid', rrfK = defaults_1.RRF_K } = options;
16
17
  const useVector = searchMode !== 'keyword';
17
18
  const useBm25 = searchMode !== 'vector' && !!queryText && !!bm25Index;
18
19
  // --- 1. Score all nodes ---
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.search = search;
4
4
  const embedder_1 = require("../../lib/embedder");
5
5
  const bm25_1 = require("../../lib/search/bm25");
6
+ const defaults_1 = require("../../lib/defaults");
6
7
  /**
7
8
  * Semantic search over the graph.
8
9
  *
@@ -15,7 +16,7 @@ const bm25_1 = require("../../lib/search/bm25");
15
16
  * 5. De-duplicate and return results sorted by score, capped at `maxResults`.
16
17
  */
17
18
  function search(graph, queryEmbedding, options = {}) {
18
- const { topK = 5, bfsDepth = 1, maxResults = 20, minScore = 0.5, bfsDecay = 0.8, queryText, bm25Index, searchMode = 'hybrid', rrfK = 60 } = options;
19
+ const { topK = defaults_1.SEARCH_TOP_K, bfsDepth = defaults_1.SEARCH_BFS_DEPTH, maxResults = defaults_1.SEARCH_MAX_RESULTS, minScore = defaults_1.SEARCH_MIN_SCORE, bfsDecay = defaults_1.SEARCH_BFS_DECAY, queryText, bm25Index, searchMode = 'hybrid', rrfK = defaults_1.RRF_K } = options;
19
20
  const useVector = searchMode !== 'keyword';
20
21
  const useBm25 = searchMode !== 'vector' && !!queryText && !!bm25Index;
21
22
  // --- 1. Score all nodes ---
@@ -2,13 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.searchFileIndex = searchFileIndex;
4
4
  const embedder_1 = require("../../lib/embedder");
5
+ const defaults_1 = require("../../lib/defaults");
5
6
  /**
6
7
  * Semantic search over file nodes by path embedding.
7
8
  * Only searches file nodes (directories have empty embeddings).
8
9
  * Pure cosine similarity, no BFS expansion.
9
10
  */
10
11
  function searchFileIndex(graph, queryEmbedding, options = {}) {
11
- const { topK = 10, minScore = 0.3 } = options;
12
+ const { topK = defaults_1.FILE_SEARCH_TOP_K, minScore = defaults_1.SEARCH_MIN_SCORE_FILES } = options;
12
13
  const scored = [];
13
14
  graph.forEachNode((_, attrs) => {
14
15
  if (attrs.kind !== 'file' || attrs.embedding.length === 0)
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.searchDocFiles = searchDocFiles;
4
4
  exports.searchCodeFiles = searchCodeFiles;
5
5
  const embedder_1 = require("../../lib/embedder");
6
+ const defaults_1 = require("../../lib/defaults");
6
7
  function searchDocFiles(graph, queryEmbedding, options = {}) {
7
- const { topK = 10, minScore = 0.3 } = options;
8
+ const { topK = defaults_1.FILE_SEARCH_TOP_K, minScore = defaults_1.SEARCH_MIN_SCORE_FILES } = options;
8
9
  // Collect root chunks (level=1) that have a fileEmbedding
9
10
  const scored = [];
10
11
  graph.forEachNode((_, attrs) => {
@@ -33,7 +34,7 @@ function searchDocFiles(graph, queryEmbedding, options = {}) {
33
34
  }));
34
35
  }
35
36
  function searchCodeFiles(graph, queryEmbedding, options = {}) {
36
- const { topK = 10, minScore = 0.3 } = options;
37
+ const { topK = defaults_1.FILE_SEARCH_TOP_K, minScore = defaults_1.SEARCH_MIN_SCORE_FILES } = options;
37
38
  // Collect file nodes that have a fileEmbedding
38
39
  const scored = [];
39
40
  graph.forEachNode((_, attrs) => {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.searchKnowledge = searchKnowledge;
4
4
  const embedder_1 = require("../../lib/embedder");
5
5
  const bm25_1 = require("../../lib/search/bm25");
6
+ const defaults_1 = require("../../lib/defaults");
6
7
  /**
7
8
  * Semantic search over the knowledge graph.
8
9
  *
@@ -12,7 +13,7 @@ const bm25_1 = require("../../lib/search/bm25");
12
13
  * 4. De-duplicate, re-filter, sort, cap at `maxResults`.
13
14
  */
14
15
  function searchKnowledge(graph, queryEmbedding, options = {}) {
15
- const { topK = 5, bfsDepth = 1, maxResults = 20, minScore = 0.5, bfsDecay = 0.8, queryText, bm25Index, searchMode = 'hybrid', rrfK = 60 } = options;
16
+ const { topK = defaults_1.SEARCH_TOP_K, bfsDepth = defaults_1.SEARCH_BFS_DEPTH, maxResults = defaults_1.SEARCH_MAX_RESULTS, minScore = defaults_1.SEARCH_MIN_SCORE, bfsDecay = defaults_1.SEARCH_BFS_DECAY, queryText, bm25Index, searchMode = 'hybrid', rrfK = defaults_1.RRF_K } = options;
16
17
  const useVector = searchMode !== 'keyword';
17
18
  const useBm25 = searchMode !== 'vector' && !!queryText && !!bm25Index;
18
19
  // --- 1. Score all nodes (skip proxy nodes) ---
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.searchSkills = searchSkills;
4
4
  const embedder_1 = require("../../lib/embedder");
5
5
  const bm25_1 = require("../../lib/search/bm25");
6
+ const defaults_1 = require("../../lib/defaults");
6
7
  /**
7
8
  * Semantic search over the skill graph.
8
9
  *
@@ -12,7 +13,7 @@ const bm25_1 = require("../../lib/search/bm25");
12
13
  * 4. De-duplicate, re-filter, sort, cap at `maxResults`.
13
14
  */
14
15
  function searchSkills(graph, queryEmbedding, options = {}) {
15
- const { topK = 5, bfsDepth = 1, maxResults = 20, minScore = 0.5, bfsDecay = 0.8, queryText, bm25Index, searchMode = 'hybrid', rrfK = 60 } = options;
16
+ const { topK = defaults_1.SEARCH_TOP_K, bfsDepth = defaults_1.SEARCH_BFS_DEPTH, maxResults = defaults_1.SEARCH_MAX_RESULTS, minScore = defaults_1.SEARCH_MIN_SCORE, bfsDecay = defaults_1.SEARCH_BFS_DECAY, queryText, bm25Index, searchMode = 'hybrid', rrfK = defaults_1.RRF_K } = options;
16
17
  const useVector = searchMode !== 'keyword';
17
18
  const useBm25 = searchMode !== 'vector' && !!queryText && !!bm25Index;
18
19
  // --- 1. Score all nodes (skip proxy nodes) ---
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.searchTasks = searchTasks;
4
4
  const embedder_1 = require("../../lib/embedder");
5
5
  const bm25_1 = require("../../lib/search/bm25");
6
+ const defaults_1 = require("../../lib/defaults");
6
7
  /**
7
8
  * Semantic search over the task graph.
8
9
  *
@@ -12,7 +13,7 @@ const bm25_1 = require("../../lib/search/bm25");
12
13
  * 4. De-duplicate, re-filter, sort, cap at `maxResults`.
13
14
  */
14
15
  function searchTasks(graph, queryEmbedding, options = {}) {
15
- const { topK = 5, bfsDepth = 1, maxResults = 20, minScore = 0.5, bfsDecay = 0.8, queryText, bm25Index, searchMode = 'hybrid', rrfK = 60 } = options;
16
+ const { topK = defaults_1.SEARCH_TOP_K, bfsDepth = defaults_1.SEARCH_BFS_DEPTH, maxResults = defaults_1.SEARCH_MAX_RESULTS, minScore = defaults_1.SEARCH_MIN_SCORE, bfsDecay = defaults_1.SEARCH_BFS_DECAY, queryText, bm25Index, searchMode = 'hybrid', rrfK = defaults_1.RRF_K } = options;
16
17
  const useVector = searchMode !== 'keyword';
17
18
  const useBm25 = searchMode !== 'vector' && !!queryText && !!bm25Index;
18
19
  // --- 1. Score all nodes (skip proxy nodes) ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphmemory/server",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "MCP server for semantic graph memory from markdown files",
5
5
  "main": "dist/cli/index.js",
6
6
  "bin": {
@@ -15,7 +15,10 @@
15
15
  "cli": "node dist/cli/index.js",
16
16
  "cli:dev": "tsx src/cli/index.ts",
17
17
  "test": "NODE_OPTIONS='--experimental-vm-modules' jest",
18
- "test:watch": "NODE_OPTIONS='--experimental-vm-modules' jest --watch"
18
+ "test:watch": "NODE_OPTIONS='--experimental-vm-modules' jest --watch",
19
+ "site:dev": "cd site && npm start",
20
+ "site:build": "cd site && npm run build",
21
+ "site:serve": "cd site && npm run serve"
19
22
  },
20
23
  "repository": {
21
24
  "type": "git",