/**
 * 도구 등록 및 관리 시스템
 * @memento/core: MCP/서버에서 공유하는 도구 레지스트리
 */
import { logger } from '../shared/utils/logger.js';
export class ToolRegistry {
    tools = new Map();
    config;
    metrics = new Map();
    cache = new Map();
    constructor(config) {
        this.config = {
            enableLogging: true,
            enableMetrics: true,
            maxExecutionTime: 30000,
            enableCaching: false,
            cacheSize: 100,
            ...config
        };
    }
    register(tool) {
        if (this.tools.has(tool.name)) {
            this.log(`Tool ${tool.name} already exists, replacing`, 'warn');
        }
        this.tools.set(tool.name, tool);
        if (this.config.enableMetrics) {
            this.metrics.set(tool.name, {
                name: tool.name,
                totalExecutions: 0,
                successfulExecutions: 0,
                failedExecutions: 0,
                averageExecutionTime: 0,
                lastExecution: null,
                errorRate: 0
            });
        }
        this.log(`Tool registered: ${tool.name}`);
    }
    registerAll(tools) {
        for (const tool of tools) {
            this.register(tool);
        }
        this.log(`Registered ${tools.length} tools`);
    }
    get(name) {
        return this.tools.get(name);
    }
    getAll() {
        return Array.from(this.tools.values());
    }
    async execute(name, params, context) {
        const tool = this.get(name);
        if (!tool) {
            throw new Error(`Unknown tool: ${name}`);
        }
        if (this.config.enableCaching) {
            const cacheKey = this.generateCacheKey(name, params);
            const cached = this.cache.get(cacheKey);
            if (cached && Date.now() - cached.timestamp < cached.ttl) {
                this.log(`Cache hit for tool: ${name}`);
                return cached.result;
            }
        }
        const startTime = Date.now();
        let result;
        try {
            result = await Promise.race([
                tool.handler(params, context),
                new Promise((_, reject) => {
                    setTimeout(() => reject(new Error(`Tool execution timeout: ${name}`)), this.config.maxExecutionTime);
                })
            ]);
            if (this.config.enableMetrics) {
                this.updateMetrics(name, true, Date.now() - startTime);
            }
            if (this.config.enableCaching && result.success) {
                this.cacheResult(name, params, result);
            }
            this.log(`Tool executed successfully: ${name}`, { duration: Date.now() - startTime });
            return result;
        }
        catch (error) {
            if (this.config.enableMetrics) {
                this.updateMetrics(name, false, Date.now() - startTime);
            }
            this.log(`Tool execution failed: ${name}`, { error: error instanceof Error ? error.message : String(error) }, 'error');
            throw error;
        }
    }
    has(name) {
        return this.tools.has(name);
    }
    remove(name) {
        const removed = this.tools.delete(name);
        if (removed)
            this.metrics.delete(name);
        return removed;
    }
    clear() {
        this.tools.clear();
        this.metrics.clear();
        this.cache.clear();
    }
    size() {
        return this.tools.size;
    }
    getNames() {
        return Array.from(this.tools.keys());
    }
    updateMetrics(name, success, executionTime) {
        const metric = this.metrics.get(name);
        if (!metric)
            return;
        metric.totalExecutions++;
        if (success)
            metric.successfulExecutions++;
        else
            metric.failedExecutions++;
        metric.averageExecutionTime =
            (metric.averageExecutionTime * (metric.totalExecutions - 1) + executionTime) / metric.totalExecutions;
        metric.lastExecution = new Date();
        metric.errorRate = metric.failedExecutions / metric.totalExecutions;
    }
    generateCacheKey(name, params) {
        return `${name}:${JSON.stringify(params)}`;
    }
    cacheResult(name, params, result) {
        if (this.cache.size >= this.config.cacheSize) {
            const oldestKey = this.cache.keys().next().value;
            if (oldestKey)
                this.cache.delete(oldestKey);
        }
        this.cache.set(this.generateCacheKey(name, params), {
            result,
            timestamp: Date.now(),
            ttl: 5 * 60 * 1000
        });
    }
    log(message, data, level = 'info') {
        if (!this.config.enableLogging)
            return;
        const timestamp = new Date().toISOString();
        const logMessage = `[${timestamp}] [ToolRegistry] [${level.toUpperCase()}] ${message}`;
        switch (level) {
            case 'error':
                logger.error(logMessage, data ? { data } : {});
                break;
            case 'warn':
                logger.warn(logMessage, data ? { data } : {});
                break;
            default:
                logger.info(logMessage, data ? { data } : {});
        }
    }
}
//# sourceMappingURL=tool-registry.js.map