diff --git a/.changeset/groq-kimi-k2-support.md b/.changeset/groq-kimi-k2-support.md new file mode 100644 index 00000000..663a0f5f --- /dev/null +++ b/.changeset/groq-kimi-k2-support.md @@ -0,0 +1,10 @@ +--- +"task-master-ai": minor +--- + +Complete Groq provider integration and add MoonshotAI Kimi K2 model support + +- Fixed Groq provider registration +- Added Groq API key validation +- Added GROQ_API_KEY to .env.example +- Added moonshotai/kimi-k2-instruct model with $1/$3 per 1M token pricing and 16k max output \ No newline at end of file diff --git a/assets/env.example b/assets/env.example index 2c5babf0..4ebc91e1 100644 --- a/assets/env.example +++ b/assets/env.example @@ -5,6 +5,7 @@ OPENAI_API_KEY="your_openai_api_key_here" # Optional, for OpenAI/Ope GOOGLE_API_KEY="your_google_api_key_here" # Optional, for Google Gemini models. MISTRAL_API_KEY="your_mistral_key_here" # Optional, for Mistral AI models. XAI_API_KEY="YOUR_XAI_KEY_HERE" # Optional, for xAI AI models. +GROQ_API_KEY="your_groq_api_key_here" # Optional, for Groq models. Format: gsk_... AZURE_OPENAI_API_KEY="your_azure_key_here" # Optional, for Azure OpenAI models (requires endpoint in .taskmaster/config.json). OLLAMA_API_KEY="your_ollama_api_key_here" # Optional: For remote Ollama servers that require authentication. GITHUB_API_KEY="your_github_api_key_here" # Optional: For GitHub import/export features. Format: ghp_... or github_pat_... \ No newline at end of file diff --git a/scripts/modules/ai-services-unified.js b/scripts/modules/ai-services-unified.js index aefae8dc..0df4bd1a 100644 --- a/scripts/modules/ai-services-unified.js +++ b/scripts/modules/ai-services-unified.js @@ -8,47 +8,48 @@ // --- Core Dependencies --- import { - getMainProvider, - getMainModelId, - getResearchProvider, - getResearchModelId, - getFallbackProvider, + MODEL_MAP, + getAzureBaseURL, + getBaseUrlForRole, + getBedrockBaseURL, + getDebugFlag, getFallbackModelId, + getFallbackProvider, + getMainModelId, + getMainProvider, + getOllamaBaseURL, getParametersForRole, + getResearchModelId, + getResearchProvider, getResponseLanguage, getUserId, - MODEL_MAP, - getDebugFlag, - getBaseUrlForRole, - isApiKeySet, - getOllamaBaseURL, - getAzureBaseURL, - getBedrockBaseURL, - getVertexProjectId, getVertexLocation, + getVertexProjectId, + isApiKeySet, providersWithoutApiKeys } from './config-manager.js'; import { - log, findProjectRoot, - resolveEnvVariable, - getCurrentTag + getCurrentTag, + log, + resolveEnvVariable } from './utils.js'; // Import provider classes import { AnthropicAIProvider, - PerplexityAIProvider, - GoogleAIProvider, - OpenAIProvider, - XAIProvider, - OpenRouterAIProvider, - OllamaAIProvider, - BedrockAIProvider, AzureProvider, - VertexAIProvider, + BedrockAIProvider, ClaudeCodeProvider, - GeminiCliProvider + GeminiCliProvider, + GoogleAIProvider, + GroqProvider, + OllamaAIProvider, + OpenAIProvider, + OpenRouterAIProvider, + PerplexityAIProvider, + VertexAIProvider, + XAIProvider } from '../../src/ai-providers/index.js'; // Import the provider registry @@ -61,6 +62,7 @@ const PROVIDERS = { google: new GoogleAIProvider(), openai: new OpenAIProvider(), xai: new XAIProvider(), + groq: new GroqProvider(), openrouter: new OpenRouterAIProvider(), ollama: new OllamaAIProvider(), bedrock: new BedrockAIProvider(), diff --git a/scripts/modules/config-manager.js b/scripts/modules/config-manager.js index e688897b..ed9a3ebc 100644 --- a/scripts/modules/config-manager.js +++ b/scripts/modules/config-manager.js @@ -1,21 +1,21 @@ import fs from 'fs'; import path from 'path'; +import { fileURLToPath } from 'url'; import chalk from 'chalk'; import { z } from 'zod'; -import { fileURLToPath } from 'url'; -import { log, findProjectRoot, resolveEnvVariable, isEmpty } from './utils.js'; +import { AI_COMMAND_NAMES } from '../../src/constants/commands.js'; import { LEGACY_CONFIG_FILE, TASKMASTER_DIR } from '../../src/constants/paths.js'; -import { findConfigPath } from '../../src/utils/path-utils.js'; import { - VALIDATED_PROVIDERS, + ALL_PROVIDERS, CUSTOM_PROVIDERS, CUSTOM_PROVIDERS_ARRAY, - ALL_PROVIDERS + VALIDATED_PROVIDERS } from '../../src/constants/providers.js'; -import { AI_COMMAND_NAMES } from '../../src/constants/commands.js'; +import { findConfigPath } from '../../src/utils/path-utils.js'; +import { findProjectRoot, isEmpty, log, resolveEnvVariable } from './utils.js'; // Calculate __dirname in ESM const __filename = fileURLToPath(import.meta.url); @@ -641,6 +641,7 @@ function isApiKeySet(providerName, session = null, projectRoot = null) { azure: 'AZURE_OPENAI_API_KEY', openrouter: 'OPENROUTER_API_KEY', xai: 'XAI_API_KEY', + groq: 'GROQ_API_KEY', vertex: 'GOOGLE_API_KEY', // Vertex uses the same key as Google 'claude-code': 'CLAUDE_CODE_API_KEY', // Not actually used, but included for consistency bedrock: 'AWS_ACCESS_KEY_ID' // Bedrock uses AWS credentials @@ -726,6 +727,10 @@ function getMcpApiKeyStatus(providerName, projectRoot = null) { apiKeyToCheck = mcpEnv.XAI_API_KEY; placeholderValue = 'YOUR_XAI_API_KEY_HERE'; break; + case 'groq': + apiKeyToCheck = mcpEnv.GROQ_API_KEY; + placeholderValue = 'YOUR_GROQ_API_KEY_HERE'; + break; case 'ollama': return true; // No key needed case 'claude-code': diff --git a/scripts/modules/supported-models.json b/scripts/modules/supported-models.json index 0960b2b9..a321e6ac 100644 --- a/scripts/modules/supported-models.json +++ b/scripts/modules/supported-models.json @@ -295,6 +295,16 @@ } ], "groq": [ + { + "id": "moonshotai/kimi-k2-instruct", + "swe_score": 0.66, + "cost_per_1m_tokens": { + "input": 1.0, + "output": 3.0 + }, + "allowed_roles": ["main", "fallback"], + "max_tokens": 16384 + }, { "id": "llama-3.3-70b-versatile", "swe_score": 0.55, diff --git a/src/ai-providers/groq.js b/src/ai-providers/groq.js index f8eda87d..8acbd6df 100644 --- a/src/ai-providers/groq.js +++ b/src/ai-providers/groq.js @@ -14,6 +14,14 @@ export class GroqProvider extends BaseAIProvider { this.name = 'Groq'; } + /** + * Returns the environment variable name required for this provider's API key. + * @returns {string} The environment variable name for the Groq API key + */ + getRequiredApiKeyName() { + return 'GROQ_API_KEY'; + } + /** * Creates and returns a Groq client instance. * @param {object} params - Parameters for client initialization diff --git a/tests/unit/ai-services-unified.test.js b/tests/unit/ai-services-unified.test.js index 3759333a..bbbe65c4 100644 --- a/tests/unit/ai-services-unified.test.js +++ b/tests/unit/ai-services-unified.test.js @@ -177,6 +177,13 @@ jest.unstable_mockModule('../../src/ai-providers/index.js', () => ({ getRequiredApiKeyName: jest.fn(() => 'XAI_API_KEY'), isRequiredApiKey: jest.fn(() => true) })), + GroqProvider: jest.fn(() => ({ + generateText: jest.fn(), + streamText: jest.fn(), + generateObject: jest.fn(), + getRequiredApiKeyName: jest.fn(() => 'GROQ_API_KEY'), + isRequiredApiKey: jest.fn(() => true) + })), OpenRouterAIProvider: jest.fn(() => ({ generateText: jest.fn(), streamText: jest.fn(),