@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
JavaScript
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