@zuvia-software-solutions/code-mapper 1.4.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 (213) hide show
  1. package/README.md +215 -0
  2. package/dist/cli/ai-context.d.ts +19 -0
  3. package/dist/cli/ai-context.js +168 -0
  4. package/dist/cli/analyze.d.ts +7 -0
  5. package/dist/cli/analyze.js +325 -0
  6. package/dist/cli/augment.d.ts +7 -0
  7. package/dist/cli/augment.js +27 -0
  8. package/dist/cli/clean.d.ts +5 -0
  9. package/dist/cli/clean.js +56 -0
  10. package/dist/cli/eval-server.d.ts +25 -0
  11. package/dist/cli/eval-server.js +365 -0
  12. package/dist/cli/index.d.ts +6 -0
  13. package/dist/cli/index.js +102 -0
  14. package/dist/cli/lazy-action.d.ts +6 -0
  15. package/dist/cli/lazy-action.js +19 -0
  16. package/dist/cli/list.d.ts +2 -0
  17. package/dist/cli/list.js +27 -0
  18. package/dist/cli/mcp.d.ts +8 -0
  19. package/dist/cli/mcp.js +35 -0
  20. package/dist/cli/refresh.d.ts +12 -0
  21. package/dist/cli/refresh.js +165 -0
  22. package/dist/cli/serve.d.ts +5 -0
  23. package/dist/cli/serve.js +8 -0
  24. package/dist/cli/setup.d.ts +6 -0
  25. package/dist/cli/setup.js +218 -0
  26. package/dist/cli/status.d.ts +2 -0
  27. package/dist/cli/status.js +33 -0
  28. package/dist/cli/tool.d.ts +28 -0
  29. package/dist/cli/tool.js +87 -0
  30. package/dist/config/ignore-service.d.ts +32 -0
  31. package/dist/config/ignore-service.js +282 -0
  32. package/dist/config/supported-languages.d.ts +23 -0
  33. package/dist/config/supported-languages.js +52 -0
  34. package/dist/core/augmentation/engine.d.ts +22 -0
  35. package/dist/core/augmentation/engine.js +232 -0
  36. package/dist/core/embeddings/embedder.d.ts +35 -0
  37. package/dist/core/embeddings/embedder.js +171 -0
  38. package/dist/core/embeddings/embedding-pipeline.d.ts +41 -0
  39. package/dist/core/embeddings/embedding-pipeline.js +402 -0
  40. package/dist/core/embeddings/index.d.ts +5 -0
  41. package/dist/core/embeddings/index.js +6 -0
  42. package/dist/core/embeddings/text-generator.d.ts +20 -0
  43. package/dist/core/embeddings/text-generator.js +159 -0
  44. package/dist/core/embeddings/types.d.ts +60 -0
  45. package/dist/core/embeddings/types.js +23 -0
  46. package/dist/core/graph/graph.d.ts +4 -0
  47. package/dist/core/graph/graph.js +65 -0
  48. package/dist/core/graph/types.d.ts +69 -0
  49. package/dist/core/graph/types.js +3 -0
  50. package/dist/core/incremental/child-process.d.ts +8 -0
  51. package/dist/core/incremental/child-process.js +649 -0
  52. package/dist/core/incremental/refresh-coordinator.d.ts +32 -0
  53. package/dist/core/incremental/refresh-coordinator.js +147 -0
  54. package/dist/core/incremental/types.d.ts +78 -0
  55. package/dist/core/incremental/types.js +153 -0
  56. package/dist/core/incremental/watcher.d.ts +63 -0
  57. package/dist/core/incremental/watcher.js +338 -0
  58. package/dist/core/ingestion/ast-cache.d.ts +12 -0
  59. package/dist/core/ingestion/ast-cache.js +34 -0
  60. package/dist/core/ingestion/call-processor.d.ts +34 -0
  61. package/dist/core/ingestion/call-processor.js +937 -0
  62. package/dist/core/ingestion/call-routing.d.ts +40 -0
  63. package/dist/core/ingestion/call-routing.js +97 -0
  64. package/dist/core/ingestion/cluster-enricher.d.ts +30 -0
  65. package/dist/core/ingestion/cluster-enricher.js +151 -0
  66. package/dist/core/ingestion/community-processor.d.ts +26 -0
  67. package/dist/core/ingestion/community-processor.js +272 -0
  68. package/dist/core/ingestion/constants.d.ts +5 -0
  69. package/dist/core/ingestion/constants.js +8 -0
  70. package/dist/core/ingestion/entry-point-scoring.d.ts +23 -0
  71. package/dist/core/ingestion/entry-point-scoring.js +317 -0
  72. package/dist/core/ingestion/export-detection.d.ts +11 -0
  73. package/dist/core/ingestion/export-detection.js +203 -0
  74. package/dist/core/ingestion/filesystem-walker.d.ts +18 -0
  75. package/dist/core/ingestion/filesystem-walker.js +64 -0
  76. package/dist/core/ingestion/framework-detection.d.ts +42 -0
  77. package/dist/core/ingestion/framework-detection.js +405 -0
  78. package/dist/core/ingestion/heritage-processor.d.ts +15 -0
  79. package/dist/core/ingestion/heritage-processor.js +237 -0
  80. package/dist/core/ingestion/import-processor.d.ts +31 -0
  81. package/dist/core/ingestion/import-processor.js +416 -0
  82. package/dist/core/ingestion/language-config.d.ts +32 -0
  83. package/dist/core/ingestion/language-config.js +161 -0
  84. package/dist/core/ingestion/mro-processor.d.ts +32 -0
  85. package/dist/core/ingestion/mro-processor.js +343 -0
  86. package/dist/core/ingestion/named-binding-extraction.d.ts +51 -0
  87. package/dist/core/ingestion/named-binding-extraction.js +343 -0
  88. package/dist/core/ingestion/parsing-processor.d.ts +20 -0
  89. package/dist/core/ingestion/parsing-processor.js +282 -0
  90. package/dist/core/ingestion/pipeline.d.ts +3 -0
  91. package/dist/core/ingestion/pipeline.js +416 -0
  92. package/dist/core/ingestion/process-processor.d.ts +42 -0
  93. package/dist/core/ingestion/process-processor.js +357 -0
  94. package/dist/core/ingestion/resolution-context.d.ts +40 -0
  95. package/dist/core/ingestion/resolution-context.js +171 -0
  96. package/dist/core/ingestion/resolvers/csharp.d.ts +10 -0
  97. package/dist/core/ingestion/resolvers/csharp.js +101 -0
  98. package/dist/core/ingestion/resolvers/go.d.ts +8 -0
  99. package/dist/core/ingestion/resolvers/go.js +33 -0
  100. package/dist/core/ingestion/resolvers/index.d.ts +14 -0
  101. package/dist/core/ingestion/resolvers/index.js +10 -0
  102. package/dist/core/ingestion/resolvers/jvm.d.ts +9 -0
  103. package/dist/core/ingestion/resolvers/jvm.js +74 -0
  104. package/dist/core/ingestion/resolvers/php.d.ts +7 -0
  105. package/dist/core/ingestion/resolvers/php.js +30 -0
  106. package/dist/core/ingestion/resolvers/ruby.d.ts +9 -0
  107. package/dist/core/ingestion/resolvers/ruby.js +13 -0
  108. package/dist/core/ingestion/resolvers/rust.d.ts +5 -0
  109. package/dist/core/ingestion/resolvers/rust.js +62 -0
  110. package/dist/core/ingestion/resolvers/standard.d.ts +16 -0
  111. package/dist/core/ingestion/resolvers/standard.js +144 -0
  112. package/dist/core/ingestion/resolvers/utils.d.ts +18 -0
  113. package/dist/core/ingestion/resolvers/utils.js +113 -0
  114. package/dist/core/ingestion/structure-processor.d.ts +4 -0
  115. package/dist/core/ingestion/structure-processor.js +39 -0
  116. package/dist/core/ingestion/symbol-table.d.ts +34 -0
  117. package/dist/core/ingestion/symbol-table.js +48 -0
  118. package/dist/core/ingestion/tree-sitter-queries.d.ts +20 -0
  119. package/dist/core/ingestion/tree-sitter-queries.js +691 -0
  120. package/dist/core/ingestion/type-env.d.ts +52 -0
  121. package/dist/core/ingestion/type-env.js +349 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +4 -0
  123. package/dist/core/ingestion/type-extractors/c-cpp.js +214 -0
  124. package/dist/core/ingestion/type-extractors/csharp.d.ts +4 -0
  125. package/dist/core/ingestion/type-extractors/csharp.js +224 -0
  126. package/dist/core/ingestion/type-extractors/go.d.ts +4 -0
  127. package/dist/core/ingestion/type-extractors/go.js +261 -0
  128. package/dist/core/ingestion/type-extractors/index.d.ts +20 -0
  129. package/dist/core/ingestion/type-extractors/index.js +30 -0
  130. package/dist/core/ingestion/type-extractors/jvm.d.ts +5 -0
  131. package/dist/core/ingestion/type-extractors/jvm.js +386 -0
  132. package/dist/core/ingestion/type-extractors/php.d.ts +4 -0
  133. package/dist/core/ingestion/type-extractors/php.js +280 -0
  134. package/dist/core/ingestion/type-extractors/python.d.ts +4 -0
  135. package/dist/core/ingestion/type-extractors/python.js +175 -0
  136. package/dist/core/ingestion/type-extractors/ruby.d.ts +12 -0
  137. package/dist/core/ingestion/type-extractors/ruby.js +218 -0
  138. package/dist/core/ingestion/type-extractors/rust.d.ts +4 -0
  139. package/dist/core/ingestion/type-extractors/rust.js +290 -0
  140. package/dist/core/ingestion/type-extractors/shared.d.ts +81 -0
  141. package/dist/core/ingestion/type-extractors/shared.js +322 -0
  142. package/dist/core/ingestion/type-extractors/swift.d.ts +4 -0
  143. package/dist/core/ingestion/type-extractors/swift.js +140 -0
  144. package/dist/core/ingestion/type-extractors/types.d.ts +111 -0
  145. package/dist/core/ingestion/type-extractors/types.js +4 -0
  146. package/dist/core/ingestion/type-extractors/typescript.d.ts +4 -0
  147. package/dist/core/ingestion/type-extractors/typescript.js +227 -0
  148. package/dist/core/ingestion/utils.d.ts +73 -0
  149. package/dist/core/ingestion/utils.js +992 -0
  150. package/dist/core/ingestion/workers/parse-worker.d.ts +99 -0
  151. package/dist/core/ingestion/workers/parse-worker.js +1055 -0
  152. package/dist/core/ingestion/workers/worker-pool.d.ts +15 -0
  153. package/dist/core/ingestion/workers/worker-pool.js +123 -0
  154. package/dist/core/lbug/csv-generator.d.ts +28 -0
  155. package/dist/core/lbug/csv-generator.js +355 -0
  156. package/dist/core/lbug/lbug-adapter.d.ts +96 -0
  157. package/dist/core/lbug/lbug-adapter.js +753 -0
  158. package/dist/core/lbug/schema.d.ts +46 -0
  159. package/dist/core/lbug/schema.js +402 -0
  160. package/dist/core/search/bm25-index.d.ts +20 -0
  161. package/dist/core/search/bm25-index.js +123 -0
  162. package/dist/core/search/hybrid-search.d.ts +32 -0
  163. package/dist/core/search/hybrid-search.js +131 -0
  164. package/dist/core/search/query-cache.d.ts +18 -0
  165. package/dist/core/search/query-cache.js +47 -0
  166. package/dist/core/search/query-expansion.d.ts +19 -0
  167. package/dist/core/search/query-expansion.js +75 -0
  168. package/dist/core/search/reranker.d.ts +29 -0
  169. package/dist/core/search/reranker.js +122 -0
  170. package/dist/core/search/types.d.ts +154 -0
  171. package/dist/core/search/types.js +51 -0
  172. package/dist/core/semantic/tsgo-service.d.ts +67 -0
  173. package/dist/core/semantic/tsgo-service.js +355 -0
  174. package/dist/core/tree-sitter/parser-loader.d.ts +12 -0
  175. package/dist/core/tree-sitter/parser-loader.js +71 -0
  176. package/dist/lib/memory-guard.d.ts +35 -0
  177. package/dist/lib/memory-guard.js +70 -0
  178. package/dist/lib/utils.d.ts +3 -0
  179. package/dist/lib/utils.js +6 -0
  180. package/dist/mcp/compatible-stdio-transport.d.ts +32 -0
  181. package/dist/mcp/compatible-stdio-transport.js +209 -0
  182. package/dist/mcp/core/embedder.d.ts +24 -0
  183. package/dist/mcp/core/embedder.js +168 -0
  184. package/dist/mcp/core/lbug-adapter.d.ts +29 -0
  185. package/dist/mcp/core/lbug-adapter.js +330 -0
  186. package/dist/mcp/local/local-backend.d.ts +188 -0
  187. package/dist/mcp/local/local-backend.js +2759 -0
  188. package/dist/mcp/resources.d.ts +22 -0
  189. package/dist/mcp/resources.js +379 -0
  190. package/dist/mcp/server.d.ts +10 -0
  191. package/dist/mcp/server.js +217 -0
  192. package/dist/mcp/staleness.d.ts +10 -0
  193. package/dist/mcp/staleness.js +25 -0
  194. package/dist/mcp/tools.d.ts +21 -0
  195. package/dist/mcp/tools.js +202 -0
  196. package/dist/server/api.d.ts +5 -0
  197. package/dist/server/api.js +340 -0
  198. package/dist/server/mcp-http.d.ts +7 -0
  199. package/dist/server/mcp-http.js +95 -0
  200. package/dist/storage/git.d.ts +6 -0
  201. package/dist/storage/git.js +35 -0
  202. package/dist/storage/repo-manager.d.ts +87 -0
  203. package/dist/storage/repo-manager.js +249 -0
  204. package/dist/types/pipeline.d.ts +35 -0
  205. package/dist/types/pipeline.js +20 -0
  206. package/hooks/claude/code-mapper-hook.cjs +238 -0
  207. package/hooks/claude/pre-tool-use.sh +79 -0
  208. package/hooks/claude/session-start.sh +42 -0
  209. package/models/mlx-embedder.py +185 -0
  210. package/package.json +100 -0
  211. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  212. package/vendor/leiden/index.cjs +355 -0
  213. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,282 @@
1
+ // code-mapper/src/config/ignore-service.ts
2
+ /** @file ignore-service.ts @description Hardcoded and user-configurable ignore rules for file/directory filtering during repo traversal */
3
+ import ignore from 'ignore';
4
+ import fs from 'fs/promises';
5
+ import nodePath from 'path';
6
+ const DEFAULT_IGNORE_LIST = new Set([
7
+ // Version control
8
+ '.git',
9
+ '.svn',
10
+ '.hg',
11
+ '.bzr',
12
+ // IDEs and editors
13
+ '.idea',
14
+ '.vscode',
15
+ '.vs',
16
+ '.eclipse',
17
+ '.settings',
18
+ '.DS_Store',
19
+ 'Thumbs.db',
20
+ // Dependencies
21
+ 'node_modules',
22
+ 'bower_components',
23
+ 'jspm_packages',
24
+ 'vendor', // PHP/Go
25
+ // 'packages' not ignored — commonly used for monorepo source code
26
+ 'venv',
27
+ '.venv',
28
+ 'env',
29
+ '.env',
30
+ '__pycache__',
31
+ '.pytest_cache',
32
+ '.mypy_cache',
33
+ 'site-packages',
34
+ '.tox',
35
+ 'eggs',
36
+ '.eggs',
37
+ 'lib64',
38
+ 'parts',
39
+ 'sdist',
40
+ 'wheels',
41
+ // Build outputs
42
+ 'dist',
43
+ 'build',
44
+ 'out',
45
+ 'output',
46
+ 'bin',
47
+ 'obj',
48
+ 'target', // Java, Rust
49
+ '.next',
50
+ '.nuxt',
51
+ '.output',
52
+ '.vercel',
53
+ '.netlify',
54
+ '.serverless',
55
+ '_build',
56
+ 'public/build',
57
+ '.parcel-cache',
58
+ '.turbo',
59
+ '.svelte-kit',
60
+ // Test and coverage
61
+ 'coverage',
62
+ '.nyc_output',
63
+ 'htmlcov',
64
+ '.coverage',
65
+ '__tests__',
66
+ '__mocks__',
67
+ '.jest',
68
+ // Logs and temp
69
+ 'logs',
70
+ 'log',
71
+ 'tmp',
72
+ 'temp',
73
+ 'cache',
74
+ '.cache',
75
+ '.tmp',
76
+ '.temp',
77
+ // Generated and compiled
78
+ '.generated',
79
+ 'generated',
80
+ 'auto-generated',
81
+ '.terraform',
82
+ '.serverless',
83
+ // Misc
84
+ '.husky',
85
+ '.github',
86
+ '.circleci',
87
+ '.gitlab',
88
+ 'fixtures',
89
+ 'snapshots',
90
+ '__snapshots__',
91
+ ]);
92
+ const IGNORED_EXTENSIONS = new Set([
93
+ // Images
94
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.webp', '.bmp', '.tiff', '.tif',
95
+ '.psd', '.ai', '.sketch', '.fig', '.xd',
96
+ // Archives
97
+ '.zip', '.tar', '.gz', '.rar', '.7z', '.bz2', '.xz', '.tgz',
98
+ // Binary and compiled
99
+ '.exe', '.dll', '.so', '.dylib', '.a', '.lib', '.o', '.obj',
100
+ '.class', '.jar', '.war', '.ear',
101
+ '.pyc', '.pyo', '.pyd',
102
+ '.beam',
103
+ '.wasm',
104
+ '.node',
105
+ // Documents
106
+ '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
107
+ '.odt', '.ods', '.odp',
108
+ // Media
109
+ '.mp4', '.mp3', '.wav', '.mov', '.avi', '.mkv', '.flv', '.wmv',
110
+ '.ogg', '.webm', '.flac', '.aac', '.m4a',
111
+ // Fonts
112
+ '.woff', '.woff2', '.ttf', '.eot', '.otf',
113
+ // Databases
114
+ '.db', '.sqlite', '.sqlite3', '.mdb', '.accdb',
115
+ // Minified and bundled
116
+ '.min.js', '.min.css', '.bundle.js', '.chunk.js',
117
+ // Source maps
118
+ '.map',
119
+ // Lock files
120
+ '.lock',
121
+ // Certificates and keys
122
+ '.pem', '.key', '.crt', '.cer', '.p12', '.pfx',
123
+ // Data files
124
+ '.csv', '.tsv', '.parquet', '.avro', '.feather',
125
+ '.npy', '.npz', '.pkl', '.pickle', '.h5', '.hdf5',
126
+ // Misc
127
+ '.bin', '.dat', '.data', '.raw',
128
+ '.iso', '.img', '.dmg',
129
+ ]);
130
+ // Exact filenames to ignore
131
+ const IGNORED_FILES = new Set([
132
+ 'package-lock.json',
133
+ 'yarn.lock',
134
+ 'pnpm-lock.yaml',
135
+ 'composer.lock',
136
+ 'Gemfile.lock',
137
+ 'poetry.lock',
138
+ 'Cargo.lock',
139
+ 'go.sum',
140
+ '.gitignore',
141
+ '.gitattributes',
142
+ '.npmrc',
143
+ '.yarnrc',
144
+ '.editorconfig',
145
+ '.prettierrc',
146
+ '.prettierignore',
147
+ '.eslintignore',
148
+ '.dockerignore',
149
+ 'Thumbs.db',
150
+ '.DS_Store',
151
+ 'LICENSE',
152
+ 'LICENSE.md',
153
+ 'LICENSE.txt',
154
+ 'CHANGELOG.md',
155
+ 'CHANGELOG',
156
+ 'CONTRIBUTING.md',
157
+ 'CODE_OF_CONDUCT.md',
158
+ 'SECURITY.md',
159
+ '.env',
160
+ '.env.local',
161
+ '.env.development',
162
+ '.env.production',
163
+ '.env.test',
164
+ '.env.example',
165
+ ]);
166
+ // NOTE: Negation patterns in .code-mapperignore (e.g. `!vendor/`) cannot override
167
+ // DEFAULT_IGNORE_LIST entries — hardcoded list protects against indexing dirs that
168
+ // are almost never source code. To include such dirs, remove them from the list
169
+ /**
170
+ * Check whether a file path should be ignored based on hardcoded rules
171
+ * @param filePath - Relative or absolute file path to check
172
+ * @returns true if the path matches any ignore rule
173
+ */
174
+ export const shouldIgnorePath = (filePath) => {
175
+ const normalizedPath = filePath.replace(/\\/g, '/');
176
+ const parts = normalizedPath.split('/');
177
+ const fileName = parts[parts.length - 1];
178
+ const fileNameLower = fileName.toLowerCase();
179
+ // Check if any path segment matches the ignore list
180
+ for (const part of parts) {
181
+ if (DEFAULT_IGNORE_LIST.has(part)) {
182
+ return true;
183
+ }
184
+ }
185
+ // Check exact filename
186
+ if (IGNORED_FILES.has(fileName) || IGNORED_FILES.has(fileNameLower)) {
187
+ return true;
188
+ }
189
+ // Check extension
190
+ const lastDotIndex = fileNameLower.lastIndexOf('.');
191
+ if (lastDotIndex !== -1) {
192
+ const ext = fileNameLower.substring(lastDotIndex);
193
+ if (IGNORED_EXTENSIONS.has(ext))
194
+ return true;
195
+ // Handle compound extensions (e.g. .min.js, .bundle.js)
196
+ const secondLastDot = fileNameLower.lastIndexOf('.', lastDotIndex - 1);
197
+ if (secondLastDot !== -1) {
198
+ const compoundExt = fileNameLower.substring(secondLastDot);
199
+ if (IGNORED_EXTENSIONS.has(compoundExt))
200
+ return true;
201
+ }
202
+ }
203
+ // TODO: dot-file filtering intentionally skipped — many are important configs
204
+ // Relies on explicit IGNORED_FILES list above instead
205
+ // Ignore generated/bundled code and TypeScript declaration files
206
+ if (fileNameLower.includes('.bundle.') ||
207
+ fileNameLower.includes('.chunk.') ||
208
+ fileNameLower.includes('.generated.') ||
209
+ fileNameLower.endsWith('.d.ts')) {
210
+ return true;
211
+ }
212
+ return false;
213
+ };
214
+ /** Check if a directory name is in the hardcoded ignore list */
215
+ export const isHardcodedIgnoredDirectory = (name) => {
216
+ return DEFAULT_IGNORE_LIST.has(name);
217
+ };
218
+ /**
219
+ * Load .gitignore and .code-mapperignore rules from the repo root
220
+ * @param repoPath - Absolute path to the repository root
221
+ * @returns An `ignore` instance with all patterns, or null if no files found
222
+ */
223
+ export const loadIgnoreRules = async (repoPath, options) => {
224
+ const ig = ignore();
225
+ let hasRules = false;
226
+ // Allow users to bypass .gitignore parsing (e.g. when .gitignore accidentally excludes source files)
227
+ const skipGitignore = options?.noGitignore ?? !!process.env.CODE_MAPPER_NO_GITIGNORE;
228
+ const filenames = skipGitignore
229
+ ? ['.code-mapperignore']
230
+ : ['.gitignore', '.code-mapperignore'];
231
+ for (const filename of filenames) {
232
+ try {
233
+ const content = await fs.readFile(nodePath.join(repoPath, filename), 'utf-8');
234
+ ig.add(content);
235
+ hasRules = true;
236
+ }
237
+ catch (err) {
238
+ const code = err.code;
239
+ if (code !== 'ENOENT') {
240
+ console.warn(` Warning: could not read ${filename}: ${err.message}`);
241
+ }
242
+ }
243
+ }
244
+ return hasRules ? ig : null;
245
+ };
246
+ /**
247
+ * Create a glob-compatible ignore filter combining .gitignore/.code-mapperignore
248
+ * patterns with hardcoded ignore lists
249
+ * @param repoPath - Absolute path to the repository root
250
+ * @returns An IgnoreLike object for glob's `ignore` option with directory-level pruning
251
+ */
252
+ export const createIgnoreFilter = async (repoPath, options) => {
253
+ const ig = await loadIgnoreRules(repoPath, options);
254
+ return {
255
+ ignored(p) {
256
+ // path-scurry returns POSIX paths — no normalization needed for `ignore` package
257
+ const rel = p.relative();
258
+ if (!rel)
259
+ return false;
260
+ // Check ignore file patterns
261
+ if (ig && ig.ignores(rel))
262
+ return true;
263
+ // Fall back to hardcoded rules
264
+ return shouldIgnorePath(rel);
265
+ },
266
+ childrenIgnored(p) {
267
+ // Fast path: check directory name against hardcoded list
268
+ // NOTE: dot-directories are primarily excluded by glob's `dot: false` in
269
+ // filesystem-walker.ts — this is defense-in-depth, do not remove `dot: false`
270
+ if (DEFAULT_IGNORE_LIST.has(p.name))
271
+ return true;
272
+ // Test both bare path and trailing-slash form for bare-name
273
+ // patterns (e.g. `local`) and dir-only patterns (e.g. `local/`)
274
+ if (ig) {
275
+ const rel = p.relative();
276
+ if (rel && (ig.ignores(rel) || ig.ignores(rel + '/')))
277
+ return true;
278
+ }
279
+ return false;
280
+ },
281
+ };
282
+ };
@@ -0,0 +1,23 @@
1
+ /** @file supported-languages.ts @description Enum of programming languages supported by the tree-sitter parser */
2
+ export declare enum SupportedLanguages {
3
+ JavaScript = "javascript",
4
+ TypeScript = "typescript",
5
+ Python = "python",
6
+ Java = "java",
7
+ C = "c",
8
+ CPlusPlus = "cpp",
9
+ CSharp = "csharp",
10
+ Go = "go",
11
+ Ruby = "ruby",
12
+ Rust = "rust",
13
+ PHP = "php",
14
+ Kotlin = "kotlin",
15
+ Swift = "swift"
16
+ }
17
+ /**
18
+ * All file extensions recognised by the code-mapper parser
19
+ *
20
+ * Derived from the extension checks in `getLanguageFromFilename`
21
+ * (core/ingestion/utils.ts) — keep in sync when adding languages
22
+ */
23
+ export declare const SUPPORTED_EXTENSIONS: ReadonlySet<string>;
@@ -0,0 +1,52 @@
1
+ // code-mapper/src/config/supported-languages.ts
2
+ /** @file supported-languages.ts @description Enum of programming languages supported by the tree-sitter parser */
3
+ export var SupportedLanguages;
4
+ (function (SupportedLanguages) {
5
+ SupportedLanguages["JavaScript"] = "javascript";
6
+ SupportedLanguages["TypeScript"] = "typescript";
7
+ SupportedLanguages["Python"] = "python";
8
+ SupportedLanguages["Java"] = "java";
9
+ SupportedLanguages["C"] = "c";
10
+ SupportedLanguages["CPlusPlus"] = "cpp";
11
+ SupportedLanguages["CSharp"] = "csharp";
12
+ SupportedLanguages["Go"] = "go";
13
+ SupportedLanguages["Ruby"] = "ruby";
14
+ SupportedLanguages["Rust"] = "rust";
15
+ SupportedLanguages["PHP"] = "php";
16
+ SupportedLanguages["Kotlin"] = "kotlin";
17
+ SupportedLanguages["Swift"] = "swift";
18
+ })(SupportedLanguages || (SupportedLanguages = {}));
19
+ /**
20
+ * All file extensions recognised by the code-mapper parser
21
+ *
22
+ * Derived from the extension checks in `getLanguageFromFilename`
23
+ * (core/ingestion/utils.ts) — keep in sync when adding languages
24
+ */
25
+ export const SUPPORTED_EXTENSIONS = new Set([
26
+ // TypeScript
27
+ '.ts', '.tsx',
28
+ // JavaScript
29
+ '.js', '.jsx',
30
+ // Python
31
+ '.py',
32
+ // Java
33
+ '.java',
34
+ // C
35
+ '.c',
36
+ // C++ (including .h — parsed as C++ superset)
37
+ '.cpp', '.cc', '.cxx', '.h', '.hpp', '.hxx', '.hh',
38
+ // C#
39
+ '.cs',
40
+ // Go
41
+ '.go',
42
+ // Rust
43
+ '.rs',
44
+ // Kotlin
45
+ '.kt', '.kts',
46
+ // PHP
47
+ '.php', '.phtml', '.php3', '.php4', '.php5', '.php8',
48
+ // Ruby
49
+ '.rb', '.rake', '.gemspec',
50
+ // Swift
51
+ '.swift',
52
+ ]);
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @file engine.ts
3
+ * @description Lightweight enrichment of search patterns with knowledge graph context
4
+ *
5
+ * Called from platform hooks (Claude Code PreToolUse, Cursor beforeShellExecution)
6
+ * when an agent runs grep/glob/search
7
+ *
8
+ * Performance target: <500ms cold, <200ms warm
9
+ * Uses BM25 only (no embeddings) for speed; clusters rank internally but never surface
10
+ * Graceful failure: any error returns empty string
11
+ */
12
+ /**
13
+ * Augment a search pattern with knowledge graph context
14
+ *
15
+ * 1) BM25 search for the pattern
16
+ * 2) Fetch callers/callees/processes for top matches
17
+ * 3) Rank by internal cluster cohesion (not exposed)
18
+ * 4) Format as structured text block
19
+ *
20
+ * Returns empty string on any error (graceful failure)
21
+ */
22
+ export declare function augment(pattern: string, cwd?: string): Promise<string>;
@@ -0,0 +1,232 @@
1
+ // code-mapper/src/core/augmentation/engine.ts
2
+ /**
3
+ * @file engine.ts
4
+ * @description Lightweight enrichment of search patterns with knowledge graph context
5
+ *
6
+ * Called from platform hooks (Claude Code PreToolUse, Cursor beforeShellExecution)
7
+ * when an agent runs grep/glob/search
8
+ *
9
+ * Performance target: <500ms cold, <200ms warm
10
+ * Uses BM25 only (no embeddings) for speed; clusters rank internally but never surface
11
+ * Graceful failure: any error returns empty string
12
+ */
13
+ import path from 'path';
14
+ import { listRegisteredRepos } from '../../storage/repo-manager.js';
15
+ /** Find the best matching repo for a given working directory */
16
+ async function findRepoForCwd(cwd) {
17
+ try {
18
+ const entries = await listRegisteredRepos({ validate: true });
19
+ const resolved = path.resolve(cwd);
20
+ // Normalize case on Windows (drive letters can differ: D: vs d:)
21
+ const isWindows = process.platform === 'win32';
22
+ const normalizedCwd = isWindows ? resolved.toLowerCase() : resolved;
23
+ const sep = path.sep;
24
+ // Longest matching repo path wins (most specific match)
25
+ let bestMatch = null;
26
+ let bestLen = 0;
27
+ for (const entry of entries) {
28
+ const repoResolved = path.resolve(entry.path);
29
+ const normalizedRepo = isWindows ? repoResolved.toLowerCase() : repoResolved;
30
+ // Match at path separator boundary to avoid false positives
31
+ // (e.g. /projects/code-mapperv2 should NOT match /projects/code-mapper)
32
+ let matched = false;
33
+ if (normalizedCwd === normalizedRepo) {
34
+ matched = true;
35
+ }
36
+ else if (normalizedCwd.startsWith(normalizedRepo + sep)) {
37
+ matched = true;
38
+ }
39
+ else if (normalizedRepo.startsWith(normalizedCwd + sep)) {
40
+ matched = true;
41
+ }
42
+ if (matched && normalizedRepo.length > bestLen) {
43
+ bestMatch = entry;
44
+ bestLen = normalizedRepo.length;
45
+ }
46
+ }
47
+ if (!bestMatch)
48
+ return null;
49
+ return {
50
+ name: bestMatch.name,
51
+ storagePath: bestMatch.storagePath,
52
+ lbugPath: path.join(bestMatch.storagePath, 'lbug'),
53
+ };
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ /**
60
+ * Augment a search pattern with knowledge graph context
61
+ *
62
+ * 1) BM25 search for the pattern
63
+ * 2) Fetch callers/callees/processes for top matches
64
+ * 3) Rank by internal cluster cohesion (not exposed)
65
+ * 4) Format as structured text block
66
+ *
67
+ * Returns empty string on any error (graceful failure)
68
+ */
69
+ export async function augment(pattern, cwd) {
70
+ if (!pattern || pattern.length < 3)
71
+ return '';
72
+ const workDir = cwd || process.cwd();
73
+ try {
74
+ const repo = await findRepoForCwd(workDir);
75
+ if (!repo)
76
+ return '';
77
+ // Lazy-load lbug adapter
78
+ const { initLbug, executeQuery, isLbugReady } = await import('../../mcp/core/lbug-adapter.js');
79
+ const { searchFTSFromLbug } = await import('../search/bm25-index.js');
80
+ const repoId = repo.name.toLowerCase();
81
+ // Init LadybugDB if needed
82
+ if (!isLbugReady(repoId)) {
83
+ await initLbug(repoId, repo.lbugPath);
84
+ }
85
+ // Step 1: BM25 search (fast, no embeddings needed)
86
+ const bm25Results = await searchFTSFromLbug(pattern, 10, repoId);
87
+ if (bm25Results.length === 0)
88
+ return '';
89
+ // Step 2: Map BM25 file results to code symbols
90
+ const symbolMatches = [];
91
+ for (const result of bm25Results.slice(0, 5)) {
92
+ const escaped = result.filePath.replace(/'/g, "''");
93
+ try {
94
+ const symbols = await executeQuery(repoId, `
95
+ MATCH (n) WHERE n.filePath = '${escaped}'
96
+ AND n.name CONTAINS '${pattern.replace(/'/g, "''").split(/\s+/)[0]}'
97
+ RETURN n.id AS id, n.name AS name, labels(n) AS type, n.filePath AS filePath
98
+ LIMIT 3
99
+ `);
100
+ for (const sym of symbols) {
101
+ symbolMatches.push({
102
+ nodeId: sym.id || sym[0],
103
+ name: sym.name || sym[1],
104
+ type: sym.type || sym[2],
105
+ filePath: sym.filePath || sym[3],
106
+ score: result.score,
107
+ });
108
+ }
109
+ }
110
+ catch { /* skip */ }
111
+ }
112
+ if (symbolMatches.length === 0)
113
+ return '';
114
+ // Step 3: Batch-fetch callers/callees/processes/cohesion (WHERE n.id IN [...])
115
+ const uniqueSymbols = symbolMatches.slice(0, 5).filter((sym, i, arr) => arr.findIndex(s => s.nodeId === sym.nodeId) === i);
116
+ if (uniqueSymbols.length === 0)
117
+ return '';
118
+ const idList = uniqueSymbols.map(s => `'${s.nodeId.replace(/'/g, "''")}'`).join(', ');
119
+ // Callers
120
+ const callersMap = new Map();
121
+ try {
122
+ const rows = await executeQuery(repoId, `
123
+ MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(n)
124
+ WHERE n.id IN [${idList}]
125
+ RETURN n.id AS targetId, caller.name AS name
126
+ LIMIT 15
127
+ `);
128
+ for (const r of rows) {
129
+ const tid = r.targetId || r[0];
130
+ const name = r.name || r[1];
131
+ if (tid && name) {
132
+ if (!callersMap.has(tid))
133
+ callersMap.set(tid, []);
134
+ callersMap.get(tid).push(name);
135
+ }
136
+ }
137
+ }
138
+ catch { /* skip */ }
139
+ // Callees
140
+ const calleesMap = new Map();
141
+ try {
142
+ const rows = await executeQuery(repoId, `
143
+ MATCH (n)-[:CodeRelation {type: 'CALLS'}]->(callee)
144
+ WHERE n.id IN [${idList}]
145
+ RETURN n.id AS sourceId, callee.name AS name
146
+ LIMIT 15
147
+ `);
148
+ for (const r of rows) {
149
+ const sid = r.sourceId || r[0];
150
+ const name = r.name || r[1];
151
+ if (sid && name) {
152
+ if (!calleesMap.has(sid))
153
+ calleesMap.set(sid, []);
154
+ calleesMap.get(sid).push(name);
155
+ }
156
+ }
157
+ }
158
+ catch { /* skip */ }
159
+ // Processes
160
+ const processesMap = new Map();
161
+ try {
162
+ const rows = await executeQuery(repoId, `
163
+ MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
164
+ WHERE n.id IN [${idList}]
165
+ RETURN n.id AS nodeId, p.heuristicLabel AS label, r.step AS step, p.stepCount AS stepCount
166
+ `);
167
+ for (const r of rows) {
168
+ const nid = r.nodeId || r[0];
169
+ const label = r.label || r[1];
170
+ const step = r.step || r[2];
171
+ const stepCount = r.stepCount || r[3];
172
+ if (nid && label) {
173
+ if (!processesMap.has(nid))
174
+ processesMap.set(nid, []);
175
+ processesMap.get(nid).push(`${label} (step ${step}/${stepCount})`);
176
+ }
177
+ }
178
+ }
179
+ catch { /* skip */ }
180
+ // Cohesion (internal ranking signal)
181
+ const cohesionMap = new Map();
182
+ try {
183
+ const rows = await executeQuery(repoId, `
184
+ MATCH (n)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
185
+ WHERE n.id IN [${idList}]
186
+ RETURN n.id AS nodeId, c.cohesion AS cohesion
187
+ `);
188
+ for (const r of rows) {
189
+ const nid = r.nodeId || r[0];
190
+ const coh = r.cohesion ?? r[1] ?? 0;
191
+ if (nid)
192
+ cohesionMap.set(nid, coh);
193
+ }
194
+ }
195
+ catch { /* skip */ }
196
+ // Assemble enriched context
197
+ const enriched = [];
198
+ for (const sym of uniqueSymbols) {
199
+ enriched.push({
200
+ name: sym.name,
201
+ filePath: sym.filePath,
202
+ callers: (callersMap.get(sym.nodeId) || []).slice(0, 3),
203
+ callees: (calleesMap.get(sym.nodeId) || []).slice(0, 3),
204
+ processes: processesMap.get(sym.nodeId) || [],
205
+ cohesion: cohesionMap.get(sym.nodeId) || 0,
206
+ });
207
+ }
208
+ if (enriched.length === 0)
209
+ return '';
210
+ // Step 4: Rank by cohesion and format output
211
+ enriched.sort((a, b) => b.cohesion - a.cohesion);
212
+ const lines = [`[Code Mapper] ${enriched.length} related symbols found:`, ''];
213
+ for (const item of enriched) {
214
+ lines.push(`${item.name} (${item.filePath})`);
215
+ if (item.callers.length > 0) {
216
+ lines.push(` Called by: ${item.callers.join(', ')}`);
217
+ }
218
+ if (item.callees.length > 0) {
219
+ lines.push(` Calls: ${item.callees.join(', ')}`);
220
+ }
221
+ if (item.processes.length > 0) {
222
+ lines.push(` Flows: ${item.processes.join(', ')}`);
223
+ }
224
+ lines.push('');
225
+ }
226
+ return lines.join('\n').trim();
227
+ }
228
+ catch {
229
+ // Graceful failure — never break the caller's tool
230
+ return '';
231
+ }
232
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @file embedder.ts
3
+ * @description MLX-accelerated code embedder via Python subprocess
4
+ *
5
+ * Replaces the previous ONNX/transformers.js embedder with Jina Code 1.5B
6
+ * running on Apple Silicon Metal via MLX. Fail-fast — no fallback.
7
+ *
8
+ * Model: jinaai/jina-code-embeddings-1.5b-mlx (1.54B params, 1536 dims, 32K context)
9
+ * Matryoshka truncation to 256 dims for optimal speed/quality tradeoff
10
+ */
11
+ import { type EmbeddingConfig, type ModelProgress } from './types.js';
12
+ /** Progress callback for model loading */
13
+ export type ModelProgressCallback = (progress: ModelProgress) => void;
14
+ /** Get the current inference device */
15
+ export declare const getCurrentDevice: () => string | null;
16
+ /**
17
+ * Initialize the MLX embedder (spawns Python subprocess, loads model)
18
+ */
19
+ export declare const initEmbedder: (_onProgress?: ModelProgressCallback, _config?: Partial<EmbeddingConfig>) => Promise<any>;
20
+ /** Check if the embedder is initialized and ready */
21
+ export declare const isEmbedderReady: () => boolean;
22
+ /** Get the embedder instance — not applicable for MLX, returns null */
23
+ export declare const getEmbedder: () => any;
24
+ /**
25
+ * Embed a single text string
26
+ */
27
+ export declare const embedText: (text: string) => Promise<Float32Array>;
28
+ /**
29
+ * Embed multiple texts in a single batch
30
+ */
31
+ export declare const embedBatch: (texts: string[]) => Promise<Float32Array[]>;
32
+ /** Convert Float32Array to number[] for LadybugDB storage */
33
+ export declare const embeddingToArray: (embedding: Float32Array) => number[];
34
+ /** Dispose the embedder subprocess */
35
+ export declare const disposeEmbedder: () => Promise<void>;