@juspay/neurolink
Version:
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
143 lines (142 loc) • 5.63 kB
JavaScript
import { createMistral } from "@ai-sdk/mistral";
import { streamText } from "ai";
import { BaseProvider } from "../core/baseProvider.js";
import { logger } from "../utils/logger.js";
import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
import { validateApiKey, createMistralConfig, getProviderModel, } from "../utils/providerConfig.js";
import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
import { buildMessagesArray } from "../utils/messageBuilder.js";
import { createProxyFetch } from "../proxy/proxyFetch.js";
// Configuration helpers - now using consolidated utility
const getMistralApiKey = () => {
return validateApiKey(createMistralConfig());
};
const getDefaultMistralModel = () => {
return getProviderModel("MISTRAL_MODEL", "mistral-large-latest");
};
/**
* Mistral AI Provider v2 - BaseProvider Implementation
* Supports official AI-SDK integration with all Mistral models
*/
export class MistralProvider extends BaseProvider {
model;
constructor(modelName, sdk) {
// Type guard for NeuroLink parameter validation
const validatedNeurolink = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
? sdk
: undefined;
super(modelName, "mistral", validatedNeurolink);
// Initialize Mistral model with API key validation and proxy support
const apiKey = getMistralApiKey();
const mistral = createMistral({
apiKey: apiKey,
fetch: createProxyFetch(),
});
this.model = mistral(this.modelName);
logger.debug("Mistral Provider v2 initialized", {
modelName: this.modelName,
providerName: this.providerName,
});
}
// generate() method is inherited from BaseProvider; this provider uses the base implementation for generation with tools
async executeStream(options, analysisSchema) {
this.validateStreamOptions(options);
const startTime = Date.now();
const timeout = this.getTimeout(options);
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
try {
// Get tools consistently with generate method
const shouldUseTools = !options.disableTools && this.supportsTools();
const tools = shouldUseTools ? await this.getAllTools() : {};
const messages = buildMessagesArray(options);
const result = await streamText({
model: this.model,
messages: messages,
temperature: options.temperature,
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
tools,
maxSteps: options.maxSteps || DEFAULT_MAX_STEPS,
toolChoice: shouldUseTools ? "auto" : "none",
abortSignal: timeoutController?.controller.signal,
});
timeoutController?.cleanup();
// Transform string stream to content object stream using BaseProvider method
const transformedStream = this.createTextStream(result);
// Create analytics promise that resolves after stream completion
const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, result, Date.now() - startTime, {
requestId: `mistral-stream-${Date.now()}`,
streamingMode: true,
});
return {
stream: transformedStream,
provider: this.providerName,
model: this.modelName,
analytics: analyticsPromise,
metadata: {
startTime,
streamId: `mistral-${Date.now()}`,
},
};
}
catch (error) {
timeoutController?.cleanup();
throw this.handleProviderError(error);
}
}
// ===================
// ABSTRACT METHOD IMPLEMENTATIONS
// ===================
getProviderName() {
return this.providerName;
}
getDefaultModel() {
return getDefaultMistralModel();
}
/**
* Returns the Vercel AI SDK model instance for Mistral
*/
getAISDKModel() {
return this.model;
}
handleProviderError(error) {
if (error instanceof TimeoutError) {
return new Error(`Mistral request timed out: ${error.message}`);
}
const errorRecord = error;
const message = typeof errorRecord?.message === "string"
? errorRecord.message
: "Unknown error";
if (message.includes("API_KEY_INVALID") ||
message.includes("Invalid API key")) {
return new Error("Invalid Mistral API key. Please check your MISTRAL_API_KEY environment variable.");
}
if (message.includes("rate limit")) {
return new Error("Mistral rate limit exceeded. Please try again later.");
}
return new Error(`Mistral error: ${message}`);
}
/**
* Validate provider configuration
*/
async validateConfiguration() {
try {
getMistralApiKey();
return true;
}
catch {
return false;
}
}
/**
* Get provider-specific configuration
*/
getConfiguration() {
return {
provider: this.providerName,
model: this.modelName,
defaultModel: getDefaultMistralModel(),
};
}
}
export default MistralProvider;