/**
 * Enhanced Error Handling Utility
 * Implements MCP Design Guide Section 5.1 principles for error visibility and self-correction
 */
export class MCPError extends Error {
    code;
    category;
    details;
    context;
    recoverable;
    suggestedActions;
    originalError;
    constructor(error) {
        super(error.message);
        this.name = 'MCPError';
        this.code = error.code;
        this.category = error.category;
        this.details = error.details;
        this.context = error.context;
        this.recoverable = error.recoverable;
        this.suggestedActions = error.suggestedActions;
        this.originalError = error.originalError;
    }
    toMCPResponse() {
        return {
            content: [
                {
                    type: 'text',
                    text: this.formatErrorMessage(),
                },
            ],
            structured: {
                error: true,
                code: this.code,
                category: this.category,
                recoverable: this.recoverable,
                details: this.details,
                context: this.context,
                suggestedActions: this.suggestedActions,
            },
        };
    }
    formatErrorMessage() {
        let message = `❌ **Error**: ${this.message}\n\n`;
        message += `🔍 **Code**: ${this.code}\n`;
        message += `📋 **Category**: ${this.category}\n`;
        if (Object.keys(this.details).length > 0) {
            message += `📝 **Details**:\n`;
            for (const [key, value] of Object.entries(this.details)) {
                message += `  • ${key}: ${JSON.stringify(value)}\n`;
            }
        }
        if (this.context && Object.keys(this.context).length > 0) {
            message += `🎯 **Context**:\n`;
            for (const [key, value] of Object.entries(this.context)) {
                message += `  • ${key}: ${JSON.stringify(value)}\n`;
            }
        }
        if (this.suggestedActions && this.suggestedActions.length > 0) {
            message += `\n💡 **Suggested Actions**:\n`;
            this.suggestedActions.forEach((action, index) => {
                message += `${index + 1}. ${action}\n`;
            });
        }
        if (this.recoverable) {
            message += `\n🔄 This error is recoverable. You can retry the operation.`;
        }
        return message;
    }
}
export class ErrorHandler {
    static DEFAULT_RETRY_CONFIG = {
        maxAttempts: 3,
        baseDelay: 1000,
        maxDelay: 10000,
        backoffMultiplier: 2,
        retryableErrors: ['NETWORK_ERROR', 'TIMEOUT', 'RATE_LIMIT', 'TEMPORARY_UNAVAILABLE'],
    };
    /**
     * Wraps a function with comprehensive error handling and retry logic
     */
    static async withErrorHandling(operation, context, retryConfig = {}) {
        const config = { ...this.DEFAULT_RETRY_CONFIG, ...retryConfig };
        let lastError;
        for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {
            try {
                return await operation();
            }
            catch (error) {
                lastError = error;
                const mcpError = this.transformError(error, context);
                // Don't retry non-recoverable errors
                if (!mcpError.recoverable || attempt === config.maxAttempts) {
                    throw mcpError;
                }
                // Don't retry errors that aren't in the retryable list
                if (!config.retryableErrors.includes(mcpError.code)) {
                    throw mcpError;
                }
                // Calculate exponential backoff delay
                const delay = Math.min(config.baseDelay * Math.pow(config.backoffMultiplier, attempt - 1), config.maxDelay);
                console.error(`[${context.module}:${context.tool}] Attempt ${attempt} failed, retrying in ${delay}ms:`, mcpError.message);
                await this.sleep(delay);
            }
        }
        // This should never be reached, but TypeScript requires it
        throw this.transformError(lastError, context);
    }
    /**
     * Transform generic errors into detailed MCP errors with full visibility
     */
    static transformError(error, context) {
        // Network/HTTP errors
        if (error.message.includes('fetch') || error.message.includes('network')) {
            return new MCPError({
                message: `Network connection failed: ${error.message}`,
                code: 'NETWORK_ERROR',
                category: 'external',
                details: {
                    originalMessage: error.message,
                    stack: error.stack,
                },
                context,
                recoverable: true,
                suggestedActions: [
                    'Check your internet connection',
                    'Verify the service endpoint is accessible',
                    'Try again in a few moments',
                ],
                originalError: error,
            });
        }
        // Validation errors
        if (error.message.includes('required') || error.message.includes('invalid')) {
            return new MCPError({
                message: `Input validation failed: ${error.message}`,
                code: 'VALIDATION_ERROR',
                category: 'validation',
                details: {
                    originalMessage: error.message,
                    providedParams: context.params,
                },
                context,
                recoverable: true,
                suggestedActions: [
                    'Check all required parameters are provided',
                    'Verify parameter types match the schema',
                    'Review the tool documentation for correct usage',
                ],
                originalError: error,
            });
        }
        // File system errors
        if (error.message.includes('ENOENT') || error.message.includes('EACCES')) {
            return new MCPError({
                message: `File system operation failed: ${error.message}`,
                code: 'FILE_SYSTEM_ERROR',
                category: 'system',
                details: {
                    originalMessage: error.message,
                    operation: context.tool,
                },
                context,
                recoverable: false,
                suggestedActions: [
                    'Check file paths are correct and accessible',
                    'Verify you have necessary permissions',
                    'Ensure the target directory exists',
                ],
                originalError: error,
            });
        }
        // Rate limiting
        if (error.message.includes('rate limit') || error.message.includes('429')) {
            return new MCPError({
                message: `Rate limit exceeded: ${error.message}`,
                code: 'RATE_LIMIT',
                category: 'external',
                details: {
                    originalMessage: error.message,
                },
                context,
                recoverable: true,
                suggestedActions: [
                    'Wait before retrying the operation',
                    'Reduce the frequency of requests',
                    'Check API quota and limits',
                ],
                originalError: error,
            });
        }
        // Authentication errors
        if (error.message.includes('unauthorized') || error.message.includes('401')) {
            return new MCPError({
                message: `Authentication failed: ${error.message}`,
                code: 'AUTH_ERROR',
                category: 'external',
                details: {
                    originalMessage: error.message,
                },
                context,
                recoverable: false,
                suggestedActions: [
                    'Check your credentials are correct',
                    'Verify API keys or tokens are valid',
                    'Ensure you have necessary permissions',
                ],
                originalError: error,
            });
        }
        // Generic error fallback
        return new MCPError({
            message: `Unexpected error in ${context.module}.${context.tool}: ${error.message}`,
            code: 'UNKNOWN_ERROR',
            category: 'system',
            details: {
                originalMessage: error.message,
                stack: error.stack,
                errorType: error.constructor.name,
            },
            context,
            recoverable: false,
            suggestedActions: [
                'Review the error details for specific issues',
                'Check system logs for additional information',
                'Report this error if it persists',
            ],
            originalError: error,
        });
    }
    /**
     * Create a validation error for schema violations
     */
    static createValidationError(field, value, constraint, context) {
        return new MCPError({
            message: `Parameter '${field}' violates constraint: ${constraint}`,
            code: 'PARAMETER_VALIDATION_ERROR',
            category: 'validation',
            details: {
                field,
                value,
                constraint,
                valueType: typeof value,
            },
            context,
            recoverable: true,
            suggestedActions: [
                `Ensure '${field}' meets the requirement: ${constraint}`,
                'Check the tool documentation for valid parameter formats',
                'Verify the parameter type matches expectations',
            ],
        });
    }
    /**
     * Create a resource not found error
     */
    static createNotFoundError(resourceType, identifier, context) {
        return new MCPError({
            message: `${resourceType} not found: ${identifier}`,
            code: 'RESOURCE_NOT_FOUND',
            category: 'validation',
            details: {
                resourceType,
                identifier,
            },
            context,
            recoverable: false,
            suggestedActions: [
                `Verify the ${resourceType} ID '${identifier}' exists`,
                `Use list commands to find available ${resourceType}s`,
                'Check for typos in the identifier',
            ],
        });
    }
    /**
     * Create a dependency error for missing prerequisites
     */
    static createDependencyError(dependency, context) {
        return new MCPError({
            message: `Missing dependency: ${dependency}`,
            code: 'DEPENDENCY_ERROR',
            category: 'validation',
            details: {
                dependency,
                tool: context.tool,
            },
            context,
            recoverable: true,
            suggestedActions: [
                `Ensure ${dependency} is properly configured`,
                'Check prerequisite setup steps',
                'Initialize required components first',
            ],
        });
    }
    static sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    /**
     * Get detailed information about a specific error
     */
    async getErrorDetails(errorId) {
        // This would normally fetch from a database
        return {
            errorId,
            type: 'validation',
            severity: 'medium',
            message: 'Sample error for development',
            timestamp: new Date().toISOString(),
            tool: 'unknown',
            context: {},
            stackTrace: null,
            rootCause: null,
            suggestions: [],
            relatedErrors: []
        };
    }
    /**
     * Analyze patterns in errors
     */
    async analyzeErrorPatterns(options) {
        return {
            totalErrors: 0,
            patternsFound: [],
            recommendations: [],
            insights: []
        };
    }
    /**
     * Get timeline of errors
     */
    async getErrorTimeline(options) {
        return [];
    }
    /**
     * Generate error report
     */
    async generateErrorReport(options) {
        const content = options.outputFormat === 'markdown'
            ? '# Error Report\n\nNo errors to report.'
            : { errors: [], summary: 'No errors' };
        return {
            content,
            summary: { totalIssues: 0, critical: 0, high: 0, medium: 0, low: 0 },
            filePath: options.saveToFile ? '.atlas/reports/error-report.md' : undefined
        };
    }
    /**
     * Track error resolution
     */
    async resolveErrorSuggestion(options) {
        return {
            errorId: options.errorId,
            suggestionId: options.suggestionId,
            implementation: options.implementation,
            effectiveness: options.effectiveness,
            notes: options.notes,
            outcome: { success: true, message: 'Tracked' }
        };
    }
    /**
     * Simulate error recovery
     */
    async simulateErrorRecovery(options) {
        return {
            errorType: options.errorType,
            severity: options.severity || 'medium',
            steps: [],
            results: { success: true, recoverable: true },
            recoveryTime: '0ms',
            effectiveness: '100%'
        };
    }
}
/**
 * Decorator for automatic error handling in tool functions
 */
export function withMCPErrorHandling(target, propertyKey, descriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (...args) {
        try {
            return await originalMethod.apply(this, args);
        }
        catch (error) {
            const context = {
                tool: propertyKey,
                module: target.constructor.name,
                params: args[0],
            };
            throw ErrorHandler.transformError(error, context);
        }
    };
    return descriptor;
}
//# sourceMappingURL=error-handler.js.map