gitnexus 1.4.1 → 1.4.6
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 +215 -194
- package/dist/cli/ai-context.d.ts +2 -1
- package/dist/cli/ai-context.js +117 -90
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +57 -30
- package/dist/cli/augment.js +1 -1
- package/dist/cli/eval-server.d.ts +1 -1
- package/dist/cli/eval-server.js +14 -6
- package/dist/cli/index.js +18 -25
- package/dist/cli/lazy-action.d.ts +6 -0
- package/dist/cli/lazy-action.js +18 -0
- package/dist/cli/mcp.js +1 -1
- package/dist/cli/setup.js +42 -32
- package/dist/cli/skill-gen.d.ts +26 -0
- package/dist/cli/skill-gen.js +549 -0
- package/dist/cli/status.js +13 -4
- package/dist/cli/tool.d.ts +3 -2
- package/dist/cli/tool.js +48 -13
- package/dist/cli/wiki.js +2 -2
- package/dist/config/ignore-service.d.ts +25 -0
- package/dist/config/ignore-service.js +76 -0
- package/dist/config/supported-languages.d.ts +1 -0
- package/dist/config/supported-languages.js +1 -1
- package/dist/core/augmentation/engine.js +99 -72
- package/dist/core/embeddings/embedder.d.ts +1 -1
- package/dist/core/embeddings/embedder.js +1 -1
- package/dist/core/embeddings/embedding-pipeline.d.ts +3 -3
- package/dist/core/embeddings/embedding-pipeline.js +74 -47
- package/dist/core/embeddings/types.d.ts +1 -1
- package/dist/core/graph/types.d.ts +5 -2
- package/dist/core/ingestion/ast-cache.js +3 -2
- package/dist/core/ingestion/call-processor.d.ts +5 -7
- package/dist/core/ingestion/call-processor.js +430 -283
- package/dist/core/ingestion/call-routing.d.ts +53 -0
- package/dist/core/ingestion/call-routing.js +108 -0
- package/dist/core/ingestion/cluster-enricher.js +16 -16
- package/dist/core/ingestion/constants.d.ts +16 -0
- package/dist/core/ingestion/constants.js +16 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +2 -1
- package/dist/core/ingestion/entry-point-scoring.js +94 -24
- package/dist/core/ingestion/export-detection.d.ts +18 -0
- package/dist/core/ingestion/export-detection.js +231 -0
- package/dist/core/ingestion/filesystem-walker.js +4 -3
- package/dist/core/ingestion/framework-detection.d.ts +5 -1
- package/dist/core/ingestion/framework-detection.js +48 -8
- package/dist/core/ingestion/heritage-processor.d.ts +13 -5
- package/dist/core/ingestion/heritage-processor.js +109 -55
- package/dist/core/ingestion/import-processor.d.ts +16 -20
- package/dist/core/ingestion/import-processor.js +202 -696
- package/dist/core/ingestion/language-config.d.ts +46 -0
- package/dist/core/ingestion/language-config.js +167 -0
- package/dist/core/ingestion/mro-processor.d.ts +45 -0
- package/dist/core/ingestion/mro-processor.js +369 -0
- package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
- package/dist/core/ingestion/named-binding-extraction.js +363 -0
- package/dist/core/ingestion/parsing-processor.d.ts +3 -11
- package/dist/core/ingestion/parsing-processor.js +85 -181
- package/dist/core/ingestion/pipeline.d.ts +5 -1
- package/dist/core/ingestion/pipeline.js +192 -116
- package/dist/core/ingestion/process-processor.js +2 -1
- package/dist/core/ingestion/resolution-context.d.ts +53 -0
- package/dist/core/ingestion/resolution-context.js +132 -0
- package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
- package/dist/core/ingestion/resolvers/csharp.js +109 -0
- package/dist/core/ingestion/resolvers/go.d.ts +19 -0
- package/dist/core/ingestion/resolvers/go.js +42 -0
- package/dist/core/ingestion/resolvers/index.d.ts +18 -0
- package/dist/core/ingestion/resolvers/index.js +13 -0
- package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
- package/dist/core/ingestion/resolvers/jvm.js +87 -0
- package/dist/core/ingestion/resolvers/php.d.ts +15 -0
- package/dist/core/ingestion/resolvers/php.js +35 -0
- package/dist/core/ingestion/resolvers/python.d.ts +19 -0
- package/dist/core/ingestion/resolvers/python.js +52 -0
- package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
- package/dist/core/ingestion/resolvers/ruby.js +15 -0
- package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
- package/dist/core/ingestion/resolvers/rust.js +73 -0
- package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
- package/dist/core/ingestion/resolvers/standard.js +123 -0
- package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
- package/dist/core/ingestion/resolvers/utils.js +122 -0
- package/dist/core/ingestion/symbol-table.d.ts +21 -1
- package/dist/core/ingestion/symbol-table.js +40 -12
- package/dist/core/ingestion/tree-sitter-queries.d.ts +12 -11
- package/dist/core/ingestion/tree-sitter-queries.js +642 -485
- package/dist/core/ingestion/type-env.d.ts +49 -0
- package/dist/core/ingestion/type-env.js +611 -0
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
- package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/csharp.js +383 -0
- package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/go.js +467 -0
- package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
- package/dist/core/ingestion/type-extractors/index.js +31 -0
- package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
- package/dist/core/ingestion/type-extractors/jvm.js +681 -0
- package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/php.js +549 -0
- package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/python.js +406 -0
- package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/ruby.js +389 -0
- package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/rust.js +449 -0
- package/dist/core/ingestion/type-extractors/shared.d.ts +133 -0
- package/dist/core/ingestion/type-extractors/shared.js +703 -0
- package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/swift.js +137 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
- package/dist/core/ingestion/type-extractors/types.js +1 -0
- package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/typescript.js +494 -0
- package/dist/core/ingestion/utils.d.ts +98 -0
- package/dist/core/ingestion/utils.js +1064 -9
- package/dist/core/ingestion/workers/parse-worker.d.ts +38 -4
- package/dist/core/ingestion/workers/parse-worker.js +251 -359
- package/dist/core/ingestion/workers/worker-pool.js +8 -0
- package/dist/core/{kuzu → lbug}/csv-generator.d.ts +1 -1
- package/dist/core/{kuzu → lbug}/csv-generator.js +20 -4
- package/dist/core/{kuzu/kuzu-adapter.d.ts → lbug/lbug-adapter.d.ts} +19 -19
- package/dist/core/{kuzu/kuzu-adapter.js → lbug/lbug-adapter.js} +82 -82
- package/dist/core/{kuzu → lbug}/schema.d.ts +4 -4
- package/dist/core/{kuzu → lbug}/schema.js +304 -289
- package/dist/core/search/bm25-index.d.ts +4 -4
- package/dist/core/search/bm25-index.js +17 -16
- package/dist/core/search/hybrid-search.d.ts +2 -2
- package/dist/core/search/hybrid-search.js +9 -9
- package/dist/core/tree-sitter/parser-loader.js +9 -2
- package/dist/core/wiki/generator.d.ts +4 -52
- package/dist/core/wiki/generator.js +53 -552
- package/dist/core/wiki/graph-queries.d.ts +4 -46
- package/dist/core/wiki/graph-queries.js +103 -282
- package/dist/core/wiki/html-viewer.js +192 -192
- package/dist/core/wiki/llm-client.js +11 -73
- package/dist/core/wiki/prompts.d.ts +8 -52
- package/dist/core/wiki/prompts.js +86 -200
- package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
- package/dist/mcp/compatible-stdio-transport.js +200 -0
- package/dist/mcp/core/{kuzu-adapter.d.ts → lbug-adapter.d.ts} +7 -9
- package/dist/mcp/core/{kuzu-adapter.js → lbug-adapter.js} +77 -79
- package/dist/mcp/local/local-backend.d.ts +7 -6
- package/dist/mcp/local/local-backend.js +176 -147
- package/dist/mcp/resources.js +42 -42
- package/dist/mcp/server.js +18 -19
- package/dist/mcp/tools.js +103 -104
- package/dist/server/api.js +12 -12
- package/dist/server/mcp-http.d.ts +1 -1
- package/dist/server/mcp-http.js +1 -1
- package/dist/storage/repo-manager.d.ts +20 -2
- package/dist/storage/repo-manager.js +55 -1
- package/dist/types/pipeline.d.ts +1 -1
- package/hooks/claude/gitnexus-hook.cjs +238 -155
- package/hooks/claude/pre-tool-use.sh +79 -79
- package/hooks/claude/session-start.sh +42 -42
- package/package.json +99 -96
- package/scripts/patch-tree-sitter-swift.cjs +74 -74
- package/skills/gitnexus-cli.md +82 -82
- package/skills/gitnexus-debugging.md +89 -89
- package/skills/gitnexus-exploring.md +78 -78
- package/skills/gitnexus-guide.md +64 -64
- package/skills/gitnexus-impact-analysis.md +97 -97
- package/skills/gitnexus-pr-review.md +163 -163
- package/skills/gitnexus-refactoring.md +121 -121
- package/vendor/leiden/index.cjs +355 -355
- package/vendor/leiden/utils.cjs +392 -392
- package/dist/core/wiki/diagrams.d.ts +0 -27
- package/dist/core/wiki/diagrams.js +0 -163
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* LadybugDB Adapter (Connection Pool)
|
|
3
3
|
*
|
|
4
|
-
* Manages a pool of
|
|
4
|
+
* Manages a pool of LadybugDB databases keyed by repoId, each with
|
|
5
5
|
* multiple Connection objects for safe concurrent query execution.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* LadybugDB Connections are NOT thread-safe — a single Connection
|
|
8
8
|
* segfaults if concurrent .query() calls hit it simultaneously.
|
|
9
9
|
* This adapter provides a checkout/return connection pool so each
|
|
10
10
|
* concurrent query gets its own Connection from the same Database.
|
|
11
11
|
*
|
|
12
|
-
* @see https://docs.
|
|
12
|
+
* @see https://docs.ladybugdb.com/concurrency — multiple Connections
|
|
13
13
|
* from the same Database is the officially supported concurrency pattern.
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
16
|
* Initialize (or reuse) a Database + connection pool for a specific repo.
|
|
17
17
|
* Retries on lock errors (e.g., when `gitnexus analyze` is running).
|
|
18
18
|
*/
|
|
19
|
-
export declare const
|
|
20
|
-
pinned?: boolean;
|
|
21
|
-
}) => Promise<void>;
|
|
19
|
+
export declare const initLbug: (repoId: string, dbPath: string) => Promise<void>;
|
|
22
20
|
export declare const executeQuery: (repoId: string, cypher: string) => Promise<any[]>;
|
|
23
21
|
/**
|
|
24
22
|
* Execute a parameterized query on a specific repo's connection pool.
|
|
@@ -30,8 +28,8 @@ export declare const executeParameterized: (repoId: string, cypher: string, para
|
|
|
30
28
|
* If repoId is provided, close only that repo's connections.
|
|
31
29
|
* If omitted, close all repos.
|
|
32
30
|
*/
|
|
33
|
-
export declare const
|
|
31
|
+
export declare const closeLbug: (repoId?: string) => Promise<void>;
|
|
34
32
|
/**
|
|
35
33
|
* Check if a specific repo's pool is active
|
|
36
34
|
*/
|
|
37
|
-
export declare const
|
|
35
|
+
export declare const isLbugReady: (repoId: string) => boolean;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* LadybugDB Adapter (Connection Pool)
|
|
3
3
|
*
|
|
4
|
-
* Manages a pool of
|
|
4
|
+
* Manages a pool of LadybugDB databases keyed by repoId, each with
|
|
5
5
|
* multiple Connection objects for safe concurrent query execution.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* LadybugDB Connections are NOT thread-safe — a single Connection
|
|
8
8
|
* segfaults if concurrent .query() calls hit it simultaneously.
|
|
9
9
|
* This adapter provides a checkout/return connection pool so each
|
|
10
10
|
* concurrent query gets its own Connection from the same Database.
|
|
11
11
|
*
|
|
12
|
-
* @see https://docs.
|
|
12
|
+
* @see https://docs.ladybugdb.com/concurrency — multiple Connections
|
|
13
13
|
* from the same Database is the officially supported concurrency pattern.
|
|
14
14
|
*/
|
|
15
15
|
import fs from 'fs/promises';
|
|
16
|
-
import
|
|
16
|
+
import lbug from '@ladybugdb/core';
|
|
17
17
|
const pool = new Map();
|
|
18
|
+
const dbCache = new Map();
|
|
18
19
|
/** Max repos in the pool (LRU eviction) */
|
|
19
|
-
const MAX_POOL_SIZE =
|
|
20
|
+
const MAX_POOL_SIZE = 5;
|
|
20
21
|
/** Idle timeout before closing a repo's connections */
|
|
21
22
|
const IDLE_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
22
23
|
/** Max connections per repo (caps concurrent queries per repo) */
|
|
@@ -24,7 +25,7 @@ const MAX_CONNS_PER_REPO = 8;
|
|
|
24
25
|
/** Connections created eagerly on init */
|
|
25
26
|
const INITIAL_CONNS_PER_REPO = 2;
|
|
26
27
|
let idleTimer = null;
|
|
27
|
-
/** Saved real stdout.write — used to silence
|
|
28
|
+
/** Saved real stdout.write — used to silence LadybugDB native output without race conditions */
|
|
28
29
|
const realStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
29
30
|
let stdoutSilenceCount = 0;
|
|
30
31
|
/**
|
|
@@ -36,7 +37,7 @@ function ensureIdleTimer() {
|
|
|
36
37
|
idleTimer = setInterval(() => {
|
|
37
38
|
const now = Date.now();
|
|
38
39
|
for (const [repoId, entry] of pool) {
|
|
39
|
-
if (
|
|
40
|
+
if (now - entry.lastUsed > IDLE_TIMEOUT_MS && entry.checkedOut === 0) {
|
|
40
41
|
closeOne(repoId);
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -54,7 +55,7 @@ function evictLRU() {
|
|
|
54
55
|
let oldestId = null;
|
|
55
56
|
let oldestTime = Infinity;
|
|
56
57
|
for (const [id, entry] of pool) {
|
|
57
|
-
if (
|
|
58
|
+
if (entry.checkedOut === 0 && entry.lastUsed < oldestTime) {
|
|
58
59
|
oldestTime = entry.lastUsed;
|
|
59
60
|
oldestId = id;
|
|
60
61
|
}
|
|
@@ -64,25 +65,20 @@ function evictLRU() {
|
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
|
-
*
|
|
68
|
+
* Remove a repo from the pool and release its shared Database ref.
|
|
69
|
+
*
|
|
70
|
+
* LadybugDB's native .closeSync() triggers N-API destructor hooks that
|
|
71
|
+
* segfault on Linux/macOS. Pool databases are opened read-only, so
|
|
72
|
+
* there is no WAL to flush — just deleting the pool entry and letting
|
|
73
|
+
* the GC (or process exit) reclaim native resources is safe.
|
|
68
74
|
*/
|
|
69
75
|
function closeOne(repoId) {
|
|
70
76
|
const entry = pool.get(repoId);
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
conn.close();
|
|
77
|
+
if (entry) {
|
|
78
|
+
const shared = dbCache.get(entry.dbPath);
|
|
79
|
+
if (shared && shared.refCount > 0) {
|
|
80
|
+
shared.refCount--;
|
|
76
81
|
}
|
|
77
|
-
catch (e) {
|
|
78
|
-
console.error('GitNexus [pool:close-conn]:', e instanceof Error ? e.message : e);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
entry.db.close();
|
|
83
|
-
}
|
|
84
|
-
catch (e) {
|
|
85
|
-
console.error('GitNexus [pool:close-db]:', e instanceof Error ? e.message : e);
|
|
86
82
|
}
|
|
87
83
|
pool.delete(repoId);
|
|
88
84
|
}
|
|
@@ -104,26 +100,12 @@ function restoreStdout() {
|
|
|
104
100
|
function createConnection(db) {
|
|
105
101
|
silenceStdout();
|
|
106
102
|
try {
|
|
107
|
-
return new
|
|
103
|
+
return new lbug.Connection(db);
|
|
108
104
|
}
|
|
109
105
|
finally {
|
|
110
106
|
restoreStdout();
|
|
111
107
|
}
|
|
112
108
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Load the FTS extension on a connection (best-effort, idempotent).
|
|
115
|
-
* Required before using QUERY_FTS_INDEX in search queries.
|
|
116
|
-
*/
|
|
117
|
-
async function loadFTSOnConnection(conn) {
|
|
118
|
-
try {
|
|
119
|
-
await conn.query('INSTALL fts');
|
|
120
|
-
}
|
|
121
|
-
catch { /* already installed */ }
|
|
122
|
-
try {
|
|
123
|
-
await conn.query('LOAD EXTENSION fts');
|
|
124
|
-
}
|
|
125
|
-
catch { /* already loaded or unavailable */ }
|
|
126
|
-
}
|
|
127
109
|
/** Query timeout in milliseconds */
|
|
128
110
|
const QUERY_TIMEOUT_MS = 30_000;
|
|
129
111
|
/** Waiter queue timeout in milliseconds */
|
|
@@ -134,7 +116,7 @@ const LOCK_RETRY_DELAY_MS = 2000;
|
|
|
134
116
|
* Initialize (or reuse) a Database + connection pool for a specific repo.
|
|
135
117
|
* Retries on lock errors (e.g., when `gitnexus analyze` is running).
|
|
136
118
|
*/
|
|
137
|
-
export const
|
|
119
|
+
export const initLbug = async (repoId, dbPath) => {
|
|
138
120
|
const existing = pool.get(repoId);
|
|
139
121
|
if (existing) {
|
|
140
122
|
existing.lastUsed = Date.now();
|
|
@@ -145,43 +127,62 @@ export const initKuzu = async (repoId, dbPath, opts) => {
|
|
|
145
127
|
await fs.stat(dbPath);
|
|
146
128
|
}
|
|
147
129
|
catch {
|
|
148
|
-
throw new Error(`
|
|
130
|
+
throw new Error(`LadybugDB not found at ${dbPath}. Run: gitnexus analyze`);
|
|
149
131
|
}
|
|
150
132
|
evictLRU();
|
|
151
|
-
//
|
|
152
|
-
// This
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
133
|
+
// Reuse an existing native Database if another repoId already opened this path.
|
|
134
|
+
// This prevents buffer manager exhaustion from multiple mmap regions on the same file.
|
|
135
|
+
let shared = dbCache.get(dbPath);
|
|
136
|
+
if (!shared) {
|
|
137
|
+
// Open in read-only mode — MCP server never writes to the database.
|
|
138
|
+
// This allows multiple MCP server instances to read concurrently, and
|
|
139
|
+
// avoids lock conflicts when `gitnexus analyze` is writing.
|
|
140
|
+
let lastError = null;
|
|
141
|
+
for (let attempt = 1; attempt <= LOCK_RETRY_ATTEMPTS; attempt++) {
|
|
142
|
+
silenceStdout();
|
|
143
|
+
try {
|
|
144
|
+
const db = new lbug.Database(dbPath, 0, // bufferManagerSize (default)
|
|
145
|
+
false, // enableCompression (default)
|
|
146
|
+
true);
|
|
147
|
+
restoreStdout();
|
|
148
|
+
shared = { db, refCount: 0, ftsLoaded: false };
|
|
149
|
+
dbCache.set(dbPath, shared);
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
restoreStdout();
|
|
154
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
155
|
+
const isLockError = lastError.message.includes('Could not set lock')
|
|
156
|
+
|| lastError.message.includes('lock');
|
|
157
|
+
if (!isLockError || attempt === LOCK_RETRY_ATTEMPTS)
|
|
158
|
+
break;
|
|
159
|
+
await new Promise(resolve => setTimeout(resolve, LOCK_RETRY_DELAY_MS * attempt));
|
|
168
160
|
}
|
|
169
|
-
pool.set(repoId, { db, available, checkedOut: 0, waiters: [], lastUsed: Date.now(), dbPath, pinned: !!opts?.pinned });
|
|
170
|
-
ensureIdleTimer();
|
|
171
|
-
return;
|
|
172
161
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
162
|
+
if (!shared) {
|
|
163
|
+
throw new Error(`LadybugDB unavailable for ${repoId}. Another process may be rebuilding the index. ` +
|
|
164
|
+
`Retry later. (${lastError?.message || 'unknown error'})`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
shared.refCount++;
|
|
168
|
+
const db = shared.db;
|
|
169
|
+
// Pre-create a small pool of connections
|
|
170
|
+
const available = [];
|
|
171
|
+
for (let i = 0; i < INITIAL_CONNS_PER_REPO; i++) {
|
|
172
|
+
available.push(createConnection(db));
|
|
173
|
+
}
|
|
174
|
+
pool.set(repoId, { db, available, checkedOut: 0, waiters: [], lastUsed: Date.now(), dbPath });
|
|
175
|
+
ensureIdleTimer();
|
|
176
|
+
// Load FTS extension once per shared Database
|
|
177
|
+
if (!shared.ftsLoaded) {
|
|
178
|
+
try {
|
|
179
|
+
await available[0].query('LOAD EXTENSION fts');
|
|
180
|
+
shared.ftsLoaded = true;
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Extension may not be installed — FTS queries will fail gracefully
|
|
181
184
|
}
|
|
182
185
|
}
|
|
183
|
-
throw new Error(`KuzuDB unavailable for ${repoId}. Another process may be rebuilding the index. ` +
|
|
184
|
-
`Retry later. (${lastError?.message || 'unknown error'})`);
|
|
185
186
|
};
|
|
186
187
|
/**
|
|
187
188
|
* Checkout a connection from the pool.
|
|
@@ -198,10 +199,7 @@ function checkout(entry) {
|
|
|
198
199
|
const totalConns = entry.available.length + entry.checkedOut;
|
|
199
200
|
if (totalConns < MAX_CONNS_PER_REPO) {
|
|
200
201
|
entry.checkedOut++;
|
|
201
|
-
|
|
202
|
-
// Load FTS on new connections (best-effort, don't block on failure)
|
|
203
|
-
loadFTSOnConnection(conn).catch(() => { });
|
|
204
|
-
return Promise.resolve(conn);
|
|
202
|
+
return Promise.resolve(createConnection(entry.db));
|
|
205
203
|
}
|
|
206
204
|
// At capacity — queue the caller with a timeout.
|
|
207
205
|
return new Promise((resolve, reject) => {
|
|
@@ -249,7 +247,7 @@ function withTimeout(promise, ms, label) {
|
|
|
249
247
|
export const executeQuery = async (repoId, cypher) => {
|
|
250
248
|
const entry = pool.get(repoId);
|
|
251
249
|
if (!entry) {
|
|
252
|
-
throw new Error(`
|
|
250
|
+
throw new Error(`LadybugDB not initialized for repo "${repoId}". Call initLbug first.`);
|
|
253
251
|
}
|
|
254
252
|
entry.lastUsed = Date.now();
|
|
255
253
|
const conn = await checkout(entry);
|
|
@@ -270,7 +268,7 @@ export const executeQuery = async (repoId, cypher) => {
|
|
|
270
268
|
export const executeParameterized = async (repoId, cypher, params) => {
|
|
271
269
|
const entry = pool.get(repoId);
|
|
272
270
|
if (!entry) {
|
|
273
|
-
throw new Error(`
|
|
271
|
+
throw new Error(`LadybugDB not initialized for repo "${repoId}". Call initLbug first.`);
|
|
274
272
|
}
|
|
275
273
|
entry.lastUsed = Date.now();
|
|
276
274
|
const conn = await checkout(entry);
|
|
@@ -294,7 +292,7 @@ export const executeParameterized = async (repoId, cypher, params) => {
|
|
|
294
292
|
* If repoId is provided, close only that repo's connections.
|
|
295
293
|
* If omitted, close all repos.
|
|
296
294
|
*/
|
|
297
|
-
export const
|
|
295
|
+
export const closeLbug = async (repoId) => {
|
|
298
296
|
if (repoId) {
|
|
299
297
|
closeOne(repoId);
|
|
300
298
|
return;
|
|
@@ -310,4 +308,4 @@ export const closeKuzu = async (repoId) => {
|
|
|
310
308
|
/**
|
|
311
309
|
* Check if a specific repo's pool is active
|
|
312
310
|
*/
|
|
313
|
-
export const
|
|
311
|
+
export const isLbugReady = (repoId) => pool.has(repoId);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides tool implementations using local .gitnexus/ indexes.
|
|
5
5
|
* Supports multiple indexed repositories via a global registry.
|
|
6
|
-
*
|
|
6
|
+
* LadybugDB connections are opened lazily per repo on first query.
|
|
7
7
|
*/
|
|
8
8
|
import { type RegistryEntry } from '../../storage/repo-manager.js';
|
|
9
9
|
/**
|
|
@@ -11,7 +11,7 @@ import { type RegistryEntry } from '../../storage/repo-manager.js';
|
|
|
11
11
|
* Matches common test file patterns across all supported languages.
|
|
12
12
|
*/
|
|
13
13
|
export declare function isTestFilePath(filePath: string): boolean;
|
|
14
|
-
/** Valid
|
|
14
|
+
/** Valid LadybugDB node labels for safe Cypher query construction */
|
|
15
15
|
export declare const VALID_NODE_LABELS: Set<string>;
|
|
16
16
|
/** Valid relation types for impact analysis filtering */
|
|
17
17
|
export declare const VALID_RELATION_TYPES: Set<string>;
|
|
@@ -33,7 +33,7 @@ interface RepoHandle {
|
|
|
33
33
|
name: string;
|
|
34
34
|
repoPath: string;
|
|
35
35
|
storagePath: string;
|
|
36
|
-
|
|
36
|
+
lbugPath: string;
|
|
37
37
|
indexedAt: string;
|
|
38
38
|
lastCommit: string;
|
|
39
39
|
stats?: RegistryEntry['stats'];
|
|
@@ -50,7 +50,7 @@ export declare class LocalBackend {
|
|
|
50
50
|
/**
|
|
51
51
|
* Re-read the global registry and update the in-memory repo map.
|
|
52
52
|
* New repos are added, existing repos are updated, removed repos are pruned.
|
|
53
|
-
*
|
|
53
|
+
* LadybugDB connections for removed repos are NOT closed (they idle-timeout naturally).
|
|
54
54
|
*/
|
|
55
55
|
private refreshRepos;
|
|
56
56
|
/**
|
|
@@ -100,7 +100,7 @@ export declare class LocalBackend {
|
|
|
100
100
|
*/
|
|
101
101
|
private query;
|
|
102
102
|
/**
|
|
103
|
-
* BM25 keyword search helper - uses
|
|
103
|
+
* BM25 keyword search helper - uses LadybugDB FTS for always-fresh results
|
|
104
104
|
*/
|
|
105
105
|
private bm25Search;
|
|
106
106
|
/**
|
|
@@ -117,7 +117,7 @@ export declare class LocalBackend {
|
|
|
117
117
|
/**
|
|
118
118
|
* Aggregate same-named clusters: group by heuristicLabel, sum symbols,
|
|
119
119
|
* weighted-average cohesion, filter out tiny clusters (<5 symbols).
|
|
120
|
-
* Raw communities stay intact in
|
|
120
|
+
* Raw communities stay intact in LadybugDB for Cypher queries.
|
|
121
121
|
*/
|
|
122
122
|
private aggregateClusters;
|
|
123
123
|
private overview;
|
|
@@ -144,6 +144,7 @@ export declare class LocalBackend {
|
|
|
144
144
|
*/
|
|
145
145
|
private rename;
|
|
146
146
|
private impact;
|
|
147
|
+
private _impactImpl;
|
|
147
148
|
/**
|
|
148
149
|
* Query clusters (communities) directly from graph.
|
|
149
150
|
* Used by getClustersResource — avoids legacy overview() dispatch.
|