1 line
41 KiB
JSON
1 line
41 KiB
JSON
{"repo": "3289david/dnpm", "files": {"src/ai/setup.js": {"2869f841eac62235650bbc79b536fe49024ebb0d": {"t": 1785746463.9046946, "n": 16327, "h": "aa5796562ca43a2d", "c": "import Enquirer from 'enquirer';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { log, section, banner, box } from '../ui/logger.js';\nimport { ConfigManager } from '../config/index.js';\nimport { AIProvider } from '../ai/provider.js';\n\nconst enquirer = new Enquirer();\n\n// ============================================================================\n// 25+ AI PROVIDERS — All API Key Required (except Ollama & Pollinations)\n// ============================================================================\nconst PROVIDERS = {\n // ── FREE / NO-KEY PROVIDERS ──────────────────────────────────────────────\n ollama: {\n name: 'Ollama (Local)',\n category: 'free',\n description: 'Free, local AI. No API key needed.',\n models: ['llama3', 'llama3:70b', 'codellama', 'mistral', 'mixtral', 'phi3', 'gemma', 'qwen2', 'deepseek-coder-v2', 'command-r'],\n keyRequired: false,\n url: 'https://ollama.ai',\n setupGuide: 'Install: curl -fsSL https://ollama.ai/install.sh | sh\\nThen: ollama pull llama3',\n },\n pollinations: {\n name: 'Pollinations.ai',\n category: 'free',\n description: 'Free AI text & image generation. No API key.',\n models: ['openai', 'mistral', 'llama', 'deepseek', 'command-r'],\n keyRequired: false,\n url: 'https://pollinations.ai',\n setupGuide: 'No setup needed. Free tier with generous limits.',\n },\n\n // ── TIER 1: MAJOR PROVIDERS (API KEY REQUIRED) ──────────────────────────\n openai: {\n name: 'OpenAI (GPT)',\n category: 'tier1',\n description: 'GPT-4o, GPT-4.1, o3, o4-mini',\n models: ['gpt-4o', 'gpt-4o-mini', 'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano', 'o3', 'o3-mini', 'o4-mini', 'gpt-4-turbo'],\n keyRequired: true,\n url: 'https://platform.openai.com/api-keys',\n keyPrefix: 'sk-',\n },\n claude: {\n name: 'Claude (Anthropic)',\n category: 'tier1',\n description: 'Claude Opus 4, Sonnet 4, Haiku',\n models: ['claude-sonnet-4-20250514', 'claude-opus-4-20250514', 'claude-haiku-4-20250514', 'claude-3.5-sonnet-20241022', 'claude-3-opus-20240229'],\n keyRequired: true,\n url: 'https://console.anthropic.com/settings/keys',\n keyPrefix: 'sk-ant-',\n },\n gemini: {\n name: 'Gemini (Google)',\n category: 'tier1',\n description: 'Gemini 2.5 Pro, Flash, Ultra',\n models: ['gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash', 'gemini-ultra'],\n keyRequired: true,\n url: 'https://aistudio.google.com/app/apikey',\n keyPrefix: 'AI',\n },\n xai: {\n name: 'xAI (Grok)',\n category: 'tier1',\n description: 'Grok-3, Grok-3 Mini by xAI',\n models: ['grok-3', 'grok-3-mini', 'grok-2', 'grok-2-mini'],\n keyRequired: true,\n url: 'https://console.x.ai',\n keyPrefix: 'xai-',\n },\n\n // ── TIER 2: SPECIALIZED PROVIDERS (API KEY REQUIRED) ────────────────────\n deepseek: {\n name: 'DeepSeek',\n category: 'tier2',\n description: 'DeepSeek-V3, Coder, Reasoner (R1)',\n models: ['deepseek-chat', 'deepseek-coder', 'deepseek-reasoner'],\n keyRequired: true,\n url: 'https://platform.deepseek.com/api_keys',\n keyPrefix: 'sk-',\n },\n mistral: {\n name: 'Mistral AI',\n category: 'tier2',\n description: 'Mistral Large, Medium, Codestral',\n models: ['mistral-large-latest', 'mistral-medium-latest', 'mistral-small-latest', 'codestral-latest', 'open-mixtral-8x22b'],\n keyRequired: true,\n url: 'https://console.mistral.ai/api-keys',\n keyPrefix: '',\n },\n cohere: {\n name: 'Cohere',\n category: 'tier2',\n description: 'Command R+, Command R, Embed',\n models: ['command-r-plus', 'command-r', 'command-light', 'command-nightly'],\n keyRequired: true,\n url: 'https://dashboard.cohere.com/api-keys',\n keyPrefix: '',\n },\n perplexity: {\n name: 'Perplexity AI',\n category: 'tier2',\n description: 'Sonar Large, Sonar Small — search-powered AI',\n models: ['sonar-pro', 'sonar', 'sonar-reasoning-pro', 'sonar-reasoning'],\n keyRequired: true,\n url: 'https://www.perplexity.ai/settings/api',\n keyPrefix: 'pplx-',\n },\n groq: {\n name: 'Groq',\n category: 'tier2',\n description: 'Ultra-fast inference. Llama, Mixtral, Gemma',\n models: ['llama-3.3-70b-versatile', 'llama-3.1-8b-instant', 'mixtral-8x7b-32768', 'gemma2-9b-it'],\n keyRequired: true,\n url: 'https://console.groq.com/keys',\n keyPrefix: 'gsk_',\n },\n together: {\n name: 'Together AI',\n category: 'tier2',\n description: 'Open-source models at scale. Llama, Qwen, DeepSeek',\n models: ['meta-llama/Llama-3.3-70B-Instruct-Turbo', 'Qwen/Qwen2.5-72B-Instruct-Turbo', 'deepseek-ai/DeepSeek-R1', 'mistralai/Mixtral-8x22B-Instruct-v0.1'],\n keyRequired: true,\n url: 'https://api.together.xyz/settings/api-keys',\n keyPrefix: '',\n },\n fireworks: {\n name: 'Fireworks AI',\n category: 'tier2',\n description: 'Fast open-source model hosting. Llama, Mixtral',\n models: ['accounts/fireworks/models/llama-v3p3-70b-instruct', 'accounts/fireworks/models/mixtral-8x22b-instruct', 'accounts/fireworks/models/qwen2p5-72b-instruct'],\n keyRequired: true,\n url: 'https://fireworks.ai/account/api-keys',\n keyPrefix: '',\n },\n\n // ── TIER 3: CLOUD PLATFORM AI (API KEY REQUIRED) ───────────────────────\n azure: {\n name: 'Azure OpenAI',\n category: 'tier3',\n description: 'Microsoft Azure-hosted GPT-4, GPT-4o',\n models: ['gpt-4o', 'gpt-4', 'gpt-4-turbo', 'gpt-35-turbo'],\n keyRequired: true,\n url: 'https://portal.azure.com/#view/Microsoft_Azure_ProjectOxford/CognitiveServicesHub',\n keyPrefix: '',\n extraConfig: ['endpoint'],\n },\n bedrock: {\n name: 'AWS Bedrock',\n category: 'tier3',\n description: 'AWS-hosted Claude, Llama, Titan, Mistral',\n models: ['anthropic.claude-sonnet-4-20250514-v1:0', 'meta.llama3-70b-instruct-v1:0', 'amazon.titan-text-premier-v1:0', 'mistral.mixtral-8x7b-instruct-v0:1'],\n keyRequired: true,\n url: 'https://console.aws.amazon.com/bedrock',\n keyPrefix: '',\n extraConfig: ['region', 'accessKeyId', 'secretAccessKey'],\n },\n vertex: {\n name: 'Google Vertex AI',\n category: 'tier3',\n description: 'Google Cloud-hosted Gemini, PaLM',\n models: ['gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-1.5-pro', 'text-bison'],\n keyRequired: true,\n url: 'https://console.cloud.google.com/vertex-ai',\n keyPrefix: '',\n extraConfig: ['projectId', 'location'],\n },\n\n // ── TIER 4: AGGREGATORS & ROUTERS (API KEY REQUIRED) ───────────────────\n openrouter: {\n name: 'OpenRouter',\n category: 'aggregator',\n description: 'Access 200+ models with one API key',\n models: ['openai/gpt-4o', 'anthropic/claude-sonnet-4-20250514', 'google/gemini-2.5-pro', 'meta-llama/llama-3.3-70b-instruct', 'deepseek/deepseek-r1'],\n keyRequired: true,\n url: 'https://openrouter.ai/keys',\n keyPrefix: 'sk-or-',\n },\n litellm: {\n name: 'LiteLLM Proxy',\n category: 'aggregator',\n description: 'Unified proxy for 100+ LLMs. Self-hosted.',\n models: ['gpt-4o', 'claude-sonnet-4-20250514', 'gemini-pro', 'command-r-plus'],\n keyRequired: true,\n url: 'https://docs.litellm.ai',\n keyPrefix: '',\n extraConfig: ['baseUrl'],\n },\n\n // ── TIER 5: OPEN-SOURCE / SPECIALIZED (API KEY REQUIRED) ───────────────\n replicate: {\n name: 'Replicate',\n category: 'specialized',\n description: 'Run open-source models via API. Llama, Stable Diffusion',\n models: ['meta/llama-3-70b-instruct', 'mistralai/mixtral-8x7b-instruct-v0.1', 'meta/llama-3-8b-instruct'],\n keyRequired: true,\n url: 'https://replicate.com/account/api-tokens',\n keyPrefix: 'r8_',\n },\n huggingface: {\n name: 'Hugging Face Inference',\n category: 'specialized',\n description: 'Run 200k+ models via Inference API',\n models: ['meta-llama/Llama-3.3-70B-Instruct', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'Qwen/Qwen2.5-72B-Instruct', 'google/gemma-2-9b-it'],\n keyRequired: true,\n url: 'https://huggingface.co/settings/tokens',\n keyPrefix: 'hf_',\n },\n ai21: {\n name: 'AI21 Labs (Jamba)',\n category: 'specialized',\n description: 'Jamba 1.5 Large, Jamba 1.5 Mini',\n models: ['jamba-1.5-large', 'jamba-1.5-mini', 'j2-ultra', 'j2-mid'],\n keyRequired: true,\n url: 'https://studio.ai21.com/account/api-key',\n keyPrefix: '',\n },\n sambanova: {\n name: 'SambaNova',\n category: 'specialized',\n description: 'Ultra-fast Llama & custom models on RDU chips',\n models: ['Meta-Llama-3.3-70B-Instruct', 'Meta-Llama-3.1-8B-Instruct', 'Meta-Llama-3.1-405B-Instruct'],\n keyRequired: true,\n url: 'https://cloud.sambanova.ai/apis',\n keyPrefix: '',\n },\n cerebras: {\n name: 'Cerebras',\n category: 'specialized',\n description: 'Fastest inference on Wafer-Scale chips',\n models: ['llama-3.3-70b', 'llama-3.1-8b'],\n keyRequired: true,\n url: 'https://cloud.cerebras.ai',\n keyPrefix: 'csk-',\n },\n lepton: {\n name: 'Lepton AI',\n category: 'specialized',\n description: 'Fast serverless AI. Llama, Mixtral hosting',\n models: ['llama3-70b', 'mixtral-8x7b', 'llama3-8b'],\n keyRequired: true,\n url: 'https://dashboard.lepton.ai',\n keyPrefix: '',\n },\n novita: {\n name: 'Novita AI',\n category: 'specialized',\n description: 'Affordable GPU cloud for LLM inference',\n models: ['meta-llama/llama-3-70b-instruct', 'mistralai/mixtral-8x7b-instruct', 'nousresearch/hermes-3-llama-3.1-70b'],\n keyRequired: true,\n url: 'https://novita.ai/dashboard/key',\n keyPrefix: '',\n },\n anyscale: {\n name: 'Anyscale Endpoints',\n category: 'specialized',\n description: 'Scalable open-source model hosting (Ray-based)',\n models: ['meta-llama/Llama-3-70b-chat-hf', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'codellama/CodeLlama-70b-Instruct-hf'],\n keyRequired: true,\n url: 'https://app.endpoints.anyscale.com',\n keyPrefix: '',\n },\n};\n\nexport async function setupWizard() {\n banner();\n section('AI Provider Setup Wizard — 25+ Providers');\n\n console.log(chalk.gray(' Configure your AI provider for intelligent DevOps.\\n'));\n\n // Group providers by category\n const categories = {\n free: { label: '🆓 Free / No API Key', providers: [] },\n tier1: { label: '⭐ Tier 1 — Major Providers', providers: [] },\n tier2: { label: '🚀 Tier 2 — Specialized', providers: [] },\n tier3: { label: '☁️ Tier 3 — Cloud Platform AI', providers: [] },\n aggregator: { label: '🔀 Aggregators & Routers', providers: [] },\n specialized: { label: '🔬 Open-Source & Specialized', providers: [] },\n };\n\n for (const [key, p] of Object.entries(PROVIDERS)) {\n const cat = p.category || 'specialized';\n if (categories[cat]) categories[cat].providers.push({ key, ...p });\n }\n\n // Build choices with category separators\n const choices = [];\n for (const [, cat] of Object.entries(categories)) {\n if (cat.providers.length === 0) continue;\n choices.push({ role: 'separator', message: chalk.bold.yellow(`\\n ─── ${cat.label} ───`) });\n for (const p of cat.providers) {\n const keyTag = p.keyRequired ? chalk.yellow(' [KEY]') : chalk.green(' [FREE]');\n choices.push({\n name: p.key,\n message: `${p.name.padEnd(28)} ${chalk.gray(p.description)}${keyTag}`,\n value: p.key,\n });\n }\n }\n\n const { provider } = await enquirer.prompt({\n type: 'select',\n name: 'provider',\n message: chalk.cyan('Choose your AI provider:'),\n choices,\n });\n\n const providerInfo = PROVIDERS[provider];\n const cm = new ConfigManager();\n await cm.init();\n\n console.log('');\n box(providerInfo.name, [\n providerInfo.description,\n `Key Required: ${providerInfo.keyRequired ? chalk.yellow('Yes') : chalk.green('No')}`,\n providerInfo.keyRequired ? `Get your key: ${chalk.cyan(providerInfo.url)}` : providerInfo.setupGuide,\n ]);\n\n // API Key input\n if (providerInfo.keyRequired) {\n console.log('');\n log(`Get your API key from: ${chalk.cyan.underline(providerInfo.url)}`, 'info');\n console.log('');\n\n const { apiKey } = await enquirer.prompt({\n type: 'password',\n name: 'apiKey',\n message: chalk.cyan(`Enter your ${providerInfo.name} API key:`),\n validate: (val) => {\n if (!val || val.trim().length < 10) return 'API key is too short';\n if (providerInfo.keyPrefix && !val.startsWith(providerInfo.keyPrefix)) {\n return `Key should start with \"${providerInfo.keyPrefix}\"`;\n }\n return true;\n },\n });\n\n await cm.setAPIKey(provider, apiKey.trim());\n log(`API key saved for ${providerInfo.name}`, 'success');\n }\n\n // Model selection\n const { model } = await enquirer.prompt({\n type: 'select',\n name: 'model',\n message: chalk.cyan('Choose your default model:'),\n choices: providerInfo.models.map((m, i) => ({\n name: m,\n message: m,\n value: m,\n })),\n });\n\n await cm.setAIProvider(provider, model);\n log(`Default AI set to ${chalk.cyan(providerInfo.name)} / ${chalk.green(model)}`, 'success');\n\n // Test connection\n console.log('');\n const { testIt } = await enquirer.prompt({\n type: 'confirm',\n name: 'testIt',\n message: chalk.cyan('Test the AI connection now?'),\n initial: true,\n });\n\n if (testIt) {\n const spinner = ora('Testing AI connection...').start();\n try {\n const ai = await AIProvider.create();\n const response = await ai.prompt('Say \"dnpm AI connected successfully!\" in one line.');\n spinner.succeed(`AI connected: ${chalk.green(response.slice(0, 100))}`);\n } catch (err) {\n spinner.fail(`Connection failed: ${err.message}`);\n log('Check your API key and try again with: dnpm setup-ai', 'warning');\n }\n }\n\n console.log('');\n log('AI setup complete! You can now use:', 'success');\n console.log(chalk.gray(`\n dnpm ai mode # Interactive AI assistant\n dnpm ai fix # Auto-fix errors\n dnpm ai ask \"question\" # Ask anything\n dnpm ai generate \"...\" # Generate code\n dnpm analyze # AI system analysis\n `));\n}\n\nexport async function quickSetKey(provider, key) {\n const providerInfo = PROVIDERS[provider];\n if (!providerInfo) {\n const available = Object.keys(PROVIDERS).join(', ');\n throw new Error(`Unknown provider: ${provider}. Available: ${available}`);\n }\n\n if (providerInfo.keyRequired && (!key || key.trim().length < 10)) {\n throw new Error('API key is too short or missing');\n }\n\n const cm = new ConfigManager();\n await cm.init();\n\n if (key) {\n await cm.setAPIKey(provider, key.trim());\n log(`API key saved for ${providerInfo.name}`, 'success');\n }\n\n return { provider, saved: true };\n}\n\nexport async function listProviders() {\n section('AI Providers — 25+ Supported');\n const cm = new ConfigManager();\n const config = await cm.getGlobalConfig();\n const currentProvider = config.ai?.provider;\n const currentModel = config.ai?.model;\n\n const categories = {\n free: '🆓 Free / No API Key',\n tier1: '⭐ Tier 1 — Major Providers',\n tier2: '🚀 Tier 2 — Specialized',\n tier3: '☁️ Cloud Platform AI',\n aggregator: '🔀 Aggregators & Routers',\n specialized: '🔬 Open-Source & Specialized',\n };\n\n const grouped = {};\n for (const [key, p] of Object.entries(PROVIDERS)) {\n const cat = p.category || 'specialized';\n if (!grouped[cat]) grouped[cat] = [];\n grouped[cat].push({ key, ...p });\n }\n\n for (const [catKey, catLabel] of Object.entries(categories)) {\n if (!grouped[catKey] || grouped[catKey].length === 0) continue;\n console.log(`\\n ${chalk.bold.yellow(catLabel)}`);\n for (const p of grouped[catKey]) {\n const isCurrent = p.key === currentProvider;\n const hasKey = config.ai?.apiKeys?.[p.key] || !p.keyRequired;\n const icon = isCurrent ? chalk.green('▶') : hasKey ? chalk.cyan('●') : chalk.gray('○');\n const status = isCurrent ? chalk.green(` (active: ${currentModel})`) : hasKey && p.keyRequired ? chalk.gray(' (key set)') : '';\n const keyTag = p.keyRequired ? '' : chalk.green(' FREE');\n\n console.log(` ${icon} ${chalk.white(p.name.padEnd(28))} ${chalk.gray(p.description)}${status}${keyTag}`);\n }\n }\n\n console.log(`\\n ${chalk.white(`Total: ${Object.keys(PROVIDERS).length} providers`)}`);\n console.log(`\\n ${chalk.gray('Setup:')} ${chalk.cyan('dnpm setup-ai')}`);\n console.log(` ${chalk.gray('Set key:')} ${chalk.cyan('dnpm config set-key <provider> <key>')}\\n`);\n}\n\nexport { PROVIDERS };\n"}, "d8041adac4e15a947cb5fdc61d33d8530ed42d8a": {"t": 1785764588.9738047, "n": 16327, "h": "aa5796562ca43a2d", "c": "import Enquirer from 'enquirer';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { log, section, banner, box } from '../ui/logger.js';\nimport { ConfigManager } from '../config/index.js';\nimport { AIProvider } from '../ai/provider.js';\n\nconst enquirer = new Enquirer();\n\n// ============================================================================\n// 25+ AI PROVIDERS — All API Key Required (except Ollama & Pollinations)\n// ============================================================================\nconst PROVIDERS = {\n // ── FREE / NO-KEY PROVIDERS ──────────────────────────────────────────────\n ollama: {\n name: 'Ollama (Local)',\n category: 'free',\n description: 'Free, local AI. No API key needed.',\n models: ['llama3', 'llama3:70b', 'codellama', 'mistral', 'mixtral', 'phi3', 'gemma', 'qwen2', 'deepseek-coder-v2', 'command-r'],\n keyRequired: false,\n url: 'https://ollama.ai',\n setupGuide: 'Install: curl -fsSL https://ollama.ai/install.sh | sh\\nThen: ollama pull llama3',\n },\n pollinations: {\n name: 'Pollinations.ai',\n category: 'free',\n description: 'Free AI text & image generation. No API key.',\n models: ['openai', 'mistral', 'llama', 'deepseek', 'command-r'],\n keyRequired: false,\n url: 'https://pollinations.ai',\n setupGuide: 'No setup needed. Free tier with generous limits.',\n },\n\n // ── TIER 1: MAJOR PROVIDERS (API KEY REQUIRED) ──────────────────────────\n openai: {\n name: 'OpenAI (GPT)',\n category: 'tier1',\n description: 'GPT-4o, GPT-4.1, o3, o4-mini',\n models: ['gpt-4o', 'gpt-4o-mini', 'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano', 'o3', 'o3-mini', 'o4-mini', 'gpt-4-turbo'],\n keyRequired: true,\n url: 'https://platform.openai.com/api-keys',\n keyPrefix: 'sk-',\n },\n claude: {\n name: 'Claude (Anthropic)',\n category: 'tier1',\n description: 'Claude Opus 4, Sonnet 4, Haiku',\n models: ['claude-sonnet-4-20250514', 'claude-opus-4-20250514', 'claude-haiku-4-20250514', 'claude-3.5-sonnet-20241022', 'claude-3-opus-20240229'],\n keyRequired: true,\n url: 'https://console.anthropic.com/settings/keys',\n keyPrefix: 'sk-ant-',\n },\n gemini: {\n name: 'Gemini (Google)',\n category: 'tier1',\n description: 'Gemini 2.5 Pro, Flash, Ultra',\n models: ['gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash', 'gemini-ultra'],\n keyRequired: true,\n url: 'https://aistudio.google.com/app/apikey',\n keyPrefix: 'AI',\n },\n xai: {\n name: 'xAI (Grok)',\n category: 'tier1',\n description: 'Grok-3, Grok-3 Mini by xAI',\n models: ['grok-3', 'grok-3-mini', 'grok-2', 'grok-2-mini'],\n keyRequired: true,\n url: 'https://console.x.ai',\n keyPrefix: 'xai-',\n },\n\n // ── TIER 2: SPECIALIZED PROVIDERS (API KEY REQUIRED) ────────────────────\n deepseek: {\n name: 'DeepSeek',\n category: 'tier2',\n description: 'DeepSeek-V3, Coder, Reasoner (R1)',\n models: ['deepseek-chat', 'deepseek-coder', 'deepseek-reasoner'],\n keyRequired: true,\n url: 'https://platform.deepseek.com/api_keys',\n keyPrefix: 'sk-',\n },\n mistral: {\n name: 'Mistral AI',\n category: 'tier2',\n description: 'Mistral Large, Medium, Codestral',\n models: ['mistral-large-latest', 'mistral-medium-latest', 'mistral-small-latest', 'codestral-latest', 'open-mixtral-8x22b'],\n keyRequired: true,\n url: 'https://console.mistral.ai/api-keys',\n keyPrefix: '',\n },\n cohere: {\n name: 'Cohere',\n category: 'tier2',\n description: 'Command R+, Command R, Embed',\n models: ['command-r-plus', 'command-r', 'command-light', 'command-nightly'],\n keyRequired: true,\n url: 'https://dashboard.cohere.com/api-keys',\n keyPrefix: '',\n },\n perplexity: {\n name: 'Perplexity AI',\n category: 'tier2',\n description: 'Sonar Large, Sonar Small — search-powered AI',\n models: ['sonar-pro', 'sonar', 'sonar-reasoning-pro', 'sonar-reasoning'],\n keyRequired: true,\n url: 'https://www.perplexity.ai/settings/api',\n keyPrefix: 'pplx-',\n },\n groq: {\n name: 'Groq',\n category: 'tier2',\n description: 'Ultra-fast inference. Llama, Mixtral, Gemma',\n models: ['llama-3.3-70b-versatile', 'llama-3.1-8b-instant', 'mixtral-8x7b-32768', 'gemma2-9b-it'],\n keyRequired: true,\n url: 'https://console.groq.com/keys',\n keyPrefix: 'gsk_',\n },\n together: {\n name: 'Together AI',\n category: 'tier2',\n description: 'Open-source models at scale. Llama, Qwen, DeepSeek',\n models: ['meta-llama/Llama-3.3-70B-Instruct-Turbo', 'Qwen/Qwen2.5-72B-Instruct-Turbo', 'deepseek-ai/DeepSeek-R1', 'mistralai/Mixtral-8x22B-Instruct-v0.1'],\n keyRequired: true,\n url: 'https://api.together.xyz/settings/api-keys',\n keyPrefix: '',\n },\n fireworks: {\n name: 'Fireworks AI',\n category: 'tier2',\n description: 'Fast open-source model hosting. Llama, Mixtral',\n models: ['accounts/fireworks/models/llama-v3p3-70b-instruct', 'accounts/fireworks/models/mixtral-8x22b-instruct', 'accounts/fireworks/models/qwen2p5-72b-instruct'],\n keyRequired: true,\n url: 'https://fireworks.ai/account/api-keys',\n keyPrefix: '',\n },\n\n // ── TIER 3: CLOUD PLATFORM AI (API KEY REQUIRED) ───────────────────────\n azure: {\n name: 'Azure OpenAI',\n category: 'tier3',\n description: 'Microsoft Azure-hosted GPT-4, GPT-4o',\n models: ['gpt-4o', 'gpt-4', 'gpt-4-turbo', 'gpt-35-turbo'],\n keyRequired: true,\n url: 'https://portal.azure.com/#view/Microsoft_Azure_ProjectOxford/CognitiveServicesHub',\n keyPrefix: '',\n extraConfig: ['endpoint'],\n },\n bedrock: {\n name: 'AWS Bedrock',\n category: 'tier3',\n description: 'AWS-hosted Claude, Llama, Titan, Mistral',\n models: ['anthropic.claude-sonnet-4-20250514-v1:0', 'meta.llama3-70b-instruct-v1:0', 'amazon.titan-text-premier-v1:0', 'mistral.mixtral-8x7b-instruct-v0:1'],\n keyRequired: true,\n url: 'https://console.aws.amazon.com/bedrock',\n keyPrefix: '',\n extraConfig: ['region', 'accessKeyId', 'secretAccessKey'],\n },\n vertex: {\n name: 'Google Vertex AI',\n category: 'tier3',\n description: 'Google Cloud-hosted Gemini, PaLM',\n models: ['gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-1.5-pro', 'text-bison'],\n keyRequired: true,\n url: 'https://console.cloud.google.com/vertex-ai',\n keyPrefix: '',\n extraConfig: ['projectId', 'location'],\n },\n\n // ── TIER 4: AGGREGATORS & ROUTERS (API KEY REQUIRED) ───────────────────\n openrouter: {\n name: 'OpenRouter',\n category: 'aggregator',\n description: 'Access 200+ models with one API key',\n models: ['openai/gpt-4o', 'anthropic/claude-sonnet-4-20250514', 'google/gemini-2.5-pro', 'meta-llama/llama-3.3-70b-instruct', 'deepseek/deepseek-r1'],\n keyRequired: true,\n url: 'https://openrouter.ai/keys',\n keyPrefix: 'sk-or-',\n },\n litellm: {\n name: 'LiteLLM Proxy',\n category: 'aggregator',\n description: 'Unified proxy for 100+ LLMs. Self-hosted.',\n models: ['gpt-4o', 'claude-sonnet-4-20250514', 'gemini-pro', 'command-r-plus'],\n keyRequired: true,\n url: 'https://docs.litellm.ai',\n keyPrefix: '',\n extraConfig: ['baseUrl'],\n },\n\n // ── TIER 5: OPEN-SOURCE / SPECIALIZED (API KEY REQUIRED) ───────────────\n replicate: {\n name: 'Replicate',\n category: 'specialized',\n description: 'Run open-source models via API. Llama, Stable Diffusion',\n models: ['meta/llama-3-70b-instruct', 'mistralai/mixtral-8x7b-instruct-v0.1', 'meta/llama-3-8b-instruct'],\n keyRequired: true,\n url: 'https://replicate.com/account/api-tokens',\n keyPrefix: 'r8_',\n },\n huggingface: {\n name: 'Hugging Face Inference',\n category: 'specialized',\n description: 'Run 200k+ models via Inference API',\n models: ['meta-llama/Llama-3.3-70B-Instruct', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'Qwen/Qwen2.5-72B-Instruct', 'google/gemma-2-9b-it'],\n keyRequired: true,\n url: 'https://huggingface.co/settings/tokens',\n keyPrefix: 'hf_',\n },\n ai21: {\n name: 'AI21 Labs (Jamba)',\n category: 'specialized',\n description: 'Jamba 1.5 Large, Jamba 1.5 Mini',\n models: ['jamba-1.5-large', 'jamba-1.5-mini', 'j2-ultra', 'j2-mid'],\n keyRequired: true,\n url: 'https://studio.ai21.com/account/api-key',\n keyPrefix: '',\n },\n sambanova: {\n name: 'SambaNova',\n category: 'specialized',\n description: 'Ultra-fast Llama & custom models on RDU chips',\n models: ['Meta-Llama-3.3-70B-Instruct', 'Meta-Llama-3.1-8B-Instruct', 'Meta-Llama-3.1-405B-Instruct'],\n keyRequired: true,\n url: 'https://cloud.sambanova.ai/apis',\n keyPrefix: '',\n },\n cerebras: {\n name: 'Cerebras',\n category: 'specialized',\n description: 'Fastest inference on Wafer-Scale chips',\n models: ['llama-3.3-70b', 'llama-3.1-8b'],\n keyRequired: true,\n url: 'https://cloud.cerebras.ai',\n keyPrefix: 'csk-',\n },\n lepton: {\n name: 'Lepton AI',\n category: 'specialized',\n description: 'Fast serverless AI. Llama, Mixtral hosting',\n models: ['llama3-70b', 'mixtral-8x7b', 'llama3-8b'],\n keyRequired: true,\n url: 'https://dashboard.lepton.ai',\n keyPrefix: '',\n },\n novita: {\n name: 'Novita AI',\n category: 'specialized',\n description: 'Affordable GPU cloud for LLM inference',\n models: ['meta-llama/llama-3-70b-instruct', 'mistralai/mixtral-8x7b-instruct', 'nousresearch/hermes-3-llama-3.1-70b'],\n keyRequired: true,\n url: 'https://novita.ai/dashboard/key',\n keyPrefix: '',\n },\n anyscale: {\n name: 'Anyscale Endpoints',\n category: 'specialized',\n description: 'Scalable open-source model hosting (Ray-based)',\n models: ['meta-llama/Llama-3-70b-chat-hf', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'codellama/CodeLlama-70b-Instruct-hf'],\n keyRequired: true,\n url: 'https://app.endpoints.anyscale.com',\n keyPrefix: '',\n },\n};\n\nexport async function setupWizard() {\n banner();\n section('AI Provider Setup Wizard — 25+ Providers');\n\n console.log(chalk.gray(' Configure your AI provider for intelligent DevOps.\\n'));\n\n // Group providers by category\n const categories = {\n free: { label: '🆓 Free / No API Key', providers: [] },\n tier1: { label: '⭐ Tier 1 — Major Providers', providers: [] },\n tier2: { label: '🚀 Tier 2 — Specialized', providers: [] },\n tier3: { label: '☁️ Tier 3 — Cloud Platform AI', providers: [] },\n aggregator: { label: '🔀 Aggregators & Routers', providers: [] },\n specialized: { label: '🔬 Open-Source & Specialized', providers: [] },\n };\n\n for (const [key, p] of Object.entries(PROVIDERS)) {\n const cat = p.category || 'specialized';\n if (categories[cat]) categories[cat].providers.push({ key, ...p });\n }\n\n // Build choices with category separators\n const choices = [];\n for (const [, cat] of Object.entries(categories)) {\n if (cat.providers.length === 0) continue;\n choices.push({ role: 'separator', message: chalk.bold.yellow(`\\n ─── ${cat.label} ───`) });\n for (const p of cat.providers) {\n const keyTag = p.keyRequired ? chalk.yellow(' [KEY]') : chalk.green(' [FREE]');\n choices.push({\n name: p.key,\n message: `${p.name.padEnd(28)} ${chalk.gray(p.description)}${keyTag}`,\n value: p.key,\n });\n }\n }\n\n const { provider } = await enquirer.prompt({\n type: 'select',\n name: 'provider',\n message: chalk.cyan('Choose your AI provider:'),\n choices,\n });\n\n const providerInfo = PROVIDERS[provider];\n const cm = new ConfigManager();\n await cm.init();\n\n console.log('');\n box(providerInfo.name, [\n providerInfo.description,\n `Key Required: ${providerInfo.keyRequired ? chalk.yellow('Yes') : chalk.green('No')}`,\n providerInfo.keyRequired ? `Get your key: ${chalk.cyan(providerInfo.url)}` : providerInfo.setupGuide,\n ]);\n\n // API Key input\n if (providerInfo.keyRequired) {\n console.log('');\n log(`Get your API key from: ${chalk.cyan.underline(providerInfo.url)}`, 'info');\n console.log('');\n\n const { apiKey } = await enquirer.prompt({\n type: 'password',\n name: 'apiKey',\n message: chalk.cyan(`Enter your ${providerInfo.name} API key:`),\n validate: (val) => {\n if (!val || val.trim().length < 10) return 'API key is too short';\n if (providerInfo.keyPrefix && !val.startsWith(providerInfo.keyPrefix)) {\n return `Key should start with \"${providerInfo.keyPrefix}\"`;\n }\n return true;\n },\n });\n\n await cm.setAPIKey(provider, apiKey.trim());\n log(`API key saved for ${providerInfo.name}`, 'success');\n }\n\n // Model selection\n const { model } = await enquirer.prompt({\n type: 'select',\n name: 'model',\n message: chalk.cyan('Choose your default model:'),\n choices: providerInfo.models.map((m, i) => ({\n name: m,\n message: m,\n value: m,\n })),\n });\n\n await cm.setAIProvider(provider, model);\n log(`Default AI set to ${chalk.cyan(providerInfo.name)} / ${chalk.green(model)}`, 'success');\n\n // Test connection\n console.log('');\n const { testIt } = await enquirer.prompt({\n type: 'confirm',\n name: 'testIt',\n message: chalk.cyan('Test the AI connection now?'),\n initial: true,\n });\n\n if (testIt) {\n const spinner = ora('Testing AI connection...').start();\n try {\n const ai = await AIProvider.create();\n const response = await ai.prompt('Say \"dnpm AI connected successfully!\" in one line.');\n spinner.succeed(`AI connected: ${chalk.green(response.slice(0, 100))}`);\n } catch (err) {\n spinner.fail(`Connection failed: ${err.message}`);\n log('Check your API key and try again with: dnpm setup-ai', 'warning');\n }\n }\n\n console.log('');\n log('AI setup complete! You can now use:', 'success');\n console.log(chalk.gray(`\n dnpm ai mode # Interactive AI assistant\n dnpm ai fix # Auto-fix errors\n dnpm ai ask \"question\" # Ask anything\n dnpm ai generate \"...\" # Generate code\n dnpm analyze # AI system analysis\n `));\n}\n\nexport async function quickSetKey(provider, key) {\n const providerInfo = PROVIDERS[provider];\n if (!providerInfo) {\n const available = Object.keys(PROVIDERS).join(', ');\n throw new Error(`Unknown provider: ${provider}. Available: ${available}`);\n }\n\n if (providerInfo.keyRequired && (!key || key.trim().length < 10)) {\n throw new Error('API key is too short or missing');\n }\n\n const cm = new ConfigManager();\n await cm.init();\n\n if (key) {\n await cm.setAPIKey(provider, key.trim());\n log(`API key saved for ${providerInfo.name}`, 'success');\n }\n\n return { provider, saved: true };\n}\n\nexport async function listProviders() {\n section('AI Providers — 25+ Supported');\n const cm = new ConfigManager();\n const config = await cm.getGlobalConfig();\n const currentProvider = config.ai?.provider;\n const currentModel = config.ai?.model;\n\n const categories = {\n free: '🆓 Free / No API Key',\n tier1: '⭐ Tier 1 — Major Providers',\n tier2: '🚀 Tier 2 — Specialized',\n tier3: '☁️ Cloud Platform AI',\n aggregator: '🔀 Aggregators & Routers',\n specialized: '🔬 Open-Source & Specialized',\n };\n\n const grouped = {};\n for (const [key, p] of Object.entries(PROVIDERS)) {\n const cat = p.category || 'specialized';\n if (!grouped[cat]) grouped[cat] = [];\n grouped[cat].push({ key, ...p });\n }\n\n for (const [catKey, catLabel] of Object.entries(categories)) {\n if (!grouped[catKey] || grouped[catKey].length === 0) continue;\n console.log(`\\n ${chalk.bold.yellow(catLabel)}`);\n for (const p of grouped[catKey]) {\n const isCurrent = p.key === currentProvider;\n const hasKey = config.ai?.apiKeys?.[p.key] || !p.keyRequired;\n const icon = isCurrent ? chalk.green('▶') : hasKey ? chalk.cyan('●') : chalk.gray('○');\n const status = isCurrent ? chalk.green(` (active: ${currentModel})`) : hasKey && p.keyRequired ? chalk.gray(' (key set)') : '';\n const keyTag = p.keyRequired ? '' : chalk.green(' FREE');\n\n console.log(` ${icon} ${chalk.white(p.name.padEnd(28))} ${chalk.gray(p.description)}${status}${keyTag}`);\n }\n }\n\n console.log(`\\n ${chalk.white(`Total: ${Object.keys(PROVIDERS).length} providers`)}`);\n console.log(`\\n ${chalk.gray('Setup:')} ${chalk.cyan('dnpm setup-ai')}`);\n console.log(` ${chalk.gray('Set key:')} ${chalk.cyan('dnpm config set-key <provider> <key>')}\\n`);\n}\n\nexport { PROVIDERS };\n"}, "23d2e99fd74d5de3df8721e768a03e97a2e25e1b": {"t": 1785764590.2901177, "n": 6487, "h": "3230860406bfb740", "c": "import Enquirer from 'enquirer';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { log, section, banner, box } from '../ui/logger.js';\nimport { ConfigManager } from '../config/index.js';\nimport { AIProvider } from '../ai/provider.js';\n\nconst enquirer = new Enquirer();\n\nconst PROVIDERS = {\n ollama: {\n name: 'Ollama',\n description: 'Free, local AI. No API key needed.',\n models: ['llama3', 'llama3:70b', 'codellama', 'mistral', 'mixtral', 'phi3', 'gemma', 'qwen2'],\n keyRequired: false,\n url: 'https://ollama.ai',\n setupGuide: 'Install: curl -fsSL https://ollama.ai/install.sh | sh\\nThen: ollama pull llama3',\n },\n openai: {\n name: 'OpenAI (GPT)',\n description: 'GPT-4o, GPT-4 Turbo, GPT-3.5',\n models: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-3.5-turbo', 'o1-preview', 'o1-mini'],\n keyRequired: true,\n url: 'https://platform.openai.com/api-keys',\n keyPrefix: 'sk-',\n },\n claude: {\n name: 'Claude (Anthropic)',\n description: 'Claude Opus 4, Sonnet 4, Haiku',\n models: ['claude-sonnet-4-20250514', 'claude-opus-4-20250514', 'claude-haiku-4-20250514', 'claude-3-5-sonnet-20241022'],\n keyRequired: true,\n url: 'https://console.anthropic.com/settings/keys',\n keyPrefix: 'sk-ant-',\n },\n gemini: {\n name: 'Gemini (Google)',\n description: 'Gemini Pro, Gemini Ultra',\n models: ['gemini-pro', 'gemini-1.5-pro', 'gemini-1.5-flash', 'gemini-ultra'],\n keyRequired: true,\n url: 'https://aistudio.google.com/app/apikey',\n keyPrefix: 'AI',\n },\n openrouter: {\n name: 'OpenRouter',\n description: 'Access 100+ models with one API key',\n models: ['openai/gpt-4o', 'anthropic/claude-sonnet-4-20250514', 'google/gemini-pro', 'meta-llama/llama-3-70b-instruct'],\n keyRequired: true,\n url: 'https://openrouter.ai/keys',\n keyPrefix: 'sk-or-',\n },\n};\n\nexport async function setupWizard() {\n banner();\n section('AI Provider Setup Wizard');\n\n console.log(chalk.gray(' Configure your AI provider for intelligent DevOps.\\n'));\n\n // Show provider options\n const { provider } = await enquirer.prompt({\n type: 'select',\n name: 'provider',\n message: chalk.cyan('Choose your AI provider:'),\n choices: Object.entries(PROVIDERS).map(([key, p]) => ({\n name: key,\n message: `${p.name.padEnd(22)} ${chalk.gray(p.description)}`,\n value: key,\n })),\n });\n\n const providerInfo = PROVIDERS[provider];\n const cm = new ConfigManager();\n await cm.init();\n\n console.log('');\n box(providerInfo.name, [\n providerInfo.description,\n `Key Required: ${providerInfo.keyRequired ? chalk.yellow('Yes') : chalk.green('No')}`,\n providerInfo.keyRequired ? `Get your key: ${chalk.cyan(providerInfo.url)}` : providerInfo.setupGuide,\n ]);\n\n // API Key input\n if (providerInfo.keyRequired) {\n console.log('');\n log(`Get your API key from: ${chalk.cyan.underline(providerInfo.url)}`, 'info');\n console.log('');\n\n const { apiKey } = await enquirer.prompt({\n type: 'password',\n name: 'apiKey',\n message: chalk.cyan(`Enter your ${providerInfo.name} API key:`),\n validate: (val) => {\n if (!val || val.trim().length < 10) return 'API key is too short';\n if (providerInfo.keyPrefix && !val.startsWith(providerInfo.keyPrefix)) {\n return `Key should start with \"${providerInfo.keyPrefix}\"`;\n }\n return true;\n },\n });\n\n await cm.setAPIKey(provider, apiKey.trim());\n log(`API key saved for ${providerInfo.name}`, 'success');\n }\n\n // Model selection\n const { model } = await enquirer.prompt({\n type: 'select',\n name: 'model',\n message: chalk.cyan('Choose your default model:'),\n choices: providerInfo.models.map((m, i) => ({\n name: m,\n message: m,\n value: m,\n })),\n });\n\n await cm.setAIProvider(provider, model);\n log(`Default AI set to ${chalk.cyan(providerInfo.name)} / ${chalk.green(model)}`, 'success');\n\n // Test connection\n console.log('');\n const { testIt } = await enquirer.prompt({\n type: 'confirm',\n name: 'testIt',\n message: chalk.cyan('Test the AI connection now?'),\n initial: true,\n });\n\n if (testIt) {\n const spinner = ora('Testing AI connection...').start();\n try {\n const ai = await AIProvider.create();\n const response = await ai.prompt('Say \"dnpm AI connected successfully!\" in one line.');\n spinner.succeed(`AI connected: ${chalk.green(response.slice(0, 100))}`);\n } catch (err) {\n spinner.fail(`Connection failed: ${err.message}`);\n log('Check your API key and try again with: dnpm setup-ai', 'warning');\n }\n }\n\n console.log('');\n log('AI setup complete! You can now use:', 'success');\n console.log(chalk.gray(`\n dnpm ai mode # Interactive AI assistant\n dnpm ai fix # Auto-fix errors\n dnpm ai ask \"question\" # Ask anything\n dnpm ai generate \"...\" # Generate code\n dnpm analyze # AI system analysis\n `));\n}\n\nexport async function quickSetKey(provider, key) {\n const providerInfo = PROVIDERS[provider];\n if (!providerInfo) {\n const available = Object.keys(PROVIDERS).join(', ');\n throw new Error(`Unknown provider: ${provider}. Available: ${available}`);\n }\n\n if (providerInfo.keyRequired && (!key || key.trim().length < 10)) {\n throw new Error('API key is too short or missing');\n }\n\n const cm = new ConfigManager();\n await cm.init();\n\n if (key) {\n await cm.setAPIKey(provider, key.trim());\n log(`API key saved for ${providerInfo.name}`, 'success');\n }\n\n return { provider, saved: true };\n}\n\nexport async function listProviders() {\n section('AI Providers');\n const cm = new ConfigManager();\n const config = await cm.getGlobalConfig();\n const currentProvider = config.ai?.provider;\n const currentModel = config.ai?.model;\n\n for (const [key, p] of Object.entries(PROVIDERS)) {\n const isCurrent = key === currentProvider;\n const hasKey = config.ai?.apiKeys?.[key] || !p.keyRequired;\n const icon = isCurrent ? chalk.green('▶') : hasKey ? chalk.cyan('●') : chalk.gray('○');\n const status = isCurrent ? chalk.green(` (active: ${currentModel})`) : hasKey && p.keyRequired ? chalk.gray(' (key set)') : '';\n\n console.log(` ${icon} ${chalk.white(p.name.padEnd(22))} ${chalk.gray(p.description)}${status}`);\n }\n\n console.log(`\\n ${chalk.gray('Setup:')} ${chalk.cyan('dnpm setup-ai')}`);\n console.log(` ${chalk.gray('Set key:')} ${chalk.cyan('dnpm config set-key <provider> <key>')}\\n`);\n}\n\nexport { PROVIDERS };\n"}}}} |