ai-debug-local-mcp
Version:
๐ฏ ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
197 lines โข 7.85 kB
JavaScript
/**
* Memory-Aware Session Manager
* Wraps session management with memory optimization and automatic cleanup
*/
import { AdvancedMemoryManager } from './advanced-memory-manager.js';
export class MemoryAwareSessionManager {
sessions = new Map();
memoryManager;
constructor() {
this.memoryManager = AdvancedMemoryManager.getInstance();
}
/**
* Create a new session with memory tracking
*/
createSession(sessionId, initialData = {}) {
const now = Date.now();
const sessionData = {
sessionId,
createdAt: now,
lastAccessed: now,
resourceCount: 0,
...initialData
};
// Register with memory manager
this.memoryManager.registerSession(sessionId, 15); // Estimate 15MB per session
this.sessions.set(sessionId, sessionData);
console.log(`๐ฑ Created session ${sessionId} with memory tracking`);
return sessionData;
}
/**
* Get session with automatic access tracking
*/
getSession(sessionId) {
const session = this.sessions.get(sessionId);
if (session) {
session.lastAccessed = Date.now();
this.memoryManager.touchSession(sessionId);
return session;
}
return undefined;
}
/**
* Update session data
*/
updateSession(sessionId, updates) {
const session = this.sessions.get(sessionId);
if (session) {
Object.assign(session, updates);
session.lastAccessed = Date.now();
this.memoryManager.touchSession(sessionId);
return true;
}
return false;
}
/**
* Add a resource to session (browser, page, etc.)
*/
addResource(sessionId, resourceType, resource, memoryMB = 5) {
const session = this.sessions.get(sessionId);
if (session) {
session[resourceType] = resource;
session.resourceCount++;
session.lastAccessed = Date.now();
this.memoryManager.addResource(sessionId, memoryMB);
console.log(`๐ Added ${resourceType} to session ${sessionId} (${memoryMB}MB)`);
return true;
}
return false;
}
/**
* Remove a resource from session
*/
async removeResource(sessionId, resourceType) {
const session = this.sessions.get(sessionId);
if (session && session[resourceType]) {
const resource = session[resourceType];
// Try to cleanup the resource
try {
if (resource && typeof resource.close === 'function') {
await resource.close();
}
}
catch (error) {
console.warn(`โ ๏ธ Failed to close ${resourceType} for session ${sessionId}:`, error instanceof Error ? error.message : String(error));
}
delete session[resourceType];
session.resourceCount = Math.max(0, session.resourceCount - 1);
session.lastAccessed = Date.now();
console.log(`๐๏ธ Removed ${resourceType} from session ${sessionId}`);
return true;
}
return false;
}
/**
* Clean up a session and all its resources
*/
async cleanupSession(sessionId) {
const session = this.sessions.get(sessionId);
if (!session) {
return false;
}
console.log(`๐งน Cleaning up session ${sessionId} with ${session.resourceCount} resources`);
// Clean up all browser resources
const cleanupPromises = [];
// Close page if exists
if (session.page) {
cleanupPromises.push(session.page.close().catch((error) => console.warn(`โ ๏ธ Failed to close page for session ${sessionId}:`, error instanceof Error ? error.message : String(error))));
}
// Close browser context if exists
if (session.context) {
cleanupPromises.push(session.context.close().catch((error) => console.warn(`โ ๏ธ Failed to close context for session ${sessionId}:`, error instanceof Error ? error.message : String(error))));
}
// Close browser if exists
if (session.browser) {
cleanupPromises.push(session.browser.close().catch((error) => console.warn(`โ ๏ธ Failed to close browser for session ${sessionId}:`, error instanceof Error ? error.message : String(error))));
}
// Wait for all cleanup operations
await Promise.allSettled(cleanupPromises);
// Remove from sessions map
this.sessions.delete(sessionId);
// Remove from memory manager
this.memoryManager.removeSession(sessionId);
console.log(`โ
Session ${sessionId} cleaned up successfully`);
return true;
}
/**
* Get all active sessions
*/
getAllSessions() {
return Array.from(this.sessions.values());
}
/**
* Get session count
*/
getSessionCount() {
return this.sessions.size;
}
/**
* Clean up expired sessions based on memory manager recommendations
*/
async cleanupExpiredSessions() {
const memoryStats = this.memoryManager.getMemoryStats();
const expiredSessions = [];
const now = Date.now();
const TTL = 30 * 60 * 1000; // 30 minutes
// Find expired sessions
for (const session of this.sessions.values()) {
if (now - session.lastAccessed > TTL) {
expiredSessions.push(session.sessionId);
}
}
// Clean up expired sessions
const cleanupPromises = expiredSessions.map(sessionId => this.cleanupSession(sessionId));
await Promise.allSettled(cleanupPromises);
if (expiredSessions.length > 0) {
console.log(`๐งน Cleaned up ${expiredSessions.length} expired sessions`);
}
return expiredSessions;
}
/**
* Force cleanup of oldest sessions if memory pressure is detected
*/
async performEmergencyCleanup() {
// HOTFIX v2.13.0: Disable aggressive memory pressure detection during startup
// The StartupAwareMemoryManager integration needs more comprehensive testing
console.log('๐ง HOTFIX: Emergency cleanup disabled during stability improvements');
return; // Skip cleanup to prevent infinite loops
const stats = this.memoryManager.getMemoryStats();
if (!stats.pressure.isUnderPressure) {
return;
}
console.log('๐จ Performing emergency session cleanup due to memory pressure');
// Sort sessions by last accessed time (oldest first)
const sessions = Array.from(this.sessions.values())
.sort((a, b) => a.lastAccessed - b.lastAccessed);
// Clean up oldest 25% of sessions
const sessionsToCleanup = sessions.slice(0, Math.ceil(sessions.length * 0.25));
const cleanupPromises = sessionsToCleanup.map(session => this.cleanupSession(session.sessionId));
await Promise.allSettled(cleanupPromises);
console.log(`๐งน Emergency cleanup completed: removed ${sessionsToCleanup.length} sessions`);
}
/**
* Get memory usage report
*/
getMemoryReport() {
const sessions = this.getAllSessions();
const totalResources = sessions.reduce((sum, session) => sum + session.resourceCount, 0);
const averageResources = sessions.length > 0 ? totalResources / sessions.length : 0;
return {
sessionCount: sessions.length,
totalResources,
averageResourcesPerSession: Math.round(averageResources * 100) / 100,
memoryStats: this.memoryManager.getMemoryStats()
};
}
}
//# sourceMappingURL=memory-aware-session-manager.js.map