gitnexus 1.4.7 → 1.4.9

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 (242) hide show
  1. package/README.md +29 -1
  2. package/dist/cli/ai-context.d.ts +1 -1
  3. package/dist/cli/ai-context.js +1 -1
  4. package/dist/cli/analyze.d.ts +2 -0
  5. package/dist/cli/analyze.js +54 -21
  6. package/dist/cli/index-repo.d.ts +15 -0
  7. package/dist/cli/index-repo.js +115 -0
  8. package/dist/cli/index.js +13 -3
  9. package/dist/cli/setup.js +90 -10
  10. package/dist/cli/wiki.d.ts +4 -0
  11. package/dist/cli/wiki.js +174 -53
  12. package/dist/config/supported-languages.d.ts +33 -1
  13. package/dist/config/supported-languages.js +32 -0
  14. package/dist/core/embeddings/embedder.d.ts +6 -1
  15. package/dist/core/embeddings/embedder.js +65 -5
  16. package/dist/core/embeddings/embedding-pipeline.js +11 -9
  17. package/dist/core/embeddings/http-client.d.ts +31 -0
  18. package/dist/core/embeddings/http-client.js +179 -0
  19. package/dist/core/embeddings/index.d.ts +1 -0
  20. package/dist/core/embeddings/index.js +1 -0
  21. package/dist/core/embeddings/types.d.ts +1 -1
  22. package/dist/core/graph/graph.js +9 -1
  23. package/dist/core/graph/types.d.ts +11 -2
  24. package/dist/core/ingestion/call-processor.d.ts +66 -2
  25. package/dist/core/ingestion/call-processor.js +650 -30
  26. package/dist/core/ingestion/call-routing.d.ts +9 -18
  27. package/dist/core/ingestion/call-routing.js +0 -19
  28. package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
  29. package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
  30. package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
  31. package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
  32. package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
  33. package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
  34. package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
  35. package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
  36. package/dist/core/ingestion/cobol-processor.d.ts +54 -0
  37. package/dist/core/ingestion/cobol-processor.js +1186 -0
  38. package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
  39. package/dist/core/ingestion/entry-point-scoring.js +52 -28
  40. package/dist/core/ingestion/export-detection.d.ts +47 -8
  41. package/dist/core/ingestion/export-detection.js +29 -50
  42. package/dist/core/ingestion/field-extractor.d.ts +29 -0
  43. package/dist/core/ingestion/field-extractor.js +25 -0
  44. package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
  45. package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
  46. package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
  47. package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
  48. package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
  49. package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
  50. package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
  51. package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
  52. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
  53. package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
  54. package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
  55. package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
  56. package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
  57. package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
  58. package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
  59. package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
  60. package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
  61. package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
  62. package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
  63. package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
  64. package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
  65. package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
  66. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
  67. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
  68. package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
  69. package/dist/core/ingestion/field-extractors/generic.js +111 -0
  70. package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
  71. package/dist/core/ingestion/field-extractors/typescript.js +291 -0
  72. package/dist/core/ingestion/field-types.d.ts +59 -0
  73. package/dist/core/ingestion/field-types.js +2 -0
  74. package/dist/core/ingestion/framework-detection.d.ts +97 -2
  75. package/dist/core/ingestion/framework-detection.js +114 -14
  76. package/dist/core/ingestion/heritage-processor.js +62 -66
  77. package/dist/core/ingestion/import-processor.d.ts +9 -10
  78. package/dist/core/ingestion/import-processor.js +150 -196
  79. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
  80. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
  81. package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
  82. package/dist/core/ingestion/import-resolvers/dart.js +44 -0
  83. package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
  84. package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
  85. package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +10 -1
  86. package/dist/core/ingestion/import-resolvers/jvm.js +159 -0
  87. package/dist/core/ingestion/import-resolvers/php.d.ts +25 -0
  88. package/dist/core/ingestion/import-resolvers/php.js +80 -0
  89. package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
  90. package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
  91. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
  92. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
  93. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
  94. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
  95. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
  96. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
  97. package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
  98. package/dist/core/ingestion/import-resolvers/swift.js +23 -0
  99. package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
  100. package/dist/core/ingestion/import-resolvers/types.js +6 -0
  101. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +2 -0
  102. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +7 -0
  103. package/dist/core/ingestion/language-config.d.ts +6 -0
  104. package/dist/core/ingestion/language-config.js +13 -0
  105. package/dist/core/ingestion/language-provider.d.ts +121 -0
  106. package/dist/core/ingestion/language-provider.js +24 -0
  107. package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
  108. package/dist/core/ingestion/languages/c-cpp.js +71 -0
  109. package/dist/core/ingestion/languages/cobol.d.ts +1 -0
  110. package/dist/core/ingestion/languages/cobol.js +26 -0
  111. package/dist/core/ingestion/languages/csharp.d.ts +8 -0
  112. package/dist/core/ingestion/languages/csharp.js +49 -0
  113. package/dist/core/ingestion/languages/dart.d.ts +12 -0
  114. package/dist/core/ingestion/languages/dart.js +58 -0
  115. package/dist/core/ingestion/languages/go.d.ts +11 -0
  116. package/dist/core/ingestion/languages/go.js +28 -0
  117. package/dist/core/ingestion/languages/index.d.ts +38 -0
  118. package/dist/core/ingestion/languages/index.js +63 -0
  119. package/dist/core/ingestion/languages/java.d.ts +9 -0
  120. package/dist/core/ingestion/languages/java.js +29 -0
  121. package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
  122. package/dist/core/ingestion/languages/kotlin.js +53 -0
  123. package/dist/core/ingestion/languages/php.d.ts +8 -0
  124. package/dist/core/ingestion/languages/php.js +145 -0
  125. package/dist/core/ingestion/languages/python.d.ts +12 -0
  126. package/dist/core/ingestion/languages/python.js +39 -0
  127. package/dist/core/ingestion/languages/ruby.d.ts +9 -0
  128. package/dist/core/ingestion/languages/ruby.js +44 -0
  129. package/dist/core/ingestion/languages/rust.d.ts +12 -0
  130. package/dist/core/ingestion/languages/rust.js +44 -0
  131. package/dist/core/ingestion/languages/swift.d.ts +12 -0
  132. package/dist/core/ingestion/languages/swift.js +133 -0
  133. package/dist/core/ingestion/languages/typescript.d.ts +10 -0
  134. package/dist/core/ingestion/languages/typescript.js +60 -0
  135. package/dist/core/ingestion/markdown-processor.d.ts +17 -0
  136. package/dist/core/ingestion/markdown-processor.js +124 -0
  137. package/dist/core/ingestion/mro-processor.js +22 -18
  138. package/dist/core/ingestion/named-binding-processor.d.ts +18 -0
  139. package/dist/core/ingestion/named-binding-processor.js +42 -0
  140. package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
  141. package/dist/core/ingestion/named-bindings/csharp.js +37 -0
  142. package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
  143. package/dist/core/ingestion/named-bindings/java.js +29 -0
  144. package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
  145. package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
  146. package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
  147. package/dist/core/ingestion/named-bindings/php.js +61 -0
  148. package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
  149. package/dist/core/ingestion/named-bindings/python.js +49 -0
  150. package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
  151. package/dist/core/ingestion/named-bindings/rust.js +64 -0
  152. package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
  153. package/dist/core/ingestion/named-bindings/types.js +6 -0
  154. package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
  155. package/dist/core/ingestion/named-bindings/typescript.js +58 -0
  156. package/dist/core/ingestion/parsing-processor.d.ts +6 -2
  157. package/dist/core/ingestion/parsing-processor.js +125 -85
  158. package/dist/core/ingestion/pipeline.d.ts +10 -0
  159. package/dist/core/ingestion/pipeline.js +1235 -317
  160. package/dist/core/ingestion/resolution-context.d.ts +5 -0
  161. package/dist/core/ingestion/resolution-context.js +8 -5
  162. package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
  163. package/dist/core/ingestion/route-extractors/expo.js +36 -0
  164. package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
  165. package/dist/core/ingestion/route-extractors/middleware.js +143 -0
  166. package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
  167. package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
  168. package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
  169. package/dist/core/ingestion/route-extractors/php.js +21 -0
  170. package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
  171. package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
  172. package/dist/core/ingestion/symbol-table.d.ts +16 -0
  173. package/dist/core/ingestion/symbol-table.js +20 -6
  174. package/dist/core/ingestion/tree-sitter-queries.d.ts +10 -9
  175. package/dist/core/ingestion/tree-sitter-queries.js +274 -11
  176. package/dist/core/ingestion/type-env.d.ts +42 -18
  177. package/dist/core/ingestion/type-env.js +481 -106
  178. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +5 -0
  179. package/dist/core/ingestion/type-extractors/c-cpp.js +119 -0
  180. package/dist/core/ingestion/type-extractors/csharp.js +149 -16
  181. package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
  182. package/dist/core/ingestion/type-extractors/dart.js +371 -0
  183. package/dist/core/ingestion/type-extractors/jvm.js +169 -66
  184. package/dist/core/ingestion/type-extractors/rust.js +35 -1
  185. package/dist/core/ingestion/type-extractors/shared.d.ts +1 -15
  186. package/dist/core/ingestion/type-extractors/shared.js +14 -112
  187. package/dist/core/ingestion/type-extractors/swift.js +338 -7
  188. package/dist/core/ingestion/type-extractors/types.d.ts +40 -8
  189. package/dist/core/ingestion/type-extractors/typescript.js +141 -9
  190. package/dist/core/ingestion/utils/ast-helpers.d.ts +83 -0
  191. package/dist/core/ingestion/utils/ast-helpers.js +817 -0
  192. package/dist/core/ingestion/utils/call-analysis.d.ts +73 -0
  193. package/dist/core/ingestion/utils/call-analysis.js +527 -0
  194. package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
  195. package/dist/core/ingestion/utils/event-loop.js +5 -0
  196. package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
  197. package/dist/core/ingestion/utils/language-detection.js +70 -0
  198. package/dist/core/ingestion/utils/verbose.d.ts +1 -0
  199. package/dist/core/ingestion/utils/verbose.js +7 -0
  200. package/dist/core/ingestion/workers/parse-worker.d.ts +55 -5
  201. package/dist/core/ingestion/workers/parse-worker.js +415 -225
  202. package/dist/core/lbug/csv-generator.js +51 -1
  203. package/dist/core/lbug/lbug-adapter.d.ts +10 -0
  204. package/dist/core/lbug/lbug-adapter.js +75 -4
  205. package/dist/core/lbug/schema.d.ts +8 -4
  206. package/dist/core/lbug/schema.js +65 -4
  207. package/dist/core/tree-sitter/parser-loader.js +7 -1
  208. package/dist/core/wiki/cursor-client.d.ts +31 -0
  209. package/dist/core/wiki/cursor-client.js +127 -0
  210. package/dist/core/wiki/generator.d.ts +28 -9
  211. package/dist/core/wiki/generator.js +115 -18
  212. package/dist/core/wiki/graph-queries.d.ts +4 -0
  213. package/dist/core/wiki/graph-queries.js +7 -1
  214. package/dist/core/wiki/llm-client.d.ts +2 -0
  215. package/dist/core/wiki/llm-client.js +8 -4
  216. package/dist/core/wiki/prompts.d.ts +3 -3
  217. package/dist/core/wiki/prompts.js +6 -0
  218. package/dist/mcp/core/embedder.js +11 -3
  219. package/dist/mcp/core/lbug-adapter.d.ts +5 -0
  220. package/dist/mcp/core/lbug-adapter.js +23 -2
  221. package/dist/mcp/local/local-backend.d.ts +38 -5
  222. package/dist/mcp/local/local-backend.js +804 -63
  223. package/dist/mcp/resources.js +2 -0
  224. package/dist/mcp/tools.js +73 -4
  225. package/dist/server/api.d.ts +19 -1
  226. package/dist/server/api.js +66 -6
  227. package/dist/storage/git.d.ts +12 -0
  228. package/dist/storage/git.js +21 -0
  229. package/dist/storage/repo-manager.d.ts +3 -0
  230. package/package.json +25 -16
  231. package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
  232. package/dist/core/ingestion/named-binding-extraction.js +0 -363
  233. package/dist/core/ingestion/resolvers/index.d.ts +0 -18
  234. package/dist/core/ingestion/resolvers/index.js +0 -13
  235. package/dist/core/ingestion/resolvers/jvm.js +0 -87
  236. package/dist/core/ingestion/resolvers/php.d.ts +0 -15
  237. package/dist/core/ingestion/resolvers/php.js +0 -35
  238. package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
  239. package/dist/core/ingestion/type-extractors/index.js +0 -31
  240. package/dist/core/ingestion/utils.d.ts +0 -138
  241. package/dist/core/ingestion/utils.js +0 -1290
  242. package/scripts/patch-tree-sitter-swift.cjs +0 -74
@@ -0,0 +1,64 @@
1
+ export function extractRustNamedBindings(importNode) {
2
+ // use_declaration may contain use_as_clause at any depth
3
+ if (importNode.type !== 'use_declaration')
4
+ return undefined;
5
+ const bindings = [];
6
+ collectRustBindings(importNode, bindings);
7
+ return bindings.length > 0 ? bindings : undefined;
8
+ }
9
+ function collectRustBindings(node, bindings) {
10
+ if (node.type === 'use_as_clause') {
11
+ // First identifier = exported name, second identifier = local alias
12
+ const idents = [];
13
+ for (let i = 0; i < node.namedChildCount; i++) {
14
+ const child = node.namedChild(i);
15
+ if (child?.type === 'identifier')
16
+ idents.push(child.text);
17
+ // For scoped_identifier, extract the last segment
18
+ if (child?.type === 'scoped_identifier') {
19
+ const nameNode = child.childForFieldName?.('name');
20
+ if (nameNode)
21
+ idents.push(nameNode.text);
22
+ }
23
+ }
24
+ if (idents.length === 2) {
25
+ bindings.push({ local: idents[1], exported: idents[0] });
26
+ }
27
+ return;
28
+ }
29
+ // Terminal identifier in a use_list: use crate::models::{User, Repo}
30
+ if (node.type === 'identifier' && node.parent?.type === 'use_list') {
31
+ bindings.push({ local: node.text, exported: node.text });
32
+ return;
33
+ }
34
+ // Skip scoped_identifier that serves as path prefix in scoped_use_list
35
+ // e.g. use crate::models::{User, Repo} — the path node "crate::models" is not an importable symbol
36
+ if (node.type === 'scoped_identifier' && node.parent?.type === 'scoped_use_list') {
37
+ return; // path prefix — the use_list sibling handles the actual symbols
38
+ }
39
+ // Terminal scoped_identifier: use crate::models::User;
40
+ // Only extract if this is a leaf (no deeper use_list/use_as_clause/scoped_use_list)
41
+ if (node.type === 'scoped_identifier') {
42
+ let hasDeeper = false;
43
+ for (let i = 0; i < node.namedChildCount; i++) {
44
+ const child = node.namedChild(i);
45
+ if (child?.type === 'use_list' || child?.type === 'use_as_clause' || child?.type === 'scoped_use_list') {
46
+ hasDeeper = true;
47
+ break;
48
+ }
49
+ }
50
+ if (!hasDeeper) {
51
+ const nameNode = node.childForFieldName?.('name');
52
+ if (nameNode) {
53
+ bindings.push({ local: nameNode.text, exported: nameNode.text });
54
+ }
55
+ return;
56
+ }
57
+ }
58
+ // Recurse into children
59
+ for (let i = 0; i < node.namedChildCount; i++) {
60
+ const child = node.namedChild(i);
61
+ if (child)
62
+ collectRustBindings(child, bindings);
63
+ }
64
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Named binding types — shared across all per-language binding extractors.
3
+ *
4
+ * Extracted from import-resolution.ts to co-locate types with their consumers.
5
+ */
6
+ import type { SyntaxNode } from '../utils/ast-helpers.js';
7
+ /** A single named import binding: local name in the importing file and exported name from the source.
8
+ * When `isModuleAlias` is true, the binding represents a Python `import X as Y` module alias
9
+ * and is routed to moduleAliasMap instead of namedImportMap during import processing. */
10
+ export interface NamedBinding {
11
+ local: string;
12
+ exported: string;
13
+ isModuleAlias?: boolean;
14
+ }
15
+ /** Per-language named binding extractor -- optional (returns undefined if language has no named imports). */
16
+ export type NamedBindingExtractorFn = (importNode: SyntaxNode) => NamedBinding[] | undefined;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Named binding types — shared across all per-language binding extractors.
3
+ *
4
+ * Extracted from import-resolution.ts to co-locate types with their consumers.
5
+ */
6
+ export {};
@@ -0,0 +1,3 @@
1
+ import { type SyntaxNode } from '../utils/ast-helpers.js';
2
+ import type { NamedBinding } from './types.js';
3
+ export declare function extractTsNamedBindings(importNode: SyntaxNode): NamedBinding[] | undefined;
@@ -0,0 +1,58 @@
1
+ import { findChild } from '../utils/ast-helpers.js';
2
+ export function extractTsNamedBindings(importNode) {
3
+ // import_statement > import_clause > named_imports > import_specifier*
4
+ const importClause = findChild(importNode, 'import_clause');
5
+ if (importClause) {
6
+ const namedImports = findChild(importClause, 'named_imports');
7
+ if (!namedImports)
8
+ return undefined; // default import, namespace import, or side-effect
9
+ const bindings = [];
10
+ for (let i = 0; i < namedImports.namedChildCount; i++) {
11
+ const specifier = namedImports.namedChild(i);
12
+ if (specifier?.type !== 'import_specifier')
13
+ continue;
14
+ const identifiers = [];
15
+ for (let j = 0; j < specifier.namedChildCount; j++) {
16
+ const child = specifier.namedChild(j);
17
+ if (child?.type === 'identifier')
18
+ identifiers.push(child.text);
19
+ }
20
+ if (identifiers.length === 1) {
21
+ bindings.push({ local: identifiers[0], exported: identifiers[0] });
22
+ }
23
+ else if (identifiers.length === 2) {
24
+ // import { Foo as Bar } → exported='Foo', local='Bar'
25
+ bindings.push({ local: identifiers[1], exported: identifiers[0] });
26
+ }
27
+ }
28
+ return bindings.length > 0 ? bindings : undefined;
29
+ }
30
+ // Re-export: export { X } from './y' → export_statement > export_clause > export_specifier
31
+ const exportClause = findChild(importNode, 'export_clause');
32
+ if (exportClause) {
33
+ const bindings = [];
34
+ for (let i = 0; i < exportClause.namedChildCount; i++) {
35
+ const specifier = exportClause.namedChild(i);
36
+ if (specifier?.type !== 'export_specifier')
37
+ continue;
38
+ const identifiers = [];
39
+ for (let j = 0; j < specifier.namedChildCount; j++) {
40
+ const child = specifier.namedChild(j);
41
+ if (child?.type === 'identifier')
42
+ identifiers.push(child.text);
43
+ }
44
+ if (identifiers.length === 1) {
45
+ // export { User } from './base' → re-exports User as User
46
+ bindings.push({ local: identifiers[0], exported: identifiers[0] });
47
+ }
48
+ else if (identifiers.length === 2) {
49
+ // export { Repo as Repository } from './models' → name=Repo, alias=Repository
50
+ // For re-exports, the first id is the source name, second is what's exported
51
+ // When another file imports { Repository }, they get Repo from the source
52
+ bindings.push({ local: identifiers[1], exported: identifiers[0] });
53
+ }
54
+ }
55
+ return bindings.length > 0 ? bindings : undefined;
56
+ }
57
+ return undefined;
58
+ }
@@ -2,7 +2,7 @@ import { KnowledgeGraph } from '../graph/types.js';
2
2
  import { SymbolTable } from './symbol-table.js';
3
3
  import { ASTCache } from './ast-cache.js';
4
4
  import { WorkerPool } from './workers/worker-pool.js';
5
- import type { ExtractedImport, ExtractedCall, ExtractedAssignment, ExtractedHeritage, ExtractedRoute, FileConstructorBindings } from './workers/parse-worker.js';
5
+ import type { ExtractedImport, ExtractedCall, ExtractedAssignment, ExtractedHeritage, ExtractedRoute, ExtractedFetchCall, ExtractedDecoratorRoute, ExtractedToolDef, FileConstructorBindings, FileTypeEnvBindings, ExtractedORMQuery } from './workers/parse-worker.js';
6
6
  export type FileProgressCallback = (current: number, total: number, filePath: string) => void;
7
7
  export interface WorkerExtractedData {
8
8
  imports: ExtractedImport[];
@@ -10,9 +10,13 @@ export interface WorkerExtractedData {
10
10
  assignments: ExtractedAssignment[];
11
11
  heritage: ExtractedHeritage[];
12
12
  routes: ExtractedRoute[];
13
+ fetchCalls: ExtractedFetchCall[];
14
+ decoratorRoutes: ExtractedDecoratorRoute[];
15
+ toolDefs: ExtractedToolDef[];
16
+ ormQueries: ExtractedORMQuery[];
13
17
  constructorBindings: FileConstructorBindings[];
18
+ typeEnvBindings: FileTypeEnvBindings[];
14
19
  }
15
- export { isNodeExported } from './export-detection.js';
16
20
  export declare const processParsing: (graph: KnowledgeGraph, files: {
17
21
  path: string;
18
22
  content: string;
@@ -1,17 +1,13 @@
1
1
  import Parser from 'tree-sitter';
2
2
  import { loadParser, loadLanguage, isLanguageAvailable } from '../tree-sitter/parser-loader.js';
3
- import { LANGUAGE_QUERIES } from './tree-sitter-queries.js';
3
+ import { getProvider } from './languages/index.js';
4
4
  import { generateId } from '../../lib/utils.js';
5
- import { getLanguageFromFilename, yieldToEventLoop, getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature } from './utils.js';
6
- import { extractPropertyDeclaredType } from './type-extractors/shared.js';
7
- import { isNodeExported } from './export-detection.js';
5
+ import { getLanguageFromFilename } from './utils/language-detection.js';
6
+ import { yieldToEventLoop } from './utils/event-loop.js';
7
+ import { getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature, getLabelFromCaptures, CLASS_CONTAINER_TYPES } from './utils/ast-helpers.js';
8
8
  import { detectFrameworkFromAST } from './framework-detection.js';
9
- import { typeConfigs } from './type-extractors/index.js';
10
- import { SupportedLanguages } from '../../config/supported-languages.js';
9
+ import { buildTypeEnv } from './type-env.js';
11
10
  import { getTreeSitterBufferSize, TREE_SITTER_MAX_BUFFER } from './constants.js';
12
- // isNodeExported imported from ./export-detection.js (shared module)
13
- // Re-export for backward compatibility with any external consumers
14
- export { isNodeExported } from './export-detection.js';
15
11
  // ============================================================================
16
12
  // Worker-based parallel parsing
17
13
  // ============================================================================
@@ -24,7 +20,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
24
20
  parseableFiles.push({ path: file.path, content: file.content });
25
21
  }
26
22
  if (parseableFiles.length === 0)
27
- return { imports: [], calls: [], assignments: [], heritage: [], routes: [], constructorBindings: [] };
23
+ return { imports: [], calls: [], assignments: [], heritage: [], routes: [], fetchCalls: [], decoratorRoutes: [], toolDefs: [], ormQueries: [], constructorBindings: [], typeEnvBindings: [] };
28
24
  const total = files.length;
29
25
  // Dispatch to worker pool — pool handles splitting into chunks and sub-batching
30
26
  const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
@@ -36,7 +32,12 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
36
32
  const allAssignments = [];
37
33
  const allHeritage = [];
38
34
  const allRoutes = [];
35
+ const allFetchCalls = [];
36
+ const allDecoratorRoutes = [];
37
+ const allToolDefs = [];
38
+ const allORMQueries = [];
39
39
  const allConstructorBindings = [];
40
+ const allTypeEnvBindings = [];
40
41
  for (const result of chunkResults) {
41
42
  for (const node of result.nodes) {
42
43
  graph.addNode({
@@ -51,6 +52,8 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
51
52
  for (const sym of result.symbols) {
52
53
  symbolTable.add(sym.filePath, sym.name, sym.nodeId, sym.type, {
53
54
  parameterCount: sym.parameterCount,
55
+ requiredParameterCount: sym.requiredParameterCount,
56
+ parameterTypes: sym.parameterTypes,
54
57
  returnType: sym.returnType,
55
58
  declaredType: sym.declaredType,
56
59
  ownerId: sym.ownerId,
@@ -61,7 +64,13 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
61
64
  allAssignments.push(...result.assignments);
62
65
  allHeritage.push(...result.heritage);
63
66
  allRoutes.push(...result.routes);
67
+ allFetchCalls.push(...result.fetchCalls);
68
+ allDecoratorRoutes.push(...result.decoratorRoutes);
69
+ allToolDefs.push(...result.toolDefs);
70
+ if (result.ormQueries)
71
+ allORMQueries.push(...result.ormQueries);
64
72
  allConstructorBindings.push(...result.constructorBindings);
73
+ allTypeEnvBindings.push(...result.typeEnvBindings);
65
74
  }
66
75
  // Merge and log skipped languages from workers
67
76
  const skippedLanguages = new Map();
@@ -78,17 +87,75 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
78
87
  }
79
88
  // Final progress
80
89
  onFileProgress?.(total, total, 'done');
81
- return { imports: allImports, calls: allCalls, assignments: allAssignments, heritage: allHeritage, routes: allRoutes, constructorBindings: allConstructorBindings };
90
+ return { imports: allImports, calls: allCalls, assignments: allAssignments, heritage: allHeritage, routes: allRoutes, fetchCalls: allFetchCalls, decoratorRoutes: allDecoratorRoutes, toolDefs: allToolDefs, ormQueries: allORMQueries, constructorBindings: allConstructorBindings, typeEnvBindings: allTypeEnvBindings };
82
91
  };
83
92
  // ============================================================================
84
93
  // Sequential fallback (original implementation)
85
94
  // ============================================================================
95
+ // Inline caches to avoid repeated parent-walks per node (same pattern as parse-worker.ts).
96
+ // Keyed by tree-sitter node reference — cleared at the start of each file.
97
+ const classIdCache = new Map();
98
+ const exportCache = new Map();
99
+ const cachedFindEnclosingClassId = (node, filePath) => {
100
+ const cached = classIdCache.get(node);
101
+ if (cached !== undefined)
102
+ return cached;
103
+ const result = findEnclosingClassId(node, filePath);
104
+ classIdCache.set(node, result);
105
+ return result;
106
+ };
107
+ const cachedExportCheck = (checker, node, name) => {
108
+ const cached = exportCache.get(node);
109
+ if (cached !== undefined)
110
+ return cached;
111
+ const result = checker(node, name);
112
+ exportCache.set(node, result);
113
+ return result;
114
+ };
115
+ // FieldExtractor cache for sequential path — same pattern as parse-worker.ts
116
+ const seqFieldInfoCache = new Map();
117
+ function seqFindEnclosingClassNode(node) {
118
+ let current = node.parent;
119
+ while (current) {
120
+ if (CLASS_CONTAINER_TYPES.has(current.type))
121
+ return current;
122
+ current = current.parent;
123
+ }
124
+ return null;
125
+ }
126
+ /** Minimal no-op SymbolTable stub for FieldExtractorContext (sequential path has a real
127
+ * SymbolTable, but it's incomplete at this stage — use the stub for safety). */
128
+ const NOOP_SYMBOL_TABLE_SEQ = {
129
+ lookupExactAll: () => [],
130
+ lookupExact: () => undefined,
131
+ lookupExactFull: () => undefined,
132
+ };
133
+ function seqGetFieldInfo(classNode, provider, context) {
134
+ if (!provider.fieldExtractor)
135
+ return undefined;
136
+ const cacheKey = classNode.startIndex;
137
+ let cached = seqFieldInfoCache.get(cacheKey);
138
+ if (cached)
139
+ return cached;
140
+ const extracted = provider.fieldExtractor.extract(classNode, context);
141
+ if (!extracted?.fields?.length)
142
+ return undefined;
143
+ cached = new Map();
144
+ for (const field of extracted.fields)
145
+ cached.set(field.name, field);
146
+ seqFieldInfoCache.set(cacheKey, cached);
147
+ return cached;
148
+ }
86
149
  const processParsingSequential = async (graph, files, symbolTable, astCache, onFileProgress) => {
87
150
  const parser = await loadParser();
88
151
  const total = files.length;
89
152
  const skippedLanguages = new Map();
90
153
  for (let i = 0; i < files.length; i++) {
91
154
  const file = files[i];
155
+ // Reset memoization before each new file (node refs are per-tree)
156
+ classIdCache.clear();
157
+ exportCache.clear();
158
+ seqFieldInfoCache.clear();
92
159
  onFileProgress?.(i + 1, total, file.path);
93
160
  if (i % 20 === 0)
94
161
  await yieldToEventLoop();
@@ -118,7 +185,8 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
118
185
  continue;
119
186
  }
120
187
  astCache.set(file.path, tree);
121
- const queryString = LANGUAGE_QUERIES[language];
188
+ const provider = getProvider(language);
189
+ const queryString = provider.treeSitterQueries;
122
190
  if (!queryString) {
123
191
  continue;
124
192
  }
@@ -133,82 +201,21 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
133
201
  console.warn(`Query error for ${file.path}:`, queryError);
134
202
  continue;
135
203
  }
204
+ // Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor)
205
+ const typeEnv = provider.fieldExtractor ? buildTypeEnv(tree, language, { enclosingFunctionFinder: provider.enclosingFunctionFinder }) : null;
136
206
  matches.forEach(match => {
137
207
  const captureMap = {};
138
208
  match.captures.forEach(c => {
139
209
  captureMap[c.name] = c.node;
140
210
  });
141
- if (captureMap['import']) {
211
+ const nodeLabel = getLabelFromCaptures(captureMap, provider);
212
+ if (!nodeLabel)
142
213
  return;
143
- }
144
- if (captureMap['call']) {
145
- return;
146
- }
147
214
  const nameNode = captureMap['name'];
148
215
  // Synthesize name for constructors without explicit @name capture (e.g. Swift init)
149
- if (!nameNode && !captureMap['definition.constructor'])
216
+ if (!nameNode && nodeLabel !== 'Constructor')
150
217
  return;
151
218
  const nodeName = nameNode ? nameNode.text : 'init';
152
- let nodeLabel = 'CodeElement';
153
- if (captureMap['definition.function']) {
154
- // C/C++: @definition.function is broad and also matches inline class methods (inside
155
- // a class/struct body). Those are already captured by @definition.method, so skip
156
- // the duplicate Function entry to prevent double-indexing in globalIndex.
157
- if (language === SupportedLanguages.CPlusPlus || language === SupportedLanguages.C) {
158
- let ancestor = captureMap['definition.function']?.parent;
159
- while (ancestor) {
160
- if (ancestor.type === 'class_specifier' || ancestor.type === 'struct_specifier') {
161
- break;
162
- }
163
- ancestor = ancestor.parent;
164
- }
165
- if (ancestor)
166
- return; // inside a class body — handled by @definition.method
167
- }
168
- nodeLabel = 'Function';
169
- }
170
- else if (captureMap['definition.class'])
171
- nodeLabel = 'Class';
172
- else if (captureMap['definition.interface'])
173
- nodeLabel = 'Interface';
174
- else if (captureMap['definition.method'])
175
- nodeLabel = 'Method';
176
- else if (captureMap['definition.struct'])
177
- nodeLabel = 'Struct';
178
- else if (captureMap['definition.enum'])
179
- nodeLabel = 'Enum';
180
- else if (captureMap['definition.namespace'])
181
- nodeLabel = 'Namespace';
182
- else if (captureMap['definition.module'])
183
- nodeLabel = 'Module';
184
- else if (captureMap['definition.trait'])
185
- nodeLabel = 'Trait';
186
- else if (captureMap['definition.impl'])
187
- nodeLabel = 'Impl';
188
- else if (captureMap['definition.type'])
189
- nodeLabel = 'TypeAlias';
190
- else if (captureMap['definition.const'])
191
- nodeLabel = 'Const';
192
- else if (captureMap['definition.static'])
193
- nodeLabel = 'Static';
194
- else if (captureMap['definition.typedef'])
195
- nodeLabel = 'Typedef';
196
- else if (captureMap['definition.macro'])
197
- nodeLabel = 'Macro';
198
- else if (captureMap['definition.union'])
199
- nodeLabel = 'Union';
200
- else if (captureMap['definition.property'])
201
- nodeLabel = 'Property';
202
- else if (captureMap['definition.record'])
203
- nodeLabel = 'Record';
204
- else if (captureMap['definition.delegate'])
205
- nodeLabel = 'Delegate';
206
- else if (captureMap['definition.annotation'])
207
- nodeLabel = 'Annotation';
208
- else if (captureMap['definition.constructor'])
209
- nodeLabel = 'Constructor';
210
- else if (captureMap['definition.template'])
211
- nodeLabel = 'Template';
212
219
  const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
213
220
  const startLine = definitionNodeForRange ? definitionNodeForRange.startPosition.row : (nameNode ? nameNode.startPosition.row : 0);
214
221
  const nodeId = generateId(nodeLabel, `${file.path}:${nodeName}`);
@@ -223,7 +230,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
223
230
  // Language-specific return type fallback (e.g. Ruby YARD @return [Type])
224
231
  // Also upgrades uninformative AST types like PHP `array` with PHPDoc `@return User[]`
225
232
  if (methodSig && (!methodSig.returnType || methodSig.returnType === 'array' || methodSig.returnType === 'iterable') && definitionNode) {
226
- const tc = typeConfigs[language];
233
+ const tc = provider.typeConfig;
227
234
  if (tc?.extractReturnType) {
228
235
  const docReturn = tc.extractReturnType(definitionNode);
229
236
  if (docReturn)
@@ -239,13 +246,15 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
239
246
  startLine: definitionNodeForRange ? definitionNodeForRange.startPosition.row : startLine,
240
247
  endLine: definitionNodeForRange ? definitionNodeForRange.endPosition.row : startLine,
241
248
  language: language,
242
- isExported: isNodeExported(nameNode || definitionNodeForRange, nodeName, language),
249
+ isExported: cachedExportCheck(provider.exportChecker, nameNode || definitionNodeForRange, nodeName),
243
250
  ...(frameworkHint ? {
244
251
  astFrameworkMultiplier: frameworkHint.entryPointMultiplier,
245
252
  astFrameworkReason: frameworkHint.reason,
246
253
  } : {}),
247
254
  ...(methodSig ? {
248
255
  parameterCount: methodSig.parameterCount,
256
+ ...(methodSig.requiredParameterCount !== undefined ? { requiredParameterCount: methodSig.requiredParameterCount } : {}),
257
+ ...(methodSig.parameterTypes ? { parameterTypes: methodSig.parameterTypes } : {}),
249
258
  returnType: methodSig.returnType,
250
259
  } : {}),
251
260
  },
@@ -254,13 +263,44 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
254
263
  // Compute enclosing class for Method/Constructor/Property/Function — used for both ownerId and HAS_METHOD
255
264
  // Function is included because Kotlin/Rust/Python capture class methods as Function nodes
256
265
  const needsOwner = nodeLabel === 'Method' || nodeLabel === 'Constructor' || nodeLabel === 'Property' || nodeLabel === 'Function';
257
- const enclosingClassId = needsOwner ? findEnclosingClassId(nameNode || definitionNodeForRange, file.path) : null;
258
- // Extract declared type for Property nodes (field/property type annotations)
259
- const declaredType = (nodeLabel === 'Property' && definitionNode)
260
- ? extractPropertyDeclaredType(definitionNode)
261
- : undefined;
266
+ const enclosingClassId = needsOwner ? cachedFindEnclosingClassId(nameNode || definitionNodeForRange, file.path) : null;
267
+ // Extract declared type and field metadata for Property nodes
268
+ let declaredType;
269
+ let seqVisibility;
270
+ let seqIsStatic;
271
+ let seqIsReadonly;
272
+ if (nodeLabel === 'Property' && definitionNode) {
273
+ // FieldExtractor is the single source of truth when available
274
+ if (provider.fieldExtractor && typeEnv) {
275
+ const classNode = seqFindEnclosingClassNode(definitionNode);
276
+ if (classNode) {
277
+ const fieldMap = seqGetFieldInfo(classNode, provider, {
278
+ typeEnv, symbolTable: NOOP_SYMBOL_TABLE_SEQ, filePath: file.path, language,
279
+ });
280
+ const info = fieldMap?.get(nodeName);
281
+ if (info) {
282
+ declaredType = info.type ?? undefined;
283
+ seqVisibility = info.visibility;
284
+ seqIsStatic = info.isStatic;
285
+ seqIsReadonly = info.isReadonly;
286
+ }
287
+ }
288
+ }
289
+ // All 14 languages register a FieldExtractor — no fallback needed.
290
+ }
291
+ // Apply field metadata to the graph node retroactively
292
+ if (seqVisibility !== undefined)
293
+ node.properties.visibility = seqVisibility;
294
+ if (seqIsStatic !== undefined)
295
+ node.properties.isStatic = seqIsStatic;
296
+ if (seqIsReadonly !== undefined)
297
+ node.properties.isReadonly = seqIsReadonly;
298
+ if (declaredType !== undefined)
299
+ node.properties.declaredType = declaredType;
262
300
  symbolTable.add(file.path, nodeName, nodeId, nodeLabel, {
263
301
  parameterCount: methodSig?.parameterCount,
302
+ requiredParameterCount: methodSig?.requiredParameterCount,
303
+ parameterTypes: methodSig?.parameterTypes,
264
304
  returnType: methodSig?.returnType,
265
305
  declaredType,
266
306
  ownerId: enclosingClassId ?? undefined,
@@ -1,6 +1,16 @@
1
1
  import { PipelineProgress, PipelineResult } from '../../types/pipeline.js';
2
+ /** A group of files with no mutual dependencies, safe to process in parallel. */
3
+ type IndependentFileGroup = readonly string[];
4
+ /** Kahn's algorithm: returns files grouped by topological level.
5
+ * Files in the same level have no mutual dependencies — safe to process in parallel.
6
+ * Files in cycles are returned as a final group (no cross-cycle propagation). */
7
+ export declare function topologicalLevelSort(importMap: ReadonlyMap<string, ReadonlySet<string>>): {
8
+ levels: readonly IndependentFileGroup[];
9
+ cycleCount: number;
10
+ };
2
11
  export interface PipelineOptions {
3
12
  /** Skip MRO, community detection, and process extraction for faster test runs. */
4
13
  skipGraphPhases?: boolean;
5
14
  }
6
15
  export declare const runPipelineFromRepo: (repoPath: string, onProgress: (progress: PipelineProgress) => void, options?: PipelineOptions) => Promise<PipelineResult>;
16
+ export {};