UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

487 lines 15.3 kB
/** * Server Adapter Error Classes * * Typed error hierarchy for server adapters following NeuroLink error patterns. */ import { ErrorCategory, ErrorSeverity, ServerAdapterErrorCode, } from "../types/index.js"; /** * Base error class for server adapter errors */ export class ServerAdapterError extends Error { code; category; severity; retryable; retryAfterMs; requestId; path; method; details; cause; constructor(message, code, context = {}) { super(message); this.name = "ServerAdapterError"; this.code = code; this.category = context.category ?? ErrorCategory.EXECUTION; this.severity = context.severity ?? ErrorSeverity.MEDIUM; this.retryable = context.retryable ?? false; this.retryAfterMs = context.retryAfterMs; this.requestId = context.requestId; this.path = context.path; this.method = context.method; this.details = context.details; this.cause = context.cause; // Maintain proper stack trace if (Error.captureStackTrace) { Error.captureStackTrace(this, ServerAdapterError); } } /** * Convert to JSON for API responses */ toJSON() { return { error: { code: this.code, message: this.message, category: this.category, requestId: this.requestId, details: this.details, retryAfter: this.retryAfterMs ? Math.ceil(this.retryAfterMs / 1000) : undefined, }, }; } /** * Get HTTP status code for this error */ getHttpStatus() { switch (this.code) { case ServerAdapterErrorCode.VALIDATION_ERROR: case ServerAdapterErrorCode.SCHEMA_ERROR: case ServerAdapterErrorCode.INVALID_CONFIG: case ServerAdapterErrorCode.INVALID_ROUTE: return 400; case ServerAdapterErrorCode.AUTH_REQUIRED: case ServerAdapterErrorCode.AUTH_INVALID: return 401; case ServerAdapterErrorCode.FORBIDDEN: return 403; case ServerAdapterErrorCode.ROUTE_NOT_FOUND: return 404; case ServerAdapterErrorCode.RATE_LIMIT_EXCEEDED: return 429; case ServerAdapterErrorCode.TIMEOUT: return 408; case ServerAdapterErrorCode.STREAM_ABORTED: return 499; default: return 500; } } } /** * Configuration error */ export class ConfigurationError extends ServerAdapterError { constructor(message, details, cause) { super(message, ServerAdapterErrorCode.INVALID_CONFIG, { category: ErrorCategory.CONFIG, severity: ErrorSeverity.HIGH, retryable: false, details, cause, }); this.name = "ConfigurationError"; } } /** * Route conflict error */ export class RouteConflictError extends ServerAdapterError { constructor(path, method, existingRoute) { super(`Route conflict: ${method} ${path} conflicts with existing route${existingRoute ? `: ${existingRoute}` : ""}`, ServerAdapterErrorCode.ROUTE_CONFLICT, { category: ErrorCategory.CONFIG, severity: ErrorSeverity.HIGH, retryable: false, path, method, details: { existingRoute }, }); this.name = "RouteConflictError"; } } /** * Route not found error */ export class RouteNotFoundError extends ServerAdapterError { constructor(path, method, requestId) { super(`Route not found: ${method} ${path}`, ServerAdapterErrorCode.ROUTE_NOT_FOUND, { category: ErrorCategory.VALIDATION, severity: ErrorSeverity.LOW, retryable: false, path, method, requestId, }); this.name = "RouteNotFoundError"; } } /** * Validation error */ export class ValidationError extends ServerAdapterError { errors; constructor(errors, requestId) { super(`Validation failed: ${errors.map((e) => e.message).join(", ")}`, ServerAdapterErrorCode.VALIDATION_ERROR, { category: ErrorCategory.VALIDATION, severity: ErrorSeverity.LOW, retryable: false, requestId, details: { errors }, }); this.name = "ValidationError"; this.errors = errors; } } /** * Authentication error */ export class AuthenticationError extends ServerAdapterError { constructor(message = "Authentication required", requestId) { super(message, ServerAdapterErrorCode.AUTH_REQUIRED, { category: ErrorCategory.AUTHENTICATION, severity: ErrorSeverity.MEDIUM, retryable: false, requestId, }); this.name = "AuthenticationError"; } } /** * Invalid authentication error */ export class InvalidAuthenticationError extends ServerAdapterError { constructor(message = "Invalid authentication credentials", requestId) { super(message, ServerAdapterErrorCode.AUTH_INVALID, { category: ErrorCategory.AUTHENTICATION, severity: ErrorSeverity.MEDIUM, retryable: false, requestId, }); this.name = "InvalidAuthenticationError"; } } /** * Authorization error */ export class AuthorizationError extends ServerAdapterError { constructor(message = "Access forbidden", requestId, requiredPermissions) { super(message, ServerAdapterErrorCode.FORBIDDEN, { category: ErrorCategory.AUTHORIZATION, severity: ErrorSeverity.MEDIUM, retryable: false, requestId, details: { requiredPermissions }, }); this.name = "AuthorizationError"; } } /** * Rate limit error */ export class RateLimitError extends ServerAdapterError { constructor(retryAfterMs, message, requestId) { super(message ?? "Too many requests, please try again later", ServerAdapterErrorCode.RATE_LIMIT_EXCEEDED, { category: ErrorCategory.RATE_LIMIT, severity: ErrorSeverity.MEDIUM, retryable: true, retryAfterMs, requestId, }); this.name = "RateLimitError"; } } /** * Timeout error */ export class TimeoutError extends ServerAdapterError { constructor(timeoutMs, operation, requestId) { super(`Operation timed out after ${timeoutMs}ms${operation ? `: ${operation}` : ""}`, ServerAdapterErrorCode.TIMEOUT, { category: ErrorCategory.EXECUTION, severity: ErrorSeverity.MEDIUM, retryable: true, requestId, details: { timeoutMs, operation }, }); this.name = "TimeoutError"; } } /** * Handler error */ export class HandlerError extends ServerAdapterError { constructor(message, cause, requestId, path, method) { super(message, ServerAdapterErrorCode.HANDLER_ERROR, { category: ErrorCategory.EXECUTION, severity: ErrorSeverity.HIGH, retryable: false, cause, requestId, path, method, }); this.name = "HandlerError"; } } /** * Streaming error */ export class StreamingError extends ServerAdapterError { constructor(message, cause, requestId) { super(message, ServerAdapterErrorCode.STREAM_ERROR, { category: ErrorCategory.STREAMING, severity: ErrorSeverity.MEDIUM, retryable: false, cause, requestId, }); this.name = "StreamingError"; } } /** * Stream aborted error */ export class StreamAbortedError extends ServerAdapterError { constructor(reason, requestId) { super(`Stream aborted${reason ? `: ${reason}` : ""}`, ServerAdapterErrorCode.STREAM_ABORTED, { category: ErrorCategory.STREAMING, severity: ErrorSeverity.LOW, retryable: false, requestId, details: { reason }, }); this.name = "StreamAbortedError"; } } /** * WebSocket error */ export class WebSocketError extends ServerAdapterError { constructor(message, cause, connectionId) { super(message, ServerAdapterErrorCode.WEBSOCKET_ERROR, { category: ErrorCategory.WEBSOCKET, severity: ErrorSeverity.MEDIUM, retryable: true, cause, details: { connectionId }, }); this.name = "WebSocketError"; } } /** * WebSocket connection failed error */ export class WebSocketConnectionError extends ServerAdapterError { constructor(message = "WebSocket connection failed", cause) { super(message, ServerAdapterErrorCode.WEBSOCKET_CONNECTION_FAILED, { category: ErrorCategory.WEBSOCKET, severity: ErrorSeverity.HIGH, retryable: true, cause, }); this.name = "WebSocketConnectionError"; } } /** * Server start error */ export class ServerStartError extends ServerAdapterError { constructor(message, cause, port, host) { super(message, ServerAdapterErrorCode.START_FAILED, { category: ErrorCategory.CONFIG, severity: ErrorSeverity.CRITICAL, retryable: true, cause, details: { port, host }, }); this.name = "ServerStartError"; } } /** * Server stop error */ export class ServerStopError extends ServerAdapterError { constructor(message, cause) { super(message, ServerAdapterErrorCode.STOP_FAILED, { category: ErrorCategory.EXECUTION, severity: ErrorSeverity.HIGH, retryable: false, cause, }); this.name = "ServerStopError"; } } /** * Already running error */ export class AlreadyRunningError extends ServerAdapterError { constructor(port, host) { super(`Server is already running${port && host ? ` on ${host}:${port}` : ""}`, ServerAdapterErrorCode.ALREADY_RUNNING, { category: ErrorCategory.CONFIG, severity: ErrorSeverity.LOW, retryable: false, details: { port, host }, }); this.name = "AlreadyRunningError"; } } /** * Not running error */ export class NotRunningError extends ServerAdapterError { constructor() { super("Server is not running", ServerAdapterErrorCode.NOT_RUNNING, { category: ErrorCategory.CONFIG, severity: ErrorSeverity.LOW, retryable: false, }); this.name = "NotRunningError"; } } /** * Shutdown timeout error * Thrown when graceful shutdown exceeds the configured timeout */ export class ShutdownTimeoutError extends ServerAdapterError { timeoutMs; remainingConnections; constructor(timeoutMs, remainingConnections) { super(`Shutdown timed out after ${timeoutMs}ms with ${remainingConnections} active connection(s)`, ServerAdapterErrorCode.STOP_FAILED, { category: ErrorCategory.EXECUTION, severity: ErrorSeverity.HIGH, retryable: false, details: { timeoutMs, remainingConnections }, }); this.name = "ShutdownTimeoutError"; this.timeoutMs = timeoutMs; this.remainingConnections = remainingConnections; } } /** * Drain timeout error * Thrown when connection draining exceeds the configured timeout */ export class DrainTimeoutError extends ServerAdapterError { timeoutMs; remainingConnections; constructor(timeoutMs, remainingConnections) { super(`Connection drain timed out after ${timeoutMs}ms with ${remainingConnections} active connection(s)`, ServerAdapterErrorCode.STOP_FAILED, { category: ErrorCategory.EXECUTION, severity: ErrorSeverity.MEDIUM, retryable: false, details: { timeoutMs, remainingConnections }, }); this.name = "DrainTimeoutError"; this.timeoutMs = timeoutMs; this.remainingConnections = remainingConnections; } } /** * Invalid lifecycle state error * Thrown when attempting an operation in an invalid lifecycle state */ export class InvalidLifecycleStateError extends ServerAdapterError { currentState; expectedStates; operation; constructor(operation, currentState, expectedStates) { super(`Cannot ${operation}: server is in '${currentState}' state, expected one of [${expectedStates.join(", ")}]`, ServerAdapterErrorCode.STOP_FAILED, { category: ErrorCategory.CONFIG, severity: ErrorSeverity.MEDIUM, retryable: false, details: { operation, currentState, expectedStates }, }); this.name = "InvalidLifecycleStateError"; this.currentState = currentState; this.expectedStates = expectedStates; this.operation = operation; } } /** * Missing dependency error */ export class MissingDependencyError extends ServerAdapterError { constructor(dependency, framework, installCommand) { super(`Missing dependency '${dependency}' for ${framework} adapter. ${installCommand ? `Install with: ${installCommand}` : ""}`, ServerAdapterErrorCode.MISSING_DEPENDENCY, { category: ErrorCategory.CONFIG, severity: ErrorSeverity.CRITICAL, retryable: false, details: { dependency, framework, installCommand }, }); this.name = "MissingDependencyError"; } } /** * Error recovery strategies */ export const ErrorRecoveryStrategies = { [ErrorCategory.CONFIG]: { strategy: "fail", maxRetries: 0, baseDelayMs: 0, }, [ErrorCategory.VALIDATION]: { strategy: "fail", maxRetries: 0, baseDelayMs: 0, }, [ErrorCategory.EXECUTION]: { strategy: "retry", maxRetries: 3, baseDelayMs: 1000, }, [ErrorCategory.EXTERNAL]: { strategy: "exponentialBackoff", maxRetries: 5, baseDelayMs: 1000, }, [ErrorCategory.RATE_LIMIT]: { strategy: "exponentialBackoff", maxRetries: 3, baseDelayMs: 5000, }, [ErrorCategory.AUTHENTICATION]: { strategy: "fail", maxRetries: 0, baseDelayMs: 0, }, [ErrorCategory.AUTHORIZATION]: { strategy: "fail", maxRetries: 0, baseDelayMs: 0, }, [ErrorCategory.STREAMING]: { strategy: "retry", maxRetries: 2, baseDelayMs: 500, }, [ErrorCategory.WEBSOCKET]: { strategy: "exponentialBackoff", maxRetries: 5, baseDelayMs: 1000, }, }; /** * Helper to wrap errors as ServerAdapterError */ export function wrapError(error, requestId, path, method) { if (error instanceof ServerAdapterError) { return error; } const message = error instanceof Error ? error.message : String(error); const cause = error instanceof Error ? error : undefined; return new HandlerError(message, cause, requestId, path, method); } //# sourceMappingURL=errors.js.map