UNPKG

minimax-mcp-tools

Version:

Async MCP server with Minimax API integration for image generation and text-to-speech

104 lines 3.33 kB
import { MinimaxRateLimitError } from '../utils/error-handler.js'; export class RateLimiter { rpm; burst; window; interval; tokens; lastRefill; queue; constructor({ rpm, burst = 1, window = 60000 }) { this.rpm = rpm; this.burst = burst; this.window = window; this.interval = window / rpm; this.tokens = burst; this.lastRefill = Date.now(); this.queue = []; } async acquire() { return new Promise((resolve, reject) => { this.queue.push({ resolve, reject, timestamp: Date.now() }); this.processQueue(); }); } processQueue() { if (this.queue.length === 0) return; this.refillTokens(); while (this.queue.length > 0 && this.tokens > 0) { const request = this.queue.shift(); if (!request) break; this.tokens--; const delay = Math.max(0, this.interval - (Date.now() - this.lastRefill)); setTimeout(() => this.processQueue(), delay); request.resolve(); } } refillTokens() { const now = Date.now(); const timePassed = now - this.lastRefill; const tokensToAdd = Math.floor(timePassed / this.interval); if (tokensToAdd > 0) { this.tokens = Math.min(this.burst, this.tokens + tokensToAdd); this.lastRefill = now; } } getStatus() { this.refillTokens(); return { tokens: this.tokens, queueLength: this.queue.length, rpm: this.rpm, burst: this.burst }; } reset() { this.tokens = this.burst; this.lastRefill = Date.now(); this.queue = []; } } export class AdaptiveRateLimiter extends RateLimiter { consecutiveErrors; originalRpm; backoffFactor; recoveryFactor; maxBackoff; constructor(config) { super(config); this.consecutiveErrors = 0; this.originalRpm = this.rpm; this.backoffFactor = config.backoffFactor || 0.5; this.recoveryFactor = config.recoveryFactor || 1.1; this.maxBackoff = config.maxBackoff || 5; } onSuccess() { if (this.consecutiveErrors > 0) { this.consecutiveErrors = Math.max(0, this.consecutiveErrors - 1); if (this.consecutiveErrors === 0) { this.rpm = Math.min(this.originalRpm, this.rpm * this.recoveryFactor); this.interval = this.window / this.rpm; } } } onError(error) { if (error instanceof MinimaxRateLimitError) { this.consecutiveErrors++; const backoffMultiplier = Math.pow(this.backoffFactor, Math.min(this.consecutiveErrors, this.maxBackoff)); this.rpm = Math.max(1, this.originalRpm * backoffMultiplier); this.interval = this.window / this.rpm; this.tokens = Math.min(this.tokens, Math.floor(this.burst * backoffMultiplier)); } } getAdaptiveStatus() { return { ...this.getStatus(), consecutiveErrors: this.consecutiveErrors, adaptedRpm: this.rpm, originalRpm: this.originalRpm }; } } //# sourceMappingURL=rate-limiter.js.map