@esankhan3/code-search-mcp 0.0.2 → 0.2.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 (50) hide show
  1. package/README.md +343 -248
  2. package/dist/__tests__/config-resolver.test.js +153 -0
  3. package/dist/__tests__/daemon-rpc.test.js +100 -0
  4. package/dist/__tests__/observability.test.js +69 -0
  5. package/dist/__tests__/projects.test.js +141 -0
  6. package/dist/backends/daemon-client.js +87 -0
  7. package/dist/backends/in-process.js +104 -0
  8. package/dist/backends/index.js +29 -0
  9. package/dist/cli/index.js +231 -0
  10. package/dist/core/config.js +362 -49
  11. package/dist/core/env-config.js +45 -43
  12. package/dist/daemon/index.js +119 -0
  13. package/dist/daemon/rpc-server.js +99 -0
  14. package/dist/daemon/watcher.js +105 -0
  15. package/dist/index.js +7 -0
  16. package/dist/observability/logger.js +66 -0
  17. package/dist/observability/metrics.js +138 -0
  18. package/dist/projects/registry.js +146 -0
  19. package/dist/resources/resources.js +3 -3
  20. package/dist/server.js +6 -2
  21. package/dist/tools/graph.js +1 -1
  22. package/dist/tools/index-tools.js +1 -1
  23. package/dist/tools/profile.js +2 -2
  24. package/dist/tools/search.js +1 -1
  25. package/dist/transports/http-transport.js +38 -0
  26. package/package.json +31 -12
  27. package/scripts/smoke/run-smoke.sh +167 -0
  28. package/dist/core/ast-graph-builder.js +0 -800
  29. package/dist/core/chunker.js +0 -368
  30. package/dist/core/claude-runner.js +0 -173
  31. package/dist/core/cross-repo-detector.js +0 -887
  32. package/dist/core/embedder.js +0 -334
  33. package/dist/core/file-walker.js +0 -186
  34. package/dist/core/git-diff.js +0 -160
  35. package/dist/core/graph-metrics.js +0 -233
  36. package/dist/core/indexer.js +0 -552
  37. package/dist/core/project-graph-builder.js +0 -202
  38. package/dist/core/query-classifier.js +0 -144
  39. package/dist/core/query-router.js +0 -210
  40. package/dist/core/rag-evaluator.js +0 -213
  41. package/dist/core/repo-profiler.js +0 -383
  42. package/dist/core/reranker.js +0 -218
  43. package/dist/core/retriever.js +0 -242
  44. package/dist/core/semantic-edge-detector.js +0 -147
  45. package/dist/core/service-mesh-inferrer.js +0 -241
  46. package/dist/core/structural-hasher.js +0 -316
  47. package/dist/core/tree-sitter-parser.js +0 -539
  48. package/dist/core/vector-store.js +0 -259
  49. package/dist/core/workspace-detector.js +0 -481
  50. /package/dist/{core → backends}/types.js +0 -0
@@ -1,539 +0,0 @@
1
- import { Parser as TSParser, Language as TSLanguage, Query as TSQuery } from "web-tree-sitter";
2
- import { createHash } from "node:crypto";
3
- import { createRequire } from "node:module";
4
- const require2 = createRequire(import.meta.url);
5
- const GRAMMAR_MAP = {
6
- typescript: "tree-sitter-typescript.wasm",
7
- javascript: "tree-sitter-javascript.wasm",
8
- tsx: "tree-sitter-tsx.wasm",
9
- go: "tree-sitter-go.wasm",
10
- python: "tree-sitter-python.wasm",
11
- rust: "tree-sitter-rust.wasm",
12
- java: "tree-sitter-java.wasm",
13
- php: "tree-sitter-php.wasm"
14
- };
15
- let parserReady = false;
16
- const languageParsers = /* @__PURE__ */ new Map();
17
- async function initTreeSitter() {
18
- if (parserReady) return;
19
- await TSParser.init();
20
- parserReady = true;
21
- }
22
- async function getParserAndLang(language) {
23
- if (languageParsers.has(language)) return languageParsers.get(language);
24
- const wasmFile = GRAMMAR_MAP[language];
25
- if (!wasmFile) return null;
26
- try {
27
- const wasmPath = require2.resolve(`tree-sitter-wasms/out/${wasmFile}`);
28
- const lang = await TSLanguage.load(wasmPath);
29
- const parser = new TSParser();
30
- parser.setLanguage(lang);
31
- const entry = { parser, lang };
32
- languageParsers.set(language, entry);
33
- return entry;
34
- } catch {
35
- return null;
36
- }
37
- }
38
- const TS_QUERIES = {
39
- entities: `
40
- (function_declaration name: (identifier) @name) @entity
41
- (class_declaration name: (type_identifier) @name) @entity
42
- (interface_declaration name: (type_identifier) @name) @entity
43
- (type_alias_declaration name: (type_identifier) @name) @entity
44
- (enum_declaration name: (identifier) @name) @entity
45
- (method_definition name: (property_identifier) @name) @entity
46
- (export_statement declaration: (function_declaration name: (identifier) @name) @entity) @export
47
- (export_statement declaration: (class_declaration name: (type_identifier) @name) @entity) @export
48
- (export_statement declaration: (interface_declaration name: (type_identifier) @name) @entity) @export
49
- (export_statement declaration: (type_alias_declaration name: (type_identifier) @name) @entity) @export
50
- (export_statement declaration: (enum_declaration name: (identifier) @name) @entity) @export
51
- (export_statement declaration: (lexical_declaration (variable_declarator name: (identifier) @name value: (arrow_function) @entity))) @export
52
- `,
53
- imports: `
54
- (import_statement source: (string) @source) @import
55
- `,
56
- calls: `
57
- (call_expression function: (identifier) @callee) @call
58
- (call_expression function: (member_expression property: (property_identifier) @callee)) @call
59
- `
60
- };
61
- const GO_QUERIES = {
62
- entities: `
63
- (function_declaration name: (identifier) @name) @entity
64
- (method_declaration name: (field_identifier) @name) @entity
65
- (type_declaration (type_spec name: (type_identifier) @name type: (struct_type))) @entity
66
- (type_declaration (type_spec name: (type_identifier) @name type: (interface_type))) @entity
67
- `,
68
- imports: `
69
- (import_spec path: (interpreted_string_literal) @source) @import
70
- `,
71
- calls: `
72
- (call_expression function: (identifier) @callee) @call
73
- (call_expression function: (selector_expression field: (field_identifier) @callee)) @call
74
- `
75
- };
76
- const PY_QUERIES = {
77
- entities: `
78
- (function_definition name: (identifier) @name) @entity
79
- (class_definition name: (identifier) @name) @entity
80
- `,
81
- imports: `
82
- (import_from_statement module_name: (dotted_name) @source) @import
83
- (import_statement name: (dotted_name) @source) @import
84
- `,
85
- calls: `
86
- (call function: (identifier) @callee) @call
87
- (call function: (attribute attribute: (identifier) @callee)) @call
88
- `
89
- };
90
- const RUST_QUERIES = {
91
- entities: `
92
- (function_item name: (identifier) @name) @entity
93
- (struct_item name: (type_identifier) @name) @entity
94
- (impl_item type: (type_identifier) @name) @entity
95
- (trait_item name: (type_identifier) @name) @entity
96
- (enum_item name: (type_identifier) @name) @entity
97
- `,
98
- imports: `
99
- (use_declaration argument: (scoped_identifier) @source) @import
100
- `,
101
- calls: `
102
- (call_expression function: (identifier) @callee) @call
103
- (call_expression function: (field_expression field: (field_identifier) @callee)) @call
104
- `
105
- };
106
- const JAVA_QUERIES = {
107
- entities: `
108
- (class_declaration name: (identifier) @name) @entity
109
- (interface_declaration name: (identifier) @name) @entity
110
- (method_declaration name: (identifier) @name) @entity
111
- (enum_declaration name: (identifier) @name) @entity
112
- `,
113
- imports: `
114
- (import_declaration (scoped_identifier) @source) @import
115
- `,
116
- calls: `
117
- (method_invocation name: (identifier) @callee) @call
118
- `
119
- };
120
- const PHP_QUERIES = {
121
- entities: `
122
- (function_definition name: (name) @name) @entity
123
- (class_declaration name: (name) @name) @entity
124
- (method_declaration name: (name) @name) @entity
125
- (interface_declaration name: (name) @name) @entity
126
- (trait_declaration name: (name) @name) @entity
127
- `,
128
- imports: `
129
- (namespace_use_declaration (namespace_use_clause (qualified_name) @source)) @import
130
- `,
131
- calls: `
132
- (function_call_expression function: (name) @callee) @call
133
- (member_call_expression name: (name) @callee) @call
134
- `
135
- };
136
- function queriesForLanguage(language) {
137
- switch (language) {
138
- case "typescript":
139
- case "javascript":
140
- case "tsx":
141
- return TS_QUERIES;
142
- case "go":
143
- return GO_QUERIES;
144
- case "python":
145
- return PY_QUERIES;
146
- case "rust":
147
- return RUST_QUERIES;
148
- case "java":
149
- return JAVA_QUERIES;
150
- case "php":
151
- return PHP_QUERIES;
152
- default:
153
- return null;
154
- }
155
- }
156
- const NODE_TYPE_TO_ENTITY = {
157
- // TypeScript / JavaScript
158
- function_declaration: "function",
159
- arrow_function: "function",
160
- class_declaration: "class",
161
- method_definition: "method",
162
- interface_declaration: "interface",
163
- type_alias_declaration: "type",
164
- enum_declaration: "enum",
165
- // Python
166
- function_definition: "function",
167
- class_definition: "class",
168
- // Go (type_spec handled separately via child type)
169
- // Rust
170
- function_item: "function",
171
- struct_item: "struct",
172
- impl_item: "module",
173
- // impl blocks act as module-level grouping
174
- trait_item: "trait",
175
- enum_item: "enum",
176
- // Java
177
- method_declaration: "method",
178
- // PHP (uses same names as TS for class/interface + 'trait_declaration')
179
- function_definition_php: "function",
180
- trait_declaration: "trait"
181
- };
182
- function detectEntityType(node, _language) {
183
- const t = node.type;
184
- const mapped = NODE_TYPE_TO_ENTITY[t];
185
- if (mapped) return mapped;
186
- if (t === "type_declaration" || t === "type_spec") {
187
- const spec = t === "type_declaration" ? node.namedChildren.find((c) => c.type === "type_spec") : node;
188
- if (spec) {
189
- const typeChild = spec.namedChildren.find(
190
- (c) => c.type === "struct_type" || c.type === "interface_type"
191
- );
192
- if (typeChild?.type === "struct_type") return "struct";
193
- if (typeChild?.type === "interface_type") return "interface";
194
- }
195
- return "type";
196
- }
197
- if (t.includes("class")) return "class";
198
- if (t.includes("interface")) return "interface";
199
- if (t.includes("method")) return "method";
200
- if (t.includes("function") || t.includes("func")) return "function";
201
- if (t.includes("struct")) return "struct";
202
- if (t.includes("enum")) return "enum";
203
- if (t.includes("trait")) return "trait";
204
- return "function";
205
- }
206
- function isExported(entityNode, language, content) {
207
- if (language === "typescript" || language === "javascript" || language === "tsx") {
208
- let cursor = entityNode.parent;
209
- while (cursor) {
210
- if (cursor.type === "export_statement") return true;
211
- cursor = cursor.parent;
212
- }
213
- return false;
214
- }
215
- if (language === "rust") {
216
- const text = content.slice(entityNode.startIndex, entityNode.startIndex + 10);
217
- return text.trimStart().startsWith("pub");
218
- }
219
- if (language === "go") {
220
- const nameChild = entityNode.namedChildren.find(
221
- (c) => c.type === "identifier" || c.type === "type_identifier" || c.type === "field_identifier"
222
- );
223
- if (nameChild) {
224
- const name = nameChild.text;
225
- return name.length > 0 && name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase();
226
- }
227
- return false;
228
- }
229
- if (language === "java") {
230
- const modifiers = entityNode.namedChildren.find((c) => c.type === "modifiers");
231
- if (modifiers) return modifiers.text.includes("public");
232
- return false;
233
- }
234
- return true;
235
- }
236
- function findContainingEntity(node) {
237
- let cursor = node.parent;
238
- while (cursor) {
239
- const t = cursor.type;
240
- if (t === "class_declaration" || t === "class_definition" || t === "class_body" || t === "impl_item" || t === "struct_item" || t === "trait_item" || t === "interface_declaration" || t === "trait_declaration") {
241
- const target = t === "class_body" && cursor.parent ? cursor.parent : cursor;
242
- const nameChild = target.namedChildren.find(
243
- (c) => c.type === "identifier" || c.type === "type_identifier" || c.type === "name"
244
- );
245
- if (nameChild) return nameChild.text;
246
- }
247
- cursor = cursor.parent;
248
- }
249
- return void 0;
250
- }
251
- function extractSignature(entityNode, entityType, _content) {
252
- if (entityType !== "function" && entityType !== "method") return void 0;
253
- const params = entityNode.namedChildren.find(
254
- (c) => c.type === "formal_parameters" || c.type === "parameters" || c.type === "parameter_list" || c.type === "typed_parameters"
255
- );
256
- const returnType = entityNode.namedChildren.find(
257
- (c) => c.type === "type_annotation" || c.type === "return_type"
258
- );
259
- if (!params) return void 0;
260
- let sig = params.text;
261
- if (returnType) sig += `: ${returnType.text}`;
262
- return sig;
263
- }
264
- function runQuery(language, querySource, rootNode) {
265
- try {
266
- const query = new TSQuery(language, querySource);
267
- return query.matches(rootNode);
268
- } catch {
269
- return [];
270
- }
271
- }
272
- function runQueryWithFallback(language, querySource, rootNode) {
273
- const fullResult = runQuery(language, querySource, rootNode);
274
- if (fullResult.length > 0) return fullResult;
275
- const patterns = querySource.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("("));
276
- const results = [];
277
- for (const pattern of patterns) {
278
- try {
279
- const q = new TSQuery(language, pattern);
280
- results.push(...q.matches(rootNode));
281
- } catch {
282
- }
283
- }
284
- return results;
285
- }
286
- function parseImportMatches(matches, language, _content, _rootNode) {
287
- const imports = [];
288
- for (const match of matches) {
289
- const sourceCapture = match.captures.find((c) => c.name === "source");
290
- const importCapture = match.captures.find((c) => c.name === "import");
291
- if (!sourceCapture) continue;
292
- let source = sourceCapture.node.text.replace(/^['"`]|['"`]$/g, "");
293
- const startLine = (importCapture ?? sourceCapture).node.startPosition.row;
294
- const isRelative = source.startsWith("./") || source.startsWith("../");
295
- const names = [];
296
- if (language === "typescript" || language === "javascript" || language === "tsx") {
297
- const importNode = importCapture?.node ?? sourceCapture.node.parent;
298
- if (importNode) {
299
- const walk = (n) => {
300
- if (n.type === "import_specifier") {
301
- const nameNode = n.namedChildren.find((c) => c.type === "identifier");
302
- if (nameNode) names.push(nameNode.text);
303
- }
304
- if (n.type === "identifier" && n.parent?.type === "import_clause") {
305
- names.push(n.text);
306
- }
307
- for (const child of n.namedChildren) walk(child);
308
- };
309
- walk(importNode);
310
- }
311
- }
312
- if (language === "python") {
313
- const importNode = importCapture?.node ?? sourceCapture.node.parent;
314
- if (importNode && importNode.type === "import_from_statement") {
315
- for (const child of importNode.namedChildren) {
316
- if (child.type === "dotted_name" && child !== sourceCapture.node) {
317
- names.push(child.text);
318
- }
319
- if (child.type === "aliased_import") {
320
- const nameNode = child.namedChildren.find((c) => c.type === "dotted_name");
321
- if (nameNode) names.push(nameNode.text);
322
- }
323
- }
324
- }
325
- }
326
- imports.push({ source, names, startLine, isRelative });
327
- }
328
- return imports;
329
- }
330
- function parseCallMatches(matches, entities) {
331
- const callSites = [];
332
- for (const match of matches) {
333
- const calleeCapture = match.captures.find((c) => c.name === "callee");
334
- if (!calleeCapture) continue;
335
- const callee = calleeCapture.node.text;
336
- const startLine = calleeCapture.node.startPosition.row;
337
- const containingEntity = entities.find(
338
- (e) => startLine >= e.startLine && startLine <= e.endLine
339
- )?.name;
340
- callSites.push({ callee, startLine, containingEntity });
341
- }
342
- return callSites;
343
- }
344
- function extractTypeReferences(entities) {
345
- const typeRefs = /* @__PURE__ */ new Set();
346
- const typeRefPattern = /(?<!['"@/\\])\b([A-Z][A-Za-z0-9]*(?:<[^>]+>)?)\b/g;
347
- for (const entity of entities) {
348
- if (entity.signature) {
349
- let m;
350
- while ((m = typeRefPattern.exec(entity.signature)) !== null) {
351
- const ref = m[1].replace(/<.*>$/, "");
352
- if (!BUILTIN_TYPES.has(ref)) typeRefs.add(ref);
353
- }
354
- }
355
- }
356
- return [...typeRefs];
357
- }
358
- const BUILTIN_TYPES = /* @__PURE__ */ new Set([
359
- "String",
360
- "Number",
361
- "Boolean",
362
- "Object",
363
- "Array",
364
- "Function",
365
- "Symbol",
366
- "Promise",
367
- "Map",
368
- "Set",
369
- "WeakMap",
370
- "WeakSet",
371
- "Date",
372
- "RegExp",
373
- "Error",
374
- "Record",
375
- "Partial",
376
- "Required",
377
- "Readonly",
378
- "Pick",
379
- "Omit",
380
- "Exclude",
381
- "Extract",
382
- "NonNullable",
383
- "ReturnType",
384
- "Parameters",
385
- "InstanceType",
386
- "Awaited",
387
- "Uint8Array",
388
- "Int32Array",
389
- "Float64Array",
390
- "ArrayBuffer",
391
- "Iterator",
392
- "AsyncIterator",
393
- "Generator",
394
- "AsyncGenerator"
395
- ]);
396
- async function parseFile(filePath, content, language) {
397
- await initTreeSitter();
398
- const parserEntry = await getParserAndLang(language);
399
- if (!parserEntry) return null;
400
- const queries = queriesForLanguage(language);
401
- if (!queries) return null;
402
- let tree;
403
- try {
404
- tree = parserEntry.parser.parse(content);
405
- } catch {
406
- return null;
407
- }
408
- if (!tree) return null;
409
- const rootNode = tree.rootNode;
410
- const lang = parserEntry.lang;
411
- const entityMatches = runQueryWithFallback(lang, queries.entities, rootNode);
412
- const entities = [];
413
- const seenEntityKeys = /* @__PURE__ */ new Set();
414
- for (const match of entityMatches) {
415
- const nameCapture = match.captures.find((c) => c.name === "name");
416
- const entityCapture = match.captures.find((c) => c.name === "entity");
417
- if (!nameCapture || !entityCapture) continue;
418
- const entityNode = entityCapture.node;
419
- const name = nameCapture.node.text;
420
- const type = detectEntityType(entityNode, language);
421
- const startLine = entityNode.startPosition.row;
422
- const endLine = entityNode.endPosition.row;
423
- const key = `${name}:${startLine}`;
424
- if (seenEntityKeys.has(key)) {
425
- const existing = entities.find((e) => e.name === name && e.startLine === startLine);
426
- const hasExportCapture2 = match.captures.some((c) => c.name === "export");
427
- if (existing && hasExportCapture2) {
428
- existing.isExported = true;
429
- }
430
- continue;
431
- }
432
- seenEntityKeys.add(key);
433
- const hasExportCapture = match.captures.some((c) => c.name === "export");
434
- const exported = hasExportCapture || isExported(entityNode, language, content);
435
- const parentName = type === "method" ? findContainingEntity(entityNode) : void 0;
436
- const signature = extractSignature(entityNode, type, content);
437
- const body = content.slice(entityNode.startIndex, entityNode.endIndex);
438
- entities.push({
439
- name,
440
- type,
441
- startLine,
442
- endLine,
443
- startByte: entityNode.startIndex,
444
- endByte: entityNode.endIndex,
445
- parent: parentName,
446
- signature,
447
- isExported: exported,
448
- body
449
- });
450
- }
451
- const importMatches = runQueryWithFallback(lang, queries.imports, rootNode);
452
- const imports = parseImportMatches(importMatches, language, content, rootNode);
453
- const callMatches = runQueryWithFallback(lang, queries.calls, rootNode);
454
- const callSites = parseCallMatches(callMatches, entities);
455
- const typeReferences = extractTypeReferences(entities);
456
- tree.delete();
457
- return {
458
- filePath,
459
- language,
460
- entities,
461
- imports,
462
- callSites,
463
- typeReferences
464
- };
465
- }
466
- async function parseFiles(files) {
467
- await initTreeSitter();
468
- const results = [];
469
- for (const file of files) {
470
- const result = await parseFile(file.path, file.content, file.language);
471
- if (result) results.push(result);
472
- }
473
- return results;
474
- }
475
- async function computeStructuralHash(_content, entity, language) {
476
- await initTreeSitter();
477
- const parserEntry = await getParserAndLang(language);
478
- if (!parserEntry) return null;
479
- let tree;
480
- try {
481
- tree = parserEntry.parser.parse(entity.body);
482
- } catch {
483
- return null;
484
- }
485
- if (!tree) return null;
486
- const identifierMap = /* @__PURE__ */ new Map();
487
- let identifierCounter = 0;
488
- const tokens = [];
489
- const SKIP_TYPES = /* @__PURE__ */ new Set([
490
- "comment",
491
- "line_comment",
492
- "block_comment",
493
- "doc_comment"
494
- // Whitespace nodes are typically not named, but include for safety
495
- ]);
496
- const IDENTIFIER_TYPES = /* @__PURE__ */ new Set([
497
- "identifier",
498
- "type_identifier",
499
- "property_identifier",
500
- "field_identifier",
501
- "shorthand_field_identifier",
502
- "name",
503
- "dotted_name"
504
- ]);
505
- function walk(node) {
506
- if (SKIP_TYPES.has(node.type)) return;
507
- if (node.namedChildCount === 0) {
508
- if (IDENTIFIER_TYPES.has(node.type)) {
509
- const text = node.text;
510
- if (!identifierMap.has(text)) {
511
- identifierMap.set(text, `v${identifierCounter++}`);
512
- }
513
- tokens.push(`${node.type}:${identifierMap.get(text)}`);
514
- } else {
515
- tokens.push(`${node.type}:${node.text}`);
516
- }
517
- } else {
518
- tokens.push(`(${node.type}`);
519
- for (const child of node.namedChildren) {
520
- walk(child);
521
- }
522
- tokens.push(")");
523
- }
524
- }
525
- walk(tree.rootNode);
526
- tree.delete();
527
- const canonical = tokens.join(" ");
528
- return createHash("sha256").update(canonical).digest("hex");
529
- }
530
- function supportedLanguages() {
531
- return Object.keys(GRAMMAR_MAP);
532
- }
533
- export {
534
- computeStructuralHash,
535
- initTreeSitter,
536
- parseFile,
537
- parseFiles,
538
- supportedLanguages
539
- };