UNPKG

@stackmemoryai/stackmemory

Version:

Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.

474 lines (465 loc) 15.5 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import { v4 as uuidv4 } from "uuid"; import * as fs from "fs/promises"; import * as path from "path"; import { logger } from "../../../core/monitoring/logger.js"; import { RalphStackMemoryBridge } from "../bridge/ralph-stackmemory-bridge.js"; class ExtendedCoherenceManager { activeSessions = /* @__PURE__ */ new Map(); baseDir; monitoringInterval; performanceHistory = /* @__PURE__ */ new Map(); constructor(baseDir = "./.coherence-sessions") { this.baseDir = baseDir; } /** * Initialize the coherence management system */ async initialize() { await fs.mkdir(this.baseDir, { recursive: true }); this.monitoringInterval = setInterval( () => this.monitorActiveSessionsHealth(), 6e4 // Check every minute ); logger.info("Extended Coherence Manager initialized", { baseDir: this.baseDir, monitoringEnabled: true }); } /** * Start an extended coherence work session */ async startCoherenceSession(agentConfig, taskConfig, sessionConfig) { const sessionId = uuidv4(); const defaultConfig = this.generateConfigForComplexity(taskConfig.complexity); const config = { ...defaultConfig, ...sessionConfig }; const session = { id: sessionId, agent: agentConfig, task: { ...taskConfig, breakpoints: taskConfig.breakpoints || this.generateBreakpoints(taskConfig) }, config, state: { status: "active", currentPhase: "initialization", completedMilestones: [], lastCheckpoint: Date.now(), interventionCount: 0, refreshCount: 0 }, metrics: [], interventions: [] }; this.activeSessions.set(sessionId, session); await this.initializeSessionWorkspace(session); await this.launchAgentSession(session); logger.info("Extended coherence session started", { sessionId, agent: agentConfig.role, estimatedDuration: taskConfig.estimatedDuration, maxDuration: config.maxDuration }); return sessionId; } /** * Generate configuration optimized for task complexity */ generateConfigForComplexity(complexity) { const configs = { low: { maxDuration: 60, // 1 hour coherenceThreshold: 0.7, checkpointInterval: 15, // 15 minutes refreshStrategy: "checkpoint", enableMemoryPalace: false, enableProgressTracking: true, enableAutoRefresh: false, enableHealthMonitoring: true }, medium: { maxDuration: 180, // 3 hours coherenceThreshold: 0.8, checkpointInterval: 10, // 10 minutes refreshStrategy: "context_refresh", enableMemoryPalace: true, enableProgressTracking: true, enableAutoRefresh: true, enableHealthMonitoring: true }, high: { maxDuration: 360, // 6 hours coherenceThreshold: 0.85, checkpointInterval: 8, // 8 minutes refreshStrategy: "context_refresh", enableMemoryPalace: true, enableProgressTracking: true, enableAutoRefresh: true, enableHealthMonitoring: true }, very_high: { maxDuration: 720, // 12 hours coherenceThreshold: 0.9, checkpointInterval: 5, // 5 minutes refreshStrategy: "full_restart", enableMemoryPalace: true, enableProgressTracking: true, enableAutoRefresh: true, enableHealthMonitoring: true } }; return configs[complexity]; } /** * Monitor active sessions for coherence degradation */ async monitorActiveSessionsHealth() { for (const [sessionId, session] of this.activeSessions) { if (session.state.status === "active") { await this.assessSessionCoherence(session); } } } /** * Assess session coherence and intervene if necessary */ async assessSessionCoherence(session) { const metrics = await this.calculateCoherenceMetrics(session); session.metrics.push(metrics); if (session.metrics.length > 10) { session.metrics.shift(); } const overallCoherence = this.calculateOverallCoherence(metrics); logger.debug("Session coherence assessment", { sessionId: session.id, coherence: overallCoherence, threshold: session.config.coherenceThreshold, duration: metrics.duration }); if (overallCoherence < session.config.coherenceThreshold) { await this.interventeInSession(session, "coherence_degradation", overallCoherence); } const timeSinceCheckpoint = Date.now() - session.state.lastCheckpoint; const checkpointDue = timeSinceCheckpoint > session.config.checkpointInterval * 60 * 1e3; if (checkpointDue) { await this.checkpointSession(session); } } /** * Calculate comprehensive coherence metrics */ async calculateCoherenceMetrics(session) { const now = Date.now(); const duration = (now - session.metrics[0]?.startTime || now) / (1e3 * 60); const recentOutputs = await this.getRecentAgentOutputs(session); const outputQuality = this.assessOutputQuality(recentOutputs); const contextRetention = this.assessContextRetention(recentOutputs, session.task); const taskRelevance = this.assessTaskRelevance(recentOutputs, session.task); const repetitionRate = this.calculateRepetitionRate(recentOutputs); const divergenceRate = this.calculateDivergenceRate(recentOutputs, session.task); const errorRate = this.calculateErrorRate(recentOutputs); const progressRate = this.calculateProgressRate(session); return { sessionId: session.id, startTime: session.metrics[0]?.startTime || now, currentTime: now, duration, outputQuality, contextRetention, taskRelevance, progressRate, repetitionRate, divergenceRate, errorRate, memoryUsage: await this.getMemoryUsage(session), contextWindowUsage: await this.getContextWindowUsage(session), stateCheckpoints: session.interventions.filter((i) => i.type === "checkpoint").length }; } /** * Calculate overall coherence score */ calculateOverallCoherence(metrics) { const weights = { outputQuality: 0.3, contextRetention: 0.25, taskRelevance: 0.25, repetitionPenalty: 0.1, // penalty for repetition divergencePenalty: 0.1 // penalty for divergence }; const baseScore = metrics.outputQuality * weights.outputQuality + metrics.contextRetention * weights.contextRetention + metrics.taskRelevance * weights.taskRelevance; const penalties = metrics.repetitionRate * weights.repetitionPenalty + metrics.divergenceRate * weights.divergencePenalty; return Math.max(0, baseScore - penalties); } /** * Intervene in a session to restore coherence */ async interventeInSession(session, reason, currentCoherence) { logger.warn("Intervening in session due to coherence degradation", { sessionId: session.id, reason, currentCoherence, interventionCount: session.state.interventionCount }); const intervention = { timestamp: Date.now(), type: session.config.refreshStrategy, reason, effectiveness: 0 // will be calculated later }; switch (session.config.refreshStrategy) { case "checkpoint": await this.checkpointSession(session); break; case "context_refresh": await this.refreshSessionContext(session); break; case "full_restart": await this.restartSession(session); break; default: await this.provideGuidance(session, reason); intervention.type = "guidance"; } session.interventions.push(intervention); session.state.interventionCount++; const previousStatus = session.state.status; session.state.status = "degraded"; setTimeout(async () => { const newMetrics = await this.calculateCoherenceMetrics(session); const newCoherence = this.calculateOverallCoherence(newMetrics); intervention.effectiveness = Math.max(0, newCoherence - currentCoherence); if (newCoherence > session.config.coherenceThreshold) { session.state.status = "active"; logger.info("Session coherence restored", { sessionId: session.id, newCoherence, effectiveness: intervention.effectiveness }); } }, 12e4); } /** * Create a checkpoint of session state */ async checkpointSession(session) { const checkpointPath = path.join( this.baseDir, session.id, `checkpoint-${Date.now()}.json` ); const checkpointData = { timestamp: Date.now(), state: session.state, recentMetrics: session.metrics.slice(-3), currentPhase: session.state.currentPhase, completedMilestones: session.state.completedMilestones, // Include recent agent context contextSummary: await this.generateContextSummary(session) }; await fs.writeFile(checkpointPath, JSON.stringify(checkpointData, null, 2)); session.state.lastCheckpoint = Date.now(); logger.info("Session checkpoint created", { sessionId: session.id, checkpointPath }); } /** * Refresh session context to restore coherence */ async refreshSessionContext(session) { logger.info("Refreshing session context", { sessionId: session.id }); const refreshPrompt = await this.generateContextRefreshPrompt(session); await this.applyContextRefresh(session, refreshPrompt); session.state.refreshCount++; } /** * Restart session from last good checkpoint */ async restartSession(session) { logger.info("Restarting session from checkpoint", { sessionId: session.id }); const checkpoint = await this.loadLatestCheckpoint(session); if (checkpoint) { session.state = { ...checkpoint.state }; await this.restartAgentFromCheckpoint(session, checkpoint); } else { await this.restartAgentFromBeginning(session); } } /** * Initialize workspace for a coherence session */ async initializeSessionWorkspace(session) { const sessionDir = path.join(this.baseDir, session.id); await fs.mkdir(sessionDir, { recursive: true }); const manifest = { sessionId: session.id, agent: session.agent, task: session.task, config: session.config, createdAt: Date.now() }; await fs.writeFile( path.join(sessionDir, "manifest.json"), JSON.stringify(manifest, null, 2) ); } /** * Launch the actual agent work session */ async launchAgentSession(session) { const sessionDir = path.join(this.baseDir, session.id); const ralph = new RalphStackMemoryBridge({ baseDir: sessionDir, maxIterations: Math.ceil(session.config.maxDuration / 5), // ~5 min per iteration useStackMemory: true }); await ralph.initialize({ task: this.buildExtendedCoherencePrompt(session), criteria: session.task.breakpoints.join("\n") }); ralph.run().catch((error) => { logger.error("Extended coherence session failed", { sessionId: session.id, error: error.message }); session.state.status = "failed"; }); } /** * Build prompt optimized for extended coherence */ buildExtendedCoherencePrompt(session) { return ` # EXTENDED COHERENCE WORK SESSION ## Your Mission ${session.task.description} ## Session Parameters - Estimated Duration: ${session.task.estimatedDuration} minutes - Maximum Duration: ${session.config.maxDuration} minutes - Coherence Threshold: ${session.config.coherenceThreshold * 100}% ## Coherence Guidelines 1. **Maintain Focus**: Stay on task throughout the entire session 2. **Track Progress**: Document incremental progress at each step 3. **Context Awareness**: Reference previous work and maintain consistency 4. **Quality Control**: Regularly assess your output quality 5. **Milestone Reporting**: Report when you reach natural breakpoints ## Breakpoints & Milestones ${session.task.breakpoints.map((bp, i) => `${i + 1}. ${bp}`).join("\n")} ## Extended Session Strategy - Take regular checkpoint breaks (every ${session.config.checkpointInterval} minutes) - Summarize your progress regularly - Ask for context refresh if you feel you're losing focus - Maintain awareness of the overall project goal - Break complex tasks into smaller, manageable chunks ## Memory Palace (if enabled) ${session.config.enableMemoryPalace ? ` Use structured memory organization: - **Project Context**: Overall goals and requirements - **Current Status**: What's been completed and what's next - **Working Memory**: Current task details and immediate context - **Reference Memory**: Important patterns, decisions, and learnings ` : ""} ## Success Criteria - Complete the task within the allocated time - Maintain high output quality throughout - Document progress and decisions clearly - Stay coherent and focused for the entire session Begin your extended coherence work session now. `; } // Placeholder implementations for helper methods async getRecentAgentOutputs(session) { return []; } assessOutputQuality(outputs) { return 0.8; } assessContextRetention(outputs, task) { return 0.7; } assessTaskRelevance(outputs, task) { return 0.9; } calculateRepetitionRate(outputs) { return 0.1; } calculateDivergenceRate(outputs, task) { return 0.05; } calculateErrorRate(outputs) { return 0.02; } calculateProgressRate(session) { return 2.5; } async getMemoryUsage(session) { return 150; } async getContextWindowUsage(session) { return 65; } generateBreakpoints(taskConfig) { return [ "Initial analysis complete", "Core implementation finished", "Testing phase complete", "Final review and cleanup done" ]; } async generateContextSummary(session) { return `Session ${session.id} context summary`; } async generateContextRefreshPrompt(session) { return "Context refresh prompt"; } async applyContextRefresh(session, prompt) { } async loadLatestCheckpoint(session) { return null; } async restartAgentFromCheckpoint(session, checkpoint) { } async restartAgentFromBeginning(session) { } async provideGuidance(session, reason) { } /** * Get extended coherence capabilities */ getCoherenceCapabilities() { const activeSessions = Array.from(this.activeSessions.values()); return { maxSessionDuration: Math.max(...activeSessions.map((s) => s.config.maxDuration)), activeSessionCount: activeSessions.filter((s) => s.state.status === "active").length, averageCoherence: activeSessions.reduce((sum, s) => { const recent = s.metrics.slice(-1)[0]; return sum + (recent ? this.calculateOverallCoherence(recent) : 0); }, 0) / activeSessions.length, totalInterventions: activeSessions.reduce((sum, s) => sum + s.interventions.length, 0) }; } } var extended_coherence_sessions_default = ExtendedCoherenceManager; export { ExtendedCoherenceManager, extended_coherence_sessions_default as default }; //# sourceMappingURL=extended-coherence-sessions.js.map