@duytransipher/gitnexus 1.4.6-sipher.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 (224) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +261 -0
  3. package/dist/cli/ai-context.d.ts +23 -0
  4. package/dist/cli/ai-context.js +265 -0
  5. package/dist/cli/analyze.d.ts +12 -0
  6. package/dist/cli/analyze.js +345 -0
  7. package/dist/cli/augment.d.ts +13 -0
  8. package/dist/cli/augment.js +33 -0
  9. package/dist/cli/clean.d.ts +10 -0
  10. package/dist/cli/clean.js +60 -0
  11. package/dist/cli/eval-server.d.ts +37 -0
  12. package/dist/cli/eval-server.js +389 -0
  13. package/dist/cli/index.d.ts +2 -0
  14. package/dist/cli/index.js +137 -0
  15. package/dist/cli/lazy-action.d.ts +6 -0
  16. package/dist/cli/lazy-action.js +18 -0
  17. package/dist/cli/list.d.ts +6 -0
  18. package/dist/cli/list.js +30 -0
  19. package/dist/cli/mcp.d.ts +8 -0
  20. package/dist/cli/mcp.js +36 -0
  21. package/dist/cli/serve.d.ts +4 -0
  22. package/dist/cli/serve.js +6 -0
  23. package/dist/cli/setup.d.ts +8 -0
  24. package/dist/cli/setup.js +367 -0
  25. package/dist/cli/sipher-patched.d.ts +2 -0
  26. package/dist/cli/sipher-patched.js +77 -0
  27. package/dist/cli/skill-gen.d.ts +26 -0
  28. package/dist/cli/skill-gen.js +549 -0
  29. package/dist/cli/status.d.ts +6 -0
  30. package/dist/cli/status.js +36 -0
  31. package/dist/cli/tool.d.ts +60 -0
  32. package/dist/cli/tool.js +180 -0
  33. package/dist/cli/wiki.d.ts +15 -0
  34. package/dist/cli/wiki.js +365 -0
  35. package/dist/config/ignore-service.d.ts +26 -0
  36. package/dist/config/ignore-service.js +284 -0
  37. package/dist/config/supported-languages.d.ts +15 -0
  38. package/dist/config/supported-languages.js +16 -0
  39. package/dist/core/augmentation/engine.d.ts +26 -0
  40. package/dist/core/augmentation/engine.js +240 -0
  41. package/dist/core/embeddings/embedder.d.ts +60 -0
  42. package/dist/core/embeddings/embedder.js +251 -0
  43. package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
  44. package/dist/core/embeddings/embedding-pipeline.js +356 -0
  45. package/dist/core/embeddings/index.d.ts +9 -0
  46. package/dist/core/embeddings/index.js +9 -0
  47. package/dist/core/embeddings/text-generator.d.ts +24 -0
  48. package/dist/core/embeddings/text-generator.js +182 -0
  49. package/dist/core/embeddings/types.d.ts +87 -0
  50. package/dist/core/embeddings/types.js +32 -0
  51. package/dist/core/graph/graph.d.ts +2 -0
  52. package/dist/core/graph/graph.js +66 -0
  53. package/dist/core/graph/types.d.ts +66 -0
  54. package/dist/core/graph/types.js +1 -0
  55. package/dist/core/ingestion/ast-cache.d.ts +11 -0
  56. package/dist/core/ingestion/ast-cache.js +35 -0
  57. package/dist/core/ingestion/call-processor.d.ts +23 -0
  58. package/dist/core/ingestion/call-processor.js +793 -0
  59. package/dist/core/ingestion/call-routing.d.ts +68 -0
  60. package/dist/core/ingestion/call-routing.js +129 -0
  61. package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
  62. package/dist/core/ingestion/cluster-enricher.js +170 -0
  63. package/dist/core/ingestion/community-processor.d.ts +39 -0
  64. package/dist/core/ingestion/community-processor.js +312 -0
  65. package/dist/core/ingestion/constants.d.ts +16 -0
  66. package/dist/core/ingestion/constants.js +16 -0
  67. package/dist/core/ingestion/entry-point-scoring.d.ts +40 -0
  68. package/dist/core/ingestion/entry-point-scoring.js +353 -0
  69. package/dist/core/ingestion/export-detection.d.ts +18 -0
  70. package/dist/core/ingestion/export-detection.js +231 -0
  71. package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
  72. package/dist/core/ingestion/filesystem-walker.js +81 -0
  73. package/dist/core/ingestion/framework-detection.d.ts +54 -0
  74. package/dist/core/ingestion/framework-detection.js +411 -0
  75. package/dist/core/ingestion/heritage-processor.d.ts +28 -0
  76. package/dist/core/ingestion/heritage-processor.js +251 -0
  77. package/dist/core/ingestion/import-processor.d.ts +34 -0
  78. package/dist/core/ingestion/import-processor.js +398 -0
  79. package/dist/core/ingestion/language-config.d.ts +46 -0
  80. package/dist/core/ingestion/language-config.js +167 -0
  81. package/dist/core/ingestion/mro-processor.d.ts +45 -0
  82. package/dist/core/ingestion/mro-processor.js +369 -0
  83. package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
  84. package/dist/core/ingestion/named-binding-extraction.js +363 -0
  85. package/dist/core/ingestion/parsing-processor.d.ts +19 -0
  86. package/dist/core/ingestion/parsing-processor.js +315 -0
  87. package/dist/core/ingestion/pipeline.d.ts +6 -0
  88. package/dist/core/ingestion/pipeline.js +401 -0
  89. package/dist/core/ingestion/process-processor.d.ts +51 -0
  90. package/dist/core/ingestion/process-processor.js +315 -0
  91. package/dist/core/ingestion/resolution-context.d.ts +53 -0
  92. package/dist/core/ingestion/resolution-context.js +132 -0
  93. package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
  94. package/dist/core/ingestion/resolvers/csharp.js +109 -0
  95. package/dist/core/ingestion/resolvers/go.d.ts +19 -0
  96. package/dist/core/ingestion/resolvers/go.js +42 -0
  97. package/dist/core/ingestion/resolvers/index.d.ts +18 -0
  98. package/dist/core/ingestion/resolvers/index.js +13 -0
  99. package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
  100. package/dist/core/ingestion/resolvers/jvm.js +87 -0
  101. package/dist/core/ingestion/resolvers/php.d.ts +15 -0
  102. package/dist/core/ingestion/resolvers/php.js +35 -0
  103. package/dist/core/ingestion/resolvers/python.d.ts +19 -0
  104. package/dist/core/ingestion/resolvers/python.js +52 -0
  105. package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
  106. package/dist/core/ingestion/resolvers/ruby.js +15 -0
  107. package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
  108. package/dist/core/ingestion/resolvers/rust.js +73 -0
  109. package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
  110. package/dist/core/ingestion/resolvers/standard.js +123 -0
  111. package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
  112. package/dist/core/ingestion/resolvers/utils.js +122 -0
  113. package/dist/core/ingestion/structure-processor.d.ts +2 -0
  114. package/dist/core/ingestion/structure-processor.js +36 -0
  115. package/dist/core/ingestion/symbol-table.d.ts +63 -0
  116. package/dist/core/ingestion/symbol-table.js +85 -0
  117. package/dist/core/ingestion/tree-sitter-queries.d.ts +15 -0
  118. package/dist/core/ingestion/tree-sitter-queries.js +888 -0
  119. package/dist/core/ingestion/type-env.d.ts +49 -0
  120. package/dist/core/ingestion/type-env.js +613 -0
  121. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
  123. package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
  124. package/dist/core/ingestion/type-extractors/csharp.js +383 -0
  125. package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
  126. package/dist/core/ingestion/type-extractors/go.js +467 -0
  127. package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
  128. package/dist/core/ingestion/type-extractors/index.js +31 -0
  129. package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
  130. package/dist/core/ingestion/type-extractors/jvm.js +681 -0
  131. package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
  132. package/dist/core/ingestion/type-extractors/php.js +549 -0
  133. package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
  134. package/dist/core/ingestion/type-extractors/python.js +455 -0
  135. package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
  136. package/dist/core/ingestion/type-extractors/ruby.js +389 -0
  137. package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
  138. package/dist/core/ingestion/type-extractors/rust.js +456 -0
  139. package/dist/core/ingestion/type-extractors/shared.d.ts +145 -0
  140. package/dist/core/ingestion/type-extractors/shared.js +810 -0
  141. package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
  142. package/dist/core/ingestion/type-extractors/swift.js +137 -0
  143. package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
  144. package/dist/core/ingestion/type-extractors/types.js +1 -0
  145. package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
  146. package/dist/core/ingestion/type-extractors/typescript.js +494 -0
  147. package/dist/core/ingestion/utils.d.ts +138 -0
  148. package/dist/core/ingestion/utils.js +1290 -0
  149. package/dist/core/ingestion/workers/parse-worker.d.ts +122 -0
  150. package/dist/core/ingestion/workers/parse-worker.js +1126 -0
  151. package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
  152. package/dist/core/ingestion/workers/worker-pool.js +128 -0
  153. package/dist/core/lbug/csv-generator.d.ts +33 -0
  154. package/dist/core/lbug/csv-generator.js +366 -0
  155. package/dist/core/lbug/lbug-adapter.d.ts +103 -0
  156. package/dist/core/lbug/lbug-adapter.js +769 -0
  157. package/dist/core/lbug/schema.d.ts +53 -0
  158. package/dist/core/lbug/schema.js +430 -0
  159. package/dist/core/search/bm25-index.d.ts +23 -0
  160. package/dist/core/search/bm25-index.js +96 -0
  161. package/dist/core/search/hybrid-search.d.ts +49 -0
  162. package/dist/core/search/hybrid-search.js +118 -0
  163. package/dist/core/tree-sitter/parser-loader.d.ts +5 -0
  164. package/dist/core/tree-sitter/parser-loader.js +63 -0
  165. package/dist/core/wiki/generator.d.ts +120 -0
  166. package/dist/core/wiki/generator.js +939 -0
  167. package/dist/core/wiki/graph-queries.d.ts +80 -0
  168. package/dist/core/wiki/graph-queries.js +238 -0
  169. package/dist/core/wiki/html-viewer.d.ts +10 -0
  170. package/dist/core/wiki/html-viewer.js +297 -0
  171. package/dist/core/wiki/llm-client.d.ts +43 -0
  172. package/dist/core/wiki/llm-client.js +186 -0
  173. package/dist/core/wiki/prompts.d.ts +53 -0
  174. package/dist/core/wiki/prompts.js +174 -0
  175. package/dist/lib/utils.d.ts +1 -0
  176. package/dist/lib/utils.js +3 -0
  177. package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
  178. package/dist/mcp/compatible-stdio-transport.js +200 -0
  179. package/dist/mcp/core/embedder.d.ts +27 -0
  180. package/dist/mcp/core/embedder.js +108 -0
  181. package/dist/mcp/core/lbug-adapter.d.ts +57 -0
  182. package/dist/mcp/core/lbug-adapter.js +455 -0
  183. package/dist/mcp/local/local-backend.d.ts +181 -0
  184. package/dist/mcp/local/local-backend.js +1722 -0
  185. package/dist/mcp/resources.d.ts +31 -0
  186. package/dist/mcp/resources.js +411 -0
  187. package/dist/mcp/server.d.ts +23 -0
  188. package/dist/mcp/server.js +296 -0
  189. package/dist/mcp/staleness.d.ts +15 -0
  190. package/dist/mcp/staleness.js +29 -0
  191. package/dist/mcp/tools.d.ts +24 -0
  192. package/dist/mcp/tools.js +292 -0
  193. package/dist/server/api.d.ts +10 -0
  194. package/dist/server/api.js +344 -0
  195. package/dist/server/mcp-http.d.ts +13 -0
  196. package/dist/server/mcp-http.js +100 -0
  197. package/dist/storage/git.d.ts +6 -0
  198. package/dist/storage/git.js +35 -0
  199. package/dist/storage/repo-manager.d.ts +138 -0
  200. package/dist/storage/repo-manager.js +299 -0
  201. package/dist/types/pipeline.d.ts +32 -0
  202. package/dist/types/pipeline.js +18 -0
  203. package/dist/unreal/bridge.d.ts +4 -0
  204. package/dist/unreal/bridge.js +113 -0
  205. package/dist/unreal/config.d.ts +6 -0
  206. package/dist/unreal/config.js +55 -0
  207. package/dist/unreal/types.d.ts +105 -0
  208. package/dist/unreal/types.js +1 -0
  209. package/hooks/claude/gitnexus-hook.cjs +238 -0
  210. package/hooks/claude/pre-tool-use.sh +79 -0
  211. package/hooks/claude/session-start.sh +42 -0
  212. package/package.json +100 -0
  213. package/scripts/ensure-cli-executable.cjs +21 -0
  214. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  215. package/scripts/setup-unreal-gitnexus.ps1 +191 -0
  216. package/skills/gitnexus-cli.md +82 -0
  217. package/skills/gitnexus-debugging.md +89 -0
  218. package/skills/gitnexus-exploring.md +78 -0
  219. package/skills/gitnexus-guide.md +64 -0
  220. package/skills/gitnexus-impact-analysis.md +97 -0
  221. package/skills/gitnexus-pr-review.md +163 -0
  222. package/skills/gitnexus-refactoring.md +121 -0
  223. package/vendor/leiden/index.cjs +355 -0
  224. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Go package import resolution.
3
+ * Handles Go module path-based package imports.
4
+ */
5
+ /**
6
+ * Extract the package directory suffix from a Go import path.
7
+ * Returns the suffix string (e.g., "/internal/auth/") or null if invalid.
8
+ */
9
+ export function resolveGoPackageDir(importPath, goModule) {
10
+ if (!importPath.startsWith(goModule.modulePath))
11
+ return null;
12
+ const relativePkg = importPath.slice(goModule.modulePath.length + 1);
13
+ if (!relativePkg)
14
+ return null;
15
+ return '/' + relativePkg + '/';
16
+ }
17
+ /**
18
+ * Resolve a Go internal package import to all .go files in the package directory.
19
+ * Returns an array of file paths.
20
+ */
21
+ export function resolveGoPackage(importPath, goModule, normalizedFileList, allFileList) {
22
+ if (!importPath.startsWith(goModule.modulePath))
23
+ return [];
24
+ // Strip module path to get relative package path
25
+ const relativePkg = importPath.slice(goModule.modulePath.length + 1); // e.g., "internal/auth"
26
+ if (!relativePkg)
27
+ return [];
28
+ const pkgSuffix = '/' + relativePkg + '/';
29
+ const matches = [];
30
+ for (let i = 0; i < normalizedFileList.length; i++) {
31
+ // Prepend '/' so paths like "internal/auth/service.go" match suffix "/internal/auth/"
32
+ const normalized = '/' + normalizedFileList[i];
33
+ // File must be directly in the package directory (not a subdirectory)
34
+ if (normalized.includes(pkgSuffix) && normalized.endsWith('.go') && !normalized.endsWith('_test.go')) {
35
+ const afterPkg = normalized.substring(normalized.indexOf(pkgSuffix) + pkgSuffix.length);
36
+ if (!afterPkg.includes('/')) {
37
+ matches.push(allFileList[i]);
38
+ }
39
+ }
40
+ }
41
+ return matches;
42
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Language-specific import resolvers.
3
+ * Extracted from import-processor.ts for maintainability.
4
+ */
5
+ export { EXTENSIONS, tryResolveWithExtensions, buildSuffixIndex, suffixResolve } from './utils.js';
6
+ export type { SuffixIndex } from './utils.js';
7
+ export { KOTLIN_EXTENSIONS, appendKotlinWildcard, resolveJvmWildcard, resolveJvmMemberImport } from './jvm.js';
8
+ export { resolveGoPackageDir, resolveGoPackage } from './go.js';
9
+ export type { GoModuleConfig } from './go.js';
10
+ export { resolveCSharpImport, resolveCSharpNamespaceDir } from './csharp.js';
11
+ export type { CSharpProjectConfig } from './csharp.js';
12
+ export { resolvePhpImport } from './php.js';
13
+ export type { ComposerConfig } from './php.js';
14
+ export { resolveRustImport, tryRustModulePath } from './rust.js';
15
+ export { resolveRubyImport } from './ruby.js';
16
+ export { resolvePythonImport } from './python.js';
17
+ export { resolveImportPath, RESOLVE_CACHE_CAP } from './standard.js';
18
+ export type { TsconfigPaths } from './standard.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Language-specific import resolvers.
3
+ * Extracted from import-processor.ts for maintainability.
4
+ */
5
+ export { EXTENSIONS, tryResolveWithExtensions, buildSuffixIndex, suffixResolve } from './utils.js';
6
+ export { KOTLIN_EXTENSIONS, appendKotlinWildcard, resolveJvmWildcard, resolveJvmMemberImport } from './jvm.js';
7
+ export { resolveGoPackageDir, resolveGoPackage } from './go.js';
8
+ export { resolveCSharpImport, resolveCSharpNamespaceDir } from './csharp.js';
9
+ export { resolvePhpImport } from './php.js';
10
+ export { resolveRustImport, tryRustModulePath } from './rust.js';
11
+ export { resolveRubyImport } from './ruby.js';
12
+ export { resolvePythonImport } from './python.js';
13
+ export { resolveImportPath, RESOLVE_CACHE_CAP } from './standard.js';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * JVM import resolution (Java + Kotlin).
3
+ * Handles wildcard imports, member/static imports, and Kotlin-specific patterns.
4
+ */
5
+ import type { SuffixIndex } from './utils.js';
6
+ /** Kotlin file extensions for JVM resolver reuse */
7
+ export declare const KOTLIN_EXTENSIONS: readonly string[];
8
+ /**
9
+ * Append .* to a Kotlin import path if the AST has a wildcard_import sibling node.
10
+ * Pure function — returns a new string without mutating the input.
11
+ */
12
+ export declare const appendKotlinWildcard: (importPath: string, importNode: any) => string;
13
+ /**
14
+ * Resolve a JVM wildcard import (com.example.*) to all matching files.
15
+ * Works for both Java (.java) and Kotlin (.kt, .kts).
16
+ */
17
+ export declare function resolveJvmWildcard(importPath: string, normalizedFileList: string[], allFileList: string[], extensions: readonly string[], index?: SuffixIndex): string[];
18
+ /**
19
+ * Try to resolve a JVM member/static import by stripping the member name.
20
+ * Java: "com.example.Constants.VALUE" -> resolve "com.example.Constants"
21
+ * Kotlin: "com.example.Constants.VALUE" -> resolve "com.example.Constants"
22
+ */
23
+ export declare function resolveJvmMemberImport(importPath: string, normalizedFileList: string[], allFileList: string[], extensions: readonly string[], index?: SuffixIndex): string | null;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * JVM import resolution (Java + Kotlin).
3
+ * Handles wildcard imports, member/static imports, and Kotlin-specific patterns.
4
+ */
5
+ /** Kotlin file extensions for JVM resolver reuse */
6
+ export const KOTLIN_EXTENSIONS = ['.kt', '.kts'];
7
+ /**
8
+ * Append .* to a Kotlin import path if the AST has a wildcard_import sibling node.
9
+ * Pure function — returns a new string without mutating the input.
10
+ */
11
+ export const appendKotlinWildcard = (importPath, importNode) => {
12
+ for (let i = 0; i < importNode.childCount; i++) {
13
+ if (importNode.child(i)?.type === 'wildcard_import') {
14
+ return importPath.endsWith('.*') ? importPath : `${importPath}.*`;
15
+ }
16
+ }
17
+ return importPath;
18
+ };
19
+ /**
20
+ * Resolve a JVM wildcard import (com.example.*) to all matching files.
21
+ * Works for both Java (.java) and Kotlin (.kt, .kts).
22
+ */
23
+ export function resolveJvmWildcard(importPath, normalizedFileList, allFileList, extensions, index) {
24
+ // "com.example.util.*" -> "com/example/util"
25
+ const packagePath = importPath.slice(0, -2).replace(/\./g, '/');
26
+ if (index) {
27
+ const candidates = extensions.flatMap(ext => index.getFilesInDir(packagePath, ext));
28
+ // Filter to only direct children (no subdirectories)
29
+ const packageSuffix = '/' + packagePath + '/';
30
+ return candidates.filter(f => {
31
+ const normalized = f.replace(/\\/g, '/');
32
+ const idx = normalized.indexOf(packageSuffix);
33
+ if (idx < 0)
34
+ return false;
35
+ const afterPkg = normalized.substring(idx + packageSuffix.length);
36
+ return !afterPkg.includes('/');
37
+ });
38
+ }
39
+ // Fallback: linear scan
40
+ const packageSuffix = '/' + packagePath + '/';
41
+ const matches = [];
42
+ for (let i = 0; i < normalizedFileList.length; i++) {
43
+ const normalized = normalizedFileList[i];
44
+ if (normalized.includes(packageSuffix) &&
45
+ extensions.some(ext => normalized.endsWith(ext))) {
46
+ const afterPackage = normalized.substring(normalized.indexOf(packageSuffix) + packageSuffix.length);
47
+ if (!afterPackage.includes('/')) {
48
+ matches.push(allFileList[i]);
49
+ }
50
+ }
51
+ }
52
+ return matches;
53
+ }
54
+ /**
55
+ * Try to resolve a JVM member/static import by stripping the member name.
56
+ * Java: "com.example.Constants.VALUE" -> resolve "com.example.Constants"
57
+ * Kotlin: "com.example.Constants.VALUE" -> resolve "com.example.Constants"
58
+ */
59
+ export function resolveJvmMemberImport(importPath, normalizedFileList, allFileList, extensions, index) {
60
+ // Member imports: com.example.Constants.VALUE or com.example.Constants.*
61
+ // The last segment is a member name if it starts with lowercase, is ALL_CAPS, or is a wildcard
62
+ const segments = importPath.split('.');
63
+ if (segments.length < 3)
64
+ return null;
65
+ const lastSeg = segments[segments.length - 1];
66
+ if (lastSeg === '*' || /^[a-z]/.test(lastSeg) || /^[A-Z_]+$/.test(lastSeg)) {
67
+ const classPath = segments.slice(0, -1).join('/');
68
+ for (const ext of extensions) {
69
+ const classSuffix = classPath + ext;
70
+ if (index) {
71
+ const result = index.get(classSuffix) || index.getInsensitive(classSuffix);
72
+ if (result)
73
+ return result;
74
+ }
75
+ else {
76
+ const fullSuffix = '/' + classSuffix;
77
+ for (let i = 0; i < normalizedFileList.length; i++) {
78
+ if (normalizedFileList[i].endsWith(fullSuffix) ||
79
+ normalizedFileList[i].toLowerCase().endsWith(fullSuffix.toLowerCase())) {
80
+ return allFileList[i];
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ return null;
87
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * PHP PSR-4 import resolution.
3
+ * Handles use-statement resolution via composer.json autoload mappings.
4
+ */
5
+ import type { SuffixIndex } from './utils.js';
6
+ /** PHP Composer PSR-4 autoload config */
7
+ export interface ComposerConfig {
8
+ /** Map of namespace prefix -> directory (e.g., "App\\" -> "app/") */
9
+ psr4: Map<string, string>;
10
+ }
11
+ /**
12
+ * Resolve a PHP use-statement import path using PSR-4 mappings.
13
+ * e.g. "App\Http\Controllers\UserController" -> "app/Http/Controllers/UserController.php"
14
+ */
15
+ export declare function resolvePhpImport(importPath: string, composerConfig: ComposerConfig | null, allFiles: Set<string>, normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * PHP PSR-4 import resolution.
3
+ * Handles use-statement resolution via composer.json autoload mappings.
4
+ */
5
+ import { suffixResolve } from './utils.js';
6
+ /**
7
+ * Resolve a PHP use-statement import path using PSR-4 mappings.
8
+ * e.g. "App\Http\Controllers\UserController" -> "app/Http/Controllers/UserController.php"
9
+ */
10
+ export function resolvePhpImport(importPath, composerConfig, allFiles, normalizedFileList, allFileList, index) {
11
+ // Normalize: replace backslashes with forward slashes
12
+ const normalized = importPath.replace(/\\/g, '/');
13
+ // Try PSR-4 resolution if composer.json was found
14
+ if (composerConfig) {
15
+ // Sort namespaces by length descending (longest match wins)
16
+ const sorted = [...composerConfig.psr4.entries()].sort((a, b) => b[0].length - a[0].length);
17
+ for (const [nsPrefix, dirPrefix] of sorted) {
18
+ const nsPrefixSlash = nsPrefix.replace(/\\/g, '/');
19
+ if (normalized.startsWith(nsPrefixSlash + '/') || normalized === nsPrefixSlash) {
20
+ const remainder = normalized.slice(nsPrefixSlash.length).replace(/^\//, '');
21
+ const filePath = dirPrefix + (remainder ? '/' + remainder : '') + '.php';
22
+ if (allFiles.has(filePath))
23
+ return filePath;
24
+ if (index) {
25
+ const result = index.getInsensitive(filePath);
26
+ if (result)
27
+ return result;
28
+ }
29
+ }
30
+ }
31
+ }
32
+ // Fallback: suffix matching (works without composer.json)
33
+ const pathParts = normalized.split('/').filter(Boolean);
34
+ return suffixResolve(pathParts, normalizedFileList, allFileList, index);
35
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Python import resolution — PEP 328 relative imports and proximity-based bare imports.
3
+ * Import system spec: PEP 302 (original), PEP 451 (current).
4
+ */
5
+ /**
6
+ * Resolve a Python import to a file path.
7
+ *
8
+ * 1. Relative (PEP 328): `.module`, `..module` — 1 dot = current package, each extra dot goes up one level.
9
+ * 2. Proximity bare import: static heuristic — checks the importer's own directory first.
10
+ * Approximates the common case where co-located files find each other without an installed package.
11
+ * Single-segment only — multi-segment (e.g. `os.path`) falls through to suffixResolve.
12
+ * Checks package (__init__.py) before module (.py), matching CPython's finder order (PEP 451 §4).
13
+ * Coexistence of both is physically impossible (same name = file vs directory), so the order
14
+ * only matters for spec compliance.
15
+ * Note: namespace packages (PEP 420, directory without __init__.py) are not handled.
16
+ *
17
+ * Returns null to let the caller fall through to suffixResolve.
18
+ */
19
+ export declare function resolvePythonImport(currentFile: string, importPath: string, allFiles: Set<string>): string | null;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Python import resolution — PEP 328 relative imports and proximity-based bare imports.
3
+ * Import system spec: PEP 302 (original), PEP 451 (current).
4
+ */
5
+ import { tryResolveWithExtensions } from './utils.js';
6
+ /**
7
+ * Resolve a Python import to a file path.
8
+ *
9
+ * 1. Relative (PEP 328): `.module`, `..module` — 1 dot = current package, each extra dot goes up one level.
10
+ * 2. Proximity bare import: static heuristic — checks the importer's own directory first.
11
+ * Approximates the common case where co-located files find each other without an installed package.
12
+ * Single-segment only — multi-segment (e.g. `os.path`) falls through to suffixResolve.
13
+ * Checks package (__init__.py) before module (.py), matching CPython's finder order (PEP 451 §4).
14
+ * Coexistence of both is physically impossible (same name = file vs directory), so the order
15
+ * only matters for spec compliance.
16
+ * Note: namespace packages (PEP 420, directory without __init__.py) are not handled.
17
+ *
18
+ * Returns null to let the caller fall through to suffixResolve.
19
+ */
20
+ export function resolvePythonImport(currentFile, importPath, allFiles) {
21
+ // Relative import — PEP 328 (https://peps.python.org/pep-0328/)
22
+ if (importPath.startsWith('.')) {
23
+ const dotMatch = importPath.match(/^(\.+)(.*)/);
24
+ if (!dotMatch)
25
+ return null;
26
+ const dotCount = dotMatch[1].length;
27
+ const modulePart = dotMatch[2];
28
+ const dirParts = currentFile.split('/').slice(0, -1);
29
+ // PEP 328: more dots than directory levels → beyond top-level package → invalid
30
+ if (dotCount - 1 > dirParts.length)
31
+ return null;
32
+ for (let i = 1; i < dotCount; i++)
33
+ dirParts.pop();
34
+ if (modulePart) {
35
+ dirParts.push(...modulePart.replace(/\./g, '/').split('/'));
36
+ }
37
+ return tryResolveWithExtensions(dirParts.join('/'), allFiles);
38
+ }
39
+ // Proximity bare import — single-segment only; package before module (PEP 451 §4)
40
+ const pathLike = importPath.replace(/\./g, '/');
41
+ if (pathLike.includes('/'))
42
+ return null;
43
+ // Normalize for Windows backslashes
44
+ const importerDir = currentFile.replace(/\\/g, '/').split('/').slice(0, -1).join('/');
45
+ if (!importerDir)
46
+ return null;
47
+ if (allFiles.has(`${importerDir}/${pathLike}/__init__.py`))
48
+ return `${importerDir}/${pathLike}/__init__.py`;
49
+ if (allFiles.has(`${importerDir}/${pathLike}.py`))
50
+ return `${importerDir}/${pathLike}.py`;
51
+ return null;
52
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Ruby require/require_relative import resolution.
3
+ * Handles path resolution for Ruby's require and require_relative calls.
4
+ */
5
+ import type { SuffixIndex } from './utils.js';
6
+ /**
7
+ * Resolve a Ruby require/require_relative path to a matching .rb file.
8
+ *
9
+ * require_relative paths are pre-normalized to './' prefix by the caller.
10
+ * require paths use suffix matching (gem-style paths like 'json', 'net/http').
11
+ */
12
+ export declare function resolveRubyImport(importPath: string, normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Ruby require/require_relative import resolution.
3
+ * Handles path resolution for Ruby's require and require_relative calls.
4
+ */
5
+ import { suffixResolve } from './utils.js';
6
+ /**
7
+ * Resolve a Ruby require/require_relative path to a matching .rb file.
8
+ *
9
+ * require_relative paths are pre-normalized to './' prefix by the caller.
10
+ * require paths use suffix matching (gem-style paths like 'json', 'net/http').
11
+ */
12
+ export function resolveRubyImport(importPath, normalizedFileList, allFileList, index) {
13
+ const pathParts = importPath.replace(/^\.\//, '').split('/').filter(Boolean);
14
+ return suffixResolve(pathParts, normalizedFileList, allFileList, index);
15
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Rust module import resolution.
3
+ * Handles crate::, super::, self:: prefix paths and :: separators.
4
+ */
5
+ /**
6
+ * Resolve Rust use-path to a file.
7
+ * Handles crate::, super::, self:: prefixes and :: path separators.
8
+ */
9
+ export declare function resolveRustImport(currentFile: string, importPath: string, allFiles: Set<string>): string | null;
10
+ /**
11
+ * Try to resolve a Rust module path to a file.
12
+ * Tries: path.rs, path/mod.rs, and with the last segment stripped
13
+ * (last segment might be a symbol name, not a module).
14
+ */
15
+ export declare function tryRustModulePath(modulePath: string, allFiles: Set<string>): string | null;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Rust module import resolution.
3
+ * Handles crate::, super::, self:: prefix paths and :: separators.
4
+ */
5
+ /**
6
+ * Resolve Rust use-path to a file.
7
+ * Handles crate::, super::, self:: prefixes and :: path separators.
8
+ */
9
+ export function resolveRustImport(currentFile, importPath, allFiles) {
10
+ let rustPath;
11
+ if (importPath.startsWith('crate::')) {
12
+ // crate:: resolves from src/ directory (standard Rust layout)
13
+ rustPath = importPath.slice(7).replace(/::/g, '/');
14
+ // Try from src/ (standard layout)
15
+ const fromSrc = tryRustModulePath('src/' + rustPath, allFiles);
16
+ if (fromSrc)
17
+ return fromSrc;
18
+ // Try from repo root (non-standard)
19
+ const fromRoot = tryRustModulePath(rustPath, allFiles);
20
+ if (fromRoot)
21
+ return fromRoot;
22
+ return null;
23
+ }
24
+ if (importPath.startsWith('super::')) {
25
+ // super:: = parent directory of current file's module
26
+ const currentDir = currentFile.split('/').slice(0, -1);
27
+ currentDir.pop(); // Go up one level for super::
28
+ rustPath = importPath.slice(7).replace(/::/g, '/');
29
+ const fullPath = [...currentDir, rustPath].join('/');
30
+ return tryRustModulePath(fullPath, allFiles);
31
+ }
32
+ if (importPath.startsWith('self::')) {
33
+ // self:: = current module's directory
34
+ const currentDir = currentFile.split('/').slice(0, -1);
35
+ rustPath = importPath.slice(6).replace(/::/g, '/');
36
+ const fullPath = [...currentDir, rustPath].join('/');
37
+ return tryRustModulePath(fullPath, allFiles);
38
+ }
39
+ // Bare path without prefix (e.g., from a use in a nested module)
40
+ // Convert :: to / and try suffix matching
41
+ if (importPath.includes('::')) {
42
+ rustPath = importPath.replace(/::/g, '/');
43
+ return tryRustModulePath(rustPath, allFiles);
44
+ }
45
+ return null;
46
+ }
47
+ /**
48
+ * Try to resolve a Rust module path to a file.
49
+ * Tries: path.rs, path/mod.rs, and with the last segment stripped
50
+ * (last segment might be a symbol name, not a module).
51
+ */
52
+ export function tryRustModulePath(modulePath, allFiles) {
53
+ // Try direct: path.rs
54
+ if (allFiles.has(modulePath + '.rs'))
55
+ return modulePath + '.rs';
56
+ // Try directory: path/mod.rs
57
+ if (allFiles.has(modulePath + '/mod.rs'))
58
+ return modulePath + '/mod.rs';
59
+ // Try path/lib.rs (for crate root)
60
+ if (allFiles.has(modulePath + '/lib.rs'))
61
+ return modulePath + '/lib.rs';
62
+ // The last segment might be a symbol (function, struct, etc.), not a module.
63
+ // Strip it and try again.
64
+ const lastSlash = modulePath.lastIndexOf('/');
65
+ if (lastSlash > 0) {
66
+ const parentPath = modulePath.substring(0, lastSlash);
67
+ if (allFiles.has(parentPath + '.rs'))
68
+ return parentPath + '.rs';
69
+ if (allFiles.has(parentPath + '/mod.rs'))
70
+ return parentPath + '/mod.rs';
71
+ }
72
+ return null;
73
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Standard import path resolution.
3
+ * Handles relative imports, path alias rewriting, and generic suffix matching.
4
+ * Used as the fallback when language-specific resolvers don't match.
5
+ */
6
+ import type { SuffixIndex } from './utils.js';
7
+ import { SupportedLanguages } from '../../../config/supported-languages.js';
8
+ /** TypeScript path alias config parsed from tsconfig.json */
9
+ export interface TsconfigPaths {
10
+ /** Map of alias prefix -> target prefix (e.g., "@/" -> "src/") */
11
+ aliases: Map<string, string>;
12
+ /** Base URL for path resolution (relative to repo root) */
13
+ baseUrl: string;
14
+ }
15
+ /** Max entries in the resolve cache. Beyond this, entries are evicted.
16
+ * 100K entries ≈ 15MB — covers the most common import patterns. */
17
+ export declare const RESOLVE_CACHE_CAP = 100000;
18
+ /**
19
+ * Resolve an import path to a file path in the repository.
20
+ *
21
+ * Language-specific preprocessing is applied before the generic resolution:
22
+ * - TypeScript/JavaScript: rewrites tsconfig path aliases
23
+ * - Rust: converts crate::/super::/self:: to relative paths
24
+ *
25
+ * Java wildcards and Go package imports are handled separately in processImports
26
+ * because they resolve to multiple files.
27
+ */
28
+ export declare const resolveImportPath: (currentFile: string, importPath: string, allFiles: Set<string>, allFileList: string[], normalizedFileList: string[], resolveCache: Map<string, string | null>, language: SupportedLanguages, tsconfigPaths: TsconfigPaths | null, index?: SuffixIndex) => string | null;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Standard import path resolution.
3
+ * Handles relative imports, path alias rewriting, and generic suffix matching.
4
+ * Used as the fallback when language-specific resolvers don't match.
5
+ */
6
+ import { tryResolveWithExtensions, suffixResolve } from './utils.js';
7
+ import { resolveRustImport } from './rust.js';
8
+ import { SupportedLanguages } from '../../../config/supported-languages.js';
9
+ /** Max entries in the resolve cache. Beyond this, entries are evicted.
10
+ * 100K entries ≈ 15MB — covers the most common import patterns. */
11
+ export const RESOLVE_CACHE_CAP = 100_000;
12
+ /**
13
+ * Resolve an import path to a file path in the repository.
14
+ *
15
+ * Language-specific preprocessing is applied before the generic resolution:
16
+ * - TypeScript/JavaScript: rewrites tsconfig path aliases
17
+ * - Rust: converts crate::/super::/self:: to relative paths
18
+ *
19
+ * Java wildcards and Go package imports are handled separately in processImports
20
+ * because they resolve to multiple files.
21
+ */
22
+ export const resolveImportPath = (currentFile, importPath, allFiles, allFileList, normalizedFileList, resolveCache, language, tsconfigPaths, index) => {
23
+ const cacheKey = `${currentFile}::${importPath}`;
24
+ if (resolveCache.has(cacheKey))
25
+ return resolveCache.get(cacheKey) ?? null;
26
+ const cache = (result) => {
27
+ // Evict oldest 20% when cap is reached instead of clearing all
28
+ if (resolveCache.size >= RESOLVE_CACHE_CAP) {
29
+ const evictCount = Math.floor(RESOLVE_CACHE_CAP * 0.2);
30
+ const iter = resolveCache.keys();
31
+ for (let i = 0; i < evictCount; i++) {
32
+ const key = iter.next().value;
33
+ if (key !== undefined)
34
+ resolveCache.delete(key);
35
+ }
36
+ }
37
+ resolveCache.set(cacheKey, result);
38
+ return result;
39
+ };
40
+ // ---- TypeScript/JavaScript: rewrite path aliases ----
41
+ if ((language === SupportedLanguages.TypeScript || language === SupportedLanguages.JavaScript) &&
42
+ tsconfigPaths &&
43
+ !importPath.startsWith('.')) {
44
+ for (const [aliasPrefix, targetPrefix] of tsconfigPaths.aliases) {
45
+ if (importPath.startsWith(aliasPrefix)) {
46
+ const remainder = importPath.slice(aliasPrefix.length);
47
+ // Build the rewritten path relative to baseUrl
48
+ const rewritten = tsconfigPaths.baseUrl === '.'
49
+ ? targetPrefix + remainder
50
+ : tsconfigPaths.baseUrl + '/' + targetPrefix + remainder;
51
+ // Try direct resolution from repo root
52
+ const resolved = tryResolveWithExtensions(rewritten, allFiles);
53
+ if (resolved)
54
+ return cache(resolved);
55
+ // Try suffix matching as fallback
56
+ const parts = rewritten.split('/').filter(Boolean);
57
+ const suffixResult = suffixResolve(parts, normalizedFileList, allFileList, index);
58
+ if (suffixResult)
59
+ return cache(suffixResult);
60
+ }
61
+ }
62
+ }
63
+ // ---- Rust: convert module path syntax to file paths ----
64
+ if (language === SupportedLanguages.Rust) {
65
+ // Handle grouped imports: use crate::module::{Foo, Bar, Baz}
66
+ // Extract the prefix path before ::{...} and resolve the module, not the symbols
67
+ let rustImportPath = importPath;
68
+ const braceIdx = importPath.indexOf('::{');
69
+ if (braceIdx !== -1) {
70
+ rustImportPath = importPath.substring(0, braceIdx);
71
+ }
72
+ else if (importPath.startsWith('{') && importPath.endsWith('}')) {
73
+ // Top-level grouped imports: use {crate::a, crate::b}
74
+ // Iterate each part and return the first that resolves. This function returns a single
75
+ // string, so callers that need ALL edges must intercept before reaching here (see the
76
+ // Rust grouped-import blocks in processImports / processImportsBatch). This fallback
77
+ // handles any path that reaches resolveImportPath directly.
78
+ const inner = importPath.slice(1, -1);
79
+ const parts = inner.split(',').map(p => p.trim()).filter(Boolean);
80
+ for (const part of parts) {
81
+ const partResult = resolveRustImport(currentFile, part, allFiles);
82
+ if (partResult)
83
+ return cache(partResult);
84
+ }
85
+ return cache(null);
86
+ }
87
+ const rustResult = resolveRustImport(currentFile, rustImportPath, allFiles);
88
+ if (rustResult)
89
+ return cache(rustResult);
90
+ // Fall through to generic resolution if Rust-specific didn't match
91
+ }
92
+ // ---- Generic relative import resolution (./ and ../) ----
93
+ const currentDir = currentFile.split('/').slice(0, -1);
94
+ const parts = importPath.split('/');
95
+ for (const part of parts) {
96
+ if (part === '.')
97
+ continue;
98
+ if (part === '..') {
99
+ currentDir.pop();
100
+ }
101
+ else {
102
+ currentDir.push(part);
103
+ }
104
+ }
105
+ const basePath = currentDir.join('/');
106
+ if (importPath.startsWith('.')) {
107
+ const resolved = tryResolveWithExtensions(basePath, allFiles);
108
+ return cache(resolved);
109
+ }
110
+ // ---- Generic package/absolute import resolution (suffix matching) ----
111
+ // Java wildcards are handled in processImports, not here
112
+ if (importPath.endsWith('.*')) {
113
+ return cache(null);
114
+ }
115
+ // C/C++ includes use actual file paths (e.g. "animal.h") — don't convert dots to slashes
116
+ const isCpp = language === SupportedLanguages.C || language === SupportedLanguages.CPlusPlus;
117
+ const pathLike = importPath.includes('/') || isCpp
118
+ ? importPath
119
+ : importPath.replace(/\./g, '/');
120
+ const pathParts = pathLike.split('/').filter(Boolean);
121
+ const resolved = suffixResolve(pathParts, normalizedFileList, allFileList, index);
122
+ return cache(resolved);
123
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Shared utilities for import resolution.
3
+ * Extracted from import-processor.ts to reduce file size.
4
+ */
5
+ /** All file extensions to try during resolution */
6
+ export declare const EXTENSIONS: string[];
7
+ /**
8
+ * Try to match a path (with extensions) against the known file set.
9
+ * Returns the matched file path or null.
10
+ */
11
+ export declare function tryResolveWithExtensions(basePath: string, allFiles: Set<string>): string | null;
12
+ /**
13
+ * Build a suffix index for O(1) endsWith lookups.
14
+ * Maps every possible path suffix to its original file path.
15
+ * e.g. for "src/com/example/Foo.java":
16
+ * "Foo.java" -> "src/com/example/Foo.java"
17
+ * "example/Foo.java" -> "src/com/example/Foo.java"
18
+ * "com/example/Foo.java" -> "src/com/example/Foo.java"
19
+ * etc.
20
+ */
21
+ export interface SuffixIndex {
22
+ /** Exact suffix lookup (case-sensitive) */
23
+ get(suffix: string): string | undefined;
24
+ /** Case-insensitive suffix lookup */
25
+ getInsensitive(suffix: string): string | undefined;
26
+ /** Get all files in a directory suffix */
27
+ getFilesInDir(dirSuffix: string, extension: string): string[];
28
+ }
29
+ export declare function buildSuffixIndex(normalizedFileList: string[], allFileList: string[]): SuffixIndex;
30
+ /**
31
+ * Suffix-based resolution using index. O(1) per lookup instead of O(files).
32
+ */
33
+ export declare function suffixResolve(pathParts: string[], normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;