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.
- package/README.md +10 -0
- package/dist/_shared/graph/types.d.ts +1 -1
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +1 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +2 -0
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/languages.d.ts +1 -0
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +1 -0
- package/dist/_shared/languages.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +3 -1
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/mro-strategy.d.ts +19 -0
- package/dist/_shared/mro-strategy.d.ts.map +1 -0
- package/dist/_shared/mro-strategy.js +2 -0
- package/dist/_shared/mro-strategy.js.map +1 -0
- package/dist/cli/ai-context.d.ts +1 -0
- package/dist/cli/ai-context.js +28 -4
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +30 -4
- package/dist/cli/group.d.ts +2 -0
- package/dist/cli/group.js +233 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli/serve.js +4 -1
- package/dist/cli/setup.js +34 -3
- package/dist/config/ignore-service.js +8 -3
- package/dist/core/augmentation/engine.js +1 -1
- package/dist/core/git-staleness.d.ts +13 -0
- package/dist/core/git-staleness.js +29 -0
- package/dist/core/group/bridge-db.d.ts +82 -0
- package/dist/core/group/bridge-db.js +460 -0
- package/dist/core/group/bridge-schema.d.ts +27 -0
- package/dist/core/group/bridge-schema.js +55 -0
- package/dist/core/group/config-parser.d.ts +3 -0
- package/dist/core/group/config-parser.js +83 -0
- package/dist/core/group/contract-extractor.d.ts +7 -0
- package/dist/core/group/contract-extractor.js +1 -0
- package/dist/core/group/extractors/fs-utils.d.ts +10 -0
- package/dist/core/group/extractors/fs-utils.js +24 -0
- package/dist/core/group/extractors/grpc-extractor.d.ts +25 -0
- package/dist/core/group/extractors/grpc-extractor.js +386 -0
- package/dist/core/group/extractors/grpc-patterns/go.d.ts +2 -0
- package/dist/core/group/extractors/grpc-patterns/go.js +97 -0
- package/dist/core/group/extractors/grpc-patterns/index.d.ts +19 -0
- package/dist/core/group/extractors/grpc-patterns/index.js +46 -0
- package/dist/core/group/extractors/grpc-patterns/java.d.ts +2 -0
- package/dist/core/group/extractors/grpc-patterns/java.js +173 -0
- package/dist/core/group/extractors/grpc-patterns/node.d.ts +4 -0
- package/dist/core/group/extractors/grpc-patterns/node.js +290 -0
- package/dist/core/group/extractors/grpc-patterns/proto.d.ts +9 -0
- package/dist/core/group/extractors/grpc-patterns/proto.js +134 -0
- package/dist/core/group/extractors/grpc-patterns/python.d.ts +2 -0
- package/dist/core/group/extractors/grpc-patterns/python.js +67 -0
- package/dist/core/group/extractors/grpc-patterns/types.d.ts +50 -0
- package/dist/core/group/extractors/grpc-patterns/types.js +1 -0
- package/dist/core/group/extractors/http-patterns/go.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/go.js +215 -0
- package/dist/core/group/extractors/http-patterns/index.d.ts +17 -0
- package/dist/core/group/extractors/http-patterns/index.js +44 -0
- package/dist/core/group/extractors/http-patterns/java.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/java.js +253 -0
- package/dist/core/group/extractors/http-patterns/node.d.ts +4 -0
- package/dist/core/group/extractors/http-patterns/node.js +354 -0
- package/dist/core/group/extractors/http-patterns/php.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/php.js +70 -0
- package/dist/core/group/extractors/http-patterns/python.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/python.js +133 -0
- package/dist/core/group/extractors/http-patterns/types.d.ts +61 -0
- package/dist/core/group/extractors/http-patterns/types.js +1 -0
- package/dist/core/group/extractors/http-route-extractor.d.ts +21 -0
- package/dist/core/group/extractors/http-route-extractor.js +391 -0
- package/dist/core/group/extractors/manifest-extractor.d.ts +54 -0
- package/dist/core/group/extractors/manifest-extractor.js +235 -0
- package/dist/core/group/extractors/topic-extractor.d.ts +8 -0
- package/dist/core/group/extractors/topic-extractor.js +97 -0
- package/dist/core/group/extractors/topic-patterns/go.d.ts +2 -0
- package/dist/core/group/extractors/topic-patterns/go.js +120 -0
- package/dist/core/group/extractors/topic-patterns/index.d.ts +14 -0
- package/dist/core/group/extractors/topic-patterns/index.js +38 -0
- package/dist/core/group/extractors/topic-patterns/java.d.ts +2 -0
- package/dist/core/group/extractors/topic-patterns/java.js +80 -0
- package/dist/core/group/extractors/topic-patterns/node.d.ts +4 -0
- package/dist/core/group/extractors/topic-patterns/node.js +155 -0
- package/dist/core/group/extractors/topic-patterns/python.d.ts +2 -0
- package/dist/core/group/extractors/topic-patterns/python.js +116 -0
- package/dist/core/group/extractors/topic-patterns/types.d.ts +25 -0
- package/dist/core/group/extractors/topic-patterns/types.js +10 -0
- package/dist/core/group/extractors/tree-sitter-scanner.d.ts +113 -0
- package/dist/core/group/extractors/tree-sitter-scanner.js +94 -0
- package/dist/core/group/matching.d.ts +13 -0
- package/dist/core/group/matching.js +198 -0
- package/dist/core/group/normalization.d.ts +3 -0
- package/dist/core/group/normalization.js +115 -0
- package/dist/core/group/service-boundary-detector.d.ts +8 -0
- package/dist/core/group/service-boundary-detector.js +155 -0
- package/dist/core/group/service.d.ts +46 -0
- package/dist/core/group/service.js +160 -0
- package/dist/core/group/storage.d.ts +9 -0
- package/dist/core/group/storage.js +91 -0
- package/dist/core/group/sync.d.ts +21 -0
- package/dist/core/group/sync.js +148 -0
- package/dist/core/group/types.d.ts +130 -0
- package/dist/core/group/types.js +1 -0
- package/dist/core/ingestion/binding-accumulator.d.ts +212 -0
- package/dist/core/ingestion/binding-accumulator.js +336 -0
- package/dist/core/ingestion/call-processor.d.ts +155 -24
- package/dist/core/ingestion/call-processor.js +1129 -247
- package/dist/core/ingestion/class-extractors/generic.d.ts +2 -0
- package/dist/core/ingestion/class-extractors/generic.js +135 -0
- package/dist/core/ingestion/class-types.d.ts +34 -0
- package/dist/core/ingestion/class-types.js +1 -0
- package/dist/core/ingestion/cobol-processor.d.ts +1 -1
- package/dist/core/ingestion/entry-point-scoring.d.ts +1 -0
- package/dist/core/ingestion/entry-point-scoring.js +1 -0
- package/dist/core/ingestion/field-types.d.ts +2 -2
- package/dist/core/ingestion/filesystem-walker.js +8 -0
- package/dist/core/ingestion/framework-detection.d.ts +1 -0
- package/dist/core/ingestion/framework-detection.js +1 -0
- package/dist/core/ingestion/heritage-processor.d.ts +8 -15
- package/dist/core/ingestion/heritage-processor.js +15 -28
- package/dist/core/ingestion/import-processor.d.ts +1 -11
- package/dist/core/ingestion/import-processor.js +1 -13
- package/dist/core/ingestion/import-resolvers/utils.js +1 -0
- package/dist/core/ingestion/import-resolvers/vue.d.ts +8 -0
- package/dist/core/ingestion/import-resolvers/vue.js +9 -0
- package/dist/core/ingestion/language-config.js +1 -1
- package/dist/core/ingestion/language-provider.d.ts +14 -3
- package/dist/core/ingestion/languages/c-cpp.js +168 -1
- package/dist/core/ingestion/languages/csharp.js +20 -0
- package/dist/core/ingestion/languages/dart.js +26 -4
- package/dist/core/ingestion/languages/go.js +22 -0
- package/dist/core/ingestion/languages/index.d.ts +1 -0
- package/dist/core/ingestion/languages/index.js +2 -0
- package/dist/core/ingestion/languages/java.js +17 -0
- package/dist/core/ingestion/languages/kotlin.js +24 -1
- package/dist/core/ingestion/languages/php.js +23 -11
- package/dist/core/ingestion/languages/python.js +9 -0
- package/dist/core/ingestion/languages/ruby.js +43 -0
- package/dist/core/ingestion/languages/rust.js +38 -0
- package/dist/core/ingestion/languages/swift.js +31 -0
- package/dist/core/ingestion/languages/typescript.d.ts +1 -0
- package/dist/core/ingestion/languages/typescript.js +52 -3
- package/dist/core/ingestion/languages/vue.d.ts +13 -0
- package/dist/core/ingestion/languages/vue.js +81 -0
- package/dist/core/ingestion/markdown-processor.d.ts +1 -1
- package/dist/core/ingestion/method-extractors/configs/c-cpp.d.ts +3 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
- package/dist/core/ingestion/method-extractors/configs/csharp.js +5 -1
- package/dist/core/ingestion/method-extractors/configs/dart.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/dart.js +376 -0
- package/dist/core/ingestion/method-extractors/configs/go.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/go.js +176 -0
- package/dist/core/ingestion/method-extractors/configs/jvm.js +14 -4
- package/dist/core/ingestion/method-extractors/configs/php.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/php.js +304 -0
- package/dist/core/ingestion/method-extractors/configs/python.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/python.js +309 -0
- package/dist/core/ingestion/method-extractors/configs/ruby.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/ruby.js +286 -0
- package/dist/core/ingestion/method-extractors/configs/rust.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/rust.js +195 -0
- package/dist/core/ingestion/method-extractors/configs/swift.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/swift.js +277 -0
- package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +85 -8
- package/dist/core/ingestion/method-extractors/generic.d.ts +6 -0
- package/dist/core/ingestion/method-extractors/generic.js +84 -17
- package/dist/core/ingestion/method-types.d.ts +29 -0
- package/dist/core/ingestion/model/field-registry.d.ts +18 -0
- package/dist/core/ingestion/model/field-registry.js +22 -0
- package/dist/core/ingestion/model/heritage-map.d.ts +70 -0
- package/dist/core/ingestion/model/heritage-map.js +159 -0
- package/dist/core/ingestion/model/index.d.ts +20 -0
- package/dist/core/ingestion/model/index.js +41 -0
- package/dist/core/ingestion/model/method-registry.d.ts +62 -0
- package/dist/core/ingestion/model/method-registry.js +130 -0
- package/dist/core/ingestion/model/registration-table.d.ts +139 -0
- package/dist/core/ingestion/model/registration-table.js +224 -0
- package/dist/core/ingestion/model/resolution-context.d.ts +93 -0
- package/dist/core/ingestion/model/resolution-context.js +337 -0
- package/dist/core/ingestion/model/resolve.d.ts +56 -0
- package/dist/core/ingestion/model/resolve.js +297 -0
- package/dist/core/ingestion/model/semantic-model.d.ts +86 -0
- package/dist/core/ingestion/model/semantic-model.js +120 -0
- package/dist/core/ingestion/model/symbol-table.d.ts +222 -0
- package/dist/core/ingestion/model/symbol-table.js +206 -0
- package/dist/core/ingestion/model/type-registry.d.ts +39 -0
- package/dist/core/ingestion/model/type-registry.js +62 -0
- package/dist/core/ingestion/mro-processor.d.ts +5 -4
- package/dist/core/ingestion/mro-processor.js +311 -107
- package/dist/core/ingestion/parsing-processor.d.ts +5 -4
- package/dist/core/ingestion/parsing-processor.js +224 -87
- package/dist/core/ingestion/pipeline-phases/cobol.d.ts +16 -0
- package/dist/core/ingestion/pipeline-phases/cobol.js +45 -0
- package/dist/core/ingestion/pipeline-phases/communities.d.ts +16 -0
- package/dist/core/ingestion/pipeline-phases/communities.js +62 -0
- package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +156 -0
- package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +37 -0
- package/dist/core/ingestion/pipeline-phases/cross-file.js +63 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +21 -0
- package/dist/core/ingestion/pipeline-phases/index.js +22 -0
- package/dist/core/ingestion/pipeline-phases/markdown.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/markdown.js +33 -0
- package/dist/core/ingestion/pipeline-phases/mro.d.ts +18 -0
- package/dist/core/ingestion/pipeline-phases/mro.js +36 -0
- package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +22 -0
- package/dist/core/ingestion/pipeline-phases/orm-extraction.js +92 -0
- package/dist/core/ingestion/pipeline-phases/orm.d.ts +15 -0
- package/dist/core/ingestion/pipeline-phases/orm.js +74 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +47 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +437 -0
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +49 -0
- package/dist/core/ingestion/pipeline-phases/parse.js +33 -0
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +16 -0
- package/dist/core/ingestion/pipeline-phases/processes.js +143 -0
- package/dist/core/ingestion/pipeline-phases/routes.d.ts +21 -0
- package/dist/core/ingestion/pipeline-phases/routes.js +243 -0
- package/dist/core/ingestion/pipeline-phases/runner.d.ts +22 -0
- package/dist/core/ingestion/pipeline-phases/runner.js +203 -0
- package/dist/core/ingestion/pipeline-phases/scan.d.ts +21 -0
- package/dist/core/ingestion/pipeline-phases/scan.js +46 -0
- package/dist/core/ingestion/pipeline-phases/structure.d.ts +27 -0
- package/dist/core/ingestion/pipeline-phases/structure.js +35 -0
- package/dist/core/ingestion/pipeline-phases/tools.d.ts +20 -0
- package/dist/core/ingestion/pipeline-phases/tools.js +79 -0
- package/dist/core/ingestion/pipeline-phases/types.d.ts +79 -0
- package/dist/core/ingestion/pipeline-phases/types.js +37 -0
- package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +35 -0
- package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +174 -0
- package/dist/core/ingestion/pipeline.d.ts +18 -10
- package/dist/core/ingestion/pipeline.js +66 -1410
- package/dist/core/ingestion/process-processor.js +1 -1
- package/dist/core/ingestion/tree-sitter-queries.d.ts +5 -5
- package/dist/core/ingestion/tree-sitter-queries.js +90 -0
- package/dist/core/ingestion/type-env.d.ts +15 -2
- package/dist/core/ingestion/type-env.js +163 -102
- package/dist/core/ingestion/type-extractors/csharp.js +17 -0
- package/dist/core/ingestion/type-extractors/jvm.js +11 -0
- package/dist/core/ingestion/type-extractors/php.js +0 -55
- package/dist/core/ingestion/type-extractors/ruby.js +0 -32
- package/dist/core/ingestion/type-extractors/swift.js +13 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +8 -8
- package/dist/core/ingestion/type-extractors/typescript.js +66 -69
- package/dist/core/ingestion/utils/ast-helpers.d.ts +32 -44
- package/dist/core/ingestion/utils/ast-helpers.js +157 -573
- package/dist/core/ingestion/utils/env.d.ts +10 -0
- package/dist/core/ingestion/utils/env.js +10 -0
- package/dist/core/ingestion/utils/graph-sort.d.ts +58 -0
- package/dist/core/ingestion/utils/graph-sort.js +100 -0
- package/dist/core/ingestion/utils/method-props.d.ts +32 -0
- package/dist/core/ingestion/utils/method-props.js +147 -0
- package/dist/core/ingestion/vue-sfc-extractor.d.ts +44 -0
- package/dist/core/ingestion/vue-sfc-extractor.js +94 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +31 -19
- package/dist/core/ingestion/workers/parse-worker.js +469 -200
- package/dist/core/lbug/lbug-adapter.d.ts +6 -0
- package/dist/core/lbug/lbug-adapter.js +134 -27
- package/dist/core/lbug/pool-adapter.d.ts +76 -0
- package/dist/core/lbug/pool-adapter.js +522 -0
- package/dist/core/run-analyze.d.ts +2 -0
- package/dist/core/run-analyze.js +1 -1
- package/dist/core/search/bm25-index.js +1 -1
- package/dist/core/tree-sitter/parser-loader.js +1 -0
- package/dist/core/wiki/graph-queries.js +1 -1
- package/dist/mcp/core/embedder.js +6 -5
- package/dist/mcp/core/lbug-adapter.d.ts +3 -63
- package/dist/mcp/core/lbug-adapter.js +3 -484
- package/dist/mcp/local/local-backend.d.ts +31 -2
- package/dist/mcp/local/local-backend.js +255 -46
- package/dist/mcp/resources.js +5 -4
- package/dist/mcp/staleness.d.ts +3 -13
- package/dist/mcp/staleness.js +2 -31
- package/dist/mcp/tools.js +80 -4
- package/dist/server/analyze-job.d.ts +2 -0
- package/dist/server/analyze-job.js +4 -0
- package/dist/server/api.d.ts +20 -1
- package/dist/server/api.js +306 -71
- package/dist/server/git-clone.d.ts +2 -1
- package/dist/server/git-clone.js +98 -5
- package/dist/storage/git.d.ts +13 -0
- package/dist/storage/git.js +25 -0
- package/dist/storage/repo-manager.js +1 -1
- package/package.json +9 -3
- package/scripts/patch-tree-sitter-swift.cjs +78 -0
- package/vendor/tree-sitter-proto/binding.gyp +30 -0
- package/vendor/tree-sitter-proto/bindings/node/binding.cc +20 -0
- package/vendor/tree-sitter-proto/bindings/node/index.d.ts +28 -0
- package/vendor/tree-sitter-proto/bindings/node/index.js +7 -0
- package/vendor/tree-sitter-proto/package.json +18 -0
- package/vendor/tree-sitter-proto/src/node-types.json +1145 -0
- package/vendor/tree-sitter-proto/src/parser.c +10149 -0
- package/vendor/tree-sitter-proto/src/tree_sitter/alloc.h +54 -0
- package/vendor/tree-sitter-proto/src/tree_sitter/array.h +291 -0
- package/vendor/tree-sitter-proto/src/tree_sitter/parser.h +266 -0
- package/dist/core/ingestion/named-binding-processor.d.ts +0 -18
- package/dist/core/ingestion/named-binding-processor.js +0 -42
- package/dist/core/ingestion/resolution-context.d.ts +0 -58
- package/dist/core/ingestion/resolution-context.js +0 -135
- package/dist/core/ingestion/symbol-table.d.ts +0 -79
- 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
|
|
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
|
|
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
|
|
245
|
-
if (!
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
|
|
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',
|
|
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 ${
|
|
284
|
+
log(`Loading edges: ${insertedRels.toLocaleString()} across ${relsByPairMeta.size} types`);
|
|
259
285
|
let pairIdx = 0;
|
|
260
286
|
let failedPairEdges = 0;
|
|
261
|
-
const
|
|
262
|
-
for (const [pairKey,
|
|
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 ||
|
|
270
|
-
log(`Loading edges: ${pairIdx}/${
|
|
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} (${
|
|
283
|
-
failedPairEdges +=
|
|
284
|
-
|
|
306
|
+
warnings.push(`${fromLabel}->${toLabel} (${rows} edges): ${retryMsg.slice(0, 80)}`);
|
|
307
|
+
failedPairEdges += rows;
|
|
308
|
+
failedPairCsvPaths.add(pairCsvPath);
|
|
285
309
|
}
|
|
286
310
|
}
|
|
287
|
-
|
|
288
|
-
|
|
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 (
|
|
319
|
+
if (failedPairCsvPaths.size > 0) {
|
|
293
320
|
log(`Inserting ${failedPairEdges} edges individually (missing schema pairs)`);
|
|
294
|
-
|
|
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
|
-
|
|
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
|
-
|
|
922
|
+
vectorExtensionLoaded = true;
|
|
816
923
|
}
|
|
817
924
|
else {
|
|
818
|
-
console.error('GitNexus:
|
|
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;
|