/**
 * Per-model token bucket rate limiter.
 * Default: 60 requests per minute per model.
 */
const buckets = new Map();
const DEFAULT_CONFIG = {
    maxRequests: 60,
    windowMs: 60_000,
};
function getBucket(modelId, config = DEFAULT_CONFIG) {
    let bucket = buckets.get(modelId);
    if (!bucket) {
        bucket = {
            tokens: config.maxRequests,
            lastRefill: Date.now(),
            lastAccessAt: Date.now(),
            maxTokens: config.maxRequests,
            refillRate: config.maxRequests / config.windowMs,
        };
        buckets.set(modelId, bucket);
    }
    bucket.lastAccessAt = Date.now();
    return bucket;
}
function refillBucket(bucket) {
    const now = Date.now();
    const elapsed = now - bucket.lastRefill;
    const tokensToAdd = elapsed * bucket.refillRate;
    bucket.tokens = Math.min(bucket.maxTokens, bucket.tokens + tokensToAdd);
    bucket.lastRefill = now;
}
/**
 * Check if a request to this model is allowed.
 */
export function checkRateLimit(modelId, config) {
    const bucket = getBucket(modelId, config);
    refillBucket(bucket);
    if (bucket.tokens >= 1) {
        bucket.tokens -= 1;
        return { allowed: true, remaining: Math.floor(bucket.tokens) };
    }
    // Calculate wait time for 1 token
    const waitMs = Math.ceil((1 - bucket.tokens) / bucket.refillRate);
    return { allowed: false, remaining: 0, retryAfterMs: waitMs };
}
/**
 * Get rate limit stats for all tracked models.
 */
export function getRateLimitStats() {
    const stats = {};
    for (const [modelId, bucket] of buckets) {
        refillBucket(bucket);
        const msUntilFull = bucket.tokens >= bucket.maxTokens
            ? 0
            : Math.ceil((bucket.maxTokens - bucket.tokens) / bucket.refillRate);
        stats[modelId] = {
            remaining: Math.floor(bucket.tokens),
            total: bucket.maxTokens,
            resetAtMs: Date.now() + msUntilFull,
        };
    }
    return stats;
}
/**
 * Prune stale rate limit buckets not accessed in the given window.
 * Call periodically (e.g., every 5 minutes) to prevent unbounded growth.
 */
export function pruneRateLimitBuckets(maxIdleMs = 300_000) {
    const now = Date.now();
    let pruned = 0;
    for (const [modelId, bucket] of buckets) {
        refillBucket(bucket);
        if (now - bucket.lastAccessAt >= maxIdleMs && bucket.tokens >= bucket.maxTokens) {
            buckets.delete(modelId);
            pruned++;
        }
    }
    return pruned;
}
/**
 * Reset all rate limit buckets (for testing).
 */
export function resetRateLimits() {
    buckets.clear();
}
//# sourceMappingURL=rate-limit.js.map