const DEFAULT_BATCH_WINDOW = 100; // ms
const DEFAULT_MAX_BATCH_SIZE = 5;
/**
 * Collects pending tool calls and groups compatible ones into batches.
 */
export class Batcher {
    pending = new Map();
    config;
    constructor(config) {
        this.config = {
            batchWindow: config?.batchWindow ?? DEFAULT_BATCH_WINDOW,
            maxBatchSize: config?.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE,
        };
    }
    /**
     * Add a call to the pending queue. Returns batch request if ready.
     */
    addCall(toolName, input) {
        if (!this.pending.has(toolName)) {
            this.pending.set(toolName, []);
        }
        const queue = this.pending.get(toolName);
        if (queue) {
            queue.push({ input, timestamp: Date.now() });
            // Check if batch is ready (max size reached)
            if (queue.length >= this.config.maxBatchSize) {
                return this.flushTool(toolName);
            }
        }
        return null;
    }
    /**
     * Flush all pending calls for a tool into a batch request.
     */
    flushTool(toolName) {
        const queue = this.pending.get(toolName);
        if (!queue || queue.length === 0) {
            return null;
        }
        const inputs = queue.map((e) => e.input);
        this.pending.delete(toolName);
        return {
            toolName,
            inputs,
            batchWindow: this.config.batchWindow,
            maxBatchSize: this.config.maxBatchSize,
        };
    }
    /**
     * Flush all expired batches (past the batch window).
     */
    flushExpired() {
        const now = Date.now();
        const results = [];
        for (const [toolName, queue] of this.pending) {
            const oldest = queue[0];
            if (oldest && now - oldest.timestamp >= this.config.batchWindow) {
                const batch = this.flushTool(toolName);
                if (batch) {
                    results.push(batch);
                }
            }
        }
        return results;
    }
    /**
     * Get the number of pending calls for a tool.
     */
    pendingCount(toolName) {
        return this.pending.get(toolName)?.length ?? 0;
    }
    /**
     * Get total pending calls across all tools.
     */
    totalPending() {
        let total = 0;
        for (const queue of this.pending.values()) {
            total += queue.length;
        }
        return total;
    }
    /**
     * Clear all pending calls.
     */
    clear() {
        this.pending.clear();
    }
}
//# sourceMappingURL=batcher.js.map