@softerist/heuristic-mcp 2.1.0 → 2.1.1
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/README.md +1 -1
- package/lib/cache.js +24 -0
- package/lib/call-graph.js +6 -6
- package/lib/config.js +18 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -148,7 +148,7 @@ Returns: Relevant validation code with file paths and line numbers
|
|
|
148
148
|
**find_similar_code** - Find duplicates or patterns
|
|
149
149
|
|
|
150
150
|
```
|
|
151
|
-
Input: A snippet
|
|
151
|
+
Input: A code snippet (paste the code directly)
|
|
152
152
|
Returns: Other code in the project that looks or functions similarly
|
|
153
153
|
```
|
|
154
154
|
|
package/lib/cache.js
CHANGED
|
@@ -164,6 +164,19 @@ export class EmbeddingsCache {
|
|
|
164
164
|
this.annIndex = null;
|
|
165
165
|
this.annMeta = null;
|
|
166
166
|
}
|
|
167
|
+
|
|
168
|
+
// Load call-graph data if it exists
|
|
169
|
+
const callGraphFile = path.join(this.config.cacheDirectory, "call-graph.json");
|
|
170
|
+
try {
|
|
171
|
+
const callGraphData = await fs.readFile(callGraphFile, "utf8");
|
|
172
|
+
const parsed = JSON.parse(callGraphData);
|
|
173
|
+
this.fileCallData = new Map(Object.entries(parsed));
|
|
174
|
+
if (this.config.verbose) {
|
|
175
|
+
console.error(`[Cache] Loaded call-graph data for ${this.fileCallData.size} files`);
|
|
176
|
+
}
|
|
177
|
+
} catch {
|
|
178
|
+
// Call-graph file doesn't exist yet, that's OK
|
|
179
|
+
}
|
|
167
180
|
} catch (error) {
|
|
168
181
|
console.error("[Cache] Failed to load cache:", error.message);
|
|
169
182
|
}
|
|
@@ -189,6 +202,12 @@ export class EmbeddingsCache {
|
|
|
189
202
|
fs.writeFile(hashFile, JSON.stringify(Object.fromEntries(this.fileHashes), null, 2)),
|
|
190
203
|
fs.writeFile(metaFile, JSON.stringify(this.cacheMeta, null, 2))
|
|
191
204
|
]);
|
|
205
|
+
|
|
206
|
+
// Save call-graph data
|
|
207
|
+
if (this.fileCallData.size > 0) {
|
|
208
|
+
const callGraphFile = path.join(this.config.cacheDirectory, "call-graph.json");
|
|
209
|
+
await fs.writeFile(callGraphFile, JSON.stringify(Object.fromEntries(this.fileCallData), null, 2));
|
|
210
|
+
}
|
|
192
211
|
} catch (error) {
|
|
193
212
|
console.error("[Cache] Failed to save cache:", error.message);
|
|
194
213
|
} finally {
|
|
@@ -220,6 +239,8 @@ export class EmbeddingsCache {
|
|
|
220
239
|
removeFileFromStore(file) {
|
|
221
240
|
this.vectorStore = this.vectorStore.filter(chunk => chunk.file !== file);
|
|
222
241
|
this.invalidateAnnIndex();
|
|
242
|
+
// Also clear call-graph data for this file
|
|
243
|
+
this.removeFileCallData(file);
|
|
223
244
|
}
|
|
224
245
|
|
|
225
246
|
|
|
@@ -419,6 +440,9 @@ export class EmbeddingsCache {
|
|
|
419
440
|
this.vectorStore = [];
|
|
420
441
|
this.fileHashes = new Map();
|
|
421
442
|
this.invalidateAnnIndex();
|
|
443
|
+
// Clear call-graph data
|
|
444
|
+
this.fileCallData.clear();
|
|
445
|
+
this.callGraph = null;
|
|
422
446
|
console.error(`[Cache] Cache cleared successfully: ${this.config.cacheDirectory}`);
|
|
423
447
|
} catch (error) {
|
|
424
448
|
console.error("[Cache] Failed to clear cache:", error.message);
|
package/lib/call-graph.js
CHANGED
|
@@ -48,20 +48,20 @@ const DEFINITION_PATTERNS = {
|
|
|
48
48
|
// Pattern for function calls (language-agnostic, catches most cases)
|
|
49
49
|
const CALL_PATTERN = /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/g;
|
|
50
50
|
|
|
51
|
-
// Common built-ins to exclude from call detection
|
|
51
|
+
// Common built-ins to exclude from call detection (all lowercase for case-insensitive matching)
|
|
52
52
|
const BUILTIN_EXCLUSIONS = new Set([
|
|
53
53
|
// JavaScript
|
|
54
54
|
"if", "for", "while", "switch", "catch", "function", "async", "await",
|
|
55
55
|
"return", "throw", "new", "typeof", "instanceof", "delete", "void",
|
|
56
56
|
"console", "require", "import", "export", "super", "this",
|
|
57
57
|
// Common functions that aren't meaningful for call graphs
|
|
58
|
-
"
|
|
59
|
-
"
|
|
58
|
+
"parseint", "parsefloat", "string", "number", "boolean", "array", "object",
|
|
59
|
+
"map", "set", "promise", "error", "json", "math", "date", "regexp",
|
|
60
60
|
// Python
|
|
61
61
|
"def", "class", "print", "len", "range", "str", "int", "float", "list", "dict",
|
|
62
|
-
"tuple", "
|
|
62
|
+
"tuple", "bool", "type", "isinstance", "hasattr", "getattr", "setattr",
|
|
63
63
|
// Go
|
|
64
|
-
"func", "make", "append", "
|
|
64
|
+
"func", "make", "append", "cap", "panic", "recover",
|
|
65
65
|
// Control flow that looks like function calls
|
|
66
66
|
"else", "try", "finally", "with", "assert", "raise", "yield"
|
|
67
67
|
]);
|
|
@@ -103,7 +103,7 @@ export function extractDefinitions(content, file) {
|
|
|
103
103
|
let match;
|
|
104
104
|
while ((match = pattern.exec(content)) !== null) {
|
|
105
105
|
const name = match[1];
|
|
106
|
-
if (name && name.length > 1 && !BUILTIN_EXCLUSIONS.has(name)) {
|
|
106
|
+
if (name && name.length > 1 && !BUILTIN_EXCLUSIONS.has(name.toLowerCase())) {
|
|
107
107
|
definitions.add(name);
|
|
108
108
|
}
|
|
109
109
|
}
|
package/lib/config.js
CHANGED
|
@@ -208,6 +208,24 @@ export async function loadConfig(workspaceDir = null) {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
if (process.env.SMART_CODING_RECENCY_BOOST !== undefined) {
|
|
212
|
+
const value = parseFloat(process.env.SMART_CODING_RECENCY_BOOST);
|
|
213
|
+
if (!isNaN(value) && value >= 0 && value <= 1) {
|
|
214
|
+
config.recencyBoost = value;
|
|
215
|
+
} else {
|
|
216
|
+
console.error(`[Config] Invalid SMART_CODING_RECENCY_BOOST: ${process.env.SMART_CODING_RECENCY_BOOST}, using default`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (process.env.SMART_CODING_RECENCY_DECAY_DAYS !== undefined) {
|
|
221
|
+
const value = parseInt(process.env.SMART_CODING_RECENCY_DECAY_DAYS, 10);
|
|
222
|
+
if (!isNaN(value) && value > 0 && value <= 365) {
|
|
223
|
+
config.recencyDecayDays = value;
|
|
224
|
+
} else {
|
|
225
|
+
console.error(`[Config] Invalid SMART_CODING_RECENCY_DECAY_DAYS: ${process.env.SMART_CODING_RECENCY_DECAY_DAYS}, using default`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
211
229
|
if (process.env.SMART_CODING_WATCH_FILES !== undefined) {
|
|
212
230
|
const value = process.env.SMART_CODING_WATCH_FILES;
|
|
213
231
|
if (value === 'true' || value === 'false') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softerist/heuristic-mcp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "An enhanced MCP server providing intelligent semantic code search with find-similar-code, recency ranking, and improved chunking. Fork of smart-coding-mcp.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|