@brutalist/mcp 0.5.1 → 0.6.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 +65 -63
- package/dist/brutalist-server.d.ts +15 -0
- package/dist/brutalist-server.d.ts.map +1 -1
- package/dist/brutalist-server.js +405 -357
- package/dist/brutalist-server.js.map +1 -1
- package/dist/cli-agents.d.ts +8 -3
- package/dist/cli-agents.d.ts.map +1 -1
- package/dist/cli-agents.js +352 -50
- package/dist/cli-agents.js.map +1 -1
- package/dist/streaming/circuit-breaker.d.ts +186 -0
- package/dist/streaming/circuit-breaker.d.ts.map +1 -0
- package/dist/streaming/circuit-breaker.js +463 -0
- package/dist/streaming/circuit-breaker.js.map +1 -0
- package/dist/streaming/intelligent-buffer.d.ts +141 -0
- package/dist/streaming/intelligent-buffer.d.ts.map +1 -0
- package/dist/streaming/intelligent-buffer.js +555 -0
- package/dist/streaming/intelligent-buffer.js.map +1 -0
- package/dist/streaming/output-parser.d.ts +89 -0
- package/dist/streaming/output-parser.d.ts.map +1 -0
- package/dist/streaming/output-parser.js +349 -0
- package/dist/streaming/output-parser.js.map +1 -0
- package/dist/streaming/progress-tracker.d.ts +149 -0
- package/dist/streaming/progress-tracker.d.ts.map +1 -0
- package/dist/streaming/progress-tracker.js +519 -0
- package/dist/streaming/progress-tracker.js.map +1 -0
- package/dist/streaming/session-manager.d.ts +238 -0
- package/dist/streaming/session-manager.d.ts.map +1 -0
- package/dist/streaming/session-manager.js +546 -0
- package/dist/streaming/session-manager.js.map +1 -0
- package/dist/streaming/sse-transport.d.ts +95 -0
- package/dist/streaming/sse-transport.d.ts.map +1 -0
- package/dist/streaming/sse-transport.js +319 -0
- package/dist/streaming/sse-transport.js.map +1 -0
- package/dist/streaming/streaming-orchestrator.d.ts +153 -0
- package/dist/streaming/streaming-orchestrator.d.ts.map +1 -0
- package/dist/streaming/streaming-orchestrator.js +436 -0
- package/dist/streaming/streaming-orchestrator.js.map +1 -0
- package/dist/test-utils/process-manager.d.ts +61 -0
- package/dist/test-utils/process-manager.d.ts.map +1 -0
- package/dist/test-utils/process-manager.js +262 -0
- package/dist/test-utils/process-manager.js.map +1 -0
- package/dist/test-utils/server-harness.d.ts +73 -0
- package/dist/test-utils/server-harness.d.ts.map +1 -0
- package/dist/test-utils/server-harness.js +296 -0
- package/dist/test-utils/server-harness.js.map +1 -0
- package/dist/test-utils/streaming-fuzz.d.ts +57 -0
- package/dist/test-utils/streaming-fuzz.d.ts.map +1 -0
- package/dist/test-utils/streaming-fuzz.js +287 -0
- package/dist/test-utils/streaming-fuzz.js.map +1 -0
- package/dist/test-utils/test-isolation.d.ts +70 -0
- package/dist/test-utils/test-isolation.d.ts.map +1 -0
- package/dist/test-utils/test-isolation.js +193 -0
- package/dist/test-utils/test-isolation.js.map +1 -0
- package/dist/tool-definitions.d.ts +6 -0
- package/dist/tool-definitions.d.ts.map +1 -0
- package/dist/tool-definitions.js +217 -0
- package/dist/tool-definitions.js.map +1 -0
- package/dist/types/brutalist.d.ts +3 -19
- package/dist/types/brutalist.d.ts.map +1 -1
- package/dist/types/tool-config.d.ts +51 -0
- package/dist/types/tool-config.d.ts.map +1 -0
- package/dist/types/tool-config.js +24 -0
- package/dist/types/tool-config.js.map +1 -0
- package/dist/utils/pagination.d.ts +2 -2
- package/dist/utils/pagination.d.ts.map +1 -1
- package/dist/utils/pagination.js +1 -1
- package/dist/utils/pagination.js.map +1 -1
- package/dist/utils/response-cache.d.ts +96 -0
- package/dist/utils/response-cache.d.ts.map +1 -0
- package/dist/utils/response-cache.js +371 -0
- package/dist/utils/response-cache.js.map +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +22 -3
- package/dist/utils.js.map +1 -1
- package/package.json +14 -4
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'crypto';
|
|
2
|
+
import { gzip, gunzip } from 'zlib';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import { logger } from '../logger.js';
|
|
5
|
+
const gzipAsync = promisify(gzip);
|
|
6
|
+
const gunzipAsync = promisify(gunzip);
|
|
7
|
+
/**
|
|
8
|
+
* LRU Response Cache with TTL and memory management
|
|
9
|
+
*/
|
|
10
|
+
export class ResponseCache {
|
|
11
|
+
entries = new Map();
|
|
12
|
+
analysisIdMap = new Map(); // NEW: ID to cache mapping
|
|
13
|
+
accessOrder = [];
|
|
14
|
+
stats = {
|
|
15
|
+
entries: 0,
|
|
16
|
+
totalSize: 0,
|
|
17
|
+
hits: 0,
|
|
18
|
+
misses: 0,
|
|
19
|
+
evictions: 0
|
|
20
|
+
};
|
|
21
|
+
// Configuration
|
|
22
|
+
maxEntries;
|
|
23
|
+
ttlMs;
|
|
24
|
+
maxTotalSizeMB;
|
|
25
|
+
maxEntrySizeMB;
|
|
26
|
+
compressionThresholdMB;
|
|
27
|
+
cleanupTimer;
|
|
28
|
+
constructor(options = {}) {
|
|
29
|
+
this.maxEntries = options.maxEntries || 50;
|
|
30
|
+
this.ttlMs = (options.ttlHours || 2) * 60 * 60 * 1000; // Convert hours to ms
|
|
31
|
+
this.maxTotalSizeMB = options.maxTotalSizeMB || 500;
|
|
32
|
+
this.maxEntrySizeMB = options.maxEntrySizeMB || 10;
|
|
33
|
+
this.compressionThresholdMB = options.compressionThresholdMB || 1;
|
|
34
|
+
// Log configuration
|
|
35
|
+
logger.info(`📦 ResponseCache initialized:`, {
|
|
36
|
+
maxEntries: this.maxEntries,
|
|
37
|
+
ttlHours: this.ttlMs / (1000 * 60 * 60),
|
|
38
|
+
maxTotalSizeMB: this.maxTotalSizeMB,
|
|
39
|
+
maxEntrySizeMB: this.maxEntrySizeMB,
|
|
40
|
+
compressionThresholdMB: this.compressionThresholdMB
|
|
41
|
+
});
|
|
42
|
+
// Periodic cleanup
|
|
43
|
+
this.cleanupTimer = setInterval(() => this.cleanupExpired(), 5 * 60 * 1000); // Every 5 minutes
|
|
44
|
+
// Allow Node to exit even if timer is active
|
|
45
|
+
this.cleanupTimer.unref();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Generate cache key from request parameters
|
|
49
|
+
*/
|
|
50
|
+
generateCacheKey(params) {
|
|
51
|
+
// Create deterministic string from params
|
|
52
|
+
const sortedParams = Object.keys(params)
|
|
53
|
+
.sort()
|
|
54
|
+
.reduce((acc, key) => {
|
|
55
|
+
if (params[key] !== undefined && key !== 'analysis_id' && key !== 'offset' && key !== 'limit' && key !== 'cursor' && key !== 'force_refresh') {
|
|
56
|
+
acc[key] = params[key];
|
|
57
|
+
}
|
|
58
|
+
return acc;
|
|
59
|
+
}, {});
|
|
60
|
+
const paramString = JSON.stringify(sortedParams);
|
|
61
|
+
const hash = createHash('sha256').update(paramString).digest('hex');
|
|
62
|
+
return hash;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Generate secure analysis ID (UUID instead of 8-char hash)
|
|
66
|
+
*/
|
|
67
|
+
generateAnalysisId(cacheKey) {
|
|
68
|
+
return randomUUID(); // Full UUID for security
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Store response with session binding
|
|
72
|
+
*/
|
|
73
|
+
async set(data, content, cacheKey, sessionId, requestId) {
|
|
74
|
+
const finalCacheKey = cacheKey || this.generateCacheKey(data);
|
|
75
|
+
const analysisId = this.generateAnalysisId(finalCacheKey);
|
|
76
|
+
// Check size limits before compression
|
|
77
|
+
const sizeInMB = Buffer.byteLength(content, 'utf8') / (1024 * 1024);
|
|
78
|
+
if (sizeInMB > this.maxEntrySizeMB) {
|
|
79
|
+
throw new Error(`Response too large: ${sizeInMB.toFixed(2)}MB > ${this.maxEntrySizeMB}MB limit`);
|
|
80
|
+
}
|
|
81
|
+
// Compress if needed
|
|
82
|
+
let finalContent = content;
|
|
83
|
+
let compressed = false;
|
|
84
|
+
if (sizeInMB > this.compressionThresholdMB) {
|
|
85
|
+
try {
|
|
86
|
+
const compressedBuffer = await gzipAsync(Buffer.from(content, 'utf8'));
|
|
87
|
+
finalContent = compressedBuffer.toString('base64');
|
|
88
|
+
compressed = true;
|
|
89
|
+
logger.debug(`📦 Compressed cache entry: ${sizeInMB.toFixed(2)}MB -> ${(compressedBuffer.length / (1024 * 1024)).toFixed(2)}MB`);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
logger.warn("Failed to compress cache entry, storing uncompressed", error);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Create cache entry with session binding
|
|
96
|
+
const entry = {
|
|
97
|
+
content: finalContent,
|
|
98
|
+
metadata: {
|
|
99
|
+
...data,
|
|
100
|
+
sessionId,
|
|
101
|
+
requestId,
|
|
102
|
+
originalSize: sizeInMB
|
|
103
|
+
},
|
|
104
|
+
timestamp: Date.now(),
|
|
105
|
+
accessCount: 1,
|
|
106
|
+
size: Buffer.byteLength(finalContent, 'utf8'),
|
|
107
|
+
compressed,
|
|
108
|
+
sessionId,
|
|
109
|
+
requestId
|
|
110
|
+
};
|
|
111
|
+
// Store in cache
|
|
112
|
+
this.entries.set(finalCacheKey, entry);
|
|
113
|
+
// Map analysis ID to cache key with session binding
|
|
114
|
+
this.analysisIdMap.set(analysisId, {
|
|
115
|
+
cacheKey: finalCacheKey,
|
|
116
|
+
sessionId: sessionId || 'anonymous',
|
|
117
|
+
created: Date.now()
|
|
118
|
+
});
|
|
119
|
+
// Update access order for LRU
|
|
120
|
+
this.updateAccessOrder(finalCacheKey);
|
|
121
|
+
// Update stats
|
|
122
|
+
this.stats.entries = this.entries.size;
|
|
123
|
+
this.stats.totalSize = Array.from(this.entries.values()).reduce((sum, e) => sum + e.size, 0);
|
|
124
|
+
// Ensure capacity limits
|
|
125
|
+
await this.ensureCapacity();
|
|
126
|
+
logger.debug(`✅ Cached response with analysis_id: ${analysisId} for session: ${sessionId?.substring(0, 8)}...`);
|
|
127
|
+
return { analysisId, cacheKey: finalCacheKey };
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Retrieve response with session validation
|
|
131
|
+
*/
|
|
132
|
+
async get(analysisIdOrCacheKey, sessionId) {
|
|
133
|
+
let cacheKey;
|
|
134
|
+
let requiredSessionId;
|
|
135
|
+
// Check if it's an analysis ID first
|
|
136
|
+
const mapping = this.analysisIdMap.get(analysisIdOrCacheKey);
|
|
137
|
+
if (mapping) {
|
|
138
|
+
cacheKey = mapping.cacheKey;
|
|
139
|
+
requiredSessionId = mapping.sessionId;
|
|
140
|
+
// Validate session access
|
|
141
|
+
if (requiredSessionId !== 'anonymous') {
|
|
142
|
+
if (!sessionId || sessionId !== requiredSessionId) {
|
|
143
|
+
logger.warn(`🚫 Session mismatch for analysis ${analysisIdOrCacheKey}: ${sessionId?.substring(0, 8) || 'none'} != ${requiredSessionId?.substring(0, 8)}`);
|
|
144
|
+
this.stats.misses++;
|
|
145
|
+
return null; // Block cross-session access
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Direct cache key access (legacy support)
|
|
151
|
+
cacheKey = analysisIdOrCacheKey;
|
|
152
|
+
}
|
|
153
|
+
const entry = this.entries.get(cacheKey);
|
|
154
|
+
if (!entry) {
|
|
155
|
+
this.stats.misses++;
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
// Check TTL
|
|
159
|
+
if (Date.now() - entry.timestamp > this.ttlMs) {
|
|
160
|
+
logger.debug(`⏰ Cache entry expired: ${cacheKey.substring(0, 8)}...`);
|
|
161
|
+
this.entries.delete(cacheKey);
|
|
162
|
+
// Also clean up analysis ID mapping
|
|
163
|
+
if (mapping) {
|
|
164
|
+
this.analysisIdMap.delete(analysisIdOrCacheKey);
|
|
165
|
+
}
|
|
166
|
+
this.stats.misses++;
|
|
167
|
+
this.stats.evictions++;
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
// Additional session validation on the entry itself
|
|
171
|
+
if (sessionId && entry.sessionId && entry.sessionId !== sessionId && entry.sessionId !== 'anonymous') {
|
|
172
|
+
logger.warn(`🚫 Entry session mismatch for ${cacheKey.substring(0, 8)}: ${sessionId?.substring(0, 8)} != ${entry.sessionId?.substring(0, 8)}`);
|
|
173
|
+
this.stats.misses++;
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
// Update access tracking
|
|
177
|
+
entry.accessCount++;
|
|
178
|
+
this.updateAccessOrder(cacheKey);
|
|
179
|
+
this.stats.hits++;
|
|
180
|
+
// Decompress if needed
|
|
181
|
+
let content = entry.content;
|
|
182
|
+
if (entry.compressed) {
|
|
183
|
+
try {
|
|
184
|
+
const compressedBuffer = Buffer.from(content, 'base64');
|
|
185
|
+
const decompressedBuffer = await gunzipAsync(compressedBuffer);
|
|
186
|
+
content = decompressedBuffer.toString('utf8');
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
logger.error("Failed to decompress cache entry", error);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
logger.debug(`🎯 Cache hit for session ${sessionId?.substring(0, 8)}...: ${cacheKey.substring(0, 8)}...`);
|
|
194
|
+
return content;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Check if key exists in cache
|
|
198
|
+
*/
|
|
199
|
+
has(keyOrId) {
|
|
200
|
+
// Check analysis ID mapping first
|
|
201
|
+
const mapping = this.analysisIdMap.get(keyOrId);
|
|
202
|
+
const cacheKey = mapping ? mapping.cacheKey : keyOrId;
|
|
203
|
+
const entry = this.entries.get(cacheKey);
|
|
204
|
+
if (!entry)
|
|
205
|
+
return false;
|
|
206
|
+
// Check if expired
|
|
207
|
+
const age = Date.now() - entry.timestamp;
|
|
208
|
+
if (age > this.ttlMs) {
|
|
209
|
+
this.delete(keyOrId);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Delete entry from cache
|
|
216
|
+
*/
|
|
217
|
+
delete(keyOrId) {
|
|
218
|
+
// Check analysis ID mapping first
|
|
219
|
+
const mapping = this.analysisIdMap.get(keyOrId);
|
|
220
|
+
const cacheKey = mapping ? mapping.cacheKey : keyOrId;
|
|
221
|
+
const entry = this.entries.get(cacheKey);
|
|
222
|
+
if (entry) {
|
|
223
|
+
this.stats.totalSize -= entry.size;
|
|
224
|
+
// Delete from entries
|
|
225
|
+
this.entries.delete(cacheKey);
|
|
226
|
+
// Remove from analysis ID mapping if it exists
|
|
227
|
+
if (mapping) {
|
|
228
|
+
this.analysisIdMap.delete(keyOrId);
|
|
229
|
+
}
|
|
230
|
+
// Remove cache key from access order
|
|
231
|
+
this.accessOrder = this.accessOrder.filter(k => k !== cacheKey);
|
|
232
|
+
this.stats.entries = this.entries.size;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Update LRU access order
|
|
237
|
+
*/
|
|
238
|
+
updateAccessOrder(key) {
|
|
239
|
+
this.accessOrder = this.accessOrder.filter(k => k !== key);
|
|
240
|
+
this.accessOrder.push(key);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Ensure cache has capacity for new entry
|
|
244
|
+
*/
|
|
245
|
+
async ensureCapacity() {
|
|
246
|
+
const maxTotalSize = this.maxTotalSizeMB * 1024 * 1024;
|
|
247
|
+
// Check total size limit
|
|
248
|
+
while (this.stats.totalSize > maxTotalSize && this.accessOrder.length > 0) {
|
|
249
|
+
const oldestKey = this.accessOrder[0];
|
|
250
|
+
logger.info(`🗑️ Evicting for size limit: ${oldestKey}`);
|
|
251
|
+
this.delete(oldestKey);
|
|
252
|
+
this.stats.evictions++;
|
|
253
|
+
}
|
|
254
|
+
// Check entry count limit
|
|
255
|
+
while (this.entries.size >= this.maxEntries && this.accessOrder.length > 0) {
|
|
256
|
+
const oldestKey = this.accessOrder[0];
|
|
257
|
+
logger.info(`🗑️ Evicting for entry limit: ${oldestKey}`);
|
|
258
|
+
this.delete(oldestKey);
|
|
259
|
+
this.stats.evictions++;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Clean up expired entries
|
|
264
|
+
*/
|
|
265
|
+
cleanupExpired() {
|
|
266
|
+
const now = Date.now();
|
|
267
|
+
let cleaned = 0;
|
|
268
|
+
for (const [key, entry] of this.entries.entries()) {
|
|
269
|
+
if (now - entry.timestamp > this.ttlMs) {
|
|
270
|
+
this.delete(key);
|
|
271
|
+
cleaned++;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (cleaned > 0) {
|
|
275
|
+
logger.info(`🧹 Cleaned ${cleaned} expired cache entries`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Get cache statistics
|
|
280
|
+
*/
|
|
281
|
+
getStats() {
|
|
282
|
+
return { ...this.stats };
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Retrieve response by analysis ID, returning full cached response object
|
|
286
|
+
*/
|
|
287
|
+
async getByAnalysisId(analysisId, sessionId) {
|
|
288
|
+
const mapping = this.analysisIdMap.get(analysisId);
|
|
289
|
+
if (!mapping) {
|
|
290
|
+
this.stats.misses++;
|
|
291
|
+
logger.debug(`❌ Cache miss by analysis ID: ${analysisId}`);
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
// Validate session access
|
|
295
|
+
if (sessionId && mapping.sessionId !== sessionId && mapping.sessionId !== 'anonymous') {
|
|
296
|
+
logger.warn(`🚫 Session mismatch for analysis ${analysisId}: ${sessionId?.substring(0, 8)} != ${mapping.sessionId?.substring(0, 8)}`);
|
|
297
|
+
this.stats.misses++;
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
const entry = this.entries.get(mapping.cacheKey);
|
|
301
|
+
if (!entry) {
|
|
302
|
+
this.stats.misses++;
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
// Check TTL
|
|
306
|
+
const age = Date.now() - entry.timestamp;
|
|
307
|
+
if (age > this.ttlMs) {
|
|
308
|
+
logger.info(`⏰ Cache expired: ${analysisId} (age: ${(age / 1000 / 60).toFixed(0)} minutes)`);
|
|
309
|
+
this.delete(analysisId);
|
|
310
|
+
this.stats.misses++;
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
// Update access order
|
|
314
|
+
this.updateAccessOrder(mapping.cacheKey);
|
|
315
|
+
this.stats.hits++;
|
|
316
|
+
logger.info(`✅ Cache hit by analysis ID: ${analysisId} (age: ${(age / 1000 / 60).toFixed(0)} minutes)`);
|
|
317
|
+
// Decompress if needed
|
|
318
|
+
let content = entry.content;
|
|
319
|
+
if (entry.compressed) {
|
|
320
|
+
try {
|
|
321
|
+
const buffer = Buffer.from(entry.content, 'base64');
|
|
322
|
+
const decompressed = await gunzipAsync(buffer);
|
|
323
|
+
content = decompressed.toString('utf-8');
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
logger.error('Decompression failed:', error);
|
|
327
|
+
this.delete(analysisId);
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
content,
|
|
333
|
+
timestamp: entry.timestamp,
|
|
334
|
+
analysisId,
|
|
335
|
+
cacheKey: mapping.cacheKey,
|
|
336
|
+
requestParams: entry.metadata,
|
|
337
|
+
compressed: entry.compressed || false,
|
|
338
|
+
size: entry.size,
|
|
339
|
+
sessionId: entry.sessionId,
|
|
340
|
+
requestId: entry.requestId
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Clear entire cache
|
|
345
|
+
*/
|
|
346
|
+
clear() {
|
|
347
|
+
this.entries.clear();
|
|
348
|
+
this.analysisIdMap.clear();
|
|
349
|
+
this.accessOrder = [];
|
|
350
|
+
this.stats = {
|
|
351
|
+
entries: 0,
|
|
352
|
+
totalSize: 0,
|
|
353
|
+
hits: this.stats.hits,
|
|
354
|
+
misses: this.stats.misses,
|
|
355
|
+
evictions: this.stats.evictions
|
|
356
|
+
};
|
|
357
|
+
logger.info('🗑️ Cache cleared');
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Destroy cache and cleanup resources
|
|
361
|
+
*/
|
|
362
|
+
destroy() {
|
|
363
|
+
if (this.cleanupTimer) {
|
|
364
|
+
clearInterval(this.cleanupTimer);
|
|
365
|
+
this.cleanupTimer = undefined;
|
|
366
|
+
}
|
|
367
|
+
this.clear();
|
|
368
|
+
logger.info('💀 Cache destroyed');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
//# sourceMappingURL=response-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-cache.js","sourceRoot":"","sources":["../../src/utils/response-cache.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAe,GACzB,MAAM,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAe,GACzB,MAAM,CAsCR"}
|
package/dist/utils.js
CHANGED
|
@@ -10,14 +10,33 @@ import { realpathSync, existsSync } from 'fs';
|
|
|
10
10
|
* @throws Error if the path is outside the project root or does not exist (if mustExist is true).
|
|
11
11
|
*/
|
|
12
12
|
export function resolveAndValidatePath(projectRoot, userPath, mustExist = false) {
|
|
13
|
+
// Check for null byte injection before any path operations
|
|
14
|
+
if (userPath.includes('\0')) {
|
|
15
|
+
throw new Error(`Path traversal detected`);
|
|
16
|
+
}
|
|
13
17
|
const absoluteProjectRoot = realpathSync(projectRoot);
|
|
18
|
+
// For absolute paths, check if they start outside project root immediately
|
|
19
|
+
if (resolve(userPath) === userPath) { // userPath is absolute
|
|
20
|
+
if (!userPath.startsWith(absoluteProjectRoot + sep) && userPath !== absoluteProjectRoot) {
|
|
21
|
+
throw new Error(`Path traversal detected`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
14
24
|
const resolvedPath = resolve(absoluteProjectRoot, userPath);
|
|
15
|
-
|
|
25
|
+
let absoluteResolvedPath;
|
|
26
|
+
const pathExists = existsSync(resolvedPath);
|
|
27
|
+
if (pathExists) {
|
|
28
|
+
// Use realpathSync to resolve symlinks and detect traversal for existing paths
|
|
29
|
+
absoluteResolvedPath = realpathSync(resolvedPath);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// For non-existent paths, use logical resolution for traversal detection
|
|
33
|
+
absoluteResolvedPath = resolvedPath;
|
|
34
|
+
}
|
|
16
35
|
// Ensure the resolved path is a sub-path of the project root
|
|
17
36
|
if (!absoluteResolvedPath.startsWith(absoluteProjectRoot + sep) && absoluteResolvedPath !== absoluteProjectRoot) {
|
|
18
|
-
throw new Error(`Path traversal detected
|
|
37
|
+
throw new Error(`Path traversal detected`);
|
|
19
38
|
}
|
|
20
|
-
if (mustExist && !
|
|
39
|
+
if (mustExist && !pathExists) {
|
|
21
40
|
throw new Error(`Path does not exist: ${userPath}`);
|
|
22
41
|
}
|
|
23
42
|
return absoluteResolvedPath;
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,GAAG,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,QAAgB,EAChB,YAAqB,KAAK;IAE1B,MAAM,mBAAmB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,GAAG,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,QAAgB,EAChB,YAAqB,KAAK;IAE1B,2DAA2D;IAC3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,mBAAmB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAEtD,2EAA2E;IAC3E,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC,uBAAuB;QAC3D,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,GAAG,GAAG,CAAC,IAAI,QAAQ,KAAK,mBAAmB,EAAE,CAAC;YACxF,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAE5D,IAAI,oBAA4B,CAAC;IACjC,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAE5C,IAAI,UAAU,EAAE,CAAC;QACf,+EAA+E;QAC/E,oBAAoB,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,yEAAyE;QACzE,oBAAoB,GAAG,YAAY,CAAC;IACtC,CAAC;IAED,6DAA6D;IAC7D,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,mBAAmB,GAAG,GAAG,CAAC,IAAI,oBAAoB,KAAK,mBAAmB,EAAE,CAAC;QAChH,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,oBAAoB,CAAC;AAC9B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brutalist/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Deploy Claude, Codex & Gemini CLI agents to demolish your work before users do. Real file analysis. Brutal honesty. Now with intelligent pagination.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,15 +21,20 @@
|
|
|
21
21
|
"prebuild": "npm run clean",
|
|
22
22
|
"build": "tsc && chmod +x dist/index.js",
|
|
23
23
|
"prepare": "npm run build",
|
|
24
|
-
"prepublishOnly": "npm run test && npm audit --production && npm run build",
|
|
24
|
+
"prepublishOnly": "npm run test:unit && npm audit --production && npm run build",
|
|
25
25
|
"watch": "tsc --watch",
|
|
26
26
|
"start": "node dist/index.js",
|
|
27
27
|
"dev": "npm run build && npm start",
|
|
28
28
|
"debug": "DEBUG=true node --trace-warnings dist/index.js",
|
|
29
29
|
"inspector": "npx @modelcontextprotocol/inspector dist/index.js",
|
|
30
30
|
"test": "jest",
|
|
31
|
+
"test:unit": "jest --config jest.config.js",
|
|
31
32
|
"test:watch": "jest --watch",
|
|
32
|
-
"test:coverage": "jest --coverage"
|
|
33
|
+
"test:coverage": "jest --coverage",
|
|
34
|
+
"test:integration": "jest --config jest.integration.config.js --detectOpenHandles",
|
|
35
|
+
"test:integration:watch": "jest --config jest.integration.config.js --watch",
|
|
36
|
+
"test:all": "npm run test:unit && npm run test:integration",
|
|
37
|
+
"test:fast": "npm run test:unit"
|
|
33
38
|
},
|
|
34
39
|
"keywords": [
|
|
35
40
|
"brutalist",
|
|
@@ -75,17 +80,22 @@
|
|
|
75
80
|
},
|
|
76
81
|
"dependencies": {
|
|
77
82
|
"@modelcontextprotocol/sdk": "^1.18.1",
|
|
83
|
+
"express": "^4.18.2",
|
|
78
84
|
"zod": "^3.24.2"
|
|
79
85
|
},
|
|
80
86
|
"devDependencies": {
|
|
81
|
-
"@types/
|
|
87
|
+
"@types/eventsource": "^1.1.15",
|
|
88
|
+
"@types/express": "^4.17.21",
|
|
82
89
|
"@types/jest": "^30.0.0",
|
|
83
90
|
"@types/node": "^20.17.28",
|
|
84
91
|
"@types/node-fetch": "^2.6.13",
|
|
92
|
+
"@types/supertest": "^6.0.3",
|
|
85
93
|
"@types/ws": "^8.18.1",
|
|
86
94
|
"dotenv": "^17.2.2",
|
|
95
|
+
"eventsource": "^4.0.0",
|
|
87
96
|
"jest": "^30.1.3",
|
|
88
97
|
"node-fetch": "^3.3.2",
|
|
98
|
+
"supertest": "^7.1.4",
|
|
89
99
|
"ts-jest": "^29.4.2",
|
|
90
100
|
"typescript": "^5.8.2",
|
|
91
101
|
"ws": "^8.18.3"
|