gitnexus 1.5.3 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/README.md +10 -0
  2. package/dist/_shared/graph/types.d.ts +1 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +1 -0
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/language-detection.d.ts.map +1 -1
  7. package/dist/_shared/language-detection.js +2 -0
  8. package/dist/_shared/language-detection.js.map +1 -1
  9. package/dist/_shared/languages.d.ts +1 -0
  10. package/dist/_shared/languages.d.ts.map +1 -1
  11. package/dist/_shared/languages.js +1 -0
  12. package/dist/_shared/languages.js.map +1 -1
  13. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  14. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.js +3 -1
  16. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  17. package/dist/_shared/mro-strategy.d.ts +19 -0
  18. package/dist/_shared/mro-strategy.d.ts.map +1 -0
  19. package/dist/_shared/mro-strategy.js +2 -0
  20. package/dist/_shared/mro-strategy.js.map +1 -0
  21. package/dist/cli/ai-context.d.ts +1 -0
  22. package/dist/cli/ai-context.js +28 -4
  23. package/dist/cli/analyze.d.ts +2 -0
  24. package/dist/cli/analyze.js +30 -4
  25. package/dist/cli/group.d.ts +2 -0
  26. package/dist/cli/group.js +233 -0
  27. package/dist/cli/index.js +3 -0
  28. package/dist/cli/serve.js +4 -1
  29. package/dist/cli/setup.js +34 -3
  30. package/dist/config/ignore-service.js +8 -3
  31. package/dist/core/augmentation/engine.js +1 -1
  32. package/dist/core/git-staleness.d.ts +13 -0
  33. package/dist/core/git-staleness.js +29 -0
  34. package/dist/core/group/bridge-db.d.ts +82 -0
  35. package/dist/core/group/bridge-db.js +460 -0
  36. package/dist/core/group/bridge-schema.d.ts +27 -0
  37. package/dist/core/group/bridge-schema.js +55 -0
  38. package/dist/core/group/config-parser.d.ts +3 -0
  39. package/dist/core/group/config-parser.js +83 -0
  40. package/dist/core/group/contract-extractor.d.ts +7 -0
  41. package/dist/core/group/contract-extractor.js +1 -0
  42. package/dist/core/group/extractors/fs-utils.d.ts +10 -0
  43. package/dist/core/group/extractors/fs-utils.js +24 -0
  44. package/dist/core/group/extractors/grpc-extractor.d.ts +25 -0
  45. package/dist/core/group/extractors/grpc-extractor.js +386 -0
  46. package/dist/core/group/extractors/grpc-patterns/go.d.ts +2 -0
  47. package/dist/core/group/extractors/grpc-patterns/go.js +97 -0
  48. package/dist/core/group/extractors/grpc-patterns/index.d.ts +19 -0
  49. package/dist/core/group/extractors/grpc-patterns/index.js +46 -0
  50. package/dist/core/group/extractors/grpc-patterns/java.d.ts +2 -0
  51. package/dist/core/group/extractors/grpc-patterns/java.js +173 -0
  52. package/dist/core/group/extractors/grpc-patterns/node.d.ts +4 -0
  53. package/dist/core/group/extractors/grpc-patterns/node.js +290 -0
  54. package/dist/core/group/extractors/grpc-patterns/proto.d.ts +9 -0
  55. package/dist/core/group/extractors/grpc-patterns/proto.js +134 -0
  56. package/dist/core/group/extractors/grpc-patterns/python.d.ts +2 -0
  57. package/dist/core/group/extractors/grpc-patterns/python.js +67 -0
  58. package/dist/core/group/extractors/grpc-patterns/types.d.ts +50 -0
  59. package/dist/core/group/extractors/grpc-patterns/types.js +1 -0
  60. package/dist/core/group/extractors/http-patterns/go.d.ts +2 -0
  61. package/dist/core/group/extractors/http-patterns/go.js +215 -0
  62. package/dist/core/group/extractors/http-patterns/index.d.ts +17 -0
  63. package/dist/core/group/extractors/http-patterns/index.js +44 -0
  64. package/dist/core/group/extractors/http-patterns/java.d.ts +2 -0
  65. package/dist/core/group/extractors/http-patterns/java.js +253 -0
  66. package/dist/core/group/extractors/http-patterns/node.d.ts +4 -0
  67. package/dist/core/group/extractors/http-patterns/node.js +354 -0
  68. package/dist/core/group/extractors/http-patterns/php.d.ts +2 -0
  69. package/dist/core/group/extractors/http-patterns/php.js +70 -0
  70. package/dist/core/group/extractors/http-patterns/python.d.ts +2 -0
  71. package/dist/core/group/extractors/http-patterns/python.js +133 -0
  72. package/dist/core/group/extractors/http-patterns/types.d.ts +61 -0
  73. package/dist/core/group/extractors/http-patterns/types.js +1 -0
  74. package/dist/core/group/extractors/http-route-extractor.d.ts +21 -0
  75. package/dist/core/group/extractors/http-route-extractor.js +391 -0
  76. package/dist/core/group/extractors/manifest-extractor.d.ts +54 -0
  77. package/dist/core/group/extractors/manifest-extractor.js +235 -0
  78. package/dist/core/group/extractors/topic-extractor.d.ts +8 -0
  79. package/dist/core/group/extractors/topic-extractor.js +97 -0
  80. package/dist/core/group/extractors/topic-patterns/go.d.ts +2 -0
  81. package/dist/core/group/extractors/topic-patterns/go.js +120 -0
  82. package/dist/core/group/extractors/topic-patterns/index.d.ts +14 -0
  83. package/dist/core/group/extractors/topic-patterns/index.js +38 -0
  84. package/dist/core/group/extractors/topic-patterns/java.d.ts +2 -0
  85. package/dist/core/group/extractors/topic-patterns/java.js +80 -0
  86. package/dist/core/group/extractors/topic-patterns/node.d.ts +4 -0
  87. package/dist/core/group/extractors/topic-patterns/node.js +155 -0
  88. package/dist/core/group/extractors/topic-patterns/python.d.ts +2 -0
  89. package/dist/core/group/extractors/topic-patterns/python.js +116 -0
  90. package/dist/core/group/extractors/topic-patterns/types.d.ts +25 -0
  91. package/dist/core/group/extractors/topic-patterns/types.js +10 -0
  92. package/dist/core/group/extractors/tree-sitter-scanner.d.ts +113 -0
  93. package/dist/core/group/extractors/tree-sitter-scanner.js +94 -0
  94. package/dist/core/group/matching.d.ts +13 -0
  95. package/dist/core/group/matching.js +198 -0
  96. package/dist/core/group/normalization.d.ts +3 -0
  97. package/dist/core/group/normalization.js +115 -0
  98. package/dist/core/group/service-boundary-detector.d.ts +8 -0
  99. package/dist/core/group/service-boundary-detector.js +155 -0
  100. package/dist/core/group/service.d.ts +46 -0
  101. package/dist/core/group/service.js +160 -0
  102. package/dist/core/group/storage.d.ts +9 -0
  103. package/dist/core/group/storage.js +91 -0
  104. package/dist/core/group/sync.d.ts +21 -0
  105. package/dist/core/group/sync.js +148 -0
  106. package/dist/core/group/types.d.ts +130 -0
  107. package/dist/core/group/types.js +1 -0
  108. package/dist/core/ingestion/binding-accumulator.d.ts +212 -0
  109. package/dist/core/ingestion/binding-accumulator.js +336 -0
  110. package/dist/core/ingestion/call-processor.d.ts +155 -24
  111. package/dist/core/ingestion/call-processor.js +1129 -247
  112. package/dist/core/ingestion/class-extractors/generic.d.ts +2 -0
  113. package/dist/core/ingestion/class-extractors/generic.js +135 -0
  114. package/dist/core/ingestion/class-types.d.ts +34 -0
  115. package/dist/core/ingestion/class-types.js +1 -0
  116. package/dist/core/ingestion/cobol-processor.d.ts +1 -1
  117. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -0
  118. package/dist/core/ingestion/entry-point-scoring.js +1 -0
  119. package/dist/core/ingestion/field-types.d.ts +2 -2
  120. package/dist/core/ingestion/filesystem-walker.js +8 -0
  121. package/dist/core/ingestion/framework-detection.d.ts +1 -0
  122. package/dist/core/ingestion/framework-detection.js +1 -0
  123. package/dist/core/ingestion/heritage-processor.d.ts +8 -15
  124. package/dist/core/ingestion/heritage-processor.js +15 -28
  125. package/dist/core/ingestion/import-processor.d.ts +1 -11
  126. package/dist/core/ingestion/import-processor.js +1 -13
  127. package/dist/core/ingestion/import-resolvers/utils.js +1 -0
  128. package/dist/core/ingestion/import-resolvers/vue.d.ts +8 -0
  129. package/dist/core/ingestion/import-resolvers/vue.js +9 -0
  130. package/dist/core/ingestion/language-config.js +1 -1
  131. package/dist/core/ingestion/language-provider.d.ts +14 -3
  132. package/dist/core/ingestion/languages/c-cpp.js +168 -1
  133. package/dist/core/ingestion/languages/csharp.js +20 -0
  134. package/dist/core/ingestion/languages/dart.js +26 -4
  135. package/dist/core/ingestion/languages/go.js +22 -0
  136. package/dist/core/ingestion/languages/index.d.ts +1 -0
  137. package/dist/core/ingestion/languages/index.js +2 -0
  138. package/dist/core/ingestion/languages/java.js +17 -0
  139. package/dist/core/ingestion/languages/kotlin.js +24 -1
  140. package/dist/core/ingestion/languages/php.js +23 -11
  141. package/dist/core/ingestion/languages/python.js +9 -0
  142. package/dist/core/ingestion/languages/ruby.js +43 -0
  143. package/dist/core/ingestion/languages/rust.js +38 -0
  144. package/dist/core/ingestion/languages/swift.js +31 -0
  145. package/dist/core/ingestion/languages/typescript.d.ts +1 -0
  146. package/dist/core/ingestion/languages/typescript.js +52 -3
  147. package/dist/core/ingestion/languages/vue.d.ts +13 -0
  148. package/dist/core/ingestion/languages/vue.js +81 -0
  149. package/dist/core/ingestion/markdown-processor.d.ts +1 -1
  150. package/dist/core/ingestion/method-extractors/configs/c-cpp.d.ts +3 -0
  151. package/dist/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  152. package/dist/core/ingestion/method-extractors/configs/csharp.js +5 -1
  153. package/dist/core/ingestion/method-extractors/configs/dart.d.ts +2 -0
  154. package/dist/core/ingestion/method-extractors/configs/dart.js +376 -0
  155. package/dist/core/ingestion/method-extractors/configs/go.d.ts +2 -0
  156. package/dist/core/ingestion/method-extractors/configs/go.js +176 -0
  157. package/dist/core/ingestion/method-extractors/configs/jvm.js +14 -4
  158. package/dist/core/ingestion/method-extractors/configs/php.d.ts +2 -0
  159. package/dist/core/ingestion/method-extractors/configs/php.js +304 -0
  160. package/dist/core/ingestion/method-extractors/configs/python.d.ts +2 -0
  161. package/dist/core/ingestion/method-extractors/configs/python.js +309 -0
  162. package/dist/core/ingestion/method-extractors/configs/ruby.d.ts +2 -0
  163. package/dist/core/ingestion/method-extractors/configs/ruby.js +286 -0
  164. package/dist/core/ingestion/method-extractors/configs/rust.d.ts +2 -0
  165. package/dist/core/ingestion/method-extractors/configs/rust.js +195 -0
  166. package/dist/core/ingestion/method-extractors/configs/swift.d.ts +2 -0
  167. package/dist/core/ingestion/method-extractors/configs/swift.js +277 -0
  168. package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +85 -8
  169. package/dist/core/ingestion/method-extractors/generic.d.ts +6 -0
  170. package/dist/core/ingestion/method-extractors/generic.js +84 -17
  171. package/dist/core/ingestion/method-types.d.ts +29 -0
  172. package/dist/core/ingestion/model/field-registry.d.ts +18 -0
  173. package/dist/core/ingestion/model/field-registry.js +22 -0
  174. package/dist/core/ingestion/model/heritage-map.d.ts +70 -0
  175. package/dist/core/ingestion/model/heritage-map.js +159 -0
  176. package/dist/core/ingestion/model/index.d.ts +20 -0
  177. package/dist/core/ingestion/model/index.js +41 -0
  178. package/dist/core/ingestion/model/method-registry.d.ts +62 -0
  179. package/dist/core/ingestion/model/method-registry.js +130 -0
  180. package/dist/core/ingestion/model/registration-table.d.ts +139 -0
  181. package/dist/core/ingestion/model/registration-table.js +224 -0
  182. package/dist/core/ingestion/model/resolution-context.d.ts +93 -0
  183. package/dist/core/ingestion/model/resolution-context.js +337 -0
  184. package/dist/core/ingestion/model/resolve.d.ts +56 -0
  185. package/dist/core/ingestion/model/resolve.js +297 -0
  186. package/dist/core/ingestion/model/semantic-model.d.ts +86 -0
  187. package/dist/core/ingestion/model/semantic-model.js +120 -0
  188. package/dist/core/ingestion/model/symbol-table.d.ts +222 -0
  189. package/dist/core/ingestion/model/symbol-table.js +206 -0
  190. package/dist/core/ingestion/model/type-registry.d.ts +39 -0
  191. package/dist/core/ingestion/model/type-registry.js +62 -0
  192. package/dist/core/ingestion/mro-processor.d.ts +5 -4
  193. package/dist/core/ingestion/mro-processor.js +311 -107
  194. package/dist/core/ingestion/parsing-processor.d.ts +5 -4
  195. package/dist/core/ingestion/parsing-processor.js +224 -87
  196. package/dist/core/ingestion/pipeline-phases/cobol.d.ts +16 -0
  197. package/dist/core/ingestion/pipeline-phases/cobol.js +45 -0
  198. package/dist/core/ingestion/pipeline-phases/communities.d.ts +16 -0
  199. package/dist/core/ingestion/pipeline-phases/communities.js +62 -0
  200. package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +17 -0
  201. package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +156 -0
  202. package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +37 -0
  203. package/dist/core/ingestion/pipeline-phases/cross-file.js +63 -0
  204. package/dist/core/ingestion/pipeline-phases/index.d.ts +21 -0
  205. package/dist/core/ingestion/pipeline-phases/index.js +22 -0
  206. package/dist/core/ingestion/pipeline-phases/markdown.d.ts +17 -0
  207. package/dist/core/ingestion/pipeline-phases/markdown.js +33 -0
  208. package/dist/core/ingestion/pipeline-phases/mro.d.ts +18 -0
  209. package/dist/core/ingestion/pipeline-phases/mro.js +36 -0
  210. package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +22 -0
  211. package/dist/core/ingestion/pipeline-phases/orm-extraction.js +92 -0
  212. package/dist/core/ingestion/pipeline-phases/orm.d.ts +15 -0
  213. package/dist/core/ingestion/pipeline-phases/orm.js +74 -0
  214. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +47 -0
  215. package/dist/core/ingestion/pipeline-phases/parse-impl.js +437 -0
  216. package/dist/core/ingestion/pipeline-phases/parse.d.ts +49 -0
  217. package/dist/core/ingestion/pipeline-phases/parse.js +33 -0
  218. package/dist/core/ingestion/pipeline-phases/processes.d.ts +16 -0
  219. package/dist/core/ingestion/pipeline-phases/processes.js +143 -0
  220. package/dist/core/ingestion/pipeline-phases/routes.d.ts +21 -0
  221. package/dist/core/ingestion/pipeline-phases/routes.js +243 -0
  222. package/dist/core/ingestion/pipeline-phases/runner.d.ts +22 -0
  223. package/dist/core/ingestion/pipeline-phases/runner.js +203 -0
  224. package/dist/core/ingestion/pipeline-phases/scan.d.ts +21 -0
  225. package/dist/core/ingestion/pipeline-phases/scan.js +46 -0
  226. package/dist/core/ingestion/pipeline-phases/structure.d.ts +27 -0
  227. package/dist/core/ingestion/pipeline-phases/structure.js +35 -0
  228. package/dist/core/ingestion/pipeline-phases/tools.d.ts +20 -0
  229. package/dist/core/ingestion/pipeline-phases/tools.js +79 -0
  230. package/dist/core/ingestion/pipeline-phases/types.d.ts +79 -0
  231. package/dist/core/ingestion/pipeline-phases/types.js +37 -0
  232. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +35 -0
  233. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +174 -0
  234. package/dist/core/ingestion/pipeline.d.ts +18 -10
  235. package/dist/core/ingestion/pipeline.js +66 -1410
  236. package/dist/core/ingestion/process-processor.js +1 -1
  237. package/dist/core/ingestion/tree-sitter-queries.d.ts +5 -5
  238. package/dist/core/ingestion/tree-sitter-queries.js +90 -0
  239. package/dist/core/ingestion/type-env.d.ts +15 -2
  240. package/dist/core/ingestion/type-env.js +163 -102
  241. package/dist/core/ingestion/type-extractors/csharp.js +17 -0
  242. package/dist/core/ingestion/type-extractors/jvm.js +11 -0
  243. package/dist/core/ingestion/type-extractors/php.js +0 -55
  244. package/dist/core/ingestion/type-extractors/ruby.js +0 -32
  245. package/dist/core/ingestion/type-extractors/swift.js +13 -0
  246. package/dist/core/ingestion/type-extractors/types.d.ts +8 -8
  247. package/dist/core/ingestion/type-extractors/typescript.js +66 -69
  248. package/dist/core/ingestion/utils/ast-helpers.d.ts +32 -44
  249. package/dist/core/ingestion/utils/ast-helpers.js +157 -573
  250. package/dist/core/ingestion/utils/env.d.ts +10 -0
  251. package/dist/core/ingestion/utils/env.js +10 -0
  252. package/dist/core/ingestion/utils/graph-sort.d.ts +58 -0
  253. package/dist/core/ingestion/utils/graph-sort.js +100 -0
  254. package/dist/core/ingestion/utils/method-props.d.ts +32 -0
  255. package/dist/core/ingestion/utils/method-props.js +147 -0
  256. package/dist/core/ingestion/vue-sfc-extractor.d.ts +44 -0
  257. package/dist/core/ingestion/vue-sfc-extractor.js +94 -0
  258. package/dist/core/ingestion/workers/parse-worker.d.ts +31 -19
  259. package/dist/core/ingestion/workers/parse-worker.js +469 -200
  260. package/dist/core/lbug/lbug-adapter.d.ts +6 -0
  261. package/dist/core/lbug/lbug-adapter.js +134 -27
  262. package/dist/core/lbug/pool-adapter.d.ts +76 -0
  263. package/dist/core/lbug/pool-adapter.js +522 -0
  264. package/dist/core/run-analyze.d.ts +2 -0
  265. package/dist/core/run-analyze.js +1 -1
  266. package/dist/core/search/bm25-index.js +1 -1
  267. package/dist/core/tree-sitter/parser-loader.js +1 -0
  268. package/dist/core/wiki/graph-queries.js +1 -1
  269. package/dist/mcp/core/embedder.js +6 -5
  270. package/dist/mcp/core/lbug-adapter.d.ts +3 -63
  271. package/dist/mcp/core/lbug-adapter.js +3 -484
  272. package/dist/mcp/local/local-backend.d.ts +31 -2
  273. package/dist/mcp/local/local-backend.js +255 -46
  274. package/dist/mcp/resources.js +5 -4
  275. package/dist/mcp/staleness.d.ts +3 -13
  276. package/dist/mcp/staleness.js +2 -31
  277. package/dist/mcp/tools.js +80 -4
  278. package/dist/server/analyze-job.d.ts +2 -0
  279. package/dist/server/analyze-job.js +4 -0
  280. package/dist/server/api.d.ts +20 -1
  281. package/dist/server/api.js +306 -71
  282. package/dist/server/git-clone.d.ts +2 -1
  283. package/dist/server/git-clone.js +98 -5
  284. package/dist/storage/git.d.ts +13 -0
  285. package/dist/storage/git.js +25 -0
  286. package/dist/storage/repo-manager.js +1 -1
  287. package/package.json +9 -3
  288. package/scripts/patch-tree-sitter-swift.cjs +78 -0
  289. package/vendor/tree-sitter-proto/binding.gyp +30 -0
  290. package/vendor/tree-sitter-proto/bindings/node/binding.cc +20 -0
  291. package/vendor/tree-sitter-proto/bindings/node/index.d.ts +28 -0
  292. package/vendor/tree-sitter-proto/bindings/node/index.js +7 -0
  293. package/vendor/tree-sitter-proto/package.json +18 -0
  294. package/vendor/tree-sitter-proto/src/node-types.json +1145 -0
  295. package/vendor/tree-sitter-proto/src/parser.c +10149 -0
  296. package/vendor/tree-sitter-proto/src/tree_sitter/alloc.h +54 -0
  297. package/vendor/tree-sitter-proto/src/tree_sitter/array.h +291 -0
  298. package/vendor/tree-sitter-proto/src/tree_sitter/parser.h +266 -0
  299. package/dist/core/ingestion/named-binding-processor.d.ts +0 -18
  300. package/dist/core/ingestion/named-binding-processor.js +0 -42
  301. package/dist/core/ingestion/resolution-context.d.ts +0 -58
  302. package/dist/core/ingestion/resolution-context.js +0 -135
  303. package/dist/core/ingestion/symbol-table.d.ts +0 -79
  304. package/dist/core/ingestion/symbol-table.js +0 -115
@@ -49,6 +49,7 @@ export declare const batchInsertNodesToLbug: (nodes: Array<{
49
49
  failed: number;
50
50
  }>;
51
51
  export declare const executeQuery: (cypher: string) => Promise<any[]>;
52
+ export declare const streamQuery: (cypher: string, onRow: (row: any) => void | Promise<void>) => Promise<number>;
52
53
  /**
53
54
  * Execute a single parameterized query (prepare/execute pattern).
54
55
  * Prevents Cypher injection by binding values as parameters.
@@ -88,6 +89,11 @@ export declare const getEmbeddingTableName: () => string;
88
89
  * Safe to call multiple times — tracks loaded state via module-level ftsLoaded.
89
90
  */
90
91
  export declare const loadFTSExtension: () => Promise<void>;
92
+ /**
93
+ * Load the VECTOR extension (required before using QUERY_VECTOR_INDEX).
94
+ * Safe to call multiple times -- tracks loaded state via module-level vectorExtensionLoaded.
95
+ */
96
+ export declare const loadVectorExtension: () => Promise<void>;
91
97
  /**
92
98
  * Create a full-text search index on a table
93
99
  * @param tableName - The node table name (e.g., 'File', 'CodeSymbol')
@@ -1,5 +1,5 @@
1
1
  import fs from 'fs/promises';
2
- import { createReadStream } from 'fs';
2
+ import { createReadStream, createWriteStream } from 'fs';
3
3
  import { createInterface } from 'readline';
4
4
  import path from 'path';
5
5
  import lbug from '@ladybugdb/core';
@@ -9,6 +9,7 @@ let db = null;
9
9
  let conn = null;
10
10
  let currentDbPath = null;
11
11
  let ftsLoaded = false;
12
+ let vectorExtensionLoaded = false;
12
13
  /** Expose the current Database for pool adapter reuse in tests. */
13
14
  export const getDatabase = () => db;
14
15
  // Global session lock for operations that touch module-level lbug globals.
@@ -91,6 +92,7 @@ export const withLbugDb = async (dbPath, operation) => {
91
92
  db = null;
92
93
  currentDbPath = null;
93
94
  ftsLoaded = false;
95
+ vectorExtensionLoaded = false;
94
96
  });
95
97
  // Sleep outside the lock — no need to block others while waiting
96
98
  await new Promise((resolve) => setTimeout(resolve, DB_LOCK_RETRY_DELAY_MS * attempt));
@@ -124,6 +126,7 @@ const doInitLbug = async (dbPath) => {
124
126
  db = null;
125
127
  currentDbPath = null;
126
128
  ftsLoaded = false;
129
+ vectorExtensionLoaded = false;
127
130
  }
128
131
  // LadybugDB stores the database as a single file (not a directory).
129
132
  // If the path already exists, it must be a valid LadybugDB database file.
@@ -167,6 +170,8 @@ const doInitLbug = async (dbPath) => {
167
170
  }
168
171
  }
169
172
  }
173
+ // Load VECTOR extension for semantic search support
174
+ await loadVectorExtension();
170
175
  currentDbPath = dbPath;
171
176
  return { db, conn };
172
177
  };
@@ -210,9 +215,12 @@ export const loadGraphToLbug = async (graph, repoPath, storagePath, onProgress)
210
215
  }
211
216
  }
212
217
  // Bulk COPY relationships — split by FROM→TO label pair (LadybugDB requires it)
213
- // Stream-read the relation CSV line by line to avoid exceeding V8 max string length
218
+ // Stream-read the relation CSV line by line and write directly to per-pair
219
+ // temp files on disk. This avoids accumulating potentially millions of CSV
220
+ // lines in memory which could exceed V8 Map or array limits on large repos.
214
221
  let relHeader = '';
215
- const relsByPair = new Map();
222
+ const relsByPairMeta = new Map();
223
+ const pairWriteStreams = new Map();
216
224
  let skippedRels = 0;
217
225
  let totalValidRels = 0;
218
226
  await new Promise((resolve, reject) => {
@@ -241,33 +249,49 @@ export const loadGraphToLbug = async (graph, repoPath, storagePath, onProgress)
241
249
  return;
242
250
  }
243
251
  const pairKey = `${fromLabel}|${toLabel}`;
244
- let list = relsByPair.get(pairKey);
245
- if (!list) {
246
- list = [];
247
- relsByPair.set(pairKey, list);
252
+ let ws = pairWriteStreams.get(pairKey);
253
+ if (!ws) {
254
+ const pairCsvPath = path.join(csvDir, `rel_${fromLabel}_${toLabel}.csv`);
255
+ ws = createWriteStream(pairCsvPath, 'utf-8');
256
+ ws.write(relHeader + '\n');
257
+ pairWriteStreams.set(pairKey, ws);
258
+ relsByPairMeta.set(pairKey, { csvPath: pairCsvPath, rows: 0 });
248
259
  }
249
- list.push(line);
260
+ const ok = ws.write(line + '\n');
261
+ relsByPairMeta.get(pairKey).rows++;
250
262
  totalValidRels++;
263
+ // Handle backpressure: pause reading when the write buffer is full,
264
+ // resume when the stream drains. Prevents unbounded memory growth
265
+ // on repos with millions of relationships.
266
+ if (!ok) {
267
+ rl.pause();
268
+ ws.once('drain', () => rl.resume());
269
+ }
251
270
  });
252
271
  rl.on('close', resolve);
253
- rl.on('error', reject);
272
+ rl.on('error', (err) => {
273
+ // Destroy all open write streams to avoid resource leaks
274
+ for (const ws of pairWriteStreams.values())
275
+ ws.destroy();
276
+ reject(err);
277
+ });
254
278
  });
279
+ // Close all per-pair write streams before COPY
280
+ await Promise.all(Array.from(pairWriteStreams.values()).map((ws) => new Promise((resolve, reject) => ws.end((err) => (err ? reject(err) : resolve())))));
255
281
  const insertedRels = totalValidRels;
256
282
  const warnings = [];
257
283
  if (insertedRels > 0) {
258
- log(`Loading edges: ${insertedRels.toLocaleString()} across ${relsByPair.size} types`);
284
+ log(`Loading edges: ${insertedRels.toLocaleString()} across ${relsByPairMeta.size} types`);
259
285
  let pairIdx = 0;
260
286
  let failedPairEdges = 0;
261
- const failedPairLines = [];
262
- for (const [pairKey, lines] of relsByPair) {
287
+ const failedPairCsvPaths = new Set();
288
+ for (const [pairKey, { csvPath: pairCsvPath, rows }] of relsByPairMeta) {
263
289
  pairIdx++;
264
290
  const [fromLabel, toLabel] = pairKey.split('|');
265
- const pairCsvPath = path.join(csvDir, `rel_${fromLabel}_${toLabel}.csv`);
266
- await fs.writeFile(pairCsvPath, relHeader + '\n' + lines.join('\n'), 'utf-8');
267
291
  const normalizedPath = normalizeCopyPath(pairCsvPath);
268
292
  const copyQuery = `COPY ${REL_TABLE_NAME} FROM "${normalizedPath}" (from="${fromLabel}", to="${toLabel}", HEADER=true, ESCAPE='"', DELIM=',', QUOTE='"', PARALLEL=false, auto_detect=false)`;
269
- if (pairIdx % 5 === 0 || lines.length > 1000) {
270
- log(`Loading edges: ${pairIdx}/${relsByPair.size} types (${fromLabel} -> ${toLabel})`);
293
+ if (pairIdx % 5 === 0 || rows > 1000) {
294
+ log(`Loading edges: ${pairIdx}/${relsByPairMeta.size} types (${fromLabel} -> ${toLabel})`);
271
295
  }
272
296
  try {
273
297
  await conn.query(copyQuery);
@@ -279,19 +303,42 @@ export const loadGraphToLbug = async (graph, repoPath, storagePath, onProgress)
279
303
  }
280
304
  catch (retryErr) {
281
305
  const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
282
- warnings.push(`${fromLabel}->${toLabel} (${lines.length} edges): ${retryMsg.slice(0, 80)}`);
283
- failedPairEdges += lines.length;
284
- failedPairLines.push(...lines);
306
+ warnings.push(`${fromLabel}->${toLabel} (${rows} edges): ${retryMsg.slice(0, 80)}`);
307
+ failedPairEdges += rows;
308
+ failedPairCsvPaths.add(pairCsvPath);
285
309
  }
286
310
  }
287
- try {
288
- await fs.unlink(pairCsvPath);
311
+ // Only delete if not in failedPairCsvPaths (needed for fallback)
312
+ if (!failedPairCsvPaths.has(pairCsvPath)) {
313
+ try {
314
+ await fs.unlink(pairCsvPath);
315
+ }
316
+ catch { }
289
317
  }
290
- catch { }
291
318
  }
292
- if (failedPairLines.length > 0) {
319
+ if (failedPairCsvPaths.size > 0) {
293
320
  log(`Inserting ${failedPairEdges} edges individually (missing schema pairs)`);
294
- await fallbackRelationshipInserts([relHeader, ...failedPairLines], validTables, getNodeLabel);
321
+ // Read failed pair files and merge for fallback inserts
322
+ const allLines = [relHeader];
323
+ for (const failedPath of failedPairCsvPaths) {
324
+ try {
325
+ const content = await fs.readFile(failedPath, 'utf-8');
326
+ const lines = content.split('\n');
327
+ // Skip header line (first) and empty lines
328
+ for (let i = 1; i < lines.length; i++) {
329
+ if (lines[i].trim())
330
+ allLines.push(lines[i]);
331
+ }
332
+ }
333
+ catch { }
334
+ try {
335
+ await fs.unlink(failedPath);
336
+ }
337
+ catch { }
338
+ }
339
+ if (allLines.length > 1) {
340
+ await fallbackRelationshipInserts(allLines, validTables, getNodeLabel);
341
+ }
295
342
  }
296
343
  }
297
344
  // Cleanup all CSVs
@@ -589,6 +636,30 @@ export const executeQuery = async (cypher) => {
589
636
  const rows = await result.getAll();
590
637
  return rows;
591
638
  };
639
+ export const streamQuery = async (cypher, onRow) => {
640
+ if (!conn) {
641
+ throw new Error('LadybugDB not initialized. Call initLbug first.');
642
+ }
643
+ const queryResult = await conn.query(cypher);
644
+ const result = Array.isArray(queryResult) ? queryResult[0] : queryResult;
645
+ let rowCount = 0;
646
+ try {
647
+ while (await result.hasNext()) {
648
+ const row = await result.getNext();
649
+ await onRow(row);
650
+ rowCount++;
651
+ }
652
+ return rowCount;
653
+ }
654
+ finally {
655
+ try {
656
+ await result.close();
657
+ }
658
+ catch {
659
+ // Best-effort cleanup only.
660
+ }
661
+ }
662
+ };
592
663
  /**
593
664
  * Execute a single parameterized query (prepare/execute pattern).
594
665
  * Prevents Cypher injection by binding values as parameters.
@@ -715,6 +786,7 @@ export const closeLbug = async () => {
715
786
  }
716
787
  currentDbPath = null;
717
788
  ftsLoaded = false;
789
+ vectorExtensionLoaded = false;
718
790
  };
719
791
  export const isLbugReady = () => conn !== null && db !== null;
720
792
  /**
@@ -803,19 +875,54 @@ export const loadFTSExtension = async () => {
803
875
  throw new Error('LadybugDB not initialized. Call initLbug first.');
804
876
  }
805
877
  try {
806
- await conn.query('INSTALL fts');
878
+ // Try loading locally first (no network required)
807
879
  await conn.query('LOAD EXTENSION fts');
808
880
  ftsLoaded = true;
809
881
  }
882
+ catch {
883
+ // Fall back to install + load (requires network)
884
+ try {
885
+ await conn.query('INSTALL fts');
886
+ await conn.query('LOAD EXTENSION fts');
887
+ ftsLoaded = true;
888
+ }
889
+ catch (err) {
890
+ const msg = err?.message || '';
891
+ if (msg.includes('already loaded') ||
892
+ msg.includes('already installed') ||
893
+ msg.includes('already exists')) {
894
+ ftsLoaded = true;
895
+ }
896
+ else {
897
+ console.error('GitNexus: FTS extension load failed:', msg);
898
+ }
899
+ }
900
+ }
901
+ };
902
+ /**
903
+ * Load the VECTOR extension (required before using QUERY_VECTOR_INDEX).
904
+ * Safe to call multiple times -- tracks loaded state via module-level vectorExtensionLoaded.
905
+ */
906
+ export const loadVectorExtension = async () => {
907
+ if (vectorExtensionLoaded)
908
+ return;
909
+ if (!conn) {
910
+ throw new Error('LadybugDB not initialized. Call initLbug first.');
911
+ }
912
+ try {
913
+ await conn.query('INSTALL VECTOR');
914
+ await conn.query('LOAD EXTENSION VECTOR');
915
+ vectorExtensionLoaded = true;
916
+ }
810
917
  catch (err) {
811
918
  const msg = err?.message || '';
812
919
  if (msg.includes('already loaded') ||
813
920
  msg.includes('already installed') ||
814
921
  msg.includes('already exists')) {
815
- ftsLoaded = true;
922
+ vectorExtensionLoaded = true;
816
923
  }
817
924
  else {
818
- console.error('GitNexus: FTS extension load failed:', msg);
925
+ console.error('GitNexus: VECTOR extension load failed:', msg);
819
926
  }
820
927
  }
821
928
  };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * LadybugDB connection pool (core). Used by MCP, sync, search, wiki, etc.
3
+ *
4
+ * LadybugDB Adapter (Connection Pool)
5
+ *
6
+ * Manages a pool of LadybugDB databases keyed by repoId, each with
7
+ * multiple Connection objects for safe concurrent query execution.
8
+ *
9
+ * LadybugDB Connections are NOT thread-safe — a single Connection
10
+ * segfaults if concurrent .query() calls hit it simultaneously.
11
+ * This adapter provides a checkout/return connection pool so each
12
+ * concurrent query gets its own Connection from the same Database.
13
+ *
14
+ * @see https://docs.ladybugdb.com/concurrency — multiple Connections
15
+ * from the same Database is the officially supported concurrency pattern.
16
+ */
17
+ import lbug from '@ladybugdb/core';
18
+ /** Saved real stdout/stderr write — used to silence native module output without race conditions */
19
+ export declare const realStdoutWrite: any;
20
+ export declare const realStderrWrite: any;
21
+ /**
22
+ * Touch a repo to reset its idle timeout.
23
+ * Call this during long-running operations to prevent the connection from being closed.
24
+ */
25
+ export declare const touchRepo: (repoId: string) => void;
26
+ /**
27
+ * Silence stdout by replacing process.stdout.write with a no-op.
28
+ * Uses a reference counter so nested silence/restore pairs are safe.
29
+ * Exported so other modules (e.g. embedder) use the same mechanism instead
30
+ * of independently patching stdout, which causes restore-order conflicts.
31
+ */
32
+ export declare function silenceStdout(): void;
33
+ export declare function restoreStdout(): void;
34
+ /**
35
+ * Initialize (or reuse) a Database + connection pool for a specific repo.
36
+ * Retries on lock errors (e.g., when `gitnexus analyze` is running).
37
+ *
38
+ * Concurrent calls for the same repoId are deduplicated — the second caller
39
+ * awaits the first's in-progress init rather than starting a redundant one.
40
+ */
41
+ export declare const initLbug: (repoId: string, dbPath: string) => Promise<void>;
42
+ /**
43
+ * Initialize a pool entry from a pre-existing Database object.
44
+ *
45
+ * Used in tests to avoid the writable→close→read-only cycle that crashes
46
+ * on macOS due to N-API destructor segfaults. The pool adapter reuses
47
+ * the core adapter's writable Database instead of opening a new read-only one.
48
+ *
49
+ * The Database is registered in the shared dbCache so closeOne() decrements
50
+ * the refCount correctly. If the Database is already cached (e.g. another
51
+ * repoId already injected it), the existing entry is reused.
52
+ */
53
+ export declare function initLbugWithDb(repoId: string, existingDb: lbug.Database, dbPath: string): Promise<void>;
54
+ export declare const executeQuery: (repoId: string, cypher: string) => Promise<any[]>;
55
+ /**
56
+ * Execute a parameterized query on a specific repo's connection pool.
57
+ * Uses prepare/execute pattern to prevent Cypher injection.
58
+ */
59
+ export declare const executeParameterized: (repoId: string, cypher: string, params: Record<string, any>) => Promise<any[]>;
60
+ /**
61
+ * Close one or all repo pools.
62
+ * If repoId is provided, close only that repo's connections.
63
+ * If omitted, close all repos.
64
+ */
65
+ export declare const closeLbug: (repoId?: string) => Promise<void>;
66
+ /**
67
+ * Check if a specific repo's pool is active
68
+ */
69
+ export declare const isLbugReady: (repoId: string) => boolean;
70
+ /** Regex to detect write operations in user-supplied Cypher queries.
71
+ * Note: CALL is NOT blocked — it's used for read-only FTS (CALL QUERY_FTS_INDEX)
72
+ * and vector search (CALL QUERY_VECTOR_INDEX). The database is opened in
73
+ * read-only mode as defense-in-depth against write procedures. */
74
+ export declare const CYPHER_WRITE_RE: RegExp;
75
+ /** Check if a Cypher query contains write operations */
76
+ export declare function isWriteQuery(query: string): boolean;