ai-mind-map 1.1.0

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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +554 -0
  3. package/dist/change-tracker/change-log.d.ts +160 -0
  4. package/dist/change-tracker/change-log.d.ts.map +1 -0
  5. package/dist/change-tracker/change-log.js +507 -0
  6. package/dist/change-tracker/change-log.js.map +1 -0
  7. package/dist/change-tracker/diff-engine.d.ts +149 -0
  8. package/dist/change-tracker/diff-engine.d.ts.map +1 -0
  9. package/dist/change-tracker/diff-engine.js +530 -0
  10. package/dist/change-tracker/diff-engine.js.map +1 -0
  11. package/dist/change-tracker/watcher.d.ts +137 -0
  12. package/dist/change-tracker/watcher.d.ts.map +1 -0
  13. package/dist/change-tracker/watcher.js +300 -0
  14. package/dist/change-tracker/watcher.js.map +1 -0
  15. package/dist/cli.d.ts +20 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +937 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/config.d.ts +38 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +222 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/context/compressor.d.ts +49 -0
  24. package/dist/context/compressor.d.ts.map +1 -0
  25. package/dist/context/compressor.js +769 -0
  26. package/dist/context/compressor.js.map +1 -0
  27. package/dist/context/progressive-disclosure.d.ts +71 -0
  28. package/dist/context/progressive-disclosure.d.ts.map +1 -0
  29. package/dist/context/progressive-disclosure.js +470 -0
  30. package/dist/context/progressive-disclosure.js.map +1 -0
  31. package/dist/context/token-budget.d.ts +121 -0
  32. package/dist/context/token-budget.d.ts.map +1 -0
  33. package/dist/context/token-budget.js +282 -0
  34. package/dist/context/token-budget.js.map +1 -0
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +944 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/install.d.ts +66 -0
  40. package/dist/install.d.ts.map +1 -0
  41. package/dist/install.js +946 -0
  42. package/dist/install.js.map +1 -0
  43. package/dist/knowledge-graph/architecture.d.ts +213 -0
  44. package/dist/knowledge-graph/architecture.d.ts.map +1 -0
  45. package/dist/knowledge-graph/architecture.js +585 -0
  46. package/dist/knowledge-graph/architecture.js.map +1 -0
  47. package/dist/knowledge-graph/cypher.d.ts +113 -0
  48. package/dist/knowledge-graph/cypher.d.ts.map +1 -0
  49. package/dist/knowledge-graph/cypher.js +1051 -0
  50. package/dist/knowledge-graph/cypher.js.map +1 -0
  51. package/dist/knowledge-graph/dead-code.d.ts +121 -0
  52. package/dist/knowledge-graph/dead-code.d.ts.map +1 -0
  53. package/dist/knowledge-graph/dead-code.js +331 -0
  54. package/dist/knowledge-graph/dead-code.js.map +1 -0
  55. package/dist/knowledge-graph/flow-analyzer.d.ts +167 -0
  56. package/dist/knowledge-graph/flow-analyzer.d.ts.map +1 -0
  57. package/dist/knowledge-graph/flow-analyzer.js +739 -0
  58. package/dist/knowledge-graph/flow-analyzer.js.map +1 -0
  59. package/dist/knowledge-graph/graph.d.ts +291 -0
  60. package/dist/knowledge-graph/graph.d.ts.map +1 -0
  61. package/dist/knowledge-graph/graph.js +978 -0
  62. package/dist/knowledge-graph/graph.js.map +1 -0
  63. package/dist/knowledge-graph/index.d.ts +17 -0
  64. package/dist/knowledge-graph/index.d.ts.map +1 -0
  65. package/dist/knowledge-graph/index.js +14 -0
  66. package/dist/knowledge-graph/index.js.map +1 -0
  67. package/dist/knowledge-graph/indexer.d.ts +112 -0
  68. package/dist/knowledge-graph/indexer.d.ts.map +1 -0
  69. package/dist/knowledge-graph/indexer.js +506 -0
  70. package/dist/knowledge-graph/indexer.js.map +1 -0
  71. package/dist/knowledge-graph/pagerank.d.ts +141 -0
  72. package/dist/knowledge-graph/pagerank.d.ts.map +1 -0
  73. package/dist/knowledge-graph/pagerank.js +493 -0
  74. package/dist/knowledge-graph/pagerank.js.map +1 -0
  75. package/dist/knowledge-graph/parser.d.ts +55 -0
  76. package/dist/knowledge-graph/parser.d.ts.map +1 -0
  77. package/dist/knowledge-graph/parser.js +1090 -0
  78. package/dist/knowledge-graph/parser.js.map +1 -0
  79. package/dist/knowledge-graph/snapshot.d.ts +107 -0
  80. package/dist/knowledge-graph/snapshot.d.ts.map +1 -0
  81. package/dist/knowledge-graph/snapshot.js +435 -0
  82. package/dist/knowledge-graph/snapshot.js.map +1 -0
  83. package/dist/memory/decision-log.d.ts +151 -0
  84. package/dist/memory/decision-log.d.ts.map +1 -0
  85. package/dist/memory/decision-log.js +482 -0
  86. package/dist/memory/decision-log.js.map +1 -0
  87. package/dist/memory/persistent-memory.d.ts +182 -0
  88. package/dist/memory/persistent-memory.d.ts.map +1 -0
  89. package/dist/memory/persistent-memory.js +579 -0
  90. package/dist/memory/persistent-memory.js.map +1 -0
  91. package/dist/memory/session-memory.d.ts +165 -0
  92. package/dist/memory/session-memory.d.ts.map +1 -0
  93. package/dist/memory/session-memory.js +382 -0
  94. package/dist/memory/session-memory.js.map +1 -0
  95. package/dist/stress-test.d.ts +10 -0
  96. package/dist/stress-test.d.ts.map +1 -0
  97. package/dist/stress-test.js +258 -0
  98. package/dist/stress-test.js.map +1 -0
  99. package/dist/tools/advanced-tools.d.ts +32 -0
  100. package/dist/tools/advanced-tools.d.ts.map +1 -0
  101. package/dist/tools/advanced-tools.js +480 -0
  102. package/dist/tools/advanced-tools.js.map +1 -0
  103. package/dist/tools/change-tools.d.ts +76 -0
  104. package/dist/tools/change-tools.d.ts.map +1 -0
  105. package/dist/tools/change-tools.js +93 -0
  106. package/dist/tools/change-tools.js.map +1 -0
  107. package/dist/tools/context-tools.d.ts +68 -0
  108. package/dist/tools/context-tools.d.ts.map +1 -0
  109. package/dist/tools/context-tools.js +141 -0
  110. package/dist/tools/context-tools.js.map +1 -0
  111. package/dist/tools/debug-tools.d.ts +25 -0
  112. package/dist/tools/debug-tools.d.ts.map +1 -0
  113. package/dist/tools/debug-tools.js +286 -0
  114. package/dist/tools/debug-tools.js.map +1 -0
  115. package/dist/tools/evolving-tools.d.ts +23 -0
  116. package/dist/tools/evolving-tools.d.ts.map +1 -0
  117. package/dist/tools/evolving-tools.js +207 -0
  118. package/dist/tools/evolving-tools.js.map +1 -0
  119. package/dist/tools/flow-tools.d.ts +24 -0
  120. package/dist/tools/flow-tools.d.ts.map +1 -0
  121. package/dist/tools/flow-tools.js +265 -0
  122. package/dist/tools/flow-tools.js.map +1 -0
  123. package/dist/tools/graph-tools.d.ts +71 -0
  124. package/dist/tools/graph-tools.d.ts.map +1 -0
  125. package/dist/tools/graph-tools.js +165 -0
  126. package/dist/tools/graph-tools.js.map +1 -0
  127. package/dist/tools/memory-tools.d.ts +62 -0
  128. package/dist/tools/memory-tools.d.ts.map +1 -0
  129. package/dist/tools/memory-tools.js +195 -0
  130. package/dist/tools/memory-tools.js.map +1 -0
  131. package/dist/tools/smart-tools.d.ts +23 -0
  132. package/dist/tools/smart-tools.d.ts.map +1 -0
  133. package/dist/tools/smart-tools.js +482 -0
  134. package/dist/tools/smart-tools.js.map +1 -0
  135. package/dist/tools/snapshot-tools.d.ts +19 -0
  136. package/dist/tools/snapshot-tools.d.ts.map +1 -0
  137. package/dist/tools/snapshot-tools.js +149 -0
  138. package/dist/tools/snapshot-tools.js.map +1 -0
  139. package/dist/types.d.ts +181 -0
  140. package/dist/types.d.ts.map +1 -0
  141. package/dist/types.js +45 -0
  142. package/dist/types.js.map +1 -0
  143. package/dist/utils/logger.d.ts +59 -0
  144. package/dist/utils/logger.d.ts.map +1 -0
  145. package/dist/utils/logger.js +142 -0
  146. package/dist/utils/logger.js.map +1 -0
  147. package/dist/utils/token-counter.d.ts +51 -0
  148. package/dist/utils/token-counter.d.ts.map +1 -0
  149. package/dist/utils/token-counter.js +181 -0
  150. package/dist/utils/token-counter.js.map +1 -0
  151. package/install.ps1 +321 -0
  152. package/install.sh +345 -0
  153. package/package.json +94 -0
  154. package/setup.bat +62 -0
@@ -0,0 +1,506 @@
1
+ /**
2
+ * AI Mind Map — Codebase Indexer (Full & Incremental)
3
+ *
4
+ * Scans a project's source files, parses each with the tree-sitter/regex parser,
5
+ * and stores extracted structural information in the knowledge graph.
6
+ *
7
+ * Supports full re-indexing and incremental updates (only re-parse changed files).
8
+ * Respects .gitignore patterns and custom ignore lists.
9
+ *
10
+ * Inspired by CocoIndex's incremental approach and Cursor's Merkle tree.
11
+ */
12
+ import { readFileSync } from 'node:fs';
13
+ import { readFile, stat } from 'node:fs/promises';
14
+ import { relative, join } from 'node:path';
15
+ import { glob } from 'glob';
16
+ import ignore from 'ignore';
17
+ import { parseFile, parseFiles, isSupportedFile, detectLanguage, getSupportedExtensions, generateContentHash, } from './parser.js';
18
+ /** Maximum file size to index (default 512KB). Files larger than this are skipped to prevent OOM. */
19
+ const MAX_FILE_SIZE_BYTES = 512 * 1024;
20
+ // ============================================================
21
+ // Indexer Class
22
+ // ============================================================
23
+ /**
24
+ * Codebase indexer that scans, parses, and indexes source files
25
+ * into the knowledge graph.
26
+ */
27
+ export class Indexer {
28
+ graph;
29
+ config;
30
+ ig;
31
+ constructor(graph, config) {
32
+ this.graph = graph;
33
+ this.config = config;
34
+ this.ig = ignore();
35
+ // Load .gitignore patterns
36
+ this.loadIgnorePatterns();
37
+ }
38
+ /** Load ignore patterns from .gitignore and config */
39
+ loadIgnorePatterns() {
40
+ // Add config-specified ignore patterns
41
+ if (this.config.ignore.length > 0) {
42
+ this.ig.add(this.config.ignore);
43
+ }
44
+ // Try to read .gitignore
45
+ try {
46
+ const gitignorePath = join(this.config.projectRoot, '.gitignore');
47
+ const gitignoreContent = readFileSync(gitignorePath, 'utf-8');
48
+ this.ig.add(gitignoreContent);
49
+ }
50
+ catch {
51
+ // No .gitignore file, continue
52
+ }
53
+ // Try nested .gitignore files
54
+ try {
55
+ const nestedIgnores = [
56
+ join(this.config.projectRoot, 'src', '.gitignore'),
57
+ join(this.config.projectRoot, 'packages', '.gitignore'),
58
+ ];
59
+ for (const p of nestedIgnores) {
60
+ try {
61
+ const content = readFileSync(p, 'utf-8');
62
+ this.ig.add(content);
63
+ }
64
+ catch {
65
+ // Skip non-existent files
66
+ }
67
+ }
68
+ }
69
+ catch {
70
+ // Skip
71
+ }
72
+ }
73
+ /**
74
+ * Scan the project directory for indexable source files.
75
+ *
76
+ * Respects .gitignore and custom ignore patterns.
77
+ * Skips binary files and files exceeding maxFileSize.
78
+ */
79
+ async scanFiles() {
80
+ const extensions = getSupportedExtensions();
81
+ // Build glob patterns from supported extensions
82
+ const patterns = extensions.map(ext => `**/*${ext}`);
83
+ // Find all matching files
84
+ const allFiles = [];
85
+ for (const pattern of patterns) {
86
+ const matches = await glob(pattern, {
87
+ cwd: this.config.projectRoot,
88
+ absolute: true,
89
+ nodir: true,
90
+ dot: false,
91
+ ignore: this.config.ignore.map(p => {
92
+ // Convert simple names to glob patterns
93
+ if (!p.includes('/') && !p.includes('*')) {
94
+ return `**/${p}/**`;
95
+ }
96
+ return p;
97
+ }),
98
+ });
99
+ allFiles.push(...matches);
100
+ }
101
+ // De-duplicate
102
+ const uniqueFiles = [...new Set(allFiles)];
103
+ // Filter through ignore patterns and size checks
104
+ const validFiles = [];
105
+ for (const absPath of uniqueFiles) {
106
+ const relPath = relative(this.config.projectRoot, absPath).replace(/\\/g, '/');
107
+ // Check ignore patterns
108
+ if (this.ig.ignores(relPath))
109
+ continue;
110
+ // Check file size
111
+ try {
112
+ const fileStat = await stat(absPath);
113
+ if (fileStat.size > this.config.maxFileSize)
114
+ continue;
115
+ if (fileStat.size === 0)
116
+ continue;
117
+ }
118
+ catch {
119
+ continue;
120
+ }
121
+ // Check if it's a supported source file
122
+ if (!isSupportedFile(absPath))
123
+ continue;
124
+ validFiles.push(absPath);
125
+ }
126
+ return validFiles.sort();
127
+ }
128
+ /**
129
+ * Perform a full index of the entire codebase.
130
+ *
131
+ * Scans all files, parses each, and stores results in the graph.
132
+ * Clears existing data before indexing.
133
+ *
134
+ * @param onProgress - Optional progress callback
135
+ * @returns Indexing statistics
136
+ */
137
+ async fullIndex(onProgress) {
138
+ const startTime = Date.now();
139
+ const stats = {
140
+ filesScanned: 0,
141
+ filesParsed: 0,
142
+ filesSkipped: 0,
143
+ filesDeleted: 0,
144
+ nodesCreated: 0,
145
+ edgesCreated: 0,
146
+ parseErrors: 0,
147
+ durationMs: 0,
148
+ languages: {},
149
+ };
150
+ // Phase 1: Scanning
151
+ onProgress?.({
152
+ phase: 'scanning',
153
+ current: 0,
154
+ total: 0,
155
+ message: 'Scanning project for source files...',
156
+ });
157
+ const files = await this.scanFiles();
158
+ stats.filesScanned = files.length;
159
+ if (files.length === 0) {
160
+ onProgress?.({
161
+ phase: 'complete',
162
+ current: 0,
163
+ total: 0,
164
+ message: 'No source files found to index.',
165
+ });
166
+ stats.durationMs = Date.now() - startTime;
167
+ return stats;
168
+ }
169
+ // Clear existing graph data
170
+ this.graph.clear();
171
+ // Phase 2: Parsing
172
+ onProgress?.({
173
+ phase: 'parsing',
174
+ current: 0,
175
+ total: files.length,
176
+ message: `Parsing ${files.length} files...`,
177
+ });
178
+ const parseResults = await parseFiles(files, 8, (current, total) => {
179
+ onProgress?.({
180
+ phase: 'parsing',
181
+ current,
182
+ total,
183
+ currentFile: files[Math.min(current, files.length - 1)],
184
+ message: `Parsed ${current}/${total} files`,
185
+ });
186
+ });
187
+ // Phase 3: Storing
188
+ onProgress?.({
189
+ phase: 'storing',
190
+ current: 0,
191
+ total: parseResults.length,
192
+ message: 'Storing parsed data in knowledge graph...',
193
+ });
194
+ for (let i = 0; i < parseResults.length; i++) {
195
+ const result = parseResults[i];
196
+ // If any single file fails, log and continue
197
+ try {
198
+ if (result.nodes.length === 0 && result.parseErrors.length > 0) {
199
+ stats.filesSkipped++;
200
+ stats.parseErrors += result.parseErrors.length;
201
+ continue;
202
+ }
203
+ stats.filesParsed++;
204
+ stats.nodesCreated += result.nodes.length;
205
+ stats.edgesCreated += result.edges.length;
206
+ // Track language distribution
207
+ if (result.language !== 'unknown') {
208
+ stats.languages[result.language] = (stats.languages[result.language] ?? 0) + 1;
209
+ }
210
+ if (result.parseErrors.length > 0) {
211
+ stats.parseErrors += result.parseErrors.length;
212
+ }
213
+ // Store in graph
214
+ this.graph.replaceFileData(result.filePath, result.nodes, result.edges);
215
+ if (i % 50 === 0) {
216
+ onProgress?.({
217
+ phase: 'storing',
218
+ current: i + 1,
219
+ total: parseResults.length,
220
+ currentFile: result.filePath,
221
+ message: `Stored ${i + 1}/${parseResults.length} files`,
222
+ });
223
+ }
224
+ }
225
+ catch {
226
+ stats.parseErrors++;
227
+ }
228
+ }
229
+ // Phase 4: Complete
230
+ stats.durationMs = Date.now() - startTime;
231
+ onProgress?.({
232
+ phase: 'complete',
233
+ current: stats.filesParsed,
234
+ total: stats.filesScanned,
235
+ message: `Indexing complete: ${stats.filesParsed} files, ${stats.nodesCreated} nodes, ${stats.edgesCreated} edges in ${stats.durationMs}ms`,
236
+ });
237
+ return stats;
238
+ }
239
+ /**
240
+ * Perform an incremental index — only re-parse files that have changed.
241
+ *
242
+ * Detects changes by comparing content hashes stored in the graph
243
+ * against current file contents.
244
+ *
245
+ * @param onProgress - Optional progress callback
246
+ * @returns Indexing statistics
247
+ */
248
+ async incrementalIndex(onProgress) {
249
+ const startTime = Date.now();
250
+ const stats = {
251
+ filesScanned: 0,
252
+ filesParsed: 0,
253
+ filesSkipped: 0,
254
+ filesDeleted: 0,
255
+ nodesCreated: 0,
256
+ edgesCreated: 0,
257
+ parseErrors: 0,
258
+ durationMs: 0,
259
+ languages: {},
260
+ };
261
+ // Phase 1: Scanning
262
+ onProgress?.({
263
+ phase: 'scanning',
264
+ current: 0,
265
+ total: 0,
266
+ message: 'Scanning for changes...',
267
+ });
268
+ const currentFiles = await this.scanFiles();
269
+ stats.filesScanned = currentFiles.length;
270
+ const indexedFiles = new Set(this.graph.getIndexedFiles());
271
+ const currentFileSet = new Set(currentFiles);
272
+ // Find files to add/update and files to delete
273
+ const filesToParse = [];
274
+ const filesToDelete = [];
275
+ // Check for new or modified files
276
+ for (const filePath of currentFiles) {
277
+ const existingHash = this.graph.getFileHash(filePath);
278
+ if (!existingHash) {
279
+ // New file
280
+ filesToParse.push(filePath);
281
+ continue;
282
+ }
283
+ // Check if content has changed
284
+ try {
285
+ const content = await readFile(filePath, 'utf-8');
286
+ const currentHash = generateContentHash(content);
287
+ if (currentHash !== existingHash) {
288
+ filesToParse.push(filePath);
289
+ }
290
+ else {
291
+ stats.filesSkipped++;
292
+ }
293
+ }
294
+ catch {
295
+ stats.filesSkipped++;
296
+ }
297
+ }
298
+ // Check for deleted files
299
+ for (const indexedFile of indexedFiles) {
300
+ if (!currentFileSet.has(indexedFile)) {
301
+ filesToDelete.push(indexedFile);
302
+ }
303
+ }
304
+ // Phase 2: Handle deletions
305
+ if (filesToDelete.length > 0) {
306
+ onProgress?.({
307
+ phase: 'cleanup',
308
+ current: 0,
309
+ total: filesToDelete.length,
310
+ message: `Removing ${filesToDelete.length} deleted files...`,
311
+ });
312
+ for (const filePath of filesToDelete) {
313
+ const deleted = this.graph.deleteFileNodes(filePath);
314
+ stats.filesDeleted++;
315
+ }
316
+ }
317
+ // Phase 3: Parse changed files
318
+ if (filesToParse.length > 0) {
319
+ onProgress?.({
320
+ phase: 'parsing',
321
+ current: 0,
322
+ total: filesToParse.length,
323
+ message: `Parsing ${filesToParse.length} changed files...`,
324
+ });
325
+ const parseResults = await parseFiles(filesToParse, 8, (current, total) => {
326
+ onProgress?.({
327
+ phase: 'parsing',
328
+ current,
329
+ total,
330
+ currentFile: filesToParse[Math.min(current, filesToParse.length - 1)],
331
+ message: `Parsed ${current}/${total} changed files`,
332
+ });
333
+ });
334
+ // Phase 4: Store results
335
+ onProgress?.({
336
+ phase: 'storing',
337
+ current: 0,
338
+ total: parseResults.length,
339
+ message: 'Updating knowledge graph...',
340
+ });
341
+ for (let i = 0; i < parseResults.length; i++) {
342
+ const result = parseResults[i];
343
+ if (result.nodes.length === 0 && result.parseErrors.length > 0) {
344
+ stats.parseErrors += result.parseErrors.length;
345
+ continue;
346
+ }
347
+ stats.filesParsed++;
348
+ stats.nodesCreated += result.nodes.length;
349
+ stats.edgesCreated += result.edges.length;
350
+ if (result.language !== 'unknown') {
351
+ stats.languages[result.language] = (stats.languages[result.language] ?? 0) + 1;
352
+ }
353
+ if (result.parseErrors.length > 0) {
354
+ stats.parseErrors += result.parseErrors.length;
355
+ }
356
+ // Replace file data atomically
357
+ this.graph.replaceFileData(result.filePath, result.nodes, result.edges);
358
+ }
359
+ }
360
+ // Phase 5: Complete
361
+ stats.durationMs = Date.now() - startTime;
362
+ const changeCount = filesToParse.length + filesToDelete.length;
363
+ onProgress?.({
364
+ phase: 'complete',
365
+ current: changeCount,
366
+ total: stats.filesScanned,
367
+ message: changeCount > 0
368
+ ? `Incremental index: ${stats.filesParsed} updated, ${stats.filesDeleted} deleted in ${stats.durationMs}ms`
369
+ : `No changes detected (${stats.filesScanned} files checked in ${stats.durationMs}ms)`,
370
+ });
371
+ return stats;
372
+ }
373
+ /**
374
+ * Index a single file (e.g., when file watcher detects a change).
375
+ *
376
+ * @param filePath - Absolute path to the changed file
377
+ * @returns Parse result, or null if file was skipped
378
+ */
379
+ async indexFile(filePath) {
380
+ // Check if file should be ignored
381
+ const relPath = relative(this.config.projectRoot, filePath).replace(/\\/g, '/');
382
+ if (this.ig.ignores(relPath))
383
+ return null;
384
+ if (!isSupportedFile(filePath))
385
+ return null;
386
+ // Skip files that are too large (prevent OOM)
387
+ const fileStat = await stat(filePath).catch(() => null);
388
+ if (!fileStat || fileStat.size > MAX_FILE_SIZE_BYTES) {
389
+ return null;
390
+ }
391
+ try {
392
+ if (fileStat.size > this.config.maxFileSize)
393
+ return null;
394
+ if (fileStat.size === 0)
395
+ return null;
396
+ }
397
+ catch {
398
+ // File may have been deleted
399
+ this.graph.deleteFileNodes(filePath);
400
+ return null;
401
+ }
402
+ const result = await parseFile(filePath);
403
+ if (result.nodes.length > 0) {
404
+ this.graph.replaceFileData(filePath, result.nodes, result.edges);
405
+ }
406
+ return result;
407
+ }
408
+ /**
409
+ * Remove a file from the index (e.g., when file watcher detects deletion).
410
+ *
411
+ * @param filePath - Absolute path to the deleted file
412
+ * @returns Number of nodes removed
413
+ */
414
+ removeFile(filePath) {
415
+ return this.graph.deleteFileNodes(filePath);
416
+ }
417
+ /**
418
+ * Auto-detect the languages used in the project based on file extension distribution.
419
+ *
420
+ * @returns Sorted array of language names (most common first)
421
+ */
422
+ async detectProjectLanguages() {
423
+ const files = await this.scanFiles();
424
+ const langCounts = {};
425
+ for (const file of files) {
426
+ const lang = detectLanguage(file);
427
+ if (lang) {
428
+ langCounts[lang] = (langCounts[lang] ?? 0) + 1;
429
+ }
430
+ }
431
+ return Object.entries(langCounts)
432
+ .sort((a, b) => b[1] - a[1])
433
+ .map(([lang]) => lang);
434
+ }
435
+ /**
436
+ * Get the current indexing status — how many files are indexed vs how many exist.
437
+ */
438
+ async getIndexStatus() {
439
+ const currentFiles = await this.scanFiles();
440
+ const indexedFiles = this.graph.getIndexedFiles();
441
+ const indexedSet = new Set(indexedFiles);
442
+ let staleCount = 0;
443
+ for (const filePath of currentFiles) {
444
+ if (!indexedSet.has(filePath)) {
445
+ staleCount++;
446
+ }
447
+ }
448
+ // Check for deleted files still in index
449
+ const currentSet = new Set(currentFiles);
450
+ for (const indexedFile of indexedFiles) {
451
+ if (!currentSet.has(indexedFile)) {
452
+ staleCount++;
453
+ }
454
+ }
455
+ const staleness = currentFiles.length > 0 ? staleCount / currentFiles.length : 0;
456
+ return {
457
+ indexedFiles: indexedFiles.length,
458
+ totalFiles: currentFiles.length,
459
+ staleness,
460
+ needsReindex: staleness > 0.1, // More than 10% stale
461
+ };
462
+ }
463
+ /** Validate the index against the filesystem. Returns files that are stale, missing, or orphaned. */
464
+ async validateIndex() {
465
+ const indexedFiles = this.graph.getIndexedFiles();
466
+ const diskFiles = await this.scanFiles();
467
+ const diskSet = new Set(diskFiles);
468
+ const indexSet = new Set(indexedFiles);
469
+ const missingFiles = [];
470
+ const staleFiles = [];
471
+ const unindexedFiles = [];
472
+ // Check indexed files against disk
473
+ for (const f of indexedFiles) {
474
+ if (!diskSet.has(f)) {
475
+ missingFiles.push(f);
476
+ }
477
+ else {
478
+ // Check if file changed
479
+ try {
480
+ const content = readFileSync(f, 'utf-8');
481
+ const currentHash = (await import('./parser.js')).generateContentHash(content);
482
+ const indexedHash = this.graph.getFileHash(f);
483
+ if (indexedHash && currentHash !== indexedHash) {
484
+ staleFiles.push(f);
485
+ }
486
+ }
487
+ catch {
488
+ staleFiles.push(f);
489
+ }
490
+ }
491
+ }
492
+ // Check for unindexed files
493
+ for (const f of diskFiles) {
494
+ if (!indexSet.has(f)) {
495
+ unindexedFiles.push(f);
496
+ }
497
+ }
498
+ return {
499
+ staleFiles,
500
+ missingFiles,
501
+ unindexedFiles,
502
+ healthy: staleFiles.length === 0 && missingFiles.length === 0 && unindexedFiles.length === 0,
503
+ };
504
+ }
505
+ }
506
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/knowledge-graph/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * AI Mind Map — PageRank-based Relevance Ranking
3
+ *
4
+ * Implements standard and personalized PageRank to rank code symbols
5
+ * by structural importance. Directly inspired by Aider's Personalized
6
+ * PageRank approach for generating compact repo maps within a token budget.
7
+ *
8
+ * Key features:
9
+ * - Standard PageRank with configurable damping factor
10
+ * - Personalized PageRank biased toward conversation-relevant nodes
11
+ * - Token-budget-aware repo map generation
12
+ * - Caching with graph-change invalidation
13
+ */
14
+ import type { GraphNode } from '../types.js';
15
+ import { KnowledgeGraph } from './graph.js';
16
+ /** PageRank configuration */
17
+ export interface PageRankConfig {
18
+ /** Damping factor (probability of following a link vs random jump). Default: 0.85 */
19
+ dampingFactor: number;
20
+ /** Maximum iterations before convergence. Default: 100 */
21
+ maxIterations: number;
22
+ /** Convergence threshold (stop when max change < epsilon). Default: 1e-6 */
23
+ epsilon: number;
24
+ }
25
+ /** Ranked node with its PageRank score */
26
+ export interface RankedNode {
27
+ node: GraphNode;
28
+ score: number;
29
+ /** Estimated token cost of this node's signature */
30
+ tokenCost: number;
31
+ }
32
+ /**
33
+ * PageRank-based relevance ranking engine for the knowledge graph.
34
+ *
35
+ * Computes structural importance of each node based on the link structure
36
+ * of the codebase graph. Supports personalized PageRank to bias rankings
37
+ * toward nodes relevant to the current conversation or query.
38
+ */
39
+ export declare class PageRankEngine {
40
+ private graph;
41
+ private config;
42
+ private cache;
43
+ constructor(graph: KnowledgeGraph, config?: Partial<PageRankConfig>);
44
+ /**
45
+ * Compute a hash of the current graph state for cache invalidation.
46
+ * Uses node/edge counts + a sample of recent update timestamps.
47
+ */
48
+ private computeGraphHash;
49
+ /**
50
+ * Check if the cached PageRank scores are still valid.
51
+ */
52
+ private isCacheValid;
53
+ /**
54
+ * Invalidate the PageRank cache (call when graph changes).
55
+ */
56
+ invalidateCache(): void;
57
+ /**
58
+ * Build a weighted adjacency list from graph edges.
59
+ *
60
+ * @returns Adjacency list: nodeId → [(targetId, weight)]
61
+ */
62
+ private buildAdjacencyList;
63
+ /**
64
+ * Compute standard PageRank for all nodes in the graph.
65
+ *
66
+ * Uses the power iteration method with weighted edges.
67
+ *
68
+ * @returns Map of node ID → PageRank score
69
+ */
70
+ computePageRank(): Map<string, number>;
71
+ /**
72
+ * Compute Personalized PageRank biased toward specific seed nodes.
73
+ *
74
+ * This is the key algorithm inspired by Aider's approach:
75
+ * instead of uniform random jumps, jumps are biased toward nodes
76
+ * mentioned in the current conversation or query.
77
+ *
78
+ * @param seedNodeIds - Node IDs to bias toward (e.g., nodes matching a query)
79
+ * @param seedWeight - How much to bias toward seeds (0-1, default 0.5)
80
+ * @returns Map of node ID → personalized PageRank score
81
+ */
82
+ computePersonalizedPageRank(seedNodeIds: string[], seedWeight?: number): Map<string, number>;
83
+ /**
84
+ * Estimate the token cost of a node's signature representation.
85
+ * Rough estimate: ~4 characters per token.
86
+ */
87
+ private estimateNodeTokenCost;
88
+ /**
89
+ * Get the top-N most important nodes ranked by PageRank.
90
+ *
91
+ * @param limit - Maximum number of nodes to return
92
+ * @param excludeTypes - Node types to exclude (e.g., ['file'] to skip file nodes)
93
+ * @returns Ranked nodes with scores and token costs
94
+ */
95
+ getTopNodes(limit?: number, excludeTypes?: string[]): RankedNode[];
96
+ /**
97
+ * Get the most relevant nodes for a set of seed nodes (personalized).
98
+ *
99
+ * @param seedNodeIds - Seed node IDs to bias toward
100
+ * @param limit - Maximum number of nodes
101
+ * @param seedWeight - Bias weight (0-1)
102
+ * @param excludeTypes - Node types to exclude
103
+ */
104
+ getRelevantNodes(seedNodeIds: string[], limit?: number, seedWeight?: number, excludeTypes?: string[]): RankedNode[];
105
+ /**
106
+ * Rank nodes by their scores, applying filters.
107
+ */
108
+ private rankNodes;
109
+ /**
110
+ * Get nodes that fit within a token budget, ranked by importance.
111
+ *
112
+ * Greedily fills the budget with the highest-ranked nodes first.
113
+ *
114
+ * @param tokenBudget - Maximum tokens to use
115
+ * @param seedNodeIds - Optional seed nodes for personalized ranking
116
+ * @param excludeTypes - Node types to exclude
117
+ * @returns Ranked nodes fitting within budget
118
+ */
119
+ getNodesWithinBudget(tokenBudget: number, seedNodeIds?: string[], excludeTypes?: string[]): RankedNode[];
120
+ /**
121
+ * Generate a compact repository map string within a token budget.
122
+ *
123
+ * Produces an Aider-style repo map that shows the most important
124
+ * symbols' signatures, organized by file. This is the primary
125
+ * output for token-efficient context.
126
+ *
127
+ * @param tokenBudget - Maximum tokens for the repo map
128
+ * @param seedNodeIds - Optional seed nodes for personalized ranking
129
+ * @returns Compact repo map string
130
+ */
131
+ generateRepoMap(tokenBudget: number, seedNodeIds?: string[]): string;
132
+ /**
133
+ * Get a simple map of file paths → their top symbols.
134
+ * Useful for a table-of-contents view of the project.
135
+ *
136
+ * @param maxSymbolsPerFile - Max symbols to show per file (default 10)
137
+ * @returns Map of file path → symbol signatures
138
+ */
139
+ getProjectTOC(maxSymbolsPerFile?: number): Map<string, string[]>;
140
+ }
141
+ //# sourceMappingURL=pagerank.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagerank.d.ts","sourceRoot":"","sources":["../../src/knowledge-graph/pagerank.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAuB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAM5C,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,qFAAqF;IACrF,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB;AA6CD;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,KAAK,CAA8B;gBAE/B,KAAK,EAAE,cAAc,EAAE,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM;IASvE;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,eAAe,IAAI,IAAI;IAQvB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAmC1B;;;;;;OAMG;IACH,eAAe,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAuFtC;;;;;;;;;;OAUG;IACH,2BAA2B,CACzB,WAAW,EAAE,MAAM,EAAE,EACrB,UAAU,GAAE,MAAY,GACvB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAuFtB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAU7B;;;;;;OAMG;IACH,WAAW,CACT,KAAK,GAAE,MAAW,EAClB,YAAY,GAAE,MAAM,EAAa,GAChC,UAAU,EAAE;IAKf;;;;;;;OAOG;IACH,gBAAgB,CACd,WAAW,EAAE,MAAM,EAAE,EACrB,KAAK,GAAE,MAAW,EAClB,UAAU,GAAE,MAAY,EACxB,YAAY,GAAE,MAAM,EAAa,GAChC,UAAU,EAAE;IAKf;;OAEG;IACH,OAAO,CAAC,SAAS;IAqCjB;;;;;;;;;OASG;IACH,oBAAoB,CAClB,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,YAAY,GAAE,MAAM,EAAa,GAChC,UAAU,EAAE;IA6Cf;;;;;;;;;;OAUG;IACH,eAAe,CACb,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EAAE,GACrB,MAAM;IAoET;;;;;;OAMG;IACH,aAAa,CAAC,iBAAiB,GAAE,MAAW,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CA2BrE"}