@thoughtflow/codebase 0.2.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 (278) hide show
  1. package/dist/contexts/context-decomposer.d.ts +13 -0
  2. package/dist/contexts/context-decomposer.d.ts.map +1 -0
  3. package/dist/contexts/context-decomposer.js +97 -0
  4. package/dist/contexts/context-decomposer.js.map +1 -0
  5. package/dist/contexts/context-document-manager.d.ts +21 -0
  6. package/dist/contexts/context-document-manager.d.ts.map +1 -0
  7. package/dist/contexts/context-document-manager.js +69 -0
  8. package/dist/contexts/context-document-manager.js.map +1 -0
  9. package/dist/contexts/context-router.d.ts +13 -0
  10. package/dist/contexts/context-router.d.ts.map +1 -0
  11. package/dist/contexts/context-router.js +94 -0
  12. package/dist/contexts/context-router.js.map +1 -0
  13. package/dist/index.d.ts +53 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +76 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/libs/codebase/deep-analyzer.d.ts +58 -0
  18. package/dist/libs/codebase/deep-analyzer.d.ts.map +1 -0
  19. package/dist/libs/codebase/deep-analyzer.js +239 -0
  20. package/dist/libs/codebase/deep-analyzer.js.map +1 -0
  21. package/dist/libs/codebase/graph/dependency-extractor.d.ts +20 -0
  22. package/dist/libs/codebase/graph/dependency-extractor.d.ts.map +1 -0
  23. package/dist/libs/codebase/graph/dependency-extractor.js +174 -0
  24. package/dist/libs/codebase/graph/dependency-extractor.js.map +1 -0
  25. package/dist/libs/codebase/graph/graph-analysis.d.ts +42 -0
  26. package/dist/libs/codebase/graph/graph-analysis.d.ts.map +1 -0
  27. package/dist/libs/codebase/graph/graph-analysis.js +222 -0
  28. package/dist/libs/codebase/graph/graph-analysis.js.map +1 -0
  29. package/dist/libs/codebase/graph/graph-visualizer.d.ts +12 -0
  30. package/dist/libs/codebase/graph/graph-visualizer.d.ts.map +1 -0
  31. package/dist/libs/codebase/graph/graph-visualizer.js +99 -0
  32. package/dist/libs/codebase/graph/graph-visualizer.js.map +1 -0
  33. package/dist/libs/codebase/indexer/batch-processor.d.ts +18 -0
  34. package/dist/libs/codebase/indexer/batch-processor.d.ts.map +1 -0
  35. package/dist/libs/codebase/indexer/batch-processor.js +39 -0
  36. package/dist/libs/codebase/indexer/batch-processor.js.map +1 -0
  37. package/dist/libs/codebase/indexer/chunker-markdown.d.ts +19 -0
  38. package/dist/libs/codebase/indexer/chunker-markdown.d.ts.map +1 -0
  39. package/dist/libs/codebase/indexer/chunker-markdown.js +138 -0
  40. package/dist/libs/codebase/indexer/chunker-markdown.js.map +1 -0
  41. package/dist/libs/codebase/indexer/chunker.d.ts +21 -0
  42. package/dist/libs/codebase/indexer/chunker.d.ts.map +1 -0
  43. package/dist/libs/codebase/indexer/chunker.js +133 -0
  44. package/dist/libs/codebase/indexer/chunker.js.map +1 -0
  45. package/dist/libs/codebase/indexer/explorer.d.ts +29 -0
  46. package/dist/libs/codebase/indexer/explorer.d.ts.map +1 -0
  47. package/dist/libs/codebase/indexer/explorer.js +278 -0
  48. package/dist/libs/codebase/indexer/explorer.js.map +1 -0
  49. package/dist/libs/codebase/indexer/indexer.d.ts +35 -0
  50. package/dist/libs/codebase/indexer/indexer.d.ts.map +1 -0
  51. package/dist/libs/codebase/indexer/indexer.js +172 -0
  52. package/dist/libs/codebase/indexer/indexer.js.map +1 -0
  53. package/dist/libs/codebase/knowledge/cross-referencer.d.ts +32 -0
  54. package/dist/libs/codebase/knowledge/cross-referencer.d.ts.map +1 -0
  55. package/dist/libs/codebase/knowledge/cross-referencer.js +132 -0
  56. package/dist/libs/codebase/knowledge/cross-referencer.js.map +1 -0
  57. package/dist/libs/codebase/knowledge/markdown-extractor.d.ts +34 -0
  58. package/dist/libs/codebase/knowledge/markdown-extractor.d.ts.map +1 -0
  59. package/dist/libs/codebase/knowledge/markdown-extractor.js +273 -0
  60. package/dist/libs/codebase/knowledge/markdown-extractor.js.map +1 -0
  61. package/dist/libs/codebase/knowledge/summarizer.d.ts +25 -0
  62. package/dist/libs/codebase/knowledge/summarizer.d.ts.map +1 -0
  63. package/dist/libs/codebase/knowledge/summarizer.js +61 -0
  64. package/dist/libs/codebase/knowledge/summarizer.js.map +1 -0
  65. package/dist/libs/codebase/search/bm25.d.ts +23 -0
  66. package/dist/libs/codebase/search/bm25.d.ts.map +1 -0
  67. package/dist/libs/codebase/search/bm25.js +93 -0
  68. package/dist/libs/codebase/search/bm25.js.map +1 -0
  69. package/dist/libs/codebase/search/hybrid-search.d.ts +22 -0
  70. package/dist/libs/codebase/search/hybrid-search.d.ts.map +1 -0
  71. package/dist/libs/codebase/search/hybrid-search.js +80 -0
  72. package/dist/libs/codebase/search/hybrid-search.js.map +1 -0
  73. package/dist/libs/codebase-index.class.d.ts +66 -0
  74. package/dist/libs/codebase-index.class.d.ts.map +1 -0
  75. package/dist/libs/codebase-index.class.js +595 -0
  76. package/dist/libs/codebase-index.class.js.map +1 -0
  77. package/dist/tools/codebase/codebase-analyze.tool.d.ts +8 -0
  78. package/dist/tools/codebase/codebase-analyze.tool.d.ts.map +1 -0
  79. package/dist/tools/codebase/codebase-analyze.tool.js +20 -0
  80. package/dist/tools/codebase/codebase-analyze.tool.js.map +1 -0
  81. package/dist/tools/codebase/codebase-crossref.tool.d.ts +8 -0
  82. package/dist/tools/codebase/codebase-crossref.tool.d.ts.map +1 -0
  83. package/dist/tools/codebase/codebase-crossref.tool.js +20 -0
  84. package/dist/tools/codebase/codebase-crossref.tool.js.map +1 -0
  85. package/dist/tools/codebase/codebase-flow.tool.d.ts +8 -0
  86. package/dist/tools/codebase/codebase-flow.tool.d.ts.map +1 -0
  87. package/dist/tools/codebase/codebase-flow.tool.js +20 -0
  88. package/dist/tools/codebase/codebase-flow.tool.js.map +1 -0
  89. package/dist/tools/codebase/codebase-graph-circular.tool.d.ts +8 -0
  90. package/dist/tools/codebase/codebase-graph-circular.tool.d.ts.map +1 -0
  91. package/dist/tools/codebase/codebase-graph-circular.tool.js +17 -0
  92. package/dist/tools/codebase/codebase-graph-circular.tool.js.map +1 -0
  93. package/dist/tools/codebase/codebase-graph-query.tool.d.ts +8 -0
  94. package/dist/tools/codebase/codebase-graph-query.tool.d.ts.map +1 -0
  95. package/dist/tools/codebase/codebase-graph-query.tool.js +21 -0
  96. package/dist/tools/codebase/codebase-graph-query.tool.js.map +1 -0
  97. package/dist/tools/codebase/codebase-graph-stats.tool.d.ts +8 -0
  98. package/dist/tools/codebase/codebase-graph-stats.tool.d.ts.map +1 -0
  99. package/dist/tools/codebase/codebase-graph-stats.tool.js +17 -0
  100. package/dist/tools/codebase/codebase-graph-stats.tool.js.map +1 -0
  101. package/dist/tools/codebase/codebase-graph-visualize.tool.d.ts +8 -0
  102. package/dist/tools/codebase/codebase-graph-visualize.tool.d.ts.map +1 -0
  103. package/dist/tools/codebase/codebase-graph-visualize.tool.js +21 -0
  104. package/dist/tools/codebase/codebase-graph-visualize.tool.js.map +1 -0
  105. package/dist/tools/codebase/codebase-impact.tool.d.ts +8 -0
  106. package/dist/tools/codebase/codebase-impact.tool.d.ts.map +1 -0
  107. package/dist/tools/codebase/codebase-impact.tool.js +21 -0
  108. package/dist/tools/codebase/codebase-impact.tool.js.map +1 -0
  109. package/dist/tools/codebase/codebase-index.tool.d.ts +8 -0
  110. package/dist/tools/codebase/codebase-index.tool.d.ts.map +1 -0
  111. package/dist/tools/codebase/codebase-index.tool.js +21 -0
  112. package/dist/tools/codebase/codebase-index.tool.js.map +1 -0
  113. package/dist/tools/codebase/codebase-knowledge.tool.d.ts +8 -0
  114. package/dist/tools/codebase/codebase-knowledge.tool.d.ts.map +1 -0
  115. package/dist/tools/codebase/codebase-knowledge.tool.js +22 -0
  116. package/dist/tools/codebase/codebase-knowledge.tool.js.map +1 -0
  117. package/dist/tools/codebase/codebase-search.tool.d.ts +8 -0
  118. package/dist/tools/codebase/codebase-search.tool.d.ts.map +1 -0
  119. package/dist/tools/codebase/codebase-search.tool.js +24 -0
  120. package/dist/tools/codebase/codebase-search.tool.js.map +1 -0
  121. package/dist/tools/codebase/codebase-status.tool.d.ts +8 -0
  122. package/dist/tools/codebase/codebase-status.tool.d.ts.map +1 -0
  123. package/dist/tools/codebase/codebase-status.tool.js +19 -0
  124. package/dist/tools/codebase/codebase-status.tool.js.map +1 -0
  125. package/dist/tools/neural/comparative-analysis.tool.d.ts +37 -0
  126. package/dist/tools/neural/comparative-analysis.tool.d.ts.map +1 -0
  127. package/dist/tools/neural/comparative-analysis.tool.js +241 -0
  128. package/dist/tools/neural/comparative-analysis.tool.js.map +1 -0
  129. package/dist/tools/neural/index.d.ts +12 -0
  130. package/dist/tools/neural/index.d.ts.map +1 -0
  131. package/dist/tools/neural/index.js +28 -0
  132. package/dist/tools/neural/index.js.map +1 -0
  133. package/dist/tools/neural/neural-deadcode.tool.d.ts +10 -0
  134. package/dist/tools/neural/neural-deadcode.tool.d.ts.map +1 -0
  135. package/dist/tools/neural/neural-deadcode.tool.js +133 -0
  136. package/dist/tools/neural/neural-deadcode.tool.js.map +1 -0
  137. package/dist/tools/neural/neural-debug.tool.d.ts +11 -0
  138. package/dist/tools/neural/neural-debug.tool.d.ts.map +1 -0
  139. package/dist/tools/neural/neural-debug.tool.js +205 -0
  140. package/dist/tools/neural/neural-debug.tool.js.map +1 -0
  141. package/dist/tools/neural/neural-explain.tool.d.ts +9 -0
  142. package/dist/tools/neural/neural-explain.tool.d.ts.map +1 -0
  143. package/dist/tools/neural/neural-explain.tool.js +100 -0
  144. package/dist/tools/neural/neural-explain.tool.js.map +1 -0
  145. package/dist/tools/neural/neural-optimize.tool.d.ts +9 -0
  146. package/dist/tools/neural/neural-optimize.tool.d.ts.map +1 -0
  147. package/dist/tools/neural/neural-optimize.tool.js +117 -0
  148. package/dist/tools/neural/neural-optimize.tool.js.map +1 -0
  149. package/dist/tools/neural/neural-pattern.tool.d.ts +10 -0
  150. package/dist/tools/neural/neural-pattern.tool.d.ts.map +1 -0
  151. package/dist/tools/neural/neural-pattern.tool.js +169 -0
  152. package/dist/tools/neural/neural-pattern.tool.js.map +1 -0
  153. package/dist/tools/neural/neural-review.tool.d.ts +11 -0
  154. package/dist/tools/neural/neural-review.tool.d.ts.map +1 -0
  155. package/dist/tools/neural/neural-review.tool.js +152 -0
  156. package/dist/tools/neural/neural-review.tool.js.map +1 -0
  157. package/dist/tools/neural/neural-security.tool.d.ts +16 -0
  158. package/dist/tools/neural/neural-security.tool.d.ts.map +1 -0
  159. package/dist/tools/neural/neural-security.tool.js +256 -0
  160. package/dist/tools/neural/neural-security.tool.js.map +1 -0
  161. package/dist/tools/neural/neural-similar.tool.d.ts +9 -0
  162. package/dist/tools/neural/neural-similar.tool.d.ts.map +1 -0
  163. package/dist/tools/neural/neural-similar.tool.js +139 -0
  164. package/dist/tools/neural/neural-similar.tool.js.map +1 -0
  165. package/dist/tools/neural/neural-smells.tool.d.ts +9 -0
  166. package/dist/tools/neural/neural-smells.tool.d.ts.map +1 -0
  167. package/dist/tools/neural/neural-smells.tool.js +123 -0
  168. package/dist/tools/neural/neural-smells.tool.js.map +1 -0
  169. package/dist/tools/neural/neural-suggest.tool.d.ts +9 -0
  170. package/dist/tools/neural/neural-suggest.tool.d.ts.map +1 -0
  171. package/dist/tools/neural/neural-suggest.tool.js +64 -0
  172. package/dist/tools/neural/neural-suggest.tool.js.map +1 -0
  173. package/dist/tools/quality/index.d.ts +8 -0
  174. package/dist/tools/quality/index.d.ts.map +1 -0
  175. package/dist/tools/quality/index.js +24 -0
  176. package/dist/tools/quality/index.js.map +1 -0
  177. package/dist/tools/quality/quality-complexity.tool.d.ts +11 -0
  178. package/dist/tools/quality/quality-complexity.tool.d.ts.map +1 -0
  179. package/dist/tools/quality/quality-complexity.tool.js +152 -0
  180. package/dist/tools/quality/quality-complexity.tool.js.map +1 -0
  181. package/dist/tools/quality/quality-coupling.tool.d.ts +9 -0
  182. package/dist/tools/quality/quality-coupling.tool.d.ts.map +1 -0
  183. package/dist/tools/quality/quality-coupling.tool.js +51 -0
  184. package/dist/tools/quality/quality-coupling.tool.js.map +1 -0
  185. package/dist/tools/quality/quality-coverage.tool.d.ts +9 -0
  186. package/dist/tools/quality/quality-coverage.tool.d.ts.map +1 -0
  187. package/dist/tools/quality/quality-coverage.tool.js +104 -0
  188. package/dist/tools/quality/quality-coverage.tool.js.map +1 -0
  189. package/dist/tools/quality/quality-deps.tool.d.ts +11 -0
  190. package/dist/tools/quality/quality-deps.tool.d.ts.map +1 -0
  191. package/dist/tools/quality/quality-deps.tool.js +119 -0
  192. package/dist/tools/quality/quality-deps.tool.js.map +1 -0
  193. package/dist/tools/quality/quality-duplication.tool.d.ts +9 -0
  194. package/dist/tools/quality/quality-duplication.tool.d.ts.map +1 -0
  195. package/dist/tools/quality/quality-duplication.tool.js +100 -0
  196. package/dist/tools/quality/quality-duplication.tool.js.map +1 -0
  197. package/dist/tools/quality/quality-size.tool.d.ts +9 -0
  198. package/dist/tools/quality/quality-size.tool.d.ts.map +1 -0
  199. package/dist/tools/quality/quality-size.tool.js +94 -0
  200. package/dist/tools/quality/quality-size.tool.js.map +1 -0
  201. package/dist/tools/quality/quality-types.tool.d.ts +9 -0
  202. package/dist/tools/quality/quality-types.tool.d.ts.map +1 -0
  203. package/dist/tools/quality/quality-types.tool.js +95 -0
  204. package/dist/tools/quality/quality-types.tool.js.map +1 -0
  205. package/dist/tools/workspace/analyze-project.tool.d.ts +36 -0
  206. package/dist/tools/workspace/analyze-project.tool.d.ts.map +1 -0
  207. package/dist/tools/workspace/analyze-project.tool.js +454 -0
  208. package/dist/tools/workspace/analyze-project.tool.js.map +1 -0
  209. package/dist/tools/workspace/codebase-research.tool.d.ts +10 -0
  210. package/dist/tools/workspace/codebase-research.tool.d.ts.map +1 -0
  211. package/dist/tools/workspace/codebase-research.tool.js +89 -0
  212. package/dist/tools/workspace/codebase-research.tool.js.map +1 -0
  213. package/dist/tools/workspace/project-scanner.tool.d.ts +55 -0
  214. package/dist/tools/workspace/project-scanner.tool.d.ts.map +1 -0
  215. package/dist/tools/workspace/project-scanner.tool.js +978 -0
  216. package/dist/tools/workspace/project-scanner.tool.js.map +1 -0
  217. package/dist/tools/workspace/search-code.tool.d.ts +14 -0
  218. package/dist/tools/workspace/search-code.tool.d.ts.map +1 -0
  219. package/dist/tools/workspace/search-code.tool.js +286 -0
  220. package/dist/tools/workspace/search-code.tool.js.map +1 -0
  221. package/package.json +17 -0
  222. package/src/contexts/context-decomposer.ts +113 -0
  223. package/src/contexts/context-document-manager.ts +70 -0
  224. package/src/contexts/context-router.ts +121 -0
  225. package/src/index.ts +65 -0
  226. package/src/libs/codebase/deep-analyzer.ts +287 -0
  227. package/src/libs/codebase/graph/dependency-extractor.ts +165 -0
  228. package/src/libs/codebase/graph/graph-analysis.ts +231 -0
  229. package/src/libs/codebase/graph/graph-visualizer.ts +124 -0
  230. package/src/libs/codebase/indexer/batch-processor.ts +47 -0
  231. package/src/libs/codebase/indexer/chunker-markdown.ts +175 -0
  232. package/src/libs/codebase/indexer/chunker.ts +126 -0
  233. package/src/libs/codebase/indexer/explorer.ts +269 -0
  234. package/src/libs/codebase/indexer/indexer.ts +174 -0
  235. package/src/libs/codebase/knowledge/cross-referencer.ts +182 -0
  236. package/src/libs/codebase/knowledge/markdown-extractor.ts +270 -0
  237. package/src/libs/codebase/knowledge/summarizer.ts +85 -0
  238. package/src/libs/codebase/search/bm25.ts +109 -0
  239. package/src/libs/codebase/search/hybrid-search.ts +109 -0
  240. package/src/libs/codebase-index.class.ts +715 -0
  241. package/src/tools/codebase/codebase-analyze.tool.ts +18 -0
  242. package/src/tools/codebase/codebase-crossref.tool.ts +18 -0
  243. package/src/tools/codebase/codebase-flow.tool.ts +18 -0
  244. package/src/tools/codebase/codebase-graph-circular.tool.ts +15 -0
  245. package/src/tools/codebase/codebase-graph-query.tool.ts +19 -0
  246. package/src/tools/codebase/codebase-graph-stats.tool.ts +15 -0
  247. package/src/tools/codebase/codebase-graph-visualize.tool.ts +19 -0
  248. package/src/tools/codebase/codebase-impact.tool.ts +19 -0
  249. package/src/tools/codebase/codebase-index.tool.ts +19 -0
  250. package/src/tools/codebase/codebase-knowledge.tool.ts +20 -0
  251. package/src/tools/codebase/codebase-search.tool.ts +22 -0
  252. package/src/tools/codebase/codebase-status.tool.ts +17 -0
  253. package/src/tools/neural/comparative-analysis.tool.ts +309 -0
  254. package/src/tools/neural/index.ts +11 -0
  255. package/src/tools/neural/neural-deadcode.tool.ts +105 -0
  256. package/src/tools/neural/neural-debug.tool.ts +199 -0
  257. package/src/tools/neural/neural-explain.tool.ts +67 -0
  258. package/src/tools/neural/neural-optimize.tool.ts +93 -0
  259. package/src/tools/neural/neural-pattern.tool.ts +141 -0
  260. package/src/tools/neural/neural-review.tool.ts +145 -0
  261. package/src/tools/neural/neural-security.tool.ts +226 -0
  262. package/src/tools/neural/neural-similar.tool.ts +113 -0
  263. package/src/tools/neural/neural-smells.tool.ts +98 -0
  264. package/src/tools/neural/neural-suggest.tool.ts +65 -0
  265. package/src/tools/quality/index.ts +7 -0
  266. package/src/tools/quality/quality-complexity.tool.ts +132 -0
  267. package/src/tools/quality/quality-coupling.tool.ts +57 -0
  268. package/src/tools/quality/quality-coverage.tool.ts +78 -0
  269. package/src/tools/quality/quality-deps.tool.ts +89 -0
  270. package/src/tools/quality/quality-duplication.tool.ts +71 -0
  271. package/src/tools/quality/quality-size.tool.ts +66 -0
  272. package/src/tools/quality/quality-types.tool.ts +66 -0
  273. package/src/tools/workspace/analyze-project.tool.ts +429 -0
  274. package/src/tools/workspace/codebase-research.tool.ts +100 -0
  275. package/src/tools/workspace/project-scanner.tool.ts +1058 -0
  276. package/src/tools/workspace/search-code.tool.ts +344 -0
  277. package/tsconfig.build.json +12 -0
  278. package/tsconfig.json +9 -0
@@ -0,0 +1,269 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { ResourceKind } from "@thoughtflow/core";
4
+ export type FileClassification =
5
+ | "source-code"
6
+ | "documentation"
7
+ | "config"
8
+ | "data"
9
+ | "test"
10
+ | "infrastructure"
11
+ | "schema"
12
+ | "api-spec"
13
+ | "unknown";
14
+
15
+ export interface ExplorerOptions {
16
+ rootPath: string;
17
+ ignorePatterns?: string[];
18
+ respectGitignore?: boolean;
19
+ includeExtensions?: string[];
20
+ excludeExtensions?: string[];
21
+ maxFileSizeBytes?: number;
22
+ }
23
+
24
+ export interface DiscoveredFile {
25
+ absolutePath: string;
26
+ relativePath: string;
27
+ extension: string;
28
+ sizeBytes: number;
29
+ language?: string;
30
+ classification: FileClassification;
31
+ resourceKind?: ResourceKind;
32
+ }
33
+
34
+ const DEFAULT_SKIP_DIRS = new Set([
35
+ "node_modules",
36
+ ".git",
37
+ "dist",
38
+ "build",
39
+ "coverage",
40
+ "out",
41
+ ".next",
42
+ ".turbo",
43
+ ".cache",
44
+ "vendor",
45
+ "__pycache__",
46
+ ".venv",
47
+ "venv",
48
+ ".idea",
49
+ ".vscode",
50
+ "target",
51
+ ".mypy_cache",
52
+ ".pytest_cache",
53
+ ]);
54
+
55
+ const DEFAULT_BINARY_EXTS = new Set([
56
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".ico", ".svg",
57
+ ".pdf", ".zip", ".gz", ".tar", ".tgz", ".bz2", ".7z", ".rar",
58
+ ".mp4", ".mov", ".avi", ".mp3", ".wav", ".ogg",
59
+ ".woff", ".woff2", ".ttf", ".eot", ".otf",
60
+ ".class", ".jar", ".exe", ".dll", ".so", ".dylib", ".bin", ".wasm", ".map",
61
+ ".pyc", ".pyo", ".o", ".a", ".lib", ".obj",
62
+ ]);
63
+
64
+ const DOC_EXTS = new Set([".md", ".mdx", ".rst", ".txt", ".adoc", ".wiki"]);
65
+ const CONFIG_EXTS = new Set([".json", ".yaml", ".yml", ".toml", ".ini", ".cfg", ".env", ".rc"]);
66
+ const SCHEMA_EXTS = new Set([".prisma", ".graphql", ".gql", ".proto", ".sql"]);
67
+ const INFRA_EXTS = new Set([".tf", ".hcl", ".bicep", ".dockerfile"]);
68
+ const TEST_PATTERNS = [/\.test\./, /\.spec\./, /\.e2e/, /\.integration\./, /__tests__\//, /test\//, /tests\//, /cypress\//];
69
+
70
+ const EXTENSION_LANG_MAP: Record<string, string> = {
71
+ ".ts": "typescript",
72
+ ".tsx": "tsx",
73
+ ".mts": "typescript",
74
+ ".cts": "typescript",
75
+ ".js": "javascript",
76
+ ".jsx": "javascript",
77
+ ".mjs": "javascript",
78
+ ".cjs": "javascript",
79
+ ".py": "python",
80
+ ".pyi": "python",
81
+ ".go": "go",
82
+ ".rs": "rust",
83
+ ".java": "java",
84
+ ".kt": "kotlin",
85
+ ".swift": "swift",
86
+ ".rb": "ruby",
87
+ ".php": "php",
88
+ ".cs": "csharp",
89
+ ".c": "c",
90
+ ".cpp": "cpp",
91
+ ".h": "c",
92
+ ".scala": "scala",
93
+ ".lua": "lua",
94
+ ".sh": "bash",
95
+ ".bash": "bash",
96
+ ".html": "html",
97
+ ".css": "css",
98
+ ".scss": "scss",
99
+ ".less": "less",
100
+ };
101
+
102
+ export class CodebaseExplorer {
103
+ explore(options: ExplorerOptions): DiscoveredFile[] {
104
+ const root = path.resolve(options.rootPath);
105
+ const maxSize = options.maxFileSizeBytes ?? 512 * 1024;
106
+ const ignorePatterns = options.ignorePatterns ?? [];
107
+ const respectGitignore = options.respectGitignore ?? true;
108
+
109
+ const gitignorePatterns = respectGitignore ? this.parseGitignores(root) : [];
110
+
111
+ const files: DiscoveredFile[] = [];
112
+ this.walk(root, root, files, maxSize, gitignorePatterns, ignorePatterns, options);
113
+ return files;
114
+ }
115
+
116
+ private walk(
117
+ dir: string,
118
+ root: string,
119
+ out: DiscoveredFile[],
120
+ maxSize: number,
121
+ gitignorePatterns: RegExp[],
122
+ extraIgnores: string[],
123
+ options: ExplorerOptions,
124
+ ): void {
125
+ let entries: fs.Dirent[];
126
+ try {
127
+ entries = fs.readdirSync(dir, { withFileTypes: true });
128
+ } catch {
129
+ return;
130
+ }
131
+
132
+ for (const entry of entries) {
133
+ const abs = path.join(dir, entry.name);
134
+ const rel = path.relative(root, abs).replace(/\\/g, "/");
135
+
136
+ if (entry.isDirectory()) {
137
+ if (DEFAULT_SKIP_DIRS.has(entry.name)) continue;
138
+ if (entry.name.startsWith(".") && !options.includeExtensions?.length) continue;
139
+ if (this.isIgnored(rel, gitignorePatterns, extraIgnores)) continue;
140
+ this.walk(abs, root, out, maxSize, gitignorePatterns, extraIgnores, options);
141
+ continue;
142
+ }
143
+
144
+ if (!entry.isFile()) continue;
145
+
146
+ const ext = path.extname(abs).toLowerCase();
147
+ if (DEFAULT_BINARY_EXTS.has(ext)) continue;
148
+ if (this.isIgnored(rel, gitignorePatterns, extraIgnores)) continue;
149
+
150
+ if (options.excludeExtensions?.includes(ext)) continue;
151
+
152
+ let stat: fs.Stats;
153
+ try {
154
+ stat = fs.statSync(abs);
155
+ } catch {
156
+ continue;
157
+ }
158
+ if (stat.size > maxSize) continue;
159
+ if (!this.isLikelyText(abs)) continue;
160
+
161
+ const classification = this.classify(rel, ext);
162
+ const resourceKind = this.toResourceKind(classification);
163
+
164
+ out.push({
165
+ absolutePath: abs,
166
+ relativePath: rel,
167
+ extension: ext,
168
+ sizeBytes: stat.size,
169
+ language: EXTENSION_LANG_MAP[ext],
170
+ classification,
171
+ resourceKind,
172
+ });
173
+ }
174
+ }
175
+
176
+ private classify(relativePath: string, ext: string): FileClassification {
177
+ if (DOC_EXTS.has(ext)) return "documentation";
178
+ if (SCHEMA_EXTS.has(ext)) return "schema";
179
+ if (INFRA_EXTS.has(ext)) return "infrastructure";
180
+ if (relativePath.includes("docker-compose") || relativePath.includes("Dockerfile") || relativePath.includes("Makefile")) return "infrastructure";
181
+ if (relativePath.includes("openapi") || relativePath.includes("swagger")) return "api-spec";
182
+ if (relativePath.includes(".github/workflows") || relativePath.includes(".gitlab-ci")) return "infrastructure";
183
+ if (CONFIG_EXTS.has(ext)) return "config";
184
+ if (TEST_PATTERNS.some((p) => p.test(relativePath))) return "test";
185
+ if (EXTENSION_LANG_MAP[ext]) return "source-code";
186
+ if (ext === ".json" || ext === ".yaml" || ext === ".yml") return "config";
187
+ return "unknown";
188
+ }
189
+
190
+ private toResourceKind(classification: FileClassification): ResourceKind | undefined {
191
+ switch (classification) {
192
+ case "schema":
193
+ return "schema";
194
+ case "config":
195
+ return "config";
196
+ case "infrastructure":
197
+ return "infra";
198
+ case "api-spec":
199
+ return "api-spec";
200
+ default:
201
+ return undefined;
202
+ }
203
+ }
204
+
205
+ private parseGitignores(root: string): RegExp[] {
206
+ const patterns: RegExp[] = [];
207
+ const gitignorePath = path.join(root, ".gitignore");
208
+ try {
209
+ const content = fs.readFileSync(gitignorePath, "utf8");
210
+ for (const line of content.split("\n")) {
211
+ const trimmed = line.trim();
212
+ if (!trimmed || trimmed.startsWith("#")) continue;
213
+ if (trimmed.startsWith("/")) continue;
214
+ try {
215
+ patterns.push(new RegExp(
216
+ trimmed
217
+ .replace(/\./g, "\\.")
218
+ .replace(/\*\*/g, "§§DOUBLESTAR§§")
219
+ .replace(/\*/g, "[^/]*")
220
+ .replace(/§§DOUBLESTAR§§/g, ".*")
221
+ .replace(/\?/g, "."),
222
+ ));
223
+ } catch {
224
+ /* noop */
225
+ }
226
+ }
227
+ } catch {
228
+ /* noop */
229
+ }
230
+ return patterns;
231
+ }
232
+
233
+ private isIgnored(relPath: string, gitignorePatterns: RegExp[], extras: string[]): boolean {
234
+ for (const p of gitignorePatterns) {
235
+ if (p.test(relPath)) return true;
236
+ }
237
+ for (const p of extras) {
238
+ try {
239
+ if (new RegExp(p).test(relPath)) return true;
240
+ } catch {
241
+ /* noop */
242
+ }
243
+ }
244
+ return false;
245
+ }
246
+
247
+ private isLikelyText(absPath: string): boolean {
248
+ let fd: number | null = null;
249
+ try {
250
+ fd = fs.openSync(absPath, "r");
251
+ const sample = Buffer.allocUnsafe(1024);
252
+ const read = fs.readSync(fd, sample, 0, sample.length, 0);
253
+ for (let i = 0; i < read; i++) {
254
+ if (sample[i] === 0) return false;
255
+ }
256
+ return true;
257
+ } catch {
258
+ return false;
259
+ } finally {
260
+ if (fd !== null) {
261
+ try {
262
+ fs.closeSync(fd);
263
+ } catch {
264
+ /* noop */
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
@@ -0,0 +1,174 @@
1
+ import type { IVectorStore, IEmbeddingProvider, VectorChunk, ChunkMetadata } from "@thoughtflow/core";
2
+ import { CodebaseExplorer, DiscoveredFile } from "./explorer";
3
+ import { CodeChunker, CodeChunk } from "./chunker";
4
+ import { MarkdownChunker, MarkdownChunk } from "./chunker-markdown";
5
+ import { BatchProcessor } from "./batch-processor";
6
+ import * as fs from "node:fs";
7
+
8
+ export interface IndexProgress {
9
+ phase: "discovering" | "chunking" | "embedding" | "storing" | "complete";
10
+ filesDiscovered: number;
11
+ filesProcessed: number;
12
+ chunksCreated: number;
13
+ chunksEmbedded: number;
14
+ elapsedMs: number;
15
+ }
16
+
17
+ export interface IndexResult {
18
+ totalFiles: number;
19
+ totalChunks: number;
20
+ timeMs: number;
21
+ collections: string[];
22
+ }
23
+
24
+ export interface IndexerOptions {
25
+ projectPath: string;
26
+ batchSize?: number;
27
+ includeDocs?: boolean;
28
+ onProgress?: (p: IndexProgress) => void;
29
+ }
30
+
31
+ export class CodebaseIndexer {
32
+ private explorer: CodebaseExplorer;
33
+ private chunker: CodeChunker;
34
+ private mdChunker: MarkdownChunker;
35
+ private processor: BatchProcessor;
36
+ private progress: IndexProgress;
37
+
38
+ constructor(
39
+ private vectorStore: IVectorStore,
40
+ private embeddingProvider: IEmbeddingProvider,
41
+ private options: IndexerOptions
42
+ ) {
43
+ this.explorer = new CodebaseExplorer();
44
+ this.chunker = new CodeChunker();
45
+ this.mdChunker = new MarkdownChunker();
46
+ this.processor = new BatchProcessor();
47
+ this.progress = {
48
+ phase: "discovering",
49
+ filesDiscovered: 0,
50
+ filesProcessed: 0,
51
+ chunksCreated: 0,
52
+ chunksEmbedded: 0,
53
+ elapsedMs: 0,
54
+ };
55
+ }
56
+
57
+ async index(): Promise<IndexResult> {
58
+ const startTime = Date.now();
59
+
60
+ await this.vectorStore.initialize?.();
61
+ await this.embeddingProvider.initialize?.();
62
+
63
+ this.updateProgress("discovering");
64
+ const files = this.explorer.explore({ rootPath: this.options.projectPath });
65
+ this.progress.filesDiscovered = files.length;
66
+ this.updateProgress("chunking");
67
+
68
+ const batchSize = this.options.batchSize ?? 50;
69
+ this.processor.start(files.length, "chunking");
70
+
71
+ const allChunks: Array<{ chunk: CodeChunk | MarkdownChunk; file: DiscoveredFile; isMarkdown: boolean }> = [];
72
+
73
+ for (const batch of this.processor.chunk(files, batchSize)) {
74
+ for (const file of batch) {
75
+ let content: string;
76
+ try {
77
+ content = fs.readFileSync(file.absolutePath, "utf8");
78
+ } catch {
79
+ continue;
80
+ }
81
+
82
+ if (file.classification === "documentation" && this.options.includeDocs !== false) {
83
+ const mdChunks = this.mdChunker.chunkFile(file, content);
84
+ for (const c of mdChunks) {
85
+ allChunks.push({ chunk: c, file, isMarkdown: true });
86
+ }
87
+ } else if (file.classification === "source-code" || file.classification === "test") {
88
+ const result = await this.chunker.chunkFile(file, content);
89
+ for (const c of result.chunks) {
90
+ allChunks.push({ chunk: c, file, isMarkdown: false });
91
+ }
92
+ }
93
+
94
+ this.progress.filesProcessed++;
95
+ this.progress.chunksCreated = allChunks.length;
96
+ }
97
+ await this.processor.advance(batch.length);
98
+ }
99
+
100
+ if (allChunks.length === 0) {
101
+ return {
102
+ totalFiles: files.length,
103
+ totalChunks: 0,
104
+ timeMs: Date.now() - startTime,
105
+ collections: [],
106
+ };
107
+ }
108
+
109
+ this.updateProgress("embedding");
110
+ this.processor.start(allChunks.length, "embedding");
111
+ const texts = allChunks.map((c) => c.chunk.text.slice(0, 512));
112
+ const vectors: number[][] = [];
113
+ const embBatchSize = this.embeddingProvider.maxBatchSize;
114
+
115
+ for (const batch of this.processor.chunk(texts, embBatchSize)) {
116
+ const batchVectors = await this.embeddingProvider.embed(batch);
117
+ vectors.push(...batchVectors);
118
+ this.progress.chunksEmbedded = vectors.length;
119
+ await this.processor.advance(batch.length);
120
+ }
121
+
122
+ this.updateProgress("storing");
123
+ this.processor.start(allChunks.length, "storing");
124
+
125
+ const vectorChunks: VectorChunk[] = allChunks.map((item, i) => {
126
+ const c = item.chunk;
127
+ const metadata: ChunkMetadata = {
128
+ projectPath: this.options.projectPath,
129
+ filePath: item.file.relativePath,
130
+ startLine: c.startLine,
131
+ endLine: c.endLine,
132
+ language: item.file.language,
133
+ chunkType: item.file.classification === "documentation" ? "documentation" : "code",
134
+ resourceKind: item.file.resourceKind,
135
+ tags: [],
136
+ };
137
+ if (item.isMarkdown) {
138
+ const mdChunk = c as MarkdownChunk;
139
+ if (mdChunk.docType) {
140
+ metadata.category = mdChunk.docType;
141
+ }
142
+ }
143
+ return {
144
+ id: c.id,
145
+ vector: vectors[i] ?? new Array(this.embeddingProvider.dimensions).fill(0),
146
+ text: c.text,
147
+ metadata,
148
+ };
149
+ });
150
+
151
+ const storeBatchSize = 500;
152
+ for (const batch of this.processor.chunk(vectorChunks, storeBatchSize)) {
153
+ await this.vectorStore.insert(batch);
154
+ await this.processor.advance(batch.length);
155
+ }
156
+
157
+ this.updateProgress("complete");
158
+ const elapsed = Date.now() - startTime;
159
+
160
+ await this.embeddingProvider.dispose?.();
161
+
162
+ return {
163
+ totalFiles: files.length,
164
+ totalChunks: allChunks.length,
165
+ timeMs: elapsed,
166
+ collections: ["default"],
167
+ };
168
+ }
169
+
170
+ private updateProgress(phase: IndexProgress["phase"]): void {
171
+ this.progress.phase = phase;
172
+ this.options.onProgress?.({ ...this.progress });
173
+ }
174
+ }
@@ -0,0 +1,182 @@
1
+ import { ExtractedDocument } from "./markdown-extractor";
2
+
3
+ export interface CrossReference {
4
+ sourceId: string;
5
+ targetId: string;
6
+ type: 'implements' | 'documents' | 'relates-to' | 'depends-on' | 'decision-for';
7
+ confidence: number;
8
+ evidence: string;
9
+ }
10
+
11
+ export interface CrossRefNode {
12
+ id: string;
13
+ type: 'feature' | 'code' | 'document' | 'decision' | 'pattern';
14
+ label: string;
15
+ filePath?: string;
16
+ summary?: string;
17
+ }
18
+
19
+ export interface CrossReferenceGraph {
20
+ nodes: Map<string, CrossRefNode>;
21
+ edges: CrossReference[];
22
+ }
23
+
24
+ export class CrossReferencer {
25
+ buildReferences(
26
+ documents: ExtractedDocument[],
27
+ codeFiles: Array<{ relativePath: string; content?: string }>,
28
+ dependencyEdges?: Array<{ from: string; to: string }>
29
+ ): CrossReferenceGraph {
30
+ const nodes = new Map<string, CrossRefNode>();
31
+ const edges: CrossReference[] = [];
32
+
33
+ for (const doc of documents) {
34
+ nodes.set(doc.id, {
35
+ id: doc.id,
36
+ type: 'document',
37
+ label: doc.title,
38
+ filePath: doc.filePath,
39
+ summary: doc.summary,
40
+ });
41
+
42
+ if (doc.docType === 'decision') {
43
+ nodes.set(doc.id, { ...nodes.get(doc.id)!, type: 'decision' });
44
+ }
45
+ }
46
+
47
+ for (const file of codeFiles) {
48
+ const id = file.relativePath.replace(/[^a-z0-9]+/gi, "-").toLowerCase();
49
+ nodes.set(id, {
50
+ id,
51
+ type: 'code',
52
+ label: file.relativePath,
53
+ filePath: file.relativePath,
54
+ });
55
+ }
56
+
57
+ for (const doc of documents) {
58
+ for (const ref of doc.references) {
59
+ const normalizedRef = ref.replace(/\.md$/, "").replace(/[^a-z0-9]+/gi, "-").toLowerCase();
60
+ const targetNode = nodes.get(normalizedRef);
61
+ if (targetNode) {
62
+ edges.push({
63
+ sourceId: doc.id,
64
+ targetId: normalizedRef,
65
+ type: 'relates-to',
66
+ confidence: 0.7,
67
+ evidence: `Explicit reference in ${doc.filePath}`,
68
+ });
69
+ }
70
+ }
71
+
72
+ for (const codeRef of doc.codeReferences) {
73
+ const matchingCodeNode = Array.from(nodes.values()).find(
74
+ (n) => n.type === 'code' && n.filePath?.includes(codeRef.replace(/^\.\//, ""))
75
+ );
76
+ if (matchingCodeNode) {
77
+ edges.push({
78
+ sourceId: doc.id,
79
+ targetId: matchingCodeNode.id,
80
+ type: 'documents',
81
+ confidence: 0.5,
82
+ evidence: `Code reference in ${doc.filePath}`,
83
+ });
84
+ }
85
+ }
86
+
87
+ const docDir = doc.filePath.replace(/\.[^.]+$/, "").toLowerCase();
88
+ for (const [nodeId, node] of nodes) {
89
+ if (node.type === 'code' && node.filePath) {
90
+ const codeDir = node.filePath.toLowerCase();
91
+ if (codeDir.includes(docDir.split("/").pop() ?? "") || docDir.includes(codeDir.split("/").pop() ?? "")) {
92
+ edges.push({
93
+ sourceId: doc.id,
94
+ targetId: nodeId,
95
+ type: 'relates-to',
96
+ confidence: 0.3,
97
+ evidence: `Path similarity: ${doc.filePath} ↔ ${node.filePath}`,
98
+ });
99
+ }
100
+ }
101
+ }
102
+ }
103
+
104
+ if (dependencyEdges) {
105
+ for (const edge of dependencyEdges) {
106
+ const fromId = edge.from.replace(/[^a-z0-9]+/gi, "-").toLowerCase();
107
+ const toId = edge.to.replace(/[^a-z0-9]+/gi, "-").toLowerCase();
108
+
109
+ const fromNode = Array.from(nodes.values()).find((n) => n.filePath === edge.from);
110
+ const toNode = Array.from(nodes.values()).find((n) => n.filePath === edge.to);
111
+
112
+ if (fromNode) {
113
+ nodes.set(fromId, fromNode);
114
+ }
115
+ if (toNode) {
116
+ nodes.set(toId, toNode);
117
+ }
118
+
119
+ edges.push({
120
+ sourceId: fromId,
121
+ targetId: toId,
122
+ type: 'depends-on',
123
+ confidence: 1.0,
124
+ evidence: `Import: ${edge.from} → ${edge.to}`,
125
+ });
126
+ }
127
+ }
128
+
129
+ return { nodes, edges };
130
+ }
131
+
132
+ findOrphanDocuments(graph: CrossReferenceGraph): string[] {
133
+ const referenced = new Set(graph.edges.map((e) => e.sourceId));
134
+ return Array.from(graph.nodes.values())
135
+ .filter((n) => n.type === 'document' && !referenced.has(n.id))
136
+ .map((n) => n.filePath ?? n.id);
137
+ }
138
+
139
+ findUndocumentedCode(
140
+ graph: CrossReferenceGraph,
141
+ minImportance: number = 1
142
+ ): string[] {
143
+ const documentedCode = new Set(
144
+ graph.edges
145
+ .filter((e) => e.type === 'documents')
146
+ .map((e) => e.targetId)
147
+ );
148
+ return Array.from(graph.nodes.values())
149
+ .filter((n) => n.type === 'code' && !documentedCode.has(n.id))
150
+ .map((n) => n.filePath ?? n.id);
151
+ }
152
+
153
+ traceChain(
154
+ graph: CrossReferenceGraph,
155
+ startId: string,
156
+ maxDepth: number = 3
157
+ ): string[][] {
158
+ const chains: string[][] = [];
159
+ const queue: Array<{ id: string; path: string[] }> = [
160
+ { id: startId, path: [startId] },
161
+ ];
162
+
163
+ while (queue.length > 0) {
164
+ const current = queue.shift()!;
165
+ if (current.path.length > maxDepth) continue;
166
+
167
+ const nextEdges = graph.edges.filter((e) => e.sourceId === current.id);
168
+ if (nextEdges.length === 0) {
169
+ chains.push([...current.path]);
170
+ continue;
171
+ }
172
+
173
+ for (const edge of nextEdges) {
174
+ if (!current.path.includes(edge.targetId)) {
175
+ queue.push({ id: edge.targetId, path: [...current.path, edge.targetId] });
176
+ }
177
+ }
178
+ }
179
+
180
+ return chains;
181
+ }
182
+ }