vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
180 lines (179 loc) • 6.87 kB
JavaScript
import path from 'path';
import logger from '../../../logger.js';
import { FileCache } from './fileCache.js';
import { TieredCache } from './tieredCache.js';
import { getCacheDirectory } from '../directoryUtils.js';
const cacheInstances = new Map();
export function createCacheManager(config) {
const cacheDir = getCacheDirectory(config);
async function getFileCache(name, options) {
if (cacheInstances.has(name)) {
const cache = cacheInstances.get(name);
if (cache instanceof FileCache) {
return cache;
}
else {
throw new Error(`Cache ${name} exists but is not a FileCache`);
}
}
const cacheOptions = {
name,
cacheDir: path.join(cacheDir, name),
maxEntries: options?.maxEntries || config.cache?.maxEntries,
maxAge: options?.maxAge || config.cache?.maxAge,
validateOnGet: options?.validateOnGet,
pruneOnStartup: options?.pruneOnStartup,
pruneInterval: options?.pruneInterval,
serialize: options?.serialize,
deserialize: options?.deserialize,
};
const cache = new FileCache(cacheOptions);
await cache.init();
cacheInstances.set(name, cache);
logger.debug(`Created file cache instance: ${name}`);
return cache;
}
async function getTieredCache(name, options) {
if (cacheInstances.has(name)) {
const cache = cacheInstances.get(name);
if (cache instanceof TieredCache) {
return cache;
}
else {
throw new Error(`Cache ${name} exists but is not a TieredCache`);
}
}
const cacheOptions = {
name,
cacheDir: path.join(cacheDir, name),
maxEntries: options?.maxEntries || config.cache?.maxEntries,
maxAge: options?.maxAge || config.cache?.maxAge,
validateOnGet: options?.validateOnGet,
pruneOnStartup: options?.pruneOnStartup,
pruneInterval: options?.pruneInterval,
serialize: options?.serialize,
deserialize: options?.deserialize,
useMemoryCache: options?.useMemoryCache ?? config.cache?.useMemoryCache ?? true,
memoryMaxEntries: options?.memoryMaxEntries,
memoryMaxAge: options?.memoryMaxAge,
memoryThreshold: options?.memoryThreshold,
memorySizeCalculator: options?.memorySizeCalculator
};
const cache = new TieredCache(cacheOptions);
await cache.init();
cacheInstances.set(name, cache);
logger.debug(`Created tiered cache instance: ${name}`);
return cache;
}
async function getCache(name, options) {
return getFileCache(name, options);
}
async function clearCache(name) {
const cache = cacheInstances.get(name);
if (cache) {
await cache.clear();
logger.debug(`Cleared cache: ${name}`);
}
}
async function clearAllCaches() {
const clearPromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => {
await cache.clear();
logger.debug(`Cleared cache: ${name}`);
});
await Promise.all(clearPromises);
logger.info(`Cleared all caches (${cacheInstances.size} instances)`);
}
async function pruneCache(name) {
const cache = cacheInstances.get(name);
if (cache) {
const prunedCount = await cache.prune();
logger.debug(`Pruned ${prunedCount} entries from cache: ${name}`);
return prunedCount;
}
return 0;
}
async function pruneAllCaches() {
let totalPruned = 0;
const prunePromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => {
const prunedCount = await cache.prune();
logger.debug(`Pruned ${prunedCount} entries from cache: ${name}`);
return prunedCount;
});
const results = await Promise.all(prunePromises);
totalPruned = results.reduce((total, count) => total + count, 0);
logger.info(`Pruned ${totalPruned} entries from all caches (${cacheInstances.size} instances)`);
return totalPruned;
}
async function getCacheStats(name) {
const cache = cacheInstances.get(name);
if (cache) {
const stats = cache.getStats();
return stats instanceof Promise ? await stats : stats;
}
return undefined;
}
async function getAllCacheStats() {
const stats = {};
for (const [name, cache] of cacheInstances.entries()) {
const cacheStats = cache.getStats();
stats[name] = cacheStats instanceof Promise ? await cacheStats : cacheStats;
}
return stats;
}
function closeAllCaches() {
for (const [name, cache] of cacheInstances.entries()) {
cache.close();
logger.debug(`Closed cache: ${name}`);
}
cacheInstances.clear();
logger.info('Closed all cache instances');
}
return {
getCache,
getFileCache,
getTieredCache,
clearCache,
clearAllCaches,
pruneCache,
pruneAllCaches,
getCacheStats,
getAllCacheStats,
closeAllCaches,
};
}
export async function clearAllCaches() {
const clearPromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => {
await cache.clear();
logger.debug(`Cleared cache: ${name}`);
});
await Promise.all(clearPromises);
logger.info(`Cleared all caches (${cacheInstances.size} instances)`);
}
export async function pruneAllCaches() {
let totalPruned = 0;
const prunePromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => {
const prunedCount = await cache.prune();
logger.debug(`Pruned ${prunedCount} entries from cache: ${name}`);
return prunedCount;
});
const results = await Promise.all(prunePromises);
totalPruned = results.reduce((total, count) => total + count, 0);
logger.info(`Pruned ${totalPruned} entries from all caches (${cacheInstances.size} instances)`);
return totalPruned;
}
export async function getCacheStats() {
const stats = {};
for (const [name, cache] of cacheInstances.entries()) {
const cacheStats = cache.getStats();
stats[name] = cacheStats instanceof Promise ? await cacheStats : cacheStats;
}
return stats;
}
export function closeAllCaches() {
for (const [name, cache] of cacheInstances.entries()) {
cache.close();
logger.debug(`Closed cache: ${name}`);
}
cacheInstances.clear();
logger.info('Closed all cache instances');
}