gitnexus 1.6.2-rc.2 → 1.6.2-rc.21

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 (198) hide show
  1. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  2. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  3. package/dist/_shared/lbug/schema-constants.js +1 -0
  4. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  5. package/dist/cli/analyze.js +3 -0
  6. package/dist/core/embeddings/ast-utils.d.ts +22 -0
  7. package/dist/core/embeddings/ast-utils.js +105 -0
  8. package/dist/core/embeddings/character-chunk.d.ts +12 -0
  9. package/dist/core/embeddings/character-chunk.js +43 -0
  10. package/dist/core/embeddings/chunker.d.ts +14 -0
  11. package/dist/core/embeddings/chunker.js +234 -0
  12. package/dist/core/embeddings/embedder.js +5 -0
  13. package/dist/core/embeddings/embedding-pipeline.d.ts +29 -24
  14. package/dist/core/embeddings/embedding-pipeline.js +244 -125
  15. package/dist/core/embeddings/line-index.d.ts +7 -0
  16. package/dist/core/embeddings/line-index.js +42 -0
  17. package/dist/core/embeddings/server-mapping.d.ts +15 -0
  18. package/dist/core/embeddings/server-mapping.js +33 -0
  19. package/dist/core/embeddings/structural-extractor.d.ts +15 -0
  20. package/dist/core/embeddings/structural-extractor.js +58 -0
  21. package/dist/core/embeddings/text-generator.d.ts +20 -13
  22. package/dist/core/embeddings/text-generator.js +151 -119
  23. package/dist/core/embeddings/types.d.ts +81 -3
  24. package/dist/core/embeddings/types.js +105 -3
  25. package/dist/core/group/extractors/http-patterns/node.js +130 -0
  26. package/dist/core/group/extractors/manifest-extractor.js +20 -5
  27. package/dist/core/group/sync.js +49 -1
  28. package/dist/core/ingestion/call-extractors/configs/c-cpp.d.ts +3 -0
  29. package/dist/core/ingestion/call-extractors/configs/c-cpp.js +8 -0
  30. package/dist/core/ingestion/call-extractors/configs/csharp.d.ts +2 -0
  31. package/dist/core/ingestion/call-extractors/configs/csharp.js +6 -0
  32. package/dist/core/ingestion/call-extractors/configs/dart.d.ts +2 -0
  33. package/dist/core/ingestion/call-extractors/configs/dart.js +5 -0
  34. package/dist/core/ingestion/call-extractors/configs/go.d.ts +2 -0
  35. package/dist/core/ingestion/call-extractors/configs/go.js +5 -0
  36. package/dist/core/ingestion/call-extractors/configs/jvm.d.ts +3 -0
  37. package/dist/core/ingestion/call-extractors/configs/jvm.js +51 -0
  38. package/dist/core/ingestion/call-extractors/configs/php.d.ts +2 -0
  39. package/dist/core/ingestion/call-extractors/configs/php.js +5 -0
  40. package/dist/core/ingestion/call-extractors/configs/python.d.ts +2 -0
  41. package/dist/core/ingestion/call-extractors/configs/python.js +5 -0
  42. package/dist/core/ingestion/call-extractors/configs/ruby.d.ts +2 -0
  43. package/dist/core/ingestion/call-extractors/configs/ruby.js +5 -0
  44. package/dist/core/ingestion/call-extractors/configs/rust.d.ts +2 -0
  45. package/dist/core/ingestion/call-extractors/configs/rust.js +5 -0
  46. package/dist/core/ingestion/call-extractors/configs/swift.d.ts +2 -0
  47. package/dist/core/ingestion/call-extractors/configs/swift.js +5 -0
  48. package/dist/core/ingestion/call-extractors/configs/typescript-javascript.d.ts +3 -0
  49. package/dist/core/ingestion/call-extractors/configs/typescript-javascript.js +8 -0
  50. package/dist/core/ingestion/call-extractors/generic.d.ts +5 -0
  51. package/dist/core/ingestion/call-extractors/generic.js +59 -0
  52. package/dist/core/ingestion/call-processor.d.ts +1 -3
  53. package/dist/core/ingestion/call-processor.js +49 -47
  54. package/dist/core/ingestion/call-types.d.ts +60 -0
  55. package/dist/core/ingestion/call-types.js +2 -0
  56. package/dist/core/ingestion/class-extractors/configs/c-cpp.d.ts +3 -0
  57. package/dist/core/ingestion/class-extractors/configs/c-cpp.js +11 -0
  58. package/dist/core/ingestion/class-extractors/configs/csharp.d.ts +2 -0
  59. package/dist/core/ingestion/class-extractors/configs/csharp.js +21 -0
  60. package/dist/core/ingestion/class-extractors/configs/dart.d.ts +2 -0
  61. package/dist/core/ingestion/class-extractors/configs/dart.js +7 -0
  62. package/dist/core/ingestion/class-extractors/configs/go.d.ts +2 -0
  63. package/dist/core/ingestion/class-extractors/configs/go.js +20 -0
  64. package/dist/core/ingestion/class-extractors/configs/jvm.d.ts +3 -0
  65. package/dist/core/ingestion/class-extractors/configs/jvm.js +35 -0
  66. package/dist/core/ingestion/class-extractors/configs/php.d.ts +2 -0
  67. package/dist/core/ingestion/class-extractors/configs/php.js +7 -0
  68. package/dist/core/ingestion/class-extractors/configs/python.d.ts +2 -0
  69. package/dist/core/ingestion/class-extractors/configs/python.js +7 -0
  70. package/dist/core/ingestion/class-extractors/configs/ruby.d.ts +2 -0
  71. package/dist/core/ingestion/class-extractors/configs/ruby.js +7 -0
  72. package/dist/core/ingestion/class-extractors/configs/rust.d.ts +2 -0
  73. package/dist/core/ingestion/class-extractors/configs/rust.js +7 -0
  74. package/dist/core/ingestion/class-extractors/configs/swift.d.ts +2 -0
  75. package/dist/core/ingestion/class-extractors/configs/swift.js +18 -0
  76. package/dist/core/ingestion/class-extractors/configs/typescript-javascript.d.ts +4 -0
  77. package/dist/core/ingestion/class-extractors/configs/typescript-javascript.js +28 -0
  78. package/dist/core/ingestion/field-types.d.ts +1 -1
  79. package/dist/core/ingestion/import-resolvers/configs/c-cpp.d.ts +7 -0
  80. package/dist/core/ingestion/import-resolvers/configs/c-cpp.js +14 -0
  81. package/dist/core/ingestion/import-resolvers/configs/csharp.d.ts +8 -0
  82. package/dist/core/ingestion/import-resolvers/configs/csharp.js +27 -0
  83. package/dist/core/ingestion/import-resolvers/configs/dart.d.ts +17 -0
  84. package/dist/core/ingestion/import-resolvers/{dart.js → configs/dart.js} +26 -16
  85. package/dist/core/ingestion/import-resolvers/configs/go.d.ts +8 -0
  86. package/dist/core/ingestion/import-resolvers/configs/go.js +26 -0
  87. package/dist/core/ingestion/import-resolvers/configs/jvm.d.ts +13 -0
  88. package/dist/core/ingestion/import-resolvers/configs/jvm.js +68 -0
  89. package/dist/core/ingestion/import-resolvers/configs/php.d.ts +8 -0
  90. package/dist/core/ingestion/import-resolvers/configs/php.js +15 -0
  91. package/dist/core/ingestion/import-resolvers/configs/python.d.ts +12 -0
  92. package/dist/core/ingestion/import-resolvers/configs/python.js +41 -0
  93. package/dist/core/ingestion/import-resolvers/configs/ruby.d.ts +8 -0
  94. package/dist/core/ingestion/import-resolvers/configs/ruby.js +16 -0
  95. package/dist/core/ingestion/import-resolvers/configs/rust.d.ts +8 -0
  96. package/dist/core/ingestion/import-resolvers/configs/rust.js +54 -0
  97. package/dist/core/ingestion/import-resolvers/configs/swift.d.ts +8 -0
  98. package/dist/core/ingestion/import-resolvers/{swift.js → configs/swift.js} +10 -5
  99. package/dist/core/ingestion/import-resolvers/configs/typescript-javascript.d.ts +9 -0
  100. package/dist/core/ingestion/import-resolvers/configs/typescript-javascript.js +23 -0
  101. package/dist/core/ingestion/import-resolvers/csharp.d.ts +4 -5
  102. package/dist/core/ingestion/import-resolvers/csharp.js +4 -20
  103. package/dist/core/ingestion/import-resolvers/go.d.ts +4 -5
  104. package/dist/core/ingestion/import-resolvers/go.js +4 -19
  105. package/dist/core/ingestion/import-resolvers/jvm.d.ts +5 -10
  106. package/dist/core/ingestion/import-resolvers/jvm.js +5 -58
  107. package/dist/core/ingestion/import-resolvers/php.d.ts +4 -5
  108. package/dist/core/ingestion/import-resolvers/php.js +4 -7
  109. package/dist/core/ingestion/import-resolvers/python.d.ts +3 -6
  110. package/dist/core/ingestion/import-resolvers/python.js +3 -18
  111. package/dist/core/ingestion/import-resolvers/resolver-factory.d.ts +24 -0
  112. package/dist/core/ingestion/import-resolvers/resolver-factory.js +33 -0
  113. package/dist/core/ingestion/import-resolvers/ruby.d.ts +4 -5
  114. package/dist/core/ingestion/import-resolvers/ruby.js +4 -7
  115. package/dist/core/ingestion/import-resolvers/rust.d.ts +4 -5
  116. package/dist/core/ingestion/import-resolvers/rust.js +4 -47
  117. package/dist/core/ingestion/import-resolvers/standard.d.ts +3 -9
  118. package/dist/core/ingestion/import-resolvers/standard.js +7 -8
  119. package/dist/core/ingestion/import-resolvers/types.d.ts +24 -0
  120. package/dist/core/ingestion/language-provider.d.ts +12 -0
  121. package/dist/core/ingestion/languages/c-cpp.js +15 -12
  122. package/dist/core/ingestion/languages/csharp.js +11 -21
  123. package/dist/core/ingestion/languages/dart.js +11 -7
  124. package/dist/core/ingestion/languages/go.js +11 -20
  125. package/dist/core/ingestion/languages/java.js +11 -18
  126. package/dist/core/ingestion/languages/kotlin.js +11 -13
  127. package/dist/core/ingestion/languages/php.js +11 -7
  128. package/dist/core/ingestion/languages/python.js +11 -7
  129. package/dist/core/ingestion/languages/ruby.js +11 -7
  130. package/dist/core/ingestion/languages/rust.js +11 -7
  131. package/dist/core/ingestion/languages/swift.js +11 -18
  132. package/dist/core/ingestion/languages/typescript.js +15 -23
  133. package/dist/core/ingestion/languages/vue.js +11 -17
  134. package/dist/core/ingestion/model/index.d.ts +2 -2
  135. package/dist/core/ingestion/model/index.js +1 -1
  136. package/dist/core/ingestion/model/resolve.d.ts +3 -0
  137. package/dist/core/ingestion/model/resolve.js +6 -2
  138. package/dist/core/ingestion/parsing-processor.d.ts +1 -2
  139. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
  140. package/dist/core/ingestion/tree-sitter-queries.js +81 -0
  141. package/dist/core/ingestion/type-env.d.ts +1 -1
  142. package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -1
  143. package/dist/core/ingestion/utils/ast-helpers.js +3 -0
  144. package/dist/core/ingestion/variable-extractors/configs/c-cpp.d.ts +3 -0
  145. package/dist/core/ingestion/variable-extractors/configs/c-cpp.js +81 -0
  146. package/dist/core/ingestion/variable-extractors/configs/csharp.d.ts +9 -0
  147. package/dist/core/ingestion/variable-extractors/configs/csharp.js +63 -0
  148. package/dist/core/ingestion/variable-extractors/configs/dart.d.ts +2 -0
  149. package/dist/core/ingestion/variable-extractors/configs/dart.js +94 -0
  150. package/dist/core/ingestion/variable-extractors/configs/go.d.ts +2 -0
  151. package/dist/core/ingestion/variable-extractors/configs/go.js +83 -0
  152. package/dist/core/ingestion/variable-extractors/configs/jvm.d.ts +18 -0
  153. package/dist/core/ingestion/variable-extractors/configs/jvm.js +115 -0
  154. package/dist/core/ingestion/variable-extractors/configs/php.d.ts +14 -0
  155. package/dist/core/ingestion/variable-extractors/configs/php.js +58 -0
  156. package/dist/core/ingestion/variable-extractors/configs/python.d.ts +2 -0
  157. package/dist/core/ingestion/variable-extractors/configs/python.js +101 -0
  158. package/dist/core/ingestion/variable-extractors/configs/ruby.d.ts +11 -0
  159. package/dist/core/ingestion/variable-extractors/configs/ruby.js +52 -0
  160. package/dist/core/ingestion/variable-extractors/configs/rust.d.ts +2 -0
  161. package/dist/core/ingestion/variable-extractors/configs/rust.js +76 -0
  162. package/dist/core/ingestion/variable-extractors/configs/swift.d.ts +2 -0
  163. package/dist/core/ingestion/variable-extractors/configs/swift.js +88 -0
  164. package/dist/core/ingestion/variable-extractors/configs/typescript-javascript.d.ts +3 -0
  165. package/dist/core/ingestion/variable-extractors/configs/typescript-javascript.js +83 -0
  166. package/dist/core/ingestion/variable-extractors/generic.d.ts +5 -0
  167. package/dist/core/ingestion/variable-extractors/generic.js +80 -0
  168. package/dist/core/ingestion/variable-types.d.ts +82 -0
  169. package/dist/core/ingestion/variable-types.js +2 -0
  170. package/dist/core/ingestion/workers/parse-worker.js +196 -166
  171. package/dist/core/ingestion/workers/worker-pool.js +3 -0
  172. package/dist/core/lbug/csv-generator.js +1 -0
  173. package/dist/core/lbug/lbug-adapter.d.ts +13 -4
  174. package/dist/core/lbug/lbug-adapter.js +166 -81
  175. package/dist/core/lbug/schema.d.ts +9 -1
  176. package/dist/core/lbug/schema.js +19 -2
  177. package/dist/core/run-analyze.js +17 -4
  178. package/dist/core/tree-sitter/parser-loader.d.ts +3 -0
  179. package/dist/core/tree-sitter/parser-loader.js +17 -8
  180. package/dist/mcp/core/embedder.js +5 -0
  181. package/dist/mcp/local/local-backend.js +29 -19
  182. package/dist/server/api.js +10 -21
  183. package/package.json +5 -3
  184. package/scripts/build-tree-sitter-proto.cjs +82 -0
  185. package/vendor/node_modules/node-addon-api/node_addon_api.Makefile +6 -0
  186. package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +104 -0
  187. package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +108 -0
  188. package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +104 -0
  189. package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +104 -0
  190. package/vendor/tree-sitter-proto/package.json +1 -7
  191. package/dist/core/ingestion/call-sites/extract-language-call-site.d.ts +0 -10
  192. package/dist/core/ingestion/call-sites/extract-language-call-site.js +0 -22
  193. package/dist/core/ingestion/call-sites/java.d.ts +0 -9
  194. package/dist/core/ingestion/call-sites/java.js +0 -30
  195. package/dist/core/ingestion/import-resolvers/dart.d.ts +0 -7
  196. package/dist/core/ingestion/import-resolvers/swift.d.ts +0 -7
  197. package/dist/core/ingestion/import-resolvers/vue.d.ts +0 -8
  198. package/dist/core/ingestion/import-resolvers/vue.js +0 -9
@@ -36,8 +36,7 @@ try {
36
36
  catch { }
37
37
  import { getLanguageFromFilename } from '../../../_shared/index.js';
38
38
  import { FUNCTION_NODE_TYPES, getDefinitionNodeFromCaptures, findEnclosingClassInfo, getLabelFromCaptures, findDescendant, extractStringContent, genericFuncName, inferFunctionLabel, CLASS_CONTAINER_TYPES, } from '../utils/ast-helpers.js';
39
- import { countCallArguments, inferCallForm, extractReceiverName, extractReceiverNode, extractMixedChain, extractCallArgTypes, } from '../utils/call-analysis.js';
40
- import { extractParsedCallSite } from '../call-sites/extract-language-call-site.js';
39
+ import { extractCallArgTypes } from '../utils/call-analysis.js';
41
40
  import { buildTypeEnv } from '../type-env.js';
42
41
  import { detectFrameworkFromAST } from '../framework-detection.js';
43
42
  import { generateId } from '../../../lib/utils.js';
@@ -1081,6 +1080,10 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
1081
1080
  }
1082
1081
  // Per-file map: decorator end-line → decorator info, for associating with definitions
1083
1082
  const fileDecorators = new Map();
1083
+ // Track start indices of definition nodes already processed by higher-priority captures
1084
+ // (e.g. @definition.function) to avoid duplicate nodes when @definition.const/@definition.variable
1085
+ // patterns overlap with the same source range.
1086
+ const processedDefinitionNodes = new Set();
1084
1087
  for (const match of matches) {
1085
1088
  const captureMap = {};
1086
1089
  for (const c of match.captures) {
@@ -1248,98 +1251,125 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
1248
1251
  }
1249
1252
  // Extract call sites
1250
1253
  if (captureMap['call']) {
1251
- const callNode0 = captureMap['call'];
1252
- const languageSeed = extractParsedCallSite(language, callNode0);
1253
- if (languageSeed) {
1254
- if (!provider.isBuiltInName(languageSeed.calledName)) {
1255
- const sourceId = findEnclosingFunctionId(callNode0, file.path, provider) ||
1256
- generateId('File', file.path);
1257
- const receiverName = languageSeed.callForm === 'member' ? languageSeed.receiverName : undefined;
1258
- let receiverTypeName = receiverName
1259
- ? typeEnv.lookup(receiverName, callNode0)
1260
- : undefined;
1261
- // Type-as-receiver (e.g. Java `User::getName`): no TypeEnv binding for the class name
1262
- if (receiverName !== undefined &&
1263
- receiverTypeName === undefined &&
1264
- languageSeed.callForm === 'member' &&
1265
- (language === SupportedLanguages.Java ||
1266
- language === SupportedLanguages.CSharp ||
1267
- language === SupportedLanguages.Kotlin)) {
1268
- const c0 = receiverName.charCodeAt(0);
1269
- if (c0 >= 65 && c0 <= 90)
1270
- receiverTypeName = receiverName;
1271
- }
1272
- result.calls.push({
1273
- filePath: file.path,
1274
- calledName: languageSeed.calledName,
1275
- sourceId,
1276
- callForm: languageSeed.callForm,
1277
- ...(receiverName !== undefined ? { receiverName } : {}),
1278
- ...(receiverTypeName !== undefined ? { receiverTypeName } : {}),
1279
- });
1280
- }
1281
- continue;
1282
- }
1254
+ const callNode = captureMap['call'];
1283
1255
  const callNameNode = captureMap['call.name'];
1284
- if (callNameNode) {
1285
- const calledName = callNameNode.text;
1286
- // Dispatch: route language-specific calls (heritage, properties, imports)
1287
- const routed = callRouter?.(calledName, captureMap['call']);
1288
- if (routed) {
1289
- if (routed.kind === 'skip')
1290
- continue;
1291
- if (routed.kind === 'import') {
1292
- result.imports.push({
1256
+ const callExtractor = provider.callExtractor;
1257
+ if (callExtractor) {
1258
+ // ── Path 1: Language-specific call site (bypasses routing) ────
1259
+ // Try language-specific extraction (e.g. Java `::` method references)
1260
+ // without callNameNode. If successful, skip routing and the generic
1261
+ // path entirely.
1262
+ const langCallSite = callExtractor.extract(callNode, undefined);
1263
+ if (langCallSite) {
1264
+ if (!provider.isBuiltInName(langCallSite.calledName)) {
1265
+ const sourceId = findEnclosingFunctionId(callNode, file.path, provider) ||
1266
+ generateId('File', file.path);
1267
+ const receiverName = langCallSite.callForm === 'member' ? langCallSite.receiverName : undefined;
1268
+ let receiverTypeName = receiverName
1269
+ ? typeEnv.lookup(receiverName, callNode)
1270
+ : undefined;
1271
+ // Type-as-receiver heuristic (e.g. Java `User::getName`)
1272
+ if (langCallSite.typeAsReceiverHeuristic &&
1273
+ receiverName !== undefined &&
1274
+ receiverTypeName === undefined &&
1275
+ langCallSite.callForm === 'member') {
1276
+ const c0 = receiverName.charCodeAt(0);
1277
+ if (c0 >= 65 && c0 <= 90)
1278
+ receiverTypeName = receiverName;
1279
+ }
1280
+ result.calls.push({
1293
1281
  filePath: file.path,
1294
- rawImportPath: routed.importPath,
1295
- language,
1282
+ calledName: langCallSite.calledName,
1283
+ sourceId,
1284
+ callForm: langCallSite.callForm,
1285
+ ...(receiverName !== undefined ? { receiverName } : {}),
1286
+ ...(receiverTypeName !== undefined ? { receiverTypeName } : {}),
1296
1287
  });
1297
- continue;
1298
1288
  }
1299
- if (routed.kind === 'heritage') {
1300
- for (const item of routed.items) {
1301
- result.heritage.push({
1289
+ continue;
1290
+ }
1291
+ // ── Path 2: Generic extraction via @call.name ────────────────
1292
+ if (callNameNode) {
1293
+ const calledName = callNameNode.text;
1294
+ // Dispatch: route language-specific calls (heritage, properties, imports)
1295
+ const routed = callRouter?.(calledName, captureMap['call']);
1296
+ if (routed) {
1297
+ if (routed.kind === 'skip')
1298
+ continue;
1299
+ if (routed.kind === 'import') {
1300
+ result.imports.push({
1302
1301
  filePath: file.path,
1303
- className: item.enclosingClass,
1304
- parentName: item.mixinName,
1305
- kind: item.heritageKind,
1302
+ rawImportPath: routed.importPath,
1303
+ language,
1306
1304
  });
1305
+ continue;
1307
1306
  }
1308
- continue;
1309
- }
1310
- if (routed.kind === 'properties') {
1311
- const propEnclosingInfo = cachedFindEnclosingClassInfo(captureMap['call'], file.path, provider.resolveEnclosingOwner);
1312
- const propEnclosingClassId = propEnclosingInfo?.classId ?? null;
1313
- // Enrich routed properties with FieldExtractor metadata
1314
- let routedFieldMap;
1315
- if (provider.fieldExtractor && typeEnv) {
1316
- const classNode = findEnclosingClassNode(captureMap['call']);
1317
- if (classNode) {
1318
- routedFieldMap = getFieldInfo(classNode, provider, {
1319
- typeEnv,
1320
- symbolTable: NOOP_SYMBOL_TABLE,
1307
+ if (routed.kind === 'heritage') {
1308
+ for (const item of routed.items) {
1309
+ result.heritage.push({
1321
1310
  filePath: file.path,
1322
- language,
1311
+ className: item.enclosingClass,
1312
+ parentName: item.mixinName,
1313
+ kind: item.heritageKind,
1323
1314
  });
1324
1315
  }
1316
+ continue;
1325
1317
  }
1326
- for (const item of routed.items) {
1327
- const routedFieldInfo = routedFieldMap?.get(item.propName);
1328
- const propQualifiedName = propEnclosingInfo
1329
- ? `${propEnclosingInfo.className}.${item.propName}`
1330
- : item.propName;
1331
- const nodeId = generateId('Property', `${file.path}:${propQualifiedName}`);
1332
- result.nodes.push({
1333
- id: nodeId,
1334
- label: 'Property',
1335
- properties: {
1336
- name: item.propName,
1318
+ if (routed.kind === 'properties') {
1319
+ const propEnclosingInfo = cachedFindEnclosingClassInfo(captureMap['call'], file.path, provider.resolveEnclosingOwner);
1320
+ const propEnclosingClassId = propEnclosingInfo?.classId ?? null;
1321
+ // Enrich routed properties with FieldExtractor metadata
1322
+ let routedFieldMap;
1323
+ if (provider.fieldExtractor && typeEnv) {
1324
+ const classNode = findEnclosingClassNode(captureMap['call']);
1325
+ if (classNode) {
1326
+ routedFieldMap = getFieldInfo(classNode, provider, {
1327
+ typeEnv,
1328
+ symbolTable: NOOP_SYMBOL_TABLE,
1329
+ filePath: file.path,
1330
+ language,
1331
+ });
1332
+ }
1333
+ }
1334
+ for (const item of routed.items) {
1335
+ const routedFieldInfo = routedFieldMap?.get(item.propName);
1336
+ const propQualifiedName = propEnclosingInfo
1337
+ ? `${propEnclosingInfo.className}.${item.propName}`
1338
+ : item.propName;
1339
+ const nodeId = generateId('Property', `${file.path}:${propQualifiedName}`);
1340
+ result.nodes.push({
1341
+ id: nodeId,
1342
+ label: 'Property',
1343
+ properties: {
1344
+ name: item.propName,
1345
+ filePath: file.path,
1346
+ startLine: item.startLine,
1347
+ endLine: item.endLine,
1348
+ language,
1349
+ isExported: true,
1350
+ description: item.accessorType,
1351
+ ...(item.declaredType
1352
+ ? { declaredType: item.declaredType }
1353
+ : routedFieldInfo?.type
1354
+ ? { declaredType: routedFieldInfo.type }
1355
+ : {}),
1356
+ ...(routedFieldInfo?.visibility !== undefined
1357
+ ? { visibility: routedFieldInfo.visibility }
1358
+ : {}),
1359
+ ...(routedFieldInfo?.isStatic !== undefined
1360
+ ? { isStatic: routedFieldInfo.isStatic }
1361
+ : {}),
1362
+ ...(routedFieldInfo?.isReadonly !== undefined
1363
+ ? { isReadonly: routedFieldInfo.isReadonly }
1364
+ : {}),
1365
+ },
1366
+ });
1367
+ result.symbols.push({
1337
1368
  filePath: file.path,
1338
- startLine: item.startLine,
1339
- endLine: item.endLine,
1340
- language,
1341
- isExported: true,
1342
- description: item.accessorType,
1369
+ name: item.propName,
1370
+ nodeId,
1371
+ type: 'Property',
1372
+ ...(propEnclosingClassId ? { ownerId: propEnclosingClassId } : {}),
1343
1373
  ...(item.declaredType
1344
1374
  ? { declaredType: item.declaredType }
1345
1375
  : routedFieldInfo?.type
@@ -1354,101 +1384,71 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
1354
1384
  ...(routedFieldInfo?.isReadonly !== undefined
1355
1385
  ? { isReadonly: routedFieldInfo.isReadonly }
1356
1386
  : {}),
1357
- },
1358
- });
1359
- result.symbols.push({
1360
- filePath: file.path,
1361
- name: item.propName,
1362
- nodeId,
1363
- type: 'Property',
1364
- ...(propEnclosingClassId ? { ownerId: propEnclosingClassId } : {}),
1365
- ...(item.declaredType
1366
- ? { declaredType: item.declaredType }
1367
- : routedFieldInfo?.type
1368
- ? { declaredType: routedFieldInfo.type }
1369
- : {}),
1370
- ...(routedFieldInfo?.visibility !== undefined
1371
- ? { visibility: routedFieldInfo.visibility }
1372
- : {}),
1373
- ...(routedFieldInfo?.isStatic !== undefined
1374
- ? { isStatic: routedFieldInfo.isStatic }
1375
- : {}),
1376
- ...(routedFieldInfo?.isReadonly !== undefined
1377
- ? { isReadonly: routedFieldInfo.isReadonly }
1378
- : {}),
1379
- });
1380
- const fileId = generateId('File', file.path);
1381
- const relId = generateId('DEFINES', `${fileId}->${nodeId}`);
1382
- result.relationships.push({
1383
- id: relId,
1384
- sourceId: fileId,
1385
- targetId: nodeId,
1386
- type: 'DEFINES',
1387
- confidence: 1.0,
1388
- reason: '',
1389
- });
1390
- if (propEnclosingClassId) {
1387
+ });
1388
+ const fileId = generateId('File', file.path);
1389
+ const relId = generateId('DEFINES', `${fileId}->${nodeId}`);
1391
1390
  result.relationships.push({
1392
- id: generateId('HAS_PROPERTY', `${propEnclosingClassId}->${nodeId}`),
1393
- sourceId: propEnclosingClassId,
1391
+ id: relId,
1392
+ sourceId: fileId,
1394
1393
  targetId: nodeId,
1395
- type: 'HAS_PROPERTY',
1394
+ type: 'DEFINES',
1396
1395
  confidence: 1.0,
1397
1396
  reason: '',
1398
1397
  });
1398
+ if (propEnclosingClassId) {
1399
+ result.relationships.push({
1400
+ id: generateId('HAS_PROPERTY', `${propEnclosingClassId}->${nodeId}`),
1401
+ sourceId: propEnclosingClassId,
1402
+ targetId: nodeId,
1403
+ type: 'HAS_PROPERTY',
1404
+ confidence: 1.0,
1405
+ reason: '',
1406
+ });
1407
+ }
1399
1408
  }
1409
+ continue;
1400
1410
  }
1401
- continue;
1411
+ // kind === 'call' — fall through to normal call processing below
1402
1412
  }
1403
- // kind === 'call' — fall through to normal call processing below
1404
- }
1405
- if (!provider.isBuiltInName(calledName)) {
1406
- const callNode = captureMap['call'];
1407
- const sourceId = findEnclosingFunctionId(callNode, file.path, provider) ||
1408
- generateId('File', file.path);
1409
- const callForm = inferCallForm(callNode, callNameNode);
1410
- let receiverName = callForm === 'member' ? extractReceiverName(callNameNode) : undefined;
1411
- let receiverTypeName = receiverName
1412
- ? typeEnv.lookup(receiverName, callNode)
1413
- : undefined;
1414
- let receiverMixedChain;
1415
- // When the receiver is a complex expression (call chain, field chain, or mixed),
1416
- // extractReceiverName returns undefined. Walk the receiver node to build a unified
1417
- // mixed chain for deferred resolution in processCallsFromExtracted.
1418
- if (callForm === 'member' && receiverName === undefined && !receiverTypeName) {
1419
- const receiverNode = extractReceiverNode(callNameNode);
1420
- if (receiverNode) {
1421
- const extracted = extractMixedChain(receiverNode);
1422
- if (extracted && extracted.chain.length > 0) {
1423
- receiverMixedChain = extracted.chain;
1424
- receiverName = extracted.baseReceiverName;
1425
- // Try the type environment immediately for the base receiver
1426
- // (covers explicitly-typed locals and annotated parameters).
1427
- if (receiverName) {
1428
- receiverTypeName = typeEnv.lookup(receiverName, callNode);
1429
- }
1413
+ if (!provider.isBuiltInName(calledName)) {
1414
+ const callSite = callExtractor.extract(callNode, callNameNode);
1415
+ if (callSite) {
1416
+ const sourceId = findEnclosingFunctionId(callNode, file.path, provider) ||
1417
+ generateId('File', file.path);
1418
+ let receiverTypeName = callSite.receiverName
1419
+ ? typeEnv.lookup(callSite.receiverName, callNode)
1420
+ : undefined;
1421
+ // Type-as-receiver heuristic
1422
+ if (callSite.typeAsReceiverHeuristic &&
1423
+ callSite.receiverName !== undefined &&
1424
+ receiverTypeName === undefined &&
1425
+ callSite.callForm === 'member') {
1426
+ const c0 = callSite.receiverName.charCodeAt(0);
1427
+ if (c0 >= 65 && c0 <= 90)
1428
+ receiverTypeName = callSite.receiverName;
1430
1429
  }
1430
+ const inferLiteralType = provider.typeConfig?.inferLiteralType;
1431
+ // Skip when no arg list / zero args: nothing to infer for overload typing
1432
+ const argTypes = inferLiteralType && callSite.argCount !== undefined && callSite.argCount > 0
1433
+ ? extractCallArgTypes(callNode, inferLiteralType, (varName, cn) => typeEnv.lookup(varName, cn))
1434
+ : undefined;
1435
+ result.calls.push({
1436
+ filePath: file.path,
1437
+ calledName: callSite.calledName,
1438
+ sourceId,
1439
+ ...(callSite.argCount !== undefined ? { argCount: callSite.argCount } : {}),
1440
+ ...(callSite.callForm !== undefined ? { callForm: callSite.callForm } : {}),
1441
+ ...(callSite.receiverName !== undefined
1442
+ ? { receiverName: callSite.receiverName }
1443
+ : {}),
1444
+ ...(receiverTypeName !== undefined ? { receiverTypeName } : {}),
1445
+ ...(callSite.receiverMixedChain !== undefined
1446
+ ? { receiverMixedChain: callSite.receiverMixedChain }
1447
+ : {}),
1448
+ ...(argTypes !== undefined ? { argTypes } : {}),
1449
+ });
1431
1450
  }
1432
1451
  }
1433
- const inferLiteralType = provider.typeConfig?.inferLiteralType;
1434
- const argCountForOverloadHints = countCallArguments(callNode);
1435
- // Skip when no arg list / zero args: nothing to infer for overload typing; saves AST walks + payload size.
1436
- const argTypes = inferLiteralType &&
1437
- argCountForOverloadHints !== undefined &&
1438
- argCountForOverloadHints > 0
1439
- ? extractCallArgTypes(callNode, inferLiteralType, (varName, cn) => typeEnv.lookup(varName, cn))
1440
- : undefined;
1441
- result.calls.push({
1442
- filePath: file.path,
1443
- calledName,
1444
- sourceId,
1445
- argCount: countCallArguments(callNode),
1446
- ...(callForm !== undefined ? { callForm } : {}),
1447
- ...(receiverName !== undefined ? { receiverName } : {}),
1448
- ...(receiverTypeName !== undefined ? { receiverTypeName } : {}),
1449
- ...(receiverMixedChain !== undefined ? { receiverMixedChain } : {}),
1450
- ...(argTypes !== undefined ? { argTypes } : {}),
1451
- });
1452
1452
  }
1453
1453
  }
1454
1454
  continue;
@@ -1505,6 +1505,17 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
1505
1505
  })
1506
1506
  : null;
1507
1507
  const nodeLabel = extractedClassSymbol?.type ?? defaultNodeLabel;
1508
+ // Dedup: variable captures (Const/Static/Variable) may overlap with higher-priority
1509
+ // captures (e.g. `const fn = () => {}` matches both @definition.function and @definition.const).
1510
+ // Skip variable captures whose definition node was already processed.
1511
+ if ((nodeLabel === 'Const' || nodeLabel === 'Static' || nodeLabel === 'Variable') &&
1512
+ definitionNode &&
1513
+ processedDefinitionNodes.has(definitionNode.startIndex)) {
1514
+ continue;
1515
+ }
1516
+ if (definitionNode) {
1517
+ processedDefinitionNodes.add(definitionNode.startIndex);
1518
+ }
1508
1519
  // Synthesize name for constructors without explicit @name capture (e.g. Swift init)
1509
1520
  if (!nameNode && nodeLabel !== 'Constructor' && !extractedClassSymbol)
1510
1521
  continue;
@@ -1657,6 +1668,25 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
1657
1668
  }
1658
1669
  }
1659
1670
  }
1671
+ // Variable/Const/Static metadata extraction via VariableExtractor
1672
+ if ((nodeLabel === 'Const' || nodeLabel === 'Static' || nodeLabel === 'Variable') &&
1673
+ definitionNode &&
1674
+ provider.variableExtractor) {
1675
+ const varCtx = {
1676
+ filePath: file.path,
1677
+ language,
1678
+ };
1679
+ const varInfo = provider.variableExtractor.extract(definitionNode, varCtx);
1680
+ if (varInfo) {
1681
+ if (varInfo.type)
1682
+ declaredType = varInfo.type;
1683
+ methodProps.visibility = varInfo.visibility;
1684
+ methodProps.isStatic = varInfo.isStatic;
1685
+ methodProps.isConst = varInfo.isConst;
1686
+ methodProps.isMutable = varInfo.isMutable;
1687
+ methodProps.scope = varInfo.scope;
1688
+ }
1689
+ }
1660
1690
  result.nodes.push({
1661
1691
  id: nodeId,
1662
1692
  label: nodeLabel,
@@ -79,6 +79,9 @@ export const createWorkerPool = (workerUrl, poolSize) => {
79
79
  onProgress(total);
80
80
  }
81
81
  }
82
+ else if (msg.type === 'warning') {
83
+ console.warn(msg.message);
84
+ }
82
85
  else if (msg.type === 'sub-batch-done') {
83
86
  sendNextSubBatch();
84
87
  }
@@ -228,6 +228,7 @@ export const streamAllCSVsToDisk = async (graph, repoPath, csvDir) => {
228
228
  'TypeAlias',
229
229
  'Const',
230
230
  'Static',
231
+ 'Variable',
231
232
  'Property',
232
233
  'Record',
233
234
  'Delegate',
@@ -1,5 +1,6 @@
1
1
  import lbug from '@ladybugdb/core';
2
2
  import { KnowledgeGraph } from '../graph/types.js';
3
+ import type { CachedEmbedding } from '../embeddings/types.js';
3
4
  /** Factory for creating WriteStreams — injectable for testing. */
4
5
  export type WriteStreamFactory = (filePath: string) => import('fs').WriteStream;
5
6
  /** Result of splitting the relationship CSV into per-label-pair files. */
@@ -92,14 +93,22 @@ export declare const getLbugStats: () => Promise<{
92
93
  * Load cached embeddings from LadybugDB before a rebuild.
93
94
  * Returns all embedding vectors so they can be re-inserted after the graph is reloaded,
94
95
  * avoiding expensive re-embedding of unchanged nodes.
96
+ *
97
+ * Detects old schema (no chunkIndex column) and returns empty cache to trigger rebuild.
95
98
  */
96
99
  export declare const loadCachedEmbeddings: () => Promise<{
97
100
  embeddingNodeIds: Set<string>;
98
- embeddings: Array<{
99
- nodeId: string;
100
- embedding: number[];
101
- }>;
101
+ embeddings: CachedEmbedding[];
102
102
  }>;
103
+ /**
104
+ * Fetch existing embedding hashes from CodeEmbedding table for incremental embedding.
105
+ * Returns a Map<nodeId, contentHash> suitable for passing to `runEmbeddingPipeline`.
106
+ * Handles legacy DBs without the `contentHash` column (all rows treated as stale with empty hash).
107
+ * Returns undefined if the CodeEmbedding table does not exist.
108
+ *
109
+ * @param execQuery - Cypher query executor (typically pool-adapter's `executeQuery`)
110
+ */
111
+ export declare const fetchExistingEmbeddingHashes: (execQuery: (cypher: string) => Promise<any[]>) => Promise<Map<string, string> | undefined>;
103
112
  export declare const closeLbug: () => Promise<void>;
104
113
  export declare const isLbugReady: () => boolean;
105
114
  /**