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

206 lines • 8.05 kB
import chalk from "chalk"; import ora from "ora"; import inquirer from "inquirer"; import fs from "fs"; import path from "path"; import { logger } from "../../lib/utils/logger.js"; import { getTopModelChoices } from "../../lib/utils/modelChoices.js"; import { AIProviderName } from "../../lib/types/index.js"; /** * Validates Mistral API key format * Mistral keys typically start with "sk-" and contain base62 plus "-" or "_". */ function validateMistralApiKey(apiKey) { const key = apiKey.trim(); return /^sk-[A-Za-z0-9_-]{20,}$/.test(key); } /** * Safely parse and reconstruct .env file content */ function updateEnvFile(updates) { const envPath = path.resolve(process.cwd(), ".env"); let envContent = ""; // Read existing .env if it exists if (fs.existsSync(envPath)) { envContent = fs.readFileSync(envPath, "utf-8"); } // Parse existing environment variables const envLines = envContent.split("\n"); const envVars = new Map(); // Track which variables we found and their positions envLines.forEach((line, index) => { const trimmed = line.trim(); if (trimmed && !trimmed.startsWith("#")) { const equalIndex = trimmed.indexOf("="); if (equalIndex > 0) { const key = trimmed.substring(0, equalIndex); const value = trimmed.substring(equalIndex + 1); envVars.set(key, { value, lineIndex: index }); } } }); // Update existing variables or add new ones for (const [key, newValue] of Object.entries(updates)) { const existing = envVars.get(key); if (existing) { // Update existing variable envLines[existing.lineIndex] = `${key}=${newValue}`; } else { // Add new variable envLines.push(`${key}=${newValue}`); } } // Write updated content fs.writeFileSync(envPath, envLines.join("\n")); } /** * Check current Mistral AI configuration */ function checkMistralConfig() { const apiKey = process.env.MISTRAL_API_KEY; const model = process.env.MISTRAL_MODEL; const hasApiKey = !!apiKey; const hasModel = !!model; const isValid = typeof apiKey === "string" && validateMistralApiKey(apiKey); return { hasApiKey, hasModel, apiKey: apiKey ? `${apiKey.substring(0, 8)}...` : undefined, model, isValid, }; } export const handleMistralSetup = async (argv) => { const spinner = ora(); try { spinner.start("Checking Mistral AI configuration..."); const config = checkMistralConfig(); spinner.stop(); // Display current status logger.always(chalk.bold.blue("\n🧠 Mistral AI Configuration Status\n")); logger.always(`${config.hasApiKey ? "āœ…" : "āŒ"} API Key: ${config.apiKey || "Not set"}`); logger.always(`${config.hasModel ? "āœ…" : "āš ļø"} Model: ${config.model || "Not set (will use default)"}`); if (config.isValid) { logger.always(chalk.green("\nāœ… Mistral AI is properly configured!")); if (argv.check) { return; } const { shouldReconfigure } = await inquirer.prompt([ { type: "confirm", name: "shouldReconfigure", message: "Configuration looks good. Do you want to reconfigure anyway?", default: false, }, ]); if (!shouldReconfigure) { logger.always(chalk.green("āœ… Keeping existing configuration.")); return; } } else { logger.always(chalk.yellow("\nāš ļø Mistral AI configuration needs setup.")); if (argv.check) { process.exit(1); } } if (argv["non-interactive"]) { logger.always(chalk.yellow("Non-interactive mode: Skipping configuration setup.")); logger.always(chalk.blue("Please set MISTRAL_API_KEY manually.")); return; } // Interactive setup logger.always(chalk.blue("\nšŸ› ļø Let's configure Mistral AI!\n")); // Show instructions for getting API key logger.always(chalk.yellow("šŸ“‹ To get your Mistral AI API key:")); logger.always("1. Visit: https://console.mistral.ai/"); logger.always("2. Sign up or sign in to your account"); logger.always("3. Go to 'API Keys' section"); logger.always("4. Create a new API key"); logger.always("5. Copy the API key\n"); // Step 1: API Key const { apiKey } = await inquirer.prompt([ { type: "password", name: "apiKey", message: "Enter your Mistral AI API key:", mask: "*", validate: (input) => { if (!input.trim()) { return "API key is required"; } if (!validateMistralApiKey(input.trim())) { return "Invalid API key format. Should be alphanumeric and at least 20 characters"; } return true; }, }, ]); // Step 2: Model Selection const { modelChoice } = await inquirer.prompt([ { type: "select", name: "modelChoice", message: "Select a Mistral model:", choices: getTopModelChoices(AIProviderName.MISTRAL, 5), }, ]); let selectedModel = modelChoice; if (modelChoice === "custom") { const { customModel } = await inquirer.prompt([ { type: "input", name: "customModel", message: "Enter custom Mistral model name:", validate: (input) => { const trimmed = input.trim(); if (!trimmed) { return "Model name is required"; } return true; }, }, ]); selectedModel = customModel.trim(); } // Save configuration spinner.start("Saving configuration..."); const updates = { MISTRAL_API_KEY: apiKey.trim(), MISTRAL_MODEL: selectedModel, }; updateEnvFile(updates); spinner.stop(); logger.always(chalk.green("\nāœ… Mistral AI configuration saved successfully!")); logger.always(chalk.blue("\nšŸ“– Usage examples:")); logger.always(chalk.gray(' neurolink generate "Hello, how are you?" --provider mistral')); logger.always(chalk.gray(` neurolink generate "Explain quantum physics" --provider mistral --model ${selectedModel}`)); logger.always(chalk.blue("\nšŸ”— Resources:")); logger.always(chalk.gray(" • Mistral AI Console: https://console.mistral.ai/")); logger.always(chalk.gray(" • API Documentation: https://docs.mistral.ai/")); logger.always(chalk.gray(" • Model Information: https://docs.mistral.ai/getting-started/models/")); logger.always(chalk.blue("\nšŸ’” Features:")); logger.always(chalk.gray(" • European GDPR-compliant AI")); logger.always(chalk.gray(" • Multilingual support")); logger.always(chalk.gray(" • Fast inference speeds")); } catch (error) { spinner.stop(); logger.error("Mistral AI setup failed", error); throw error; } }; export const setupMistralBuilder = { check: { type: "boolean", describe: "Only check existing configuration without prompting", default: false, }, "non-interactive": { type: "boolean", describe: "Skip interactive prompts", default: false, }, }; //# sourceMappingURL=setup-mistral.js.map