export class ConversationCache {
    static scopes = new Map();
    maxSize;
    ttlMs;
    scopeKey;
    constructor(maxSize = 100, ttlHours = 2, scopeKey) {
        this.maxSize = maxSize;
        this.ttlMs = ttlHours * 60 * 60 * 1000;
        this.scopeKey =
            typeof scopeKey === 'string' && scopeKey.trim() !== ''
                ? scopeKey.trim()
                : (scopeKey ?? Symbol('conversation-cache-scope'));
    }
    getOrCreateScope() {
        let scope = ConversationCache.scopes.get(this.scopeKey);
        if (!scope) {
            scope = { cache: new Map(), accessOrder: [] };
            ConversationCache.scopes.set(this.scopeKey, scope);
        }
        return scope;
    }
    peekScope() {
        return ConversationCache.scopes.get(this.scopeKey);
    }
    generateKey(conversationId, parentId) {
        return `${conversationId}:${parentId}`;
    }
    evictIfNeeded(scope) {
        while (scope.accessOrder.length > this.maxSize) {
            const oldestKey = scope.accessOrder.shift();
            if (oldestKey) {
                scope.cache.delete(oldestKey);
            }
        }
    }
    updateAccessOrder(scope, key) {
        const index = scope.accessOrder.indexOf(key);
        if (index > -1) {
            scope.accessOrder.splice(index, 1);
        }
        scope.accessOrder.push(key);
    }
    isExpired(entry) {
        return Date.now() - entry.timestamp > this.ttlMs;
    }
    set(conversationId, parentId, messages, promptTokensAccum = 0) {
        const scope = this.getOrCreateScope();
        const key = this.generateKey(conversationId, parentId);
        const entry = {
            conversationId,
            parentId,
            messages,
            timestamp: Date.now(),
            promptTokensAccum,
        };
        scope.cache.set(key, entry);
        this.updateAccessOrder(scope, key);
        this.evictIfNeeded(scope);
    }
    get(conversationId, parentId) {
        const scope = this.peekScope();
        if (!scope) {
            return null;
        }
        const key = this.generateKey(conversationId, parentId);
        const entry = scope.cache.get(key);
        if (!entry) {
            return null;
        }
        if (this.isExpired(entry)) {
            scope.cache.delete(key);
            const index = scope.accessOrder.indexOf(key);
            if (index > -1) {
                scope.accessOrder.splice(index, 1);
            }
            if (scope.cache.size === 0) {
                ConversationCache.scopes.delete(this.scopeKey);
            }
            return null;
        }
        this.updateAccessOrder(scope, key);
        return entry.messages;
    }
    has(conversationId, parentId) {
        const scope = this.peekScope();
        if (!scope) {
            return false;
        }
        const key = this.generateKey(conversationId, parentId);
        const entry = scope.cache.get(key);
        if (!entry) {
            return false;
        }
        if (this.isExpired(entry)) {
            scope.cache.delete(key);
            const index = scope.accessOrder.indexOf(key);
            if (index > -1) {
                scope.accessOrder.splice(index, 1);
            }
            if (scope.cache.size === 0) {
                ConversationCache.scopes.delete(this.scopeKey);
            }
            return false;
        }
        return true;
    }
    clear() {
        const scope = this.peekScope();
        if (!scope) {
            return;
        }
        scope.cache.clear();
        scope.accessOrder.length = 0;
        ConversationCache.scopes.delete(this.scopeKey);
    }
    size() {
        const scope = this.peekScope();
        return scope ? scope.cache.size : 0;
    }
    getAccumulatedTokens(conversationId, parentId) {
        const scope = this.peekScope();
        if (!scope) {
            return 0;
        }
        const key = this.generateKey(conversationId, parentId);
        const entry = scope.cache.get(key);
        if (!entry || this.isExpired(entry)) {
            if (entry) {
                scope.cache.delete(key);
                const index = scope.accessOrder.indexOf(key);
                if (index > -1) {
                    scope.accessOrder.splice(index, 1);
                }
                if (scope.cache.size === 0) {
                    ConversationCache.scopes.delete(this.scopeKey);
                }
            }
            return 0;
        }
        return entry.promptTokensAccum;
    }
    updateTokenCount(conversationId, parentId, additionalTokens) {
        const scope = this.peekScope();
        if (!scope) {
            return;
        }
        const key = this.generateKey(conversationId, parentId);
        const entry = scope.cache.get(key);
        if (entry && !this.isExpired(entry)) {
            entry.promptTokensAccum += additionalTokens;
            this.updateAccessOrder(scope, key);
        }
    }
    invalidate(conversationId, parentId) {
        const scope = this.peekScope();
        if (!scope) {
            return;
        }
        const key = this.generateKey(conversationId, parentId);
        scope.cache.delete(key);
        const index = scope.accessOrder.indexOf(key);
        if (index > -1) {
            scope.accessOrder.splice(index, 1);
        }
        if (scope.cache.size === 0) {
            ConversationCache.scopes.delete(this.scopeKey);
        }
    }
}
//# sourceMappingURL=ConversationCache.js.map