minimax-mcp-tools
Version:
Async MCP server with Minimax API integration for image generation and text-to-speech
162 lines • 5.44 kB
JavaScript
import { AdaptiveRateLimiter } from './rate-limiter.js';
import { RATE_LIMITS } from '../config/constants.js';
import { MinimaxError, ErrorHandler } from '../utils/error-handler.js';
export class TaskManager {
tasks;
completedTasks;
taskCounter;
constructor() {
this.tasks = new Map();
this.completedTasks = new Map();
this.taskCounter = 0;
}
generateTaskId() {
return `task_${++this.taskCounter}`;
}
async submit(fn, taskId = null) {
taskId = taskId || this.generateTaskId();
const taskPromise = Promise.resolve()
.then(fn)
.then(result => {
this.completedTasks.set(taskId, { success: true, result, completedAt: Date.now() });
return result;
})
.catch(error => {
const processedError = ErrorHandler.handleAPIError(error);
this.completedTasks.set(taskId, { success: false, error: processedError, completedAt: Date.now() });
throw processedError;
})
.finally(() => {
this.tasks.delete(taskId);
});
this.tasks.set(taskId, taskPromise);
return { taskId, promise: taskPromise };
}
async barrier() {
const activeTasks = Array.from(this.tasks.values());
if (activeTasks.length > 0) {
await Promise.allSettled(activeTasks);
}
const results = Array.from(this.completedTasks.entries()).map(([taskId, taskResult]) => ({
taskId,
...taskResult
}));
return { completed: results.length, results };
}
getTaskStatus(taskId) {
if (this.tasks.has(taskId)) {
return { status: 'running', taskId };
}
if (this.completedTasks.has(taskId)) {
return { status: 'completed', taskId, ...this.completedTasks.get(taskId) };
}
return { status: 'not_found', taskId };
}
getAllTasksStatus() {
const running = Array.from(this.tasks.keys()).map(taskId => ({ taskId, status: 'running' }));
const completed = Array.from(this.completedTasks.entries()).map(([taskId, result]) => ({
taskId,
status: 'completed',
...result
}));
return { running, completed, total: running.length + completed.length };
}
clearCompletedTasks() {
const count = this.completedTasks.size;
this.completedTasks.clear();
return count;
}
getStats() {
return {
activeTasks: this.tasks.size,
completedTasks: this.completedTasks.size,
totalProcessed: this.taskCounter
};
}
}
export class RateLimitedTaskManager extends TaskManager {
rateLimiters;
metrics;
taskCounters;
constructor(options = {}) {
super();
this.rateLimiters = {
image: new AdaptiveRateLimiter({
...RATE_LIMITS.IMAGE,
backoffFactor: options.backoffFactor || 0.7,
recoveryFactor: options.recoveryFactor || 1.05
}),
tts: new AdaptiveRateLimiter({
...RATE_LIMITS.TTS,
backoffFactor: options.backoffFactor || 0.7,
recoveryFactor: options.recoveryFactor || 1.05
})
};
this.metrics = {
image: { requests: 0, successes: 0, errors: 0 },
tts: { requests: 0, successes: 0, errors: 0 }
};
this.taskCounters = {
image: 0,
tts: 0
};
}
async submitImageTask(fn, taskId = null) {
if (!taskId) {
taskId = `img-${++this.taskCounters.image}`;
}
return this.submitRateLimitedTask('image', fn, taskId);
}
async submitTTSTask(fn, taskId = null) {
if (!taskId) {
taskId = `tts-${++this.taskCounters.tts}`;
}
return this.submitRateLimitedTask('tts', fn, taskId);
}
async submitRateLimitedTask(type, fn, taskId = null) {
const rateLimiter = this.rateLimiters[type];
if (!rateLimiter) {
throw new MinimaxError(`Unknown task type: ${type}`);
}
const wrappedFn = async () => {
await rateLimiter.acquire();
this.metrics[type].requests++;
try {
const result = await fn();
this.metrics[type].successes++;
rateLimiter.onSuccess();
return result;
}
catch (error) {
this.metrics[type].errors++;
rateLimiter.onError(error);
throw error;
}
};
return this.submit(wrappedFn, taskId);
}
getRateLimiterStatus() {
return {
image: this.rateLimiters.image.getAdaptiveStatus(),
tts: this.rateLimiters.tts.getAdaptiveStatus()
};
}
getMetrics() {
return {
...this.metrics,
rateLimiters: this.getRateLimiterStatus()
};
}
resetMetrics() {
this.metrics = {
image: { requests: 0, successes: 0, errors: 0 },
tts: { requests: 0, successes: 0, errors: 0 }
};
this.taskCounters = {
image: 0,
tts: 0
};
Object.values(this.rateLimiters).forEach(limiter => limiter.reset());
}
}
//# sourceMappingURL=task-manager.js.map