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/PROMPT.md +218 -35
- package/README.md +212 -855
- package/core-engine.mjs +363 -159
- package/indexer.mjs +8 -8
- package/mcp-server.mjs +397 -150
- package/package.json +1 -1
- package/parser-utils.mjs +42 -2
- package/watch-daemon.mjs +2 -2
package/package.json
CHANGED
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; //
|
|
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
|
|
135
|
+
process.stderr.write(`[daemon] ❌ Error in ${filename}: ${err.message}\n`);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
process.stderr.write(`🚀 Chokidar Watcher Daemon
|
|
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 }
|