PRIX / lib /src /utils /errors.js
yamxxx1's picture
Upload 139 files
7da7e2c verified
Raw
History Blame
6.63 kB
"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