@mrxkun/mcfast-mcp 4.0.6 → 4.0.12
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 +1 -1
- package/src/index.js +118 -36
- package/src/memory/memory-engine.js +42 -38
- package/src/memory/stores/database.js +6 -2
- package/src/memory/utils/daily-logs.js +6 -22
- package/src/memory/utils/indexer.js +6 -5
- package/src/memory/utils/sync-engine.js +7 -18
- package/src/utils/audit-queue.js +127 -0
- package/src/utils/colors.js +31 -0
- package/src/utils/context-prefetcher.js +170 -0
- package/src/utils/intelligence-cache.js +114 -0
- package/src/utils/parallel-search.js +130 -0
- package/src/utils/streaming-api.js +168 -0
- package/src/utils/streaming.js +180 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrxkun/mcfast-mcp",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.12",
|
|
4
4
|
"description": "Ultra-fast code editing with WASM acceleration, fuzzy patching, multi-layer caching, and 8 unified tools. Optimized for AI code assistants with 80-98% latency reduction. Phase 4: ML Intelligence Layer.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/index.js
CHANGED
|
@@ -41,6 +41,10 @@ import {
|
|
|
41
41
|
import { safeEdit } from './utils/backup.js';
|
|
42
42
|
import { formatError } from './utils/error-formatter.js';
|
|
43
43
|
import { MemoryEngine } from './memory/index.js';
|
|
44
|
+
import { getAuditQueue } from './utils/audit-queue.js';
|
|
45
|
+
import { getIntelligenceCache } from './utils/intelligence-cache.js';
|
|
46
|
+
import { getContextPrefetcher } from './utils/context-prefetcher.js';
|
|
47
|
+
import { parallelMemorySearch } from './utils/parallel-search.js';
|
|
44
48
|
|
|
45
49
|
const execAsync = promisify(exec);
|
|
46
50
|
|
|
@@ -108,6 +112,62 @@ async function searchMemoryContext(instruction, maxResults = 5) {
|
|
|
108
112
|
}
|
|
109
113
|
}
|
|
110
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Auto-trigger intelligence tools after successful edit
|
|
117
|
+
* Runs async in background to not block user
|
|
118
|
+
*/
|
|
119
|
+
async function autoTriggerIntelligence(filePath, instruction) {
|
|
120
|
+
try {
|
|
121
|
+
// Only trigger if intelligence is enabled
|
|
122
|
+
if (process.env.MCFAST_INTELLIGENCE_AUTO !== 'true') {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const engine = await getMemoryEngine();
|
|
127
|
+
const cache = getIntelligenceCache();
|
|
128
|
+
|
|
129
|
+
// 1. Detect patterns (cached for 5 minutes)
|
|
130
|
+
const patternCacheKey = { file: filePath, type: 'patterns' };
|
|
131
|
+
let patterns = cache.get('patterns', patternCacheKey);
|
|
132
|
+
|
|
133
|
+
if (!patterns) {
|
|
134
|
+
patterns = await engine.detectPatterns();
|
|
135
|
+
if (patterns && patterns.length > 0) {
|
|
136
|
+
cache.set('patterns', patternCacheKey, patterns);
|
|
137
|
+
console.error(`${colors.cyan}[Intelligence]${colors.reset} 💡 Detected ${patterns.length} patterns`);
|
|
138
|
+
|
|
139
|
+
// Log high-confidence patterns
|
|
140
|
+
patterns.filter(p => p.confidence > 0.8).forEach(p => {
|
|
141
|
+
console.error(`${colors.yellow}[Pattern]${colors.reset} ${p.type}: ${p.message}`);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 2. Get suggestions (cached for 5 minutes)
|
|
147
|
+
const suggestionCacheKey = { file: filePath, type: 'suggestions' };
|
|
148
|
+
let suggestions = cache.get('suggestions', suggestionCacheKey);
|
|
149
|
+
|
|
150
|
+
if (!suggestions) {
|
|
151
|
+
suggestions = await engine.getSuggestions({ currentFile: filePath });
|
|
152
|
+
if (suggestions && suggestions.length > 0) {
|
|
153
|
+
cache.set('suggestions', suggestionCacheKey, suggestions);
|
|
154
|
+
console.error(`${colors.cyan}[Intelligence]${colors.reset} 💡 ${suggestions.length} suggestions available`);
|
|
155
|
+
|
|
156
|
+
// Show top suggestions
|
|
157
|
+
suggestions.slice(0, 3).forEach(s => {
|
|
158
|
+
console.error(`${colors.yellow}[Suggestion]${colors.reset} ${s.type}: ${s.message}`);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
} catch (error) {
|
|
164
|
+
// Silent fail - intelligence should not break the tool
|
|
165
|
+
if (VERBOSE) {
|
|
166
|
+
console.error(`${colors.yellow}[Intelligence]${colors.reset} Auto-trigger failed: ${error.message}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
111
171
|
/**
|
|
112
172
|
* Log edit to memory after successful edit
|
|
113
173
|
*/
|
|
@@ -222,6 +282,28 @@ const TOOL_ALIASES = {
|
|
|
222
282
|
'list_files_fast': 'list_files',
|
|
223
283
|
'read_file': 'read',
|
|
224
284
|
'goto_definition': 'search', // redirected
|
|
285
|
+
// VSCode MCP client adds prefixes
|
|
286
|
+
'mcp--mcfast--edit': 'edit',
|
|
287
|
+
'mcp--mcfast--search': 'search',
|
|
288
|
+
'mcp--mcfast--read': 'read',
|
|
289
|
+
'mcp--mcfast--list_files': 'list_files',
|
|
290
|
+
'mcp--mcfast--reapply': 'reapply',
|
|
291
|
+
'mcp--mcfast--memory_search': 'memory_search',
|
|
292
|
+
'mcp--mcfast--memory_get': 'memory_get',
|
|
293
|
+
'mcp--mcfast--detect_patterns': 'detect_patterns',
|
|
294
|
+
'mcp--mcfast--get_suggestions': 'get_suggestions',
|
|
295
|
+
'mcp--mcfast--select_strategy': 'select_strategy',
|
|
296
|
+
// Alternative format with double dashes
|
|
297
|
+
'mcfast_edit': 'edit',
|
|
298
|
+
'mcfast_search': 'search',
|
|
299
|
+
'mcfast_read': 'read',
|
|
300
|
+
'mcfast_list_files': 'list_files',
|
|
301
|
+
'mcfast_reapply': 'reapply',
|
|
302
|
+
'mcfast_memory_search': 'memory_search',
|
|
303
|
+
'mcfast_memory_get': 'memory_get',
|
|
304
|
+
'mcfast_detect_patterns': 'detect_patterns',
|
|
305
|
+
'mcfast_get_suggestions': 'get_suggestions',
|
|
306
|
+
'mcfast_select_strategy': 'select_strategy',
|
|
225
307
|
};
|
|
226
308
|
|
|
227
309
|
/**
|
|
@@ -728,6 +810,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
728
810
|
/**
|
|
729
811
|
* Report audit log to Dashboard
|
|
730
812
|
* Sends operation logs to mcfast Dashboard for monitoring
|
|
813
|
+
* Now uses AuditQueue for batching to reduce HTTP overhead
|
|
731
814
|
*/
|
|
732
815
|
async function reportAudit(data) {
|
|
733
816
|
try {
|
|
@@ -755,42 +838,33 @@ async function reportAudit(data) {
|
|
|
755
838
|
latency_ms: data.latency_ms || 0,
|
|
756
839
|
instruction: data.instruction || '',
|
|
757
840
|
files_count: data.files_count || 0,
|
|
841
|
+
diff_size: data.diff_size || 0, // ✅ Thêm diff_size
|
|
758
842
|
input_tokens: data.input_tokens || 0,
|
|
759
843
|
output_tokens: data.output_tokens || 0,
|
|
760
844
|
strategy: data.strategy || null,
|
|
761
845
|
error: data.error || null,
|
|
846
|
+
error_message: data.error || null, // ✅ Thêm error_message cho server
|
|
847
|
+
result_summary: data.result_summary || null, // ✅ Thêm result_summary
|
|
762
848
|
metadata: data.metadata || {}
|
|
763
849
|
};
|
|
764
850
|
|
|
765
|
-
//
|
|
766
|
-
const
|
|
851
|
+
// Use AuditQueue for batching instead of immediate send
|
|
852
|
+
const queue = getAuditQueue({
|
|
853
|
+
token: TOKEN,
|
|
854
|
+
apiUrl: process.env.MCFAST_DASHBOARD_URL || 'https://mcfast.vercel.app/api/v1/logs/audit',
|
|
855
|
+
batchSize: 5,
|
|
856
|
+
flushInterval: 5000,
|
|
857
|
+
verbose: VERBOSE
|
|
858
|
+
});
|
|
767
859
|
|
|
768
|
-
|
|
769
|
-
console.error(`${colors.dim}[Audit] Sending to: ${DASHBOARD_API_URL}${colors.reset}`);
|
|
770
|
-
console.error(`${colors.dim}[Audit] Tool: ${auditData.tool}, Status: ${auditData.status}${colors.reset}`);
|
|
771
|
-
}
|
|
860
|
+
queue.add(auditData);
|
|
772
861
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
'Content-Type': 'application/json',
|
|
777
|
-
'Authorization': `Bearer ${TOKEN}`
|
|
778
|
-
},
|
|
779
|
-
body: JSON.stringify(auditData)
|
|
780
|
-
});
|
|
781
|
-
|
|
782
|
-
if (!response.ok) {
|
|
783
|
-
const errorText = await response.text().catch(() => 'Unknown error');
|
|
784
|
-
if (VERBOSE) {
|
|
785
|
-
console.error(`${colors.yellow}[Audit] Failed - HTTP ${response.status}: ${errorText}${colors.reset}`);
|
|
786
|
-
}
|
|
787
|
-
} else {
|
|
788
|
-
if (VERBOSE) {
|
|
789
|
-
console.error(`${colors.green}[Audit] Logged successfully ✓${colors.reset}`);
|
|
790
|
-
}
|
|
862
|
+
if (VERBOSE) {
|
|
863
|
+
const stats = queue.getStats();
|
|
864
|
+
console.error(`${colors.dim}[Audit] Queued for batching. Queue size: ${stats.queued}${colors.reset}`);
|
|
791
865
|
}
|
|
792
866
|
|
|
793
|
-
// Also log to local file if configured
|
|
867
|
+
// Also log to local file if configured (immediate)
|
|
794
868
|
if (process.env.MCFAST_AUDIT_FILE) {
|
|
795
869
|
const logLine = JSON.stringify(auditData) + '\n';
|
|
796
870
|
await fs.appendFile(process.env.MCFAST_AUDIT_FILE, logLine).catch((err) => {
|
|
@@ -1055,7 +1129,8 @@ async function handleSearchFilesystem({ query, path: searchPath, isRegex = false
|
|
|
1055
1129
|
lines.forEach((line, idx) => {
|
|
1056
1130
|
if (line.includes(query)) {
|
|
1057
1131
|
matches.push({
|
|
1058
|
-
|
|
1132
|
+
file,
|
|
1133
|
+
lineNumber: idx + 1,
|
|
1059
1134
|
content: line.trim()
|
|
1060
1135
|
});
|
|
1061
1136
|
}
|
|
@@ -1100,7 +1175,7 @@ async function handleSearchFilesystem({ query, path: searchPath, isRegex = false
|
|
|
1100
1175
|
contentMatches.slice(0, 10).forEach(({ file, matches }) => {
|
|
1101
1176
|
output += `\n${colors.yellow}${file}${colors.reset}\n`;
|
|
1102
1177
|
matches.forEach(match => {
|
|
1103
|
-
output += ` ${colors.dim}${match.
|
|
1178
|
+
output += ` ${colors.dim}${match.lineNumber}:${colors.reset} ${match.content}\n`;
|
|
1104
1179
|
});
|
|
1105
1180
|
});
|
|
1106
1181
|
}
|
|
@@ -1631,6 +1706,12 @@ async function handleEdit({ instruction, files, code_edit, dryRun = false }) {
|
|
|
1631
1706
|
durationMs: Date.now() - editStartTime
|
|
1632
1707
|
});
|
|
1633
1708
|
|
|
1709
|
+
// Auto-trigger intelligence tools in background (non-blocking)
|
|
1710
|
+
if (!result.isError) {
|
|
1711
|
+
const firstFile = Object.keys(files)[0];
|
|
1712
|
+
autoTriggerIntelligence(firstFile, instruction).catch(() => {});
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1634
1715
|
return result;
|
|
1635
1716
|
}
|
|
1636
1717
|
|
|
@@ -1864,7 +1945,7 @@ async function handleReadFileInternal({ path: filePath, start_line, end_line, ma
|
|
|
1864
1945
|
} else if (startLine && currentLine >= startLine) {
|
|
1865
1946
|
lines.push(line);
|
|
1866
1947
|
if (max_lines && lines.length >= max_lines) break;
|
|
1867
|
-
} else if (lines.length <
|
|
1948
|
+
} else if (max_lines && lines.length < max_lines) {
|
|
1868
1949
|
lines.push(line);
|
|
1869
1950
|
} else {
|
|
1870
1951
|
break;
|
|
@@ -2155,7 +2236,7 @@ async function handleSearchCode({ query, files, regex = false, caseSensitive = f
|
|
|
2155
2236
|
});
|
|
2156
2237
|
return {
|
|
2157
2238
|
content: [{ type: "text", text: `❌ Search error: ${error.message}` }],
|
|
2158
|
-
isError: true
|
|
2239
|
+
isError: true,
|
|
2159
2240
|
};
|
|
2160
2241
|
}
|
|
2161
2242
|
}
|
|
@@ -2169,7 +2250,7 @@ async function handleSearchCodeAI({ query, files, contextLines = 2 }) {
|
|
|
2169
2250
|
if (!TOKEN) {
|
|
2170
2251
|
return {
|
|
2171
2252
|
content: [{ type: "text", text: "❌ Error: MCFAST_TOKEN is missing. Please set it in your MCP config." }],
|
|
2172
|
-
isError: true
|
|
2253
|
+
isError: true,
|
|
2173
2254
|
};
|
|
2174
2255
|
}
|
|
2175
2256
|
try {
|
|
@@ -2744,13 +2825,14 @@ async function handleMemorySearch({ query, type = 'all', maxResults = 6, minScor
|
|
|
2744
2825
|
score: result.finalScore || result.score
|
|
2745
2826
|
}));
|
|
2746
2827
|
} else {
|
|
2747
|
-
|
|
2748
|
-
|
|
2828
|
+
// Use parallel search for 'all' type - faster!
|
|
2829
|
+
const parallelResult = await parallelMemorySearch(engine, query, maxResults);
|
|
2830
|
+
results = parallelResult.results.map(result => ({
|
|
2749
2831
|
type: 'chunk',
|
|
2750
|
-
content: result.
|
|
2751
|
-
file: result.filePath || result.path,
|
|
2752
|
-
score: result.
|
|
2753
|
-
method:
|
|
2832
|
+
content: result.content || result.code,
|
|
2833
|
+
file: result.file || result.filePath || result.path,
|
|
2834
|
+
score: result._score || result.score || 0.5,
|
|
2835
|
+
method: result._source
|
|
2754
2836
|
}));
|
|
2755
2837
|
}
|
|
2756
2838
|
|
|
@@ -13,7 +13,6 @@ import { DailyLogs } from './utils/daily-logs.js';
|
|
|
13
13
|
import { SyncEngine } from './utils/sync-engine.js';
|
|
14
14
|
import { PatternDetector, SuggestionEngine, StrategySelector } from '../intelligence/index.js';
|
|
15
15
|
import path from 'path';
|
|
16
|
-
import os from 'os';
|
|
17
16
|
|
|
18
17
|
export class MemoryEngine {
|
|
19
18
|
constructor(options = {}) {
|
|
@@ -23,25 +22,19 @@ export class MemoryEngine {
|
|
|
23
22
|
this.projectPath = null;
|
|
24
23
|
this.isInitialized = false;
|
|
25
24
|
|
|
26
|
-
// Memory path
|
|
27
|
-
this.memoryPath = options.memoryPath ||
|
|
25
|
+
// Memory path - now stored in project directory
|
|
26
|
+
this.memoryPath = options.memoryPath || null; // Will be set on initialize
|
|
28
27
|
|
|
29
28
|
// Daily Logs - auto-generated markdown notes
|
|
30
|
-
this.dailyLogs =
|
|
31
|
-
memoryPath: this.memoryPath
|
|
32
|
-
});
|
|
29
|
+
this.dailyLogs = null; // Will be initialized on initialize
|
|
33
30
|
|
|
34
31
|
// Sync Engine - local ↔ cloud (optional, auto-detect from MCFAST_TOKEN)
|
|
35
32
|
this.syncEngine = null;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
baseUrl: options.baseUrl || process.env.MCFAST_DASHBOARD_URL || 'https://mcfast.vercel.app',
|
|
42
|
-
syncInterval: options.syncInterval || 5 * 60 * 1000
|
|
43
|
-
});
|
|
44
|
-
}
|
|
33
|
+
this.syncEngineOptions = {
|
|
34
|
+
apiKey: options.apiKey || process.env.MCFAST_TOKEN,
|
|
35
|
+
baseUrl: options.baseUrl || process.env.MCFAST_DASHBOARD_URL || 'https://mcfast.vercel.app',
|
|
36
|
+
syncInterval: options.syncInterval || 5 * 60 * 1000
|
|
37
|
+
};
|
|
45
38
|
|
|
46
39
|
// Sử dụng UltraEnhancedEmbedder cho 90% accuracy
|
|
47
40
|
this.embedder = new UltraEnhancedEmbedder({
|
|
@@ -69,41 +62,38 @@ export class MemoryEngine {
|
|
|
69
62
|
this.patternDetector = null;
|
|
70
63
|
this.suggestionEngine = null;
|
|
71
64
|
this.strategySelector = null;
|
|
72
|
-
|
|
73
|
-
if (this.intelligenceEnabled) {
|
|
74
|
-
this.patternDetector = new PatternDetector({ db: this.db });
|
|
75
|
-
this.suggestionEngine = new SuggestionEngine({
|
|
76
|
-
db: this.db,
|
|
77
|
-
memoryEngine: this
|
|
78
|
-
});
|
|
79
|
-
this.strategySelector = new StrategySelector({ db: this.db });
|
|
80
|
-
}
|
|
81
65
|
}
|
|
82
66
|
|
|
83
67
|
async initialize(projectPath) {
|
|
84
68
|
if (this.isInitialized) return;
|
|
85
69
|
|
|
86
70
|
this.projectPath = projectPath;
|
|
87
|
-
await this.db.initialize();
|
|
88
71
|
|
|
89
|
-
//
|
|
90
|
-
if (this.
|
|
91
|
-
|
|
92
|
-
console.log('[MemoryEngine] Smart router config loaded');
|
|
72
|
+
// Set memory path to project directory
|
|
73
|
+
if (!this.memoryPath) {
|
|
74
|
+
this.memoryPath = path.join(projectPath, '.mcfast', 'memory');
|
|
93
75
|
}
|
|
94
76
|
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
console.log('[MemoryEngine] ✅ Connected to Dashboard');
|
|
99
|
-
} else {
|
|
100
|
-
console.log('[MemoryEngine] ⚠️ Dashboard connection failed, using offline mode');
|
|
77
|
+
// Update database path if not explicitly set
|
|
78
|
+
if (!this.db.dbPath) {
|
|
79
|
+
this.db.dbPath = path.join(this.memoryPath, 'index.db');
|
|
101
80
|
}
|
|
102
81
|
|
|
82
|
+
await this.db.initialize();
|
|
83
|
+
|
|
84
|
+
// Initialize Daily Logs with project-specific path
|
|
85
|
+
this.dailyLogs = new DailyLogs({
|
|
86
|
+
memoryPath: this.memoryPath
|
|
87
|
+
});
|
|
88
|
+
|
|
103
89
|
// Initialize Sync Engine if configured
|
|
104
|
-
if (this.
|
|
105
|
-
|
|
106
|
-
|
|
90
|
+
if (this.syncEngineOptions.apiKey && this.syncEngineOptions.enableSync !== false) {
|
|
91
|
+
this.syncEngine = new SyncEngine({
|
|
92
|
+
memoryPath: this.memoryPath,
|
|
93
|
+
apiKey: this.syncEngineOptions.apiKey,
|
|
94
|
+
baseUrl: this.syncEngineOptions.baseUrl,
|
|
95
|
+
syncInterval: this.syncEngineOptions.syncInterval
|
|
96
|
+
});
|
|
107
97
|
}
|
|
108
98
|
|
|
109
99
|
this.watcher = new FileWatcher(projectPath, this);
|
|
@@ -114,6 +104,20 @@ export class MemoryEngine {
|
|
|
114
104
|
console.log(`[MemoryEngine] Smart Routing: ${this.smartRoutingEnabled ? 'ENABLED' : 'DISABLED'}`);
|
|
115
105
|
console.log(`[MemoryEngine] Intelligence Layer: ${this.intelligenceEnabled ? 'ENABLED' : 'DISABLED'}`);
|
|
116
106
|
|
|
107
|
+
// Initialize intelligence engines if enabled
|
|
108
|
+
if (this.intelligenceEnabled) {
|
|
109
|
+
try {
|
|
110
|
+
const { PatternDetector, SuggestionEngine, StrategySelector } = await import('../intelligence/index.js');
|
|
111
|
+
this.patternDetector = new PatternDetector({ memoryEngine: this });
|
|
112
|
+
this.suggestionEngine = new SuggestionEngine({ memoryEngine: this });
|
|
113
|
+
this.strategySelector = new StrategySelector({ memoryEngine: this });
|
|
114
|
+
console.log('[MemoryEngine] Intelligence engines initialized');
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.warn('[MemoryEngine] Failed to initialize intelligence engines:', error.message);
|
|
117
|
+
this.intelligenceEnabled = false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
117
121
|
// Load intelligence models
|
|
118
122
|
if (this.intelligenceEnabled) {
|
|
119
123
|
await this.patternDetector.loadModel?.();
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import os from 'os';
|
|
4
3
|
import fs from 'fs/promises';
|
|
5
4
|
|
|
6
5
|
export class MemoryDatabase {
|
|
7
|
-
constructor(dbPath =
|
|
6
|
+
constructor(dbPath = null) {
|
|
8
7
|
this.dbPath = dbPath;
|
|
9
8
|
this.db = null;
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
async initialize() {
|
|
12
|
+
// If dbPath not set, create in current directory
|
|
13
|
+
if (!this.dbPath) {
|
|
14
|
+
this.dbPath = path.join(process.cwd(), '.mcfast', 'memory', 'index.db');
|
|
15
|
+
}
|
|
16
|
+
|
|
13
17
|
await fs.mkdir(path.dirname(this.dbPath), { recursive: true });
|
|
14
18
|
this.db = new Database(this.dbPath);
|
|
15
19
|
this.db.pragma('journal_mode = WAL');
|
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import os from 'os';
|
|
9
8
|
|
|
10
9
|
export class DailyLogs {
|
|
11
10
|
constructor(options = {}) {
|
|
12
|
-
this.memoryPath = options.memoryPath
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
this.memoryPath = options.memoryPath;
|
|
12
|
+
if (!this.memoryPath) {
|
|
13
|
+
throw new Error('memoryPath is required for DailyLogs');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Ensure directory exists
|
|
17
17
|
if (!fs.existsSync(this.memoryPath)) {
|
|
18
18
|
fs.mkdirSync(this.memoryPath, { recursive: true });
|
|
19
19
|
}
|
|
@@ -47,8 +47,6 @@ export class DailyLogs {
|
|
|
47
47
|
* Log a file creation event
|
|
48
48
|
*/
|
|
49
49
|
logFileCreated(filePath, facts = []) {
|
|
50
|
-
this.ensureMemoryDir();
|
|
51
|
-
|
|
52
50
|
const content = [
|
|
53
51
|
`## ${this.formatTime()} - File Created`,
|
|
54
52
|
`**File:** \`${filePath}\``,
|
|
@@ -63,8 +61,6 @@ export class DailyLogs {
|
|
|
63
61
|
* Log a file modification event
|
|
64
62
|
*/
|
|
65
63
|
logFileModified(filePath, changes = {}) {
|
|
66
|
-
this.ensureMemoryDir();
|
|
67
|
-
|
|
68
64
|
const parts = [`**File:** \`${filePath}\``];
|
|
69
65
|
|
|
70
66
|
if (changes.added && changes.added.length > 0) {
|
|
@@ -92,8 +88,6 @@ export class DailyLogs {
|
|
|
92
88
|
* Log a file deletion event
|
|
93
89
|
*/
|
|
94
90
|
logFileDeleted(filePath) {
|
|
95
|
-
this.ensureMemoryDir();
|
|
96
|
-
|
|
97
91
|
const content = [
|
|
98
92
|
`## ${this.formatTime()} - File Deleted`,
|
|
99
93
|
`**File:** \`${filePath}\``,
|
|
@@ -107,8 +101,6 @@ export class DailyLogs {
|
|
|
107
101
|
* Log an edit session
|
|
108
102
|
*/
|
|
109
103
|
logEdit(edit) {
|
|
110
|
-
this.ensureMemoryDir();
|
|
111
|
-
|
|
112
104
|
const {
|
|
113
105
|
instruction,
|
|
114
106
|
files = [],
|
|
@@ -139,8 +131,6 @@ export class DailyLogs {
|
|
|
139
131
|
* Log a search query
|
|
140
132
|
*/
|
|
141
133
|
logSearch(query, resultsCount, duration) {
|
|
142
|
-
this.ensureMemoryDir();
|
|
143
|
-
|
|
144
134
|
const content = [
|
|
145
135
|
`## ${this.formatTime()} - Search`,
|
|
146
136
|
`**Query:** "${query}"`,
|
|
@@ -156,8 +146,6 @@ export class DailyLogs {
|
|
|
156
146
|
* Add a curated memory entry to MEMORY.md
|
|
157
147
|
*/
|
|
158
148
|
addCuratedMemory(title, content, tags = []) {
|
|
159
|
-
this.ensureMemoryDir();
|
|
160
|
-
|
|
161
149
|
const memoryPath = this.getMemoryFilePath();
|
|
162
150
|
const timestamp = new Date().toISOString();
|
|
163
151
|
|
|
@@ -219,8 +207,6 @@ export class DailyLogs {
|
|
|
219
207
|
* Get logs for a date range
|
|
220
208
|
*/
|
|
221
209
|
getLogsInRange(startDate, endDate) {
|
|
222
|
-
this.ensureMemoryDir();
|
|
223
|
-
|
|
224
210
|
const logs = [];
|
|
225
211
|
const files = fs.readdirSync(this.memoryPath)
|
|
226
212
|
.filter(f => f.match(/^\d{4}-\d{2}-\d{2}\.md$/))
|
|
@@ -241,8 +227,6 @@ export class DailyLogs {
|
|
|
241
227
|
* Clean up old logs (keep last N days)
|
|
242
228
|
*/
|
|
243
229
|
cleanupOldLogs(keepDays = 30) {
|
|
244
|
-
this.ensureMemoryDir();
|
|
245
|
-
|
|
246
230
|
const cutoffDate = new Date();
|
|
247
231
|
cutoffDate.setDate(cutoffDate.getDate() - keepDays);
|
|
248
232
|
const cutoffStr = cutoffDate.toISOString().split('T')[0].replace(/-/g, '');
|
|
@@ -7,6 +7,7 @@ import { parse } from '../../strategies/tree-sitter/index.js';
|
|
|
7
7
|
import { detectLanguage } from '../../strategies/syntax-validator.js';
|
|
8
8
|
import { Chunker } from './chunker.js';
|
|
9
9
|
import { Embedder } from './embedder.js';
|
|
10
|
+
import { getQuery } from '../../strategies/tree-sitter/languages.js';
|
|
10
11
|
import crypto from 'crypto';
|
|
11
12
|
|
|
12
13
|
export class CodeIndexer {
|
|
@@ -58,14 +59,14 @@ export class CodeIndexer {
|
|
|
58
59
|
const fileId = this.generateFileId(filePath);
|
|
59
60
|
|
|
60
61
|
try {
|
|
61
|
-
|
|
62
|
-
const
|
|
62
|
+
// Use getQuery to compile the query properly
|
|
63
|
+
const query = await getQuery(language, 'definitions');
|
|
63
64
|
|
|
64
|
-
if (
|
|
65
|
-
const captures =
|
|
65
|
+
if (query) {
|
|
66
|
+
const captures = query.captures(ast.rootNode);
|
|
66
67
|
|
|
67
68
|
for (const capture of captures) {
|
|
68
|
-
if (capture.name === 'name') {
|
|
69
|
+
if (capture.name === 'name' || capture.name === 'function') {
|
|
69
70
|
facts.push({
|
|
70
71
|
id: this.generateFactId(fileId, capture.node.text, 'function'),
|
|
71
72
|
file_id: fileId,
|
|
@@ -6,30 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
import path from 'path';
|
|
9
|
-
import os from 'os';
|
|
10
9
|
import crypto from 'crypto';
|
|
11
10
|
|
|
12
11
|
export class SyncEngine {
|
|
13
12
|
constructor(options = {}) {
|
|
14
|
-
this.memoryPath = options.memoryPath
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this.apiKey = options.apiKey || process.env.MCFAST_TOKEN;
|
|
13
|
+
this.memoryPath = options.memoryPath;
|
|
14
|
+
if (!this.memoryPath) {
|
|
15
|
+
throw new Error('memoryPath is required for SyncEngine');
|
|
16
|
+
}
|
|
19
17
|
|
|
18
|
+
this.apiKey = options.apiKey;
|
|
19
|
+
this.baseUrl = options.baseUrl || 'https://mcfast.vercel.app';
|
|
20
20
|
this.syncInterval = options.syncInterval || 5 * 60 * 1000; // 5 minutes
|
|
21
|
-
this.
|
|
22
|
-
this.syncQueue = [];
|
|
23
|
-
this.isOnline = true;
|
|
24
|
-
this.isSyncing = false;
|
|
25
|
-
this.listeners = new Set();
|
|
26
|
-
|
|
27
|
-
// Check online status
|
|
28
|
-
if (typeof window !== 'undefined') {
|
|
29
|
-
this.isOnline = navigator.onLine;
|
|
30
|
-
window.addEventListener('online', () => this.handleOnline());
|
|
31
|
-
window.addEventListener('offline', () => this.handleOffline());
|
|
32
|
-
}
|
|
21
|
+
this.syncTimer = null;
|
|
33
22
|
}
|
|
34
23
|
|
|
35
24
|
/**
|