Skip to main content
Glama
SessionState.js27.9 kB
/** * Main session state management class for the Clear Thought MCP server * * This class manages all thinking session data and provides centralized * access to different types of thinking tools and their data. */ import { PDRKnowledgeGraph } from "./PDRKnowledgeGraph.js"; // Import unified store import { UnifiedStore } from "./stores/UnifiedStore.js"; /** * Main session state class */ export class SessionState { /** Expose config via getter */ getConfig() { return this.config; } /** Expose unified store via getter (read-only reference) */ getStore() { return this.unifiedStore; } /** * Create a new session state * @param sessionId - Unique identifier for this session * @param config - Server configuration */ constructor(sessionId, config) { /** PDR Knowledge Graphs for sessions */ this.pdrGraphs = new Map(); /** PDR Sessions */ this.pdrSessions = new Map(); /** OODA Loop Sessions */ this.oodaSessions = new Map(); /** Ulysses Protocol Sessions */ this.ulyssesSessions = new Map(); /** Metagame KPI tracking */ this.metagameKPIs = new Map(); this.sessionId = sessionId; this.config = config; this.createdAt = new Date(); this.lastAccessedAt = new Date(); // Initialize unified store this.unifiedStore = new UnifiedStore(config.persistenceEnabled ? { persistenceDir: config.persistenceDir, knowledgeGraphFile: config.knowledgeGraphFile, } : undefined); // Start timeout timer this.resetTimeout(); } /** * Reset the session timeout */ resetTimeout() { if (this.timeoutTimer) { clearTimeout(this.timeoutTimer); } this.timeoutTimer = setTimeout(() => { this.cleanup(); }, this.config.sessionTimeout); this.lastAccessedAt = new Date(); } /** * Touch the session to prevent timeout */ touch() { this.resetTimeout(); } // ============================================================================ // Thought Management // ============================================================================ /** * Add a new thought * @param thought - The thought data * @returns True if added, false if limit reached */ addThought(thought) { this.touch(); // Check thought limit if (this.unifiedStore.getByType("thought").length >= this.config.maxThoughtsPerSession) { return false; } const id = `thought-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "thought", data: thought }); return true; } /** * Get all thoughts */ getThoughts() { this.touch(); return this.unifiedStore.getByType("thought").map((item) => item.data); } /** * Get remaining thought capacity */ getRemainingThoughts() { return Math.max(0, this.config.maxThoughtsPerSession - this.unifiedStore.getByType("thought").length); } // ============================================================================ // Mental Model Management // ============================================================================ /** * Add a mental model application */ addMentalModel(model) { this.touch(); const id = `model-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "mental_model", data: model }); } /** * Get all mental model applications */ getMentalModels() { this.touch(); return this.unifiedStore.getByType("mental_model").map((item) => item.data); } // ============================================================================ // Debugging Management // ============================================================================ /** * Add a debugging session */ addDebuggingSession(session) { this.touch(); const id = `debug-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "debugging", data: session }); } /** * Get all debugging sessions */ getDebuggingSessions() { this.touch(); return this.unifiedStore.getByType("debugging").map((item) => item.data); } // ============================================================================ // Collaborative Reasoning Management // ============================================================================ /** * Add a collaborative session */ addCollaborativeSession(session) { this.touch(); const id = `collab-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "collaborative", data: session }); } /** * Get all collaborative sessions */ getCollaborativeSessions() { this.touch(); return this.unifiedStore .getByType("collaborative") .map((item) => item.data); } /** * Get a specific collaborative session by ID */ getCollaborativeSession(sessionId) { this.touch(); const items = this.unifiedStore.getByType("collaborative"); return items.find((item) => item.data.sessionId === sessionId)?.data; } // ============================================================================ // Decision Framework Management // ============================================================================ /** * Add a decision session */ addDecision(decision) { this.touch(); const id = `decision-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "decision", data: decision }); } /** * Get all decision sessions */ getDecisions() { this.touch(); return this.unifiedStore.getByType("decision").map((item) => item.data); } /** * Get a specific decision by ID */ getDecision(decisionId) { this.touch(); const items = this.unifiedStore.getByType("decision"); return items.find((item) => item.data.decisionId === decisionId)?.data; } // ============================================================================ // Metacognitive Monitoring Management // ============================================================================ /** * Add a metacognitive monitoring session */ addMetacognitive(session) { this.touch(); const id = `meta-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "metacognitive", data: session }); } /** * Get all metacognitive sessions */ getMetacognitiveSessions() { this.touch(); return this.unifiedStore .getByType("metacognitive") .map((item) => item.data); } /** * Get a specific metacognitive session by ID */ getMetacognitiveSession(monitoringId) { this.touch(); const items = this.unifiedStore.getByType("metacognitive"); return items.find((item) => item.data.monitoringId === monitoringId)?.data; } // ============================================================================ // Scientific Method Management // ============================================================================ /** * Add a scientific inquiry session */ addScientificInquiry(inquiry) { this.touch(); const id = `sci-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "scientific", data: inquiry }); } /** * Get all scientific inquiry sessions */ getScientificInquiries() { this.touch(); return this.unifiedStore.getByType("scientific").map((item) => item.data); } /** * Get a specific scientific inquiry by ID */ getScientificInquiry(inquiryId) { this.touch(); const items = this.unifiedStore.getByType("scientific"); return items.find((item) => item.data.inquiryId === inquiryId)?.data; } // ============================================================================ // Creative Thinking Management // ============================================================================ /** * Add a creative thinking session */ addCreativeSession(session) { this.touch(); const id = `creative-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "creative", data: session }); } /** * Get all creative sessions */ getCreativeSessions() { this.touch(); return this.unifiedStore.getByType("creative").map((item) => item.data); } // ============================================================================ // Systems Thinking Management // ============================================================================ /** * Add a systems thinking session */ addSystemsAnalysis(system) { this.touch(); const id = `systems-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "systems", data: system }); } /** * Get all systems analyses */ getSystemsAnalyses() { this.touch(); return this.unifiedStore.getByType("systems").map((item) => item.data); } // ============================================================================ // Visual Reasoning Management // ============================================================================ /** * Add a visual reasoning operation */ addVisualOperation(visual) { this.touch(); const id = `visual-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "visual", data: visual }); } /** * Get all visual operations */ getVisualOperations() { this.touch(); return this.unifiedStore.getByType("visual").map((item) => item.data); } /** * Get visual operations for a specific diagram */ getVisualDiagram(diagramId) { this.touch(); const items = this.unifiedStore.getByType("visual"); return items .filter((item) => item.data.diagramId === diagramId) .map((item) => item.data); } // ============================================================================ // PDR Knowledge Graph Support // ============================================================================ /** * Get or create a PDR knowledge graph for a session */ getPDRGraph(graphId, mode) { this.touch(); const id = graphId || this.sessionId; if (!this.pdrGraphs.has(id)) { this.pdrGraphs.set(id, new PDRKnowledgeGraph(id, mode || "standard")); } return this.pdrGraphs.get(id); } /** * Set a PDR knowledge graph */ setPDRGraph(graphId, graph) { this.touch(); this.pdrGraphs.set(graphId, graph); } /** * Get or create a PDR session */ getPDRSession(sessionId) { this.touch(); const id = sessionId || this.sessionId; return this.pdrSessions.get(id); } /** * Set a PDR session */ setPDRSession(sessionId, session) { this.touch(); this.pdrSessions.set(sessionId, session); } /** * Serialize PDR graph for persistence */ serializePDRGraph(graphId) { const id = graphId || this.sessionId; const graph = this.pdrGraphs.get(id); return graph ? graph.serialize() : undefined; } /** * Deserialize PDR graph from storage */ deserializePDRGraph(data, graphId) { const graph = PDRKnowledgeGraph.deserialize(data); const id = graphId || this.sessionId; this.pdrGraphs.set(id, graph); } // ============================================================================ // Argumentation Support (Socratic method uses ArgumentData) // ============================================================================ /** * Add a Socratic/argumentation session * Note: Since SocraticData extends ArgumentData, we can store it directly */ addArgumentation(argument) { this.touch(); const isSocratic = argument.question !== undefined || argument.stage !== undefined; if (isSocratic) { const id = `socratic-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "socratic", data: argument, }); } else { const id = `argument-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; this.unifiedStore.add(id, { type: "argument", data: argument, }); } } // ============================================================================ // Statistics and Export // ============================================================================ /** * Get comprehensive session statistics */ getStats() { this.touch(); const toolsUsed = new Set(); let totalOperations = 0; // Get statistics from unified store const stats = this.unifiedStore.getStats(); // Check which tools have been used if (stats.thought > 0) { toolsUsed.add("sequential-thinking"); totalOperations += stats.thought; } if (stats.mental_model > 0) { toolsUsed.add("mental-models"); totalOperations += stats.mental_model; } if (stats.debugging > 0) { toolsUsed.add("debugging"); totalOperations += stats.debugging; } if (stats.collaborative > 0) { toolsUsed.add("collaborative-reasoning"); totalOperations += stats.collaborative; } if (stats.decision > 0) { toolsUsed.add("decision-framework"); totalOperations += stats.decision; } if (stats.metacognitive > 0) { toolsUsed.add("metacognitive-monitoring"); totalOperations += stats.metacognitive; } if (stats.scientific > 0) { toolsUsed.add("scientific-method"); totalOperations += stats.scientific; } if (stats.creative > 0) { toolsUsed.add("creative-thinking"); totalOperations += stats.creative; } if (stats.systems > 0) { toolsUsed.add("systems-thinking"); totalOperations += stats.systems; } if (stats.visual > 0) { toolsUsed.add("visual-reasoning"); totalOperations += stats.visual; } if (stats.argument > 0) { toolsUsed.add("argumentation"); totalOperations += stats.argument; } if (stats.socratic > 0) { toolsUsed.add("socratic-method"); totalOperations += stats.socratic; } return { sessionId: this.sessionId, createdAt: this.createdAt, lastAccessedAt: this.lastAccessedAt, thoughtCount: stats.thought || 0, toolsUsed: Array.from(toolsUsed), totalOperations, isActive: !!this.timeoutTimer, remainingThoughts: this.getRemainingThoughts(), stores: stats, }; } /** * Export session data * @param storeType - Optional specific store to export * @returns Exportable session data */ export(storeType) { this.touch(); const baseExport = { version: "1.0.0", timestamp: new Date().toISOString(), sessionId: this.sessionId, }; // Export specific store if requested if (storeType) { const exports = []; switch (storeType) { case "thoughts": this.unifiedStore.getByType("thought").forEach((item) => { exports.push({ ...baseExport, sessionType: "sequential", data: item.data, }); }); break; case "mentalModels": this.unifiedStore.getByType("mental_model").forEach((item) => { exports.push({ ...baseExport, sessionType: "mental-model", data: item.data, }); }); break; case "debugging": this.unifiedStore.getByType("debugging").forEach((item) => { exports.push({ ...baseExport, sessionType: "debugging", data: item.data, }); }); break; case "collaborative": this.unifiedStore.getByType("collaborative").forEach((item) => { exports.push({ ...baseExport, sessionType: "collaborative", data: item.data, }); }); break; case "decisions": this.unifiedStore.getByType("decision").forEach((item) => { exports.push({ ...baseExport, sessionType: "decision", data: item.data, }); }); break; case "metacognitive": this.unifiedStore.getByType("metacognitive").forEach((item) => { exports.push({ ...baseExport, sessionType: "metacognitive", data: item.data, }); }); break; case "scientific": this.unifiedStore.getByType("scientific").forEach((item) => { exports.push({ ...baseExport, sessionType: "scientific", data: item.data, }); }); break; case "creative": this.unifiedStore.getByType("creative").forEach((item) => { exports.push({ ...baseExport, sessionType: "creative", data: item.data, }); }); break; case "systems": this.unifiedStore.getByType("systems").forEach((item) => { exports.push({ ...baseExport, sessionType: "systems", data: item.data, }); }); break; case "visual": this.unifiedStore.getByType("visual").forEach((item) => { exports.push({ ...baseExport, sessionType: "visual", data: item.data, }); }); break; case "argument": this.unifiedStore.getByType("argument").forEach((item) => { exports.push({ ...baseExport, sessionType: "argument", data: item.data, }); }); break; case "socratic": this.unifiedStore.getByType("socratic").forEach((item) => { exports.push({ ...baseExport, sessionType: "socratic", data: item.data, }); }); break; } return exports.length === 1 ? exports[0] : exports; } // Export all data const allExports = []; // Add exports from all stores this.unifiedStore.getByType("thought").forEach((item) => { allExports.push({ ...baseExport, sessionType: "sequential", data: item.data, }); }); this.unifiedStore.getByType("mental_model").forEach((item) => { allExports.push({ ...baseExport, sessionType: "mental-model", data: item.data, }); }); this.unifiedStore.getByType("debugging").forEach((item) => { allExports.push({ ...baseExport, sessionType: "debugging", data: item.data, }); }); this.unifiedStore.getByType("collaborative").forEach((item) => { allExports.push({ ...baseExport, sessionType: "collaborative", data: item.data, }); }); this.unifiedStore.getByType("decision").forEach((item) => { allExports.push({ ...baseExport, sessionType: "decision", data: item.data, }); }); this.unifiedStore.getByType("metacognitive").forEach((item) => { allExports.push({ ...baseExport, sessionType: "metacognitive", data: item.data, }); }); this.unifiedStore.getByType("scientific").forEach((item) => { allExports.push({ ...baseExport, sessionType: "scientific", data: item.data, }); }); this.unifiedStore.getByType("creative").forEach((item) => { allExports.push({ ...baseExport, sessionType: "creative", data: item.data, }); }); this.unifiedStore.getByType("systems").forEach((item) => { allExports.push({ ...baseExport, sessionType: "systems", data: item.data, }); }); this.unifiedStore.getByType("visual").forEach((item) => { allExports.push({ ...baseExport, sessionType: "visual", data: item.data, }); }); this.unifiedStore.getByType("argument").forEach((item) => { allExports.push({ ...baseExport, sessionType: "argument", data: item.data, }); }); this.unifiedStore.getByType("socratic").forEach((item) => { allExports.push({ ...baseExport, sessionType: "socratic", data: item.data, }); }); return allExports; } /** * Import session data * @param data - The session export data to import */ import(data) { this.touch(); const imports = Array.isArray(data) ? data : [data]; imports.forEach((item) => { switch (item.sessionType) { case "sequential": this.addThought(item.data); break; case "mental-model": this.addMentalModel(item.data); break; case "debugging": this.addDebuggingSession(item.data); break; case "collaborative": this.addCollaborativeSession(item.data); break; case "decision": this.addDecision(item.data); break; case "metacognitive": this.addMetacognitive(item.data); break; case "scientific": this.addScientificInquiry(item.data); break; case "creative": this.addCreativeSession(item.data); break; case "systems": this.addSystemsAnalysis(item.data); break; case "visual": this.addVisualOperation(item.data); break; case "argument": this.addArgumentation(item.data); break; case "socratic": this.addArgumentation(item.data); break; } }); } /** * Cleanup session data and stop timers */ cleanup() { if (this.timeoutTimer) { clearTimeout(this.timeoutTimer); this.timeoutTimer = undefined; } // Clear unified store this.unifiedStore.clear(); } /** * Check if session is still active */ isActive() { return !!this.timeoutTimer; } // ============= Metagame Session Management ============= /** * Create or get an OODA Loop session */ getOODASession(sessionId) { return this.oodaSessions.get(sessionId); } setOODASession(sessionId, session) { this.oodaSessions.set(sessionId, session); this.resetTimeout(); } /** * Create or get a Ulysses Protocol session */ getUlyssesSession(sessionId) { return this.ulyssesSessions.get(sessionId); } setUlyssesSession(sessionId, session) { this.ulyssesSessions.set(sessionId, session); this.resetTimeout(); } /** * Track KPI metrics for metagames */ updateKPI(key, value, label, target, direction) { const existing = this.metagameKPIs.get(key); const timestamp = new Date().toISOString(); if (existing) { existing.value = value; existing.history.push({ timestamp, value }); // Keep only last 100 history entries if (existing.history.length > 100) { existing.history = existing.history.slice(-100); } } else { this.metagameKPIs.set(key, { key, label: label || key, value, target, direction: direction || "up", history: [{ timestamp, value }], }); } this.resetTimeout(); } /** * Get all KPIs or a specific one */ getKPIs(key) { if (key) { return this.metagameKPIs.get(key); } return Array.from(this.metagameKPIs.values()); } /** * Clear metagame sessions */ clearMetagameSessions() { this.oodaSessions.clear(); this.ulyssesSessions.clear(); this.metagameKPIs.clear(); this.resetTimeout(); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/waldzellai/clearthought-onepointfive'

If you have feedback or need assistance with the MCP directory API, please join our Discord server