gitnexus 1.4.0 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -18
- package/dist/cli/analyze.js +37 -28
- package/dist/cli/augment.js +1 -1
- package/dist/cli/eval-server.d.ts +1 -1
- package/dist/cli/eval-server.js +1 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/mcp.js +1 -1
- package/dist/cli/setup.js +25 -13
- package/dist/cli/status.js +13 -4
- package/dist/cli/tool.d.ts +1 -1
- package/dist/cli/tool.js +2 -2
- 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 +94 -67
- 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 +52 -25
- package/dist/core/embeddings/types.d.ts +1 -1
- package/dist/core/ingestion/call-processor.d.ts +6 -7
- package/dist/core/ingestion/call-processor.js +490 -127
- package/dist/core/ingestion/call-routing.d.ts +53 -0
- package/dist/core/ingestion/call-routing.js +108 -0
- package/dist/core/ingestion/entry-point-scoring.js +13 -2
- package/dist/core/ingestion/export-detection.js +1 -0
- package/dist/core/ingestion/filesystem-walker.js +4 -3
- package/dist/core/ingestion/framework-detection.js +9 -0
- package/dist/core/ingestion/heritage-processor.d.ts +3 -4
- package/dist/core/ingestion/heritage-processor.js +40 -50
- package/dist/core/ingestion/import-processor.d.ts +3 -5
- package/dist/core/ingestion/import-processor.js +41 -10
- package/dist/core/ingestion/parsing-processor.d.ts +2 -1
- package/dist/core/ingestion/parsing-processor.js +41 -4
- package/dist/core/ingestion/pipeline.d.ts +5 -1
- package/dist/core/ingestion/pipeline.js +174 -121
- package/dist/core/ingestion/resolution-context.d.ts +53 -0
- package/dist/core/ingestion/resolution-context.js +132 -0
- package/dist/core/ingestion/resolvers/index.d.ts +2 -0
- package/dist/core/ingestion/resolvers/index.js +2 -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/standard.js +0 -22
- package/dist/core/ingestion/resolvers/utils.js +2 -0
- package/dist/core/ingestion/symbol-table.d.ts +3 -0
- package/dist/core/ingestion/symbol-table.js +1 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +3 -2
- package/dist/core/ingestion/tree-sitter-queries.js +53 -1
- package/dist/core/ingestion/type-env.d.ts +32 -10
- package/dist/core/ingestion/type-env.js +520 -47
- package/dist/core/ingestion/type-extractors/c-cpp.js +326 -1
- package/dist/core/ingestion/type-extractors/csharp.js +282 -2
- package/dist/core/ingestion/type-extractors/go.js +333 -2
- package/dist/core/ingestion/type-extractors/index.d.ts +3 -2
- package/dist/core/ingestion/type-extractors/index.js +3 -1
- package/dist/core/ingestion/type-extractors/jvm.js +537 -4
- package/dist/core/ingestion/type-extractors/php.js +387 -7
- package/dist/core/ingestion/type-extractors/python.js +356 -5
- 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.js +399 -2
- package/dist/core/ingestion/type-extractors/shared.d.ts +116 -1
- package/dist/core/ingestion/type-extractors/shared.js +488 -14
- package/dist/core/ingestion/type-extractors/swift.js +95 -1
- package/dist/core/ingestion/type-extractors/types.d.ts +81 -0
- package/dist/core/ingestion/type-extractors/typescript.js +436 -2
- package/dist/core/ingestion/utils.d.ts +33 -2
- package/dist/core/ingestion/utils.js +399 -27
- package/dist/core/ingestion/workers/parse-worker.d.ts +18 -1
- package/dist/core/ingestion/workers/parse-worker.js +169 -19
- package/dist/core/{kuzu → lbug}/csv-generator.d.ts +1 -1
- package/dist/core/{kuzu → lbug}/csv-generator.js +1 -1
- 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} +70 -65
- package/dist/core/{kuzu → lbug}/schema.d.ts +1 -1
- package/dist/core/{kuzu → lbug}/schema.js +1 -1
- package/dist/core/search/bm25-index.d.ts +4 -4
- package/dist/core/search/bm25-index.js +10 -10
- package/dist/core/search/hybrid-search.d.ts +2 -2
- package/dist/core/search/hybrid-search.js +6 -6
- package/dist/core/tree-sitter/parser-loader.js +9 -2
- package/dist/core/wiki/generator.d.ts +2 -2
- package/dist/core/wiki/generator.js +4 -4
- package/dist/core/wiki/graph-queries.d.ts +4 -4
- package/dist/core/wiki/graph-queries.js +7 -7
- package/dist/mcp/core/{kuzu-adapter.d.ts → lbug-adapter.d.ts} +7 -7
- package/dist/mcp/core/{kuzu-adapter.js → lbug-adapter.js} +72 -43
- package/dist/mcp/local/local-backend.d.ts +6 -6
- package/dist/mcp/local/local-backend.js +25 -18
- 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/package.json +5 -3
- package/dist/core/ingestion/symbol-resolver.d.ts +0 -32
- package/dist/core/ingestion/symbol-resolver.js +0 -83
|
@@ -56,7 +56,7 @@ async function findRepoForCwd(cwd) {
|
|
|
56
56
|
return {
|
|
57
57
|
name: bestMatch.name,
|
|
58
58
|
storagePath: bestMatch.storagePath,
|
|
59
|
-
|
|
59
|
+
lbugPath: path.join(bestMatch.storagePath, 'lbug'),
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
catch {
|
|
@@ -81,16 +81,16 @@ export async function augment(pattern, cwd) {
|
|
|
81
81
|
const repo = await findRepoForCwd(workDir);
|
|
82
82
|
if (!repo)
|
|
83
83
|
return '';
|
|
84
|
-
// Lazy-load
|
|
85
|
-
const {
|
|
86
|
-
const {
|
|
84
|
+
// Lazy-load lbug adapter (skip unnecessary init)
|
|
85
|
+
const { initLbug, executeQuery, isLbugReady } = await import('../../mcp/core/lbug-adapter.js');
|
|
86
|
+
const { searchFTSFromLbug } = await import('../search/bm25-index.js');
|
|
87
87
|
const repoId = repo.name.toLowerCase();
|
|
88
|
-
// Init
|
|
89
|
-
if (!
|
|
90
|
-
await
|
|
88
|
+
// Init LadybugDB if not already
|
|
89
|
+
if (!isLbugReady(repoId)) {
|
|
90
|
+
await initLbug(repoId, repo.lbugPath);
|
|
91
91
|
}
|
|
92
92
|
// Step 1: BM25 search (fast, no embeddings)
|
|
93
|
-
const bm25Results = await
|
|
93
|
+
const bm25Results = await searchFTSFromLbug(pattern, 10, repoId);
|
|
94
94
|
if (bm25Results.length === 0)
|
|
95
95
|
return '';
|
|
96
96
|
// Step 2: Map BM25 file results to symbols
|
|
@@ -118,72 +118,99 @@ export async function augment(pattern, cwd) {
|
|
|
118
118
|
}
|
|
119
119
|
if (symbolMatches.length === 0)
|
|
120
120
|
return '';
|
|
121
|
-
// Step 3:
|
|
122
|
-
//
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const rows = await executeQuery(repoId, `
|
|
145
|
-
MATCH (n {id: '${escaped}'})-[:CodeRelation {type: 'CALLS'}]->(callee)
|
|
146
|
-
RETURN callee.name AS name
|
|
147
|
-
LIMIT 3
|
|
148
|
-
`);
|
|
149
|
-
callees = rows.map((r) => r.name || r[0]).filter(Boolean);
|
|
121
|
+
// Step 3: Batch-fetch callers/callees/processes/cohesion for top matches
|
|
122
|
+
// Uses batched WHERE n.id IN [...] queries instead of per-symbol queries
|
|
123
|
+
const uniqueSymbols = symbolMatches.slice(0, 5).filter((sym, i, arr) => arr.findIndex(s => s.nodeId === sym.nodeId) === i);
|
|
124
|
+
if (uniqueSymbols.length === 0)
|
|
125
|
+
return '';
|
|
126
|
+
const idList = uniqueSymbols.map(s => `'${s.nodeId.replace(/'/g, "''")}'`).join(', ');
|
|
127
|
+
// Batch fetch callers
|
|
128
|
+
const callersMap = new Map();
|
|
129
|
+
try {
|
|
130
|
+
const rows = await executeQuery(repoId, `
|
|
131
|
+
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(n)
|
|
132
|
+
WHERE n.id IN [${idList}]
|
|
133
|
+
RETURN n.id AS targetId, caller.name AS name
|
|
134
|
+
LIMIT 15
|
|
135
|
+
`);
|
|
136
|
+
for (const r of rows) {
|
|
137
|
+
const tid = r.targetId || r[0];
|
|
138
|
+
const name = r.name || r[1];
|
|
139
|
+
if (tid && name) {
|
|
140
|
+
if (!callersMap.has(tid))
|
|
141
|
+
callersMap.set(tid, []);
|
|
142
|
+
callersMap.get(tid).push(name);
|
|
143
|
+
}
|
|
150
144
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
145
|
+
}
|
|
146
|
+
catch { /* skip */ }
|
|
147
|
+
// Batch fetch callees
|
|
148
|
+
const calleesMap = new Map();
|
|
149
|
+
try {
|
|
150
|
+
const rows = await executeQuery(repoId, `
|
|
151
|
+
MATCH (n)-[:CodeRelation {type: 'CALLS'}]->(callee)
|
|
152
|
+
WHERE n.id IN [${idList}]
|
|
153
|
+
RETURN n.id AS sourceId, callee.name AS name
|
|
154
|
+
LIMIT 15
|
|
155
|
+
`);
|
|
156
|
+
for (const r of rows) {
|
|
157
|
+
const sid = r.sourceId || r[0];
|
|
158
|
+
const name = r.name || r[1];
|
|
159
|
+
if (sid && name) {
|
|
160
|
+
if (!calleesMap.has(sid))
|
|
161
|
+
calleesMap.set(sid, []);
|
|
162
|
+
calleesMap.get(sid).push(name);
|
|
163
|
+
}
|
|
165
164
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
165
|
+
}
|
|
166
|
+
catch { /* skip */ }
|
|
167
|
+
// Batch fetch processes
|
|
168
|
+
const processesMap = new Map();
|
|
169
|
+
try {
|
|
170
|
+
const rows = await executeQuery(repoId, `
|
|
171
|
+
MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
172
|
+
WHERE n.id IN [${idList}]
|
|
173
|
+
RETURN n.id AS nodeId, p.heuristicLabel AS label, r.step AS step, p.stepCount AS stepCount
|
|
174
|
+
`);
|
|
175
|
+
for (const r of rows) {
|
|
176
|
+
const nid = r.nodeId || r[0];
|
|
177
|
+
const label = r.label || r[1];
|
|
178
|
+
const step = r.step || r[2];
|
|
179
|
+
const stepCount = r.stepCount || r[3];
|
|
180
|
+
if (nid && label) {
|
|
181
|
+
if (!processesMap.has(nid))
|
|
182
|
+
processesMap.set(nid, []);
|
|
183
|
+
processesMap.get(nid).push(`${label} (step ${step}/${stepCount})`);
|
|
177
184
|
}
|
|
178
185
|
}
|
|
179
|
-
|
|
186
|
+
}
|
|
187
|
+
catch { /* skip */ }
|
|
188
|
+
// Batch fetch cohesion
|
|
189
|
+
const cohesionMap = new Map();
|
|
190
|
+
try {
|
|
191
|
+
const rows = await executeQuery(repoId, `
|
|
192
|
+
MATCH (n)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
|
|
193
|
+
WHERE n.id IN [${idList}]
|
|
194
|
+
RETURN n.id AS nodeId, c.cohesion AS cohesion
|
|
195
|
+
`);
|
|
196
|
+
for (const r of rows) {
|
|
197
|
+
const nid = r.nodeId || r[0];
|
|
198
|
+
const coh = r.cohesion ?? r[1] ?? 0;
|
|
199
|
+
if (nid)
|
|
200
|
+
cohesionMap.set(nid, coh);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch { /* skip */ }
|
|
204
|
+
// Assemble enriched results
|
|
205
|
+
const enriched = [];
|
|
206
|
+
for (const sym of uniqueSymbols) {
|
|
180
207
|
enriched.push({
|
|
181
208
|
name: sym.name,
|
|
182
209
|
filePath: sym.filePath,
|
|
183
|
-
callers,
|
|
184
|
-
callees,
|
|
185
|
-
processes,
|
|
186
|
-
cohesion,
|
|
210
|
+
callers: (callersMap.get(sym.nodeId) || []).slice(0, 3),
|
|
211
|
+
callees: (calleesMap.get(sym.nodeId) || []).slice(0, 3),
|
|
212
|
+
processes: processesMap.get(sym.nodeId) || [],
|
|
213
|
+
cohesion: cohesionMap.get(sym.nodeId) || 0,
|
|
187
214
|
});
|
|
188
215
|
}
|
|
189
216
|
if (enriched.length === 0)
|
|
@@ -50,7 +50,7 @@ export declare const embedText: (text: string) => Promise<Float32Array>;
|
|
|
50
50
|
*/
|
|
51
51
|
export declare const embedBatch: (texts: string[]) => Promise<Float32Array[]>;
|
|
52
52
|
/**
|
|
53
|
-
* Convert Float32Array to regular number array (for
|
|
53
|
+
* Convert Float32Array to regular number array (for LadybugDB storage)
|
|
54
54
|
*/
|
|
55
55
|
export declare const embeddingToArray: (embedding: Float32Array) => number[];
|
|
56
56
|
/**
|
|
@@ -225,7 +225,7 @@ export const embedBatch = async (texts) => {
|
|
|
225
225
|
return embeddings;
|
|
226
226
|
};
|
|
227
227
|
/**
|
|
228
|
-
* Convert Float32Array to regular number array (for
|
|
228
|
+
* Convert Float32Array to regular number array (for LadybugDB storage)
|
|
229
229
|
*/
|
|
230
230
|
export const embeddingToArray = (embedding) => {
|
|
231
231
|
return Array.from(embedding);
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Embedding Pipeline Module
|
|
3
3
|
*
|
|
4
4
|
* Orchestrates the background embedding process:
|
|
5
|
-
* 1. Query embeddable nodes from
|
|
5
|
+
* 1. Query embeddable nodes from LadybugDB
|
|
6
6
|
* 2. Generate text representations
|
|
7
7
|
* 3. Batch embed using transformers.js
|
|
8
|
-
* 4. Update
|
|
8
|
+
* 4. Update LadybugDB with embeddings
|
|
9
9
|
* 5. Create vector index for semantic search
|
|
10
10
|
*/
|
|
11
11
|
import { type EmbeddingProgress, type EmbeddingConfig, type SemanticSearchResult } from './types.js';
|
|
@@ -16,7 +16,7 @@ export type EmbeddingProgressCallback = (progress: EmbeddingProgress) => void;
|
|
|
16
16
|
/**
|
|
17
17
|
* Run the embedding pipeline
|
|
18
18
|
*
|
|
19
|
-
* @param executeQuery - Function to execute Cypher queries against
|
|
19
|
+
* @param executeQuery - Function to execute Cypher queries against LadybugDB
|
|
20
20
|
* @param executeWithReusedStatement - Function to execute with reused prepared statement
|
|
21
21
|
* @param onProgress - Callback for progress updates
|
|
22
22
|
* @param config - Optional configuration override
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Embedding Pipeline Module
|
|
3
3
|
*
|
|
4
4
|
* Orchestrates the background embedding process:
|
|
5
|
-
* 1. Query embeddable nodes from
|
|
5
|
+
* 1. Query embeddable nodes from LadybugDB
|
|
6
6
|
* 2. Generate text representations
|
|
7
7
|
* 3. Batch embed using transformers.js
|
|
8
|
-
* 4. Update
|
|
8
|
+
* 4. Update LadybugDB with embeddings
|
|
9
9
|
* 5. Create vector index for semantic search
|
|
10
10
|
*/
|
|
11
11
|
import { initEmbedder, embedBatch, embedText, embeddingToArray, isEmbedderReady } from './embedder.js';
|
|
@@ -13,7 +13,7 @@ import { generateBatchEmbeddingTexts } from './text-generator.js';
|
|
|
13
13
|
import { DEFAULT_EMBEDDING_CONFIG, EMBEDDABLE_LABELS, } from './types.js';
|
|
14
14
|
const isDev = process.env.NODE_ENV === 'development';
|
|
15
15
|
/**
|
|
16
|
-
* Query all embeddable nodes from
|
|
16
|
+
* Query all embeddable nodes from LadybugDB
|
|
17
17
|
* Uses table-specific queries (File has different schema than code elements)
|
|
18
18
|
*/
|
|
19
19
|
const queryEmbeddableNodes = async (executeQuery) => {
|
|
@@ -76,7 +76,20 @@ const batchInsertEmbeddings = async (executeWithReusedStatement, updates) => {
|
|
|
76
76
|
* Create the vector index for semantic search
|
|
77
77
|
* Now indexes the separate CodeEmbedding table
|
|
78
78
|
*/
|
|
79
|
+
let vectorExtensionLoaded = false;
|
|
79
80
|
const createVectorIndex = async (executeQuery) => {
|
|
81
|
+
// LadybugDB v0.15+ requires explicit VECTOR extension loading (once per session)
|
|
82
|
+
if (!vectorExtensionLoaded) {
|
|
83
|
+
try {
|
|
84
|
+
await executeQuery('INSTALL VECTOR');
|
|
85
|
+
await executeQuery('LOAD EXTENSION VECTOR');
|
|
86
|
+
vectorExtensionLoaded = true;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Extension may already be loaded — CREATE_VECTOR_INDEX will fail clearly if not
|
|
90
|
+
vectorExtensionLoaded = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
80
93
|
const cypher = `
|
|
81
94
|
CALL CREATE_VECTOR_INDEX('CodeEmbedding', 'code_embedding_idx', 'embedding', metric := 'cosine')
|
|
82
95
|
`;
|
|
@@ -93,7 +106,7 @@ const createVectorIndex = async (executeQuery) => {
|
|
|
93
106
|
/**
|
|
94
107
|
* Run the embedding pipeline
|
|
95
108
|
*
|
|
96
|
-
* @param executeQuery - Function to execute Cypher queries against
|
|
109
|
+
* @param executeQuery - Function to execute Cypher queries against LadybugDB
|
|
97
110
|
* @param executeWithReusedStatement - Function to execute with reused prepared statement
|
|
98
111
|
* @param onProgress - Callback for progress updates
|
|
99
112
|
* @param config - Optional configuration override
|
|
@@ -167,7 +180,7 @@ export const runEmbeddingPipeline = async (executeQuery, executeWithReusedStatem
|
|
|
167
180
|
const texts = generateBatchEmbeddingTexts(batch, finalConfig);
|
|
168
181
|
// Embed the batch
|
|
169
182
|
const embeddings = await embedBatch(texts);
|
|
170
|
-
// Update
|
|
183
|
+
// Update LadybugDB with embeddings
|
|
171
184
|
const updates = batch.map((node, i) => ({
|
|
172
185
|
id: node.id,
|
|
173
186
|
embedding: embeddingToArray(embeddings[i]),
|
|
@@ -253,49 +266,63 @@ export const semanticSearch = async (executeQuery, query, k = 10, maxDistance =
|
|
|
253
266
|
if (embResults.length === 0) {
|
|
254
267
|
return [];
|
|
255
268
|
}
|
|
256
|
-
//
|
|
257
|
-
const
|
|
269
|
+
// Group results by label for batched metadata queries
|
|
270
|
+
const byLabel = new Map();
|
|
258
271
|
for (const embRow of embResults) {
|
|
259
272
|
const nodeId = embRow.nodeId ?? embRow[0];
|
|
260
273
|
const distance = embRow.distance ?? embRow[1];
|
|
261
|
-
// Extract label from node ID (format: Label:path:name)
|
|
262
274
|
const labelEndIdx = nodeId.indexOf(':');
|
|
263
275
|
const label = labelEndIdx > 0 ? nodeId.substring(0, labelEndIdx) : 'Unknown';
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
if (!byLabel.has(label))
|
|
277
|
+
byLabel.set(label, []);
|
|
278
|
+
byLabel.get(label).push({ nodeId, distance });
|
|
279
|
+
}
|
|
280
|
+
// Batch-fetch metadata per label
|
|
281
|
+
const results = [];
|
|
282
|
+
for (const [label, items] of byLabel) {
|
|
283
|
+
const idList = items.map(i => `'${i.nodeId.replace(/'/g, "''")}'`).join(', ');
|
|
266
284
|
try {
|
|
267
285
|
let nodeQuery;
|
|
268
286
|
if (label === 'File') {
|
|
269
287
|
nodeQuery = `
|
|
270
|
-
MATCH (n:File
|
|
271
|
-
RETURN n.name AS name, n.filePath AS filePath
|
|
288
|
+
MATCH (n:File) WHERE n.id IN [${idList}]
|
|
289
|
+
RETURN n.id AS id, n.name AS name, n.filePath AS filePath
|
|
272
290
|
`;
|
|
273
291
|
}
|
|
274
292
|
else {
|
|
275
293
|
nodeQuery = `
|
|
276
|
-
MATCH (n:${label}
|
|
277
|
-
RETURN n.name AS name, n.filePath AS filePath,
|
|
294
|
+
MATCH (n:${label}) WHERE n.id IN [${idList}]
|
|
295
|
+
RETURN n.id AS id, n.name AS name, n.filePath AS filePath,
|
|
278
296
|
n.startLine AS startLine, n.endLine AS endLine
|
|
279
297
|
`;
|
|
280
298
|
}
|
|
281
299
|
const nodeRows = await executeQuery(nodeQuery);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
300
|
+
const rowMap = new Map();
|
|
301
|
+
for (const row of nodeRows) {
|
|
302
|
+
const id = row.id ?? row[0];
|
|
303
|
+
rowMap.set(id, row);
|
|
304
|
+
}
|
|
305
|
+
for (const item of items) {
|
|
306
|
+
const nodeRow = rowMap.get(item.nodeId);
|
|
307
|
+
if (nodeRow) {
|
|
308
|
+
results.push({
|
|
309
|
+
nodeId: item.nodeId,
|
|
310
|
+
name: nodeRow.name ?? nodeRow[1] ?? '',
|
|
311
|
+
label,
|
|
312
|
+
filePath: nodeRow.filePath ?? nodeRow[2] ?? '',
|
|
313
|
+
distance: item.distance,
|
|
314
|
+
startLine: label !== 'File' ? (nodeRow.startLine ?? nodeRow[3]) : undefined,
|
|
315
|
+
endLine: label !== 'File' ? (nodeRow.endLine ?? nodeRow[4]) : undefined,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
293
318
|
}
|
|
294
319
|
}
|
|
295
320
|
catch {
|
|
296
321
|
// Table might not exist, skip
|
|
297
322
|
}
|
|
298
323
|
}
|
|
324
|
+
// Re-sort by distance since batch queries may have mixed order
|
|
325
|
+
results.sort((a, b) => a.distance - b.distance);
|
|
299
326
|
return results;
|
|
300
327
|
};
|
|
301
328
|
/**
|
|
@@ -64,7 +64,7 @@ export interface SemanticSearchResult {
|
|
|
64
64
|
endLine?: number;
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
* Node data for embedding (minimal structure from
|
|
67
|
+
* Node data for embedding (minimal structure from LadybugDB query)
|
|
68
68
|
*/
|
|
69
69
|
export interface EmbeddableNode {
|
|
70
70
|
id: string;
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { KnowledgeGraph } from '../graph/types.js';
|
|
2
2
|
import { ASTCache } from './ast-cache.js';
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
import type { ExtractedCall, ExtractedRoute } from './workers/parse-worker.js';
|
|
3
|
+
import type { ResolutionContext } from './resolution-context.js';
|
|
4
|
+
import type { ExtractedCall, ExtractedHeritage, ExtractedRoute, FileConstructorBindings } from './workers/parse-worker.js';
|
|
6
5
|
export declare const processCalls: (graph: KnowledgeGraph, files: {
|
|
7
6
|
path: string;
|
|
8
7
|
content: string;
|
|
9
|
-
}[], astCache: ASTCache,
|
|
8
|
+
}[], astCache: ASTCache, ctx: ResolutionContext, onProgress?: (current: number, total: number) => void) => Promise<ExtractedHeritage[]>;
|
|
9
|
+
export declare const extractReturnTypeName: (raw: string, depth?: number) => string | undefined;
|
|
10
10
|
/**
|
|
11
11
|
* Fast path: resolve pre-extracted call sites from workers.
|
|
12
12
|
* No AST parsing — workers already extracted calledName + sourceId.
|
|
13
|
-
* This function only does symbol table lookups + graph mutations.
|
|
14
13
|
*/
|
|
15
|
-
export declare const processCallsFromExtracted: (graph: KnowledgeGraph, extractedCalls: ExtractedCall[],
|
|
14
|
+
export declare const processCallsFromExtracted: (graph: KnowledgeGraph, extractedCalls: ExtractedCall[], ctx: ResolutionContext, onProgress?: (current: number, total: number) => void, constructorBindings?: FileConstructorBindings[]) => Promise<void>;
|
|
16
15
|
/**
|
|
17
16
|
* Resolve pre-extracted Laravel routes to CALLS edges from route files to controller methods.
|
|
18
17
|
*/
|
|
19
|
-
export declare const processRoutesFromExtracted: (graph: KnowledgeGraph, extractedRoutes: ExtractedRoute[],
|
|
18
|
+
export declare const processRoutesFromExtracted: (graph: KnowledgeGraph, extractedRoutes: ExtractedRoute[], ctx: ResolutionContext, onProgress?: (current: number, total: number) => void) => Promise<void>;
|