import { countTokens } from './counter.js';
import { ResponseCache } from './response-cache.js';
import { compress, selectStrategy } from './context-compressor.js';
import { Deduplicator } from './deduplicator.js';
import { Batcher } from './batcher.js';
import { IncrementalTracker } from './incremental.js';
import { BudgetManager } from './budget.js';
import { OptimizationReporter } from './reporter.js';
const DEFAULT_CONFIG = {
    cacheEnabled: true,
    compressionEnabled: true,
    deduplicationEnabled: true,
    batchingEnabled: false, // opt-in
    incrementalEnabled: true,
    budgetLimit: null,
};
/**
 * Central orchestrator for all token optimization components.
 */
export class TokenOptimizer {
    cache;
    deduplicator;
    batcher;
    incremental;
    budget;
    reporter;
    config;
    sessionId;
    constructor(sessionId, config) {
        this.sessionId = sessionId;
        this.config = { ...DEFAULT_CONFIG, ...config };
        this.cache = new ResponseCache();
        this.deduplicator = new Deduplicator();
        this.batcher = new Batcher();
        this.incremental = new IncrementalTracker();
        this.budget = new BudgetManager({ limit: this.config.budgetLimit });
        this.reporter = new OptimizationReporter();
    }
    /**
     * Optimize a tool's input before execution.
     * Returns cached result if available, or compressed input.
     */
    optimizeInput(toolName, input) {
        const inputTokens = countTokens(input).tokens;
        this.reporter.recordUsage(toolName, inputTokens);
        this.budget.consume(inputTokens, toolName);
        // Check cache
        if (this.config.cacheEnabled) {
            const cacheKey = ResponseCache.hashKey(`${toolName}:${input}`);
            const cached = this.cache.get(cacheKey);
            if (cached !== undefined) {
                this.reporter.recordCacheHit(toolName, countTokens(cached).tokens);
                return { cached: true, cachedResult: cached, processedInput: input };
            }
            this.reporter.recordCacheMiss(toolName);
        }
        // Compress if enabled and input is large
        let processed = input;
        if (this.config.compressionEnabled && inputTokens > 2000) {
            const strategy = selectStrategy(input);
            const result = compress(input, strategy);
            processed = result.compressed;
            this.reporter.recordCompression(result.ratio);
        }
        return { cached: false, processedInput: processed };
    }
    /**
     * Optimize a tool's response after execution.
     */
    optimizeResponse(toolName, input, response) {
        const responseTokens = countTokens(response).tokens;
        this.budget.consume(responseTokens, toolName);
        let result = response;
        // Cache the response
        if (this.config.cacheEnabled) {
            const cacheKey = ResponseCache.hashKey(`${toolName}:${input}`);
            this.cache.set(cacheKey, response);
        }
        // Deduplicate
        if (this.config.deduplicationEnabled) {
            const dedupResult = this.deduplicator.deduplicate(result, this.sessionId);
            if (dedupResult.ratio > 0) {
                result = dedupResult.deduplicated;
                this.reporter.recordDeduplication(dedupResult.ratio);
            }
        }
        // Compress if over budget
        if (this.config.compressionEnabled && this.budget.isOverBudget()) {
            const strategy = selectStrategy(result);
            const compressed = compress(result, strategy);
            result = compressed.compressed;
            this.reporter.recordCompression(compressed.ratio);
        }
        return result;
    }
    /**
     * Generate optimization report for this session.
     */
    getReport() {
        return this.reporter.generateReport(this.sessionId, this.cache.stats());
    }
    /**
     * Get human-readable report.
     */
    getFormattedReport() {
        return this.reporter.formatReport(this.getReport());
    }
    /**
     * Get current configuration.
     */
    getConfig() {
        return { ...this.config };
    }
    /**
     * Reset all optimization state.
     */
    reset() {
        this.cache.clear();
        this.deduplicator.clear();
        this.batcher.clear();
        this.incremental.clear();
        this.budget.reset();
        this.reporter.reset();
    }
}
//# sourceMappingURL=optimizer.js.map