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.
Files changed (102) hide show
  1. package/README.md +19 -18
  2. package/dist/cli/analyze.js +37 -28
  3. package/dist/cli/augment.js +1 -1
  4. package/dist/cli/eval-server.d.ts +1 -1
  5. package/dist/cli/eval-server.js +1 -1
  6. package/dist/cli/index.js +1 -0
  7. package/dist/cli/mcp.js +1 -1
  8. package/dist/cli/setup.js +25 -13
  9. package/dist/cli/status.js +13 -4
  10. package/dist/cli/tool.d.ts +1 -1
  11. package/dist/cli/tool.js +2 -2
  12. package/dist/cli/wiki.js +2 -2
  13. package/dist/config/ignore-service.d.ts +25 -0
  14. package/dist/config/ignore-service.js +76 -0
  15. package/dist/config/supported-languages.d.ts +1 -0
  16. package/dist/config/supported-languages.js +1 -1
  17. package/dist/core/augmentation/engine.js +94 -67
  18. package/dist/core/embeddings/embedder.d.ts +1 -1
  19. package/dist/core/embeddings/embedder.js +1 -1
  20. package/dist/core/embeddings/embedding-pipeline.d.ts +3 -3
  21. package/dist/core/embeddings/embedding-pipeline.js +52 -25
  22. package/dist/core/embeddings/types.d.ts +1 -1
  23. package/dist/core/ingestion/call-processor.d.ts +6 -7
  24. package/dist/core/ingestion/call-processor.js +490 -127
  25. package/dist/core/ingestion/call-routing.d.ts +53 -0
  26. package/dist/core/ingestion/call-routing.js +108 -0
  27. package/dist/core/ingestion/entry-point-scoring.js +13 -2
  28. package/dist/core/ingestion/export-detection.js +1 -0
  29. package/dist/core/ingestion/filesystem-walker.js +4 -3
  30. package/dist/core/ingestion/framework-detection.js +9 -0
  31. package/dist/core/ingestion/heritage-processor.d.ts +3 -4
  32. package/dist/core/ingestion/heritage-processor.js +40 -50
  33. package/dist/core/ingestion/import-processor.d.ts +3 -5
  34. package/dist/core/ingestion/import-processor.js +41 -10
  35. package/dist/core/ingestion/parsing-processor.d.ts +2 -1
  36. package/dist/core/ingestion/parsing-processor.js +41 -4
  37. package/dist/core/ingestion/pipeline.d.ts +5 -1
  38. package/dist/core/ingestion/pipeline.js +174 -121
  39. package/dist/core/ingestion/resolution-context.d.ts +53 -0
  40. package/dist/core/ingestion/resolution-context.js +132 -0
  41. package/dist/core/ingestion/resolvers/index.d.ts +2 -0
  42. package/dist/core/ingestion/resolvers/index.js +2 -0
  43. package/dist/core/ingestion/resolvers/python.d.ts +19 -0
  44. package/dist/core/ingestion/resolvers/python.js +52 -0
  45. package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
  46. package/dist/core/ingestion/resolvers/ruby.js +15 -0
  47. package/dist/core/ingestion/resolvers/standard.js +0 -22
  48. package/dist/core/ingestion/resolvers/utils.js +2 -0
  49. package/dist/core/ingestion/symbol-table.d.ts +3 -0
  50. package/dist/core/ingestion/symbol-table.js +1 -0
  51. package/dist/core/ingestion/tree-sitter-queries.d.ts +3 -2
  52. package/dist/core/ingestion/tree-sitter-queries.js +53 -1
  53. package/dist/core/ingestion/type-env.d.ts +32 -10
  54. package/dist/core/ingestion/type-env.js +520 -47
  55. package/dist/core/ingestion/type-extractors/c-cpp.js +326 -1
  56. package/dist/core/ingestion/type-extractors/csharp.js +282 -2
  57. package/dist/core/ingestion/type-extractors/go.js +333 -2
  58. package/dist/core/ingestion/type-extractors/index.d.ts +3 -2
  59. package/dist/core/ingestion/type-extractors/index.js +3 -1
  60. package/dist/core/ingestion/type-extractors/jvm.js +537 -4
  61. package/dist/core/ingestion/type-extractors/php.js +387 -7
  62. package/dist/core/ingestion/type-extractors/python.js +356 -5
  63. package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
  64. package/dist/core/ingestion/type-extractors/ruby.js +389 -0
  65. package/dist/core/ingestion/type-extractors/rust.js +399 -2
  66. package/dist/core/ingestion/type-extractors/shared.d.ts +116 -1
  67. package/dist/core/ingestion/type-extractors/shared.js +488 -14
  68. package/dist/core/ingestion/type-extractors/swift.js +95 -1
  69. package/dist/core/ingestion/type-extractors/types.d.ts +81 -0
  70. package/dist/core/ingestion/type-extractors/typescript.js +436 -2
  71. package/dist/core/ingestion/utils.d.ts +33 -2
  72. package/dist/core/ingestion/utils.js +399 -27
  73. package/dist/core/ingestion/workers/parse-worker.d.ts +18 -1
  74. package/dist/core/ingestion/workers/parse-worker.js +169 -19
  75. package/dist/core/{kuzu → lbug}/csv-generator.d.ts +1 -1
  76. package/dist/core/{kuzu → lbug}/csv-generator.js +1 -1
  77. package/dist/core/{kuzu/kuzu-adapter.d.ts → lbug/lbug-adapter.d.ts} +19 -19
  78. package/dist/core/{kuzu/kuzu-adapter.js → lbug/lbug-adapter.js} +70 -65
  79. package/dist/core/{kuzu → lbug}/schema.d.ts +1 -1
  80. package/dist/core/{kuzu → lbug}/schema.js +1 -1
  81. package/dist/core/search/bm25-index.d.ts +4 -4
  82. package/dist/core/search/bm25-index.js +10 -10
  83. package/dist/core/search/hybrid-search.d.ts +2 -2
  84. package/dist/core/search/hybrid-search.js +6 -6
  85. package/dist/core/tree-sitter/parser-loader.js +9 -2
  86. package/dist/core/wiki/generator.d.ts +2 -2
  87. package/dist/core/wiki/generator.js +4 -4
  88. package/dist/core/wiki/graph-queries.d.ts +4 -4
  89. package/dist/core/wiki/graph-queries.js +7 -7
  90. package/dist/mcp/core/{kuzu-adapter.d.ts → lbug-adapter.d.ts} +7 -7
  91. package/dist/mcp/core/{kuzu-adapter.js → lbug-adapter.js} +72 -43
  92. package/dist/mcp/local/local-backend.d.ts +6 -6
  93. package/dist/mcp/local/local-backend.js +25 -18
  94. package/dist/server/api.js +12 -12
  95. package/dist/server/mcp-http.d.ts +1 -1
  96. package/dist/server/mcp-http.js +1 -1
  97. package/dist/storage/repo-manager.d.ts +20 -2
  98. package/dist/storage/repo-manager.js +55 -1
  99. package/dist/types/pipeline.d.ts +1 -1
  100. package/package.json +5 -3
  101. package/dist/core/ingestion/symbol-resolver.d.ts +0 -32
  102. 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
- kuzuPath: path.join(bestMatch.storagePath, 'kuzu'),
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 kuzu adapter (skip unnecessary init)
85
- const { initKuzu, executeQuery, isKuzuReady } = await import('../../mcp/core/kuzu-adapter.js');
86
- const { searchFTSFromKuzu } = await import('../search/bm25-index.js');
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 KuzuDB if not already
89
- if (!isKuzuReady(repoId)) {
90
- await initKuzu(repoId, repo.kuzuPath);
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 searchFTSFromKuzu(pattern, 10, repoId);
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: For top matches, fetch callers/callees/processes
122
- // Also get cluster cohesion internally for ranking
123
- const enriched = [];
124
- const seen = new Set();
125
- for (const sym of symbolMatches.slice(0, 5)) {
126
- if (seen.has(sym.nodeId))
127
- continue;
128
- seen.add(sym.nodeId);
129
- const escaped = sym.nodeId.replace(/'/g, "''");
130
- // Callers
131
- let callers = [];
132
- try {
133
- const rows = await executeQuery(repoId, `
134
- MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(n {id: '${escaped}'})
135
- RETURN caller.name AS name
136
- LIMIT 3
137
- `);
138
- callers = rows.map((r) => r.name || r[0]).filter(Boolean);
139
- }
140
- catch { /* skip */ }
141
- // Callees
142
- let callees = [];
143
- try {
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
- catch { /* skip */ }
152
- // Processes
153
- let processes = [];
154
- try {
155
- const rows = await executeQuery(repoId, `
156
- MATCH (n {id: '${escaped}'})-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
157
- RETURN p.heuristicLabel AS label, r.step AS step, p.stepCount AS stepCount
158
- `);
159
- processes = rows.map((r) => {
160
- const label = r.label || r[0];
161
- const step = r.step || r[1];
162
- const stepCount = r.stepCount || r[2];
163
- return `${label} (step ${step}/${stepCount})`;
164
- }).filter(Boolean);
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
- catch { /* skip */ }
167
- // Cluster cohesion (internal ranking signal)
168
- let cohesion = 0;
169
- try {
170
- const rows = await executeQuery(repoId, `
171
- MATCH (n {id: '${escaped}'})-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
172
- RETURN c.cohesion AS cohesion
173
- LIMIT 1
174
- `);
175
- if (rows.length > 0) {
176
- cohesion = (rows[0].cohesion ?? rows[0][0]) || 0;
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
- catch { /* skip */ }
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 KuzuDB storage)
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 KuzuDB storage)
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 KuzuDB
5
+ * 1. Query embeddable nodes from LadybugDB
6
6
  * 2. Generate text representations
7
7
  * 3. Batch embed using transformers.js
8
- * 4. Update KuzuDB with embeddings
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 KuzuDB
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 KuzuDB
5
+ * 1. Query embeddable nodes from LadybugDB
6
6
  * 2. Generate text representations
7
7
  * 3. Batch embed using transformers.js
8
- * 4. Update KuzuDB with embeddings
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 KuzuDB
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 KuzuDB
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 KuzuDB with embeddings
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
- // Get metadata for each result by querying each node table
257
- const results = [];
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
- // Query the specific table for this node
265
- // File nodes don't have startLine/endLine
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 {id: '${nodeId.replace(/'/g, "''")}'})
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} {id: '${nodeId.replace(/'/g, "''")}'})
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
- if (nodeRows.length > 0) {
283
- const nodeRow = nodeRows[0];
284
- results.push({
285
- nodeId,
286
- name: nodeRow.name ?? nodeRow[0] ?? '',
287
- label,
288
- filePath: nodeRow.filePath ?? nodeRow[1] ?? '',
289
- distance,
290
- startLine: label !== 'File' ? (nodeRow.startLine ?? nodeRow[2]) : undefined,
291
- endLine: label !== 'File' ? (nodeRow.endLine ?? nodeRow[3]) : undefined,
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 KuzuDB query)
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 { SymbolTable } from './symbol-table.js';
4
- import { ImportMap, PackageMap, NamedImportMap } from './import-processor.js';
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, symbolTable: SymbolTable, importMap: ImportMap, packageMap?: PackageMap, onProgress?: (current: number, total: number) => void, namedImportMap?: NamedImportMap) => Promise<void>;
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[], symbolTable: SymbolTable, importMap: ImportMap, packageMap?: PackageMap, onProgress?: (current: number, total: number) => void, namedImportMap?: NamedImportMap) => Promise<void>;
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[], symbolTable: SymbolTable, importMap: ImportMap, packageMap?: PackageMap, onProgress?: (current: number, total: number) => void) => Promise<void>;
18
+ export declare const processRoutesFromExtracted: (graph: KnowledgeGraph, extractedRoutes: ExtractedRoute[], ctx: ResolutionContext, onProgress?: (current: number, total: number) => void) => Promise<void>;