UNPKG

@nanocollective/nanocoder

Version:

A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter

155 lines 5 kB
import { getModelContextLimit, getSessionContextLimit } from '../models/index.js'; import { createTokenizer } from '../tokenization/index.js'; import { compressionBackup } from './compression-backup.js'; import { compressMessages } from './message-compression.js'; /** * Singleton class for managing auto-compact session overrides. * Provides encapsulated state management instead of global mutable object. */ class AutoCompactSessionManager { _enabled = null; _threshold = null; _mode = null; get enabled() { return this._enabled; } get threshold() { return this._threshold; } get mode() { return this._mode; } setEnabled(enabled) { this._enabled = enabled; } setThreshold(threshold) { if (threshold !== null) { this._threshold = Math.max(50, Math.min(95, threshold)); } else { this._threshold = null; } } setMode(mode) { this._mode = mode; } reset() { this._enabled = null; this._threshold = null; this._mode = null; } } // Singleton instance const autoCompactSession = new AutoCompactSessionManager(); // Legacy export for backward compatibility export const autoCompactSessionOverrides = new Proxy({}, { get(_target, prop) { if (prop === 'enabled') return autoCompactSession.enabled; if (prop === 'threshold') return autoCompactSession.threshold; if (prop === 'mode') return autoCompactSession.mode; return undefined; }, set(_target, prop, value) { if (prop === 'enabled') autoCompactSession.setEnabled(value); else if (prop === 'threshold') autoCompactSession.setThreshold(value); else if (prop === 'mode') autoCompactSession.setMode(value); return true; }, }); /** * Perform auto-compact on messages (async) * Returns compressed messages if compression was performed, null otherwise */ export async function performAutoCompact(messages, systemMessage, provider, model, config, onNotify) { // Check if auto compact is enabled const enabled = autoCompactSessionOverrides.enabled !== null ? autoCompactSessionOverrides.enabled : config.enabled; if (!enabled) { return null; } // Get threshold const threshold = autoCompactSessionOverrides.threshold !== null ? autoCompactSessionOverrides.threshold : config.threshold; // Get mode const mode = autoCompactSessionOverrides.mode !== null ? autoCompactSessionOverrides.mode : config.mode; // Get context limit: session override takes priority let contextLimit; const sessionLimit = getSessionContextLimit(); if (sessionLimit !== null) { contextLimit = sessionLimit; } else { try { contextLimit = await getModelContextLimit(model); } catch { return null; } } if (!contextLimit) { return null; } // Create tokenizer let tokenizer; try { tokenizer = createTokenizer(provider, model); } catch { return null; } try { // Calculate current token count const allMessages = [systemMessage, ...messages]; let totalTokens = 0; for (const msg of allMessages) { totalTokens += tokenizer.countTokens(msg); } // Check if threshold is reached const usagePercentage = (totalTokens / contextLimit) * 100; if (usagePercentage < threshold) { return null; } compressionBackup.storeBackup(messages); const result = compressMessages(messages, tokenizer, { mode }); // Show notification if enabled if (config.notifyUser && onNotify) { const reduction = Math.round(result.reductionPercentage); onNotify(`Context at ${Math.round(usagePercentage)}% capacity - auto-compacting...\n\nContext Compacted: ${result.originalTokenCount.toLocaleString()} tokens → ${result.compressedTokenCount.toLocaleString()} tokens (${reduction}% reduction)`); } // Return compressed messages return result.compressedMessages; } finally { // Clean up tokenizer if (tokenizer?.free) { tokenizer.free(); } } } // Set session override for auto-compact enabled state export function setAutoCompactEnabled(enabled) { autoCompactSession.setEnabled(enabled); } // Set session override for auto-compact threshold export function setAutoCompactThreshold(threshold) { autoCompactSession.setThreshold(threshold); } // Set session override for auto-compact mode export function setAutoCompactMode(mode) { autoCompactSession.setMode(mode); } // Reset all session overrides export function resetAutoCompactSession() { autoCompactSession.reset(); } //# sourceMappingURL=auto-compact.js.map