@emmahyde/thinking-patterns
Version:
MCP server combining systematic thinking, mental models, debugging approaches, and stochastic algorithms for comprehensive cognitive pattern support
105 lines (104 loc) • 3.63 kB
JavaScript
export class InMemorySessionManager {
constructor() {
this.sessions = new Map();
this.SESSION_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour
// Run cleanup every 15 minutes
this.cleanupInterval = setInterval(() => {
this.cleanupExpiredSessions();
}, 15 * 60 * 1000);
}
createSession(sessionId) {
const now = new Date();
this.sessions.set(sessionId, {
thoughtHistory: [],
branches: {},
createdAt: now,
lastAccessedAt: now,
});
}
getSession(sessionId) {
const session = this.sessions.get(sessionId);
if (session) {
session.lastAccessedAt = new Date();
return session;
}
return null;
}
clearSession(sessionId) {
this.sessions.delete(sessionId);
}
cleanupExpiredSessions() {
const now = new Date();
const expiredSessions = [];
for (const [sessionId, session] of this.sessions.entries()) {
const timeSinceLastAccess = now.getTime() - session.lastAccessedAt.getTime();
if (timeSinceLastAccess > this.SESSION_TIMEOUT_MS) {
expiredSessions.push(sessionId);
}
}
for (const sessionId of expiredSessions) {
this.sessions.delete(sessionId);
// Log cleanup to console (suppress during tests)
if (process.env.NODE_ENV !== 'test' && process.env.JEST_WORKER_ID === undefined) {
console.log(`Cleaned up expired session: ${sessionId}`);
}
}
if (expiredSessions.length > 0) {
// Log cleanup summary to console (suppress during tests)
if (process.env.NODE_ENV !== 'test' && process.env.JEST_WORKER_ID === undefined) {
console.log(`Cleaned up ${expiredSessions.length} expired sessions`);
}
}
}
addThought(sessionId, thought) {
let session = this.getSession(sessionId);
if (!session) {
this.createSession(sessionId);
session = this.getSession(sessionId);
}
session.thoughtHistory.push(thought);
}
addBranch(sessionId, branchId, thought) {
let session = this.getSession(sessionId);
if (!session) {
this.createSession(sessionId);
session = this.getSession(sessionId);
}
if (!session.branches[branchId]) {
session.branches[branchId] = [];
}
session.branches[branchId].push(thought);
}
getThoughtHistory(sessionId) {
const session = this.getSession(sessionId);
return session ? [...session.thoughtHistory] : [];
}
getBranches(sessionId) {
const session = this.getSession(sessionId);
return session ? session.branches : {};
}
destroy() {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
}
this.sessions.clear();
}
// Utility methods for monitoring
getSessionCount() {
return this.sessions.size;
}
getSessionInfo() {
const sessionInfo = [];
for (const [sessionId, session] of this.sessions.entries()) {
sessionInfo.push({
sessionId,
thoughtCount: session.thoughtHistory.length,
branchCount: Object.keys(session.branches).length,
lastAccessed: session.lastAccessedAt,
});
}
return sessionInfo;
}
}
// Export a singleton instance
export const sessionManager = new InMemorySessionManager();