ragcode-context-engine 0.1.0

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 (174) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +366 -0
  3. package/README.zh-CN.md +363 -0
  4. package/dist/src/cli/configure/app.d.ts +6 -0
  5. package/dist/src/cli/configure/app.js +81 -0
  6. package/dist/src/cli/configure/run.d.ts +5 -0
  7. package/dist/src/cli/configure/run.js +85 -0
  8. package/dist/src/cli/configure/state.d.ts +42 -0
  9. package/dist/src/cli/configure/state.js +174 -0
  10. package/dist/src/cli/configure.d.ts +31 -0
  11. package/dist/src/cli/configure.js +101 -0
  12. package/dist/src/cli/index.d.ts +2 -0
  13. package/dist/src/cli/index.js +503 -0
  14. package/dist/src/cli/tui/index-progress.d.ts +12 -0
  15. package/dist/src/cli/tui/index-progress.js +49 -0
  16. package/dist/src/cli/tui/watch-status.d.ts +10 -0
  17. package/dist/src/cli/tui/watch-status.js +27 -0
  18. package/dist/src/cli/update.d.ts +18 -0
  19. package/dist/src/cli/update.js +111 -0
  20. package/dist/src/config/dotenv.d.ts +1 -0
  21. package/dist/src/config/dotenv.js +14 -0
  22. package/dist/src/config/graph-runtime.d.ts +13 -0
  23. package/dist/src/config/graph-runtime.js +29 -0
  24. package/dist/src/config/runtime-config.d.ts +87 -0
  25. package/dist/src/config/runtime-config.js +215 -0
  26. package/dist/src/config/semantic-runtime.d.ts +24 -0
  27. package/dist/src/config/semantic-runtime.js +89 -0
  28. package/dist/src/context/context-builder.d.ts +20 -0
  29. package/dist/src/context/context-builder.js +277 -0
  30. package/dist/src/context/expansion-policy.d.ts +6 -0
  31. package/dist/src/context/expansion-policy.js +49 -0
  32. package/dist/src/context/skeletonizer.d.ts +2 -0
  33. package/dist/src/context/skeletonizer.js +79 -0
  34. package/dist/src/context/snippet-renderer.d.ts +2 -0
  35. package/dist/src/context/snippet-renderer.js +67 -0
  36. package/dist/src/core/contracts.d.ts +74 -0
  37. package/dist/src/core/contracts.js +1 -0
  38. package/dist/src/core/engine.d.ts +64 -0
  39. package/dist/src/core/engine.js +442 -0
  40. package/dist/src/core/types.d.ts +490 -0
  41. package/dist/src/core/types.js +1 -0
  42. package/dist/src/diagnostics/doctor.d.ts +66 -0
  43. package/dist/src/diagnostics/doctor.js +193 -0
  44. package/dist/src/diagnostics/embedding-test.d.ts +24 -0
  45. package/dist/src/diagnostics/embedding-test.js +83 -0
  46. package/dist/src/graph/diff-files.d.ts +1 -0
  47. package/dist/src/graph/diff-files.js +14 -0
  48. package/dist/src/graph/impact-report.d.ts +10 -0
  49. package/dist/src/graph/impact-report.js +173 -0
  50. package/dist/src/graph/in-memory-graph-store.d.ts +36 -0
  51. package/dist/src/graph/in-memory-graph-store.js +395 -0
  52. package/dist/src/graph/owner-ranking.d.ts +2 -0
  53. package/dist/src/graph/owner-ranking.js +41 -0
  54. package/dist/src/graph/sqlite-graph-store.d.ts +51 -0
  55. package/dist/src/graph/sqlite-graph-store.js +724 -0
  56. package/dist/src/graph/sqlite-statements.d.ts +36 -0
  57. package/dist/src/graph/sqlite-statements.js +105 -0
  58. package/dist/src/graph/target-matcher.d.ts +13 -0
  59. package/dist/src/graph/target-matcher.js +64 -0
  60. package/dist/src/index.d.ts +32 -0
  61. package/dist/src/index.js +32 -0
  62. package/dist/src/indexing/analyzers/fallback-analyzer.d.ts +6 -0
  63. package/dist/src/indexing/analyzers/fallback-analyzer.js +45 -0
  64. package/dist/src/indexing/analyzers/go-treesitter-analyzer.d.ts +2 -0
  65. package/dist/src/indexing/analyzers/go-treesitter-analyzer.js +87 -0
  66. package/dist/src/indexing/analyzers/java-treesitter-analyzer.d.ts +2 -0
  67. package/dist/src/indexing/analyzers/java-treesitter-analyzer.js +88 -0
  68. package/dist/src/indexing/analyzers/python-treesitter-analyzer.d.ts +2 -0
  69. package/dist/src/indexing/analyzers/python-treesitter-analyzer.js +96 -0
  70. package/dist/src/indexing/analyzers/registry.d.ts +5 -0
  71. package/dist/src/indexing/analyzers/registry.js +23 -0
  72. package/dist/src/indexing/analyzers/rust-treesitter-analyzer.d.ts +2 -0
  73. package/dist/src/indexing/analyzers/rust-treesitter-analyzer.js +96 -0
  74. package/dist/src/indexing/analyzers/tree-sitter-base.d.ts +30 -0
  75. package/dist/src/indexing/analyzers/tree-sitter-base.js +163 -0
  76. package/dist/src/indexing/analyzers/types.d.ts +17 -0
  77. package/dist/src/indexing/analyzers/types.js +1 -0
  78. package/dist/src/indexing/analyzers/typescript-analyzer.d.ts +5 -0
  79. package/dist/src/indexing/analyzers/typescript-analyzer.js +199 -0
  80. package/dist/src/indexing/ast-analyzer.d.ts +11 -0
  81. package/dist/src/indexing/ast-analyzer.js +11 -0
  82. package/dist/src/indexing/chunker.d.ts +11 -0
  83. package/dist/src/indexing/chunker.js +157 -0
  84. package/dist/src/indexing/ignore-policy.d.ts +6 -0
  85. package/dist/src/indexing/ignore-policy.js +40 -0
  86. package/dist/src/indexing/indexer.d.ts +13 -0
  87. package/dist/src/indexing/indexer.js +189 -0
  88. package/dist/src/indexing/language.d.ts +3 -0
  89. package/dist/src/indexing/language.js +24 -0
  90. package/dist/src/indexing/scanner.d.ts +13 -0
  91. package/dist/src/indexing/scanner.js +87 -0
  92. package/dist/src/lsp/definition-resolver.d.ts +6 -0
  93. package/dist/src/lsp/definition-resolver.js +60 -0
  94. package/dist/src/lsp/typescript-language-service.d.ts +21 -0
  95. package/dist/src/lsp/typescript-language-service.js +82 -0
  96. package/dist/src/mcp/server.d.ts +11 -0
  97. package/dist/src/mcp/server.js +64 -0
  98. package/dist/src/mcp/tools.d.ts +266 -0
  99. package/dist/src/mcp/tools.js +309 -0
  100. package/dist/src/project/project-identity.d.ts +2 -0
  101. package/dist/src/project/project-identity.js +24 -0
  102. package/dist/src/project/project-registry.d.ts +12 -0
  103. package/dist/src/project/project-registry.js +49 -0
  104. package/dist/src/project/workspace-resolver.d.ts +20 -0
  105. package/dist/src/project/workspace-resolver.js +62 -0
  106. package/dist/src/retrieval/graph-reranker.d.ts +11 -0
  107. package/dist/src/retrieval/graph-reranker.js +0 -0
  108. package/dist/src/retrieval/hybrid-retriever.d.ts +31 -0
  109. package/dist/src/retrieval/hybrid-retriever.js +111 -0
  110. package/dist/src/retrieval/path-classification.d.ts +6 -0
  111. package/dist/src/retrieval/path-classification.js +22 -0
  112. package/dist/src/retrieval/query-matching.d.ts +22 -0
  113. package/dist/src/retrieval/query-matching.js +166 -0
  114. package/dist/src/retrieval/query-planner.d.ts +5 -0
  115. package/dist/src/retrieval/query-planner.js +77 -0
  116. package/dist/src/retrieval/ranking-signals.d.ts +19 -0
  117. package/dist/src/retrieval/ranking-signals.js +97 -0
  118. package/dist/src/retrieval/topology-distance.d.ts +21 -0
  119. package/dist/src/retrieval/topology-distance.js +116 -0
  120. package/dist/src/reuse/reuse-detector.d.ts +12 -0
  121. package/dist/src/reuse/reuse-detector.js +564 -0
  122. package/dist/src/semantic/deterministic-embedding.d.ts +7 -0
  123. package/dist/src/semantic/deterministic-embedding.js +31 -0
  124. package/dist/src/semantic/in-memory-semantic-store.d.ts +11 -0
  125. package/dist/src/semantic/in-memory-semantic-store.js +65 -0
  126. package/dist/src/semantic/lance-semantic-store.d.ts +131 -0
  127. package/dist/src/semantic/lance-semantic-store.js +623 -0
  128. package/dist/src/semantic/openai-compatible-embedding.d.ts +19 -0
  129. package/dist/src/semantic/openai-compatible-embedding.js +75 -0
  130. package/dist/src/service/service-identity.d.ts +13 -0
  131. package/dist/src/service/service-identity.js +48 -0
  132. package/dist/src/service/service-manager.d.ts +29 -0
  133. package/dist/src/service/service-manager.js +231 -0
  134. package/dist/src/service/service-templates.d.ts +22 -0
  135. package/dist/src/service/service-templates.js +101 -0
  136. package/dist/src/subgraph/impact-explainer.d.ts +2 -0
  137. package/dist/src/subgraph/impact-explainer.js +54 -0
  138. package/dist/src/subgraph/node-expander.d.ts +13 -0
  139. package/dist/src/subgraph/node-expander.js +139 -0
  140. package/dist/src/subgraph/output-preset.d.ts +3 -0
  141. package/dist/src/subgraph/output-preset.js +102 -0
  142. package/dist/src/subgraph/subgraph-builder.d.ts +17 -0
  143. package/dist/src/subgraph/subgraph-builder.js +688 -0
  144. package/dist/src/topology/export-index.d.ts +7 -0
  145. package/dist/src/topology/export-index.js +14 -0
  146. package/dist/src/topology/framework-topology.d.ts +3 -0
  147. package/dist/src/topology/framework-topology.js +460 -0
  148. package/dist/src/topology/import-resolver.d.ts +2 -0
  149. package/dist/src/topology/import-resolver.js +29 -0
  150. package/dist/src/topology/orm-topology.d.ts +3 -0
  151. package/dist/src/topology/orm-topology.js +200 -0
  152. package/dist/src/topology/runtime-topology.d.ts +3 -0
  153. package/dist/src/topology/runtime-topology.js +204 -0
  154. package/dist/src/topology/symbol-resolver.d.ts +6 -0
  155. package/dist/src/topology/symbol-resolver.js +74 -0
  156. package/dist/src/topology/test-topology.d.ts +2 -0
  157. package/dist/src/topology/test-topology.js +82 -0
  158. package/dist/src/utils/hash.d.ts +2 -0
  159. package/dist/src/utils/hash.js +7 -0
  160. package/dist/src/utils/path.d.ts +2 -0
  161. package/dist/src/utils/path.js +7 -0
  162. package/dist/src/watch/event-journal.d.ts +17 -0
  163. package/dist/src/watch/event-journal.js +81 -0
  164. package/dist/src/watch/file-event-coalescer.d.ts +9 -0
  165. package/dist/src/watch/file-event-coalescer.js +39 -0
  166. package/dist/src/watch/index-scheduler.d.ts +52 -0
  167. package/dist/src/watch/index-scheduler.js +190 -0
  168. package/dist/src/watch/watch-daemon.d.ts +73 -0
  169. package/dist/src/watch/watch-daemon.js +368 -0
  170. package/dist/src/watch/watcher-liveness.d.ts +47 -0
  171. package/dist/src/watch/watcher-liveness.js +168 -0
  172. package/dist/src/web/server.d.ts +1 -0
  173. package/dist/src/web/server.js +375 -0
  174. package/package.json +94 -0
@@ -0,0 +1,96 @@
1
+ import Parser from "tree-sitter";
2
+ // @ts-ignore - tree-sitter-rust doesn't have TypeScript definitions
3
+ import Rust from "tree-sitter-rust";
4
+ import { analyzeWithTreeSitter } from "./tree-sitter-base.js";
5
+ let parser = null;
6
+ function getParser() {
7
+ if (!parser) {
8
+ parser = new Parser();
9
+ parser.setLanguage(Rust);
10
+ }
11
+ return parser;
12
+ }
13
+ const rustConfig = {
14
+ symbolPatterns: [
15
+ {
16
+ type: "function_item",
17
+ kind: "function",
18
+ nameField: "name",
19
+ exportModifierCheck: (node) => {
20
+ return node.children.some((child) => child.type === "visibility_modifier" && child.text === "pub");
21
+ }
22
+ },
23
+ {
24
+ type: "struct_item",
25
+ kind: "type",
26
+ nameField: "name",
27
+ exportModifierCheck: (node) => {
28
+ return node.children.some((child) => child.type === "visibility_modifier" && child.text === "pub");
29
+ }
30
+ },
31
+ {
32
+ type: "enum_item",
33
+ kind: "type",
34
+ nameField: "name",
35
+ exportModifierCheck: (node) => {
36
+ return node.children.some((child) => child.type === "visibility_modifier" && child.text === "pub");
37
+ }
38
+ },
39
+ {
40
+ type: "trait_item",
41
+ kind: "type",
42
+ nameField: "name",
43
+ exportModifierCheck: (node) => {
44
+ return node.children.some((child) => child.type === "visibility_modifier" && child.text === "pub");
45
+ }
46
+ },
47
+ {
48
+ type: "impl_item",
49
+ kind: "type",
50
+ nameField: "type",
51
+ exportModifierCheck: () => false // impl blocks are internal implementation details
52
+ }
53
+ ],
54
+ importPatterns: [
55
+ {
56
+ type: "use_declaration",
57
+ sourceField: "argument",
58
+ bindingsExtractor: (node) => {
59
+ const argNode = node.childForFieldName("argument");
60
+ if (!argNode)
61
+ return [];
62
+ const path = argNode.text;
63
+ return [{ imported: path, local: path.split("::").pop() ?? path }];
64
+ }
65
+ }
66
+ ],
67
+ callPatterns: [
68
+ {
69
+ type: "call_expression",
70
+ nameExtractor: (node) => {
71
+ const functionNode = node.childForFieldName("function");
72
+ if (!functionNode)
73
+ return undefined;
74
+ if (functionNode.type === "identifier") {
75
+ return functionNode.text;
76
+ }
77
+ else if (functionNode.type === "field_expression") {
78
+ const fieldNode = functionNode.childForFieldName("field");
79
+ return fieldNode?.text;
80
+ }
81
+ else if (functionNode.type === "scoped_identifier") {
82
+ const nameNode = functionNode.childForFieldName("name");
83
+ return nameNode?.text;
84
+ }
85
+ return undefined;
86
+ }
87
+ }
88
+ ]
89
+ };
90
+ export const rustTreeSitterAnalyzer = {
91
+ language: "rust",
92
+ capabilities: ["symbols", "imports", "exports", "calls"],
93
+ analyzeFile: ({ repoRoot, file, content }) => {
94
+ return analyzeWithTreeSitter(getParser(), rustConfig, repoRoot, file, content);
95
+ }
96
+ };
@@ -0,0 +1,30 @@
1
+ import Parser from "tree-sitter";
2
+ import type { CodeFile, SymbolKind } from "../../core/types.js";
3
+ import type { FileAnalysis } from "./types.js";
4
+ export interface TreeSitterNodePattern {
5
+ type: string;
6
+ kind: SymbolKind;
7
+ nameField?: string;
8
+ nameExtractor?: (node: Parser.SyntaxNode) => string | undefined;
9
+ signatureField?: string;
10
+ exportModifierCheck?: (node: Parser.SyntaxNode) => boolean;
11
+ }
12
+ export interface TreeSitterImportPattern {
13
+ type: string;
14
+ sourceField?: string;
15
+ sourceExtractor?: (node: Parser.SyntaxNode) => string | undefined;
16
+ bindingsExtractor?: (node: Parser.SyntaxNode) => Array<{
17
+ imported: string;
18
+ local: string;
19
+ }>;
20
+ }
21
+ export interface TreeSitterCallPattern {
22
+ type: string;
23
+ nameExtractor: (node: Parser.SyntaxNode) => string | undefined;
24
+ }
25
+ export interface TreeSitterLanguageConfig {
26
+ symbolPatterns: TreeSitterNodePattern[];
27
+ importPatterns: TreeSitterImportPattern[];
28
+ callPatterns: TreeSitterCallPattern[];
29
+ }
30
+ export declare function analyzeWithTreeSitter(parser: Parser, config: TreeSitterLanguageConfig, repoRoot: string, file: CodeFile, content: string): FileAnalysis;
@@ -0,0 +1,163 @@
1
+ import { sha256, stableId } from "../../utils/hash.js";
2
+ import { createFileSymbol } from "./fallback-analyzer.js";
3
+ export function analyzeWithTreeSitter(parser, config, repoRoot, file, content) {
4
+ const tree = parser.parse(content);
5
+ const lines = content.split(/\r?\n/);
6
+ const fileSymbol = createFileSymbol(repoRoot, file, lines.length);
7
+ const symbols = [fileSymbol];
8
+ const chunks = [];
9
+ const edges = [];
10
+ // Extract imports
11
+ extractImports(tree.rootNode, config.importPatterns, repoRoot, file, fileSymbol.id, edges);
12
+ // Extract symbols and their relationships
13
+ const symbolStack = [fileSymbol];
14
+ function visit(node) {
15
+ const symbol = extractSymbol(node, config.symbolPatterns, repoRoot, file, content);
16
+ if (symbol) {
17
+ symbols.push(symbol);
18
+ chunks.push(createChunkFromSymbol(repoRoot, file, content, symbol, node));
19
+ // Containment edge
20
+ edges.push({
21
+ projectId: file.projectId,
22
+ sourceId: symbolStack[symbolStack.length - 1]?.id ?? fileSymbol.id,
23
+ targetId: symbol.id,
24
+ kind: "contains",
25
+ metadata: { sourceFile: file.path }
26
+ });
27
+ // Export edge
28
+ if (symbol.exported) {
29
+ edges.push({
30
+ projectId: file.projectId,
31
+ sourceId: fileSymbol.id,
32
+ targetId: symbol.id,
33
+ kind: "exports",
34
+ metadata: { sourceFile: file.path, name: symbol.name }
35
+ });
36
+ }
37
+ symbolStack.push(symbol);
38
+ // Extract calls within this symbol
39
+ extractCalls(node, config.callPatterns, repoRoot, file, symbol.id, edges);
40
+ for (const child of node.children) {
41
+ visit(child);
42
+ }
43
+ symbolStack.pop();
44
+ }
45
+ else {
46
+ for (const child of node.children) {
47
+ visit(child);
48
+ }
49
+ }
50
+ }
51
+ visit(tree.rootNode);
52
+ return { chunks, symbols, edges };
53
+ }
54
+ function extractSymbol(node, patterns, repoRoot, file, content) {
55
+ for (const pattern of patterns) {
56
+ if (node.type === pattern.type) {
57
+ const name = pattern.nameExtractor
58
+ ? pattern.nameExtractor(node)
59
+ : pattern.nameField
60
+ ? node.childForFieldName(pattern.nameField)?.text
61
+ : undefined;
62
+ if (!name)
63
+ continue;
64
+ const startLine = node.startPosition.row + 1;
65
+ const endLine = node.endPosition.row + 1;
66
+ const signature = extractSignature(node, content);
67
+ const exported = pattern.exportModifierCheck ? pattern.exportModifierCheck(node) : false;
68
+ return {
69
+ id: stableId([repoRoot, file.path, name, startLine, endLine, pattern.kind]),
70
+ projectId: file.projectId,
71
+ filePath: file.path,
72
+ name,
73
+ kind: pattern.kind,
74
+ language: file.language,
75
+ startLine,
76
+ endLine,
77
+ signature,
78
+ exported
79
+ };
80
+ }
81
+ }
82
+ return undefined;
83
+ }
84
+ function extractImports(root, patterns, repoRoot, file, fileSymbolId, edges) {
85
+ function visit(node) {
86
+ for (const pattern of patterns) {
87
+ if (node.type === pattern.type) {
88
+ const source = pattern.sourceExtractor
89
+ ? pattern.sourceExtractor(node)
90
+ : pattern.sourceField
91
+ ? node.childForFieldName(pattern.sourceField)?.text.replace(/['"]/g, "")
92
+ : undefined;
93
+ if (source) {
94
+ const bindings = pattern.bindingsExtractor ? pattern.bindingsExtractor(node) : [];
95
+ edges.push({
96
+ projectId: file.projectId,
97
+ sourceId: fileSymbolId,
98
+ targetId: stableId([repoRoot, source, "module"]),
99
+ kind: "imports",
100
+ metadata: {
101
+ source,
102
+ sourceFile: file.path,
103
+ line: node.startPosition.row + 1,
104
+ bindings: bindings.length > 0 ? bindings : undefined
105
+ }
106
+ });
107
+ }
108
+ }
109
+ }
110
+ for (const child of node.children) {
111
+ visit(child);
112
+ }
113
+ }
114
+ visit(root);
115
+ }
116
+ function extractCalls(node, patterns, repoRoot, file, symbolId, edges) {
117
+ function visit(node) {
118
+ for (const pattern of patterns) {
119
+ if (node.type === pattern.type) {
120
+ const targetName = pattern.nameExtractor(node);
121
+ if (targetName) {
122
+ edges.push({
123
+ projectId: file.projectId,
124
+ sourceId: symbolId,
125
+ targetId: stableId([repoRoot, targetName, "symbol"]),
126
+ kind: "calls",
127
+ metadata: {
128
+ targetName,
129
+ sourceFile: file.path,
130
+ line: node.startPosition.row + 1
131
+ }
132
+ });
133
+ }
134
+ }
135
+ }
136
+ for (const child of node.children) {
137
+ visit(child);
138
+ }
139
+ }
140
+ visit(node);
141
+ }
142
+ function createChunkFromSymbol(repoRoot, file, content, symbol, node) {
143
+ const body = node.text;
144
+ return {
145
+ id: stableId([repoRoot, file.path, symbol.name, symbol.startLine, symbol.endLine, sha256(body)]),
146
+ projectId: file.projectId,
147
+ repoRoot,
148
+ filePath: file.path,
149
+ language: file.language,
150
+ kind: symbol.kind === "unknown" ? "block" : symbol.kind,
151
+ symbolName: symbol.name,
152
+ startLine: symbol.startLine,
153
+ endLine: symbol.endLine,
154
+ content: body,
155
+ contentHash: sha256(body)
156
+ };
157
+ }
158
+ function extractSignature(node, content) {
159
+ const start = node.startIndex;
160
+ const firstLineEnd = content.indexOf("\n", start);
161
+ const end = firstLineEnd === -1 ? node.endIndex : Math.min(firstLineEnd, start + 200);
162
+ return content.slice(start, end).trim();
163
+ }
@@ -0,0 +1,17 @@
1
+ import type { CodeChunk, CodeFile, GraphEdge, LanguageId, SymbolNode } from "../../core/types.js";
2
+ export interface FileAnalysis {
3
+ chunks: CodeChunk[];
4
+ symbols: SymbolNode[];
5
+ edges: GraphEdge[];
6
+ }
7
+ export interface AnalyzeFileInput {
8
+ repoRoot: string;
9
+ file: CodeFile;
10
+ content: string;
11
+ }
12
+ export type AnalyzerCapability = "symbols" | "imports" | "exports" | "calls" | "definitions" | "framework_routes" | "tests";
13
+ export interface LanguageAnalyzer {
14
+ language: LanguageId;
15
+ capabilities: AnalyzerCapability[];
16
+ analyzeFile(input: AnalyzeFileInput): FileAnalysis;
17
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { CodeFile } from "../../core/types.js";
2
+ import type { FileAnalysis, LanguageAnalyzer } from "./types.js";
3
+ export declare const typescriptAnalyzer: LanguageAnalyzer;
4
+ export declare const javascriptAnalyzer: LanguageAnalyzer;
5
+ export declare function analyzeTypeScriptFile(repoRoot: string, file: CodeFile, content: string): FileAnalysis;
@@ -0,0 +1,199 @@
1
+ import ts from "typescript";
2
+ import { sha256, stableId } from "../../utils/hash.js";
3
+ import { createFileSymbol, fallbackFileAnalysis } from "./fallback-analyzer.js";
4
+ export const typescriptAnalyzer = {
5
+ language: "typescript",
6
+ capabilities: ["symbols", "imports", "exports", "calls", "definitions", "framework_routes", "tests"],
7
+ analyzeFile: ({ repoRoot, file, content }) => analyzeTypeScriptFile(repoRoot, file, content)
8
+ };
9
+ export const javascriptAnalyzer = {
10
+ ...typescriptAnalyzer,
11
+ language: "javascript"
12
+ };
13
+ export function analyzeTypeScriptFile(repoRoot, file, content) {
14
+ const sourceFile = ts.createSourceFile(file.path, content, ts.ScriptTarget.Latest, true, scriptKindForPath(file.path));
15
+ const lines = content.split(/\r?\n/);
16
+ const chunks = [];
17
+ const symbols = [];
18
+ const edges = [];
19
+ const fileSymbol = createFileSymbol(repoRoot, file, lines.length);
20
+ symbols.push(fileSymbol);
21
+ for (const statement of sourceFile.statements) {
22
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
23
+ const importSource = statement.moduleSpecifier.text;
24
+ edges.push({
25
+ projectId: file.projectId,
26
+ sourceId: fileSymbol.id,
27
+ targetId: stableId([repoRoot, importSource, "module"]),
28
+ kind: "imports",
29
+ metadata: { source: importSource, sourceFile: file.path, line: lineRange(sourceFile, statement).startLine, bindings: importBindings(statement) }
30
+ });
31
+ }
32
+ }
33
+ const symbolStack = [fileSymbol];
34
+ function visit(node) {
35
+ const symbol = symbolFromNode(repoRoot, file, sourceFile, node);
36
+ if (symbol) {
37
+ if (symbol.kind === "variable" && symbolStack[symbolStack.length - 1]?.kind !== "file" && !symbol.exported) {
38
+ ts.forEachChild(node, visit);
39
+ return;
40
+ }
41
+ symbols.push(symbol);
42
+ chunks.push(chunkFromSymbol(repoRoot, file, sourceFile, content, symbol, node));
43
+ edges.push({
44
+ projectId: file.projectId,
45
+ sourceId: symbolStack[symbolStack.length - 1]?.id ?? fileSymbol.id,
46
+ targetId: symbol.id,
47
+ kind: "contains",
48
+ metadata: { sourceFile: file.path }
49
+ });
50
+ if (symbol.exported) {
51
+ edges.push({
52
+ projectId: file.projectId,
53
+ sourceId: fileSymbol.id,
54
+ targetId: symbol.id,
55
+ kind: "exports",
56
+ metadata: { sourceFile: file.path, name: symbol.name }
57
+ });
58
+ }
59
+ symbolStack.push(symbol);
60
+ ts.forEachChild(node, visit);
61
+ symbolStack.pop();
62
+ return;
63
+ }
64
+ if (ts.isCallExpression(node)) {
65
+ const targetName = callTargetName(node.expression);
66
+ if (targetName) {
67
+ edges.push({
68
+ projectId: file.projectId,
69
+ sourceId: symbolStack[symbolStack.length - 1]?.id ?? fileSymbol.id,
70
+ targetId: stableId([repoRoot, targetName, "symbol"]),
71
+ kind: "calls",
72
+ metadata: { targetName, sourceFile: file.path, line: lineRange(sourceFile, node).startLine, position: callTargetPosition(node.expression, sourceFile) }
73
+ });
74
+ }
75
+ }
76
+ ts.forEachChild(node, visit);
77
+ }
78
+ ts.forEachChild(sourceFile, visit);
79
+ if (chunks.length === 0) {
80
+ return fallbackFileAnalysis(repoRoot, file, content, fileSymbol, edges);
81
+ }
82
+ return { chunks, symbols, edges };
83
+ }
84
+ function symbolFromNode(repoRoot, file, sourceFile, node) {
85
+ const named = nodeName(node);
86
+ if (!named)
87
+ return undefined;
88
+ const range = lineRange(sourceFile, node);
89
+ const kind = symbolKind(node);
90
+ if (!kind)
91
+ return undefined;
92
+ return {
93
+ id: stableId([repoRoot, file.path, named, range.startLine, range.endLine, kind]),
94
+ projectId: file.projectId,
95
+ filePath: file.path,
96
+ name: named,
97
+ kind,
98
+ language: file.language,
99
+ startLine: range.startLine,
100
+ endLine: range.endLine,
101
+ signature: firstLine(sourceFile.text.slice(node.getStart(sourceFile), node.getEnd())),
102
+ exported: hasExportModifier(node)
103
+ };
104
+ }
105
+ function chunkFromSymbol(repoRoot, file, sourceFile, content, symbol, node) {
106
+ const body = content.slice(node.getStart(sourceFile), node.getEnd());
107
+ return {
108
+ id: stableId([repoRoot, file.path, symbol.name, symbol.startLine, symbol.endLine, sha256(body)]),
109
+ projectId: file.projectId,
110
+ repoRoot,
111
+ filePath: file.path,
112
+ language: file.language,
113
+ kind: symbol.kind === "unknown" ? "block" : symbol.kind,
114
+ symbolName: symbol.name,
115
+ startLine: symbol.startLine,
116
+ endLine: symbol.endLine,
117
+ content: body,
118
+ contentHash: sha256(body)
119
+ };
120
+ }
121
+ function nodeName(node) {
122
+ if ((ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) && node.name) {
123
+ return node.name.text;
124
+ }
125
+ if (ts.isMethodDeclaration(node) && node.name) {
126
+ return propertyName(node.name);
127
+ }
128
+ if (ts.isVariableStatement(node)) {
129
+ const declaration = node.declarationList.declarations[0];
130
+ if (declaration?.name && ts.isIdentifier(declaration.name))
131
+ return declaration.name.text;
132
+ }
133
+ return undefined;
134
+ }
135
+ function symbolKind(node) {
136
+ if (ts.isFunctionDeclaration(node))
137
+ return "function";
138
+ if (ts.isClassDeclaration(node))
139
+ return "class";
140
+ if (ts.isMethodDeclaration(node))
141
+ return "method";
142
+ if (ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node))
143
+ return "type";
144
+ if (ts.isVariableStatement(node))
145
+ return "variable";
146
+ return undefined;
147
+ }
148
+ function propertyName(name) {
149
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name))
150
+ return name.text;
151
+ return undefined;
152
+ }
153
+ function callTargetName(expression) {
154
+ if (ts.isIdentifier(expression))
155
+ return expression.text;
156
+ if (ts.isPropertyAccessExpression(expression))
157
+ return expression.name.text;
158
+ return undefined;
159
+ }
160
+ function callTargetPosition(expression, sourceFile) {
161
+ if (ts.isPropertyAccessExpression(expression))
162
+ return expression.name.getStart(sourceFile);
163
+ return expression.getStart(sourceFile);
164
+ }
165
+ function importBindings(node) {
166
+ const clause = node.importClause;
167
+ if (!clause)
168
+ return [];
169
+ const bindings = [];
170
+ if (clause.name)
171
+ bindings.push({ imported: "default", local: clause.name.text });
172
+ const namedBindings = clause.namedBindings;
173
+ if (namedBindings && ts.isNamedImports(namedBindings)) {
174
+ for (const element of namedBindings.elements) {
175
+ bindings.push({ imported: element.propertyName?.text ?? element.name.text, local: element.name.text });
176
+ }
177
+ }
178
+ return bindings;
179
+ }
180
+ function hasExportModifier(node) {
181
+ return Boolean(ts.canHaveModifiers(node) && ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
182
+ }
183
+ function lineRange(sourceFile, node) {
184
+ const start = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
185
+ const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
186
+ return { startLine: start.line + 1, endLine: end.line + 1 };
187
+ }
188
+ function firstLine(content) {
189
+ return content.split(/\r?\n/, 1)[0]?.trim() ?? "";
190
+ }
191
+ function scriptKindForPath(filePath) {
192
+ if (filePath.endsWith(".tsx"))
193
+ return ts.ScriptKind.TSX;
194
+ if (filePath.endsWith(".jsx"))
195
+ return ts.ScriptKind.JSX;
196
+ if (filePath.endsWith(".js") || filePath.endsWith(".mjs") || filePath.endsWith(".cjs"))
197
+ return ts.ScriptKind.JS;
198
+ return ts.ScriptKind.TS;
199
+ }
@@ -0,0 +1,11 @@
1
+ import type { CodeFile } from "../core/types.js";
2
+ import type { FileAnalysis } from "./analyzers/types.js";
3
+ export type { AnalyzerCapability, AnalyzeFileInput, FileAnalysis, LanguageAnalyzer } from "./analyzers/types.js";
4
+ export { analyzerFor, analyzeFileWithRegistry, listAnalyzers } from "./analyzers/registry.js";
5
+ export { fallbackAnalyzer } from "./analyzers/fallback-analyzer.js";
6
+ export { goTreeSitterAnalyzer, goTreeSitterAnalyzer as goAnalyzer } from "./analyzers/go-treesitter-analyzer.js";
7
+ export { javaTreeSitterAnalyzer, javaTreeSitterAnalyzer as javaAnalyzer } from "./analyzers/java-treesitter-analyzer.js";
8
+ export { pythonTreeSitterAnalyzer, pythonTreeSitterAnalyzer as pythonAnalyzer } from "./analyzers/python-treesitter-analyzer.js";
9
+ export { rustTreeSitterAnalyzer, rustTreeSitterAnalyzer as rustAnalyzer } from "./analyzers/rust-treesitter-analyzer.js";
10
+ export { javascriptAnalyzer, typescriptAnalyzer } from "./analyzers/typescript-analyzer.js";
11
+ export declare function analyzeFile(repoRoot: string, file: CodeFile, content: string): FileAnalysis;
@@ -0,0 +1,11 @@
1
+ import { analyzeFileWithRegistry } from "./analyzers/registry.js";
2
+ export { analyzerFor, analyzeFileWithRegistry, listAnalyzers } from "./analyzers/registry.js";
3
+ export { fallbackAnalyzer } from "./analyzers/fallback-analyzer.js";
4
+ export { goTreeSitterAnalyzer, goTreeSitterAnalyzer as goAnalyzer } from "./analyzers/go-treesitter-analyzer.js";
5
+ export { javaTreeSitterAnalyzer, javaTreeSitterAnalyzer as javaAnalyzer } from "./analyzers/java-treesitter-analyzer.js";
6
+ export { pythonTreeSitterAnalyzer, pythonTreeSitterAnalyzer as pythonAnalyzer } from "./analyzers/python-treesitter-analyzer.js";
7
+ export { rustTreeSitterAnalyzer, rustTreeSitterAnalyzer as rustAnalyzer } from "./analyzers/rust-treesitter-analyzer.js";
8
+ export { javascriptAnalyzer, typescriptAnalyzer } from "./analyzers/typescript-analyzer.js";
9
+ export function analyzeFile(repoRoot, file, content) {
10
+ return analyzeFileWithRegistry({ repoRoot, file, content });
11
+ }
@@ -0,0 +1,11 @@
1
+ import type { CodeChunk, CodeFile, GraphEdge, SymbolNode } from "../core/types.js";
2
+ export interface ChunkingResult {
3
+ chunks: CodeChunk[];
4
+ symbols: SymbolNode[];
5
+ edges: GraphEdge[];
6
+ }
7
+ export interface ChunkOptions {
8
+ targetLines?: number;
9
+ }
10
+ export declare function chunkFiles(repoRoot: string, files: CodeFile[], options?: ChunkOptions): Promise<ChunkingResult>;
11
+ export declare function chunkFilesIncremental(repoRoot: string, files: CodeFile[], filesToAnalyze: CodeFile[], cached: ChunkingResult, options?: ChunkOptions): Promise<ChunkingResult>;