"use strict"; /** * Centralized Error Handling * Standardizes error handling across the codebase */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateRetryDelay = exports.shouldRetry = exports.defaultRetryConfig = exports.classifyError = exports.safeExecuteSync = exports.safeExecute = exports.logError = exports.createError = exports.ErrorCodes = void 0; const pino_1 = __importDefault(require("pino")); const logger = (0, pino_1.default)({ level: process.env.LOG_LEVEL || 'info' }); /** * Error codes for different failure modes */ exports.ErrorCodes = { // AI/LLM errors AI_RATE_LIMIT: 'AI_RATE_LIMIT', AI_CONTEXT_TOO_LARGE: 'AI_CONTEXT_TOO_LARGE', AI_TIMEOUT: 'AI_TIMEOUT', AI_AUTHENTICATION: 'AI_AUTHENTICATION', AI_SERVICE_UNAVAILABLE: 'AI_SERVICE_UNAVAILABLE', // GitHub API errors GITHUB_RATE_LIMIT: 'GITHUB_RATE_LIMIT', GITHUB_AUTHENTICATION: 'GITHUB_AUTHENTICATION', GITHUB_NOT_FOUND: 'GITHUB_NOT_FOUND', GITHUB_CONFLICT: 'GITHUB_CONFLICT', GITHUB_TIMEOUT: 'GITHUB_TIMEOUT', // File system errors FS_READ_ERROR: 'FS_READ_ERROR', FS_WRITE_ERROR: 'FS_WRITE_ERROR', FS_NOT_FOUND: 'FS_NOT_FOUND', // Parse/analysis errors PARSE_ERROR: 'PARSE_ERROR', AST_ANALYSIS_ERROR: 'AST_ANALYSIS_ERROR', PATCH_PARSE_ERROR: 'PATCH_PARSE_ERROR', // Context errors CONTEXT_MISSING: 'CONTEXT_MISSING', INVALID_PAYLOAD: 'INVALID_PAYLOAD', // Circuit breaker CIRCUIT_OPEN: 'CIRCUIT_OPEN', // Unknown UNKNOWN: 'UNKNOWN' }; /** * Create a standardized error */ const createError = (message, severity, code, context, cause) => ({ message, severity, code, context, cause }); exports.createError = createError; /** * Log error with appropriate level based on severity */ const logError = (error) => { const logData = { code: error.code, severity: error.severity, context: error.context, cause: error.cause?.message }; switch (error.severity) { case 'critical': logger.fatal(logData, error.message); break; case 'high': logger.error(logData, error.message); break; case 'medium': logger.warn(logData, error.message); break; case 'low': logger.info(logData, error.message); break; case 'info': logger.debug(logData, error.message); break; } }; exports.logError = logError; /** * Safe wrapper for async functions * Standardizes error handling */ const safeExecute = async (fn, errorCode, severity = 'medium', context, fallback) => { try { return await fn(); } catch (error) { const prixError = (0, exports.createError)(error instanceof Error ? error.message : String(error), severity, errorCode, context, error instanceof Error ? error : undefined); (0, exports.logError)(prixError); return fallback; } }; exports.safeExecute = safeExecute; /** * Safe wrapper for sync functions */ const safeExecuteSync = (fn, errorCode, severity = 'medium', context, fallback) => { try { return fn(); } catch (error) { const prixError = (0, exports.createError)(error instanceof Error ? error.message : String(error), severity, errorCode, context, error instanceof Error ? error : undefined); (0, exports.logError)(prixError); return fallback; } }; exports.safeExecuteSync = safeExecuteSync; /** * Classify error from external service */ const classifyError = (error) => { // AI API errors if (error?.status === 429) { return (0, exports.createError)('AI rate limit exceeded', 'high', exports.ErrorCodes.AI_RATE_LIMIT, { status: 429 }); } if (error?.status === 413) { return (0, exports.createError)('AI context too large', 'high', exports.ErrorCodes.AI_CONTEXT_TOO_LARGE, { status: 413 }); } if (error?.code === 'ETIMEDOUT' || error?.code === 'ECONNABORTED') { return (0, exports.createError)('AI timeout', 'medium', exports.ErrorCodes.AI_TIMEOUT, { code: error.code }); } if (error?.status === 401) { return (0, exports.createError)('AI authentication failed', 'critical', exports.ErrorCodes.AI_AUTHENTICATION, { status: 401 }); } if (error?.status === 503 || error?.status === 502) { return (0, exports.createError)('AI service unavailable', 'high', exports.ErrorCodes.AI_SERVICE_UNAVAILABLE, { status: error.status }); } // GitHub API errors if (error?.status === 403 && error?.message?.includes('rate limit')) { return (0, exports.createError)('GitHub rate limit exceeded', 'high', exports.ErrorCodes.GITHUB_RATE_LIMIT, { status: 403 }); } if (error?.status === 401) { return (0, exports.createError)('GitHub authentication failed', 'critical', exports.ErrorCodes.GITHUB_AUTHENTICATION, { status: 401 }); } if (error?.status === 404) { return (0, exports.createError)('GitHub resource not found', 'medium', exports.ErrorCodes.GITHUB_NOT_FOUND, { status: 404 }); } if (error?.status === 409) { return (0, exports.createError)('GitHub conflict', 'medium', exports.ErrorCodes.GITHUB_CONFLICT, { status: 409 }); } // Default return (0, exports.createError)(error?.message || 'Unknown error', 'medium', exports.ErrorCodes.UNKNOWN, { originalError: error }); }; exports.classifyError = classifyError; /** * Default retry configuration */ exports.defaultRetryConfig = { maxRetries: 3, baseDelay: 1000, maxDelay: 30000, retryableCodes: [ exports.ErrorCodes.AI_RATE_LIMIT, exports.ErrorCodes.AI_TIMEOUT, exports.ErrorCodes.AI_SERVICE_UNAVAILABLE, exports.ErrorCodes.GITHUB_RATE_LIMIT, exports.ErrorCodes.GITHUB_TIMEOUT ] }; /** * Check if error should be retried */ const shouldRetry = (error, config = exports.defaultRetryConfig) => { return config.retryableCodes.includes(error.code); }; exports.shouldRetry = shouldRetry; /** * Calculate delay for retry with exponential backoff */ const calculateRetryDelay = (attempt, config = exports.defaultRetryConfig) => { const delay = Math.min(config.baseDelay * Math.pow(2, attempt), config.maxDelay); // Add jitter to prevent thundering herd return delay + Math.random() * 1000; }; exports.calculateRetryDelay = calculateRetryDelay; //# sourceMappingURL=errors.js.map