@juspay/neurolink 7.24.0 → 7.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,5 @@
1
+ ## [7.24.1](https://github.com/juspay/neurolink/compare/v7.24.0...v7.24.1) (2025-08-21)
2
+
1
3
  ## [7.24.0](https://github.com/juspay/neurolink/compare/v7.23.0...v7.24.0) (2025-08-20)
2
4
 
3
5
  ### Features
package/dist/cli/index.js CHANGED
@@ -14,6 +14,7 @@ import { fileURLToPath } from "url";
14
14
  import { addOllamaCommands } from "./commands/ollama.js";
15
15
  import { addSageMakerCommands } from "./commands/sagemaker.js";
16
16
  import { CLICommandFactory } from "./factories/commandFactory.js";
17
+ import { AuthenticationError, AuthorizationError, NetworkError, RateLimitError, } from "../lib/types/errors.js";
17
18
  import { logger } from "../lib/utils/logger.js";
18
19
  // Get version from package.json
19
20
  const __filename = fileURLToPath(import.meta.url);
@@ -32,69 +33,8 @@ catch (error) {
32
33
  }
33
34
  // Utility Functions (Simple, Zero Maintenance)
34
35
  function handleError(error, context) {
35
- const specificErrorMessage = error.message;
36
- const originalErrorMessageLowerCase = error.message
37
- ? error.message.toLowerCase()
38
- : "";
39
- const errorStringLowerCase = String(error).toLowerCase();
40
- let isAuthError = false;
41
- let genericMessage = specificErrorMessage; // Initialize genericMessage with the specific one
42
- if (originalErrorMessageLowerCase.includes("api_key") ||
43
- originalErrorMessageLowerCase.includes("google_ai_api_key") ||
44
- originalErrorMessageLowerCase.includes("aws_access_key_id") ||
45
- originalErrorMessageLowerCase.includes("aws_secret_access_key") ||
46
- originalErrorMessageLowerCase.includes("aws_session_token") ||
47
- originalErrorMessageLowerCase.includes("google_application_credentials") ||
48
- originalErrorMessageLowerCase.includes("google_service_account_key") ||
49
- originalErrorMessageLowerCase.includes("google_auth_client_email") ||
50
- originalErrorMessageLowerCase.includes("anthropic_api_key") ||
51
- originalErrorMessageLowerCase.includes("azure_openai_api_key")) {
52
- isAuthError = true;
53
- }
54
- else if (
55
- // Fallback to checking the full stringified error if direct message didn't match
56
- errorStringLowerCase.includes("api_key") ||
57
- errorStringLowerCase.includes("google_ai_api_key") ||
58
- errorStringLowerCase.includes("aws_access_key_id") ||
59
- errorStringLowerCase.includes("aws_secret_access_key") ||
60
- errorStringLowerCase.includes("aws_session_token") ||
61
- errorStringLowerCase.includes("google_application_credentials") ||
62
- errorStringLowerCase.includes("google_service_account_key") ||
63
- errorStringLowerCase.includes("google_auth_client_email") ||
64
- errorStringLowerCase.includes("anthropic_api_key") ||
65
- errorStringLowerCase.includes("azure_openai_api_key")) {
66
- isAuthError = true;
67
- }
68
- if (isAuthError) {
69
- genericMessage =
70
- "Authentication error: Missing or invalid API key/credentials for the selected provider.";
71
- }
72
- else if (originalErrorMessageLowerCase.includes("enotfound") || // Prefer direct message checks
73
- originalErrorMessageLowerCase.includes("econnrefused") ||
74
- originalErrorMessageLowerCase.includes("invalid-endpoint") ||
75
- originalErrorMessageLowerCase.includes("network error") ||
76
- originalErrorMessageLowerCase.includes("could not connect") ||
77
- originalErrorMessageLowerCase.includes("timeout") ||
78
- errorStringLowerCase.includes("enotfound") || // Fallback to full string
79
- errorStringLowerCase.includes("econnrefused") ||
80
- errorStringLowerCase.includes("invalid-endpoint") ||
81
- errorStringLowerCase.includes("network error") ||
82
- errorStringLowerCase.includes("could not connect") ||
83
- errorStringLowerCase.includes("timeout") // General timeout
84
- ) {
85
- genericMessage =
86
- "Network error: Could not connect to the API endpoint or the request timed out.";
87
- }
88
- else if (errorStringLowerCase.includes("not authorized") ||
89
- errorStringLowerCase.includes("permission denied")) {
90
- genericMessage =
91
- "Authorization error: You are not authorized to perform this action or access this resource.";
92
- }
93
- // If no specific condition matched, genericMessage remains error.message
94
- logger.error(chalk.red(`❌ ${context} failed: ${genericMessage}`));
95
- // Smart hints for common errors (just string matching!)
96
- if (genericMessage.toLowerCase().includes("api key") ||
97
- genericMessage.toLowerCase().includes("credential")) {
36
+ logger.error(chalk.red(`❌ ${context} failed: ${error.message}`));
37
+ if (error instanceof AuthenticationError) {
98
38
  logger.error(chalk.yellow("💡 Set Google AI Studio API key (RECOMMENDED): export GOOGLE_AI_API_KEY=AIza-..."));
99
39
  logger.error(chalk.yellow("💡 Or set OpenAI API key: export OPENAI_API_KEY=sk-..."));
100
40
  logger.error(chalk.yellow("💡 Or set AWS Bedrock credentials: export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_REGION=us-east-1"));
@@ -102,14 +42,16 @@ function handleError(error, context) {
102
42
  logger.error(chalk.yellow("💡 Or set Anthropic API key: export ANTHROPIC_API_KEY=sk-ant-..."));
103
43
  logger.error(chalk.yellow("💡 Or set Azure OpenAI credentials: export AZURE_OPENAI_API_KEY=... AZURE_OPENAI_ENDPOINT=..."));
104
44
  }
105
- if (error.message.toLowerCase().includes("rate limit")) {
45
+ else if (error instanceof RateLimitError) {
106
46
  logger.error(chalk.yellow("💡 Try again in a few moments or use --provider vertex"));
107
47
  }
108
- if (error.message.toLowerCase().includes("not authorized") ||
109
- error.message.toLowerCase().includes("permission denied")) {
48
+ else if (error instanceof AuthorizationError) {
110
49
  logger.error(chalk.yellow("💡 Check your account permissions for the selected model/service."));
111
50
  logger.error(chalk.yellow("💡 For AWS Bedrock, ensure you have permissions for the specific model and consider using inference profile ARNs."));
112
51
  }
52
+ else if (error instanceof NetworkError) {
53
+ logger.error(chalk.yellow("💡 Check your internet connection and the provider's status page."));
54
+ }
113
55
  process.exit(1);
114
56
  }
115
57
  // Manual pre-validation for unknown flags
@@ -3,6 +3,7 @@ import { streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
5
  import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
6
+ import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
6
7
  import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
7
8
  import { validateApiKey, createAnthropicConfig, getProviderModel, } from "../utils/providerConfig.js";
8
9
  import { buildMessagesArray } from "../utils/messageBuilder.js";
@@ -50,45 +51,36 @@ export class AnthropicProvider extends BaseProvider {
50
51
  }
51
52
  handleProviderError(error) {
52
53
  if (error instanceof TimeoutError) {
53
- return new Error(`Anthropic request timed out after ${error.timeout}ms: ${error.message}`);
54
+ throw new NetworkError(`Request timed out after ${error.timeout}ms`, this.providerName);
54
55
  }
55
56
  const errorRecord = error;
56
- // Handle API key errors
57
- if ((typeof errorRecord?.message === "string" &&
58
- errorRecord.message.includes("API_KEY_INVALID")) ||
59
- (typeof errorRecord?.message === "string" &&
60
- errorRecord.message.includes("Invalid API key"))) {
61
- return new Error("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.");
57
+ const message = typeof errorRecord?.message === "string"
58
+ ? errorRecord.message
59
+ : "Unknown error";
60
+ if (message.includes("API_KEY_INVALID") ||
61
+ message.includes("Invalid API key")) {
62
+ throw new AuthenticationError("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.", this.providerName);
62
63
  }
63
- // Handle rate limiting errors
64
- if (typeof errorRecord?.message === "string" &&
65
- (errorRecord.message.includes("rate limit") ||
66
- errorRecord.message.includes("too_many_requests") ||
67
- errorRecord.message.includes("429"))) {
68
- return new Error("Anthropic rate limit exceeded. Please try again later.");
64
+ if (message.includes("rate limit") ||
65
+ message.includes("too_many_requests") ||
66
+ message.includes("429")) {
67
+ throw new RateLimitError("Anthropic rate limit exceeded. Please try again later.", this.providerName);
69
68
  }
70
- // Handle connection errors
71
- if (typeof errorRecord?.message === "string" &&
72
- (errorRecord.message.includes("ECONNRESET") ||
73
- errorRecord.message.includes("ENOTFOUND") ||
74
- errorRecord.message.includes("ECONNREFUSED") ||
75
- errorRecord.message.includes("network") ||
76
- errorRecord.message.includes("connection"))) {
77
- return new Error("Anthropic API connection error. Please check your internet connection and try again.");
69
+ if (message.includes("ECONNRESET") ||
70
+ message.includes("ENOTFOUND") ||
71
+ message.includes("ECONNREFUSED") ||
72
+ message.includes("network") ||
73
+ message.includes("connection")) {
74
+ throw new NetworkError(`Connection error: ${message}`, this.providerName);
78
75
  }
79
- // Handle server errors
80
- if (typeof errorRecord?.message === "string" &&
81
- (errorRecord.message.includes("500") ||
82
- errorRecord.message.includes("502") ||
83
- errorRecord.message.includes("503") ||
84
- errorRecord.message.includes("504") ||
85
- errorRecord.message.includes("server error"))) {
86
- return new Error("Anthropic API server error. Please try again in a few moments.");
76
+ if (message.includes("500") ||
77
+ message.includes("502") ||
78
+ message.includes("503") ||
79
+ message.includes("504") ||
80
+ message.includes("server error")) {
81
+ throw new ProviderError(`Server error: ${message}`, this.providerName);
87
82
  }
88
- const message = typeof errorRecord?.message === "string"
89
- ? errorRecord.message
90
- : "Unknown error";
91
- return new Error(`Anthropic error: ${message}`);
83
+ throw new ProviderError(`Anthropic error: ${message}`, this.providerName);
92
84
  }
93
85
  // executeGenerate removed - BaseProvider handles all generation with tools
94
86
  async executeStream(options, analysisSchema) {
@@ -4,6 +4,7 @@ import { GoogleAIModels } from "../core/types.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { logger } from "../utils/logger.js";
6
6
  import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
7
+ import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
7
8
  import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
8
9
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
9
10
  import { buildMessagesArray } from "../utils/messageBuilder.js";
@@ -44,21 +45,19 @@ export class GoogleAIStudioProvider extends BaseProvider {
44
45
  }
45
46
  handleProviderError(error) {
46
47
  if (error instanceof TimeoutError) {
47
- return new Error(`Google AI request timed out: ${error.message}`);
48
+ throw new NetworkError(error.message, this.providerName);
48
49
  }
49
50
  const errorRecord = error;
50
- if (typeof errorRecord?.message === "string" &&
51
- errorRecord.message.includes("API_KEY_INVALID")) {
52
- return new Error("Invalid Google AI API key. Please check your GOOGLE_AI_API_KEY environment variable.");
53
- }
54
- if (typeof errorRecord?.message === "string" &&
55
- errorRecord.message.includes("RATE_LIMIT_EXCEEDED")) {
56
- return new Error("Google AI rate limit exceeded. Please try again later.");
57
- }
58
51
  const message = typeof errorRecord?.message === "string"
59
52
  ? errorRecord.message
60
53
  : "Unknown error";
61
- return new Error(`Google AI error: ${message}`);
54
+ if (message.includes("API_KEY_INVALID")) {
55
+ throw new AuthenticationError("Invalid Google AI API key. Please check your GOOGLE_AI_API_KEY environment variable.", this.providerName);
56
+ }
57
+ if (message.includes("RATE_LIMIT_EXCEEDED")) {
58
+ throw new RateLimitError("Google AI rate limit exceeded. Please try again later.", this.providerName);
59
+ }
60
+ throw new ProviderError(`Google AI error: ${message}`, this.providerName);
62
61
  }
63
62
  // executeGenerate removed - BaseProvider handles all generation with tools
64
63
  async executeStream(options, analysisSchema) {
@@ -119,7 +118,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
119
118
  getApiKey() {
120
119
  const apiKey = process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
121
120
  if (!apiKey) {
122
- throw new Error("GOOGLE_AI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY environment variable is not set");
121
+ throw new AuthenticationError("GOOGLE_AI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY environment variable is not set", this.providerName);
123
122
  }
124
123
  return apiKey;
125
124
  }
@@ -4,6 +4,7 @@ import { AIProviderName } from "../core/types.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { logger } from "../utils/logger.js";
6
6
  import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
7
+ import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
7
8
  import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
8
9
  import { validateApiKey, createOpenAIConfig, getProviderModel, } from "../utils/providerConfig.js";
9
10
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
@@ -53,20 +54,28 @@ export class OpenAIProvider extends BaseProvider {
53
54
  }
54
55
  handleProviderError(error) {
55
56
  if (error instanceof TimeoutError) {
56
- return new Error(`OpenAI request timed out: ${error.message}`);
57
+ throw new NetworkError(error.message, this.providerName);
57
58
  }
58
59
  const errorObj = error;
59
60
  const message = errorObj?.message && typeof errorObj.message === "string"
60
61
  ? errorObj.message
61
62
  : "Unknown error";
63
+ const errorType = errorObj?.type && typeof errorObj.type === "string"
64
+ ? errorObj.type
65
+ : undefined;
62
66
  if (message.includes("API_KEY_INVALID") ||
63
- message.includes("Invalid API key")) {
64
- return new Error("Invalid OpenAI API key. Please check your OPENAI_API_KEY environment variable.");
67
+ message.includes("Invalid API key") ||
68
+ errorType === "invalid_api_key") {
69
+ throw new AuthenticationError("Invalid OpenAI API key. Please check your OPENAI_API_KEY environment variable.", this.providerName);
65
70
  }
66
- if (message.includes("rate limit")) {
67
- return new Error("OpenAI rate limit exceeded. Please try again later.");
71
+ if (message.includes("rate limit") || errorType === "rate_limit_error") {
72
+ throw new RateLimitError("OpenAI rate limit exceeded. Please try again later.", this.providerName);
68
73
  }
69
- return new Error(`OpenAI error: ${message}`);
74
+ if (message.includes("model_not_found")) {
75
+ throw new InvalidModelError(`Model not found: ${this.modelName}`, this.providerName);
76
+ }
77
+ // Generic provider error
78
+ throw new ProviderError(`OpenAI error: ${message}`, this.providerName);
70
79
  }
71
80
  /**
72
81
  * executeGenerate method removed - generation is now handled by BaseProvider.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Base error class for all NeuroLink-specific errors.
3
+ * This allows for easy identification of errors thrown by the SDK.
4
+ */
5
+ export declare class BaseError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ /**
9
+ * Thrown when a provider encounters a generic error.
10
+ */
11
+ export declare class ProviderError extends BaseError {
12
+ provider?: string | undefined;
13
+ constructor(message: string, provider?: string | undefined);
14
+ }
15
+ /**
16
+ * Thrown for authentication-related errors, such as invalid or missing API keys.
17
+ */
18
+ export declare class AuthenticationError extends ProviderError {
19
+ constructor(message: string, provider?: string);
20
+ }
21
+ /**
22
+ * Thrown for authorization errors, where the user does not have permission.
23
+ */
24
+ export declare class AuthorizationError extends ProviderError {
25
+ constructor(message: string, provider?: string);
26
+ }
27
+ /**
28
+ * Thrown for network-related issues, such as connectivity problems or timeouts.
29
+ */
30
+ export declare class NetworkError extends ProviderError {
31
+ constructor(message: string, provider?: string);
32
+ }
33
+ /**
34
+ * Thrown when an API rate limit has been exceeded.
35
+ */
36
+ export declare class RateLimitError extends ProviderError {
37
+ constructor(message: string, provider?: string);
38
+ }
39
+ /**
40
+ * Thrown when a specified model is not found or is invalid for the provider.
41
+ */
42
+ export declare class InvalidModelError extends ProviderError {
43
+ constructor(message: string, provider?: string);
44
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Base error class for all NeuroLink-specific errors.
3
+ * This allows for easy identification of errors thrown by the SDK.
4
+ */
5
+ export class BaseError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = this.constructor.name;
9
+ }
10
+ }
11
+ /**
12
+ * Thrown when a provider encounters a generic error.
13
+ */
14
+ export class ProviderError extends BaseError {
15
+ provider;
16
+ constructor(message, provider) {
17
+ super(provider ? `[${provider}] ${message}` : message);
18
+ this.provider = provider;
19
+ }
20
+ }
21
+ /**
22
+ * Thrown for authentication-related errors, such as invalid or missing API keys.
23
+ */
24
+ export class AuthenticationError extends ProviderError {
25
+ constructor(message, provider) {
26
+ super(message, provider);
27
+ }
28
+ }
29
+ /**
30
+ * Thrown for authorization errors, where the user does not have permission.
31
+ */
32
+ export class AuthorizationError extends ProviderError {
33
+ constructor(message, provider) {
34
+ super(message, provider);
35
+ }
36
+ }
37
+ /**
38
+ * Thrown for network-related issues, such as connectivity problems or timeouts.
39
+ */
40
+ export class NetworkError extends ProviderError {
41
+ constructor(message, provider) {
42
+ super(message, provider);
43
+ }
44
+ }
45
+ /**
46
+ * Thrown when an API rate limit has been exceeded.
47
+ */
48
+ export class RateLimitError extends ProviderError {
49
+ constructor(message, provider) {
50
+ super(message, provider);
51
+ }
52
+ }
53
+ /**
54
+ * Thrown when a specified model is not found or is invalid for the provider.
55
+ */
56
+ export class InvalidModelError extends ProviderError {
57
+ constructor(message, provider) {
58
+ super(message, provider);
59
+ }
60
+ }
@@ -3,6 +3,7 @@ import { streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
5
  import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
6
+ import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
6
7
  import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
7
8
  import { validateApiKey, createAnthropicConfig, getProviderModel, } from "../utils/providerConfig.js";
8
9
  import { buildMessagesArray } from "../utils/messageBuilder.js";
@@ -50,45 +51,36 @@ export class AnthropicProvider extends BaseProvider {
50
51
  }
51
52
  handleProviderError(error) {
52
53
  if (error instanceof TimeoutError) {
53
- return new Error(`Anthropic request timed out after ${error.timeout}ms: ${error.message}`);
54
+ throw new NetworkError(`Request timed out after ${error.timeout}ms`, this.providerName);
54
55
  }
55
56
  const errorRecord = error;
56
- // Handle API key errors
57
- if ((typeof errorRecord?.message === "string" &&
58
- errorRecord.message.includes("API_KEY_INVALID")) ||
59
- (typeof errorRecord?.message === "string" &&
60
- errorRecord.message.includes("Invalid API key"))) {
61
- return new Error("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.");
57
+ const message = typeof errorRecord?.message === "string"
58
+ ? errorRecord.message
59
+ : "Unknown error";
60
+ if (message.includes("API_KEY_INVALID") ||
61
+ message.includes("Invalid API key")) {
62
+ throw new AuthenticationError("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.", this.providerName);
62
63
  }
63
- // Handle rate limiting errors
64
- if (typeof errorRecord?.message === "string" &&
65
- (errorRecord.message.includes("rate limit") ||
66
- errorRecord.message.includes("too_many_requests") ||
67
- errorRecord.message.includes("429"))) {
68
- return new Error("Anthropic rate limit exceeded. Please try again later.");
64
+ if (message.includes("rate limit") ||
65
+ message.includes("too_many_requests") ||
66
+ message.includes("429")) {
67
+ throw new RateLimitError("Anthropic rate limit exceeded. Please try again later.", this.providerName);
69
68
  }
70
- // Handle connection errors
71
- if (typeof errorRecord?.message === "string" &&
72
- (errorRecord.message.includes("ECONNRESET") ||
73
- errorRecord.message.includes("ENOTFOUND") ||
74
- errorRecord.message.includes("ECONNREFUSED") ||
75
- errorRecord.message.includes("network") ||
76
- errorRecord.message.includes("connection"))) {
77
- return new Error("Anthropic API connection error. Please check your internet connection and try again.");
69
+ if (message.includes("ECONNRESET") ||
70
+ message.includes("ENOTFOUND") ||
71
+ message.includes("ECONNREFUSED") ||
72
+ message.includes("network") ||
73
+ message.includes("connection")) {
74
+ throw new NetworkError(`Connection error: ${message}`, this.providerName);
78
75
  }
79
- // Handle server errors
80
- if (typeof errorRecord?.message === "string" &&
81
- (errorRecord.message.includes("500") ||
82
- errorRecord.message.includes("502") ||
83
- errorRecord.message.includes("503") ||
84
- errorRecord.message.includes("504") ||
85
- errorRecord.message.includes("server error"))) {
86
- return new Error("Anthropic API server error. Please try again in a few moments.");
76
+ if (message.includes("500") ||
77
+ message.includes("502") ||
78
+ message.includes("503") ||
79
+ message.includes("504") ||
80
+ message.includes("server error")) {
81
+ throw new ProviderError(`Server error: ${message}`, this.providerName);
87
82
  }
88
- const message = typeof errorRecord?.message === "string"
89
- ? errorRecord.message
90
- : "Unknown error";
91
- return new Error(`Anthropic error: ${message}`);
83
+ throw new ProviderError(`Anthropic error: ${message}`, this.providerName);
92
84
  }
93
85
  // executeGenerate removed - BaseProvider handles all generation with tools
94
86
  async executeStream(options, analysisSchema) {
@@ -4,6 +4,7 @@ import { GoogleAIModels } from "../core/types.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { logger } from "../utils/logger.js";
6
6
  import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
7
+ import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
7
8
  import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
8
9
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
9
10
  import { buildMessagesArray } from "../utils/messageBuilder.js";
@@ -44,21 +45,19 @@ export class GoogleAIStudioProvider extends BaseProvider {
44
45
  }
45
46
  handleProviderError(error) {
46
47
  if (error instanceof TimeoutError) {
47
- return new Error(`Google AI request timed out: ${error.message}`);
48
+ throw new NetworkError(error.message, this.providerName);
48
49
  }
49
50
  const errorRecord = error;
50
- if (typeof errorRecord?.message === "string" &&
51
- errorRecord.message.includes("API_KEY_INVALID")) {
52
- return new Error("Invalid Google AI API key. Please check your GOOGLE_AI_API_KEY environment variable.");
53
- }
54
- if (typeof errorRecord?.message === "string" &&
55
- errorRecord.message.includes("RATE_LIMIT_EXCEEDED")) {
56
- return new Error("Google AI rate limit exceeded. Please try again later.");
57
- }
58
51
  const message = typeof errorRecord?.message === "string"
59
52
  ? errorRecord.message
60
53
  : "Unknown error";
61
- return new Error(`Google AI error: ${message}`);
54
+ if (message.includes("API_KEY_INVALID")) {
55
+ throw new AuthenticationError("Invalid Google AI API key. Please check your GOOGLE_AI_API_KEY environment variable.", this.providerName);
56
+ }
57
+ if (message.includes("RATE_LIMIT_EXCEEDED")) {
58
+ throw new RateLimitError("Google AI rate limit exceeded. Please try again later.", this.providerName);
59
+ }
60
+ throw new ProviderError(`Google AI error: ${message}`, this.providerName);
62
61
  }
63
62
  // executeGenerate removed - BaseProvider handles all generation with tools
64
63
  async executeStream(options, analysisSchema) {
@@ -119,7 +118,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
119
118
  getApiKey() {
120
119
  const apiKey = process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
121
120
  if (!apiKey) {
122
- throw new Error("GOOGLE_AI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY environment variable is not set");
121
+ throw new AuthenticationError("GOOGLE_AI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY environment variable is not set", this.providerName);
123
122
  }
124
123
  return apiKey;
125
124
  }
@@ -4,6 +4,7 @@ import { AIProviderName } from "../core/types.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { logger } from "../utils/logger.js";
6
6
  import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
7
+ import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
7
8
  import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
8
9
  import { validateApiKey, createOpenAIConfig, getProviderModel, } from "../utils/providerConfig.js";
9
10
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
@@ -53,20 +54,28 @@ export class OpenAIProvider extends BaseProvider {
53
54
  }
54
55
  handleProviderError(error) {
55
56
  if (error instanceof TimeoutError) {
56
- return new Error(`OpenAI request timed out: ${error.message}`);
57
+ throw new NetworkError(error.message, this.providerName);
57
58
  }
58
59
  const errorObj = error;
59
60
  const message = errorObj?.message && typeof errorObj.message === "string"
60
61
  ? errorObj.message
61
62
  : "Unknown error";
63
+ const errorType = errorObj?.type && typeof errorObj.type === "string"
64
+ ? errorObj.type
65
+ : undefined;
62
66
  if (message.includes("API_KEY_INVALID") ||
63
- message.includes("Invalid API key")) {
64
- return new Error("Invalid OpenAI API key. Please check your OPENAI_API_KEY environment variable.");
67
+ message.includes("Invalid API key") ||
68
+ errorType === "invalid_api_key") {
69
+ throw new AuthenticationError("Invalid OpenAI API key. Please check your OPENAI_API_KEY environment variable.", this.providerName);
65
70
  }
66
- if (message.includes("rate limit")) {
67
- return new Error("OpenAI rate limit exceeded. Please try again later.");
71
+ if (message.includes("rate limit") || errorType === "rate_limit_error") {
72
+ throw new RateLimitError("OpenAI rate limit exceeded. Please try again later.", this.providerName);
68
73
  }
69
- return new Error(`OpenAI error: ${message}`);
74
+ if (message.includes("model_not_found")) {
75
+ throw new InvalidModelError(`Model not found: ${this.modelName}`, this.providerName);
76
+ }
77
+ // Generic provider error
78
+ throw new ProviderError(`OpenAI error: ${message}`, this.providerName);
70
79
  }
71
80
  /**
72
81
  * executeGenerate method removed - generation is now handled by BaseProvider.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Base error class for all NeuroLink-specific errors.
3
+ * This allows for easy identification of errors thrown by the SDK.
4
+ */
5
+ export declare class BaseError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ /**
9
+ * Thrown when a provider encounters a generic error.
10
+ */
11
+ export declare class ProviderError extends BaseError {
12
+ provider?: string | undefined;
13
+ constructor(message: string, provider?: string | undefined);
14
+ }
15
+ /**
16
+ * Thrown for authentication-related errors, such as invalid or missing API keys.
17
+ */
18
+ export declare class AuthenticationError extends ProviderError {
19
+ constructor(message: string, provider?: string);
20
+ }
21
+ /**
22
+ * Thrown for authorization errors, where the user does not have permission.
23
+ */
24
+ export declare class AuthorizationError extends ProviderError {
25
+ constructor(message: string, provider?: string);
26
+ }
27
+ /**
28
+ * Thrown for network-related issues, such as connectivity problems or timeouts.
29
+ */
30
+ export declare class NetworkError extends ProviderError {
31
+ constructor(message: string, provider?: string);
32
+ }
33
+ /**
34
+ * Thrown when an API rate limit has been exceeded.
35
+ */
36
+ export declare class RateLimitError extends ProviderError {
37
+ constructor(message: string, provider?: string);
38
+ }
39
+ /**
40
+ * Thrown when a specified model is not found or is invalid for the provider.
41
+ */
42
+ export declare class InvalidModelError extends ProviderError {
43
+ constructor(message: string, provider?: string);
44
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Base error class for all NeuroLink-specific errors.
3
+ * This allows for easy identification of errors thrown by the SDK.
4
+ */
5
+ export class BaseError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = this.constructor.name;
9
+ }
10
+ }
11
+ /**
12
+ * Thrown when a provider encounters a generic error.
13
+ */
14
+ export class ProviderError extends BaseError {
15
+ provider;
16
+ constructor(message, provider) {
17
+ super(provider ? `[${provider}] ${message}` : message);
18
+ this.provider = provider;
19
+ }
20
+ }
21
+ /**
22
+ * Thrown for authentication-related errors, such as invalid or missing API keys.
23
+ */
24
+ export class AuthenticationError extends ProviderError {
25
+ constructor(message, provider) {
26
+ super(message, provider);
27
+ }
28
+ }
29
+ /**
30
+ * Thrown for authorization errors, where the user does not have permission.
31
+ */
32
+ export class AuthorizationError extends ProviderError {
33
+ constructor(message, provider) {
34
+ super(message, provider);
35
+ }
36
+ }
37
+ /**
38
+ * Thrown for network-related issues, such as connectivity problems or timeouts.
39
+ */
40
+ export class NetworkError extends ProviderError {
41
+ constructor(message, provider) {
42
+ super(message, provider);
43
+ }
44
+ }
45
+ /**
46
+ * Thrown when an API rate limit has been exceeded.
47
+ */
48
+ export class RateLimitError extends ProviderError {
49
+ constructor(message, provider) {
50
+ super(message, provider);
51
+ }
52
+ }
53
+ /**
54
+ * Thrown when a specified model is not found or is invalid for the provider.
55
+ */
56
+ export class InvalidModelError extends ProviderError {
57
+ constructor(message, provider) {
58
+ super(message, provider);
59
+ }
60
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "7.24.0",
3
+ "version": "7.24.1",
4
4
  "description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
5
5
  "author": {
6
6
  "name": "Juspay Technologies",