@juspay/neurolink 9.68.17 → 9.68.18

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.
@@ -1,33 +1,25 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
4
- import type { LanguageModel } from "../types/index.js";
2
+ import type { NeurolinkCredentials } from "../types/index.js";
3
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
5
4
  /**
6
- * Mistral AI Provider v2 - BaseProvider Implementation
7
- * Supports official AI-SDK integration with all Mistral models
5
+ * Mistral AI Provider direct HTTP, no AI SDK.
6
+ *
7
+ * OpenAI-compatible chat completions at api.mistral.ai/v1. All request/stream/
8
+ * tool-loop orchestration lives in `OpenAIChatCompletionsProvider`; this class
9
+ * only declares configuration and the provider-specific error mapping.
10
+ *
11
+ * Mistral's `/chat/completions` accepts `response_format: { type:
12
+ * "json_schema" }` on current models (mistral-small-2506 and newer), so no
13
+ * structured-output downgrade is needed — the base client's default
14
+ * pass-through is correct.
15
+ *
16
+ * @see https://docs.mistral.ai/api/
8
17
  */
9
- export declare class MistralProvider extends BaseProvider {
10
- private model;
18
+ export declare class MistralProvider extends OpenAIChatCompletionsProvider {
11
19
  constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["mistral"]);
12
- protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
13
- getProviderName(): AIProviderName;
14
- getDefaultModel(): string;
15
- /**
16
- * Returns the Vercel AI SDK model instance for Mistral
17
- */
18
- getAISDKModel(): LanguageModel;
19
- formatProviderError(error: unknown): Error;
20
- /**
21
- * Validate provider configuration
22
- */
23
- validateConfiguration(): Promise<boolean>;
24
- /**
25
- * Get provider-specific configuration
26
- */
27
- getConfiguration(): {
28
- provider: AIProviderName;
29
- model: string;
30
- defaultModel: string;
31
- };
20
+ protected getProviderName(): AIProviderName;
21
+ protected getDefaultModel(): string;
22
+ protected formatProviderError(error: unknown): Error;
23
+ protected getFallbackModelName(): string;
24
+ protected getFallbackModels(): string[];
32
25
  }
33
- export default MistralProvider;
@@ -1,135 +1,64 @@
1
- import { createMistral } from "@ai-sdk/mistral";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import { DEFAULT_MAX_STEPS } from "../core/constants.js";
4
- import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
5
- import { isNeuroLink } from "../neurolink.js";
6
- import { createProxyFetch } from "../proxy/proxyFetch.js";
7
- import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
8
- import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
1
+ import { MistralModels } from "../constants/enums.js";
2
+ import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
9
3
  import { logger } from "../utils/logger.js";
4
+ import { redactUrlCredentials } from "../utils/logSanitize.js";
10
5
  import { createMistralConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
11
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
12
- import { resolveToolChoice } from "../utils/toolChoice.js";
13
- import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
14
- import { stepCountIs } from "../utils/tool.js";
15
- import { streamText } from "../utils/generation.js";
16
- // Configuration helpers - now using consolidated utility
6
+ import { TimeoutError } from "../utils/timeout.js";
7
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
8
+ const MISTRAL_DEFAULT_BASE_URL = "https://api.mistral.ai/v1";
17
9
  const getMistralApiKey = () => {
18
10
  return validateApiKey(createMistralConfig());
19
11
  };
20
12
  const getDefaultMistralModel = () => {
21
- // Default to vision-capable Mistral Small 2506 (June 2025) with multimodal support
22
- return getProviderModel("MISTRAL_MODEL", "mistral-small-2506");
13
+ // Vision-capable Mistral Small (June 2025) with multimodal support.
14
+ return getProviderModel("MISTRAL_MODEL", MistralModels.MISTRAL_SMALL_2506);
23
15
  };
24
16
  /**
25
- * Mistral AI Provider v2 - BaseProvider Implementation
26
- * Supports official AI-SDK integration with all Mistral models
17
+ * Mistral AI Provider direct HTTP, no AI SDK.
18
+ *
19
+ * OpenAI-compatible chat completions at api.mistral.ai/v1. All request/stream/
20
+ * tool-loop orchestration lives in `OpenAIChatCompletionsProvider`; this class
21
+ * only declares configuration and the provider-specific error mapping.
22
+ *
23
+ * Mistral's `/chat/completions` accepts `response_format: { type:
24
+ * "json_schema" }` on current models (mistral-small-2506 and newer), so no
25
+ * structured-output downgrade is needed — the base client's default
26
+ * pass-through is correct.
27
+ *
28
+ * @see https://docs.mistral.ai/api/
27
29
  */
28
- export class MistralProvider extends BaseProvider {
29
- model;
30
+ export class MistralProvider extends OpenAIChatCompletionsProvider {
30
31
  constructor(modelName, sdk, _region, credentials) {
31
- // Type guard for NeuroLink parameter validation
32
- const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
33
- super(modelName, "mistral", validatedNeurolink);
34
- // Initialize Mistral model with API key validation and proxy support
35
- const apiKey = credentials?.apiKey ?? getMistralApiKey();
36
- const mistral = createMistral({
37
- apiKey: apiKey,
38
- fetch: createProxyFetch(),
39
- });
40
- this.model = mistral(this.modelName);
41
- logger.debug("Mistral Provider v2 initialized", {
32
+ // Trim the override before applying precedence. A blank/whitespace
33
+ // `credentials.apiKey` must NOT bypass `getMistralApiKey()` that would
34
+ // build a client with an unusable bearer token and fail at request time
35
+ // with a confusing 401 instead of at construction time.
36
+ const overrideApiKey = credentials?.apiKey?.trim();
37
+ const apiKey = overrideApiKey && overrideApiKey.length > 0
38
+ ? overrideApiKey
39
+ : getMistralApiKey();
40
+ // Treat blank/whitespace overrides as unset so an empty
41
+ // `credentials.baseURL` or `MISTRAL_BASE_URL=` cannot silently override
42
+ // the default with "" (mirrors the apiKey precedence above).
43
+ const baseURL = credentials?.baseURL?.trim() ||
44
+ process.env.MISTRAL_BASE_URL?.trim() ||
45
+ MISTRAL_DEFAULT_BASE_URL;
46
+ super("mistral", modelName, sdk, { baseURL, apiKey });
47
+ logger.debug("Mistral Provider initialized", {
42
48
  modelName: this.modelName,
43
49
  providerName: this.providerName,
50
+ baseURL: redactUrlCredentials(this.config.baseURL),
44
51
  });
45
52
  }
46
- // generate() method is inherited from BaseProvider; this provider uses the base implementation for generation with tools
47
- async executeStream(options, _analysisSchema) {
48
- this.validateStreamOptions(options);
49
- const startTime = Date.now();
50
- const timeout = this.getTimeout(options);
51
- const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
52
- try {
53
- // Get tools - options.tools is pre-merged by BaseProvider.stream()
54
- const shouldUseTools = !options.disableTools && this.supportsTools();
55
- const tools = shouldUseTools
56
- ? options.tools || (await this.getAllTools())
57
- : {};
58
- // Build message array from options with multimodal support
59
- // Using protected helper from BaseProvider to eliminate code duplication
60
- const messages = await this.buildMessagesForStream(options);
61
- const model = await this.getAISDKModelWithMiddleware(options); // This is where network connection happens!
62
- // Reviewer follow-up: capture upstream provider errors via onError
63
- // so the post-stream NoOutput sentinel carries the real cause.
64
- let capturedProviderError;
65
- const result = await streamText({
66
- model,
67
- messages: messages,
68
- temperature: options.temperature,
69
- maxOutputTokens: options.maxTokens, // No default limit - unlimited unless specified
70
- tools,
71
- stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
72
- toolChoice: resolveToolChoice(options, tools, shouldUseTools),
73
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
74
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
75
- experimental_repairToolCall: this.getToolCallRepairFn(options),
76
- onError: (event) => {
77
- capturedProviderError = event.error;
78
- logger.error("Mistral: Stream error", {
79
- error: event.error instanceof Error
80
- ? event.error.message
81
- : String(event.error),
82
- });
83
- },
84
- onStepFinish: ({ toolCalls, toolResults }) => {
85
- emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
86
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
87
- logger.warn("[MistralProvider] Failed to store tool executions", {
88
- provider: this.providerName,
89
- error: error instanceof Error ? error.message : String(error),
90
- });
91
- });
92
- },
93
- });
94
- timeoutController?.cleanup();
95
- // Transform string stream to content object stream using BaseProvider method
96
- const transformedStream = this.createTextStream(result, () => capturedProviderError);
97
- // Create analytics promise that resolves after stream completion
98
- const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
99
- requestId: `mistral-stream-${Date.now()}`,
100
- streamingMode: true,
101
- });
102
- return {
103
- stream: transformedStream,
104
- provider: this.providerName,
105
- model: this.modelName,
106
- analytics: analyticsPromise,
107
- metadata: {
108
- startTime,
109
- streamId: `mistral-${Date.now()}`,
110
- },
111
- };
112
- }
113
- catch (error) {
114
- timeoutController?.cleanup();
115
- throw this.handleProviderError(error);
116
- }
117
- }
118
- // ===================
119
- // ABSTRACT METHOD IMPLEMENTATIONS
120
- // ===================
53
+ // ===========================================================================
54
+ // Abstract hooks (required)
55
+ // ===========================================================================
121
56
  getProviderName() {
122
- return this.providerName;
57
+ return "mistral";
123
58
  }
124
59
  getDefaultModel() {
125
60
  return getDefaultMistralModel();
126
61
  }
127
- /**
128
- * Returns the Vercel AI SDK model instance for Mistral
129
- */
130
- getAISDKModel() {
131
- return this.model;
132
- }
133
62
  formatProviderError(error) {
134
63
  if (error instanceof TimeoutError) {
135
64
  return new NetworkError(`Request timed out: ${error.message}`, "mistral");
@@ -139,36 +68,32 @@ export class MistralProvider extends BaseProvider {
139
68
  ? errorRecord.message
140
69
  : "Unknown error";
141
70
  if (message.includes("API_KEY_INVALID") ||
142
- message.includes("Invalid API key")) {
71
+ message.includes("Invalid API key") ||
72
+ message.includes("Unauthorized") ||
73
+ message.includes("401")) {
143
74
  return new AuthenticationError("Invalid Mistral API key. Please check your MISTRAL_API_KEY environment variable.", "mistral");
144
75
  }
145
- if (message.includes("Rate limit exceeded")) {
76
+ if (message.includes("rate limit") ||
77
+ message.includes("Rate limit") ||
78
+ message.includes("429")) {
146
79
  return new RateLimitError("Mistral rate limit exceeded", "mistral");
147
80
  }
81
+ if (message.includes("model_not_found") || message.includes("404")) {
82
+ return new InvalidModelError(`Mistral model '${this.modelName}' not found.`, "mistral");
83
+ }
148
84
  return new ProviderError(`Mistral error: ${message}`, "mistral");
149
85
  }
150
- /**
151
- * Validate provider configuration
152
- */
153
- async validateConfiguration() {
154
- try {
155
- getMistralApiKey();
156
- return true;
157
- }
158
- catch {
159
- return false;
160
- }
86
+ // ===========================================================================
87
+ // Optional hooks
88
+ // ===========================================================================
89
+ getFallbackModelName() {
90
+ return MistralModels.MISTRAL_SMALL_2506;
161
91
  }
162
- /**
163
- * Get provider-specific configuration
164
- */
165
- getConfiguration() {
166
- return {
167
- provider: this.providerName,
168
- model: this.modelName,
169
- defaultModel: getDefaultMistralModel(),
170
- };
92
+ getFallbackModels() {
93
+ return [
94
+ MistralModels.MISTRAL_SMALL_2506,
95
+ MistralModels.MISTRAL_LARGE_LATEST,
96
+ ];
171
97
  }
172
98
  }
173
- export default MistralProvider;
174
99
  //# sourceMappingURL=mistral.js.map
@@ -129,6 +129,7 @@ export type NeurolinkCredentials = {
129
129
  };
130
130
  mistral?: {
131
131
  apiKey?: string;
132
+ baseURL?: string;
132
133
  };
133
134
  huggingFace?: {
134
135
  apiKey?: string;
@@ -1,33 +1,25 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
4
- import type { LanguageModel } from "../types/index.js";
2
+ import type { NeurolinkCredentials } from "../types/index.js";
3
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
5
4
  /**
6
- * Mistral AI Provider v2 - BaseProvider Implementation
7
- * Supports official AI-SDK integration with all Mistral models
5
+ * Mistral AI Provider direct HTTP, no AI SDK.
6
+ *
7
+ * OpenAI-compatible chat completions at api.mistral.ai/v1. All request/stream/
8
+ * tool-loop orchestration lives in `OpenAIChatCompletionsProvider`; this class
9
+ * only declares configuration and the provider-specific error mapping.
10
+ *
11
+ * Mistral's `/chat/completions` accepts `response_format: { type:
12
+ * "json_schema" }` on current models (mistral-small-2506 and newer), so no
13
+ * structured-output downgrade is needed — the base client's default
14
+ * pass-through is correct.
15
+ *
16
+ * @see https://docs.mistral.ai/api/
8
17
  */
9
- export declare class MistralProvider extends BaseProvider {
10
- private model;
18
+ export declare class MistralProvider extends OpenAIChatCompletionsProvider {
11
19
  constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["mistral"]);
12
- protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
13
- getProviderName(): AIProviderName;
14
- getDefaultModel(): string;
15
- /**
16
- * Returns the Vercel AI SDK model instance for Mistral
17
- */
18
- getAISDKModel(): LanguageModel;
19
- formatProviderError(error: unknown): Error;
20
- /**
21
- * Validate provider configuration
22
- */
23
- validateConfiguration(): Promise<boolean>;
24
- /**
25
- * Get provider-specific configuration
26
- */
27
- getConfiguration(): {
28
- provider: AIProviderName;
29
- model: string;
30
- defaultModel: string;
31
- };
20
+ protected getProviderName(): AIProviderName;
21
+ protected getDefaultModel(): string;
22
+ protected formatProviderError(error: unknown): Error;
23
+ protected getFallbackModelName(): string;
24
+ protected getFallbackModels(): string[];
32
25
  }
33
- export default MistralProvider;
@@ -1,135 +1,64 @@
1
- import { createMistral } from "@ai-sdk/mistral";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import { DEFAULT_MAX_STEPS } from "../core/constants.js";
4
- import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
5
- import { isNeuroLink } from "../neurolink.js";
6
- import { createProxyFetch } from "../proxy/proxyFetch.js";
7
- import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
8
- import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
1
+ import { MistralModels } from "../constants/enums.js";
2
+ import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
9
3
  import { logger } from "../utils/logger.js";
4
+ import { redactUrlCredentials } from "../utils/logSanitize.js";
10
5
  import { createMistralConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
11
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
12
- import { resolveToolChoice } from "../utils/toolChoice.js";
13
- import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
14
- import { stepCountIs } from "../utils/tool.js";
15
- import { streamText } from "../utils/generation.js";
16
- // Configuration helpers - now using consolidated utility
6
+ import { TimeoutError } from "../utils/timeout.js";
7
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
8
+ const MISTRAL_DEFAULT_BASE_URL = "https://api.mistral.ai/v1";
17
9
  const getMistralApiKey = () => {
18
10
  return validateApiKey(createMistralConfig());
19
11
  };
20
12
  const getDefaultMistralModel = () => {
21
- // Default to vision-capable Mistral Small 2506 (June 2025) with multimodal support
22
- return getProviderModel("MISTRAL_MODEL", "mistral-small-2506");
13
+ // Vision-capable Mistral Small (June 2025) with multimodal support.
14
+ return getProviderModel("MISTRAL_MODEL", MistralModels.MISTRAL_SMALL_2506);
23
15
  };
24
16
  /**
25
- * Mistral AI Provider v2 - BaseProvider Implementation
26
- * Supports official AI-SDK integration with all Mistral models
17
+ * Mistral AI Provider direct HTTP, no AI SDK.
18
+ *
19
+ * OpenAI-compatible chat completions at api.mistral.ai/v1. All request/stream/
20
+ * tool-loop orchestration lives in `OpenAIChatCompletionsProvider`; this class
21
+ * only declares configuration and the provider-specific error mapping.
22
+ *
23
+ * Mistral's `/chat/completions` accepts `response_format: { type:
24
+ * "json_schema" }` on current models (mistral-small-2506 and newer), so no
25
+ * structured-output downgrade is needed — the base client's default
26
+ * pass-through is correct.
27
+ *
28
+ * @see https://docs.mistral.ai/api/
27
29
  */
28
- export class MistralProvider extends BaseProvider {
29
- model;
30
+ export class MistralProvider extends OpenAIChatCompletionsProvider {
30
31
  constructor(modelName, sdk, _region, credentials) {
31
- // Type guard for NeuroLink parameter validation
32
- const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
33
- super(modelName, "mistral", validatedNeurolink);
34
- // Initialize Mistral model with API key validation and proxy support
35
- const apiKey = credentials?.apiKey ?? getMistralApiKey();
36
- const mistral = createMistral({
37
- apiKey: apiKey,
38
- fetch: createProxyFetch(),
39
- });
40
- this.model = mistral(this.modelName);
41
- logger.debug("Mistral Provider v2 initialized", {
32
+ // Trim the override before applying precedence. A blank/whitespace
33
+ // `credentials.apiKey` must NOT bypass `getMistralApiKey()` that would
34
+ // build a client with an unusable bearer token and fail at request time
35
+ // with a confusing 401 instead of at construction time.
36
+ const overrideApiKey = credentials?.apiKey?.trim();
37
+ const apiKey = overrideApiKey && overrideApiKey.length > 0
38
+ ? overrideApiKey
39
+ : getMistralApiKey();
40
+ // Treat blank/whitespace overrides as unset so an empty
41
+ // `credentials.baseURL` or `MISTRAL_BASE_URL=` cannot silently override
42
+ // the default with "" (mirrors the apiKey precedence above).
43
+ const baseURL = credentials?.baseURL?.trim() ||
44
+ process.env.MISTRAL_BASE_URL?.trim() ||
45
+ MISTRAL_DEFAULT_BASE_URL;
46
+ super("mistral", modelName, sdk, { baseURL, apiKey });
47
+ logger.debug("Mistral Provider initialized", {
42
48
  modelName: this.modelName,
43
49
  providerName: this.providerName,
50
+ baseURL: redactUrlCredentials(this.config.baseURL),
44
51
  });
45
52
  }
46
- // generate() method is inherited from BaseProvider; this provider uses the base implementation for generation with tools
47
- async executeStream(options, _analysisSchema) {
48
- this.validateStreamOptions(options);
49
- const startTime = Date.now();
50
- const timeout = this.getTimeout(options);
51
- const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
52
- try {
53
- // Get tools - options.tools is pre-merged by BaseProvider.stream()
54
- const shouldUseTools = !options.disableTools && this.supportsTools();
55
- const tools = shouldUseTools
56
- ? options.tools || (await this.getAllTools())
57
- : {};
58
- // Build message array from options with multimodal support
59
- // Using protected helper from BaseProvider to eliminate code duplication
60
- const messages = await this.buildMessagesForStream(options);
61
- const model = await this.getAISDKModelWithMiddleware(options); // This is where network connection happens!
62
- // Reviewer follow-up: capture upstream provider errors via onError
63
- // so the post-stream NoOutput sentinel carries the real cause.
64
- let capturedProviderError;
65
- const result = await streamText({
66
- model,
67
- messages: messages,
68
- temperature: options.temperature,
69
- maxOutputTokens: options.maxTokens, // No default limit - unlimited unless specified
70
- tools,
71
- stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
72
- toolChoice: resolveToolChoice(options, tools, shouldUseTools),
73
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
74
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
75
- experimental_repairToolCall: this.getToolCallRepairFn(options),
76
- onError: (event) => {
77
- capturedProviderError = event.error;
78
- logger.error("Mistral: Stream error", {
79
- error: event.error instanceof Error
80
- ? event.error.message
81
- : String(event.error),
82
- });
83
- },
84
- onStepFinish: ({ toolCalls, toolResults }) => {
85
- emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
86
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
87
- logger.warn("[MistralProvider] Failed to store tool executions", {
88
- provider: this.providerName,
89
- error: error instanceof Error ? error.message : String(error),
90
- });
91
- });
92
- },
93
- });
94
- timeoutController?.cleanup();
95
- // Transform string stream to content object stream using BaseProvider method
96
- const transformedStream = this.createTextStream(result, () => capturedProviderError);
97
- // Create analytics promise that resolves after stream completion
98
- const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
99
- requestId: `mistral-stream-${Date.now()}`,
100
- streamingMode: true,
101
- });
102
- return {
103
- stream: transformedStream,
104
- provider: this.providerName,
105
- model: this.modelName,
106
- analytics: analyticsPromise,
107
- metadata: {
108
- startTime,
109
- streamId: `mistral-${Date.now()}`,
110
- },
111
- };
112
- }
113
- catch (error) {
114
- timeoutController?.cleanup();
115
- throw this.handleProviderError(error);
116
- }
117
- }
118
- // ===================
119
- // ABSTRACT METHOD IMPLEMENTATIONS
120
- // ===================
53
+ // ===========================================================================
54
+ // Abstract hooks (required)
55
+ // ===========================================================================
121
56
  getProviderName() {
122
- return this.providerName;
57
+ return "mistral";
123
58
  }
124
59
  getDefaultModel() {
125
60
  return getDefaultMistralModel();
126
61
  }
127
- /**
128
- * Returns the Vercel AI SDK model instance for Mistral
129
- */
130
- getAISDKModel() {
131
- return this.model;
132
- }
133
62
  formatProviderError(error) {
134
63
  if (error instanceof TimeoutError) {
135
64
  return new NetworkError(`Request timed out: ${error.message}`, "mistral");
@@ -139,35 +68,31 @@ export class MistralProvider extends BaseProvider {
139
68
  ? errorRecord.message
140
69
  : "Unknown error";
141
70
  if (message.includes("API_KEY_INVALID") ||
142
- message.includes("Invalid API key")) {
71
+ message.includes("Invalid API key") ||
72
+ message.includes("Unauthorized") ||
73
+ message.includes("401")) {
143
74
  return new AuthenticationError("Invalid Mistral API key. Please check your MISTRAL_API_KEY environment variable.", "mistral");
144
75
  }
145
- if (message.includes("Rate limit exceeded")) {
76
+ if (message.includes("rate limit") ||
77
+ message.includes("Rate limit") ||
78
+ message.includes("429")) {
146
79
  return new RateLimitError("Mistral rate limit exceeded", "mistral");
147
80
  }
81
+ if (message.includes("model_not_found") || message.includes("404")) {
82
+ return new InvalidModelError(`Mistral model '${this.modelName}' not found.`, "mistral");
83
+ }
148
84
  return new ProviderError(`Mistral error: ${message}`, "mistral");
149
85
  }
150
- /**
151
- * Validate provider configuration
152
- */
153
- async validateConfiguration() {
154
- try {
155
- getMistralApiKey();
156
- return true;
157
- }
158
- catch {
159
- return false;
160
- }
86
+ // ===========================================================================
87
+ // Optional hooks
88
+ // ===========================================================================
89
+ getFallbackModelName() {
90
+ return MistralModels.MISTRAL_SMALL_2506;
161
91
  }
162
- /**
163
- * Get provider-specific configuration
164
- */
165
- getConfiguration() {
166
- return {
167
- provider: this.providerName,
168
- model: this.modelName,
169
- defaultModel: getDefaultMistralModel(),
170
- };
92
+ getFallbackModels() {
93
+ return [
94
+ MistralModels.MISTRAL_SMALL_2506,
95
+ MistralModels.MISTRAL_LARGE_LATEST,
96
+ ];
171
97
  }
172
98
  }
173
- export default MistralProvider;
@@ -129,6 +129,7 @@ export type NeurolinkCredentials = {
129
129
  };
130
130
  mistral?: {
131
131
  apiKey?: string;
132
+ baseURL?: string;
132
133
  };
133
134
  huggingFace?: {
134
135
  apiKey?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "9.68.17",
3
+ "version": "9.68.18",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "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 applications with 21+ providers: OpenAI, Anthropic, Google AI Studio, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, LiteLLM, SageMaker, Hugging Face, Ollama, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech).",
6
6
  "author": {