@mrxkun/mcfast-mcp 4.0.15 → 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.
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Daily Logs Layer
3
+ * Layer 1: Append-only daily notes
4
+ * File: memory/YYYY-MM-DD.md
5
+ */
6
+
7
+ import fs from 'fs/promises';
8
+ import path from 'path';
9
+
10
+ export class DailyLogs {
11
+ constructor(options = {}) {
12
+ this.memoryPath = options.memoryPath || '.mcfast';
13
+ this.logsDir = path.join(this.memoryPath, 'memory');
14
+ }
15
+
16
+ /**
17
+ * Get today's date string
18
+ */
19
+ getTodayDate() {
20
+ const now = new Date();
21
+ return now.toISOString().split('T')[0]; // YYYY-MM-DD
22
+ }
23
+
24
+ /**
25
+ * Get today's log file path
26
+ */
27
+ getTodayLogPath() {
28
+ return path.join(this.logsDir, `${this.getTodayDate()}.md`);
29
+ }
30
+
31
+ /**
32
+ * Get yesterday's log file path
33
+ */
34
+ getYesterdayLogPath() {
35
+ const yesterday = new Date();
36
+ yesterday.setDate(yesterday.getDate() - 1);
37
+ const dateStr = yesterday.toISOString().split('T')[0];
38
+ return path.join(this.logsDir, `${dateStr}.md`);
39
+ }
40
+
41
+ /**
42
+ * Ensure logs directory exists
43
+ */
44
+ async ensureDirectory() {
45
+ await fs.mkdir(this.logsDir, { recursive: true });
46
+ }
47
+
48
+ /**
49
+ * Log an entry to today's file
50
+ * @param {string} title - Entry title
51
+ * @param {string} content - Entry content
52
+ * @param {Object} metadata - Optional metadata
53
+ */
54
+ async log(title, content, metadata = {}) {
55
+ await this.ensureDirectory();
56
+
57
+ const logPath = this.getTodayLogPath();
58
+ const timestamp = new Date().toLocaleTimeString('en-US', {
59
+ hour: '2-digit',
60
+ minute: '2-digit',
61
+ hour12: true
62
+ });
63
+
64
+ let entry = `\n## ${timestamp} - ${title}\n\n${content}\n`;
65
+
66
+ // Add metadata if provided
67
+ if (Object.keys(metadata).length > 0) {
68
+ entry += '\n**Metadata:**\n';
69
+ for (const [key, value] of Object.entries(metadata)) {
70
+ entry += `- ${key}: ${value}\n`;
71
+ }
72
+ }
73
+
74
+ entry += '\n---\n';
75
+
76
+ // Check if file exists
77
+ let fileContent = '';
78
+ try {
79
+ fileContent = await fs.readFile(logPath, 'utf-8');
80
+ } catch (error) {
81
+ // File doesn't exist, create header
82
+ fileContent = `# Daily Log - ${this.getTodayDate()}\n\n`;
83
+ }
84
+
85
+ // Append entry
86
+ await fs.writeFile(logPath, fileContent + entry);
87
+
88
+ console.log(`[DailyLogs] Logged: "${title}" to ${logPath}`);
89
+ return logPath;
90
+ }
91
+
92
+ /**
93
+ * Log file creation event
94
+ */
95
+ async logFileCreated(filePath, facts = []) {
96
+ const factNames = facts.map(f => f.name).join(', ');
97
+ const content = facts.length > 0
98
+ ? `Created file with ${facts.length} symbols: ${factNames}`
99
+ : 'Created new file';
100
+
101
+ return this.log('File Created', content, {
102
+ file: filePath,
103
+ symbols: facts.length,
104
+ factNames
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Log file modification event
110
+ */
111
+ async logFileModified(filePath, changes = {}) {
112
+ const { linesAdded = 0, linesRemoved = 0, facts = [] } = changes;
113
+
114
+ let content = `Modified file`;
115
+ if (linesAdded > 0 || linesRemoved > 0) {
116
+ content += ` (+${linesAdded}/-${linesRemoved} lines)`;
117
+ }
118
+ if (facts.length > 0) {
119
+ content += `\nUpdated symbols: ${facts.map(f => f.name).join(', ')}`;
120
+ }
121
+
122
+ return this.log('File Modified', content, {
123
+ file: filePath,
124
+ linesAdded,
125
+ linesRemoved,
126
+ facts: facts.length
127
+ });
128
+ }
129
+
130
+ /**
131
+ * Log file deletion event
132
+ */
133
+ async logFileDeleted(filePath) {
134
+ return this.log('File Deleted', `Deleted file: ${filePath}`, {
135
+ file: filePath
136
+ });
137
+ }
138
+
139
+ /**
140
+ * Log an edit session
141
+ */
142
+ async logEdit(edit) {
143
+ const { instruction, files, strategy, success } = edit;
144
+
145
+ let content = `**Instruction:** ${instruction}\n\n`;
146
+ if (files && files.length > 0) {
147
+ content += `**Files:** ${files.join(', ')}\n\n`;
148
+ }
149
+ if (strategy) {
150
+ content += `**Strategy:** ${strategy}\n\n`;
151
+ }
152
+ content += `**Success:** ${success ? '✅' : '❌'}`;
153
+
154
+ return this.log('Edit Session', content, {
155
+ files: files?.length || 0,
156
+ strategy,
157
+ success
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Read today's log
163
+ */
164
+ async getTodayLog() {
165
+ const logPath = this.getTodayLogPath();
166
+ try {
167
+ return await fs.readFile(logPath, 'utf-8');
168
+ } catch (error) {
169
+ return null;
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Read yesterday's log
175
+ */
176
+ async getYesterdayLog() {
177
+ const logPath = this.getYesterdayLogPath();
178
+ try {
179
+ return await fs.readFile(logPath, 'utf-8');
180
+ } catch (error) {
181
+ return null;
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Get recent logs (last N days)
187
+ */
188
+ async getRecentLogs(days = 7) {
189
+ const logs = [];
190
+
191
+ for (let i = 0; i < days; i++) {
192
+ const date = new Date();
193
+ date.setDate(date.getDate() - i);
194
+ const dateStr = date.toISOString().split('T')[0];
195
+ const logPath = path.join(this.logsDir, `${dateStr}.md`);
196
+
197
+ try {
198
+ const content = await fs.readFile(logPath, 'utf-8');
199
+ logs.push({ date: dateStr, content });
200
+ } catch (error) {
201
+ // File doesn't exist, skip
202
+ }
203
+ }
204
+
205
+ return logs;
206
+ }
207
+
208
+ /**
209
+ * Get all log files
210
+ */
211
+ async getAllLogs() {
212
+ try {
213
+ const files = await fs.readdir(this.logsDir);
214
+ return files
215
+ .filter(f => f.endsWith('.md'))
216
+ .sort()
217
+ .reverse();
218
+ } catch (error) {
219
+ return [];
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Check if today's log exists
225
+ */
226
+ async hasTodayLog() {
227
+ try {
228
+ await fs.access(this.getTodayLogPath());
229
+ return true;
230
+ } catch {
231
+ return false;
232
+ }
233
+ }
234
+ }
235
+
236
+ export default DailyLogs;