@mrxkun/mcfast-mcp 4.0.14 → 4.1.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.
- package/package.json +2 -2
- package/src/memory/bootstrap/agents-md.js +173 -0
- package/src/memory/index.js +26 -13
- package/src/memory/layers/curated-memory.js +324 -0
- package/src/memory/layers/daily-logs.js +236 -0
- package/src/memory/memory-engine.js +472 -452
- package/src/memory/stores/codebase-database.js +418 -0
- package/src/memory/stores/memory-database.js +425 -0
- package/src/memory/utils/markdown-chunker.js +242 -0
- package/src/memory/watchers/file-watcher.js +286 -20
- package/src/tools/memory_get.js +139 -100
- package/src/tools/memory_search.js +118 -86
package/src/tools/memory_get.js
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* memory_get Tool
|
|
3
|
-
* Read content from memory storage using MemoryEngine
|
|
4
|
-
*
|
|
2
|
+
* memory_get Tool v3.0
|
|
3
|
+
* Read content from memory storage using MemoryEngine v4.1.0
|
|
4
|
+
* Supports: Two-tier memory (daily logs + curated), AGENTS.md
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import fs from 'fs/promises';
|
|
8
8
|
import path from 'path';
|
|
9
|
-
import os from 'os';
|
|
10
9
|
import { MemoryEngine } from '../memory/index.js';
|
|
11
10
|
|
|
12
11
|
// Memory engine instance (initialized lazily)
|
|
13
12
|
let memoryEngine = null;
|
|
13
|
+
let enginePromise = null;
|
|
14
14
|
|
|
15
15
|
async function getMemoryEngine() {
|
|
16
|
-
if (
|
|
16
|
+
if (memoryEngine) return memoryEngine;
|
|
17
|
+
if (enginePromise) return enginePromise;
|
|
18
|
+
|
|
19
|
+
enginePromise = (async () => {
|
|
17
20
|
memoryEngine = new MemoryEngine({
|
|
18
21
|
apiKey: process.env.MCFAST_TOKEN,
|
|
19
22
|
enableSync: true
|
|
20
23
|
});
|
|
21
24
|
await memoryEngine.initialize(process.cwd());
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
return memoryEngine;
|
|
26
|
+
})();
|
|
27
|
+
|
|
28
|
+
return enginePromise;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
/**
|
|
27
32
|
* Execute memory get
|
|
28
33
|
* @param {Object} args - Tool arguments
|
|
29
|
-
* @param {string} args.path - Path to memory file
|
|
34
|
+
* @param {string} args.path - Path to memory file
|
|
30
35
|
* @param {number} [args.from=1] - Start line
|
|
31
36
|
* @param {number} [args.lines=50] - Number of lines to read
|
|
32
37
|
* @returns {Promise<Object>} File content
|
|
@@ -50,43 +55,48 @@ export async function execute(args) {
|
|
|
50
55
|
|
|
51
56
|
try {
|
|
52
57
|
// Special paths
|
|
53
|
-
if (relativePath === '
|
|
54
|
-
return await
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (relativePath === 'stats' || relativePath === 'memory/stats') {
|
|
58
|
-
return await getMemoryStats();
|
|
58
|
+
if (relativePath === 'agents' || relativePath === 'AGENTS.md') {
|
|
59
|
+
return await getAgentsMd();
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
if (relativePath === 'today' || relativePath === 'memory/today') {
|
|
62
63
|
return await getTodayLog();
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
if (relativePath === '
|
|
66
|
-
return await
|
|
66
|
+
if (relativePath === 'yesterday' || relativePath === 'memory/yesterday') {
|
|
67
|
+
return await getYesterdayLog();
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}],
|
|
76
|
-
isError: true
|
|
77
|
-
};
|
|
70
|
+
if (relativePath === 'curated' || relativePath === 'MEMORY.md') {
|
|
71
|
+
return await getCuratedMemory();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (relativePath === 'stats' || relativePath === 'memory/stats') {
|
|
75
|
+
return await getMemoryStats();
|
|
78
76
|
}
|
|
79
77
|
|
|
78
|
+
// Regular file path - resolve relative to project
|
|
79
|
+
const projectPath = process.cwd();
|
|
80
|
+
const mcfastPath = path.join(projectPath, '.mcfast');
|
|
81
|
+
|
|
80
82
|
// Construct full path
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
let fullPath;
|
|
84
|
+
if (relativePath.startsWith('/')) {
|
|
85
|
+
fullPath = relativePath;
|
|
86
|
+
} else if (relativePath.startsWith('memory/')) {
|
|
87
|
+
fullPath = path.join(mcfastPath, relativePath);
|
|
88
|
+
} else if (relativePath.startsWith('.mcfast/')) {
|
|
89
|
+
fullPath = path.join(projectPath, relativePath);
|
|
90
|
+
} else {
|
|
91
|
+
fullPath = path.join(mcfastPath, relativePath);
|
|
92
|
+
}
|
|
83
93
|
|
|
84
|
-
// Security: Ensure path is within
|
|
85
|
-
if (!fullPath.startsWith(
|
|
94
|
+
// Security: Ensure path is within .mcfast directory
|
|
95
|
+
if (!fullPath.startsWith(mcfastPath)) {
|
|
86
96
|
return {
|
|
87
97
|
content: [{
|
|
88
98
|
type: "text",
|
|
89
|
-
text: "❌ Error: Path
|
|
99
|
+
text: "❌ Error: Path must be within .mcfast directory"
|
|
90
100
|
}],
|
|
91
101
|
isError: true
|
|
92
102
|
};
|
|
@@ -108,7 +118,7 @@ export async function execute(args) {
|
|
|
108
118
|
return {
|
|
109
119
|
content: [{
|
|
110
120
|
type: "text",
|
|
111
|
-
text: `❌ File not found: ${relativePath}
|
|
121
|
+
text: `❌ File not found: ${relativePath}\n\nTip: Use 'memory_search' to find available files.`
|
|
112
122
|
}],
|
|
113
123
|
isError: true
|
|
114
124
|
};
|
|
@@ -125,11 +135,16 @@ export async function execute(args) {
|
|
|
125
135
|
const extractedContent = extractedLines.join('\n');
|
|
126
136
|
|
|
127
137
|
// Format output
|
|
128
|
-
let output = `📄
|
|
138
|
+
let output = `📄 ${path.basename(fullPath)}\n`;
|
|
139
|
+
output += `Path: ${relativePath}\n`;
|
|
129
140
|
output += `Lines: ${startLine}-${endLine} of ${allLines.length}\n`;
|
|
130
|
-
output += '─'.repeat(40) + '\n';
|
|
141
|
+
output += '─'.repeat(40) + '\n\n';
|
|
131
142
|
output += extractedContent;
|
|
132
143
|
|
|
144
|
+
if (endLine < allLines.length) {
|
|
145
|
+
output += `\n\n... (${allLines.length - endLine} more lines)`;
|
|
146
|
+
}
|
|
147
|
+
|
|
133
148
|
return {
|
|
134
149
|
content: [{
|
|
135
150
|
type: "text",
|
|
@@ -138,7 +153,9 @@ export async function execute(args) {
|
|
|
138
153
|
metadata: {
|
|
139
154
|
path: relativePath,
|
|
140
155
|
lines: extractedLines.length,
|
|
141
|
-
totalLines: allLines.length
|
|
156
|
+
totalLines: allLines.length,
|
|
157
|
+
from: startLine,
|
|
158
|
+
to: endLine
|
|
142
159
|
}
|
|
143
160
|
};
|
|
144
161
|
} catch (error) {
|
|
@@ -153,19 +170,47 @@ export async function execute(args) {
|
|
|
153
170
|
}
|
|
154
171
|
}
|
|
155
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Get AGENTS.md content
|
|
175
|
+
*/
|
|
176
|
+
async function getAgentsMd() {
|
|
177
|
+
try {
|
|
178
|
+
const projectPath = process.cwd();
|
|
179
|
+
const agentsPath = path.join(projectPath, '.mcfast', 'AGENTS.md');
|
|
180
|
+
|
|
181
|
+
const content = await fs.readFile(agentsPath, 'utf8');
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
content: [{
|
|
185
|
+
type: "text",
|
|
186
|
+
text: `📋 Agent Instructions (AGENTS.md)\n\n${content}`
|
|
187
|
+
}],
|
|
188
|
+
metadata: { path: 'AGENTS.md' }
|
|
189
|
+
};
|
|
190
|
+
} catch (error) {
|
|
191
|
+
return {
|
|
192
|
+
content: [{
|
|
193
|
+
type: "text",
|
|
194
|
+
text: "❌ AGENTS.md not found. Run initialization first."
|
|
195
|
+
}],
|
|
196
|
+
isError: true
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
156
201
|
/**
|
|
157
202
|
* Get today's daily log
|
|
158
203
|
*/
|
|
159
204
|
async function getTodayLog() {
|
|
160
205
|
try {
|
|
161
206
|
const engine = await getMemoryEngine();
|
|
162
|
-
const todayLog = engine.getTodayLog();
|
|
207
|
+
const todayLog = await engine.getTodayLog();
|
|
163
208
|
|
|
164
|
-
if (!todayLog
|
|
209
|
+
if (!todayLog) {
|
|
165
210
|
return {
|
|
166
211
|
content: [{
|
|
167
212
|
type: "text",
|
|
168
|
-
text: "📝 No activity logged today"
|
|
213
|
+
text: "📝 No activity logged today\n\nToday's log will be created when events are recorded."
|
|
169
214
|
}],
|
|
170
215
|
metadata: { empty: true }
|
|
171
216
|
};
|
|
@@ -179,7 +224,8 @@ async function getTodayLog() {
|
|
|
179
224
|
content: [{
|
|
180
225
|
type: "text",
|
|
181
226
|
text: output
|
|
182
|
-
}]
|
|
227
|
+
}],
|
|
228
|
+
metadata: { path: 'memory/YYYY-MM-DD.md' }
|
|
183
229
|
};
|
|
184
230
|
} catch (error) {
|
|
185
231
|
return {
|
|
@@ -193,44 +239,39 @@ async function getTodayLog() {
|
|
|
193
239
|
}
|
|
194
240
|
|
|
195
241
|
/**
|
|
196
|
-
* Get
|
|
242
|
+
* Get yesterday's daily log
|
|
197
243
|
*/
|
|
198
|
-
async function
|
|
244
|
+
async function getYesterdayLog() {
|
|
199
245
|
try {
|
|
200
246
|
const engine = await getMemoryEngine();
|
|
201
|
-
const
|
|
247
|
+
const yesterdayLog = await engine.getYesterdayLog();
|
|
202
248
|
|
|
203
|
-
if (!
|
|
249
|
+
if (!yesterdayLog) {
|
|
204
250
|
return {
|
|
205
251
|
content: [{
|
|
206
252
|
type: "text",
|
|
207
|
-
text: "📝 No
|
|
253
|
+
text: "📝 No activity logged yesterday"
|
|
208
254
|
}],
|
|
209
255
|
metadata: { empty: true }
|
|
210
256
|
};
|
|
211
257
|
}
|
|
212
258
|
|
|
213
|
-
let output =
|
|
214
|
-
output += `Found: ${memories.length} memory(s)\n`;
|
|
259
|
+
let output = `📅 Yesterday's Activity Log\n`;
|
|
215
260
|
output += '─'.repeat(40) + '\n\n';
|
|
216
|
-
|
|
217
|
-
memories.forEach((memory, idx) => {
|
|
218
|
-
output += `[${idx + 1}] ${memory.title}\n`;
|
|
219
|
-
output += `Tags: ${memory.tags?.join(', ') || 'none'}\n`;
|
|
220
|
-
output += `${memory.content?.substring(0, 200) || ''}...\n\n`;
|
|
221
|
-
});
|
|
261
|
+
output += yesterdayLog;
|
|
222
262
|
|
|
223
263
|
return {
|
|
224
264
|
content: [{
|
|
225
265
|
type: "text",
|
|
226
266
|
text: output
|
|
227
|
-
}]
|
|
267
|
+
}],
|
|
268
|
+
metadata: { path: 'memory/YYYY-MM-DD.md' }
|
|
228
269
|
};
|
|
229
270
|
} catch (error) {
|
|
230
271
|
return {
|
|
231
272
|
content: [{
|
|
232
273
|
type: "text",
|
|
233
|
-
text: `❌ Error getting
|
|
274
|
+
text: `❌ Error getting yesterday's log: ${error.message}`
|
|
234
275
|
}],
|
|
235
276
|
isError: true
|
|
236
277
|
};
|
|
@@ -238,58 +279,41 @@ async function getCuratedMemories() {
|
|
|
238
279
|
}
|
|
239
280
|
|
|
240
281
|
/**
|
|
241
|
-
* Get memory
|
|
282
|
+
* Get curated memory (MEMORY.md)
|
|
242
283
|
*/
|
|
243
|
-
async function
|
|
244
|
-
const memoryDir = path.join(os.homedir(), '.mcfast', 'memory');
|
|
245
|
-
const logsDir = path.join(memoryDir, 'logs');
|
|
246
|
-
|
|
284
|
+
async function getCuratedMemory() {
|
|
247
285
|
try {
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
.reverse();
|
|
253
|
-
|
|
254
|
-
if (logFiles.length === 0) {
|
|
286
|
+
const engine = await getMemoryEngine();
|
|
287
|
+
const content = await engine.getCuratedMemory();
|
|
288
|
+
|
|
289
|
+
if (!content) {
|
|
255
290
|
return {
|
|
256
291
|
content: [{
|
|
257
292
|
type: "text",
|
|
258
|
-
text: "
|
|
293
|
+
text: "📚 MEMORY.md\n\nNo curated memory found. This file stores long-term knowledge."
|
|
259
294
|
}],
|
|
260
295
|
metadata: { empty: true }
|
|
261
296
|
};
|
|
262
297
|
}
|
|
263
298
|
|
|
264
|
-
|
|
265
|
-
let output = `📝 Memory Logs\n`;
|
|
266
|
-
output += `Found: ${logFiles.length} log file(s)\n`;
|
|
299
|
+
let output = `📚 Curated Memory (MEMORY.md)\n`;
|
|
267
300
|
output += '─'.repeat(40) + '\n\n';
|
|
268
|
-
|
|
269
|
-
const filesToRead = logFiles.slice(0, 5);
|
|
270
|
-
for (const file of filesToRead) {
|
|
271
|
-
const filePath = path.join(logsDir, file);
|
|
272
|
-
const content = await fs.readFile(filePath, 'utf8');
|
|
273
|
-
const fileLines = content.split('\n').slice(0, 20);
|
|
274
|
-
|
|
275
|
-
output += `📅 ${file.replace('.md', '')}\n`;
|
|
276
|
-
output += fileLines.join('\n');
|
|
277
|
-
output += '\n\n---\n\n';
|
|
278
|
-
}
|
|
301
|
+
output += content;
|
|
279
302
|
|
|
280
303
|
return {
|
|
281
304
|
content: [{
|
|
282
305
|
type: "text",
|
|
283
306
|
text: output
|
|
284
|
-
}]
|
|
307
|
+
}],
|
|
308
|
+
metadata: { path: 'MEMORY.md' }
|
|
285
309
|
};
|
|
286
|
-
} catch (
|
|
310
|
+
} catch (error) {
|
|
287
311
|
return {
|
|
288
312
|
content: [{
|
|
289
313
|
type: "text",
|
|
290
|
-
text:
|
|
314
|
+
text: `❌ Error getting curated memory: ${error.message}`
|
|
291
315
|
}],
|
|
292
|
-
|
|
316
|
+
isError: true
|
|
293
317
|
};
|
|
294
318
|
}
|
|
295
319
|
}
|
|
@@ -301,25 +325,40 @@ async function getMemoryStats() {
|
|
|
301
325
|
try {
|
|
302
326
|
const engine = await getMemoryEngine();
|
|
303
327
|
const stats = engine.getStats();
|
|
304
|
-
const syncStatus = engine.getSyncStatus();
|
|
305
|
-
|
|
306
|
-
let output = `📊 Memory Statistics\n`;
|
|
307
|
-
output += '─'.repeat(40) + '\n';
|
|
308
|
-
output += `Indexed Files: ${stats.files || 0}\n`;
|
|
309
|
-
output += `Facts Stored: ${stats.facts || 0}\n`;
|
|
310
|
-
output += `Code Chunks: ${stats.chunks || 0}\n`;
|
|
311
|
-
output += `Embeddings: ${stats.embeddings || 0}\n`;
|
|
312
|
-
output += `Edit History: ${stats.edits || 0}\n\n`;
|
|
313
328
|
|
|
314
|
-
output
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
329
|
+
let output = `📊 Memory System Statistics\n`;
|
|
330
|
+
output += '─'.repeat(40) + '\n\n';
|
|
331
|
+
|
|
332
|
+
// Memory stats
|
|
333
|
+
output += `📝 Memory Index\n`;
|
|
334
|
+
output += ` Files: ${stats.memory?.files || 0}\n`;
|
|
335
|
+
output += ` Chunks: ${stats.memory?.chunks || 0}\n`;
|
|
336
|
+
output += ` Embeddings: ${stats.memory?.embeddings || 0}\n\n`;
|
|
337
|
+
|
|
338
|
+
// Codebase stats
|
|
339
|
+
output += `💻 Codebase Index\n`;
|
|
340
|
+
output += ` Files: ${stats.codebase?.files || 0}\n`;
|
|
341
|
+
output += ` Facts: ${stats.codebase?.facts || 0}\n`;
|
|
342
|
+
output += ` Chunks: ${stats.codebase?.chunks || 0}\n`;
|
|
343
|
+
output += ` Embeddings: ${stats.codebase?.embeddings || 0}\n`;
|
|
344
|
+
output += ` Edits: ${stats.codebase?.edits || 0}\n\n`;
|
|
345
|
+
|
|
346
|
+
// Indexing status
|
|
347
|
+
if (stats.indexing?.is_complete !== undefined) {
|
|
348
|
+
output += `🔄 Indexing\n`;
|
|
349
|
+
output += ` Complete: ${stats.indexing.is_complete ? '✅' : '⏳'}\n`;
|
|
350
|
+
output += ` Indexed: ${stats.indexing.indexed_files || 0}/${stats.indexing.total_files || 0}\n`;
|
|
351
|
+
output += ` Failed: ${stats.indexing.failed_files || 0}\n\n`;
|
|
319
352
|
}
|
|
320
353
|
|
|
321
|
-
|
|
322
|
-
|
|
354
|
+
// Sync status
|
|
355
|
+
const syncStatus = engine.getSyncStatus();
|
|
356
|
+
output += `☁️ Sync\n`;
|
|
357
|
+
output += ` Enabled: ${syncStatus.enabled ? '✅' : '❌'}\n`;
|
|
358
|
+
if (syncStatus.enabled) {
|
|
359
|
+
output += ` Status: ${syncStatus.status || 'unknown'}\n`;
|
|
360
|
+
output += ` Pending: ${syncStatus.pendingChanges || 0}\n`;
|
|
361
|
+
}
|
|
323
362
|
|
|
324
363
|
return {
|
|
325
364
|
content: [{
|