@vohongtho.infotech/code-intel 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/README.md +44 -6
  2. package/dist/cli/main.js +4738 -237
  3. package/dist/cli/main.js.map +1 -1
  4. package/dist/index.d.ts +396 -31
  5. package/dist/index.js +4832 -17
  6. package/dist/index.js.map +1 -1
  7. package/package.json +17 -12
  8. package/dist/call-graph/call-builder.d.ts +0 -6
  9. package/dist/call-graph/call-builder.d.ts.map +0 -1
  10. package/dist/call-graph/call-builder.js +0 -69
  11. package/dist/call-graph/call-builder.js.map +0 -1
  12. package/dist/call-graph/call-classifier.d.ts +0 -12
  13. package/dist/call-graph/call-classifier.d.ts.map +0 -1
  14. package/dist/call-graph/call-classifier.js +0 -11
  15. package/dist/call-graph/call-classifier.js.map +0 -1
  16. package/dist/call-graph/index.d.ts +0 -4
  17. package/dist/call-graph/index.d.ts.map +0 -1
  18. package/dist/call-graph/index.js +0 -3
  19. package/dist/call-graph/index.js.map +0 -1
  20. package/dist/cli/context-writer.d.ts +0 -18
  21. package/dist/cli/context-writer.d.ts.map +0 -1
  22. package/dist/cli/context-writer.js +0 -104
  23. package/dist/cli/context-writer.js.map +0 -1
  24. package/dist/cli/main.d.ts +0 -3
  25. package/dist/cli/main.d.ts.map +0 -1
  26. package/dist/cli/skill-writer.d.ts +0 -17
  27. package/dist/cli/skill-writer.d.ts.map +0 -1
  28. package/dist/cli/skill-writer.js +0 -249
  29. package/dist/cli/skill-writer.js.map +0 -1
  30. package/dist/clustering/community-detector.d.ts +0 -9
  31. package/dist/clustering/community-detector.d.ts.map +0 -1
  32. package/dist/clustering/community-detector.js +0 -67
  33. package/dist/clustering/community-detector.js.map +0 -1
  34. package/dist/clustering/index.d.ts +0 -3
  35. package/dist/clustering/index.d.ts.map +0 -1
  36. package/dist/clustering/index.js +0 -2
  37. package/dist/clustering/index.js.map +0 -1
  38. package/dist/flow-detection/entry-point-finder.d.ts +0 -14
  39. package/dist/flow-detection/entry-point-finder.d.ts.map +0 -1
  40. package/dist/flow-detection/entry-point-finder.js +0 -86
  41. package/dist/flow-detection/entry-point-finder.js.map +0 -1
  42. package/dist/flow-detection/index.d.ts +0 -3
  43. package/dist/flow-detection/index.d.ts.map +0 -1
  44. package/dist/flow-detection/index.js +0 -2
  45. package/dist/flow-detection/index.js.map +0 -1
  46. package/dist/graph/id-generator.d.ts +0 -4
  47. package/dist/graph/id-generator.d.ts.map +0 -1
  48. package/dist/graph/id-generator.js +0 -7
  49. package/dist/graph/id-generator.js.map +0 -1
  50. package/dist/graph/index.d.ts +0 -4
  51. package/dist/graph/index.d.ts.map +0 -1
  52. package/dist/graph/index.js +0 -3
  53. package/dist/graph/index.js.map +0 -1
  54. package/dist/graph/knowledge-graph.d.ts +0 -21
  55. package/dist/graph/knowledge-graph.d.ts.map +0 -1
  56. package/dist/graph/knowledge-graph.js +0 -126
  57. package/dist/graph/knowledge-graph.js.map +0 -1
  58. package/dist/http/app.d.ts +0 -5
  59. package/dist/http/app.d.ts.map +0 -1
  60. package/dist/http/app.js +0 -361
  61. package/dist/http/app.js.map +0 -1
  62. package/dist/http/index.d.ts +0 -2
  63. package/dist/http/index.d.ts.map +0 -1
  64. package/dist/http/index.js +0 -2
  65. package/dist/http/index.js.map +0 -1
  66. package/dist/index.d.ts.map +0 -1
  67. package/dist/inheritance/heritage-builder.d.ts +0 -9
  68. package/dist/inheritance/heritage-builder.d.ts.map +0 -1
  69. package/dist/inheritance/heritage-builder.js +0 -40
  70. package/dist/inheritance/heritage-builder.js.map +0 -1
  71. package/dist/inheritance/index.d.ts +0 -6
  72. package/dist/inheritance/index.d.ts.map +0 -1
  73. package/dist/inheritance/index.js +0 -4
  74. package/dist/inheritance/index.js.map +0 -1
  75. package/dist/inheritance/mro-walker.d.ts +0 -3
  76. package/dist/inheritance/mro-walker.d.ts.map +0 -1
  77. package/dist/inheritance/mro-walker.js +0 -80
  78. package/dist/inheritance/mro-walker.js.map +0 -1
  79. package/dist/inheritance/override-detector.d.ts +0 -4
  80. package/dist/inheritance/override-detector.d.ts.map +0 -1
  81. package/dist/inheritance/override-detector.js +0 -39
  82. package/dist/inheritance/override-detector.js.map +0 -1
  83. package/dist/languages/index.d.ts +0 -3
  84. package/dist/languages/index.d.ts.map +0 -1
  85. package/dist/languages/index.js +0 -2
  86. package/dist/languages/index.js.map +0 -1
  87. package/dist/languages/modules/c.d.ts +0 -3
  88. package/dist/languages/modules/c.d.ts.map +0 -1
  89. package/dist/languages/modules/c.js +0 -23
  90. package/dist/languages/modules/c.js.map +0 -1
  91. package/dist/languages/modules/cpp.d.ts +0 -3
  92. package/dist/languages/modules/cpp.d.ts.map +0 -1
  93. package/dist/languages/modules/cpp.js +0 -23
  94. package/dist/languages/modules/cpp.js.map +0 -1
  95. package/dist/languages/modules/csharp.d.ts +0 -3
  96. package/dist/languages/modules/csharp.d.ts.map +0 -1
  97. package/dist/languages/modules/csharp.js +0 -21
  98. package/dist/languages/modules/csharp.js.map +0 -1
  99. package/dist/languages/modules/dart.d.ts +0 -3
  100. package/dist/languages/modules/dart.d.ts.map +0 -1
  101. package/dist/languages/modules/dart.js +0 -30
  102. package/dist/languages/modules/dart.js.map +0 -1
  103. package/dist/languages/modules/go.d.ts +0 -3
  104. package/dist/languages/modules/go.d.ts.map +0 -1
  105. package/dist/languages/modules/go.js +0 -25
  106. package/dist/languages/modules/go.js.map +0 -1
  107. package/dist/languages/modules/java.d.ts +0 -3
  108. package/dist/languages/modules/java.d.ts.map +0 -1
  109. package/dist/languages/modules/java.js +0 -23
  110. package/dist/languages/modules/java.js.map +0 -1
  111. package/dist/languages/modules/kotlin.d.ts +0 -3
  112. package/dist/languages/modules/kotlin.d.ts.map +0 -1
  113. package/dist/languages/modules/kotlin.js +0 -22
  114. package/dist/languages/modules/kotlin.js.map +0 -1
  115. package/dist/languages/modules/php.d.ts +0 -3
  116. package/dist/languages/modules/php.d.ts.map +0 -1
  117. package/dist/languages/modules/php.js +0 -21
  118. package/dist/languages/modules/php.js.map +0 -1
  119. package/dist/languages/modules/python.d.ts +0 -3
  120. package/dist/languages/modules/python.d.ts.map +0 -1
  121. package/dist/languages/modules/python.js +0 -36
  122. package/dist/languages/modules/python.js.map +0 -1
  123. package/dist/languages/modules/ruby.d.ts +0 -3
  124. package/dist/languages/modules/ruby.d.ts.map +0 -1
  125. package/dist/languages/modules/ruby.js +0 -20
  126. package/dist/languages/modules/ruby.js.map +0 -1
  127. package/dist/languages/modules/rust.d.ts +0 -3
  128. package/dist/languages/modules/rust.d.ts.map +0 -1
  129. package/dist/languages/modules/rust.js +0 -23
  130. package/dist/languages/modules/rust.js.map +0 -1
  131. package/dist/languages/modules/swift.d.ts +0 -3
  132. package/dist/languages/modules/swift.d.ts.map +0 -1
  133. package/dist/languages/modules/swift.js +0 -21
  134. package/dist/languages/modules/swift.js.map +0 -1
  135. package/dist/languages/modules/typescript.d.ts +0 -4
  136. package/dist/languages/modules/typescript.d.ts.map +0 -1
  137. package/dist/languages/modules/typescript.js +0 -47
  138. package/dist/languages/modules/typescript.js.map +0 -1
  139. package/dist/languages/registry.d.ts +0 -5
  140. package/dist/languages/registry.d.ts.map +0 -1
  141. package/dist/languages/registry.js +0 -37
  142. package/dist/languages/registry.js.map +0 -1
  143. package/dist/languages/types.d.ts +0 -18
  144. package/dist/languages/types.d.ts.map +0 -1
  145. package/dist/languages/types.js +0 -2
  146. package/dist/languages/types.js.map +0 -1
  147. package/dist/mcp-server/index.d.ts +0 -2
  148. package/dist/mcp-server/index.d.ts.map +0 -1
  149. package/dist/mcp-server/index.js +0 -2
  150. package/dist/mcp-server/index.js.map +0 -1
  151. package/dist/mcp-server/server.d.ts +0 -5
  152. package/dist/mcp-server/server.d.ts.map +0 -1
  153. package/dist/mcp-server/server.js +0 -224
  154. package/dist/mcp-server/server.js.map +0 -1
  155. package/dist/multi-repo/cross-repo-search.d.ts +0 -3
  156. package/dist/multi-repo/cross-repo-search.d.ts.map +0 -1
  157. package/dist/multi-repo/cross-repo-search.js +0 -5
  158. package/dist/multi-repo/cross-repo-search.js.map +0 -1
  159. package/dist/multi-repo/group-config.d.ts +0 -10
  160. package/dist/multi-repo/group-config.d.ts.map +0 -1
  161. package/dist/multi-repo/group-config.js +0 -54
  162. package/dist/multi-repo/group-config.js.map +0 -1
  163. package/dist/multi-repo/group-manager.d.ts +0 -6
  164. package/dist/multi-repo/group-manager.d.ts.map +0 -1
  165. package/dist/multi-repo/group-manager.js +0 -42
  166. package/dist/multi-repo/group-manager.js.map +0 -1
  167. package/dist/multi-repo/index.d.ts +0 -5
  168. package/dist/multi-repo/index.d.ts.map +0 -1
  169. package/dist/multi-repo/index.js +0 -4
  170. package/dist/multi-repo/index.js.map +0 -1
  171. package/dist/parsing/ast-cache.d.ts +0 -13
  172. package/dist/parsing/ast-cache.d.ts.map +0 -1
  173. package/dist/parsing/ast-cache.js +0 -45
  174. package/dist/parsing/ast-cache.js.map +0 -1
  175. package/dist/parsing/index.d.ts +0 -5
  176. package/dist/parsing/index.d.ts.map +0 -1
  177. package/dist/parsing/index.js +0 -4
  178. package/dist/parsing/index.js.map +0 -1
  179. package/dist/parsing/parser-manager.d.ts +0 -7
  180. package/dist/parsing/parser-manager.d.ts.map +0 -1
  181. package/dist/parsing/parser-manager.js +0 -48
  182. package/dist/parsing/parser-manager.js.map +0 -1
  183. package/dist/parsing/queries/c.d.ts +0 -2
  184. package/dist/parsing/queries/c.d.ts.map +0 -1
  185. package/dist/parsing/queries/c.js +0 -32
  186. package/dist/parsing/queries/c.js.map +0 -1
  187. package/dist/parsing/queries/cpp.d.ts +0 -2
  188. package/dist/parsing/queries/cpp.d.ts.map +0 -1
  189. package/dist/parsing/queries/cpp.js +0 -45
  190. package/dist/parsing/queries/cpp.js.map +0 -1
  191. package/dist/parsing/queries/csharp.d.ts +0 -2
  192. package/dist/parsing/queries/csharp.d.ts.map +0 -1
  193. package/dist/parsing/queries/csharp.js +0 -55
  194. package/dist/parsing/queries/csharp.js.map +0 -1
  195. package/dist/parsing/queries/go.d.ts +0 -2
  196. package/dist/parsing/queries/go.d.ts.map +0 -1
  197. package/dist/parsing/queries/go.js +0 -46
  198. package/dist/parsing/queries/go.js.map +0 -1
  199. package/dist/parsing/queries/index.d.ts +0 -13
  200. package/dist/parsing/queries/index.d.ts.map +0 -1
  201. package/dist/parsing/queries/index.js +0 -13
  202. package/dist/parsing/queries/index.js.map +0 -1
  203. package/dist/parsing/queries/java.d.ts +0 -2
  204. package/dist/parsing/queries/java.d.ts.map +0 -1
  205. package/dist/parsing/queries/java.js +0 -46
  206. package/dist/parsing/queries/java.js.map +0 -1
  207. package/dist/parsing/queries/kotlin.d.ts +0 -2
  208. package/dist/parsing/queries/kotlin.d.ts.map +0 -1
  209. package/dist/parsing/queries/kotlin.js +0 -41
  210. package/dist/parsing/queries/kotlin.js.map +0 -1
  211. package/dist/parsing/queries/php.d.ts +0 -2
  212. package/dist/parsing/queries/php.d.ts.map +0 -1
  213. package/dist/parsing/queries/php.js +0 -60
  214. package/dist/parsing/queries/php.js.map +0 -1
  215. package/dist/parsing/queries/python.d.ts +0 -2
  216. package/dist/parsing/queries/python.d.ts.map +0 -1
  217. package/dist/parsing/queries/python.js +0 -47
  218. package/dist/parsing/queries/python.js.map +0 -1
  219. package/dist/parsing/queries/ruby.d.ts +0 -2
  220. package/dist/parsing/queries/ruby.d.ts.map +0 -1
  221. package/dist/parsing/queries/ruby.js +0 -36
  222. package/dist/parsing/queries/ruby.js.map +0 -1
  223. package/dist/parsing/queries/rust.d.ts +0 -2
  224. package/dist/parsing/queries/rust.d.ts.map +0 -1
  225. package/dist/parsing/queries/rust.js +0 -47
  226. package/dist/parsing/queries/rust.js.map +0 -1
  227. package/dist/parsing/queries/swift.d.ts +0 -2
  228. package/dist/parsing/queries/swift.d.ts.map +0 -1
  229. package/dist/parsing/queries/swift.js +0 -39
  230. package/dist/parsing/queries/swift.js.map +0 -1
  231. package/dist/parsing/queries/typescript.d.ts +0 -2
  232. package/dist/parsing/queries/typescript.d.ts.map +0 -1
  233. package/dist/parsing/queries/typescript.js +0 -84
  234. package/dist/parsing/queries/typescript.js.map +0 -1
  235. package/dist/parsing/query-runner.d.ts +0 -8
  236. package/dist/parsing/query-runner.d.ts.map +0 -1
  237. package/dist/parsing/query-runner.js +0 -16
  238. package/dist/parsing/query-runner.js.map +0 -1
  239. package/dist/pipeline/dag-validator.d.ts +0 -8
  240. package/dist/pipeline/dag-validator.d.ts.map +0 -1
  241. package/dist/pipeline/dag-validator.js +0 -88
  242. package/dist/pipeline/dag-validator.js.map +0 -1
  243. package/dist/pipeline/index.d.ts +0 -6
  244. package/dist/pipeline/index.d.ts.map +0 -1
  245. package/dist/pipeline/index.js +0 -4
  246. package/dist/pipeline/index.js.map +0 -1
  247. package/dist/pipeline/orchestrator.d.ts +0 -8
  248. package/dist/pipeline/orchestrator.d.ts.map +0 -1
  249. package/dist/pipeline/orchestrator.js +0 -47
  250. package/dist/pipeline/orchestrator.js.map +0 -1
  251. package/dist/pipeline/phases/cluster-phase.d.ts +0 -3
  252. package/dist/pipeline/phases/cluster-phase.d.ts.map +0 -1
  253. package/dist/pipeline/phases/cluster-phase.js +0 -52
  254. package/dist/pipeline/phases/cluster-phase.js.map +0 -1
  255. package/dist/pipeline/phases/flow-phase.d.ts +0 -3
  256. package/dist/pipeline/phases/flow-phase.d.ts.map +0 -1
  257. package/dist/pipeline/phases/flow-phase.js +0 -92
  258. package/dist/pipeline/phases/flow-phase.js.map +0 -1
  259. package/dist/pipeline/phases/index.d.ts +0 -6
  260. package/dist/pipeline/phases/index.d.ts.map +0 -1
  261. package/dist/pipeline/phases/index.js +0 -6
  262. package/dist/pipeline/phases/index.js.map +0 -1
  263. package/dist/pipeline/phases/parse-phase.d.ts +0 -3
  264. package/dist/pipeline/phases/parse-phase.d.ts.map +0 -1
  265. package/dist/pipeline/phases/parse-phase.js +0 -288
  266. package/dist/pipeline/phases/parse-phase.js.map +0 -1
  267. package/dist/pipeline/phases/resolve-phase.d.ts +0 -3
  268. package/dist/pipeline/phases/resolve-phase.d.ts.map +0 -1
  269. package/dist/pipeline/phases/resolve-phase.js +0 -388
  270. package/dist/pipeline/phases/resolve-phase.js.map +0 -1
  271. package/dist/pipeline/phases/scan-phase.d.ts +0 -4
  272. package/dist/pipeline/phases/scan-phase.d.ts.map +0 -1
  273. package/dist/pipeline/phases/scan-phase.js +0 -119
  274. package/dist/pipeline/phases/scan-phase.js.map +0 -1
  275. package/dist/pipeline/types.d.ts +0 -19
  276. package/dist/pipeline/types.d.ts.map +0 -1
  277. package/dist/pipeline/types.js +0 -2
  278. package/dist/pipeline/types.js.map +0 -1
  279. package/dist/resolver/binding-tracker.d.ts +0 -15
  280. package/dist/resolver/binding-tracker.d.ts.map +0 -1
  281. package/dist/resolver/binding-tracker.js +0 -22
  282. package/dist/resolver/binding-tracker.js.map +0 -1
  283. package/dist/resolver/import-resolver.d.ts +0 -16
  284. package/dist/resolver/import-resolver.d.ts.map +0 -1
  285. package/dist/resolver/import-resolver.js +0 -43
  286. package/dist/resolver/import-resolver.js.map +0 -1
  287. package/dist/resolver/index.d.ts +0 -5
  288. package/dist/resolver/index.d.ts.map +0 -1
  289. package/dist/resolver/index.js +0 -3
  290. package/dist/resolver/index.js.map +0 -1
  291. package/dist/resolver/strategies/namespace-alias.d.ts +0 -3
  292. package/dist/resolver/strategies/namespace-alias.d.ts.map +0 -1
  293. package/dist/resolver/strategies/namespace-alias.js +0 -15
  294. package/dist/resolver/strategies/namespace-alias.js.map +0 -1
  295. package/dist/resolver/strategies/package-lookup.d.ts +0 -3
  296. package/dist/resolver/strategies/package-lookup.d.ts.map +0 -1
  297. package/dist/resolver/strategies/package-lookup.js +0 -10
  298. package/dist/resolver/strategies/package-lookup.js.map +0 -1
  299. package/dist/resolver/strategies/relative-path.d.ts +0 -3
  300. package/dist/resolver/strategies/relative-path.d.ts.map +0 -1
  301. package/dist/resolver/strategies/relative-path.js +0 -12
  302. package/dist/resolver/strategies/relative-path.js.map +0 -1
  303. package/dist/resolver/strategies/types.d.ts +0 -11
  304. package/dist/resolver/strategies/types.d.ts.map +0 -1
  305. package/dist/resolver/strategies/types.js +0 -2
  306. package/dist/resolver/strategies/types.js.map +0 -1
  307. package/dist/resolver/strategies/wildcard-expand.d.ts +0 -3
  308. package/dist/resolver/strategies/wildcard-expand.d.ts.map +0 -1
  309. package/dist/resolver/strategies/wildcard-expand.js +0 -8
  310. package/dist/resolver/strategies/wildcard-expand.js.map +0 -1
  311. package/dist/scope-analysis/index.d.ts +0 -3
  312. package/dist/scope-analysis/index.d.ts.map +0 -1
  313. package/dist/scope-analysis/index.js +0 -2
  314. package/dist/scope-analysis/index.js.map +0 -1
  315. package/dist/scope-analysis/scope-builder.d.ts +0 -16
  316. package/dist/scope-analysis/scope-builder.d.ts.map +0 -1
  317. package/dist/scope-analysis/scope-builder.js +0 -19
  318. package/dist/scope-analysis/scope-builder.js.map +0 -1
  319. package/dist/search/embedder.d.ts +0 -14
  320. package/dist/search/embedder.d.ts.map +0 -1
  321. package/dist/search/embedder.js +0 -45
  322. package/dist/search/embedder.js.map +0 -1
  323. package/dist/search/index.d.ts +0 -7
  324. package/dist/search/index.d.ts.map +0 -1
  325. package/dist/search/index.js +0 -4
  326. package/dist/search/index.js.map +0 -1
  327. package/dist/search/text-search.d.ts +0 -12
  328. package/dist/search/text-search.d.ts.map +0 -1
  329. package/dist/search/text-search.js +0 -72
  330. package/dist/search/text-search.js.map +0 -1
  331. package/dist/search/vector-index.d.ts +0 -18
  332. package/dist/search/vector-index.d.ts.map +0 -1
  333. package/dist/search/vector-index.js +0 -70
  334. package/dist/search/vector-index.js.map +0 -1
  335. package/dist/shared/detection.d.ts +0 -4
  336. package/dist/shared/detection.d.ts.map +0 -1
  337. package/dist/shared/detection.js +0 -38
  338. package/dist/shared/detection.js.map +0 -1
  339. package/dist/shared/graph-types.d.ts +0 -22
  340. package/dist/shared/graph-types.d.ts.map +0 -1
  341. package/dist/shared/graph-types.js +0 -2
  342. package/dist/shared/graph-types.js.map +0 -1
  343. package/dist/shared/index.d.ts +0 -5
  344. package/dist/shared/index.d.ts.map +0 -1
  345. package/dist/shared/index.js +0 -3
  346. package/dist/shared/index.js.map +0 -1
  347. package/dist/shared/languages.d.ts +0 -17
  348. package/dist/shared/languages.d.ts.map +0 -1
  349. package/dist/shared/languages.js +0 -18
  350. package/dist/shared/languages.js.map +0 -1
  351. package/dist/shared/pipeline-types.d.ts +0 -21
  352. package/dist/shared/pipeline-types.d.ts.map +0 -1
  353. package/dist/shared/pipeline-types.js +0 -2
  354. package/dist/shared/pipeline-types.js.map +0 -1
  355. package/dist/storage/csv-writer.d.ts +0 -9
  356. package/dist/storage/csv-writer.d.ts.map +0 -1
  357. package/dist/storage/csv-writer.js +0 -77
  358. package/dist/storage/csv-writer.js.map +0 -1
  359. package/dist/storage/db-manager.d.ts +0 -12
  360. package/dist/storage/db-manager.d.ts.map +0 -1
  361. package/dist/storage/db-manager.js +0 -50
  362. package/dist/storage/db-manager.js.map +0 -1
  363. package/dist/storage/graph-loader.d.ts +0 -7
  364. package/dist/storage/graph-loader.d.ts.map +0 -1
  365. package/dist/storage/graph-loader.js +0 -71
  366. package/dist/storage/graph-loader.js.map +0 -1
  367. package/dist/storage/index.d.ts +0 -10
  368. package/dist/storage/index.d.ts.map +0 -1
  369. package/dist/storage/index.js +0 -7
  370. package/dist/storage/index.js.map +0 -1
  371. package/dist/storage/metadata.d.ts +0 -15
  372. package/dist/storage/metadata.d.ts.map +0 -1
  373. package/dist/storage/metadata.js +0 -23
  374. package/dist/storage/metadata.js.map +0 -1
  375. package/dist/storage/repo-registry.d.ts +0 -15
  376. package/dist/storage/repo-registry.d.ts.map +0 -1
  377. package/dist/storage/repo-registry.js +0 -34
  378. package/dist/storage/repo-registry.js.map +0 -1
  379. package/dist/storage/schema.d.ts +0 -6
  380. package/dist/storage/schema.d.ts.map +0 -1
  381. package/dist/storage/schema.js +0 -54
  382. package/dist/storage/schema.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,18 +1,4833 @@
1
- export { createKnowledgeGraph } from './graph/index.js';
2
- export { generateNodeId, generateEdgeId } from './graph/index.js';
3
- export { initParser, getParser, getLanguage, parseSource, runQuery, AstCache } from './parsing/index.js';
4
- export { getLanguageModule, getAllLanguageModules } from './languages/index.js';
5
- export { resolveImports, BindingTracker } from './resolver/index.js';
6
- export { buildCallEdges, classifyCall } from './call-graph/index.js';
7
- export { buildHeritageEdges, computeMRO, detectOverrides } from './inheritance/index.js';
8
- export { runPipeline, validateDAG, topologicalSort } from './pipeline/index.js';
9
- export { scanPhase, structurePhase, parsePhase, resolvePhase, clusterPhase, flowPhase, } from './pipeline/index.js';
10
- export { createScope, resolveBinding, addBinding } from './scope-analysis/index.js';
11
- export { detectCommunities, addClustersToGraph } from './clustering/index.js';
12
- export { findEntryPoints, traceFlow } from './flow-detection/index.js';
13
- export { textSearch, reciprocalRankFusion } from './search/index.js';
14
- export { createMcpServer, startMcpStdio } from './mcp-server/index.js';
15
- export { createApp, startHttpServer } from './http/index.js';
16
- export { DbManager, loadGraphToDB, upsertRepo, loadRegistry, removeRepo, saveMetadata, loadMetadata, getDbPath } from './storage/index.js';
17
- export { listGroups, getGroup, createGroup, deleteGroup, mergeSearchResults } from './multi-repo/index.js';
1
+ import fs6 from 'fs';
2
+ import path6 from 'path';
3
+ import os3 from 'os';
4
+ import { Parser, Language, Query } from 'web-tree-sitter';
5
+ import winston from 'winston';
6
+ import DailyRotateFile from 'winston-daily-rotate-file';
7
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
8
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js';
10
+ import { Database, Connection } from '@ladybugdb/core';
11
+ import { execSync } from 'child_process';
12
+ import express from 'express';
13
+ import cors from 'cors';
14
+ import { fileURLToPath } from 'url';
15
+
16
+ var __defProp = Object.defineProperty;
17
+ var __getOwnPropNames = Object.getOwnPropertyNames;
18
+ var __esm = (fn, res) => function __init() {
19
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
20
+ };
21
+ var __export = (target, all) => {
22
+ for (var name in all)
23
+ __defProp(target, name, { get: all[name], enumerable: true });
24
+ };
25
+
26
+ // src/search/embedder.ts
27
+ var embedder_exports = {};
28
+ __export(embedder_exports, {
29
+ embedNodes: () => embedNodes
30
+ });
31
+ async function getEmbedder() {
32
+ if (!pipelineInstance) {
33
+ const { pipeline } = await import('@huggingface/transformers');
34
+ pipelineInstance = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
35
+ }
36
+ return pipelineInstance;
37
+ }
38
+ async function embedNodes(graph, opts = {}) {
39
+ const { batchSize = 32, onProgress } = opts;
40
+ const candidates = [];
41
+ for (const node of graph.allNodes()) {
42
+ if (["cluster", "directory", "flow"].includes(node.kind)) continue;
43
+ const text = buildText(node);
44
+ candidates.push({ id: node.id, name: node.name, kind: node.kind, filePath: node.filePath, text });
45
+ }
46
+ const embedder = await getEmbedder();
47
+ const results = [];
48
+ for (let i = 0; i < candidates.length; i += batchSize) {
49
+ const batch = candidates.slice(i, i + batchSize);
50
+ const texts = batch.map((c) => c.text);
51
+ for (let j = 0; j < texts.length; j++) {
52
+ const out = await embedder(texts[j], { pooling: "mean", normalize: true });
53
+ results.push({ ...batch[j], embedding: Array.from(out.data) });
54
+ }
55
+ onProgress?.(Math.min(i + batchSize, candidates.length), candidates.length);
56
+ }
57
+ return results;
58
+ }
59
+ function buildText(node) {
60
+ const parts = [`${node.kind} ${node.name}`];
61
+ const sig = node.metadata?.signature;
62
+ if (sig) parts.push(sig);
63
+ if (node.content) parts.push(node.content.slice(0, 256));
64
+ parts.push(node.filePath);
65
+ return parts.join(" ").slice(0, 512);
66
+ }
67
+ var pipelineInstance;
68
+ var init_embedder = __esm({
69
+ "src/search/embedder.ts"() {
70
+ pipelineInstance = null;
71
+ }
72
+ });
73
+
74
+ // src/multi-repo/group-registry.ts
75
+ var group_registry_exports = {};
76
+ __export(group_registry_exports, {
77
+ addMember: () => addMember,
78
+ deleteGroup: () => deleteGroup,
79
+ groupExists: () => groupExists,
80
+ listGroups: () => listGroups,
81
+ loadGroup: () => loadGroup,
82
+ loadSyncResult: () => loadSyncResult,
83
+ removeMember: () => removeMember,
84
+ saveGroup: () => saveGroup,
85
+ saveSyncResult: () => saveSyncResult
86
+ });
87
+ function groupFile(name) {
88
+ return path6.join(GROUPS_DIR, `${name}.json`);
89
+ }
90
+ function loadGroup(name) {
91
+ try {
92
+ return JSON.parse(fs6.readFileSync(groupFile(name), "utf-8"));
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+ function saveGroup(group) {
98
+ fs6.mkdirSync(GROUPS_DIR, { recursive: true });
99
+ fs6.writeFileSync(groupFile(group.name), JSON.stringify(group, null, 2) + "\n");
100
+ }
101
+ function listGroups() {
102
+ const groups = [];
103
+ try {
104
+ for (const file of fs6.readdirSync(GROUPS_DIR)) {
105
+ if (!file.endsWith(".json") || file.endsWith(".sync.json")) continue;
106
+ try {
107
+ const g = JSON.parse(
108
+ fs6.readFileSync(path6.join(GROUPS_DIR, file), "utf-8")
109
+ );
110
+ groups.push(g);
111
+ } catch {
112
+ }
113
+ }
114
+ } catch {
115
+ }
116
+ return groups;
117
+ }
118
+ function deleteGroup(name) {
119
+ try {
120
+ fs6.unlinkSync(groupFile(name));
121
+ } catch {
122
+ }
123
+ try {
124
+ fs6.unlinkSync(path6.join(GROUPS_DIR, `${name}.sync.json`));
125
+ } catch {
126
+ }
127
+ }
128
+ function groupExists(name) {
129
+ return fs6.existsSync(groupFile(name));
130
+ }
131
+ function addMember(groupName, member) {
132
+ const group = loadGroup(groupName);
133
+ if (!group) throw new Error(`Group "${groupName}" not found.`);
134
+ const idx = group.members.findIndex((m) => m.groupPath === member.groupPath);
135
+ if (idx >= 0) {
136
+ group.members[idx] = member;
137
+ } else {
138
+ group.members.push(member);
139
+ }
140
+ saveGroup(group);
141
+ return group;
142
+ }
143
+ function removeMember(groupName, groupPath) {
144
+ const group = loadGroup(groupName);
145
+ if (!group) throw new Error(`Group "${groupName}" not found.`);
146
+ const before = group.members.length;
147
+ group.members = group.members.filter((m) => m.groupPath !== groupPath);
148
+ if (group.members.length === before) {
149
+ throw new Error(`No member at path "${groupPath}" in group "${groupName}".`);
150
+ }
151
+ saveGroup(group);
152
+ return group;
153
+ }
154
+ function saveSyncResult(result) {
155
+ fs6.mkdirSync(GROUPS_DIR, { recursive: true });
156
+ fs6.writeFileSync(
157
+ path6.join(GROUPS_DIR, `${result.groupName}.sync.json`),
158
+ JSON.stringify(result, null, 2) + "\n"
159
+ );
160
+ }
161
+ function loadSyncResult(groupName) {
162
+ try {
163
+ return JSON.parse(
164
+ fs6.readFileSync(path6.join(GROUPS_DIR, `${groupName}.sync.json`), "utf-8")
165
+ );
166
+ } catch {
167
+ return null;
168
+ }
169
+ }
170
+ var GROUPS_DIR;
171
+ var init_group_registry = __esm({
172
+ "src/multi-repo/group-registry.ts"() {
173
+ GROUPS_DIR = path6.join(os3.homedir(), ".code-intel", "groups");
174
+ }
175
+ });
176
+
177
+ // src/graph/knowledge-graph.ts
178
+ function createKnowledgeGraph() {
179
+ const nodes = /* @__PURE__ */ new Map();
180
+ const edges = /* @__PURE__ */ new Map();
181
+ const edgesByKind = /* @__PURE__ */ new Map();
182
+ const edgesFromNode = /* @__PURE__ */ new Map();
183
+ const edgesToNode = /* @__PURE__ */ new Map();
184
+ function indexEdge(edge) {
185
+ let kindSet = edgesByKind.get(edge.kind);
186
+ if (!kindSet) {
187
+ kindSet = /* @__PURE__ */ new Set();
188
+ edgesByKind.set(edge.kind, kindSet);
189
+ }
190
+ kindSet.add(edge.id);
191
+ let fromSet = edgesFromNode.get(edge.source);
192
+ if (!fromSet) {
193
+ fromSet = /* @__PURE__ */ new Set();
194
+ edgesFromNode.set(edge.source, fromSet);
195
+ }
196
+ fromSet.add(edge.id);
197
+ let toSet = edgesToNode.get(edge.target);
198
+ if (!toSet) {
199
+ toSet = /* @__PURE__ */ new Set();
200
+ edgesToNode.set(edge.target, toSet);
201
+ }
202
+ toSet.add(edge.id);
203
+ }
204
+ function unindexEdge(edge) {
205
+ edgesByKind.get(edge.kind)?.delete(edge.id);
206
+ edgesFromNode.get(edge.source)?.delete(edge.id);
207
+ edgesToNode.get(edge.target)?.delete(edge.id);
208
+ }
209
+ return {
210
+ addNode(node) {
211
+ nodes.set(node.id, node);
212
+ },
213
+ addEdge(edge) {
214
+ edges.set(edge.id, edge);
215
+ indexEdge(edge);
216
+ },
217
+ getNode(id) {
218
+ return nodes.get(id);
219
+ },
220
+ getEdge(id) {
221
+ return edges.get(id);
222
+ },
223
+ *findEdgesByKind(kind) {
224
+ const ids = edgesByKind.get(kind);
225
+ if (!ids) return;
226
+ for (const id of ids) {
227
+ const edge = edges.get(id);
228
+ if (edge) yield edge;
229
+ }
230
+ },
231
+ *findEdgesFrom(sourceId) {
232
+ const ids = edgesFromNode.get(sourceId);
233
+ if (!ids) return;
234
+ for (const id of ids) {
235
+ const edge = edges.get(id);
236
+ if (edge) yield edge;
237
+ }
238
+ },
239
+ *findEdgesTo(targetId) {
240
+ const ids = edgesToNode.get(targetId);
241
+ if (!ids) return;
242
+ for (const id of ids) {
243
+ const edge = edges.get(id);
244
+ if (edge) yield edge;
245
+ }
246
+ },
247
+ removeNodeCascade(id) {
248
+ const fromEdges = edgesFromNode.get(id);
249
+ if (fromEdges) {
250
+ for (const edgeId of [...fromEdges]) {
251
+ const edge = edges.get(edgeId);
252
+ if (edge) {
253
+ unindexEdge(edge);
254
+ edges.delete(edgeId);
255
+ }
256
+ }
257
+ }
258
+ const toEdges = edgesToNode.get(id);
259
+ if (toEdges) {
260
+ for (const edgeId of [...toEdges]) {
261
+ const edge = edges.get(edgeId);
262
+ if (edge) {
263
+ unindexEdge(edge);
264
+ edges.delete(edgeId);
265
+ }
266
+ }
267
+ }
268
+ edgesFromNode.delete(id);
269
+ edgesToNode.delete(id);
270
+ nodes.delete(id);
271
+ },
272
+ removeEdge(id) {
273
+ const edge = edges.get(id);
274
+ if (edge) {
275
+ unindexEdge(edge);
276
+ edges.delete(id);
277
+ }
278
+ },
279
+ *allNodes() {
280
+ yield* nodes.values();
281
+ },
282
+ *allEdges() {
283
+ yield* edges.values();
284
+ },
285
+ get size() {
286
+ return { nodes: nodes.size, edges: edges.size };
287
+ },
288
+ clear() {
289
+ nodes.clear();
290
+ edges.clear();
291
+ edgesByKind.clear();
292
+ edgesFromNode.clear();
293
+ edgesToNode.clear();
294
+ }
295
+ };
296
+ }
297
+
298
+ // src/graph/id-generator.ts
299
+ function generateNodeId(kind, filePath, qualifiedName) {
300
+ return `${kind}:${filePath}:${qualifiedName}`;
301
+ }
302
+ function generateEdgeId(source, target, kind) {
303
+ return `${kind}:${source}->${target}`;
304
+ }
305
+ var initialized = false;
306
+ var parserCache = /* @__PURE__ */ new Map();
307
+ var languageCache = /* @__PURE__ */ new Map();
308
+ var GRAMMAR_WASM_MAP = {
309
+ // WASM grammar files to be downloaded/provided per language
310
+ // For now, the parser manager provides a placeholder
311
+ };
312
+ async function initParser() {
313
+ if (initialized) return;
314
+ await Parser.init();
315
+ initialized = true;
316
+ }
317
+ async function getParser(lang) {
318
+ await initParser();
319
+ let parser = parserCache.get(lang);
320
+ if (parser) return parser;
321
+ parser = new Parser();
322
+ parserCache.set(lang, parser);
323
+ return parser;
324
+ }
325
+ async function getLanguage(lang) {
326
+ const cached = languageCache.get(lang);
327
+ if (cached) return cached;
328
+ const wasmPath = GRAMMAR_WASM_MAP[lang];
329
+ if (!wasmPath) return null;
330
+ try {
331
+ const language = await Language.load(wasmPath);
332
+ languageCache.set(lang, language);
333
+ return language;
334
+ } catch {
335
+ return null;
336
+ }
337
+ }
338
+ async function parseSource(lang, source) {
339
+ const parser = await getParser(lang);
340
+ const language = await getLanguage(lang);
341
+ if (!language) return null;
342
+ parser.setLanguage(language);
343
+ return parser.parse(source);
344
+ }
345
+ function runQuery(tree, language, querySource) {
346
+ const query = new Query(language, querySource);
347
+ const matches = query.matches(tree.rootNode);
348
+ const captures = [];
349
+ for (const match of matches) {
350
+ for (const capture of match.captures) {
351
+ captures.push({
352
+ name: capture.name,
353
+ node: capture.node,
354
+ text: capture.node.text
355
+ });
356
+ }
357
+ }
358
+ return captures;
359
+ }
360
+
361
+ // src/parsing/ast-cache.ts
362
+ var DEFAULT_MAX = 500;
363
+ var AstCache = class {
364
+ cache = /* @__PURE__ */ new Map();
365
+ maxEntries;
366
+ constructor(maxEntries = DEFAULT_MAX) {
367
+ this.maxEntries = maxEntries;
368
+ }
369
+ get(filePath) {
370
+ const entry = this.cache.get(filePath);
371
+ if (entry) {
372
+ entry.accessedAt = Date.now();
373
+ return entry.tree;
374
+ }
375
+ return void 0;
376
+ }
377
+ set(filePath, tree) {
378
+ if (this.cache.size >= this.maxEntries) {
379
+ this.evictLRU();
380
+ }
381
+ this.cache.set(filePath, { tree, accessedAt: Date.now() });
382
+ }
383
+ has(filePath) {
384
+ return this.cache.has(filePath);
385
+ }
386
+ clear() {
387
+ this.cache.clear();
388
+ }
389
+ get size() {
390
+ return this.cache.size;
391
+ }
392
+ evictLRU() {
393
+ let oldest = null;
394
+ let oldestTime = Infinity;
395
+ for (const [key, entry] of this.cache) {
396
+ if (entry.accessedAt < oldestTime) {
397
+ oldest = key;
398
+ oldestTime = entry.accessedAt;
399
+ }
400
+ }
401
+ if (oldest) {
402
+ this.cache.delete(oldest);
403
+ }
404
+ }
405
+ };
406
+
407
+ // src/shared/detection.ts
408
+ var EXTENSION_MAP = {
409
+ ".ts": "typescript" /* TypeScript */,
410
+ ".tsx": "typescript" /* TypeScript */,
411
+ ".mts": "typescript" /* TypeScript */,
412
+ ".cts": "typescript" /* TypeScript */,
413
+ ".js": "javascript" /* JavaScript */,
414
+ ".jsx": "javascript" /* JavaScript */,
415
+ ".mjs": "javascript" /* JavaScript */,
416
+ ".cjs": "javascript" /* JavaScript */,
417
+ ".py": "python" /* Python */,
418
+ ".pyi": "python" /* Python */,
419
+ ".java": "java" /* Java */,
420
+ ".go": "go" /* Go */,
421
+ ".c": "c" /* C */,
422
+ ".h": "c" /* C */,
423
+ ".cpp": "cpp" /* Cpp */,
424
+ ".cxx": "cpp" /* Cpp */,
425
+ ".cc": "cpp" /* Cpp */,
426
+ ".hpp": "cpp" /* Cpp */,
427
+ ".hxx": "cpp" /* Cpp */,
428
+ ".cs": "csharp" /* CSharp */,
429
+ ".rs": "rust" /* Rust */,
430
+ ".php": "php" /* PHP */,
431
+ ".kt": "kotlin" /* Kotlin */,
432
+ ".kts": "kotlin" /* Kotlin */,
433
+ ".rb": "ruby" /* Ruby */,
434
+ ".swift": "swift" /* Swift */,
435
+ ".dart": "dart" /* Dart */
436
+ };
437
+ function detectLanguage(filePath) {
438
+ const ext = filePath.slice(filePath.lastIndexOf("."));
439
+ return EXTENSION_MAP[ext] ?? null;
440
+ }
441
+ function getSupportedExtensions() {
442
+ return Object.keys(EXTENSION_MAP);
443
+ }
444
+
445
+ // src/parsing/queries/typescript.ts
446
+ var typescriptQueries = `
447
+ ;; Class declaration
448
+ (class_declaration
449
+ name: (type_identifier) @def.class.name) @def.class
450
+
451
+ ;; Abstract class
452
+ (abstract_class_declaration
453
+ name: (type_identifier) @def.class.name) @def.class
454
+
455
+ ;; Interface declaration
456
+ (interface_declaration
457
+ name: (type_identifier) @def.interface.name) @def.interface
458
+
459
+ ;; Type alias
460
+ (type_alias_declaration
461
+ name: (type_identifier) @def.type_alias.name) @def.type_alias
462
+
463
+ ;; Enum
464
+ (enum_declaration
465
+ name: (identifier) @def.enum.name) @def.enum
466
+
467
+ ;; Function declaration
468
+ (function_declaration
469
+ name: (identifier) @def.func.name) @def.func
470
+
471
+ ;; Arrow function in variable
472
+ (lexical_declaration
473
+ (variable_declarator
474
+ name: (identifier) @def.func.name
475
+ value: (arrow_function))) @def.func
476
+
477
+ ;; Const/let/var variable (non-function)
478
+ (lexical_declaration
479
+ (variable_declarator
480
+ name: (identifier) @def.var.name
481
+ value: (_) @def.var.value)) @def.var
482
+
483
+ ;; Method definition
484
+ (method_definition
485
+ name: (property_identifier) @def.method.name) @def.method
486
+
487
+ ;; Public field definition
488
+ (public_field_definition
489
+ name: (property_identifier) @def.property.name) @def.property
490
+
491
+ ;; Import statement
492
+ (import_statement
493
+ source: (string) @imp.source) @imp
494
+
495
+ ;; Import specifier
496
+ (import_specifier
497
+ name: (identifier) @imp.name)
498
+
499
+ ;; Namespace import
500
+ (namespace_import (identifier) @imp.namespace)
501
+
502
+ ;; Export statement
503
+ (export_statement) @export
504
+
505
+ ;; Call expression \u2014 function call
506
+ (call_expression
507
+ function: (identifier) @call.name) @call
508
+
509
+ ;; Call expression \u2014 member call
510
+ (call_expression
511
+ function: (member_expression
512
+ object: (_) @call.receiver
513
+ property: (property_identifier) @call.method)) @call.member
514
+
515
+ ;; New expression
516
+ (new_expression
517
+ constructor: (identifier) @call.constructor) @call.new
518
+
519
+ ;; Class heritage \u2014 extends
520
+ (class_heritage
521
+ (extends_clause
522
+ value: (identifier) @inherit.extends))
523
+
524
+ ;; Class heritage \u2014 implements
525
+ (class_heritage
526
+ (implements_clause
527
+ (type_reference (type_identifier) @inherit.implements)))
528
+ `;
529
+ function resolveRelative(rawPath, fromFile, workspace) {
530
+ const fromDir = path6.dirname(fromFile);
531
+ const cleaned = rawPath.replace(/['"]/g, "");
532
+ const extensions = [".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"];
533
+ const resolved = workspace.resolve(fromDir, cleaned);
534
+ if (resolved) return resolved;
535
+ for (const ext of extensions) {
536
+ const r = workspace.resolve(fromDir, cleaned + ext);
537
+ if (r) return r;
538
+ }
539
+ return null;
540
+ }
541
+ var typescriptModule = {
542
+ lang: "typescript" /* TypeScript */,
543
+ fileExtensions: [".ts", ".tsx", ".mts", ".cts"],
544
+ queries: typescriptQueries,
545
+ importStyle: "explicit",
546
+ inheritanceStrategy: "depth-first",
547
+ resolveImport(rawPath, fromFile, workspace) {
548
+ const cleaned = rawPath.replace(/['"]/g, "");
549
+ if (cleaned.startsWith(".")) {
550
+ return resolveRelative(rawPath, fromFile, workspace);
551
+ }
552
+ return workspace.findByPackage(cleaned);
553
+ },
554
+ isExported(node) {
555
+ const parent = node.parent;
556
+ if (!parent) return false;
557
+ return parent.type === "export_statement" || node.type === "export_statement";
558
+ },
559
+ extractType(node) {
560
+ const typeAnnotation = node.childForFieldName("type");
561
+ return typeAnnotation?.text ?? null;
562
+ }
563
+ };
564
+ var javascriptModule = {
565
+ ...typescriptModule,
566
+ lang: "javascript" /* JavaScript */,
567
+ fileExtensions: [".js", ".jsx", ".mjs", ".cjs"]
568
+ };
569
+
570
+ // src/parsing/queries/python.ts
571
+ var pythonQueries = `
572
+ ;; Class definition
573
+ (class_definition
574
+ name: (identifier) @def.class.name) @def.class
575
+
576
+ ;; Function definition
577
+ (function_definition
578
+ name: (identifier) @def.func.name) @def.func
579
+
580
+ ;; Decorated definition
581
+ (decorated_definition
582
+ (function_definition
583
+ name: (identifier) @def.func.name)) @def.func.decorated
584
+
585
+ ;; Import from
586
+ (import_from_statement
587
+ module_name: (dotted_name) @imp.source) @imp
588
+
589
+ ;; Import
590
+ (import_statement
591
+ name: (dotted_name) @imp.module) @imp.direct
592
+
593
+ ;; Import alias
594
+ (aliased_import
595
+ name: (dotted_name) @imp.alias.original
596
+ alias: (identifier) @imp.alias.name)
597
+
598
+ ;; Call expression
599
+ (call
600
+ function: (identifier) @call.name) @call
601
+
602
+ ;; Attribute call
603
+ (call
604
+ function: (attribute
605
+ object: (_) @call.receiver
606
+ attribute: (identifier) @call.method)) @call.member
607
+
608
+ ;; Assignment
609
+ (assignment
610
+ left: (identifier) @def.var.name) @def.var
611
+
612
+ ;; Class base classes
613
+ (class_definition
614
+ superclasses: (argument_list
615
+ (identifier) @inherit.extends))
616
+ `;
617
+ var pythonModule = {
618
+ lang: "python" /* Python */,
619
+ fileExtensions: [".py", ".pyi"],
620
+ queries: pythonQueries,
621
+ importStyle: "namespace",
622
+ inheritanceStrategy: "c3",
623
+ resolveImport(rawPath, fromFile, workspace) {
624
+ const cleaned = rawPath.replace(/['"]/g, "");
625
+ const parts = cleaned.split(".");
626
+ const fromDir = path6.dirname(fromFile);
627
+ const relPath = parts.join("/");
628
+ for (const suffix of ["/__init__.py", ".py"]) {
629
+ const r = workspace.resolve(fromDir, relPath + suffix);
630
+ if (r) return r;
631
+ }
632
+ return workspace.findByPackage(cleaned);
633
+ },
634
+ isExported(node) {
635
+ const name = node.childForFieldName("name");
636
+ if (!name) return true;
637
+ return !name.text.startsWith("_");
638
+ },
639
+ extractType(node) {
640
+ const returnType = node.childForFieldName("return_type");
641
+ return returnType?.text ?? null;
642
+ }
643
+ };
644
+
645
+ // src/parsing/queries/java.ts
646
+ var javaQueries = `
647
+ ;; Class declaration
648
+ (class_declaration
649
+ name: (identifier) @def.class.name) @def.class
650
+
651
+ ;; Interface declaration
652
+ (interface_declaration
653
+ name: (identifier) @def.interface.name) @def.interface
654
+
655
+ ;; Enum declaration
656
+ (enum_declaration
657
+ name: (identifier) @def.enum.name) @def.enum
658
+
659
+ ;; Method declaration
660
+ (method_declaration
661
+ name: (identifier) @def.method.name) @def.method
662
+
663
+ ;; Constructor declaration
664
+ (constructor_declaration
665
+ name: (identifier) @def.constructor.name) @def.constructor
666
+
667
+ ;; Field declaration
668
+ (field_declaration
669
+ declarator: (variable_declarator
670
+ name: (identifier) @def.property.name)) @def.property
671
+
672
+ ;; Import
673
+ (import_declaration
674
+ (scoped_identifier) @imp.source) @imp
675
+
676
+ ;; Call
677
+ (method_invocation
678
+ name: (identifier) @call.name) @call
679
+
680
+ ;; Object creation
681
+ (object_creation_expression
682
+ type: (type_identifier) @call.constructor) @call.new
683
+
684
+ ;; Extends
685
+ (superclass (type_identifier) @inherit.extends)
686
+
687
+ ;; Implements
688
+ (super_interfaces
689
+ (type_list (type_identifier) @inherit.implements))
690
+ `;
691
+
692
+ // src/languages/modules/java.ts
693
+ var javaModule = {
694
+ lang: "java" /* Java */,
695
+ fileExtensions: [".java"],
696
+ queries: javaQueries,
697
+ importStyle: "explicit",
698
+ inheritanceStrategy: "depth-first",
699
+ resolveImport(rawPath, _fromFile, workspace) {
700
+ const cleaned = rawPath.replace(/['"]/g, "");
701
+ const filePath = cleaned.replace(/\./g, "/") + ".java";
702
+ return workspace.findByPackage(filePath);
703
+ },
704
+ isExported(node) {
705
+ const text = node.text;
706
+ return text.includes("public");
707
+ },
708
+ extractType(node) {
709
+ const typeNode = node.childForFieldName("type");
710
+ return typeNode?.text ?? null;
711
+ }
712
+ };
713
+
714
+ // src/parsing/queries/go.ts
715
+ var goQueries = `
716
+ ;; Function declaration
717
+ (function_declaration
718
+ name: (identifier) @def.func.name) @def.func
719
+
720
+ ;; Method declaration
721
+ (method_declaration
722
+ name: (field_identifier) @def.method.name) @def.method
723
+
724
+ ;; Type declaration \u2014 struct
725
+ (type_declaration
726
+ (type_spec
727
+ name: (type_identifier) @def.struct.name
728
+ type: (struct_type))) @def.struct
729
+
730
+ ;; Type declaration \u2014 interface
731
+ (type_declaration
732
+ (type_spec
733
+ name: (type_identifier) @def.interface.name
734
+ type: (interface_type))) @def.interface
735
+
736
+ ;; Import spec
737
+ (import_spec
738
+ path: (interpreted_string_literal) @imp.source) @imp
739
+
740
+ ;; Call expression
741
+ (call_expression
742
+ function: (identifier) @call.name) @call
743
+
744
+ ;; Selector call
745
+ (call_expression
746
+ function: (selector_expression
747
+ operand: (_) @call.receiver
748
+ field: (field_identifier) @call.method)) @call.member
749
+
750
+ ;; Const declaration
751
+ (const_declaration
752
+ (const_spec
753
+ name: (identifier) @def.constant.name)) @def.constant
754
+
755
+ ;; Var declaration
756
+ (var_declaration
757
+ (var_spec
758
+ name: (identifier) @def.var.name)) @def.var
759
+ `;
760
+
761
+ // src/languages/modules/go.ts
762
+ var goModule = {
763
+ lang: "go" /* Go */,
764
+ fileExtensions: [".go"],
765
+ queries: goQueries,
766
+ importStyle: "wildcard",
767
+ inheritanceStrategy: "depth-first",
768
+ resolveImport(rawPath, _fromFile, workspace) {
769
+ const cleaned = rawPath.replace(/['"]/g, "");
770
+ return workspace.findByPackage(cleaned);
771
+ },
772
+ isExported(node) {
773
+ const name = node.childForFieldName("name");
774
+ if (!name) return false;
775
+ const first = name.text[0];
776
+ return first === first.toUpperCase() && first !== first.toLowerCase();
777
+ },
778
+ extractType(node) {
779
+ const typeNode = node.childForFieldName("type");
780
+ return typeNode?.text ?? null;
781
+ }
782
+ };
783
+
784
+ // src/parsing/queries/c.ts
785
+ var cQueries = `
786
+ ;; Function definition
787
+ (function_definition
788
+ declarator: (function_declarator
789
+ declarator: (identifier) @def.func.name)) @def.func
790
+
791
+ ;; Struct specifier
792
+ (struct_specifier
793
+ name: (type_identifier) @def.struct.name) @def.struct
794
+
795
+ ;; Enum specifier
796
+ (enum_specifier
797
+ name: (type_identifier) @def.enum.name) @def.enum
798
+
799
+ ;; Typedef
800
+ (type_definition
801
+ declarator: (type_identifier) @def.type_alias.name) @def.type_alias
802
+
803
+ ;; Include
804
+ (preproc_include
805
+ path: (_) @imp.source) @imp
806
+
807
+ ;; Call
808
+ (call_expression
809
+ function: (identifier) @call.name) @call
810
+
811
+ ;; Global variable
812
+ (declaration
813
+ declarator: (init_declarator
814
+ declarator: (identifier) @def.var.name)) @def.var
815
+ `;
816
+ var cModule = {
817
+ lang: "c" /* C */,
818
+ fileExtensions: [".c", ".h"],
819
+ queries: cQueries,
820
+ importStyle: "include",
821
+ inheritanceStrategy: "none",
822
+ resolveImport(rawPath, fromFile, workspace) {
823
+ const cleaned = rawPath.replace(/[<>"']/g, "");
824
+ const fromDir = path6.dirname(fromFile);
825
+ return workspace.resolve(fromDir, cleaned);
826
+ },
827
+ isExported(_node) {
828
+ return true;
829
+ },
830
+ extractType(node) {
831
+ const typeNode = node.childForFieldName("type");
832
+ return typeNode?.text ?? null;
833
+ }
834
+ };
835
+
836
+ // src/parsing/queries/cpp.ts
837
+ var cppQueries = `
838
+ ;; Class specifier
839
+ (class_specifier
840
+ name: (type_identifier) @def.class.name) @def.class
841
+
842
+ ;; Struct specifier
843
+ (struct_specifier
844
+ name: (type_identifier) @def.struct.name) @def.struct
845
+
846
+ ;; Function definition
847
+ (function_definition
848
+ declarator: (function_declarator
849
+ declarator: (identifier) @def.func.name)) @def.func
850
+
851
+ ;; Namespace definition
852
+ (namespace_definition
853
+ name: (identifier) @def.namespace.name) @def.namespace
854
+
855
+ ;; Template declaration
856
+ (template_declaration
857
+ (class_specifier
858
+ name: (type_identifier) @def.class.name)) @def.class.template
859
+
860
+ ;; Include
861
+ (preproc_include
862
+ path: (_) @imp.source) @imp
863
+
864
+ ;; Call
865
+ (call_expression
866
+ function: (identifier) @call.name) @call
867
+
868
+ ;; Member call
869
+ (call_expression
870
+ function: (field_expression
871
+ field: (field_identifier) @call.method)) @call.member
872
+
873
+ ;; Base class clause
874
+ (base_class_clause
875
+ (type_identifier) @inherit.extends)
876
+
877
+ ;; Enum
878
+ (enum_specifier
879
+ name: (type_identifier) @def.enum.name) @def.enum
880
+ `;
881
+ var cppModule = {
882
+ lang: "cpp" /* Cpp */,
883
+ fileExtensions: [".cpp", ".cxx", ".cc", ".hpp", ".hxx"],
884
+ queries: cppQueries,
885
+ importStyle: "include",
886
+ inheritanceStrategy: "depth-first",
887
+ resolveImport(rawPath, fromFile, workspace) {
888
+ const cleaned = rawPath.replace(/[<>"']/g, "");
889
+ const fromDir = path6.dirname(fromFile);
890
+ return workspace.resolve(fromDir, cleaned);
891
+ },
892
+ isExported(_node) {
893
+ return true;
894
+ },
895
+ extractType(node) {
896
+ const typeNode = node.childForFieldName("type");
897
+ return typeNode?.text ?? null;
898
+ }
899
+ };
900
+
901
+ // src/parsing/queries/csharp.ts
902
+ var csharpQueries = `
903
+ ;; Class declaration
904
+ (class_declaration
905
+ name: (identifier) @def.class.name) @def.class
906
+
907
+ ;; Interface declaration
908
+ (interface_declaration
909
+ name: (identifier) @def.interface.name) @def.interface
910
+
911
+ ;; Struct declaration
912
+ (struct_declaration
913
+ name: (identifier) @def.struct.name) @def.struct
914
+
915
+ ;; Enum declaration
916
+ (enum_declaration
917
+ name: (identifier) @def.enum.name) @def.enum
918
+
919
+ ;; Method declaration
920
+ (method_declaration
921
+ name: (identifier) @def.method.name) @def.method
922
+
923
+ ;; Constructor declaration
924
+ (constructor_declaration
925
+ name: (identifier) @def.constructor.name) @def.constructor
926
+
927
+ ;; Property declaration
928
+ (property_declaration
929
+ name: (identifier) @def.property.name) @def.property
930
+
931
+ ;; Namespace declaration
932
+ (namespace_declaration
933
+ name: (_) @def.namespace.name) @def.namespace
934
+
935
+ ;; Using directive
936
+ (using_directive
937
+ (qualified_name) @imp.source) @imp
938
+
939
+ ;; Invocation
940
+ (invocation_expression
941
+ function: (identifier) @call.name) @call
942
+
943
+ ;; Member invocation
944
+ (invocation_expression
945
+ function: (member_access_expression
946
+ name: (identifier) @call.method)) @call.member
947
+
948
+ ;; Object creation
949
+ (object_creation_expression
950
+ type: (identifier) @call.constructor) @call.new
951
+
952
+ ;; Base list (extends/implements)
953
+ (base_list
954
+ (identifier) @inherit.extends)
955
+ `;
956
+
957
+ // src/languages/modules/csharp.ts
958
+ var csharpModule = {
959
+ lang: "csharp" /* CSharp */,
960
+ fileExtensions: [".cs"],
961
+ queries: csharpQueries,
962
+ importStyle: "explicit",
963
+ inheritanceStrategy: "depth-first",
964
+ resolveImport(rawPath, _fromFile, workspace) {
965
+ const cleaned = rawPath.replace(/['"]/g, "");
966
+ return workspace.findByPackage(cleaned);
967
+ },
968
+ isExported(node) {
969
+ return node.text.includes("public") || node.text.includes("internal");
970
+ },
971
+ extractType(node) {
972
+ const typeNode = node.childForFieldName("type");
973
+ return typeNode?.text ?? null;
974
+ }
975
+ };
976
+
977
+ // src/parsing/queries/rust.ts
978
+ var rustQueries = `
979
+ ;; Function item
980
+ (function_item
981
+ name: (identifier) @def.func.name) @def.func
982
+
983
+ ;; Struct item
984
+ (struct_item
985
+ name: (type_identifier) @def.struct.name) @def.struct
986
+
987
+ ;; Enum item
988
+ (enum_item
989
+ name: (type_identifier) @def.enum.name) @def.enum
990
+
991
+ ;; Trait item
992
+ (trait_item
993
+ name: (type_identifier) @def.trait.name) @def.trait
994
+
995
+ ;; Impl item
996
+ (impl_item
997
+ type: (type_identifier) @def.class.name) @def.impl
998
+
999
+ ;; Type alias
1000
+ (type_item
1001
+ name: (type_identifier) @def.type_alias.name) @def.type_alias
1002
+
1003
+ ;; Use declaration
1004
+ (use_declaration
1005
+ argument: (_) @imp.source) @imp
1006
+
1007
+ ;; Call
1008
+ (call_expression
1009
+ function: (identifier) @call.name) @call
1010
+
1011
+ ;; Method call
1012
+ (call_expression
1013
+ function: (field_expression
1014
+ field: (field_identifier) @call.method)) @call.member
1015
+
1016
+ ;; Const item
1017
+ (const_item
1018
+ name: (identifier) @def.constant.name) @def.constant
1019
+
1020
+ ;; Static item
1021
+ (static_item
1022
+ name: (identifier) @def.var.name) @def.var
1023
+ `;
1024
+
1025
+ // src/languages/modules/rust.ts
1026
+ var rustModule = {
1027
+ lang: "rust" /* Rust */,
1028
+ fileExtensions: [".rs"],
1029
+ queries: rustQueries,
1030
+ importStyle: "explicit",
1031
+ inheritanceStrategy: "none",
1032
+ resolveImport(rawPath, _fromFile, workspace) {
1033
+ const cleaned = rawPath.replace(/['"]/g, "");
1034
+ const parts = cleaned.split("::");
1035
+ const filePath = parts.join("/") + ".rs";
1036
+ return workspace.findByPackage(filePath);
1037
+ },
1038
+ isExported(node) {
1039
+ return node.text.startsWith("pub ") || node.text.startsWith("pub(");
1040
+ },
1041
+ extractType(node) {
1042
+ const returnType = node.childForFieldName("return_type");
1043
+ return returnType?.text ?? null;
1044
+ }
1045
+ };
1046
+
1047
+ // src/parsing/queries/php.ts
1048
+ var phpQueries = `
1049
+ ;; Class declaration
1050
+ (class_declaration
1051
+ name: (name) @def.class.name) @def.class
1052
+
1053
+ ;; Interface declaration
1054
+ (interface_declaration
1055
+ name: (name) @def.interface.name) @def.interface
1056
+
1057
+ ;; Trait declaration
1058
+ (trait_declaration
1059
+ name: (name) @def.trait.name) @def.trait
1060
+
1061
+ ;; Function definition
1062
+ (function_definition
1063
+ name: (name) @def.func.name) @def.func
1064
+
1065
+ ;; Method declaration
1066
+ (method_declaration
1067
+ name: (name) @def.method.name) @def.method
1068
+
1069
+ ;; Property declaration
1070
+ (property_declaration
1071
+ (property_element
1072
+ (variable_name) @def.property.name)) @def.property
1073
+
1074
+ ;; Namespace definition
1075
+ (namespace_definition
1076
+ name: (namespace_name) @def.namespace.name) @def.namespace
1077
+
1078
+ ;; Use declaration (import)
1079
+ (namespace_use_declaration
1080
+ (namespace_use_clause
1081
+ (qualified_name) @imp.source)) @imp
1082
+
1083
+ ;; Include/require
1084
+ (include_expression
1085
+ (_) @imp.source) @imp.include
1086
+
1087
+ ;; Function call
1088
+ (function_call_expression
1089
+ function: (name) @call.name) @call
1090
+
1091
+ ;; Method call
1092
+ (member_call_expression
1093
+ name: (name) @call.method) @call.member
1094
+
1095
+ ;; Object creation
1096
+ (object_creation_expression
1097
+ (name) @call.constructor) @call.new
1098
+
1099
+ ;; Class base clause
1100
+ (base_clause
1101
+ (name) @inherit.extends)
1102
+
1103
+ ;; Class interface clause
1104
+ (class_interface_clause
1105
+ (name) @inherit.implements)
1106
+ `;
1107
+
1108
+ // src/languages/modules/php.ts
1109
+ var phpModule = {
1110
+ lang: "php" /* PHP */,
1111
+ fileExtensions: [".php"],
1112
+ queries: phpQueries,
1113
+ importStyle: "explicit",
1114
+ inheritanceStrategy: "depth-first",
1115
+ resolveImport(rawPath, _fromFile, workspace) {
1116
+ const cleaned = rawPath.replace(/['"\\]/g, "/").replace(/^\//, "");
1117
+ return workspace.findByPackage(cleaned + ".php");
1118
+ },
1119
+ isExported(node) {
1120
+ return node.text.includes("public") || !node.text.includes("private");
1121
+ },
1122
+ extractType(node) {
1123
+ const typeNode = node.childForFieldName("type");
1124
+ return typeNode?.text ?? null;
1125
+ }
1126
+ };
1127
+
1128
+ // src/parsing/queries/kotlin.ts
1129
+ var kotlinQueries = `
1130
+ ;; Class declaration
1131
+ (class_declaration
1132
+ (type_identifier) @def.class.name) @def.class
1133
+
1134
+ ;; Object declaration
1135
+ (object_declaration
1136
+ (type_identifier) @def.class.name) @def.class.object
1137
+
1138
+ ;; Interface declaration
1139
+ (class_declaration
1140
+ (type_identifier) @def.interface.name) @def.interface
1141
+
1142
+ ;; Function declaration
1143
+ (function_declaration
1144
+ (simple_identifier) @def.func.name) @def.func
1145
+
1146
+ ;; Property declaration
1147
+ (property_declaration
1148
+ (variable_declaration
1149
+ (simple_identifier) @def.property.name)) @def.property
1150
+
1151
+ ;; Import
1152
+ (import_header
1153
+ (identifier) @imp.source) @imp
1154
+
1155
+ ;; Call
1156
+ (call_expression
1157
+ (simple_identifier) @call.name) @call
1158
+
1159
+ ;; Navigation call
1160
+ (call_expression
1161
+ (navigation_expression
1162
+ (simple_identifier) @call.method)) @call.member
1163
+
1164
+ ;; Delegation specifier (extends/implements)
1165
+ (delegation_specifier
1166
+ (user_type
1167
+ (type_identifier) @inherit.extends))
1168
+ `;
1169
+
1170
+ // src/languages/modules/kotlin.ts
1171
+ var kotlinModule = {
1172
+ lang: "kotlin" /* Kotlin */,
1173
+ fileExtensions: [".kt", ".kts"],
1174
+ queries: kotlinQueries,
1175
+ importStyle: "explicit",
1176
+ inheritanceStrategy: "depth-first",
1177
+ resolveImport(rawPath, _fromFile, workspace) {
1178
+ const cleaned = rawPath.replace(/['"]/g, "");
1179
+ const filePath = cleaned.replace(/\./g, "/") + ".kt";
1180
+ return workspace.findByPackage(filePath);
1181
+ },
1182
+ isExported(node) {
1183
+ return !node.text.includes("private") && !node.text.includes("internal");
1184
+ },
1185
+ extractType(node) {
1186
+ const typeNode = node.childForFieldName("type");
1187
+ return typeNode?.text ?? null;
1188
+ }
1189
+ };
1190
+
1191
+ // src/parsing/queries/ruby.ts
1192
+ var rubyQueries = `
1193
+ ;; Class
1194
+ (class
1195
+ name: (constant) @def.class.name) @def.class
1196
+
1197
+ ;; Module
1198
+ (module
1199
+ name: (constant) @def.module.name) @def.module
1200
+
1201
+ ;; Method
1202
+ (method
1203
+ name: (identifier) @def.method.name) @def.method
1204
+
1205
+ ;; Singleton method
1206
+ (singleton_method
1207
+ name: (identifier) @def.method.name) @def.method.static
1208
+
1209
+ ;; Assignment
1210
+ (assignment
1211
+ left: (identifier) @def.var.name) @def.var
1212
+
1213
+ ;; Require
1214
+ (call
1215
+ method: (identifier) @_method
1216
+ arguments: (argument_list (string) @imp.source)
1217
+ (#match? @_method "^require"))
1218
+
1219
+ ;; Call
1220
+ (call
1221
+ method: (identifier) @call.name) @call
1222
+
1223
+ ;; Superclass
1224
+ (superclass
1225
+ (constant) @inherit.extends)
1226
+ `;
1227
+
1228
+ // src/languages/modules/ruby.ts
1229
+ var rubyModule = {
1230
+ lang: "ruby" /* Ruby */,
1231
+ fileExtensions: [".rb"],
1232
+ queries: rubyQueries,
1233
+ importStyle: "wildcard",
1234
+ inheritanceStrategy: "mixin-aware",
1235
+ resolveImport(rawPath, _fromFile, workspace) {
1236
+ const cleaned = rawPath.replace(/['"]/g, "");
1237
+ return workspace.findByPackage(cleaned + ".rb") ?? workspace.findByPackage(cleaned);
1238
+ },
1239
+ isExported(_node) {
1240
+ return true;
1241
+ },
1242
+ extractType(_node) {
1243
+ return null;
1244
+ }
1245
+ };
1246
+
1247
+ // src/parsing/queries/swift.ts
1248
+ var swiftQueries = `
1249
+ ;; Class declaration
1250
+ (class_declaration
1251
+ name: (type_identifier) @def.class.name) @def.class
1252
+
1253
+ ;; Struct declaration
1254
+ (struct_declaration
1255
+ name: (type_identifier) @def.struct.name) @def.struct
1256
+
1257
+ ;; Protocol declaration
1258
+ (protocol_declaration
1259
+ name: (type_identifier) @def.interface.name) @def.interface
1260
+
1261
+ ;; Enum declaration
1262
+ (enum_declaration
1263
+ name: (type_identifier) @def.enum.name) @def.enum
1264
+
1265
+ ;; Function declaration
1266
+ (function_declaration
1267
+ name: (simple_identifier) @def.func.name) @def.func
1268
+
1269
+ ;; Property declaration
1270
+ (property_declaration
1271
+ (pattern
1272
+ (simple_identifier) @def.property.name)) @def.property
1273
+
1274
+ ;; Import
1275
+ (import_declaration
1276
+ (identifier) @imp.source) @imp
1277
+
1278
+ ;; Call
1279
+ (call_expression
1280
+ (simple_identifier) @call.name) @call
1281
+
1282
+ ;; Inheritance
1283
+ (inheritance_specifier
1284
+ (type_identifier) @inherit.extends)
1285
+ `;
1286
+
1287
+ // src/languages/modules/swift.ts
1288
+ var swiftModule = {
1289
+ lang: "swift" /* Swift */,
1290
+ fileExtensions: [".swift"],
1291
+ queries: swiftQueries,
1292
+ importStyle: "wildcard",
1293
+ inheritanceStrategy: "depth-first",
1294
+ resolveImport(rawPath, _fromFile, workspace) {
1295
+ const cleaned = rawPath.replace(/['"]/g, "");
1296
+ return workspace.findByPackage(cleaned);
1297
+ },
1298
+ isExported(node) {
1299
+ return !node.text.includes("private") && !node.text.includes("fileprivate");
1300
+ },
1301
+ extractType(node) {
1302
+ const typeAnnotation = node.childForFieldName("type");
1303
+ return typeAnnotation?.text ?? null;
1304
+ }
1305
+ };
1306
+ var dartModule = {
1307
+ lang: "dart" /* Dart */,
1308
+ fileExtensions: [".dart"],
1309
+ queries: typescriptQueries,
1310
+ // Dart grammar fallback
1311
+ importStyle: "wildcard",
1312
+ inheritanceStrategy: "depth-first",
1313
+ resolveImport(rawPath, fromFile, workspace) {
1314
+ const cleaned = rawPath.replace(/['"]/g, "");
1315
+ if (cleaned.startsWith("package:")) {
1316
+ const pkg = cleaned.replace("package:", "");
1317
+ return workspace.findByPackage(pkg);
1318
+ }
1319
+ const fromDir = path6.dirname(fromFile);
1320
+ return workspace.resolve(fromDir, cleaned);
1321
+ },
1322
+ isExported(node) {
1323
+ const name = node.childForFieldName("name");
1324
+ if (!name) return true;
1325
+ return !name.text.startsWith("_");
1326
+ },
1327
+ extractType(node) {
1328
+ const typeNode = node.childForFieldName("type");
1329
+ return typeNode?.text ?? null;
1330
+ }
1331
+ };
1332
+
1333
+ // src/languages/registry.ts
1334
+ var MODULES = {
1335
+ ["typescript" /* TypeScript */]: typescriptModule,
1336
+ ["javascript" /* JavaScript */]: javascriptModule,
1337
+ ["python" /* Python */]: pythonModule,
1338
+ ["java" /* Java */]: javaModule,
1339
+ ["go" /* Go */]: goModule,
1340
+ ["c" /* C */]: cModule,
1341
+ ["cpp" /* Cpp */]: cppModule,
1342
+ ["csharp" /* CSharp */]: csharpModule,
1343
+ ["rust" /* Rust */]: rustModule,
1344
+ ["php" /* PHP */]: phpModule,
1345
+ ["kotlin" /* Kotlin */]: kotlinModule,
1346
+ ["ruby" /* Ruby */]: rubyModule,
1347
+ ["swift" /* Swift */]: swiftModule,
1348
+ ["dart" /* Dart */]: dartModule
1349
+ };
1350
+ function getLanguageModule(lang) {
1351
+ return MODULES[lang];
1352
+ }
1353
+ function getAllLanguageModules() {
1354
+ return Object.values(MODULES);
1355
+ }
1356
+
1357
+ // src/resolver/binding-tracker.ts
1358
+ var BindingTracker = class {
1359
+ bindings = /* @__PURE__ */ new Map();
1360
+ addBinding(filePath, binding) {
1361
+ let fileBindings = this.bindings.get(filePath);
1362
+ if (!fileBindings) {
1363
+ fileBindings = /* @__PURE__ */ new Map();
1364
+ this.bindings.set(filePath, fileBindings);
1365
+ }
1366
+ fileBindings.set(binding.localName, binding);
1367
+ }
1368
+ getBinding(filePath, localName) {
1369
+ return this.bindings.get(filePath)?.get(localName);
1370
+ }
1371
+ getFileBindings(filePath) {
1372
+ const fileBindings = this.bindings.get(filePath);
1373
+ return fileBindings ? [...fileBindings.values()] : [];
1374
+ }
1375
+ clear() {
1376
+ this.bindings.clear();
1377
+ }
1378
+ };
1379
+
1380
+ // src/resolver/import-resolver.ts
1381
+ function resolveImports(filePath, fileNodeId, imports, langModule, workspace) {
1382
+ const bindings = new BindingTracker();
1383
+ const edges = [];
1384
+ const maxReExportHops = 5;
1385
+ for (const imp of imports) {
1386
+ let resolvedPath = langModule.resolveImport(imp.rawPath, filePath, workspace);
1387
+ let hops = 0;
1388
+ const visited = /* @__PURE__ */ new Set();
1389
+ while (resolvedPath && hops < maxReExportHops && !visited.has(resolvedPath)) {
1390
+ visited.add(resolvedPath);
1391
+ hops++;
1392
+ break;
1393
+ }
1394
+ if (!resolvedPath) continue;
1395
+ const targetNodeId = `file:${resolvedPath}:${resolvedPath}`;
1396
+ const edge = {
1397
+ id: generateEdgeId(fileNodeId, targetNodeId, "imports"),
1398
+ source: fileNodeId,
1399
+ target: targetNodeId,
1400
+ kind: "imports",
1401
+ weight: 0.95,
1402
+ label: imp.rawPath
1403
+ };
1404
+ edges.push(edge);
1405
+ for (const localName of imp.localNames) {
1406
+ const binding = {
1407
+ localName,
1408
+ sourcePath: resolvedPath,
1409
+ exportedName: localName,
1410
+ isDefault: imp.isDefault,
1411
+ isNamespace: imp.isNamespace
1412
+ };
1413
+ bindings.addBinding(filePath, binding);
1414
+ }
1415
+ }
1416
+ return { edges, bindings };
1417
+ }
1418
+
1419
+ // src/call-graph/call-builder.ts
1420
+ function buildCallEdges(callSites, graph, bindings) {
1421
+ const edges = [];
1422
+ const symbolIndex = buildSymbolIndex(graph);
1423
+ const tiers = [
1424
+ {
1425
+ name: "same-file",
1426
+ confidence: 0.95,
1427
+ resolve(cs) {
1428
+ const key = `${cs.callerFilePath}:${cs.name}`;
1429
+ return symbolIndex.get(key) ?? null;
1430
+ }
1431
+ },
1432
+ {
1433
+ name: "imported",
1434
+ confidence: 0.9,
1435
+ resolve(cs) {
1436
+ const binding = bindings.getBinding(cs.callerFilePath, cs.name);
1437
+ if (!binding) return null;
1438
+ const key = `${binding.sourcePath}:${binding.exportedName}`;
1439
+ return symbolIndex.get(key) ?? null;
1440
+ }
1441
+ },
1442
+ {
1443
+ name: "global",
1444
+ confidence: 0.5,
1445
+ resolve(cs) {
1446
+ return globalSymbolIndex.get(cs.name) ?? null;
1447
+ }
1448
+ }
1449
+ ];
1450
+ const globalSymbolIndex = /* @__PURE__ */ new Map();
1451
+ for (const node of graph.allNodes()) {
1452
+ if (["function", "method", "class", "constructor"].includes(node.kind)) {
1453
+ if (!globalSymbolIndex.has(node.name)) {
1454
+ globalSymbolIndex.set(node.name, node.id);
1455
+ }
1456
+ }
1457
+ }
1458
+ for (const cs of callSites) {
1459
+ for (const tier of tiers) {
1460
+ const targetId = tier.resolve(cs);
1461
+ if (targetId && targetId !== cs.callerNodeId) {
1462
+ edges.push({
1463
+ id: generateEdgeId(cs.callerNodeId, targetId, "calls"),
1464
+ source: cs.callerNodeId,
1465
+ target: targetId,
1466
+ kind: "calls",
1467
+ weight: tier.confidence,
1468
+ label: cs.name
1469
+ });
1470
+ break;
1471
+ }
1472
+ }
1473
+ }
1474
+ return edges;
1475
+ }
1476
+ function buildSymbolIndex(graph) {
1477
+ const index = /* @__PURE__ */ new Map();
1478
+ for (const node of graph.allNodes()) {
1479
+ if (["function", "method", "class", "constructor", "variable"].includes(node.kind)) {
1480
+ const key = `${node.filePath}:${node.name}`;
1481
+ index.set(key, node.id);
1482
+ }
1483
+ }
1484
+ return index;
1485
+ }
1486
+
1487
+ // src/call-graph/call-classifier.ts
1488
+ function classifyCall(name, hasReceiver, isNew) {
1489
+ if (isNew) return "constructor";
1490
+ if (hasReceiver) return "member";
1491
+ if (name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase()) {
1492
+ return "constructor";
1493
+ }
1494
+ return "free";
1495
+ }
1496
+
1497
+ // src/inheritance/heritage-builder.ts
1498
+ function buildHeritageEdges(heritages, graph) {
1499
+ const edges = [];
1500
+ const classIndex = /* @__PURE__ */ new Map();
1501
+ for (const node of graph.allNodes()) {
1502
+ if (["class", "interface", "struct", "trait"].includes(node.kind)) {
1503
+ classIndex.set(node.name, node.id);
1504
+ }
1505
+ }
1506
+ for (const h of heritages) {
1507
+ for (const name of h.extendsNames) {
1508
+ const targetId = classIndex.get(name);
1509
+ if (targetId) {
1510
+ edges.push({
1511
+ id: generateEdgeId(h.classNodeId, targetId, "extends"),
1512
+ source: h.classNodeId,
1513
+ target: targetId,
1514
+ kind: "extends",
1515
+ weight: 1,
1516
+ label: `extends ${name}`
1517
+ });
1518
+ }
1519
+ }
1520
+ for (const name of h.implementsNames) {
1521
+ const targetId = classIndex.get(name);
1522
+ if (targetId) {
1523
+ edges.push({
1524
+ id: generateEdgeId(h.classNodeId, targetId, "implements"),
1525
+ source: h.classNodeId,
1526
+ target: targetId,
1527
+ kind: "implements",
1528
+ weight: 1,
1529
+ label: `implements ${name}`
1530
+ });
1531
+ }
1532
+ }
1533
+ }
1534
+ return edges;
1535
+ }
1536
+
1537
+ // src/inheritance/mro-walker.ts
1538
+ function computeMRO(classId, parentMap, strategy) {
1539
+ switch (strategy) {
1540
+ case "depth-first":
1541
+ return depthFirstMRO(classId, parentMap);
1542
+ case "c3":
1543
+ return c3Linearize(classId, parentMap);
1544
+ case "mixin-aware":
1545
+ return mixinAwareMRO(classId, parentMap);
1546
+ case "none":
1547
+ return [classId];
1548
+ }
1549
+ }
1550
+ function depthFirstMRO(classId, parentMap) {
1551
+ const result = [];
1552
+ const visited = /* @__PURE__ */ new Set();
1553
+ const stack = [classId];
1554
+ while (stack.length > 0) {
1555
+ const current = stack.pop();
1556
+ if (visited.has(current)) continue;
1557
+ visited.add(current);
1558
+ result.push(current);
1559
+ const parents = parentMap.get(current) ?? [];
1560
+ for (let i = parents.length - 1; i >= 0; i--) {
1561
+ stack.push(parents[i]);
1562
+ }
1563
+ }
1564
+ return result;
1565
+ }
1566
+ function c3Linearize(classId, parentMap) {
1567
+ const cache = /* @__PURE__ */ new Map();
1568
+ const inProgress = /* @__PURE__ */ new Set();
1569
+ function linearize(cls) {
1570
+ if (cache.has(cls)) return cache.get(cls);
1571
+ if (inProgress.has(cls)) return [cls];
1572
+ inProgress.add(cls);
1573
+ const parents = parentMap.get(cls) ?? [];
1574
+ if (parents.length === 0) {
1575
+ const result2 = [cls];
1576
+ cache.set(cls, result2);
1577
+ inProgress.delete(cls);
1578
+ return result2;
1579
+ }
1580
+ const parentLinearizations = parents.map((p) => linearize(p));
1581
+ const sequences = [...parentLinearizations, parents];
1582
+ const result = [cls];
1583
+ while (sequences.some((s) => s.length > 0)) {
1584
+ let found = false;
1585
+ for (const seq of sequences) {
1586
+ if (seq.length === 0) continue;
1587
+ const head = seq[0];
1588
+ const inTail = sequences.some((s) => s.indexOf(head) > 0);
1589
+ if (!inTail) {
1590
+ result.push(head);
1591
+ for (const s of sequences) {
1592
+ const idx = s.indexOf(head);
1593
+ if (idx >= 0) s.splice(idx, 1);
1594
+ }
1595
+ found = true;
1596
+ break;
1597
+ }
1598
+ }
1599
+ if (!found) break;
1600
+ }
1601
+ cache.set(cls, result);
1602
+ inProgress.delete(cls);
1603
+ return result;
1604
+ }
1605
+ return linearize(classId);
1606
+ }
1607
+ function mixinAwareMRO(classId, parentMap) {
1608
+ return depthFirstMRO(classId, parentMap);
1609
+ }
1610
+
1611
+ // src/inheritance/override-detector.ts
1612
+ function detectOverrides(graph) {
1613
+ const edges = [];
1614
+ const methodsByOwner = /* @__PURE__ */ new Map();
1615
+ for (const edge of graph.findEdgesByKind("has_member")) {
1616
+ const member = graph.getNode(edge.target);
1617
+ if (member && member.kind === "method") {
1618
+ let methods = methodsByOwner.get(edge.source);
1619
+ if (!methods) {
1620
+ methods = /* @__PURE__ */ new Map();
1621
+ methodsByOwner.set(edge.source, methods);
1622
+ }
1623
+ methods.set(member.name, member.id);
1624
+ }
1625
+ }
1626
+ for (const extendsEdge of graph.findEdgesByKind("extends")) {
1627
+ const childMethods = methodsByOwner.get(extendsEdge.source);
1628
+ const parentMethods = methodsByOwner.get(extendsEdge.target);
1629
+ if (!childMethods || !parentMethods) continue;
1630
+ for (const [methodName, childMethodId] of childMethods) {
1631
+ const parentMethodId = parentMethods.get(methodName);
1632
+ if (parentMethodId) {
1633
+ edges.push({
1634
+ id: generateEdgeId(childMethodId, parentMethodId, "overrides"),
1635
+ source: childMethodId,
1636
+ target: parentMethodId,
1637
+ kind: "overrides",
1638
+ weight: 1,
1639
+ label: `overrides ${methodName}`
1640
+ });
1641
+ }
1642
+ }
1643
+ }
1644
+ return edges;
1645
+ }
1646
+
1647
+ // src/pipeline/dag-validator.ts
1648
+ function validateDAG(phases) {
1649
+ const errors = [];
1650
+ const names = /* @__PURE__ */ new Set();
1651
+ for (const phase of phases) {
1652
+ if (names.has(phase.name)) {
1653
+ errors.push({ type: "duplicate", message: `Duplicate phase name: ${phase.name}` });
1654
+ }
1655
+ names.add(phase.name);
1656
+ }
1657
+ for (const phase of phases) {
1658
+ for (const dep of phase.dependencies) {
1659
+ if (!names.has(dep)) {
1660
+ errors.push({
1661
+ type: "missing-dep",
1662
+ message: `Phase "${phase.name}" depends on missing phase "${dep}"`
1663
+ });
1664
+ }
1665
+ }
1666
+ }
1667
+ const visiting = /* @__PURE__ */ new Set();
1668
+ const visited = /* @__PURE__ */ new Set();
1669
+ const phaseMap = new Map(phases.map((p) => [p.name, p]));
1670
+ function dfs(name, path19) {
1671
+ if (visiting.has(name)) {
1672
+ const cycleStart = path19.indexOf(name);
1673
+ const cycle = path19.slice(cycleStart).concat(name);
1674
+ errors.push({ type: "cycle", message: `Cycle detected: ${cycle.join(" \u2192 ")}` });
1675
+ return true;
1676
+ }
1677
+ if (visited.has(name)) return false;
1678
+ visiting.add(name);
1679
+ path19.push(name);
1680
+ const phase = phaseMap.get(name);
1681
+ if (phase) {
1682
+ for (const dep of phase.dependencies) {
1683
+ if (dfs(dep, path19)) return true;
1684
+ }
1685
+ }
1686
+ visiting.delete(name);
1687
+ visited.add(name);
1688
+ path19.pop();
1689
+ return false;
1690
+ }
1691
+ for (const phase of phases) {
1692
+ if (!visited.has(phase.name)) {
1693
+ dfs(phase.name, []);
1694
+ }
1695
+ }
1696
+ return errors;
1697
+ }
1698
+ function topologicalSort(phases) {
1699
+ const phaseMap = new Map(phases.map((p) => [p.name, p]));
1700
+ const inDegree = /* @__PURE__ */ new Map();
1701
+ const adjList = /* @__PURE__ */ new Map();
1702
+ for (const phase of phases) {
1703
+ inDegree.set(phase.name, 0);
1704
+ adjList.set(phase.name, []);
1705
+ }
1706
+ for (const phase of phases) {
1707
+ for (const dep of phase.dependencies) {
1708
+ adjList.get(dep)?.push(phase.name);
1709
+ inDegree.set(phase.name, (inDegree.get(phase.name) ?? 0) + 1);
1710
+ }
1711
+ }
1712
+ const queue = [];
1713
+ for (const [name, degree] of inDegree) {
1714
+ if (degree === 0) queue.push(name);
1715
+ }
1716
+ const sorted = [];
1717
+ while (queue.length > 0) {
1718
+ const current = queue.shift();
1719
+ sorted.push(phaseMap.get(current));
1720
+ for (const neighbor of adjList.get(current) ?? []) {
1721
+ const newDegree = (inDegree.get(neighbor) ?? 1) - 1;
1722
+ inDegree.set(neighbor, newDegree);
1723
+ if (newDegree === 0) queue.push(neighbor);
1724
+ }
1725
+ }
1726
+ return sorted;
1727
+ }
1728
+
1729
+ // src/pipeline/orchestrator.ts
1730
+ async function runPipeline(phases, context) {
1731
+ const errors = validateDAG(phases);
1732
+ if (errors.length > 0) {
1733
+ throw new Error(`Pipeline validation failed:
1734
+ ${errors.map((e) => e.message).join("\n")}`);
1735
+ }
1736
+ const sorted = topologicalSort(phases);
1737
+ const results = /* @__PURE__ */ new Map();
1738
+ const startTime = Date.now();
1739
+ let success = true;
1740
+ for (const phase of sorted) {
1741
+ context.onProgress?.(phase.name, "running");
1742
+ const phaseStart = Date.now();
1743
+ try {
1744
+ const depResults = /* @__PURE__ */ new Map();
1745
+ for (const dep of phase.dependencies) {
1746
+ const depResult = results.get(dep);
1747
+ if (depResult) depResults.set(dep, depResult);
1748
+ }
1749
+ const result = await phase.execute(context, depResults);
1750
+ results.set(phase.name, result);
1751
+ context.onProgress?.(phase.name, result.status);
1752
+ if (result.status === "failed") {
1753
+ success = false;
1754
+ break;
1755
+ }
1756
+ } catch (err) {
1757
+ const result = {
1758
+ status: "failed",
1759
+ duration: Date.now() - phaseStart,
1760
+ message: err instanceof Error ? err.message : String(err)
1761
+ };
1762
+ results.set(phase.name, result);
1763
+ context.onProgress?.(phase.name, "failed");
1764
+ success = false;
1765
+ break;
1766
+ }
1767
+ }
1768
+ return {
1769
+ success,
1770
+ results,
1771
+ totalDuration: Date.now() - startTime
1772
+ };
1773
+ }
1774
+ var IGNORED_DIRS = /* @__PURE__ */ new Set([
1775
+ "node_modules",
1776
+ ".git",
1777
+ ".svn",
1778
+ ".hg",
1779
+ "dist",
1780
+ "dist-tests",
1781
+ "build",
1782
+ "out",
1783
+ "__pycache__",
1784
+ ".tox",
1785
+ ".pytest_cache",
1786
+ ".mypy_cache",
1787
+ "vendor",
1788
+ "target",
1789
+ ".code-intel",
1790
+ "coverage",
1791
+ ".next",
1792
+ ".turbo",
1793
+ ".cache",
1794
+ "tmp",
1795
+ "temp",
1796
+ ".parcel-cache",
1797
+ ".venv",
1798
+ "venv",
1799
+ ".env",
1800
+ "env",
1801
+ "__snapshots__",
1802
+ ".nyc_output",
1803
+ "storybook-static"
1804
+ ]);
1805
+ function loadIgnorePatterns(workspaceRoot) {
1806
+ try {
1807
+ const raw = fs6.readFileSync(path6.join(workspaceRoot, ".codeintelignore"), "utf-8");
1808
+ const extras = /* @__PURE__ */ new Set();
1809
+ for (const line of raw.split("\n")) {
1810
+ const trimmed = line.trim();
1811
+ if (trimmed && !trimmed.startsWith("#")) extras.add(trimmed);
1812
+ }
1813
+ return extras;
1814
+ } catch {
1815
+ return /* @__PURE__ */ new Set();
1816
+ }
1817
+ }
1818
+ var IGNORED_FILE_SUFFIXES = [".d.ts", ".js.map", ".d.ts.map", ".min.js", ".min.css"];
1819
+ var MAX_FILE_SIZE_BYTES = 512 * 1024;
1820
+ var scanPhase = {
1821
+ name: "scan",
1822
+ dependencies: [],
1823
+ async execute(context) {
1824
+ const start = Date.now();
1825
+ const extensions = new Set(getSupportedExtensions());
1826
+ const filePaths = [];
1827
+ const extraIgnore = loadIgnorePatterns(context.workspaceRoot);
1828
+ function walk(dir) {
1829
+ let entries;
1830
+ try {
1831
+ entries = fs6.readdirSync(dir, { withFileTypes: true });
1832
+ } catch {
1833
+ return;
1834
+ }
1835
+ for (const entry of entries) {
1836
+ if (entry.isDirectory()) {
1837
+ if (entry.name.startsWith(".")) continue;
1838
+ if (IGNORED_DIRS.has(entry.name)) continue;
1839
+ if (extraIgnore.has(entry.name)) continue;
1840
+ walk(path6.join(dir, entry.name));
1841
+ } else if (entry.isFile()) {
1842
+ const name = entry.name;
1843
+ if (IGNORED_FILE_SUFFIXES.some((s) => name.endsWith(s))) continue;
1844
+ const ext = path6.extname(name);
1845
+ if (!extensions.has(ext)) continue;
1846
+ const fullPath = path6.join(dir, name);
1847
+ try {
1848
+ const stat = fs6.statSync(fullPath);
1849
+ if (stat.size > MAX_FILE_SIZE_BYTES) continue;
1850
+ } catch {
1851
+ continue;
1852
+ }
1853
+ filePaths.push(fullPath);
1854
+ }
1855
+ }
1856
+ }
1857
+ walk(context.workspaceRoot);
1858
+ context.filePaths.push(...filePaths);
1859
+ context.onPhaseProgress?.("scan", filePaths.length, filePaths.length);
1860
+ return {
1861
+ status: "completed",
1862
+ duration: Date.now() - start,
1863
+ message: `Found ${filePaths.length} source files`
1864
+ };
1865
+ }
1866
+ };
1867
+ var structurePhase = {
1868
+ name: "structure",
1869
+ dependencies: ["scan"],
1870
+ async execute(context) {
1871
+ const start = Date.now();
1872
+ const dirs = /* @__PURE__ */ new Set();
1873
+ let structDone = 0;
1874
+ for (const filePath of context.filePaths) {
1875
+ const relativePath = path6.relative(context.workspaceRoot, filePath);
1876
+ const lang = detectLanguage(filePath);
1877
+ context.graph.addNode({
1878
+ id: generateNodeId("file", relativePath, relativePath),
1879
+ kind: "file",
1880
+ name: path6.basename(filePath),
1881
+ filePath: relativePath,
1882
+ metadata: lang ? { language: lang } : void 0
1883
+ });
1884
+ let dir = path6.dirname(relativePath);
1885
+ while (dir && dir !== "." && dir !== "") {
1886
+ if (dirs.has(dir)) break;
1887
+ dirs.add(dir);
1888
+ dir = path6.dirname(dir);
1889
+ }
1890
+ structDone++;
1891
+ context.onPhaseProgress?.("structure", structDone, context.filePaths.length);
1892
+ }
1893
+ for (const dir of dirs) {
1894
+ context.graph.addNode({
1895
+ id: generateNodeId("directory", dir, dir),
1896
+ kind: "directory",
1897
+ name: path6.basename(dir),
1898
+ filePath: dir
1899
+ });
1900
+ }
1901
+ return {
1902
+ status: "completed",
1903
+ duration: Date.now() - start,
1904
+ message: `Created ${context.filePaths.length} file nodes, ${dirs.size} directory nodes`
1905
+ };
1906
+ }
1907
+ };
1908
+ var SENSITIVE_KEYS = [
1909
+ "password",
1910
+ "passwd",
1911
+ "pass",
1912
+ "pwd",
1913
+ "secret",
1914
+ "secretkey",
1915
+ "secret_key",
1916
+ "secretaccesskey",
1917
+ "accesskeyid",
1918
+ "credentials",
1919
+ "auth",
1920
+ "authentication",
1921
+ "login",
1922
+ "api_key",
1923
+ "apikey",
1924
+ "api",
1925
+ "access_key",
1926
+ "access_token",
1927
+ "accesskey",
1928
+ "auth_key",
1929
+ "auth_token",
1930
+ "authkey",
1931
+ "token",
1932
+ "jwt",
1933
+ "bearer_token",
1934
+ "refresh_token",
1935
+ "session_token",
1936
+ "session_key",
1937
+ "oauth_token",
1938
+ "connection_string",
1939
+ "conn_string",
1940
+ "db_uri",
1941
+ "db_url",
1942
+ "database_url",
1943
+ "mongodb_uri",
1944
+ "mysql_uri",
1945
+ "postgres_uri",
1946
+ "sql_uri",
1947
+ "db_username",
1948
+ "db_password",
1949
+ "db_host",
1950
+ "db_port",
1951
+ "db_name",
1952
+ "encryption_key",
1953
+ "crypto_key",
1954
+ "private_key",
1955
+ "public_key",
1956
+ "ssl_key",
1957
+ "ssh_key",
1958
+ "pgp_key",
1959
+ "rsa_key",
1960
+ "aes_key",
1961
+ "email",
1962
+ "phone",
1963
+ "telephone",
1964
+ "mobile",
1965
+ "ssn",
1966
+ "social_security",
1967
+ "credit_card",
1968
+ "cc_number",
1969
+ "card_number",
1970
+ "cvv",
1971
+ "expiry_date",
1972
+ "birth_date",
1973
+ "dob",
1974
+ "address",
1975
+ "zip_code",
1976
+ "postal_code",
1977
+ "bank_account",
1978
+ "iban",
1979
+ "swift_code",
1980
+ "routing_number",
1981
+ "tax_id",
1982
+ "vat_number",
1983
+ "financial_id",
1984
+ "certificate",
1985
+ "client_cert",
1986
+ "server_cert",
1987
+ "ca_cert",
1988
+ "aws_key",
1989
+ "aws_secret",
1990
+ "azure_key",
1991
+ "gcp_key",
1992
+ "s3_key",
1993
+ "cloudinary_key",
1994
+ "stripe_key",
1995
+ "paypal_key",
1996
+ "twilio_key",
1997
+ "app_secret",
1998
+ "client_secret",
1999
+ "consumer_secret",
2000
+ "encryption_secret",
2001
+ "master_key",
2002
+ "root_password",
2003
+ "admin_password",
2004
+ "config_secret",
2005
+ "env_secret",
2006
+ "deploy_key",
2007
+ "ci_key",
2008
+ "session_id",
2009
+ "cookie_secret",
2010
+ "csrf_token",
2011
+ "xsrf_token",
2012
+ "license_key",
2013
+ "product_key",
2014
+ "serial_number",
2015
+ "activation_code"
2016
+ ];
2017
+ var SENSITIVE_PATTERNS = [
2018
+ /(?:password|passwd|secret|api_key|access_token|auth_token|token)\s*[:=]\s*([^\s,]+)/gi,
2019
+ /\b\d{16}\b/gi,
2020
+ /\b\d{3}-\d{2}-\d{4}\b/gi,
2021
+ /\b[A-Za-z0-9]{32}\b/gi,
2022
+ /\b[A-Za-z0-9_-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b/gi,
2023
+ /\b\d{10}\b/gi,
2024
+ /\b[A-Za-z0-9]{64}\b/gi,
2025
+ /(?:connection_string|db_uri|db_url|mongodb_uri)\s*[:=]\s*([^\s,]+)/gi,
2026
+ /(?:apikey|api_key|auth_key)\s*[:=]\s*([^\s,]+)/gi,
2027
+ /(?:bearer\s+)[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+/gi
2028
+ ];
2029
+ var SENSITIVE_KEYS_REGEX = new RegExp(`^(${SENSITIVE_KEYS.join("|")})$`, "i");
2030
+ var Logger = class _Logger {
2031
+ static instance = null;
2032
+ static maskSensitiveData(value) {
2033
+ if (typeof value === "string" && value.length > 5) {
2034
+ const firstChar = value.at(0);
2035
+ const lastChar = value.at(-1);
2036
+ return firstChar + "*".repeat(value.length - 2) + lastChar;
2037
+ }
2038
+ return value;
2039
+ }
2040
+ static maskSensitive(message, args = []) {
2041
+ const maskString = (input) => {
2042
+ if (typeof input !== "string") return input;
2043
+ return SENSITIVE_PATTERNS.reduce((str, pattern) => {
2044
+ return str.replace(
2045
+ pattern,
2046
+ (match, value) => value ? match.replace(value, _Logger.maskSensitiveData(value)) : match
2047
+ );
2048
+ }, input);
2049
+ };
2050
+ const deepMask = (obj) => {
2051
+ if (typeof obj === "string") return maskString(obj);
2052
+ if (Array.isArray(obj)) return obj.map((item) => deepMask(item));
2053
+ if (typeof obj === "object" && obj !== null) {
2054
+ return Object.entries(obj).reduce(
2055
+ (acc, [key, value]) => {
2056
+ if (value === void 0) return acc;
2057
+ const isSensitiveKey = SENSITIVE_KEYS_REGEX.test(key);
2058
+ acc[key] = isSensitiveKey && typeof value === "string" ? _Logger.maskSensitiveData(value) : deepMask(value);
2059
+ return acc;
2060
+ },
2061
+ {}
2062
+ );
2063
+ }
2064
+ return obj;
2065
+ };
2066
+ return {
2067
+ maskedMessage: maskString(message),
2068
+ maskedArgs: args.map((arg) => deepMask(arg))
2069
+ };
2070
+ }
2071
+ /** Global log directory: ~/.code-intel/logs */
2072
+ static LOG_DIR = path6.join(os3.homedir(), ".code-intel", "logs");
2073
+ static getLogger() {
2074
+ if (!_Logger.instance) {
2075
+ const isProduction = process.env.NODE_ENV === "production";
2076
+ const logLevel = process.env.LOG_LEVEL ?? "info";
2077
+ const transports = [];
2078
+ transports.push(new winston.transports.Console());
2079
+ if (!isProduction) {
2080
+ try {
2081
+ if (!fs6.existsSync(_Logger.LOG_DIR)) {
2082
+ fs6.mkdirSync(_Logger.LOG_DIR, { recursive: true });
2083
+ }
2084
+ transports.push(
2085
+ new DailyRotateFile({
2086
+ filename: path6.join(_Logger.LOG_DIR, "%DATE%-code-intel.log"),
2087
+ datePattern: "YYYY-MM-DD",
2088
+ maxSize: "20m",
2089
+ maxFiles: "14d"
2090
+ })
2091
+ );
2092
+ } catch {
2093
+ }
2094
+ }
2095
+ _Logger.instance = winston.createLogger({
2096
+ level: logLevel,
2097
+ format: winston.format.combine(
2098
+ winston.format.timestamp(),
2099
+ winston.format.printf(({ timestamp, level, message, ...meta }) => {
2100
+ const args = meta[/* @__PURE__ */ Symbol.for("splat")] || [];
2101
+ const { maskedMessage, maskedArgs } = _Logger.maskSensitive(message, args);
2102
+ const formattedArgs = maskedArgs.map(
2103
+ (arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg)
2104
+ );
2105
+ const suffix = formattedArgs.length ? " " + formattedArgs.join(" ") : "";
2106
+ return `${timestamp} [${level.toUpperCase()}]: ${maskedMessage}${suffix}`;
2107
+ })
2108
+ ),
2109
+ transports
2110
+ });
2111
+ }
2112
+ return _Logger.instance;
2113
+ }
2114
+ static info(message, ...args) {
2115
+ _Logger.getLogger().info(message, ...args);
2116
+ }
2117
+ static warn(message, ...args) {
2118
+ _Logger.getLogger().warn(message, ...args);
2119
+ }
2120
+ static error(message, ...args) {
2121
+ _Logger.getLogger().error(message, ...args);
2122
+ }
2123
+ static debug(message, ...args) {
2124
+ _Logger.getLogger().debug(message, ...args);
2125
+ }
2126
+ };
2127
+ var logger_default = Logger;
2128
+ Logger.getLogger();
2129
+
2130
+ // src/pipeline/phases/parse-phase.ts
2131
+ var parsePhase = {
2132
+ name: "parse",
2133
+ dependencies: ["structure"],
2134
+ async execute(context) {
2135
+ const start = Date.now();
2136
+ let symbolCount = 0;
2137
+ if (!context.fileCache) context.fileCache = /* @__PURE__ */ new Map();
2138
+ if (!context.fileFunctionIndex) context.fileFunctionIndex = /* @__PURE__ */ new Map();
2139
+ const CONCURRENCY = 64;
2140
+ const filePaths = context.filePaths;
2141
+ let readDone = 0;
2142
+ for (let i = 0; i < filePaths.length; i += CONCURRENCY) {
2143
+ const batch = filePaths.slice(i, i + CONCURRENCY);
2144
+ await Promise.all(batch.map(async (filePath) => {
2145
+ try {
2146
+ const source = await fs6.promises.readFile(filePath, "utf-8");
2147
+ context.fileCache.set(filePath, source);
2148
+ } catch {
2149
+ }
2150
+ }));
2151
+ readDone += batch.length;
2152
+ context.onPhaseProgress?.("parse:read", readDone, filePaths.length);
2153
+ }
2154
+ let parseDone = 0;
2155
+ for (const filePath of filePaths) {
2156
+ const lang = detectLanguage(filePath);
2157
+ if (!lang) {
2158
+ if (context.verbose) {
2159
+ const relativePath2 = path6.relative(context.workspaceRoot, filePath);
2160
+ logger_default.info(` [parse] skipped (no parser): ${relativePath2}`);
2161
+ }
2162
+ continue;
2163
+ }
2164
+ const source = context.fileCache.get(filePath);
2165
+ if (!source) continue;
2166
+ const relativePath = path6.relative(context.workspaceRoot, filePath);
2167
+ const fileNodeId = generateNodeId("file", relativePath, relativePath);
2168
+ const fileNode = context.graph.getNode(fileNodeId);
2169
+ if (fileNode) {
2170
+ fileNode.content = source.slice(0, 2e3);
2171
+ }
2172
+ const nodes = [];
2173
+ const edges = [];
2174
+ const seen = /* @__PURE__ */ new Set();
2175
+ const lines = source.split("\n");
2176
+ for (let i = 0; i < lines.length; i++) {
2177
+ const line = lines[i];
2178
+ const trimmed = line.trim();
2179
+ if (trimmed.startsWith("//") || trimmed.startsWith("#") || trimmed.startsWith("*") || trimmed.startsWith("/*")) continue;
2180
+ const extracted = extractSymbol(trimmed, lang);
2181
+ if (!extracted) continue;
2182
+ const dedupeKey = extracted.name + ":" + extracted.kind;
2183
+ if (seen.has(dedupeKey)) continue;
2184
+ seen.add(dedupeKey);
2185
+ const nodeId = generateNodeId(extracted.kind, relativePath, extracted.name);
2186
+ const endLine = estimateEndLine(lines, i, lang);
2187
+ nodes.push({
2188
+ id: nodeId,
2189
+ kind: extracted.kind,
2190
+ name: extracted.name,
2191
+ filePath: relativePath,
2192
+ startLine: i + 1,
2193
+ endLine,
2194
+ exported: extracted.exported,
2195
+ content: extractBlock(lines, i, 20)
2196
+ });
2197
+ edges.push({
2198
+ id: generateEdgeId(fileNodeId, nodeId, "contains"),
2199
+ source: fileNodeId,
2200
+ target: nodeId,
2201
+ kind: "contains",
2202
+ weight: 1
2203
+ });
2204
+ if (extracted.ownerName) {
2205
+ const ownerId = generateNodeId("class", relativePath, extracted.ownerName);
2206
+ if (context.graph.getNode(ownerId) || nodes.some((n) => n.id === ownerId)) {
2207
+ edges.push({
2208
+ id: generateEdgeId(ownerId, nodeId, "has_member"),
2209
+ source: ownerId,
2210
+ target: nodeId,
2211
+ kind: "has_member",
2212
+ weight: 1
2213
+ });
2214
+ }
2215
+ }
2216
+ symbolCount++;
2217
+ }
2218
+ for (const n of nodes) context.graph.addNode(n);
2219
+ for (const e of edges) context.graph.addEdge(e);
2220
+ const funcs = nodes.filter((n) => n.kind === "function" || n.kind === "method").map((n) => ({ id: n.id, startLine: n.startLine ?? 0, endLine: n.endLine })).sort((a, b) => a.startLine - b.startLine);
2221
+ if (funcs.length > 0) {
2222
+ context.fileFunctionIndex.set(relativePath, funcs);
2223
+ }
2224
+ parseDone++;
2225
+ context.onPhaseProgress?.("parse", parseDone, filePaths.length);
2226
+ }
2227
+ return {
2228
+ status: "completed",
2229
+ duration: Date.now() - start,
2230
+ message: `Extracted ${symbolCount} symbols from ${filePaths.length} files`
2231
+ };
2232
+ }
2233
+ };
2234
+ function extractSymbol(line, lang, _lineNum, _filePath) {
2235
+ if (lang === "typescript" /* TypeScript */ || lang === "javascript" /* JavaScript */) {
2236
+ const func = line.match(/^(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s+(\w+)/);
2237
+ if (func) return { kind: "function", name: func[1], exported: line.includes("export") };
2238
+ const arrowFunc = line.match(/^(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(/);
2239
+ if (arrowFunc) return { kind: "function", name: arrowFunc[1], exported: line.includes("export") };
2240
+ const arrowFunc2 = line.match(/^(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?(?:\([^)]*\)|[a-zA-Z_]\w*)\s*=>/);
2241
+ if (arrowFunc2) return { kind: "function", name: arrowFunc2[1], exported: line.includes("export") };
2242
+ const cls = line.match(/^(?:export\s+)?(?:default\s+)?(?:abstract\s+)?class\s+(\w+)/);
2243
+ if (cls) return { kind: "class", name: cls[1], exported: line.includes("export") };
2244
+ const iface = line.match(/^(?:export\s+)?interface\s+(\w+)/);
2245
+ if (iface) return { kind: "interface", name: iface[1], exported: line.includes("export") };
2246
+ const enumM = line.match(/^(?:export\s+)?enum\s+(\w+)/);
2247
+ if (enumM) return { kind: "enum", name: enumM[1], exported: line.includes("export") };
2248
+ const typeAlias = line.match(/^(?:export\s+)?type\s+(\w+)\s*[=<]/);
2249
+ if (typeAlias) return { kind: "type_alias", name: typeAlias[1], exported: line.includes("export") };
2250
+ const constVar = line.match(/^(?:export\s+)?const\s+(\w+)\s*(?::\s*\w[^=]*)?\s*=/);
2251
+ if (constVar && /^[A-Z_]+$/.test(constVar[1])) {
2252
+ return { kind: "constant", name: constVar[1], exported: line.includes("export") };
2253
+ }
2254
+ }
2255
+ if (lang === "python" /* Python */) {
2256
+ const func = line.match(/^(?:async\s+)?def\s+(\w+)/);
2257
+ if (func) return { kind: func[1].startsWith("__") ? "method" : "function", name: func[1], exported: !func[1].startsWith("_") };
2258
+ const cls = line.match(/^class\s+(\w+)/);
2259
+ if (cls) return { kind: "class", name: cls[1], exported: !cls[1].startsWith("_") };
2260
+ }
2261
+ if (lang === "java" /* Java */) {
2262
+ const cls = line.match(/(?:public|private|protected)?\s*(?:static\s+)?(?:abstract\s+)?(?:final\s+)?class\s+(\w+)/);
2263
+ if (cls) return { kind: "class", name: cls[1], exported: line.includes("public") };
2264
+ const iface = line.match(/(?:public\s+)?interface\s+(\w+)/);
2265
+ if (iface) return { kind: "interface", name: iface[1], exported: line.includes("public") };
2266
+ const enumM = line.match(/(?:public\s+)?enum\s+(\w+)/);
2267
+ if (enumM) return { kind: "enum", name: enumM[1], exported: line.includes("public") };
2268
+ const method = line.match(/(?:public|private|protected)\s+(?:static\s+)?(?:[\w<>\[\]]+)\s+(\w+)\s*\(/);
2269
+ if (method) return { kind: "method", name: method[1], exported: line.includes("public") };
2270
+ }
2271
+ if (lang === "go" /* Go */) {
2272
+ const func = line.match(/^func\s+(\w+)\s*\(/);
2273
+ if (func) return { kind: "function", name: func[1], exported: func[1][0] === func[1][0].toUpperCase() };
2274
+ const method = line.match(/^func\s+\([^)]+\)\s+(\w+)\s*\(/);
2275
+ if (method) return { kind: "method", name: method[1], exported: method[1][0] === method[1][0].toUpperCase() };
2276
+ const structM = line.match(/^type\s+(\w+)\s+struct\b/);
2277
+ if (structM) return { kind: "struct", name: structM[1], exported: structM[1][0] === structM[1][0].toUpperCase() };
2278
+ const ifaceM = line.match(/^type\s+(\w+)\s+interface\b/);
2279
+ if (ifaceM) return { kind: "interface", name: ifaceM[1], exported: ifaceM[1][0] === ifaceM[1][0].toUpperCase() };
2280
+ }
2281
+ if (lang === "rust" /* Rust */) {
2282
+ const func = line.match(/^(?:pub\s+)?(?:async\s+)?fn\s+(\w+)/);
2283
+ if (func) return { kind: "function", name: func[1], exported: line.startsWith("pub") };
2284
+ const structM = line.match(/^(?:pub\s+)?struct\s+(\w+)/);
2285
+ if (structM) return { kind: "struct", name: structM[1], exported: line.startsWith("pub") };
2286
+ const enumM = line.match(/^(?:pub\s+)?enum\s+(\w+)/);
2287
+ if (enumM) return { kind: "enum", name: enumM[1], exported: line.startsWith("pub") };
2288
+ const traitM = line.match(/^(?:pub\s+)?trait\s+(\w+)/);
2289
+ if (traitM) return { kind: "trait", name: traitM[1], exported: line.startsWith("pub") };
2290
+ const implM = line.match(/^impl(?:<[^>]*>)?\s+(\w+)/);
2291
+ if (implM) return { kind: "class", name: implM[1], exported: false };
2292
+ }
2293
+ if (lang === "c" /* C */ || lang === "cpp" /* Cpp */) {
2294
+ const cls = line.match(/^(?:class|struct)\s+(\w+)/);
2295
+ if (cls) return { kind: lang === "cpp" /* Cpp */ ? "class" : "struct", name: cls[1], exported: true };
2296
+ const nsM = line.match(/^namespace\s+(\w+)/);
2297
+ if (nsM) return { kind: "namespace", name: nsM[1], exported: true };
2298
+ const func = line.match(/^(?:[\w:*&<>\[\]]+\s+)+(\w+)\s*\([^;]*$/);
2299
+ if (func && !["if", "for", "while", "switch", "return"].includes(func[1])) {
2300
+ return { kind: "function", name: func[1], exported: true };
2301
+ }
2302
+ }
2303
+ if (lang === "csharp" /* CSharp */) {
2304
+ const cls = line.match(/(?:public|internal|private)?\s*(?:static\s+)?(?:abstract\s+)?(?:partial\s+)?class\s+(\w+)/);
2305
+ if (cls) return { kind: "class", name: cls[1], exported: line.includes("public") };
2306
+ const iface = line.match(/(?:public\s+)?interface\s+(\w+)/);
2307
+ if (iface) return { kind: "interface", name: iface[1], exported: line.includes("public") };
2308
+ const structM = line.match(/(?:public\s+)?struct\s+(\w+)/);
2309
+ if (structM) return { kind: "struct", name: structM[1], exported: line.includes("public") };
2310
+ const method = line.match(/(?:public|private|protected|internal)\s+(?:static\s+)?(?:async\s+)?(?:[\w<>\[\]?]+)\s+(\w+)\s*\(/);
2311
+ if (method) return { kind: "method", name: method[1], exported: line.includes("public") };
2312
+ const nsM = line.match(/namespace\s+([\w.]+)/);
2313
+ if (nsM) return { kind: "namespace", name: nsM[1], exported: true };
2314
+ }
2315
+ if (lang === "php" /* PHP */) {
2316
+ const cls = line.match(/(?:abstract\s+)?class\s+(\w+)/);
2317
+ if (cls) return { kind: "class", name: cls[1], exported: true };
2318
+ const func = line.match(/(?:public|private|protected|static\s+)*function\s+(\w+)/);
2319
+ if (func) return { kind: "function", name: func[1], exported: line.includes("public") || !line.includes("private") };
2320
+ const iface = line.match(/interface\s+(\w+)/);
2321
+ if (iface) return { kind: "interface", name: iface[1], exported: true };
2322
+ const traitM = line.match(/trait\s+(\w+)/);
2323
+ if (traitM) return { kind: "trait", name: traitM[1], exported: true };
2324
+ }
2325
+ if (lang === "kotlin" /* Kotlin */) {
2326
+ const cls = line.match(/(?:data\s+|sealed\s+|abstract\s+|open\s+)?class\s+(\w+)/);
2327
+ if (cls) return { kind: "class", name: cls[1], exported: !line.includes("private") };
2328
+ const iface = line.match(/interface\s+(\w+)/);
2329
+ if (iface) return { kind: "interface", name: iface[1], exported: !line.includes("private") };
2330
+ const func = line.match(/(?:suspend\s+)?fun\s+(\w+)/);
2331
+ if (func) return { kind: "function", name: func[1], exported: !line.includes("private") };
2332
+ const obj = line.match(/object\s+(\w+)/);
2333
+ if (obj) return { kind: "class", name: obj[1], exported: !line.includes("private") };
2334
+ }
2335
+ if (lang === "ruby" /* Ruby */) {
2336
+ const cls = line.match(/^class\s+(\w+)/);
2337
+ if (cls) return { kind: "class", name: cls[1], exported: true };
2338
+ const modM = line.match(/^module\s+(\w+)/);
2339
+ if (modM) return { kind: "module", name: modM[1], exported: true };
2340
+ const method = line.match(/^(?:def\s+(?:self\.)?(\w+))/);
2341
+ if (method) return { kind: "method", name: method[1], exported: true };
2342
+ }
2343
+ if (lang === "swift" /* Swift */) {
2344
+ const cls = line.match(/(?:public\s+|open\s+)?(?:final\s+)?class\s+(\w+)/);
2345
+ if (cls) return { kind: "class", name: cls[1], exported: !line.includes("private") };
2346
+ const structM = line.match(/(?:public\s+)?struct\s+(\w+)/);
2347
+ if (structM) return { kind: "struct", name: structM[1], exported: !line.includes("private") };
2348
+ const proto = line.match(/(?:public\s+)?protocol\s+(\w+)/);
2349
+ if (proto) return { kind: "interface", name: proto[1], exported: !line.includes("private") };
2350
+ const enumM = line.match(/(?:public\s+)?enum\s+(\w+)/);
2351
+ if (enumM) return { kind: "enum", name: enumM[1], exported: !line.includes("private") };
2352
+ const func = line.match(/(?:public\s+|private\s+|internal\s+)?(?:static\s+)?func\s+(\w+)/);
2353
+ if (func) return { kind: "function", name: func[1], exported: !line.includes("private") };
2354
+ }
2355
+ if (lang === "dart" /* Dart */) {
2356
+ const cls = line.match(/(?:abstract\s+)?class\s+(\w+)/);
2357
+ if (cls) return { kind: "class", name: cls[1], exported: !cls[1].startsWith("_") };
2358
+ const func = line.match(/^(?:\w+\s+)?(\w+)\s*\(/);
2359
+ if (func && !["if", "for", "while", "switch", "catch", "return"].includes(func[1])) {
2360
+ return { kind: "function", name: func[1], exported: !func[1].startsWith("_") };
2361
+ }
2362
+ }
2363
+ return null;
2364
+ }
2365
+ function estimateEndLine(lines, startIdx, lang) {
2366
+ const MAX_SCAN = 200;
2367
+ const end = Math.min(startIdx + MAX_SCAN, lines.length);
2368
+ if (lang !== "python" /* Python */ && lang !== "ruby" /* Ruby */) {
2369
+ let depth = 0;
2370
+ let foundOpen = false;
2371
+ for (let i = startIdx; i < end; i++) {
2372
+ for (const ch of lines[i]) {
2373
+ if (ch === "{") {
2374
+ depth++;
2375
+ foundOpen = true;
2376
+ } else if (ch === "}") {
2377
+ depth--;
2378
+ if (foundOpen && depth === 0) return i + 1;
2379
+ }
2380
+ }
2381
+ }
2382
+ return void 0;
2383
+ }
2384
+ const startIndent = (lines[startIdx].match(/^(\s*)/) ?? ["", ""])[1].length;
2385
+ for (let i = startIdx + 1; i < end; i++) {
2386
+ const l = lines[i];
2387
+ if (l.trim() === "") continue;
2388
+ const indent = (l.match(/^(\s*)/) ?? ["", ""])[1].length;
2389
+ if (indent <= startIndent && l.trim() !== "") return i;
2390
+ }
2391
+ return void 0;
2392
+ }
2393
+ function extractBlock(lines, startIdx, maxLines) {
2394
+ const end = Math.min(startIdx + maxLines, lines.length);
2395
+ return lines.slice(startIdx, end).join("\n");
2396
+ }
2397
+ var CALL_KEYWORDS = /* @__PURE__ */ new Set([
2398
+ "if",
2399
+ "for",
2400
+ "while",
2401
+ "switch",
2402
+ "catch",
2403
+ "return",
2404
+ "throw",
2405
+ "typeof",
2406
+ "instanceof",
2407
+ "delete",
2408
+ "void",
2409
+ "new",
2410
+ "import",
2411
+ "export",
2412
+ "from",
2413
+ "const",
2414
+ "let",
2415
+ "var",
2416
+ "function",
2417
+ "class",
2418
+ "interface",
2419
+ "type",
2420
+ "enum",
2421
+ "extends",
2422
+ "implements"
2423
+ ]);
2424
+ var resolvePhase = {
2425
+ name: "resolve",
2426
+ dependencies: ["parse"],
2427
+ async execute(context) {
2428
+ const start = Date.now();
2429
+ const { graph, workspaceRoot, filePaths } = context;
2430
+ const fileCache = context.fileCache ?? /* @__PURE__ */ new Map();
2431
+ const fileFunctionIndex = context.fileFunctionIndex ?? /* @__PURE__ */ new Map();
2432
+ let importEdges = 0;
2433
+ let callEdges = 0;
2434
+ let heritageEdges = 0;
2435
+ const fileIndex = /* @__PURE__ */ new Map();
2436
+ for (const fp of filePaths) {
2437
+ const rel = path6.relative(workspaceRoot, fp);
2438
+ fileIndex.set(rel, fp);
2439
+ const noExt = rel.replace(/\.\w+$/, "");
2440
+ if (!fileIndex.has(noExt)) fileIndex.set(noExt, fp);
2441
+ const base = path6.basename(rel, path6.extname(rel));
2442
+ if (!fileIndex.has(base)) fileIndex.set(base, fp);
2443
+ }
2444
+ const symbolIndex = /* @__PURE__ */ new Map();
2445
+ const fileSymbolIndex = /* @__PURE__ */ new Map();
2446
+ for (const node of graph.allNodes()) {
2447
+ if ([
2448
+ "function",
2449
+ "class",
2450
+ "interface",
2451
+ "method",
2452
+ "enum",
2453
+ "type_alias",
2454
+ "variable",
2455
+ "constant",
2456
+ "struct",
2457
+ "trait"
2458
+ ].includes(node.kind)) {
2459
+ symbolIndex.set(node.name, node.id);
2460
+ let fileMap = fileSymbolIndex.get(node.filePath);
2461
+ if (!fileMap) {
2462
+ fileMap = /* @__PURE__ */ new Map();
2463
+ fileSymbolIndex.set(node.filePath, fileMap);
2464
+ }
2465
+ fileMap.set(node.name, node.id);
2466
+ }
2467
+ }
2468
+ let fileDone = 0;
2469
+ for (const filePath of filePaths) {
2470
+ const lang = detectLanguage(filePath);
2471
+ if (!lang) continue;
2472
+ const relativePath = path6.relative(workspaceRoot, filePath);
2473
+ const fileNodeId = generateNodeId("file", relativePath, relativePath);
2474
+ const source = fileCache.get(filePath);
2475
+ if (!source) continue;
2476
+ const lines = source.split("\n");
2477
+ const imports = extractImports(lines, lang === "python");
2478
+ const calls = extractCalls(lines);
2479
+ const heritages = extractHeritage(lines);
2480
+ for (const imp of imports) {
2481
+ const cleaned = imp.rawPath.replace(/['"]/g, "");
2482
+ let resolvedRelPath = null;
2483
+ if (cleaned.startsWith(".")) {
2484
+ const cleanedNoJs = cleaned.replace(/\.(js|jsx)$/, "");
2485
+ const fromDir = path6.dirname(relativePath);
2486
+ for (const ext of ["", ".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", "/index.ts", "/index.js"]) {
2487
+ const candidate = path6.join(fromDir, cleanedNoJs + ext);
2488
+ const normalized = path6.normalize(candidate);
2489
+ if (fileIndex.has(normalized)) {
2490
+ const absPath = fileIndex.get(normalized);
2491
+ resolvedRelPath = path6.relative(workspaceRoot, absPath);
2492
+ break;
2493
+ }
2494
+ }
2495
+ } else {
2496
+ for (const ext of ["", ".ts", ".js", ".py", ".java", ".go"]) {
2497
+ if (fileIndex.has(cleaned + ext)) {
2498
+ resolvedRelPath = cleaned + ext;
2499
+ break;
2500
+ }
2501
+ }
2502
+ if (!resolvedRelPath) {
2503
+ const asPath = cleaned.replace(/\./g, "/");
2504
+ for (const ext of ["", ".ts", ".js", ".py", ".java", ".go", "/index.ts", "/__init__.py"]) {
2505
+ if (fileIndex.has(asPath + ext)) {
2506
+ resolvedRelPath = asPath + ext;
2507
+ break;
2508
+ }
2509
+ }
2510
+ }
2511
+ }
2512
+ if (resolvedRelPath) {
2513
+ const targetFileId = generateNodeId("file", resolvedRelPath, resolvedRelPath);
2514
+ if (graph.getNode(targetFileId)) {
2515
+ const edgeId = generateEdgeId(fileNodeId, targetFileId, "imports");
2516
+ if (!graph.getEdge(edgeId)) {
2517
+ graph.addEdge({
2518
+ id: edgeId,
2519
+ source: fileNodeId,
2520
+ target: targetFileId,
2521
+ kind: "imports",
2522
+ weight: 0.95,
2523
+ label: cleaned
2524
+ });
2525
+ importEdges++;
2526
+ }
2527
+ }
2528
+ }
2529
+ }
2530
+ const localSymbols = fileSymbolIndex.get(relativePath);
2531
+ const funcList = fileFunctionIndex.get(relativePath);
2532
+ for (const call of calls) {
2533
+ let targetId = localSymbols?.get(call.name);
2534
+ let confidence = 0.95;
2535
+ if (!targetId) {
2536
+ targetId = symbolIndex.get(call.name);
2537
+ confidence = 0.5;
2538
+ }
2539
+ if (targetId) {
2540
+ const callerNodeId = funcList ? findEnclosingFunctionFast(funcList, call.line) : null;
2541
+ const sourceId = callerNodeId ?? fileNodeId;
2542
+ if (sourceId !== targetId) {
2543
+ const edgeId = generateEdgeId(sourceId, targetId, "calls");
2544
+ if (!graph.getEdge(edgeId)) {
2545
+ graph.addEdge({
2546
+ id: edgeId,
2547
+ source: sourceId,
2548
+ target: targetId,
2549
+ kind: "calls",
2550
+ weight: confidence,
2551
+ label: call.name
2552
+ });
2553
+ callEdges++;
2554
+ }
2555
+ }
2556
+ }
2557
+ }
2558
+ for (const h of heritages) {
2559
+ const classNodeId = localSymbols?.get(h.className) ?? symbolIndex.get(h.className);
2560
+ if (!classNodeId) continue;
2561
+ for (const ext of h.extendsNames) {
2562
+ const targetId = symbolIndex.get(ext);
2563
+ if (targetId) {
2564
+ const edgeId = generateEdgeId(classNodeId, targetId, "extends");
2565
+ if (!graph.getEdge(edgeId)) {
2566
+ graph.addEdge({
2567
+ id: edgeId,
2568
+ source: classNodeId,
2569
+ target: targetId,
2570
+ kind: "extends",
2571
+ weight: 1,
2572
+ label: `extends ${ext}`
2573
+ });
2574
+ heritageEdges++;
2575
+ }
2576
+ }
2577
+ }
2578
+ for (const impl of h.implementsNames) {
2579
+ const targetId = symbolIndex.get(impl);
2580
+ if (targetId) {
2581
+ const edgeId = generateEdgeId(classNodeId, targetId, "implements");
2582
+ if (!graph.getEdge(edgeId)) {
2583
+ graph.addEdge({
2584
+ id: edgeId,
2585
+ source: classNodeId,
2586
+ target: targetId,
2587
+ kind: "implements",
2588
+ weight: 1,
2589
+ label: `implements ${impl}`
2590
+ });
2591
+ heritageEdges++;
2592
+ }
2593
+ }
2594
+ }
2595
+ }
2596
+ fileDone++;
2597
+ context.onPhaseProgress?.("resolve", fileDone, filePaths.length);
2598
+ }
2599
+ return {
2600
+ status: "completed",
2601
+ duration: Date.now() - start,
2602
+ message: `Resolved ${importEdges} imports, ${callEdges} calls, ${heritageEdges} heritage edges. Graph: ${graph.size.nodes} nodes, ${graph.size.edges} edges`
2603
+ };
2604
+ }
2605
+ };
2606
+ function extractImports(lines, isPython) {
2607
+ const imports = [];
2608
+ for (let i = 0; i < lines.length; i++) {
2609
+ const line = lines[i].trim();
2610
+ const tsImport = line.match(/import\s+.*?from\s+['"]([^'"]+)['"]/);
2611
+ if (tsImport) {
2612
+ const names = [];
2613
+ const namedMatch = line.match(/\{([^}]+)\}/);
2614
+ if (namedMatch) {
2615
+ names.push(
2616
+ ...namedMatch[1].split(",").map((n) => n.trim().split(/\s+as\s+/).pop().trim()).filter(Boolean)
2617
+ );
2618
+ }
2619
+ const defaultMatch = line.match(/import\s+(\w+)/);
2620
+ if (defaultMatch && defaultMatch[1] !== "type") names.push(defaultMatch[1]);
2621
+ imports.push({ rawPath: tsImport[1], localNames: names, isDefault: !namedMatch, line: i + 1 });
2622
+ continue;
2623
+ }
2624
+ if (isPython) {
2625
+ const fromImport = line.match(/from\s+([\w.]+)\s+import\s+(.+)/);
2626
+ if (fromImport) {
2627
+ const names = fromImport[2].split(",").map((n) => n.trim().split(/\s+as\s+/).pop().trim()).filter(Boolean);
2628
+ imports.push({ rawPath: fromImport[1], localNames: names, isDefault: false, line: i + 1 });
2629
+ continue;
2630
+ }
2631
+ const directImport = line.match(/^import\s+([\w.]+)(?:\s+as\s+(\w+))?/);
2632
+ if (directImport) {
2633
+ imports.push({
2634
+ rawPath: directImport[1],
2635
+ localNames: [directImport[2] ?? directImport[1].split(".").pop()],
2636
+ isDefault: false,
2637
+ line: i + 1
2638
+ });
2639
+ continue;
2640
+ }
2641
+ }
2642
+ const javaImport = line.match(/^import\s+(?:static\s+)?([\w.]+)/);
2643
+ if (javaImport && !line.includes("from")) {
2644
+ const parts = javaImport[1].split(".");
2645
+ imports.push({ rawPath: javaImport[1], localNames: [parts[parts.length - 1]], isDefault: false, line: i + 1 });
2646
+ continue;
2647
+ }
2648
+ const goImport = line.match(/^\s*"([^"]+)"/);
2649
+ if (goImport && (i > 0 && lines[i - 1]?.includes("import") || line.match(/^import\s+"/))) {
2650
+ const parts = goImport[1].split("/");
2651
+ imports.push({ rawPath: goImport[1], localNames: [parts[parts.length - 1]], isDefault: false, line: i + 1 });
2652
+ continue;
2653
+ }
2654
+ const includeMatch = line.match(/#include\s+[<"]([^>"]+)[>"]/);
2655
+ if (includeMatch) {
2656
+ imports.push({ rawPath: includeMatch[1], localNames: [], isDefault: false, line: i + 1 });
2657
+ continue;
2658
+ }
2659
+ const rustUse = line.match(/^use\s+([\w:]+)/);
2660
+ if (rustUse) {
2661
+ const parts = rustUse[1].split("::");
2662
+ imports.push({ rawPath: rustUse[1], localNames: [parts[parts.length - 1]], isDefault: false, line: i + 1 });
2663
+ continue;
2664
+ }
2665
+ const usingMatch = line.match(/^using\s+([\w.]+)/);
2666
+ if (usingMatch) {
2667
+ const parts = usingMatch[1].split(".");
2668
+ imports.push({ rawPath: usingMatch[1], localNames: [parts[parts.length - 1]], isDefault: false, line: i + 1 });
2669
+ }
2670
+ const requireMatch = line.match(/require\s+['"]([^'"]+)['"]/);
2671
+ if (requireMatch) {
2672
+ imports.push({ rawPath: requireMatch[1], localNames: [], isDefault: false, line: i + 1 });
2673
+ }
2674
+ }
2675
+ return imports;
2676
+ }
2677
+ function extractCalls(lines) {
2678
+ const calls = [];
2679
+ const callRegex = /(?:new\s+)?(\w+)\s*\(/g;
2680
+ for (let i = 0; i < lines.length; i++) {
2681
+ const line = lines[i];
2682
+ if (/^\s*(export\s+)?(async\s+)?function\s/.test(line)) continue;
2683
+ if (/^\s*(export\s+)?(abstract\s+)?class\s/.test(line)) continue;
2684
+ if (/^\s*(export\s+)?interface\s/.test(line)) continue;
2685
+ if (/^\s*(export\s+)?enum\s/.test(line)) continue;
2686
+ if (/^\s*(export\s+)?type\s+\w+\s*=/.test(line)) continue;
2687
+ if (/^\s*import\s/.test(line)) continue;
2688
+ if (/^\s*\/\//.test(line)) continue;
2689
+ let match;
2690
+ callRegex.lastIndex = 0;
2691
+ while ((match = callRegex.exec(line)) !== null) {
2692
+ const name = match[1];
2693
+ if (CALL_KEYWORDS.has(name)) continue;
2694
+ const isNew = line.substring(Math.max(0, match.index - 4), match.index).includes("new");
2695
+ calls.push({ name, isNew, line: i + 1 });
2696
+ }
2697
+ const memberCallRegex = /(\w+)\.(\w+)\s*\(/g;
2698
+ memberCallRegex.lastIndex = 0;
2699
+ while ((match = memberCallRegex.exec(line)) !== null) {
2700
+ calls.push({ name: match[2], receiverText: match[1], isNew: false, line: i + 1 });
2701
+ }
2702
+ }
2703
+ return calls;
2704
+ }
2705
+ function extractHeritage(lines) {
2706
+ const heritages = [];
2707
+ for (const line of lines) {
2708
+ const classMatch = line.match(/class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?/);
2709
+ if (classMatch) {
2710
+ const extendsNames = classMatch[2] ? [classMatch[2]] : [];
2711
+ const implementsNames = classMatch[3] ? classMatch[3].split(",").map((n) => n.trim()).filter(Boolean) : [];
2712
+ heritages.push({ className: classMatch[1], extendsNames, implementsNames });
2713
+ continue;
2714
+ }
2715
+ const pyClassMatch = line.match(/class\s+(\w+)\(([^)]+)\)/);
2716
+ if (pyClassMatch) {
2717
+ const bases = pyClassMatch[2].split(",").map((n) => n.trim()).filter(Boolean);
2718
+ heritages.push({ className: pyClassMatch[1], extendsNames: bases, implementsNames: [] });
2719
+ }
2720
+ }
2721
+ return heritages;
2722
+ }
2723
+ function findEnclosingFunctionFast(funcs, line) {
2724
+ let lo = 0;
2725
+ let hi = funcs.length - 1;
2726
+ let best = null;
2727
+ while (lo <= hi) {
2728
+ const mid = lo + hi >> 1;
2729
+ const fn = funcs[mid];
2730
+ if (fn.startLine <= line) {
2731
+ if (fn.endLine === void 0 || line <= fn.endLine) {
2732
+ best = fn.id;
2733
+ }
2734
+ lo = mid + 1;
2735
+ } else {
2736
+ hi = mid - 1;
2737
+ }
2738
+ }
2739
+ return best;
2740
+ }
2741
+
2742
+ // src/pipeline/phases/cluster-phase.ts
2743
+ var clusterPhase = {
2744
+ name: "cluster",
2745
+ dependencies: ["resolve"],
2746
+ async execute(context) {
2747
+ const start = Date.now();
2748
+ const { graph } = context;
2749
+ const relevantKinds = /* @__PURE__ */ new Set(["function", "class", "method", "interface", "struct", "trait", "enum"]);
2750
+ const nodesByDir = /* @__PURE__ */ new Map();
2751
+ for (const node of graph.allNodes()) {
2752
+ if (!relevantKinds.has(node.kind)) continue;
2753
+ const dir = node.filePath.split("/").slice(0, -1).join("/") || ".";
2754
+ let group = nodesByDir.get(dir);
2755
+ if (!group) {
2756
+ group = [];
2757
+ nodesByDir.set(dir, group);
2758
+ }
2759
+ group.push({ id: node.id, name: node.name });
2760
+ }
2761
+ let clusterCount = 0;
2762
+ const dirEntries = [...nodesByDir.entries()];
2763
+ let clusterDone = 0;
2764
+ for (const [dir, members] of dirEntries) {
2765
+ clusterDone++;
2766
+ context.onPhaseProgress?.("cluster", clusterDone, dirEntries.length);
2767
+ if (members.length < 2) continue;
2768
+ const clusterId = generateNodeId("cluster", dir, `cluster-${clusterCount}`);
2769
+ const label = dir.split("/").filter(Boolean).pop() ?? `cluster-${clusterCount}`;
2770
+ graph.addNode({
2771
+ id: clusterId,
2772
+ kind: "cluster",
2773
+ name: label,
2774
+ filePath: dir,
2775
+ metadata: { memberCount: members.length }
2776
+ });
2777
+ for (const member of members) {
2778
+ graph.addEdge({
2779
+ id: generateEdgeId(member.id, clusterId, "belongs_to"),
2780
+ source: member.id,
2781
+ target: clusterId,
2782
+ kind: "belongs_to",
2783
+ weight: 1
2784
+ });
2785
+ }
2786
+ clusterCount++;
2787
+ }
2788
+ return {
2789
+ status: "completed",
2790
+ duration: Date.now() - start,
2791
+ message: `Created ${clusterCount} clusters`
2792
+ };
2793
+ }
2794
+ };
2795
+
2796
+ // src/pipeline/phases/flow-phase.ts
2797
+ var flowPhase = {
2798
+ name: "flow",
2799
+ dependencies: ["resolve"],
2800
+ async execute(context) {
2801
+ const start = Date.now();
2802
+ const { graph } = context;
2803
+ const calledNodes = /* @__PURE__ */ new Set();
2804
+ for (const edge of graph.findEdgesByKind("calls")) {
2805
+ calledNodes.add(edge.target);
2806
+ }
2807
+ const entryPoints = [];
2808
+ for (const node of graph.allNodes()) {
2809
+ if (!["function", "method"].includes(node.kind)) continue;
2810
+ let score = 0;
2811
+ const hasCallers = calledNodes.has(node.id);
2812
+ const outCalls = [...graph.findEdgesFrom(node.id)].filter((e) => e.kind === "calls");
2813
+ if (!hasCallers && outCalls.length > 0) score += 10;
2814
+ if (node.exported) score += 5;
2815
+ if (/^(main|handle|init|start|run|execute|process|serve|listen|bootstrap)/.test(node.name)) score += 3;
2816
+ if (node.filePath.includes("test") || node.filePath.includes("spec") || node.filePath.includes("__test")) score -= 20;
2817
+ if (node.filePath.includes("route") || node.filePath.includes("controller") || node.filePath.includes("handler")) score += 8;
2818
+ if (score >= 5) {
2819
+ entryPoints.push({ id: node.id, name: node.name, score, filePath: node.filePath });
2820
+ }
2821
+ }
2822
+ entryPoints.sort((a, b) => b.score - a.score);
2823
+ const maxFlows = 75;
2824
+ const maxDepth = 10;
2825
+ const maxBranching = 4;
2826
+ let flowCount = 0;
2827
+ const epSlice = entryPoints.slice(0, 20);
2828
+ for (let epIdx = 0; epIdx < epSlice.length; epIdx++) {
2829
+ const ep = epSlice[epIdx];
2830
+ context.onPhaseProgress?.("flow", epIdx + 1, epSlice.length);
2831
+ if (flowCount >= maxFlows) break;
2832
+ const queue = [{ nodeId: ep.id, path: [ep.id] }];
2833
+ const visited = /* @__PURE__ */ new Set();
2834
+ while (queue.length > 0 && flowCount < maxFlows) {
2835
+ const { nodeId, path: path19 } = queue.shift();
2836
+ if (path19.length > maxDepth) continue;
2837
+ const callEdges = [...graph.findEdgesFrom(nodeId)].filter((e) => e.kind === "calls").slice(0, maxBranching);
2838
+ if (callEdges.length === 0 && path19.length >= 3) {
2839
+ const flowId = generateNodeId("flow", ep.filePath, `flow-${flowCount}`);
2840
+ graph.addNode({
2841
+ id: flowId,
2842
+ kind: "flow",
2843
+ name: `${ep.name} flow ${flowCount}`,
2844
+ filePath: ep.filePath,
2845
+ metadata: { steps: path19, entryPoint: ep.name }
2846
+ });
2847
+ for (let i = 0; i < path19.length; i++) {
2848
+ graph.addEdge({
2849
+ id: generateEdgeId(path19[i], flowId, `step_of_${i}`),
2850
+ source: path19[i],
2851
+ target: flowId,
2852
+ kind: "step_of",
2853
+ weight: 1,
2854
+ label: `step ${i + 1}`
2855
+ });
2856
+ }
2857
+ flowCount++;
2858
+ continue;
2859
+ }
2860
+ for (const edge of callEdges) {
2861
+ if (visited.has(edge.target)) continue;
2862
+ visited.add(edge.target);
2863
+ queue.push({ nodeId: edge.target, path: [...path19, edge.target] });
2864
+ }
2865
+ }
2866
+ }
2867
+ return {
2868
+ status: "completed",
2869
+ duration: Date.now() - start,
2870
+ message: `Found ${entryPoints.length} entry points, traced ${flowCount} flows`
2871
+ };
2872
+ }
2873
+ };
2874
+
2875
+ // src/scope-analysis/scope-builder.ts
2876
+ function createScope(name, kind, parent = null) {
2877
+ const scope = { name, kind, parent, bindings: /* @__PURE__ */ new Map(), children: [] };
2878
+ parent?.children.push(scope);
2879
+ return scope;
2880
+ }
2881
+ function resolveBinding(name, scope) {
2882
+ let current = scope;
2883
+ while (current !== null) {
2884
+ const binding = current.bindings.get(name);
2885
+ if (binding) return binding;
2886
+ current = current.parent;
2887
+ }
2888
+ return null;
2889
+ }
2890
+ function addBinding(scope, binding) {
2891
+ scope.bindings.set(binding.name, binding);
2892
+ }
2893
+
2894
+ // src/clustering/community-detector.ts
2895
+ function detectCommunities(graph) {
2896
+ const relevantKinds = /* @__PURE__ */ new Set(["function", "class", "method", "interface", "struct"]);
2897
+ const nodes = [];
2898
+ for (const node of graph.allNodes()) {
2899
+ if (relevantKinds.has(node.kind)) {
2900
+ nodes.push(node);
2901
+ }
2902
+ }
2903
+ if (nodes.length < 10) return [];
2904
+ const dirGroups = /* @__PURE__ */ new Map();
2905
+ for (const node of nodes) {
2906
+ const dir = node.filePath.split("/").slice(0, -1).join("/") || ".";
2907
+ let group = dirGroups.get(dir);
2908
+ if (!group) {
2909
+ group = [];
2910
+ dirGroups.set(dir, group);
2911
+ }
2912
+ group.push(node);
2913
+ }
2914
+ const clusters = [];
2915
+ let idx = 0;
2916
+ for (const [dir, members] of dirGroups) {
2917
+ if (members.length < 2) continue;
2918
+ const clusterId = generateNodeId("cluster", dir, `cluster-${idx}`);
2919
+ const label = generateLabel(dir, members);
2920
+ clusters.push({
2921
+ clusterId,
2922
+ label,
2923
+ memberIds: members.map((m) => m.id)
2924
+ });
2925
+ idx++;
2926
+ }
2927
+ return clusters;
2928
+ }
2929
+ function generateLabel(dir, members) {
2930
+ const parts = dir.split("/").filter(Boolean);
2931
+ if (parts.length > 0) {
2932
+ return parts[parts.length - 1];
2933
+ }
2934
+ return `cluster-${members[0]?.name ?? "unknown"}`;
2935
+ }
2936
+ function addClustersToGraph(graph, clusters) {
2937
+ for (const cluster of clusters) {
2938
+ graph.addNode({
2939
+ id: cluster.clusterId,
2940
+ kind: "cluster",
2941
+ name: cluster.label,
2942
+ filePath: "",
2943
+ metadata: { memberCount: cluster.memberIds.length }
2944
+ });
2945
+ for (const memberId of cluster.memberIds) {
2946
+ graph.addEdge({
2947
+ id: generateEdgeId(memberId, cluster.clusterId, "belongs_to"),
2948
+ source: memberId,
2949
+ target: cluster.clusterId,
2950
+ kind: "belongs_to",
2951
+ weight: 1
2952
+ });
2953
+ }
2954
+ }
2955
+ }
2956
+
2957
+ // src/flow-detection/entry-point-finder.ts
2958
+ function findEntryPoints(graph) {
2959
+ const calledNodes = /* @__PURE__ */ new Set();
2960
+ for (const edge of graph.findEdgesByKind("calls")) {
2961
+ calledNodes.add(edge.target);
2962
+ }
2963
+ const entryPoints = [];
2964
+ for (const node of graph.allNodes()) {
2965
+ if (!["function", "method"].includes(node.kind)) continue;
2966
+ const outEdges = [...graph.findEdgesFrom(node.id)].filter((e) => e.kind === "calls");
2967
+ const inDegree = calledNodes.has(node.id) ? 1 : 0;
2968
+ let score = 0;
2969
+ if (outEdges.length > 0 && inDegree === 0) score += 10;
2970
+ if (node.exported) score += 5;
2971
+ if (/^(main|handle|init|start|run|execute|process|serve|listen)/.test(node.name)) score += 3;
2972
+ if (node.filePath.includes("test") || node.filePath.includes("spec")) score -= 20;
2973
+ if (node.filePath.includes("route") || node.filePath.includes("controller")) score += 8;
2974
+ if (score >= 5) {
2975
+ entryPoints.push({
2976
+ nodeId: node.id,
2977
+ name: node.name,
2978
+ score,
2979
+ filePath: node.filePath
2980
+ });
2981
+ }
2982
+ }
2983
+ return entryPoints.sort((a, b) => b.score - a.score);
2984
+ }
2985
+ function traceFlow(entryId, graph, maxDepth = 10, maxBranching = 4) {
2986
+ const flows = [];
2987
+ const maxFlows = 75;
2988
+ function bfs() {
2989
+ const queue = [{ nodeId: entryId, path: [entryId] }];
2990
+ const visited = /* @__PURE__ */ new Set();
2991
+ while (queue.length > 0 && flows.length < maxFlows) {
2992
+ const { nodeId, path: path19 } = queue.shift();
2993
+ if (path19.length > maxDepth) continue;
2994
+ const callEdges = [...graph.findEdgesFrom(nodeId)].filter((e) => e.kind === "calls").slice(0, maxBranching);
2995
+ if (callEdges.length === 0 && path19.length >= 3) {
2996
+ flows.push({ entryPointId: entryId, steps: [...path19] });
2997
+ continue;
2998
+ }
2999
+ for (const edge of callEdges) {
3000
+ if (visited.has(edge.target)) continue;
3001
+ visited.add(edge.target);
3002
+ queue.push({ nodeId: edge.target, path: [...path19, edge.target] });
3003
+ }
3004
+ }
3005
+ }
3006
+ bfs();
3007
+ return deduplicateFlows(flows);
3008
+ }
3009
+ function deduplicateFlows(flows) {
3010
+ const result = [];
3011
+ for (const flow of flows) {
3012
+ const edges = /* @__PURE__ */ new Set();
3013
+ for (let i = 0; i < flow.steps.length - 1; i++) {
3014
+ edges.add(`${flow.steps[i]}->${flow.steps[i + 1]}`);
3015
+ }
3016
+ const isDuplicate = result.some((existing) => {
3017
+ const existingEdges = /* @__PURE__ */ new Set();
3018
+ for (let i = 0; i < existing.steps.length - 1; i++) {
3019
+ existingEdges.add(`${existing.steps[i]}->${existing.steps[i + 1]}`);
3020
+ }
3021
+ let overlap = 0;
3022
+ for (const e of edges) {
3023
+ if (existingEdges.has(e)) overlap++;
3024
+ }
3025
+ return overlap / Math.max(edges.size, 1) > 0.7;
3026
+ });
3027
+ if (!isDuplicate) result.push(flow);
3028
+ }
3029
+ return result;
3030
+ }
3031
+
3032
+ // src/search/text-search.ts
3033
+ function textSearch(graph, query, limit = 20) {
3034
+ const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
3035
+ const results = [];
3036
+ const isTestPath = (fp) => fp.includes("test") || fp.includes("spec") || fp.includes("__test");
3037
+ const isDistPath = (fp) => fp.includes("/dist") || fp.includes("\\dist") || fp.includes(".d.ts");
3038
+ for (const node of graph.allNodes()) {
3039
+ if (["directory", "cluster", "flow"].includes(node.kind)) continue;
3040
+ let score = 0;
3041
+ const nameLC = node.name.toLowerCase();
3042
+ const pathLC = node.filePath.toLowerCase();
3043
+ for (const term of terms) {
3044
+ if (nameLC === term) score += 10;
3045
+ else if (nameLC.startsWith(term)) score += 7;
3046
+ else if (nameLC.includes(term)) score += 5;
3047
+ if (pathLC.includes(term)) score += 2;
3048
+ if (node.content?.toLowerCase().includes(term)) score += 3;
3049
+ }
3050
+ if (score > 0) {
3051
+ if (isDistPath(node.filePath)) score -= 8;
3052
+ if (isTestPath(node.filePath)) score -= 4;
3053
+ if (["function", "class", "interface", "method"].includes(node.kind)) score += 1;
3054
+ }
3055
+ if (score > 0) {
3056
+ results.push({
3057
+ nodeId: node.id,
3058
+ name: node.name,
3059
+ kind: node.kind,
3060
+ filePath: node.filePath,
3061
+ score,
3062
+ snippet: node.content?.slice(0, 200)
3063
+ });
3064
+ }
3065
+ }
3066
+ results.sort((a, b) => b.score - a.score);
3067
+ return results.slice(0, limit);
3068
+ }
3069
+ function reciprocalRankFusion(...rankings) {
3070
+ const K = 60;
3071
+ const scoreMap = /* @__PURE__ */ new Map();
3072
+ for (const ranking of rankings) {
3073
+ for (let rank = 0; rank < ranking.length; rank++) {
3074
+ const result = ranking[rank];
3075
+ const existing = scoreMap.get(result.nodeId);
3076
+ const rrfContribution = 1 / (K + rank + 1);
3077
+ if (existing) {
3078
+ existing.rrfScore += rrfContribution;
3079
+ } else {
3080
+ scoreMap.set(result.nodeId, {
3081
+ result,
3082
+ rrfScore: rrfContribution
3083
+ });
3084
+ }
3085
+ }
3086
+ }
3087
+ return [...scoreMap.values()].sort((a, b) => b.rrfScore - a.rrfScore).map((entry) => ({ ...entry.result, score: entry.rrfScore }));
3088
+ }
3089
+
3090
+ // src/search/index.ts
3091
+ init_embedder();
3092
+
3093
+ // src/search/vector-index.ts
3094
+ var EMBED_TABLE = "embed_nodes";
3095
+ var EMBED_DIM = 384;
3096
+ var INDEX_NAME = "embed_vec_idx";
3097
+ var VectorIndex = class {
3098
+ db;
3099
+ constructor(db) {
3100
+ this.db = db;
3101
+ }
3102
+ async init() {
3103
+ await this.db.execute("INSTALL VECTOR");
3104
+ await this.db.execute("LOAD EXTENSION VECTOR");
3105
+ await this.db.execute(`
3106
+ CREATE NODE TABLE IF NOT EXISTS ${EMBED_TABLE} (
3107
+ id STRING,
3108
+ name STRING,
3109
+ kind STRING,
3110
+ file_path STRING,
3111
+ text STRING,
3112
+ embedding FLOAT[${EMBED_DIM}],
3113
+ PRIMARY KEY (id)
3114
+ )
3115
+ `);
3116
+ }
3117
+ async buildIndex(nodes) {
3118
+ await this.db.execute(`MATCH (n:${EMBED_TABLE}) DETACH DELETE n`).catch(() => {
3119
+ });
3120
+ for (const node of nodes) {
3121
+ const vecLiteral = `[${node.embedding.join(",")}]`;
3122
+ await this.db.execute(
3123
+ `CREATE (:${EMBED_TABLE} {
3124
+ id: '${esc(node.id)}',
3125
+ name: '${esc(node.name)}',
3126
+ kind: '${esc(node.kind)}',
3127
+ file_path: '${esc(node.filePath)}',
3128
+ text: '${esc(node.text)}',
3129
+ embedding: ${vecLiteral}
3130
+ })`
3131
+ );
3132
+ }
3133
+ await this.db.execute(`CALL DROP_VECTOR_INDEX('${EMBED_TABLE}', '${INDEX_NAME}')`).catch(() => {
3134
+ });
3135
+ await this.db.execute(`CALL CREATE_VECTOR_INDEX('${EMBED_TABLE}', '${INDEX_NAME}', 'embedding')`);
3136
+ }
3137
+ async search(queryEmbedding, topK = 10) {
3138
+ const vecLiteral = `[${queryEmbedding.join(",")}]`;
3139
+ const rows = await this.db.query(
3140
+ `CALL QUERY_VECTOR_INDEX('${EMBED_TABLE}', '${INDEX_NAME}', ${vecLiteral}, ${topK}) RETURN node.id, node.name, node.kind, node.file_path, distance`
3141
+ );
3142
+ return rows.map((r) => ({
3143
+ nodeId: String(r["node.id"]),
3144
+ name: String(r["node.name"]),
3145
+ kind: String(r["node.kind"]),
3146
+ filePath: String(r["node.file_path"]),
3147
+ score: 1 - Number(r["distance"])
3148
+ // cosine distance → similarity
3149
+ }));
3150
+ }
3151
+ async isBuilt() {
3152
+ try {
3153
+ const rows = await this.db.query(`MATCH (n:${EMBED_TABLE}) RETURN count(n) AS cnt`);
3154
+ return Number(rows[0]?.cnt ?? 0) > 0;
3155
+ } catch {
3156
+ return false;
3157
+ }
3158
+ }
3159
+ };
3160
+ function esc(s) {
3161
+ return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "");
3162
+ }
3163
+ var GLOBAL_DIR = path6.join(os3.homedir(), ".code-intel");
3164
+ var REPOS_FILE = path6.join(GLOBAL_DIR, "repos.json");
3165
+ function loadRegistry() {
3166
+ try {
3167
+ const data = fs6.readFileSync(REPOS_FILE, "utf-8");
3168
+ return JSON.parse(data);
3169
+ } catch {
3170
+ return [];
3171
+ }
3172
+ }
3173
+ function saveRegistry(entries) {
3174
+ fs6.mkdirSync(GLOBAL_DIR, { recursive: true });
3175
+ fs6.writeFileSync(REPOS_FILE, JSON.stringify(entries, null, 2));
3176
+ }
3177
+ function upsertRepo(entry) {
3178
+ const entries = loadRegistry();
3179
+ const idx = entries.findIndex((e) => e.path === entry.path);
3180
+ if (idx >= 0) {
3181
+ entries[idx] = entry;
3182
+ } else {
3183
+ entries.push(entry);
3184
+ }
3185
+ saveRegistry(entries);
3186
+ }
3187
+ function removeRepo(repoPath) {
3188
+ const entries = loadRegistry().filter((e) => e.path !== repoPath);
3189
+ saveRegistry(entries);
3190
+ }
3191
+ function saveMetadata(repoDir, metadata) {
3192
+ const metaDir = path6.join(repoDir, ".code-intel");
3193
+ fs6.mkdirSync(metaDir, { recursive: true });
3194
+ fs6.writeFileSync(path6.join(metaDir, "meta.json"), JSON.stringify(metadata, null, 2));
3195
+ }
3196
+ function loadMetadata(repoDir) {
3197
+ try {
3198
+ const data = fs6.readFileSync(path6.join(repoDir, ".code-intel", "meta.json"), "utf-8");
3199
+ return JSON.parse(data);
3200
+ } catch {
3201
+ return null;
3202
+ }
3203
+ }
3204
+ function getDbPath(repoDir) {
3205
+ return path6.join(repoDir, ".code-intel", "graph.db");
3206
+ }
3207
+ function getVectorDbPath(repoDir) {
3208
+ return path6.join(repoDir, ".code-intel", "vector.db");
3209
+ }
3210
+
3211
+ // src/mcp-server/server.ts
3212
+ init_group_registry();
3213
+ var DbManager = class {
3214
+ db = null;
3215
+ conn = null;
3216
+ dbPath;
3217
+ constructor(dbPath) {
3218
+ this.dbPath = dbPath;
3219
+ }
3220
+ async init() {
3221
+ fs6.mkdirSync(path6.dirname(this.dbPath), { recursive: true });
3222
+ this.db = new Database(this.dbPath);
3223
+ await this.db.init();
3224
+ this.conn = new Connection(this.db);
3225
+ await this.conn.init();
3226
+ }
3227
+ async query(cypher) {
3228
+ if (!this.conn) throw new Error("Database not initialized");
3229
+ const result = await this.conn.query(cypher);
3230
+ const qr = Array.isArray(result) ? result[0] : result;
3231
+ const rows = await qr.getAll();
3232
+ qr.close();
3233
+ return rows;
3234
+ }
3235
+ async execute(cypher) {
3236
+ if (!this.conn) throw new Error("Database not initialized");
3237
+ const result = await this.conn.query(cypher);
3238
+ const qr = Array.isArray(result) ? result[0] : result;
3239
+ qr.close();
3240
+ }
3241
+ close() {
3242
+ try {
3243
+ this.conn?.close();
3244
+ } catch {
3245
+ }
3246
+ try {
3247
+ this.db?.close();
3248
+ } catch {
3249
+ }
3250
+ this.conn = null;
3251
+ this.db = null;
3252
+ }
3253
+ get isOpen() {
3254
+ return this.conn !== null;
3255
+ }
3256
+ };
3257
+
3258
+ // src/storage/schema.ts
3259
+ var NODE_TABLE_MAP = {
3260
+ file: "file_nodes",
3261
+ directory: "dir_nodes",
3262
+ function: "func_nodes",
3263
+ class: "class_nodes",
3264
+ interface: "iface_nodes",
3265
+ method: "method_nodes",
3266
+ constructor: "ctor_nodes",
3267
+ variable: "var_nodes",
3268
+ property: "prop_nodes",
3269
+ struct: "struct_nodes",
3270
+ enum: "enum_nodes",
3271
+ trait: "trait_nodes",
3272
+ namespace: "ns_nodes",
3273
+ module: "mod_nodes",
3274
+ type_alias: "type_nodes",
3275
+ constant: "const_nodes",
3276
+ route: "route_nodes",
3277
+ cluster: "cluster_nodes",
3278
+ flow: "flow_nodes"
3279
+ };
3280
+ var ALL_NODE_TABLES = [...new Set(Object.values(NODE_TABLE_MAP))];
3281
+ function getCreateNodeTableDDL(tableName) {
3282
+ return `CREATE NODE TABLE IF NOT EXISTS ${tableName} (
3283
+ id STRING,
3284
+ name STRING,
3285
+ file_path STRING,
3286
+ start_line INT64,
3287
+ end_line INT64,
3288
+ exported BOOLEAN,
3289
+ content STRING,
3290
+ metadata STRING,
3291
+ PRIMARY KEY (id)
3292
+ )`;
3293
+ }
3294
+ function getCreateEdgeTableDDL() {
3295
+ const ddls = [];
3296
+ const uniqueTables = ALL_NODE_TABLES;
3297
+ const fromToPairs = [];
3298
+ for (const from of uniqueTables) {
3299
+ for (const to of uniqueTables) {
3300
+ fromToPairs.push(`FROM ${from} TO ${to}`);
3301
+ }
3302
+ }
3303
+ ddls.push(`CREATE REL TABLE IF NOT EXISTS code_edges (
3304
+ ${fromToPairs.join(",\n ")},
3305
+ kind STRING,
3306
+ weight DOUBLE,
3307
+ label STRING
3308
+ )`);
3309
+ return ddls;
3310
+ }
3311
+
3312
+ // src/multi-repo/graph-from-db.ts
3313
+ var TABLE_TO_KIND = Object.fromEntries(
3314
+ Object.entries(NODE_TABLE_MAP).map(([kind, table]) => [table, kind])
3315
+ );
3316
+ function parseRow(row, kind) {
3317
+ return {
3318
+ id: String(row["id"] ?? ""),
3319
+ kind,
3320
+ name: String(row["name"] ?? ""),
3321
+ filePath: String(row["file_path"] ?? ""),
3322
+ startLine: row["start_line"] != null ? Number(row["start_line"]) : void 0,
3323
+ endLine: row["end_line"] != null ? Number(row["end_line"]) : void 0,
3324
+ exported: row["exported"] != null ? Boolean(row["exported"]) : void 0,
3325
+ content: row["content"] ? String(row["content"]) : void 0,
3326
+ metadata: row["metadata"] ? (() => {
3327
+ try {
3328
+ return JSON.parse(String(row["metadata"]));
3329
+ } catch {
3330
+ return void 0;
3331
+ }
3332
+ })() : void 0
3333
+ };
3334
+ }
3335
+ async function loadGraphFromDB(graph, db) {
3336
+ for (const table of ALL_NODE_TABLES) {
3337
+ const kind = TABLE_TO_KIND[table];
3338
+ if (!kind) continue;
3339
+ let rows = [];
3340
+ try {
3341
+ rows = await db.query(`MATCH (n:${table}) RETURN n.id, n.name, n.file_path, n.start_line, n.end_line, n.exported, n.content, n.metadata`);
3342
+ } catch {
3343
+ continue;
3344
+ }
3345
+ for (const row of rows) {
3346
+ const node = parseRow({
3347
+ id: row["n.id"],
3348
+ name: row["n.name"],
3349
+ file_path: row["n.file_path"],
3350
+ start_line: row["n.start_line"],
3351
+ end_line: row["n.end_line"],
3352
+ exported: row["n.exported"],
3353
+ content: row["n.content"],
3354
+ metadata: row["n.metadata"]
3355
+ }, kind);
3356
+ if (node.id && node.name) graph.addNode(node);
3357
+ }
3358
+ }
3359
+ try {
3360
+ const edgeRows = await db.query(
3361
+ `MATCH (a)-[e:code_edges]->(b) RETURN a.id, b.id, e.kind, e.weight, e.label`
3362
+ );
3363
+ for (const row of edgeRows) {
3364
+ const sourceId = String(row["a.id"] ?? "");
3365
+ const targetId = String(row["b.id"] ?? "");
3366
+ const kind = String(row["e.kind"] ?? "");
3367
+ if (!sourceId || !targetId || !kind) continue;
3368
+ const edge = {
3369
+ id: `${sourceId}::${kind}::${targetId}`,
3370
+ source: sourceId,
3371
+ target: targetId,
3372
+ kind,
3373
+ weight: row["e.weight"] != null ? Number(row["e.weight"]) : void 0,
3374
+ label: row["e.label"] ? String(row["e.label"]) : void 0
3375
+ };
3376
+ graph.addEdge(edge);
3377
+ }
3378
+ } catch {
3379
+ }
3380
+ }
3381
+
3382
+ // src/multi-repo/group-sync.ts
3383
+ function extractContracts(graph, repoName, repoPath) {
3384
+ const contracts = [];
3385
+ for (const node of graph.allNodes()) {
3386
+ if (node.exported === true && ["function", "class", "interface", "method", "type_alias", "constant", "enum", "struct", "trait"].includes(node.kind)) {
3387
+ contracts.push({
3388
+ repoName,
3389
+ repoPath,
3390
+ kind: "export",
3391
+ name: node.name,
3392
+ nodeId: node.id,
3393
+ nodeKind: node.kind,
3394
+ filePath: node.filePath,
3395
+ signature: node.content?.split("\n")[0]?.trim()
3396
+ });
3397
+ }
3398
+ if (node.kind === "route") {
3399
+ contracts.push({
3400
+ repoName,
3401
+ repoPath,
3402
+ kind: "route",
3403
+ name: node.name,
3404
+ nodeId: node.id,
3405
+ nodeKind: node.kind,
3406
+ filePath: node.filePath,
3407
+ signature: node.content?.split("\n")[0]?.trim()
3408
+ });
3409
+ }
3410
+ if (["interface", "type_alias"].includes(node.kind)) {
3411
+ const nameLower = node.name.toLowerCase();
3412
+ if (nameLower.includes("event") || nameLower.includes("message")) {
3413
+ contracts.push({
3414
+ repoName,
3415
+ repoPath,
3416
+ kind: "event",
3417
+ name: node.name,
3418
+ nodeId: node.id,
3419
+ nodeKind: node.kind,
3420
+ filePath: node.filePath
3421
+ });
3422
+ } else if (nameLower.includes("schema") || nameLower.includes("dto") || nameLower.includes("request") || nameLower.includes("response")) {
3423
+ contracts.push({
3424
+ repoName,
3425
+ repoPath,
3426
+ kind: "schema",
3427
+ name: node.name,
3428
+ nodeId: node.id,
3429
+ nodeKind: node.kind,
3430
+ filePath: node.filePath
3431
+ });
3432
+ }
3433
+ }
3434
+ }
3435
+ return contracts;
3436
+ }
3437
+ function matchContracts(allContracts) {
3438
+ const links = [];
3439
+ const byRepo = /* @__PURE__ */ new Map();
3440
+ for (const c of allContracts) {
3441
+ const arr = byRepo.get(c.repoName) ?? [];
3442
+ arr.push(c);
3443
+ byRepo.set(c.repoName, arr);
3444
+ }
3445
+ const repoNames = [...byRepo.keys()];
3446
+ for (let i = 0; i < repoNames.length; i++) {
3447
+ for (let j = 0; j < repoNames.length; j++) {
3448
+ if (i === j) continue;
3449
+ const providerContracts = byRepo.get(repoNames[i]);
3450
+ const consumerContracts = byRepo.get(repoNames[j]);
3451
+ const consumerByName = /* @__PURE__ */ new Map();
3452
+ for (const c of consumerContracts) consumerByName.set(c.name, c);
3453
+ for (const provider of providerContracts) {
3454
+ const consumer = consumerByName.get(provider.name);
3455
+ if (consumer) {
3456
+ const sameKind = provider.kind === consumer.kind;
3457
+ links.push({
3458
+ providerRepo: provider.repoName,
3459
+ providerContract: provider.name,
3460
+ consumerRepo: consumer.repoName,
3461
+ consumerContract: consumer.name,
3462
+ matchKind: provider.kind === "route" ? "route-match" : "name-match",
3463
+ confidence: sameKind ? 0.9 : 0.6
3464
+ });
3465
+ } else {
3466
+ const providerLC = provider.name.toLowerCase();
3467
+ for (const c of consumerContracts) {
3468
+ if (c.name.toLowerCase().includes(providerLC) || providerLC.includes(c.name.toLowerCase())) {
3469
+ if (c.name.length >= 4 && provider.name.length >= 4) {
3470
+ links.push({
3471
+ providerRepo: provider.repoName,
3472
+ providerContract: provider.name,
3473
+ consumerRepo: c.repoName,
3474
+ consumerContract: c.name,
3475
+ matchKind: "name-match",
3476
+ confidence: 0.4
3477
+ });
3478
+ }
3479
+ }
3480
+ }
3481
+ }
3482
+ }
3483
+ }
3484
+ }
3485
+ const seen = /* @__PURE__ */ new Map();
3486
+ for (const link of links) {
3487
+ const key = `${link.providerRepo}:${link.providerContract}:${link.consumerRepo}:${link.consumerContract}`;
3488
+ const existing = seen.get(key);
3489
+ if (!existing || link.confidence > existing.confidence) {
3490
+ seen.set(key, link);
3491
+ }
3492
+ }
3493
+ return [...seen.values()].sort((a, b) => b.confidence - a.confidence);
3494
+ }
3495
+ async function syncGroup(group) {
3496
+ const registry = loadRegistry();
3497
+ const allContracts = [];
3498
+ for (const member of group.members) {
3499
+ const regEntry = registry.find((r) => r.name === member.registryName);
3500
+ if (!regEntry) {
3501
+ logger_default.warn(` \u26A0 Registry entry "${member.registryName}" not found \u2014 skipping ${member.groupPath}`);
3502
+ continue;
3503
+ }
3504
+ const dbPath = path6.join(regEntry.path, ".code-intel", "graph.db");
3505
+ if (!fs6.existsSync(dbPath)) {
3506
+ logger_default.warn(` \u26A0 No index at ${dbPath} \u2014 run \`code-intel analyze ${regEntry.path}\` first`);
3507
+ continue;
3508
+ }
3509
+ const graph = createKnowledgeGraph();
3510
+ const db = new DbManager(dbPath);
3511
+ try {
3512
+ await db.init();
3513
+ await loadGraphFromDB(graph, db);
3514
+ db.close();
3515
+ } catch (err) {
3516
+ db.close();
3517
+ logger_default.warn(` \u26A0 Could not load graph for "${member.registryName}": ${err instanceof Error ? err.message : err}`);
3518
+ continue;
3519
+ }
3520
+ const contracts = extractContracts(graph, member.registryName, regEntry.path);
3521
+ logger_default.info(` \u2713 ${member.registryName} (${member.groupPath}): ${contracts.length} contracts`);
3522
+ allContracts.push(...contracts);
3523
+ }
3524
+ const links = matchContracts(allContracts);
3525
+ return {
3526
+ groupName: group.name,
3527
+ syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
3528
+ memberCount: group.members.length,
3529
+ contracts: allContracts,
3530
+ links
3531
+ };
3532
+ }
3533
+ async function queryGroup(group, query, limit = 20) {
3534
+ const registry = loadRegistry();
3535
+ const perRepo = [];
3536
+ const allRankings = [];
3537
+ for (const member of group.members) {
3538
+ const regEntry = registry.find((r) => r.name === member.registryName);
3539
+ if (!regEntry) continue;
3540
+ const dbPath = path6.join(regEntry.path, ".code-intel", "graph.db");
3541
+ if (!fs6.existsSync(dbPath)) continue;
3542
+ const graph = createKnowledgeGraph();
3543
+ const db = new DbManager(dbPath);
3544
+ try {
3545
+ await db.init();
3546
+ await loadGraphFromDB(graph, db);
3547
+ db.close();
3548
+ } catch {
3549
+ db.close();
3550
+ continue;
3551
+ }
3552
+ const results = textSearch(graph, query, limit);
3553
+ const taggedResults = results.map((r) => ({
3554
+ ...r,
3555
+ snippet: `[${member.registryName}] ${r.snippet ?? ""}`.trim()
3556
+ }));
3557
+ perRepo.push({
3558
+ repoName: member.registryName,
3559
+ repoPath: regEntry.path,
3560
+ groupPath: member.groupPath,
3561
+ results: taggedResults
3562
+ });
3563
+ allRankings.push(taggedResults);
3564
+ }
3565
+ const merged = reciprocalRankFusion(...allRankings).slice(0, limit);
3566
+ return { perRepo, merged };
3567
+ }
3568
+ function createMcpServer(graph, repoName, workspaceRoot) {
3569
+ const server = new Server(
3570
+ { name: "code-intel", version: "0.1.0" },
3571
+ { capabilities: { tools: {}, resources: {} } }
3572
+ );
3573
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
3574
+ tools: [
3575
+ // ── Core repo tools ──────────────────────────────────────────────────
3576
+ {
3577
+ name: "repos",
3578
+ description: "List all indexed repositories with node and edge counts",
3579
+ inputSchema: { type: "object", properties: {} }
3580
+ },
3581
+ {
3582
+ name: "overview",
3583
+ description: "Repository summary: total nodes/edges and a full breakdown of node and edge counts by kind. Use this first to understand the shape of the codebase.",
3584
+ inputSchema: { type: "object", properties: {} }
3585
+ },
3586
+ // ── Search & inspect ─────────────────────────────────────────────────
3587
+ {
3588
+ name: "search",
3589
+ description: "BM25 keyword search across all indexed symbols \u2014 functions, classes, files, routes, etc.",
3590
+ inputSchema: {
3591
+ type: "object",
3592
+ properties: {
3593
+ query: { type: "string", description: "Search query (symbol name, keyword, or partial match)" },
3594
+ limit: { type: "number", description: "Max results to return (default: 20)" }
3595
+ },
3596
+ required: ["query"]
3597
+ }
3598
+ },
3599
+ {
3600
+ name: "inspect",
3601
+ description: "360\xB0 view of a symbol: definition location, callers, callees, heritage (extends/implements), members, cluster, and source preview (first 500 chars)",
3602
+ inputSchema: {
3603
+ type: "object",
3604
+ properties: {
3605
+ symbol_name: { type: "string", description: "Exact symbol name to inspect" }
3606
+ },
3607
+ required: ["symbol_name"]
3608
+ }
3609
+ },
3610
+ {
3611
+ name: "blast_radius",
3612
+ description: "Impact analysis: traverse the call/import graph to find all symbols that depend on or are affected by a given symbol. Returns risk level (LOW / MEDIUM / HIGH).",
3613
+ inputSchema: {
3614
+ type: "object",
3615
+ properties: {
3616
+ target: { type: "string", description: "Target symbol name" },
3617
+ direction: {
3618
+ type: "string",
3619
+ enum: ["callers", "callees", "both"],
3620
+ description: "Which direction to trace \u2014 callers (who depends on it), callees (what it depends on), or both (default: both)"
3621
+ },
3622
+ max_hops: { type: "number", description: "Maximum traversal depth (default: 5)" }
3623
+ },
3624
+ required: ["target"]
3625
+ }
3626
+ },
3627
+ {
3628
+ name: "file_symbols",
3629
+ description: "List all symbols defined in a specific file \u2014 useful to understand what a file exports or contains without reading raw source.",
3630
+ inputSchema: {
3631
+ type: "object",
3632
+ properties: {
3633
+ file_path: { type: "string", description: 'File path (partial match is supported, e.g. "auth/login.ts")' }
3634
+ },
3635
+ required: ["file_path"]
3636
+ }
3637
+ },
3638
+ {
3639
+ name: "find_path",
3640
+ description: "Find the shortest call/import path between two symbols. Useful for tracing how one module reaches another.",
3641
+ inputSchema: {
3642
+ type: "object",
3643
+ properties: {
3644
+ from: { type: "string", description: "Source symbol name" },
3645
+ to: { type: "string", description: "Target symbol name" },
3646
+ max_hops: { type: "number", description: "Maximum path length to search (default: 8)" }
3647
+ },
3648
+ required: ["from", "to"]
3649
+ }
3650
+ },
3651
+ {
3652
+ name: "list_exports",
3653
+ description: "List all exported symbols in the repository. Helps AI understand the public API surface of the codebase.",
3654
+ inputSchema: {
3655
+ type: "object",
3656
+ properties: {
3657
+ kind: {
3658
+ type: "string",
3659
+ description: "Filter by node kind: function | class | interface | method | type_alias | constant | enum (optional)"
3660
+ },
3661
+ limit: { type: "number", description: "Max results (default: 100)" }
3662
+ }
3663
+ }
3664
+ },
3665
+ // ── Routes, clusters, flows ──────────────────────────────────────────
3666
+ {
3667
+ name: "routes",
3668
+ description: "List all HTTP route handler mappings detected in the codebase (kind=route or route/handler/controller files)",
3669
+ inputSchema: { type: "object", properties: {} }
3670
+ },
3671
+ {
3672
+ name: "clusters",
3673
+ description: "List detected code clusters (directory-based communities) with member counts and top 10 symbols each. Useful for understanding code organisation.",
3674
+ inputSchema: {
3675
+ type: "object",
3676
+ properties: {
3677
+ limit: { type: "number", description: "Max clusters to return (default: 50)" }
3678
+ }
3679
+ }
3680
+ },
3681
+ {
3682
+ name: "flows",
3683
+ description: "List all detected execution flows \u2014 entry points traced through the call graph. Each flow has a name, entry point, and ordered steps.",
3684
+ inputSchema: {
3685
+ type: "object",
3686
+ properties: {
3687
+ limit: { type: "number", description: "Max flows to return (default: 50)" }
3688
+ }
3689
+ }
3690
+ },
3691
+ // ── Git change impact ─────────────────────────────────────────────────
3692
+ {
3693
+ name: "detect_changes",
3694
+ description: "Git-diff impact analysis: detects which source files and line ranges changed (HEAD vs working tree or a custom diff), maps them to graph symbols, and computes the combined blast radius. Ideal for PR review or pre-commit analysis.",
3695
+ inputSchema: {
3696
+ type: "object",
3697
+ properties: {
3698
+ base_ref: {
3699
+ type: "string",
3700
+ description: 'Git ref to diff against (default: HEAD). Examples: "HEAD~1", "main", a commit SHA.'
3701
+ },
3702
+ diff_text: {
3703
+ type: "string",
3704
+ description: "Raw unified diff text. If provided, base_ref is ignored and this diff is parsed directly."
3705
+ }
3706
+ }
3707
+ }
3708
+ },
3709
+ // ── Raw query ─────────────────────────────────────────────────────────
3710
+ {
3711
+ name: "raw_query",
3712
+ description: "Execute a simplified Cypher-like graph query. Supports: name='X' (exact name match) or :kind (list nodes of a kind, max 50)",
3713
+ inputSchema: {
3714
+ type: "object",
3715
+ properties: {
3716
+ cypher: { type: "string", description: "Query string \u2014 e.g. name='runPipeline' or :function" }
3717
+ },
3718
+ required: ["cypher"]
3719
+ }
3720
+ },
3721
+ // ── Group / multi-repo tools ──────────────────────────────────────────
3722
+ {
3723
+ name: "group_list",
3724
+ description: "List all configured repository groups, or show the full membership of one group. Repository groups track multiple repos as a logical system.",
3725
+ inputSchema: {
3726
+ type: "object",
3727
+ properties: {
3728
+ name: { type: "string", description: "Group name to inspect (optional \u2014 omit to list all groups)" }
3729
+ }
3730
+ }
3731
+ },
3732
+ {
3733
+ name: "group_sync",
3734
+ description: "Extract cross-repo contracts (exports, routes, schemas, events) from every member repo in a group and detect provider\u2192consumer links via name matching and RRF scoring.",
3735
+ inputSchema: {
3736
+ type: "object",
3737
+ properties: {
3738
+ name: { type: "string", description: "Group name to sync" }
3739
+ },
3740
+ required: ["name"]
3741
+ }
3742
+ },
3743
+ {
3744
+ name: "group_contracts",
3745
+ description: "Inspect extracted contracts and confidence-ranked cross-repo links from the last group sync. Supports filtering by kind, repo, and minimum confidence.",
3746
+ inputSchema: {
3747
+ type: "object",
3748
+ properties: {
3749
+ name: { type: "string", description: "Group name" },
3750
+ kind: {
3751
+ type: "string",
3752
+ enum: ["export", "route", "schema", "event"],
3753
+ description: "Filter by contract kind (optional)"
3754
+ },
3755
+ repo: { type: "string", description: "Filter by registry name (optional)" },
3756
+ min_confidence: { type: "number", description: "Minimum link confidence 0\u20131 (default: 0)" }
3757
+ },
3758
+ required: ["name"]
3759
+ }
3760
+ },
3761
+ {
3762
+ name: "group_query",
3763
+ description: "BM25 search across all repos in a group, merged via Reciprocal Rank Fusion (RRF). Returns a unified ranked list plus per-repo breakdown.",
3764
+ inputSchema: {
3765
+ type: "object",
3766
+ properties: {
3767
+ name: { type: "string", description: "Group name" },
3768
+ query: { type: "string", description: "Search query" },
3769
+ limit: { type: "number", description: "Max results per repo (default: 10)" }
3770
+ },
3771
+ required: ["name", "query"]
3772
+ }
3773
+ },
3774
+ {
3775
+ name: "group_status",
3776
+ description: "Check index freshness and sync staleness for all repos in a group. Flags repos that have not been indexed or are stale (>24h).",
3777
+ inputSchema: {
3778
+ type: "object",
3779
+ properties: {
3780
+ name: { type: "string", description: "Group name" }
3781
+ },
3782
+ required: ["name"]
3783
+ }
3784
+ }
3785
+ ]
3786
+ }));
3787
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3788
+ const { name, arguments: args } = request.params;
3789
+ const a = args ?? {};
3790
+ switch (name) {
3791
+ // ── repos ──────────────────────────────────────────────────────────────
3792
+ case "repos": {
3793
+ const registry = loadRegistry();
3794
+ return {
3795
+ content: [{
3796
+ type: "text",
3797
+ text: JSON.stringify(
3798
+ registry.map((r) => ({ name: r.name, path: r.path, indexedAt: r.indexedAt, stats: r.stats })),
3799
+ null,
3800
+ 2
3801
+ )
3802
+ }]
3803
+ };
3804
+ }
3805
+ // ── overview ───────────────────────────────────────────────────────────
3806
+ case "overview": {
3807
+ const kindCounts = {};
3808
+ for (const node of graph.allNodes()) {
3809
+ kindCounts[node.kind] = (kindCounts[node.kind] ?? 0) + 1;
3810
+ }
3811
+ const edgeCounts = {};
3812
+ for (const edge of graph.allEdges()) {
3813
+ edgeCounts[edge.kind] = (edgeCounts[edge.kind] ?? 0) + 1;
3814
+ }
3815
+ return {
3816
+ content: [{
3817
+ type: "text",
3818
+ text: JSON.stringify({
3819
+ repo: repoName,
3820
+ stats: graph.size,
3821
+ nodeCounts: kindCounts,
3822
+ edgeCounts
3823
+ }, null, 2)
3824
+ }]
3825
+ };
3826
+ }
3827
+ // ── search ─────────────────────────────────────────────────────────────
3828
+ case "search": {
3829
+ const query = a.query;
3830
+ const limit = a.limit ?? 20;
3831
+ const results = textSearch(graph, query, limit);
3832
+ return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
3833
+ }
3834
+ // ── inspect ────────────────────────────────────────────────────────────
3835
+ case "inspect": {
3836
+ const symbolName = a.symbol_name;
3837
+ const node = findNodeByName(graph, symbolName);
3838
+ if (!node) return { content: [{ type: "text", text: `Symbol "${symbolName}" not found. Try search first.` }] };
3839
+ const incoming = [...graph.findEdgesTo(node.id)];
3840
+ const outgoing = [...graph.findEdgesFrom(node.id)];
3841
+ return {
3842
+ content: [{
3843
+ type: "text",
3844
+ text: JSON.stringify({
3845
+ node: {
3846
+ id: node.id,
3847
+ kind: node.kind,
3848
+ name: node.name,
3849
+ filePath: node.filePath,
3850
+ startLine: node.startLine,
3851
+ endLine: node.endLine,
3852
+ exported: node.exported
3853
+ },
3854
+ callers: incoming.filter((e) => e.kind === "calls").map((e) => ({
3855
+ id: e.source,
3856
+ name: graph.getNode(e.source)?.name,
3857
+ file: graph.getNode(e.source)?.filePath
3858
+ })),
3859
+ callees: outgoing.filter((e) => e.kind === "calls").map((e) => ({
3860
+ id: e.target,
3861
+ name: graph.getNode(e.target)?.name,
3862
+ file: graph.getNode(e.target)?.filePath
3863
+ })),
3864
+ imports: incoming.filter((e) => e.kind === "imports").map((e) => graph.getNode(e.source)?.name),
3865
+ importedBy: outgoing.filter((e) => e.kind === "imports").map((e) => graph.getNode(e.target)?.name),
3866
+ extends: outgoing.filter((e) => e.kind === "extends").map((e) => graph.getNode(e.target)?.name),
3867
+ implements: outgoing.filter((e) => e.kind === "implements").map((e) => graph.getNode(e.target)?.name),
3868
+ members: outgoing.filter((e) => e.kind === "has_member").map((e) => ({
3869
+ name: graph.getNode(e.target)?.name,
3870
+ kind: graph.getNode(e.target)?.kind
3871
+ })),
3872
+ cluster: incoming.filter((e) => e.kind === "belongs_to").map((e) => graph.getNode(e.target)?.name)[0],
3873
+ content: node.content?.slice(0, 500)
3874
+ }, null, 2)
3875
+ }]
3876
+ };
3877
+ }
3878
+ // ── blast_radius ───────────────────────────────────────────────────────
3879
+ case "blast_radius": {
3880
+ const target = a.target;
3881
+ const direction = a.direction ?? "both";
3882
+ const maxHops = a.max_hops ?? 5;
3883
+ const node = findNodeByName(graph, target);
3884
+ if (!node) return { content: [{ type: "text", text: `Symbol "${target}" not found.` }] };
3885
+ const affected = /* @__PURE__ */ new Set();
3886
+ const queue = [{ id: node.id, depth: 0 }];
3887
+ const visited = /* @__PURE__ */ new Set();
3888
+ while (queue.length > 0) {
3889
+ const { id, depth } = queue.shift();
3890
+ if (visited.has(id) || depth > maxHops) continue;
3891
+ visited.add(id);
3892
+ affected.add(id);
3893
+ if (direction === "callers" || direction === "both") {
3894
+ for (const edge of graph.findEdgesTo(id)) {
3895
+ if (edge.kind === "calls" || edge.kind === "imports") queue.push({ id: edge.source, depth: depth + 1 });
3896
+ }
3897
+ }
3898
+ if (direction === "callees" || direction === "both") {
3899
+ for (const edge of graph.findEdgesFrom(id)) {
3900
+ if (edge.kind === "calls" || edge.kind === "imports") queue.push({ id: edge.target, depth: depth + 1 });
3901
+ }
3902
+ }
3903
+ }
3904
+ const affectedDetails = [...affected].map((id) => {
3905
+ const n = graph.getNode(id);
3906
+ return n ? { id, name: n.name, kind: n.kind, filePath: n.filePath } : { id };
3907
+ });
3908
+ const risk = affected.size > 10 ? "HIGH" : affected.size > 5 ? "MEDIUM" : "LOW";
3909
+ return {
3910
+ content: [{
3911
+ type: "text",
3912
+ text: JSON.stringify({
3913
+ target: node.name,
3914
+ affectedCount: affected.size,
3915
+ riskLevel: risk,
3916
+ affected: affectedDetails
3917
+ }, null, 2)
3918
+ }]
3919
+ };
3920
+ }
3921
+ // ── file_symbols ───────────────────────────────────────────────────────
3922
+ case "file_symbols": {
3923
+ const filePath = a.file_path;
3924
+ const matches = [];
3925
+ for (const node of graph.allNodes()) {
3926
+ if (node.filePath && node.filePath.includes(filePath)) {
3927
+ matches.push({ kind: node.kind, name: node.name, startLine: node.startLine, exported: node.exported });
3928
+ }
3929
+ }
3930
+ if (matches.length === 0) {
3931
+ return { content: [{ type: "text", text: `No symbols found for file path matching "${filePath}".` }] };
3932
+ }
3933
+ matches.sort((a2, b) => (a2.startLine ?? 0) - (b.startLine ?? 0));
3934
+ return { content: [{ type: "text", text: JSON.stringify(matches, null, 2) }] };
3935
+ }
3936
+ // ── find_path ──────────────────────────────────────────────────────────
3937
+ case "find_path": {
3938
+ const fromName = a.from;
3939
+ const toName = a.to;
3940
+ const maxHops = a.max_hops ?? 8;
3941
+ const fromNode = findNodeByName(graph, fromName);
3942
+ const toNode = findNodeByName(graph, toName);
3943
+ if (!fromNode) return { content: [{ type: "text", text: `Source symbol "${fromName}" not found.` }] };
3944
+ if (!toNode) return { content: [{ type: "text", text: `Target symbol "${toName}" not found.` }] };
3945
+ const queue = [{ id: fromNode.id, path: [fromNode.id] }];
3946
+ const visited = /* @__PURE__ */ new Set();
3947
+ let foundPath = null;
3948
+ while (queue.length > 0) {
3949
+ const { id, path: currentPath } = queue.shift();
3950
+ if (visited.has(id)) continue;
3951
+ visited.add(id);
3952
+ if (id === toNode.id) {
3953
+ foundPath = currentPath;
3954
+ break;
3955
+ }
3956
+ if (currentPath.length > maxHops) continue;
3957
+ for (const edge of graph.findEdgesFrom(id)) {
3958
+ if ((edge.kind === "calls" || edge.kind === "imports") && !visited.has(edge.target)) {
3959
+ queue.push({ id: edge.target, path: [...currentPath, edge.target] });
3960
+ }
3961
+ }
3962
+ }
3963
+ if (!foundPath) {
3964
+ return { content: [{ type: "text", text: `No path found from "${fromName}" to "${toName}" within ${maxHops} hops.` }] };
3965
+ }
3966
+ const pathDetails = foundPath.map((id) => {
3967
+ const n = graph.getNode(id);
3968
+ return n ? { id, name: n.name, kind: n.kind, filePath: n.filePath } : { id };
3969
+ });
3970
+ return {
3971
+ content: [{
3972
+ type: "text",
3973
+ text: JSON.stringify({ from: fromName, to: toName, hops: foundPath.length - 1, path: pathDetails }, null, 2)
3974
+ }]
3975
+ };
3976
+ }
3977
+ // ── list_exports ───────────────────────────────────────────────────────
3978
+ case "list_exports": {
3979
+ const kindFilter = a.kind;
3980
+ const limit = a.limit ?? 100;
3981
+ const exports$1 = [];
3982
+ for (const node of graph.allNodes()) {
3983
+ if (!node.exported) continue;
3984
+ if (kindFilter && node.kind !== kindFilter) continue;
3985
+ exports$1.push({ kind: node.kind, name: node.name, filePath: node.filePath, startLine: node.startLine });
3986
+ if (exports$1.length >= limit) break;
3987
+ }
3988
+ return { content: [{ type: "text", text: JSON.stringify({ total: exports$1.length, exports: exports$1 }, null, 2) }] };
3989
+ }
3990
+ // ── routes ─────────────────────────────────────────────────────────────
3991
+ case "routes": {
3992
+ const routes = [];
3993
+ for (const node of graph.allNodes()) {
3994
+ if (node.kind === "route" || node.kind === "function" && /route|handler|controller/i.test(node.filePath)) {
3995
+ routes.push({ name: node.name, filePath: node.filePath, startLine: node.startLine });
3996
+ }
3997
+ }
3998
+ return { content: [{ type: "text", text: JSON.stringify(routes, null, 2) }] };
3999
+ }
4000
+ // ── clusters ───────────────────────────────────────────────────────────
4001
+ case "clusters": {
4002
+ const limit = a.limit ?? 50;
4003
+ const clusters = [];
4004
+ for (const node of graph.allNodes()) {
4005
+ if (node.kind === "cluster") {
4006
+ const members = [];
4007
+ for (const edge of graph.findEdgesTo(node.id)) {
4008
+ if (edge.kind === "belongs_to") {
4009
+ const member = graph.getNode(edge.source);
4010
+ if (member && member.kind !== "cluster") {
4011
+ members.push({ name: member.name, kind: member.kind });
4012
+ }
4013
+ }
4014
+ }
4015
+ clusters.push({
4016
+ id: node.id,
4017
+ name: node.name,
4018
+ memberCount: node.metadata?.memberCount ?? members.length,
4019
+ topSymbols: members.slice(0, 10)
4020
+ });
4021
+ if (clusters.length >= limit) break;
4022
+ }
4023
+ }
4024
+ return { content: [{ type: "text", text: JSON.stringify(clusters, null, 2) }] };
4025
+ }
4026
+ // ── flows ──────────────────────────────────────────────────────────────
4027
+ case "flows": {
4028
+ const limit = a.limit ?? 50;
4029
+ const flows = [];
4030
+ for (const node of graph.allNodes()) {
4031
+ if (node.kind === "flow") {
4032
+ const steps = node.metadata?.steps;
4033
+ flows.push({
4034
+ id: node.id,
4035
+ name: node.name,
4036
+ entryPoint: node.metadata?.entryPoint,
4037
+ steps: steps ?? [],
4038
+ stepCount: Array.isArray(steps) ? steps.length : 0
4039
+ });
4040
+ if (flows.length >= limit) break;
4041
+ }
4042
+ }
4043
+ return { content: [{ type: "text", text: JSON.stringify(flows, null, 2) }] };
4044
+ }
4045
+ // ── detect_changes ─────────────────────────────────────────────────────
4046
+ case "detect_changes": {
4047
+ const baseRef = a.base_ref ?? "HEAD";
4048
+ const diffTextInput = a.diff_text;
4049
+ let diffText;
4050
+ const repoRoot = workspaceRoot ?? process.cwd();
4051
+ if (diffTextInput) {
4052
+ diffText = diffTextInput;
4053
+ } else {
4054
+ try {
4055
+ diffText = execSync(`git diff ${baseRef}`, { cwd: repoRoot, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
4056
+ if (!diffText.trim()) {
4057
+ diffText = execSync(`git diff HEAD`, { cwd: repoRoot, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
4058
+ }
4059
+ } catch {
4060
+ return { content: [{ type: "text", text: `Could not run git diff in ${repoRoot}. Ensure the path is a Git repository.` }] };
4061
+ }
4062
+ }
4063
+ if (!diffText.trim()) {
4064
+ return { content: [{ type: "text", text: "No changes detected in git diff." }] };
4065
+ }
4066
+ const changedFiles = parseDiff(diffText);
4067
+ const hitNodes = /* @__PURE__ */ new Set();
4068
+ for (const { filePath: changedFile, changedLines } of changedFiles) {
4069
+ for (const node of graph.allNodes()) {
4070
+ if (!node.filePath) continue;
4071
+ const normNode = node.filePath.replace(repoRoot + "/", "").replace(repoRoot + path6.sep, "");
4072
+ const normChanged = changedFile.replace(/^a\/|^b\//, "");
4073
+ if (!normNode.endsWith(normChanged) && !normChanged.endsWith(normNode)) continue;
4074
+ if (node.startLine !== void 0 && node.endLine !== void 0) {
4075
+ const overlaps = changedLines.some((l) => l >= node.startLine && l <= node.endLine);
4076
+ if (overlaps) hitNodes.add(node.id);
4077
+ } else if (node.startLine !== void 0) {
4078
+ const overlaps = changedLines.some((l) => Math.abs(l - node.startLine) <= 3);
4079
+ if (overlaps) hitNodes.add(node.id);
4080
+ }
4081
+ }
4082
+ }
4083
+ const allAffected = /* @__PURE__ */ new Set();
4084
+ for (const startId of hitNodes) {
4085
+ const queue = [{ id: startId, depth: 0 }];
4086
+ const visited = /* @__PURE__ */ new Set();
4087
+ while (queue.length > 0) {
4088
+ const { id, depth } = queue.shift();
4089
+ if (visited.has(id) || depth > 5) continue;
4090
+ visited.add(id);
4091
+ allAffected.add(id);
4092
+ for (const edge of graph.findEdgesTo(id)) {
4093
+ if (edge.kind === "calls" || edge.kind === "imports") queue.push({ id: edge.source, depth: depth + 1 });
4094
+ }
4095
+ }
4096
+ }
4097
+ const changedSymbols = [...hitNodes].map((id) => {
4098
+ const n = graph.getNode(id);
4099
+ return n ? { id, name: n.name, kind: n.kind, filePath: n.filePath } : { id };
4100
+ });
4101
+ const affectedSymbols = [...allAffected].filter((id) => !hitNodes.has(id)).map((id) => {
4102
+ const n = graph.getNode(id);
4103
+ return n ? { id, name: n.name, kind: n.kind, filePath: n.filePath } : { id };
4104
+ });
4105
+ const risk = allAffected.size > 10 ? "HIGH" : allAffected.size > 4 ? "MEDIUM" : "LOW";
4106
+ return {
4107
+ content: [{
4108
+ type: "text",
4109
+ text: JSON.stringify({
4110
+ baseRef,
4111
+ changedFiles: changedFiles.map((f) => f.filePath),
4112
+ directlyChangedSymbols: changedSymbols,
4113
+ transitivelyAffectedSymbols: affectedSymbols,
4114
+ totalAffected: allAffected.size,
4115
+ riskLevel: risk
4116
+ }, null, 2)
4117
+ }]
4118
+ };
4119
+ }
4120
+ // ── raw_query ──────────────────────────────────────────────────────────
4121
+ case "raw_query": {
4122
+ const q = a.cypher;
4123
+ const nameMatch = q?.match(/name\s*=\s*['"]([^'"]+)['"]/i);
4124
+ if (nameMatch) {
4125
+ const results = [];
4126
+ for (const node of graph.allNodes()) {
4127
+ if (node.name === nameMatch[1]) results.push(node);
4128
+ }
4129
+ return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
4130
+ }
4131
+ const kindMatch = q?.match(/:\s*(\w+)/);
4132
+ if (kindMatch) {
4133
+ const results = [];
4134
+ for (const node of graph.allNodes()) {
4135
+ if (node.kind === kindMatch[1]) results.push(node);
4136
+ if (results.length >= 50) break;
4137
+ }
4138
+ return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
4139
+ }
4140
+ return { content: [{ type: "text", text: "Query not recognized. Use name='X' or :kind syntax." }] };
4141
+ }
4142
+ // ── group_list ─────────────────────────────────────────────────────────
4143
+ case "group_list": {
4144
+ const groupName = a.name;
4145
+ if (groupName) {
4146
+ const group = loadGroup(groupName);
4147
+ if (!group) return { content: [{ type: "text", text: `Group "${groupName}" not found.` }] };
4148
+ return { content: [{ type: "text", text: JSON.stringify(group, null, 2) }] };
4149
+ }
4150
+ const groups = listGroups();
4151
+ return {
4152
+ content: [{
4153
+ type: "text",
4154
+ text: JSON.stringify(
4155
+ groups.map((g) => ({ name: g.name, createdAt: g.createdAt, lastSync: g.lastSync, memberCount: g.members.length, members: g.members })),
4156
+ null,
4157
+ 2
4158
+ )
4159
+ }]
4160
+ };
4161
+ }
4162
+ // ── group_sync ─────────────────────────────────────────────────────────
4163
+ case "group_sync": {
4164
+ const groupName = a.name;
4165
+ const group = loadGroup(groupName);
4166
+ if (!group) return { content: [{ type: "text", text: `Group "${groupName}" not found.` }] };
4167
+ if (group.members.length === 0) return { content: [{ type: "text", text: `Group "${groupName}" has no members.` }] };
4168
+ const result = await syncGroup(group);
4169
+ saveSyncResult(result);
4170
+ group.lastSync = result.syncedAt;
4171
+ saveGroup(group);
4172
+ return {
4173
+ content: [{
4174
+ type: "text",
4175
+ text: JSON.stringify({
4176
+ groupName: result.groupName,
4177
+ syncedAt: result.syncedAt,
4178
+ memberCount: result.memberCount,
4179
+ contractCount: result.contracts.length,
4180
+ linkCount: result.links.length,
4181
+ topLinks: result.links.slice(0, 20)
4182
+ }, null, 2)
4183
+ }]
4184
+ };
4185
+ }
4186
+ // ── group_contracts ────────────────────────────────────────────────────
4187
+ case "group_contracts": {
4188
+ const groupName = a.name;
4189
+ const kindFilter = a.kind;
4190
+ const repoFilter = a.repo;
4191
+ const minConf = a.min_confidence ?? 0;
4192
+ const result = loadSyncResult(groupName);
4193
+ if (!result) return { content: [{ type: "text", text: `No sync data for group "${groupName}". Run group_sync first.` }] };
4194
+ let contracts = result.contracts;
4195
+ if (kindFilter) contracts = contracts.filter((c) => c.kind === kindFilter);
4196
+ if (repoFilter) contracts = contracts.filter((c) => c.repoName === repoFilter);
4197
+ let links = result.links.filter((l) => l.confidence >= minConf);
4198
+ if (repoFilter) links = links.filter((l) => l.providerRepo === repoFilter || l.consumerRepo === repoFilter);
4199
+ return {
4200
+ content: [{
4201
+ type: "text",
4202
+ text: JSON.stringify({ syncedAt: result.syncedAt, contracts, links }, null, 2)
4203
+ }]
4204
+ };
4205
+ }
4206
+ // ── group_query ────────────────────────────────────────────────────────
4207
+ case "group_query": {
4208
+ const groupName = a.name;
4209
+ const query = a.query;
4210
+ const limit = a.limit ?? 10;
4211
+ const group = loadGroup(groupName);
4212
+ if (!group) return { content: [{ type: "text", text: `Group "${groupName}" not found.` }] };
4213
+ const { perRepo, merged } = await queryGroup(group, query, limit);
4214
+ return {
4215
+ content: [{
4216
+ type: "text",
4217
+ text: JSON.stringify({ query, merged, perRepo }, null, 2)
4218
+ }]
4219
+ };
4220
+ }
4221
+ // ── group_status ───────────────────────────────────────────────────────
4222
+ case "group_status": {
4223
+ const groupName = a.name;
4224
+ const group = loadGroup(groupName);
4225
+ if (!group) return { content: [{ type: "text", text: `Group "${groupName}" not found.` }] };
4226
+ const registry = loadRegistry();
4227
+ const now = Date.now();
4228
+ const memberStatus = group.members.map((m) => {
4229
+ const regEntry = registry.find((r) => r.name === m.registryName);
4230
+ if (!regEntry) return { groupPath: m.groupPath, registryName: m.registryName, status: "NOT_IN_REGISTRY" };
4231
+ const meta = loadMetadata(regEntry.path);
4232
+ if (!meta) return { groupPath: m.groupPath, registryName: m.registryName, repoPath: regEntry.path, status: "NOT_INDEXED" };
4233
+ const ageMin = Math.round((now - new Date(meta.indexedAt).getTime()) / 6e4);
4234
+ const stale = ageMin > 1440;
4235
+ return {
4236
+ groupPath: m.groupPath,
4237
+ registryName: m.registryName,
4238
+ repoPath: regEntry.path,
4239
+ indexedAt: meta.indexedAt,
4240
+ ageMinutes: ageMin,
4241
+ status: stale ? "STALE" : "OK",
4242
+ stats: meta.stats
4243
+ };
4244
+ });
4245
+ const syncAge = group.lastSync ? Math.round((now - new Date(group.lastSync).getTime()) / 6e4) : null;
4246
+ return {
4247
+ content: [{
4248
+ type: "text",
4249
+ text: JSON.stringify({
4250
+ group: groupName,
4251
+ lastSync: group.lastSync ?? null,
4252
+ syncAgeMinutes: syncAge,
4253
+ members: memberStatus
4254
+ }, null, 2)
4255
+ }]
4256
+ };
4257
+ }
4258
+ default:
4259
+ return { content: [{ type: "text", text: `Unknown tool: ${name}` }] };
4260
+ }
4261
+ });
4262
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
4263
+ resources: [
4264
+ { uri: `codeintel://repo/${repoName}/overview`, name: `${repoName} Overview`, mimeType: "application/json" },
4265
+ { uri: `codeintel://repo/${repoName}/clusters`, name: `${repoName} Clusters`, mimeType: "application/json" },
4266
+ { uri: `codeintel://repo/${repoName}/flows`, name: `${repoName} Flows`, mimeType: "application/json" }
4267
+ ]
4268
+ }));
4269
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
4270
+ const { uri } = request.params;
4271
+ if (uri.endsWith("/overview")) {
4272
+ const kindCounts = {};
4273
+ for (const node of graph.allNodes()) {
4274
+ kindCounts[node.kind] = (kindCounts[node.kind] ?? 0) + 1;
4275
+ }
4276
+ return { contents: [{ uri, mimeType: "application/json", text: JSON.stringify({ repo: repoName, stats: graph.size, nodeCounts: kindCounts }) }] };
4277
+ }
4278
+ if (uri.endsWith("/clusters")) {
4279
+ const clusters = [];
4280
+ for (const node of graph.allNodes()) {
4281
+ if (node.kind === "cluster") clusters.push({ id: node.id, name: node.name, memberCount: node.metadata?.memberCount });
4282
+ }
4283
+ return { contents: [{ uri, mimeType: "application/json", text: JSON.stringify(clusters) }] };
4284
+ }
4285
+ if (uri.endsWith("/flows")) {
4286
+ const flows = [];
4287
+ for (const node of graph.allNodes()) {
4288
+ if (node.kind === "flow") flows.push({ id: node.id, name: node.name, steps: node.metadata?.steps, entryPoint: node.metadata?.entryPoint });
4289
+ }
4290
+ return { contents: [{ uri, mimeType: "application/json", text: JSON.stringify(flows) }] };
4291
+ }
4292
+ throw new Error(`Unknown resource: ${uri}`);
4293
+ });
4294
+ return server;
4295
+ }
4296
+ async function startMcpStdio(graph, repoName, workspaceRoot) {
4297
+ const server = createMcpServer(graph, repoName, workspaceRoot);
4298
+ const transport = new StdioServerTransport();
4299
+ await server.connect(transport);
4300
+ }
4301
+ function findNodeByName(graph, name) {
4302
+ for (const node of graph.allNodes()) {
4303
+ if (node.name === name) return node;
4304
+ }
4305
+ return void 0;
4306
+ }
4307
+ function parseDiff(diffText) {
4308
+ const result = [];
4309
+ let currentFile = null;
4310
+ let currentNewLine = 0;
4311
+ const changedLinesMap = /* @__PURE__ */ new Map();
4312
+ for (const raw of diffText.split("\n")) {
4313
+ const fileMatch = raw.match(/^\+\+\+ b\/(.+)/);
4314
+ if (fileMatch) {
4315
+ currentFile = fileMatch[1];
4316
+ if (!changedLinesMap.has(currentFile)) changedLinesMap.set(currentFile, []);
4317
+ continue;
4318
+ }
4319
+ const hunkMatch = raw.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
4320
+ if (hunkMatch) {
4321
+ currentNewLine = parseInt(hunkMatch[1], 10);
4322
+ continue;
4323
+ }
4324
+ if (!currentFile) continue;
4325
+ if (raw.startsWith("+") && !raw.startsWith("+++")) {
4326
+ changedLinesMap.get(currentFile).push(currentNewLine);
4327
+ currentNewLine++;
4328
+ } else if (raw.startsWith("-") && !raw.startsWith("---")) ; else if (!raw.startsWith("\\")) {
4329
+ currentNewLine++;
4330
+ }
4331
+ }
4332
+ for (const [filePath, changedLines] of changedLinesMap) {
4333
+ result.push({ filePath, changedLines });
4334
+ }
4335
+ return result;
4336
+ }
4337
+
4338
+ // src/storage/graph-loader.ts
4339
+ async function loadGraphToDB(graph, dbManager) {
4340
+ for (const table of ALL_NODE_TABLES) {
4341
+ await dbManager.execute(getCreateNodeTableDDL(table));
4342
+ }
4343
+ const edgeDDLs = getCreateEdgeTableDDL();
4344
+ for (const ddl of edgeDDLs) {
4345
+ try {
4346
+ await dbManager.execute(ddl);
4347
+ } catch {
4348
+ }
4349
+ }
4350
+ let nodeCount = 0;
4351
+ for (const node of graph.allNodes()) {
4352
+ const table = NODE_TABLE_MAP[node.kind];
4353
+ const props = buildNodeProps(node);
4354
+ try {
4355
+ await dbManager.execute(`CREATE (:${table} ${props})`);
4356
+ nodeCount++;
4357
+ } catch {
4358
+ }
4359
+ }
4360
+ let edgeCount = 0;
4361
+ for (const edge of graph.allEdges()) {
4362
+ const sourceNode = graph.getNode(edge.source);
4363
+ const targetNode = graph.getNode(edge.target);
4364
+ if (!sourceNode || !targetNode) continue;
4365
+ const fromTable = NODE_TABLE_MAP[sourceNode.kind];
4366
+ const toTable = NODE_TABLE_MAP[targetNode.kind];
4367
+ try {
4368
+ await dbManager.execute(
4369
+ `MATCH (a:${fromTable} {id: '${escCypher(edge.source)}'}), (b:${toTable} {id: '${escCypher(edge.target)}'}) CREATE (a)-[:code_edges {kind: '${edge.kind}', weight: ${edge.weight ?? 1}, label: '${escCypher(edge.label ?? "")}'}]->(b)`
4370
+ );
4371
+ edgeCount++;
4372
+ } catch {
4373
+ }
4374
+ }
4375
+ return { nodeCount, edgeCount };
4376
+ }
4377
+ function buildNodeProps(node) {
4378
+ const parts = [
4379
+ `id: '${escCypher(node.id)}'`,
4380
+ `name: '${escCypher(node.name)}'`,
4381
+ `file_path: '${escCypher(node.filePath)}'`
4382
+ ];
4383
+ if (node.startLine !== void 0) parts.push(`start_line: ${node.startLine}`);
4384
+ if (node.endLine !== void 0) parts.push(`end_line: ${node.endLine}`);
4385
+ if (node.exported !== void 0) parts.push(`exported: ${node.exported}`);
4386
+ if (node.content) parts.push(`content: '${escCypher(node.content.slice(0, 500))}'`);
4387
+ if (node.metadata) parts.push(`metadata: '${escCypher(JSON.stringify(node.metadata))}'`);
4388
+ return `{${parts.join(", ")}}`;
4389
+ }
4390
+ function escCypher(s) {
4391
+ return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "");
4392
+ }
4393
+
4394
+ // src/http/app.ts
4395
+ init_group_registry();
4396
+ var __dirname$1 = path6.dirname(fileURLToPath(import.meta.url));
4397
+ var WEB_DIST = path6.resolve(__dirname$1, "..", "..", "..", "web", "dist");
4398
+ function createApp(graph, repoName, workspaceRoot) {
4399
+ const app = express();
4400
+ app.use(cors({ origin: true }));
4401
+ app.use(express.json({ limit: "10mb" }));
4402
+ let vectorIndex = null;
4403
+ let vectorIndexBuilding = false;
4404
+ let vectorIndexReady = false;
4405
+ async function ensureVectorIndex() {
4406
+ if (vectorIndexReady && vectorIndex) return vectorIndex;
4407
+ if (!workspaceRoot || vectorIndexBuilding) return null;
4408
+ vectorIndexBuilding = true;
4409
+ try {
4410
+ const { embedNodes: embedNodes2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
4411
+ const dbPath = getVectorDbPath(workspaceRoot);
4412
+ const db = new DbManager(dbPath);
4413
+ await db.init();
4414
+ const idx = new VectorIndex(db);
4415
+ await idx.init();
4416
+ const alreadyBuilt = await idx.isBuilt();
4417
+ if (!alreadyBuilt) {
4418
+ logger_default.info(" [vector] Building embeddings\u2026");
4419
+ const nodes = await embedNodes2(graph, {
4420
+ onProgress: (done, total) => {
4421
+ if (done % 50 === 0 || done === total) process.stdout.write(`\r [vector] ${done}/${total}`);
4422
+ }
4423
+ });
4424
+ logger_default.info("");
4425
+ await idx.buildIndex(nodes);
4426
+ logger_default.info(` [vector] Index built: ${nodes.length} embeddings`);
4427
+ } else {
4428
+ logger_default.info(" [vector] Index already exists, skipping rebuild.");
4429
+ }
4430
+ vectorIndex = idx;
4431
+ vectorIndexReady = true;
4432
+ return idx;
4433
+ } catch (err) {
4434
+ logger_default.warn(" [vector] Index build failed:", err instanceof Error ? err.message : err);
4435
+ return null;
4436
+ } finally {
4437
+ vectorIndexBuilding = false;
4438
+ }
4439
+ }
4440
+ if (workspaceRoot) {
4441
+ setImmediate(() => ensureVectorIndex().catch(() => {
4442
+ }));
4443
+ }
4444
+ app.get("/api/health", (_req, res) => {
4445
+ res.json({ status: "ok", nodes: graph.size.nodes, edges: graph.size.edges });
4446
+ });
4447
+ app.get("/api/repos", (_req, res) => {
4448
+ const registry = loadRegistry();
4449
+ if (registry.length === 0) {
4450
+ res.json([{ name: repoName, path: workspaceRoot ?? "", nodes: graph.size.nodes, edges: graph.size.edges, indexedAt: null }]);
4451
+ return;
4452
+ }
4453
+ res.json(registry.map((r) => ({
4454
+ name: r.name,
4455
+ path: r.path,
4456
+ nodes: r.stats.nodes,
4457
+ edges: r.stats.edges,
4458
+ indexedAt: r.indexedAt,
4459
+ active: r.path === workspaceRoot
4460
+ })));
4461
+ });
4462
+ async function loadRepoGraph(requestedRepo) {
4463
+ if (requestedRepo === repoName) return graph;
4464
+ const registry = loadRegistry();
4465
+ const entry = registry.find((r) => r.name === requestedRepo || r.path === requestedRepo);
4466
+ if (!entry) return null;
4467
+ const dbPath = path6.join(entry.path, ".code-intel", "graph.db");
4468
+ if (!fs6.existsSync(dbPath)) return null;
4469
+ const repoGraph = createKnowledgeGraph();
4470
+ const db = new DbManager(dbPath);
4471
+ try {
4472
+ await db.init();
4473
+ await loadGraphFromDB(repoGraph, db);
4474
+ db.close();
4475
+ return repoGraph;
4476
+ } catch {
4477
+ db.close();
4478
+ return null;
4479
+ }
4480
+ }
4481
+ app.get("/api/graph/:repo", async (req, res) => {
4482
+ const requestedRepo = decodeURIComponent(req.params.repo);
4483
+ const g = await loadRepoGraph(requestedRepo);
4484
+ if (!g) {
4485
+ res.status(404).json({ error: `Repo "${requestedRepo}" not found or not indexed. Run: code-intel analyze <path>` });
4486
+ return;
4487
+ }
4488
+ const nodes = [...g.allNodes()];
4489
+ const edges = [...g.allEdges()];
4490
+ res.json({ nodes, edges });
4491
+ });
4492
+ async function getGraphForRepo(requestedRepo) {
4493
+ if (!requestedRepo || requestedRepo === repoName) return graph;
4494
+ const g = await loadRepoGraph(requestedRepo);
4495
+ return g ?? graph;
4496
+ }
4497
+ app.post("/api/search", async (req, res) => {
4498
+ const { query, limit, repo } = req.body;
4499
+ const g = await getGraphForRepo(repo);
4500
+ const results = textSearch(g, query, limit ?? 20);
4501
+ res.json({ results });
4502
+ });
4503
+ app.post("/api/vector-search", async (req, res) => {
4504
+ const { query, limit = 10 } = req.body;
4505
+ if (!query) {
4506
+ res.status(400).json({ error: "Missing query" });
4507
+ return;
4508
+ }
4509
+ const idx = await ensureVectorIndex();
4510
+ if (!idx) {
4511
+ const results = textSearch(graph, query, limit);
4512
+ res.json({ results, source: "text-fallback", vectorReady: false });
4513
+ return;
4514
+ }
4515
+ try {
4516
+ const { pipeline } = await import('@huggingface/transformers');
4517
+ const embedder = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
4518
+ const out = await embedder(query, { pooling: "mean", normalize: true });
4519
+ const queryEmbedding = Array.from(out.data);
4520
+ const hits = await idx.search(queryEmbedding, limit);
4521
+ const results = hits.map((h) => ({
4522
+ nodeId: h.nodeId,
4523
+ name: h.name,
4524
+ kind: h.kind,
4525
+ filePath: h.filePath,
4526
+ score: h.score
4527
+ }));
4528
+ res.json({ results, source: "vector", vectorReady: true });
4529
+ } catch (err) {
4530
+ const results = textSearch(graph, query, limit);
4531
+ res.json({ results, source: "text-fallback", vectorReady: false, error: err instanceof Error ? err.message : String(err) });
4532
+ }
4533
+ });
4534
+ app.get("/api/vector-status", (_req, res) => {
4535
+ res.json({ ready: vectorIndexReady, building: vectorIndexBuilding });
4536
+ });
4537
+ app.post("/api/files/read", (req, res) => {
4538
+ const { file_path } = req.body;
4539
+ try {
4540
+ const content = fs6.readFileSync(file_path, "utf-8");
4541
+ res.json({ content });
4542
+ } catch {
4543
+ res.status(404).json({ error: "File not found" });
4544
+ }
4545
+ });
4546
+ app.post("/api/grep", (req, res) => {
4547
+ const { pattern, file_paths } = req.body;
4548
+ const results = [];
4549
+ try {
4550
+ const regex = new RegExp(pattern, "gi");
4551
+ const paths = file_paths ?? [];
4552
+ if (paths.length === 0) {
4553
+ for (const node of graph.allNodes()) {
4554
+ if (node.kind === "file" && node.content) {
4555
+ const lines = node.content.split("\n");
4556
+ for (let i = 0; i < lines.length; i++) {
4557
+ if (regex.test(lines[i])) {
4558
+ results.push({ file: node.filePath, line: i + 1, text: lines[i].trim() });
4559
+ }
4560
+ regex.lastIndex = 0;
4561
+ }
4562
+ }
4563
+ }
4564
+ }
4565
+ res.json({ results: results.slice(0, 100) });
4566
+ } catch {
4567
+ res.status(400).json({ error: "Invalid regex pattern" });
4568
+ }
4569
+ });
4570
+ app.post("/api/cypher", async (req, res) => {
4571
+ const { query: q } = req.body;
4572
+ if (!q) {
4573
+ res.status(400).json({ error: "Missing query" });
4574
+ return;
4575
+ }
4576
+ if (workspaceRoot) {
4577
+ try {
4578
+ const dbPath = getDbPath(workspaceRoot);
4579
+ const dbm = new DbManager(dbPath);
4580
+ await dbm.init();
4581
+ const rows = await dbm.query(q);
4582
+ dbm.close();
4583
+ res.json({ results: rows });
4584
+ return;
4585
+ } catch (err) {
4586
+ }
4587
+ }
4588
+ try {
4589
+ const nameMatch = q?.match(/name\s*=\s*['"]([^'"]+)['"]/i);
4590
+ if (nameMatch) {
4591
+ const name = nameMatch[1];
4592
+ const results = [];
4593
+ for (const node of graph.allNodes()) {
4594
+ if (node.name === name) {
4595
+ const incoming = [...graph.findEdgesTo(node.id)];
4596
+ const outgoing = [...graph.findEdgesFrom(node.id)];
4597
+ results.push({ node, incoming: incoming.length, outgoing: outgoing.length });
4598
+ }
4599
+ }
4600
+ res.json({ results });
4601
+ return;
4602
+ }
4603
+ const kindMatch = q?.match(/:\s*(\w+)/);
4604
+ if (kindMatch) {
4605
+ const kind = kindMatch[1];
4606
+ const results = [];
4607
+ for (const node of graph.allNodes()) {
4608
+ if (node.kind === kind) results.push(node);
4609
+ if (results.length >= 50) break;
4610
+ }
4611
+ res.json({ results });
4612
+ return;
4613
+ }
4614
+ res.json({ results: [], message: "Query not recognized." });
4615
+ } catch {
4616
+ res.status(400).json({ error: "Invalid query" });
4617
+ }
4618
+ });
4619
+ app.get("/api/nodes/:id", async (req, res) => {
4620
+ const nodeId = decodeURIComponent(req.params.id);
4621
+ const g = await getGraphForRepo(req.query.repo);
4622
+ const node = g.getNode(nodeId);
4623
+ if (!node) {
4624
+ res.status(404).json({ error: "Node not found" });
4625
+ return;
4626
+ }
4627
+ const incoming = [...g.findEdgesTo(nodeId)];
4628
+ const outgoing = [...g.findEdgesFrom(nodeId)];
4629
+ res.json({
4630
+ node,
4631
+ callers: incoming.filter((e) => e.kind === "calls").map((e) => ({
4632
+ id: e.source,
4633
+ name: g.getNode(e.source)?.name,
4634
+ weight: e.weight
4635
+ })),
4636
+ callees: outgoing.filter((e) => e.kind === "calls").map((e) => ({
4637
+ id: e.target,
4638
+ name: g.getNode(e.target)?.name,
4639
+ weight: e.weight
4640
+ })),
4641
+ imports: outgoing.filter((e) => e.kind === "imports").map((e) => ({
4642
+ id: e.target,
4643
+ name: g.getNode(e.target)?.name
4644
+ })),
4645
+ importedBy: incoming.filter((e) => e.kind === "imports").map((e) => ({
4646
+ id: e.source,
4647
+ name: g.getNode(e.source)?.name
4648
+ })),
4649
+ extends: outgoing.filter((e) => e.kind === "extends").map((e) => ({
4650
+ id: e.target,
4651
+ name: g.getNode(e.target)?.name
4652
+ })),
4653
+ implementsEdges: outgoing.filter((e) => e.kind === "implements").map((e) => ({
4654
+ id: e.target,
4655
+ name: g.getNode(e.target)?.name
4656
+ })),
4657
+ members: outgoing.filter((e) => e.kind === "has_member").map((e) => ({
4658
+ id: e.target,
4659
+ name: g.getNode(e.target)?.name,
4660
+ kind: g.getNode(e.target)?.kind
4661
+ })),
4662
+ cluster: incoming.filter((e) => e.kind === "belongs_to").map((e) => g.getNode(e.target)?.name)[0]
4663
+ });
4664
+ });
4665
+ app.post("/api/blast-radius", async (req, res) => {
4666
+ const { target, direction = "both", max_hops = 5, repo } = req.body;
4667
+ const g = await getGraphForRepo(repo);
4668
+ let targetNode = null;
4669
+ for (const node of g.allNodes()) {
4670
+ if (node.name === target || node.id === target) {
4671
+ targetNode = node;
4672
+ break;
4673
+ }
4674
+ }
4675
+ if (!targetNode) {
4676
+ res.status(404).json({ error: `Symbol "${target}" not found` });
4677
+ return;
4678
+ }
4679
+ const affected = /* @__PURE__ */ new Map();
4680
+ const queue = [{ id: targetNode.id, depth: 0 }];
4681
+ const visited = /* @__PURE__ */ new Set();
4682
+ while (queue.length > 0) {
4683
+ const { id, depth } = queue.shift();
4684
+ if (visited.has(id) || depth > max_hops) continue;
4685
+ visited.add(id);
4686
+ const node = g.getNode(id);
4687
+ if (node) affected.set(id, { name: node.name, kind: node.kind, depth });
4688
+ if (direction === "callers" || direction === "both") {
4689
+ for (const edge of g.findEdgesTo(id)) {
4690
+ if (edge.kind === "calls" || edge.kind === "imports") queue.push({ id: edge.source, depth: depth + 1 });
4691
+ }
4692
+ }
4693
+ if (direction === "callees" || direction === "both") {
4694
+ for (const edge of g.findEdgesFrom(id)) {
4695
+ if (edge.kind === "calls" || edge.kind === "imports") queue.push({ id: edge.target, depth: depth + 1 });
4696
+ }
4697
+ }
4698
+ }
4699
+ res.json({
4700
+ target: targetNode.name,
4701
+ affectedCount: [...affected.values()].filter((a) => a.depth > 0).length,
4702
+ affected: [...affected.entries()].map(([id, info]) => ({ id, ...info })).filter((a) => a.depth > 0)
4703
+ });
4704
+ });
4705
+ app.get("/api/flows", async (req, res) => {
4706
+ const g = await getGraphForRepo(req.query.repo);
4707
+ const flows = [];
4708
+ for (const node of g.allNodes()) {
4709
+ if (node.kind === "flow") flows.push({ id: node.id, name: node.name, steps: node.metadata?.steps });
4710
+ }
4711
+ res.json({ flows });
4712
+ });
4713
+ app.get("/api/clusters", async (req, res) => {
4714
+ const g = await getGraphForRepo(req.query.repo);
4715
+ const clusters = [];
4716
+ for (const node of g.allNodes()) {
4717
+ if (node.kind === "cluster") {
4718
+ clusters.push({ id: node.id, name: node.name, memberCount: node.metadata?.memberCount ?? 0 });
4719
+ }
4720
+ }
4721
+ res.json({ clusters });
4722
+ });
4723
+ app.get("/api/groups", (_req, res) => {
4724
+ const groups = listGroups();
4725
+ res.json(groups.map((g) => ({
4726
+ name: g.name,
4727
+ memberCount: g.members.length,
4728
+ lastSync: g.lastSync ?? null,
4729
+ createdAt: g.createdAt
4730
+ })));
4731
+ });
4732
+ app.get("/api/groups/:name", (req, res) => {
4733
+ const group = loadGroup(req.params.name);
4734
+ if (!group) {
4735
+ res.status(404).json({ error: "Group not found" });
4736
+ return;
4737
+ }
4738
+ res.json(group);
4739
+ });
4740
+ app.get("/api/groups/:name/contracts", (req, res) => {
4741
+ const result = loadSyncResult(req.params.name);
4742
+ if (!result) {
4743
+ res.status(404).json({ error: "No sync result. Run sync first." });
4744
+ return;
4745
+ }
4746
+ res.json(result);
4747
+ });
4748
+ app.post("/api/groups/:name/sync", async (req, res) => {
4749
+ const group = loadGroup(req.params.name);
4750
+ if (!group) {
4751
+ res.status(404).json({ error: "Group not found" });
4752
+ return;
4753
+ }
4754
+ try {
4755
+ const result = await syncGroup(group);
4756
+ saveSyncResult(result);
4757
+ group.lastSync = result.syncedAt;
4758
+ const { saveGroup: saveGroup2 } = await Promise.resolve().then(() => (init_group_registry(), group_registry_exports));
4759
+ saveGroup2(group);
4760
+ res.json(result);
4761
+ } catch (err) {
4762
+ res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
4763
+ }
4764
+ });
4765
+ app.post("/api/groups/:name/search", async (req, res) => {
4766
+ const group = loadGroup(req.params.name);
4767
+ if (!group) {
4768
+ res.status(404).json({ error: "Group not found" });
4769
+ return;
4770
+ }
4771
+ const { q, limit = 20 } = req.body;
4772
+ if (!q) {
4773
+ res.status(400).json({ error: "Missing query q" });
4774
+ return;
4775
+ }
4776
+ try {
4777
+ const { perRepo, merged } = await queryGroup(group, q, limit);
4778
+ res.json({ perRepo, merged });
4779
+ } catch (err) {
4780
+ res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
4781
+ }
4782
+ });
4783
+ app.get("/api/groups/:name/graph", async (req, res) => {
4784
+ const group = loadGroup(req.params.name);
4785
+ if (!group) {
4786
+ res.status(404).json({ error: "Group not found" });
4787
+ return;
4788
+ }
4789
+ const registry = loadRegistry();
4790
+ const mergedGraph = createKnowledgeGraph();
4791
+ for (const member of group.members) {
4792
+ const regEntry = registry.find((r) => r.name === member.registryName);
4793
+ if (!regEntry) continue;
4794
+ const dbPath = path6.join(regEntry.path, ".code-intel", "graph.db");
4795
+ if (!fs6.existsSync(dbPath)) continue;
4796
+ const db = new DbManager(dbPath);
4797
+ try {
4798
+ await db.init();
4799
+ await loadGraphFromDB(mergedGraph, db);
4800
+ db.close();
4801
+ } catch {
4802
+ db.close();
4803
+ }
4804
+ }
4805
+ res.json({ nodes: [...mergedGraph.allNodes()], edges: [...mergedGraph.allEdges()] });
4806
+ });
4807
+ if (fs6.existsSync(WEB_DIST)) {
4808
+ app.use(express.static(WEB_DIST));
4809
+ app.get("/{*path}", (_req, res) => {
4810
+ res.sendFile(path6.join(WEB_DIST, "index.html"));
4811
+ });
4812
+ }
4813
+ return app;
4814
+ }
4815
+ function startHttpServer(graph, repoName, port = 4747, workspaceRoot) {
4816
+ const app = createApp(graph, repoName, workspaceRoot);
4817
+ app.listen(port, () => {
4818
+ logger_default.info(`Code Intelligence server running at http://localhost:${port}`);
4819
+ logger_default.info(` Graph: ${graph.size.nodes} nodes, ${graph.size.edges} edges`);
4820
+ });
4821
+ }
4822
+
4823
+ // src/multi-repo/index.ts
4824
+ init_group_registry();
4825
+
4826
+ // src/multi-repo/cross-repo-search.ts
4827
+ function mergeSearchResults(...perRepoResults) {
4828
+ return reciprocalRankFusion(...perRepoResults);
4829
+ }
4830
+
4831
+ export { AstCache, BindingTracker, DbManager, addBinding, addClustersToGraph, addMember, buildCallEdges, buildHeritageEdges, classifyCall, clusterPhase, computeMRO, createApp, createKnowledgeGraph, createMcpServer, createScope, deleteGroup, detectCommunities, detectOverrides, findEntryPoints, flowPhase, generateEdgeId, generateNodeId, getAllLanguageModules, getDbPath, getLanguage, getLanguageModule, getParser, groupExists, initParser, listGroups, loadGraphToDB, loadGroup, loadMetadata, loadRegistry, loadSyncResult, mergeSearchResults, parsePhase, parseSource, queryGroup, reciprocalRankFusion, removeMember, removeRepo, resolveBinding, resolveImports, resolvePhase, runPipeline, runQuery, saveGroup, saveMetadata, saveSyncResult, scanPhase, startHttpServer, startMcpStdio, structurePhase, syncGroup, textSearch, topologicalSort, traceFlow, upsertRepo, validateDAG };
4832
+ //# sourceMappingURL=index.js.map
18
4833
  //# sourceMappingURL=index.js.map