@ai-capabilities-suite/mcp-debugger-core
Version:
Core debugging engine for Node.js and TypeScript applications. Provides Inspector Protocol integration, breakpoint management, variable inspection, execution control, profiling, hang detection, and source map support.
137 lines • 4.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionManager = void 0;
const crypto_1 = require("crypto");
const debug_session_1 = require("./debug-session");
const audit_logger_1 = require("./audit-logger");
/**
* Manages multiple concurrent debug sessions
* Provides session isolation and lifecycle management
*/
class SessionManager {
constructor(auditLogger) {
this.sessions = new Map();
this.auditLogger = auditLogger || new audit_logger_1.AuditLogger();
}
/**
* Generate a unique session ID
*/
generateSessionId() {
return (0, crypto_1.randomBytes)(16).toString('hex');
}
/**
* Create a new debug session
* @param config Session configuration
* @returns The created debug session
*/
async createSession(config) {
const sessionId = this.generateSessionId();
const session = new debug_session_1.DebugSession(sessionId, config);
// Store session before starting to ensure it's tracked
this.sessions.set(sessionId, session);
// Register crash handler to automatically clean up crashed sessions
session.onCrash((error) => {
// Log crash
this.auditLogger.log(sessionId, 'session_crash', { error: error.message }, false, error.message);
// Session will clean itself up, we just need to remove it from tracking
this.sessions.delete(sessionId);
});
try {
await session.start();
this.auditLogger.log(sessionId, 'session_create', { command: config.command, args: config.args }, true);
return session;
}
catch (error) {
// Remove session if start fails
this.sessions.delete(sessionId);
this.auditLogger.log(sessionId, 'session_create', { command: config.command, args: config.args }, false, error instanceof Error ? error.message : String(error));
throw error;
}
}
/**
* Get a session by ID
* @param sessionId Session identifier
* @returns The debug session or undefined if not found
*/
getSession(sessionId) {
return this.sessions.get(sessionId);
}
/**
* Get all active sessions
* @returns Array of all debug sessions
*/
getAllSessions() {
return Array.from(this.sessions.values());
}
/**
* Check if a session exists
* @param sessionId Session identifier
* @returns True if session exists
*/
hasSession(sessionId) {
return this.sessions.has(sessionId);
}
/**
* Remove and cleanup a session
* @param sessionId Session identifier
* @returns True if session was found and removed
*/
async removeSession(sessionId) {
const session = this.sessions.get(sessionId);
if (!session) {
this.auditLogger.log(sessionId, 'session_remove', {}, false, 'Session not found');
return false;
}
try {
await session.cleanup();
this.sessions.delete(sessionId);
this.auditLogger.log(sessionId, 'session_remove', {}, true);
return true;
}
catch (error) {
this.auditLogger.log(sessionId, 'session_remove', {}, false, error instanceof Error ? error.message : String(error));
throw error;
}
}
/**
* Cleanup all sessions
*/
async cleanupAll() {
const cleanupPromises = Array.from(this.sessions.values()).map(async (session) => {
try {
await session.cleanup();
}
catch (error) {
// Log error but continue with other cleanups
console.warn('Error during session cleanup:', error);
}
});
await Promise.allSettled(cleanupPromises);
this.sessions.clear();
}
/**
* Get the number of active sessions
*/
getSessionCount() {
return this.sessions.size;
}
/**
* Get the audit logger
* @returns The audit logger instance
*/
getAuditLogger() {
return this.auditLogger;
}
/**
* Remove terminated sessions
*/
pruneTerminatedSessions() {
for (const [id, session] of this.sessions.entries()) {
if (!session.isActive()) {
this.sessions.delete(id);
}
}
}
}
exports.SessionManager = SessionManager;
//# sourceMappingURL=session-manager.js.map