UNPKG

flashbacker

Version:

Claude Code state management with session continuity and AI personas

145 lines 6.54 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoContextManager = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const os_1 = __importDefault(require("os")); const session_token_parser_js_1 = require("../utils/session-token-parser.js"); const stderr_directive_js_1 = require("../utils/stderr-directive.js"); /** * AutoContextManager handles token monitoring and compaction detection * Based on Cline's context management patterns but adapted for Claude Code session logs */ class AutoContextManager { constructor(projectDir) { this.projectDir = projectDir; } /** * Get current token usage from session logs * Parses JSONL files for exact token counts from API responses */ async getCurrentTokenUsage() { const sessionInfo = await (0, session_token_parser_js_1.parseCurrentSessionTokens)(this.projectDir); return sessionInfo.currentContextTokens; } /** * Get current session information * Extracts session ID, message count, and token usage */ async getSessionInfo() { const sessionTokenInfo = await (0, session_token_parser_js_1.parseCurrentSessionTokens)(this.projectDir); return { sessionId: sessionTokenInfo.sessionId, messageCount: sessionTokenInfo.messageCount, tokenUsage: sessionTokenInfo.currentContextTokens, timestamp: sessionTokenInfo.timestamp, }; } /** * Check if todo update should be triggered * Based on 80% threshold or message count intervals */ async shouldTriggerTodoUpdate() { try { // Get current session info const currentInfo = await this.getSessionInfo(); // Get model configuration for threshold calculation const modelConfig = await this.getModelConfig(); // Progressive token thresholds (25%, 50%, 70%, 80%) const tokenPercentage = currentInfo.tokenUsage / modelConfig.contextWindow; const progressiveThresholds = tokenPercentage >= 0.25 || // 25% early reminder tokenPercentage >= 0.5 || // 50% regular update tokenPercentage >= 0.7 || // 70% warning tokenPercentage >= 0.8; // 80% critical // POST-COMPACTION DETECTION: 0-24% after activity suggests compaction occurred const lowContextAfterActivity = tokenPercentage < 0.25 && currentInfo.messageCount > 20 && currentInfo.tokenUsage > 1000; // Has some tokens but very low percentage // Message-based triggers (ranges that actually work) const messageRangeUpdate = currentInfo.messageCount > 50 && (Math.floor(currentInfo.messageCount / 50) % 4 === 0); // Every 4th group of 50 (200, 400, 600, etc.) // Simple periodic trigger (much less frequent) const periodicUpdate = currentInfo.messageCount > 100 && Math.floor(currentInfo.messageCount / 100) % 3 === 0; // Every 300 messages (300, 600, 900, etc.) return progressiveThresholds || lowContextAfterActivity || messageRangeUpdate || periodicUpdate; } catch (error) { console.error('Error checking todo update triggers:', error); return false; } } /** * Get model configuration from settings * Helper method for threshold calculations */ async getModelConfig() { try { const settingsPath = path_1.default.join(os_1.default.homedir(), '.claude', 'settings.json'); if (await fs_extra_1.default.pathExists(settingsPath)) { const settings = JSON.parse(await fs_extra_1.default.readFile(settingsPath, 'utf8')); const model = settings.model || 'sonnet'; // Parse context window from model name let contextWindow = 200000; // Default for standard models if (model.includes('[1m]')) { contextWindow = 1000000; // 1M context models } else if (model.includes('gpt-4')) { contextWindow = 128000; // GPT-4 context } return { model, contextWindow, warningThreshold: Math.floor(contextWindow * 0.8), emergencyThreshold: Math.floor(contextWindow * 0.95), }; } // Fallback to conservative defaults return { model: 'unknown', contextWindow: 200000, warningThreshold: 160000, emergencyThreshold: 190000, }; } catch (error) { console.error('Error reading model config:', error); return { model: 'error', contextWindow: 200000, warningThreshold: 160000, emergencyThreshold: 190000, }; } } /** * Direct Claude to appropriate template based on context state * Detects post-compaction scenarios and triggers session restoration */ async directClaudeToMaintenanceTemplate() { try { const currentInfo = await this.getSessionInfo(); const modelConfig = await this.getModelConfig(); const tokenPercentage = currentInfo.tokenUsage / modelConfig.contextWindow; // DETECT POST-COMPACTION: Low context after activity suggests compaction const isPostCompaction = tokenPercentage < 0.25 && currentInfo.messageCount > 20 && currentInfo.tokenUsage > 1000; if (isPostCompaction) { // Context was compacted - trigger session restoration (0, stderr_directive_js_1.emitCompactionDirective)(Math.round(tokenPercentage * 100)); } else { // Normal maintenance (0, stderr_directive_js_1.emitMaintenanceDirective)(Math.round(tokenPercentage * 100)); } } catch (error) { console.error('Auto-context directive failed:', error); } } } exports.AutoContextManager = AutoContextManager; //# sourceMappingURL=auto-context-manager.js.map