UNPKG

voyageai-cli

Version:

CLI for Voyage AI embeddings, reranking, and MongoDB Atlas Vector Search

115 lines (97 loc) 3.58 kB
'use strict'; const pc = require('picocolors'); const ui = require('./ui'); const { identifyKey } = require('./api'); const { showBanner } = require('./banner'); const { loadConfig, isFirstRun, isWelcomeSuppressed, saveConfig } = require('./config'); const { send } = require('./telemetry'); const { runWizard } = require('./wizard'); const { createCLIRenderer } = require('./wizard-cli'); const { welcomeSteps } = require('./wizard-steps-welcome'); /** * Determine if the welcome flow should run. * Conditions: first run, interactive TTY, not suppressed by env var. * @param {string} [configPath] - Override config path (for testing) * @returns {boolean} */ function shouldShowWelcome(configPath) { if (!isFirstRun(configPath)) return false; if (isWelcomeSuppressed(configPath)) return false; if (!process.stdin.isTTY || !process.stdout.isTTY) return false; return true; } /** * Run the first-run welcome wizard. * * Shows the banner, collects API key (and optionally MongoDB URI), * saves to ~/.vai/config.json, and prints next steps. * * @param {object} [opts] * @param {string} [opts.configPath] - Override config path (for testing) * @returns {Promise<boolean>} true if setup completed, false if cancelled */ async function runWelcome(opts = {}) { // Show the banner first showBanner(); console.log(pc.bold(' Welcome! Let\'s get you set up.\n')); console.log(' To use vai, you need a Voyage AI API key.'); console.log(` Get a free key at: ${pc.cyan('https://dash.voyageai.com/api-keys')}`); console.log(` (MongoDB Atlas keys starting with ${pc.cyan('al-')} also work)\n`); const renderer = createCLIRenderer({ title: 'vai setup', doneMessage: 'Setup complete!', }); const { answers, cancelled } = await runWizard({ steps: welcomeSteps, config: {}, renderer, }); if (cancelled) { return false; } // Build config object const config = loadConfig(opts.configPath); const apiKey = (answers.apiKey || '').trim(); if (apiKey) { config.apiKey = apiKey; // Auto-detect base URL from key prefix const keyInfo = identifyKey(apiKey); config.baseUrl = keyInfo.expectedBase; // Set in process.env so subsequent commands in the same session work process.env.VOYAGE_API_KEY = apiKey; } if (answers.mongodbUri) { const uri = answers.mongodbUri.trim(); if (uri) { config.mongodbUri = uri; process.env.MONGODB_URI = uri; } } // Save to ~/.vai/config.json saveConfig(config, opts.configPath); // Show next steps console.log(''); if (apiKey) { const keyInfo = identifyKey(apiKey); console.log(` ${ui.green('\u2713')} API key saved (${pc.dim(keyInfo.label)} endpoint)`); } if (answers.mongodbUri) { console.log(` ${ui.green('\u2713')} MongoDB URI saved`); } console.log(''); console.log(pc.bold(' What to do next:\n')); console.log(` ${pc.cyan('vai quickstart')} Zero-to-search tutorial (2 min)`); console.log(` ${pc.cyan('vai doctor')} Verify your full setup`); console.log(` ${pc.cyan('vai nano setup')} Enable free local embeddings`); console.log(` ${pc.cyan('vai embed "hello"')} Generate your first embedding`); console.log(''); console.log(pc.dim(' Run vai --help to see all commands.\n')); // Telemetry (non-blocking, fire-and-forget) send('cli_welcome_complete', { hasApiKey: !!apiKey, hasMongo: !!answers.mongodbUri, keyType: apiKey ? identifyKey(apiKey).type : 'none', }); return true; } module.exports = { shouldShowWelcome, runWelcome };