graph-indexer 1.0.1 → 1.0.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graph-indexer",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Zero-DB, Air-gapped, In-Memory Graph Indexer MCP Server with Hybrid RRF Search and Cross-Language Topology",
5
5
  "type": "module",
6
6
  "main": "core-engine.mjs",
package/parser-utils.mjs CHANGED
@@ -19,7 +19,7 @@ import path from 'path';
19
19
  import { createHash } from 'crypto';
20
20
  import ignore from 'ignore';
21
21
  import Parser from 'tree-sitter';
22
- const { Query } = Parser; // Importación robusta nativa
22
+ const { Query } = Parser; // Native parser query helper
23
23
 
24
24
  import TypeScript from 'tree-sitter-typescript';
25
25
  import JavaScript from 'tree-sitter-javascript';
@@ -398,6 +398,7 @@ export function extractSemanticChunks(rootNode, relPath, sourceCode, ext) {
398
398
  const params = extractParams(chunkNode, ext);
399
399
  const returnType = extractReturnType(chunkNode, ext);
400
400
  const classContext = extractClassContext(chunkNode);
401
+ const typeRefs = extractTypeAnnotations(chunkNode, ext);
401
402
 
402
403
  const id = createHash('sha256')
403
404
  .update(`${relPath}::${chunkNode.startPosition.row}::${chunkNode.startPosition.column}`)
@@ -408,7 +409,8 @@ export function extractSemanticChunks(rootNode, relPath, sourceCode, ext) {
408
409
  docstring: docstring, code_snippet: snippet, content_hash: hash,
409
410
  start_line: chunkNode.startPosition.row + 1, end_line: chunkNode.endPosition.row + 1,
410
411
  calls: outgoingCalls,
411
- params, return_type: returnType, class_context: classContext
412
+ params, return_type: returnType, class_context: classContext,
413
+ type_refs: typeRefs,
412
414
  });
413
415
  }
414
416
  } catch (e) {
@@ -709,6 +711,44 @@ export function extractClassContext(chunkNode) {
709
711
  return '';
710
712
  }
711
713
 
714
+ /**
715
+ * Frontier 2: Extract TypeScript/Python type annotation names from a chunk node.
716
+ * Returns simple type names (e.g. ['User', 'AuthToken', 'PaymentService'])
717
+ * used to enrich the inverted index and the type_refs chunk field.
718
+ */
719
+ export function extractTypeAnnotations(chunkNode, ext) {
720
+ const types = new Set();
721
+ const JS_LIKE = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
722
+ if (!JS_LIKE.includes(ext) && ext !== '.py') return [];
723
+
724
+ function walk(node) {
725
+ // TypeScript: type_annotation nodes contain the type text
726
+ if (node.type === 'type_annotation') {
727
+ const typeText = node.text.replace(/^:\s*/, '').trim();
728
+ // Extract simple identifiers from the type (skip primitives)
729
+ const PRIMITIVES = new Set(['string','number','boolean','void','any','unknown','never','null','undefined','object','symbol','bigint']);
730
+ for (const match of typeText.matchAll(/\b([A-Z][A-Za-z0-9]*)\b/g)) {
731
+ if (!PRIMITIVES.has(match[1].toLowerCase())) types.add(match[1]);
732
+ }
733
+ }
734
+ // TypeScript: generic_type, predefined_type (string, number…) skip, named types keep
735
+ else if (node.type === 'type_identifier' || node.type === 'generic_type') {
736
+ const name = node.children[0]?.text || node.text;
737
+ if (name && /^[A-Z]/.test(name)) types.add(name);
738
+ }
739
+ // Python: type comments or annotations (annotation nodes)
740
+ else if (node.type === 'annotation' && ext === '.py') {
741
+ const typeText = node.text.replace(/^->\s*|^:\s*/, '').trim();
742
+ for (const match of typeText.matchAll(/\b([A-Z][A-Za-z0-9]*)\b/g)) {
743
+ types.add(match[1]);
744
+ }
745
+ }
746
+ for (const child of node.children) walk(child);
747
+ }
748
+ walk(chunkNode);
749
+ return Array.from(types).slice(0, 20);
750
+ }
751
+
712
752
  export function extractCalls(rootNode) {
713
753
  const calls = new Set();
714
754
  function walk(node) {
package/watch-daemon.mjs CHANGED
@@ -132,11 +132,11 @@ async function processFileChange(absolutePath) {
132
132
  db.saveDebounced();
133
133
  process.stderr.write(`[daemon] 🔄 Synced: ${filename} (Cache Hit: ${newChunks.length - chunksToEmbed.length}/${newChunks.length})\n`);
134
134
  } catch (err) {
135
- process.stderr.write(`[daemon] ❌ Error en ${filename}: ${err.message}\n`);
135
+ process.stderr.write(`[daemon] ❌ Error in ${filename}: ${err.message}\n`);
136
136
  }
137
137
  }
138
138
 
139
- process.stderr.write(`🚀 Chokidar Watcher Daemon iniciado en: ${PROJECT_ROOT}\n`);
139
+ process.stderr.write(`🚀 Chokidar Watcher Daemon started in: ${PROJECT_ROOT}\n`);
140
140
  const watcher = chokidar.watch(PROJECT_ROOT, {
141
141
  ignored: /(^|[\/\\])\../, persistent: true,
142
142
  awaitWriteFinish: { stabilityThreshold: 300, pollInterval: 100 }