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

553 lines 17.3 kB
/** * Error Classes for NeuroLink Client SDK * * Provides comprehensive error classification and handling for API errors, * network errors, validation errors, and more. * * @module @neurolink/client/errors */ // ============================================================================= // Error Codes // ============================================================================= /** * Standard error codes for NeuroLink API errors */ export const ErrorCode = { // Client Errors (4xx) BAD_REQUEST: "BAD_REQUEST", UNAUTHORIZED: "UNAUTHORIZED", FORBIDDEN: "FORBIDDEN", NOT_FOUND: "NOT_FOUND", METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED", CONFLICT: "CONFLICT", PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE", RATE_LIMITED: "RATE_LIMITED", INVALID_REQUEST: "INVALID_REQUEST", VALIDATION_ERROR: "VALIDATION_ERROR", // Server Errors (5xx) INTERNAL_ERROR: "INTERNAL_ERROR", SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE", GATEWAY_TIMEOUT: "GATEWAY_TIMEOUT", BAD_GATEWAY: "BAD_GATEWAY", // Network Errors NETWORK_ERROR: "NETWORK_ERROR", TIMEOUT: "TIMEOUT", CONNECTION_REFUSED: "CONNECTION_REFUSED", DNS_ERROR: "DNS_ERROR", // Client-Side Errors CONFIGURATION_ERROR: "CONFIGURATION_ERROR", SERIALIZATION_ERROR: "SERIALIZATION_ERROR", STREAM_ERROR: "STREAM_ERROR", ABORT_ERROR: "ABORT_ERROR", // Provider Errors PROVIDER_ERROR: "PROVIDER_ERROR", MODEL_NOT_FOUND: "MODEL_NOT_FOUND", CONTEXT_LENGTH_EXCEEDED: "CONTEXT_LENGTH_EXCEEDED", CONTENT_FILTERED: "CONTENT_FILTERED", // Unknown UNKNOWN: "UNKNOWN", }; // ============================================================================= // Base Error Class // ============================================================================= /** * Base error class for all NeuroLink client errors * * Provides consistent error structure with error codes, status codes, * and additional metadata. */ export class NeuroLinkError extends Error { /** Error code for programmatic handling */ code; /** HTTP status code (if applicable) */ status; /** Additional error details */ details; /** Whether the error is retryable */ retryable; /** Request ID for error tracking */ requestId; constructor(message, code = ErrorCode.UNKNOWN, options) { super(message, { cause: options?.cause }); this.name = "NeuroLinkError"; this.code = code; this.status = options?.status; this.details = options?.details; this.retryable = options?.retryable ?? false; this.requestId = options?.requestId; } /** * Convert error to API error format */ toApiError() { return { code: this.code, message: this.message, status: this.status ?? 500, details: this.details, retryable: this.retryable, requestId: this.requestId, }; } /** * Convert error to JSON */ toJSON() { return { name: this.name, code: this.code, message: this.message, status: this.status, details: this.details, retryable: this.retryable, requestId: this.requestId, stack: this.stack, }; } } // ============================================================================= // HTTP Error Classes // ============================================================================= /** * Error for HTTP-related failures */ export class HttpError extends NeuroLinkError { /** HTTP response headers */ headers; /** HTTP response body */ body; constructor(message, status, options) { const code = options?.code ?? mapStatusToErrorCode(status); const retryable = isRetryableStatus(status); super(message, code, { status, details: options?.details, retryable, requestId: options?.requestId, }); this.name = "HttpError"; this.headers = options?.headers; this.body = options?.body; } } /** * Error for rate limiting (429) */ export class ClientRateLimitError extends HttpError { /** Retry-After value in seconds (if provided) */ retryAfter; /** Rate limit reset time */ resetAt; constructor(message = "Rate limit exceeded", options) { super(message, 429, { code: ErrorCode.RATE_LIMITED, details: options?.details, requestId: options?.requestId, }); this.name = "ClientRateLimitError"; this.retryAfter = options?.retryAfter; this.resetAt = options?.resetAt; } } /** * Error for validation failures (400) */ export class ClientValidationError extends HttpError { /** Field-level validation errors */ fieldErrors; constructor(message = "Validation failed", options) { super(message, 400, { code: ErrorCode.VALIDATION_ERROR, details: { ...options?.details, ...(options?.fieldErrors && { fieldErrors: options.fieldErrors, }), }, requestId: options?.requestId, }); this.name = "ClientValidationError"; this.fieldErrors = options?.fieldErrors; } } /** * Error for authentication failures (401) */ export class ClientAuthenticationError extends HttpError { constructor(message = "Authentication required", options) { super(message, 401, { code: ErrorCode.UNAUTHORIZED, details: options?.details, requestId: options?.requestId, }); this.name = "ClientAuthenticationError"; } } /** * Error for authorization failures (403) */ export class ClientAuthorizationError extends HttpError { constructor(message = "Access forbidden", options) { super(message, 403, { code: ErrorCode.FORBIDDEN, details: options?.details, requestId: options?.requestId, }); this.name = "ClientAuthorizationError"; } } /** * Error for not found (404) */ export class NotFoundError extends HttpError { /** Resource type that was not found */ resourceType; /** Resource ID that was not found */ resourceId; constructor(message = "Resource not found", options) { super(message, 404, { code: ErrorCode.NOT_FOUND, details: { ...options?.details, ...(options?.resourceType && { resourceType: options.resourceType }), ...(options?.resourceId && { resourceId: options.resourceId }), }, requestId: options?.requestId, }); this.name = "NotFoundError"; this.resourceType = options?.resourceType; this.resourceId = options?.resourceId; } } // ============================================================================= // Network Error Classes // ============================================================================= /** * Error for network-related failures */ export class ClientNetworkError extends NeuroLinkError { constructor(message = "Network error occurred", options) { super(message, options?.code ?? ErrorCode.NETWORK_ERROR, { details: options?.details, retryable: true, cause: options?.cause, requestId: options?.requestId, }); this.name = "ClientNetworkError"; } } /** * Error for request timeout */ export class ClientTimeoutError extends ClientNetworkError { /** Timeout duration in milliseconds */ timeoutMs; constructor(timeoutMs, message, options) { super(message ?? `Request timed out after ${timeoutMs}ms`, { code: ErrorCode.TIMEOUT, details: { ...options?.details, timeoutMs, }, requestId: options?.requestId, }); this.name = "ClientTimeoutError"; this.timeoutMs = timeoutMs; } } /** * Error for connection refused */ export class ClientConnectionError extends ClientNetworkError { /** Target host */ host; /** Target port */ port; constructor(message = "Connection refused", options) { super(message, { code: ErrorCode.CONNECTION_REFUSED, details: { ...options?.details, ...(options?.host && { host: options.host }), ...(options?.port !== undefined && { port: options.port }), }, cause: options?.cause, requestId: options?.requestId, }); this.name = "ClientConnectionError"; this.host = options?.host; this.port = options?.port; } } // ============================================================================= // Client-Side Error Classes // ============================================================================= /** * Error for request cancellation */ export class AbortError extends NeuroLinkError { constructor(message = "Request was aborted", options) { super(message, ErrorCode.ABORT_ERROR, { retryable: false, requestId: options?.requestId, }); this.name = "AbortError"; } } /** * Error for configuration issues */ export class ClientConfigurationError extends NeuroLinkError { /** Configuration field with issue */ field; constructor(message, options) { super(message, ErrorCode.CONFIGURATION_ERROR, { details: { ...options?.details, ...(options?.field && { field: options.field }), }, retryable: false, }); this.name = "ClientConfigurationError"; this.field = options?.field; } } /** * Error for stream processing failures */ export class StreamError extends NeuroLinkError { constructor(message = "Stream processing failed", options) { super(message, ErrorCode.STREAM_ERROR, { details: options?.details, retryable: false, cause: options?.cause, requestId: options?.requestId, }); this.name = "StreamError"; } } // ============================================================================= // Provider Error Classes // ============================================================================= /** * Error from AI provider */ export class ClientProviderError extends NeuroLinkError { /** Provider name */ provider; /** Model name */ model; /** Original provider error */ providerError; constructor(message, options) { super(message, ErrorCode.PROVIDER_ERROR, { status: options?.status, details: { ...options?.details, ...(options?.provider && { provider: options.provider }), ...(options?.model && { model: options.model }), }, retryable: options?.retryable ?? false, requestId: options?.requestId, }); this.name = "ClientProviderError"; this.provider = options?.provider; this.model = options?.model; this.providerError = options?.providerError; } } /** * Error for context length exceeded */ export class ContextLengthError extends ClientProviderError { /** Maximum allowed tokens */ maxTokens; /** Requested tokens */ requestedTokens; constructor(message = "Context length exceeded", options) { super(message, { provider: options?.provider, model: options?.model, details: { ...(options?.maxTokens !== undefined && { maxTokens: options.maxTokens, }), ...(options?.requestedTokens !== undefined && { requestedTokens: options.requestedTokens, }), }, retryable: false, requestId: options?.requestId, }); this.name = "ContextLengthError"; this.maxTokens = options?.maxTokens; this.requestedTokens = options?.requestedTokens; } } /** * Error for content filtering */ export class ContentFilterError extends ClientProviderError { /** Filter category that triggered */ category; constructor(message = "Content was filtered", options) { super(message, { provider: options?.provider, model: options?.model, details: { ...(options?.category && { category: options.category }), }, retryable: false, requestId: options?.requestId, }); this.name = "ContentFilterError"; this.category = options?.category; } } // ============================================================================= // Error Factory Functions // ============================================================================= /** * Create an error from an API error response */ export function createErrorFromResponse(apiError, options) { const { code, message, status, details, retryable } = apiError; // Map to specific error class based on status if (status === 401) { return new ClientAuthenticationError(message, { details, requestId: options?.requestId, }); } if (status === 403) { return new ClientAuthorizationError(message, { details, requestId: options?.requestId, }); } if (status === 404) { return new NotFoundError(message, { details, requestId: options?.requestId, }); } if (status === 429) { return new ClientRateLimitError(message, { details, requestId: options?.requestId, }); } if (status === 400 && code === "VALIDATION_ERROR") { return new ClientValidationError(message, { details, requestId: options?.requestId, }); } // Generic HTTP error if (status) { return new HttpError(message, status, { code: code, details, requestId: options?.requestId, }); } // Generic error return new NeuroLinkError(message, code, { details, retryable: retryable ?? false, requestId: options?.requestId, }); } /** * Create an error from a native Error object */ export function createErrorFromNative(error, options) { // Handle AbortError if (error.name === "AbortError") { return new AbortError(error.message, { requestId: options?.requestId }); } // Handle timeout if (error.message.includes("timeout") || error.name === "TimeoutError") { return new ClientTimeoutError(0, error.message, { requestId: options?.requestId, }); } // Handle network errors if (error.message.includes("network") || error.message.includes("ECONNREFUSED") || error.message.includes("ENOTFOUND")) { return new ClientNetworkError(error.message, { cause: error, requestId: options?.requestId, }); } // Generic error return new NeuroLinkError(error.message, ErrorCode.UNKNOWN, { cause: error, requestId: options?.requestId, }); } // ============================================================================= // Utility Functions // ============================================================================= /** * Map HTTP status code to error code */ export function mapStatusToErrorCode(status) { const mapping = { 400: ErrorCode.BAD_REQUEST, 401: ErrorCode.UNAUTHORIZED, 403: ErrorCode.FORBIDDEN, 404: ErrorCode.NOT_FOUND, 405: ErrorCode.METHOD_NOT_ALLOWED, 409: ErrorCode.CONFLICT, 413: ErrorCode.PAYLOAD_TOO_LARGE, 429: ErrorCode.RATE_LIMITED, 500: ErrorCode.INTERNAL_ERROR, 502: ErrorCode.BAD_GATEWAY, 503: ErrorCode.SERVICE_UNAVAILABLE, 504: ErrorCode.GATEWAY_TIMEOUT, }; return (mapping[status] ?? (status >= 500 ? ErrorCode.INTERNAL_ERROR : ErrorCode.UNKNOWN)); } /** * Check if a status code is retryable */ export function isRetryableStatus(status) { return [408, 429, 500, 502, 503, 504].includes(status); } /** * Check if an error is retryable */ export function isRetryableError(error) { if (error instanceof NeuroLinkError) { return error.retryable; } if (error instanceof Error) { // Network errors are generally retryable if (error.message.includes("network") || error.message.includes("ECONNREFUSED") || error.message.includes("ETIMEDOUT")) { return true; } } return false; } /** * Type guard for NeuroLinkError */ export function isNeuroLinkError(error) { return error instanceof NeuroLinkError; } /** * Type guard for ClientApiError */ export function isApiError(error) { if (typeof error !== "object" || error === null) { return false; } const obj = error; return typeof obj.code === "string" && typeof obj.message === "string"; } //# sourceMappingURL=errors.js.map