diff --git a/PROVIDERS.md b/PROVIDERS.md index b2af8d8..2eab4ac 100644 --- a/PROVIDERS.md +++ b/PROVIDERS.md @@ -6,24 +6,24 @@ This document provides detailed information about all supported AI providers in vibecheck supports 10 AI providers, each optimized for cost-efficiency and quality: -1. **OpenAI** - GPT-4o-mini -2. **Google Gemini** - gemini-2.5-flash -3. **Anthropic** - Claude 3.5 Haiku -4. **Groq** - Llama 3.3 70B Versatile -5. **xAI** - Grok Beta -6. **Moonshot AI Kimi** - moonshot-v1-auto -7. **Alibaba Qwen** - qwen-turbo -8. **DeepSeek** - deepseek-chat -9. **Perplexity** - sonar +1. **OpenAI** - gpt-5-mini +2. **Google Gemini** - gemini-3-flash-preview +3. **Anthropic** - claude-haiku-4-5-20251001 +4. **Groq** - openai/gpt-oss-20b +5. **xAI** - grok-4-1-fast-reasoning +6. **Moonshot AI Kimi** - kimi-k2.5 +7. **Alibaba Qwen** - qwen3-coder-plus +8. **DeepSeek** - deepseek-chat (V3.2 alias) +9. **Perplexity** - sonar-pro 10. **Ollama** - gpt-oss:20b (local) --- ## Provider Setup -### 1. OpenAI (GPT-4o-mini) +### 1. OpenAI (gpt-5-mini) -**Model**: `gpt-4o-mini` +**Model**: `gpt-5-mini` **Cost**: $0.15/1M input tokens, $0.60/1M output tokens **Speed**: Fast **API Key**: Get from [OpenAI Platform](https://platform.openai.com/api-keys) @@ -35,9 +35,9 @@ vibecheck commit --provider openai --- -### 2. Google Gemini (gemini-2.5-flash) +### 2. Google Gemini (gemini-3-flash-preview) -**Model**: `gemini-2.5-flash` +**Model**: `gemini-3-flash-preview` **Cost**: $0.075/1M input tokens, $0.30/1M output tokens **Speed**: Fast **API Key**: Get from [Google AI Studio](https://aistudio.google.com/app/apikey) @@ -54,9 +54,9 @@ vibecheck commit --provider gemini --- -### 3. Anthropic (Claude 3.5 Haiku) +### 3. Anthropic (claude-haiku-4-5-20251001) -**Model**: `claude-3.5-haiku-20241022` +**Model**: `claude-haiku-4-5-20251001` **Cost**: $0.80/1M input tokens, $4.00/1M output tokens **Speed**: Fast **API Key**: Get from [Anthropic Console](https://console.anthropic.com/settings/keys) @@ -73,9 +73,9 @@ vibecheck commit --provider anthropic --- -### 4. Groq (Llama 3.3 70B Versatile) +### 4. Groq (openai/gpt-oss-20b) -**Model**: `llama-3.3-70b-versatile` +**Model**: `openai/gpt-oss-20b` **Cost**: Free tier available **Speed**: Ultra-fast (fastest inference) **API Key**: Get from [Groq Console](https://console.groq.com/keys) @@ -93,9 +93,9 @@ vibecheck commit --provider groq --- -### 5. xAI (Grok Beta) +### 5. xAI (grok-4-1-fast-reasoning) -**Model**: `grok-beta` +**Model**: `grok-4-1-fast-reasoning` **Cost**: Competitive pricing **Speed**: Fast **API Key**: Get from [xAI Console](https://console.x.ai/) @@ -112,9 +112,9 @@ vibecheck commit --provider grok --- -### 6. Moonshot AI Kimi (moonshot-v1-auto) +### 6. Moonshot AI Kimi (kimi-k2.5) -**Model**: `moonshot-v1-auto` +**Model**: `kimi-k2.5` **Cost**: Very low (competitive with Gemini) **Speed**: Ultra-fast **API Key**: Get from [Moonshot AI Platform](https://platform.moonshot.cn/) @@ -133,9 +133,9 @@ vibecheck commit --provider kimi --- -### 7. Alibaba Qwen (qwen-turbo) +### 7. Alibaba Qwen (qwen3-coder-plus) -**Model**: `qwen-turbo` +**Model**: `qwen3-coder-plus` **Cost**: Very low (extremely competitive) **Speed**: Ultra-fast **API Key**: Get from [Alibaba Cloud DashScope](https://dashscope.aliyun.com/) @@ -154,9 +154,9 @@ vibecheck commit --provider qwen --- -### 8. DeepSeek (deepseek-chat) +### 8. DeepSeek (deepseek-chat, V3.2 alias) -**Model**: `deepseek-chat` +**Model**: `deepseek-chat` (DeepSeek-V3.2 alias) **Cost**: Extremely low ($0.14/1M input, $0.28/1M output) **Speed**: Ultra-fast **API Key**: Get from [DeepSeek Platform](https://platform.deepseek.com/) @@ -175,9 +175,9 @@ vibecheck commit --provider deepseek --- -### 9. Perplexity (sonar) +### 9. Perplexity (sonar-pro) -**Model**: `sonar` +**Model**: `sonar-pro` **Cost**: ~$0.60/1M input tokens, ~$0.60/1M output tokens **Speed**: Fast **API Key**: Get from [Perplexity Dashboard](https://www.perplexity.ai/settings/api) diff --git a/README.md b/README.md index 01e7308..fca8275 100644 --- a/README.md +++ b/README.md @@ -264,15 +264,15 @@ export OLLAMA_HOST="http://localhost:11434" ```bash vibecheck commit -vibecheck commit --provider openai # GPT-4o-mini -vibecheck commit --provider gemini # Gemini 2.5 Flash -vibecheck commit --provider anthropic # Claude 3.5 Haiku -vibecheck commit --provider groq # Llama 3.3 70B -vibecheck commit --provider grok # Grok Beta -vibecheck commit --provider kimi # Kimi K2 (Moonshot-v1-auto) -vibecheck commit --provider qwen # Qwen Turbo -vibecheck commit --provider deepseek # DeepSeek Chat -vibecheck commit --provider perplexity # Perplexity Sonar (sonar) +vibecheck commit --provider openai # gpt-5-mini +vibecheck commit --provider gemini # gemini-3-flash-preview +vibecheck commit --provider anthropic # claude-haiku-4-5-20251001 +vibecheck commit --provider groq # openai/gpt-oss-20b +vibecheck commit --provider grok # grok-4-1-fast-reasoning +vibecheck commit --provider kimi # kimi-k2.5 +vibecheck commit --provider qwen # qwen3-coder-plus +vibecheck commit --provider deepseek # deepseek-chat (DeepSeek-V3.2 alias) +vibecheck commit --provider perplexity # sonar-pro vibecheck commit --provider ollama # gpt-oss:20b (local) vibecheck commit --prompt "make sure to use 02 emoji's in my commit message" diff --git a/internal/llm/anthropic/client.go b/internal/llm/anthropic/client.go index 29f8b7a..b3cf447 100644 --- a/internal/llm/anthropic/client.go +++ b/internal/llm/anthropic/client.go @@ -27,38 +27,13 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio option.WithAPIKey(key), ) - systemPrompt := `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE - -below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message -The git diff is in the second next message.` + systemPrompt := llm.GetSystemPrompt("anthropic") userMessage := fmt.Sprintf("User added extra context is: %s\n\nGit diff:\n%s", additionalContext, diff) - // Using Claude 3.5 Haiku for cost-efficiency - most affordable Claude model + // Using Anthropic's current Haiku alias for low-cost commit-message generation. message, err := client.Messages.New(ctx, anthropicsdk.MessageNewParams{ - Model: anthropicsdk.ModelClaude3_5Haiku20241022, + Model: anthropicsdk.Model("claude-haiku-4-5-20251001"), MaxTokens: 1024, Messages: []anthropicsdk.MessageParam{ anthropicsdk.NewUserMessage(anthropicsdk.NewTextBlock(userMessage)), diff --git a/internal/llm/anthropic/client_test.go b/internal/llm/anthropic/client_test.go index e7fbf68..b5b1248 100644 --- a/internal/llm/anthropic/client_test.go +++ b/internal/llm/anthropic/client_test.go @@ -30,13 +30,13 @@ func TestAPIKeyValidation(t *testing.T) { } // TestModelSelection verifies the correct model is used -// According to Anthropic docs: claude-3-5-haiku-20241022 should be used +// According to Anthropic docs: claude-haiku-4-5-20251001 should be used func TestModelSelection(t *testing.T) { // Verify the model constant matches Anthropic's documented model identifier - // The code uses: anthropicsdk.ModelClaude3_5Haiku20241022 - expectedModel := "claude-3-5-haiku-20241022" - if expectedModel != "claude-3-5-haiku-20241022" { - t.Errorf("Model should be claude-3-5-haiku-20241022, got %s", expectedModel) + // The code uses: anthropicsdk.string model ID claude-haiku-4-5-20251001 + expectedModel := "claude-haiku-4-5-20251001" + if expectedModel != "claude-haiku-4-5-20251001" { + t.Errorf("Model should be claude-haiku-4-5-20251001, got %s", expectedModel) } } @@ -53,7 +53,7 @@ func TestRequestStructure(t *testing.T) { // - Messages: []anthropicsdk.MessageParam with NewUserMessage(NewTextBlock(...)) // - System: []anthropicsdk.TextBlockParam // - MaxTokens: 1024 - // - Model: ModelClaude3_5Haiku20241022 + // - Model: string model ID claude-haiku-4-5-20251001 } // TestResponseHandling verifies response parsing matches Anthropic API spec diff --git a/internal/llm/deepseek/client.go b/internal/llm/deepseek/client.go index e9c4924..d413111 100644 --- a/internal/llm/deepseek/client.go +++ b/internal/llm/deepseek/client.go @@ -41,34 +41,10 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio return "", fmt.Errorf("DEEPSEEK_API_KEY environment variable not set") } - systemPrompt := `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE - -below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message -The git diff is in the second next message.` + systemPrompt := llm.GetSystemPrompt("deepseek") reqBody := chatRequest{ + // DeepSeek v3.2 is exposed under the "deepseek-chat" model ID in the chat API. Model: "deepseek-chat", Messages: []message{ {Role: "system", Content: systemPrompt}, diff --git a/internal/llm/deepseek/client_test.go b/internal/llm/deepseek/client_test.go index 914a476..f8a4f47 100644 --- a/internal/llm/deepseek/client_test.go +++ b/internal/llm/deepseek/client_test.go @@ -39,7 +39,7 @@ func TestEndpointURL(t *testing.T) { // According to DeepSeek docs: OpenAI-compatible format with model and messages func TestRequestStructure(t *testing.T) { // Verify the implementation uses: - // 1. Model: "deepseek-chat" (as per DeepSeek docs) + // 1. Model: "deepseek-chat" (DeepSeek v3.2 alias in the chat API) // 2. Messages array with role and content // 3. System message with role "system" // 4. User messages with role "user" diff --git a/internal/llm/gemini/client.go b/internal/llm/gemini/client.go index b01a699..131c5f4 100644 --- a/internal/llm/gemini/client.go +++ b/internal/llm/gemini/client.go @@ -29,8 +29,8 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio } defer client.Close() - // Using gemini-2.5-flash for best performance and cost-efficiency - model := client.GenerativeModel("gemini-2.5-flash") + // Using gemini-3-flash-preview for best performance and cost-efficiency + model := client.GenerativeModel("gemini-3-flash-preview") // Configure model parameters for better responses model.SetTemperature(0.7) @@ -61,10 +61,7 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio // Gemini works better with system instructions set on the model model.SystemInstruction = &genai.Content{ Parts: []genai.Part{ - genai.Text(`You are a commit message generator. Analyze the git diff and generate a conventional commit message. -Format: (): -Types: feat, fix, chore, docs, style, refactor, test, perf -Keep it concise and professional. Add 2-4 bullet points for details.`), + genai.Text(llm.GetSystemPrompt("gemini")), }, } diff --git a/internal/llm/gemini/client_test.go b/internal/llm/gemini/client_test.go index 332a4a8..59ef5f4 100644 --- a/internal/llm/gemini/client_test.go +++ b/internal/llm/gemini/client_test.go @@ -55,11 +55,11 @@ func containsHelper(s, substr string) bool { } // TestModelSelection verifies the correct model is used -// According to Gemini docs: gemini-2.5-flash should be used +// According to Gemini docs: gemini-3-flash-preview should be used func TestModelSelection(t *testing.T) { - expectedModel := "gemini-2.5-flash" - if expectedModel != "gemini-2.5-flash" { - t.Errorf("Model should be gemini-2.5-flash, got %s", expectedModel) + expectedModel := "gemini-3-flash-preview" + if expectedModel != "gemini-3-flash-preview" { + t.Errorf("Model should be gemini-3-flash-preview, got %s", expectedModel) } } diff --git a/internal/llm/grok/client.go b/internal/llm/grok/client.go index 8fa3105..49f2224 100644 --- a/internal/llm/grok/client.go +++ b/internal/llm/grok/client.go @@ -29,41 +29,15 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio option.WithBaseURL("https://api.x.ai/v1"), ) - // Using grok-beta model + // Using grok-4-1-fast-reasoning model chatCompletion, err := client.Chat.Completions.New(ctx, openaisdk.ChatCompletionNewParams{ Messages: []openaisdk.ChatCompletionMessageParamUnion{ - openaisdk.SystemMessage( - `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE - -below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message -The git diff is in the second next message.`), + openaisdk.SystemMessage(llm.GetSystemPrompt("grok")), openaisdk.UserMessage(fmt.Sprintf("User added extra context is: %s", additionalContext)), openaisdk.UserMessage(diff), }, - Model: "grok-beta", + Model: "grok-4-1-fast-reasoning", }) if err != nil { return "", fmt.Errorf("error while prompting to Grok: %w", err) diff --git a/internal/llm/grok/client_test.go b/internal/llm/grok/client_test.go index 7da298e..aa5e1f5 100644 --- a/internal/llm/grok/client_test.go +++ b/internal/llm/grok/client_test.go @@ -36,11 +36,11 @@ func TestBaseURL(t *testing.T) { } // TestModelSelection verifies the correct model is used -// According to xAI docs: grok-beta is the model name +// According to xAI docs: grok-4-1-fast-reasoning is the model name func TestModelSelection(t *testing.T) { - expectedModel := "grok-beta" - if expectedModel != "grok-beta" { - t.Errorf("Model should be grok-beta, got %s", expectedModel) + expectedModel := "grok-4-1-fast-reasoning" + if expectedModel != "grok-4-1-fast-reasoning" { + t.Errorf("Model should be grok-4-1-fast-reasoning, got %s", expectedModel) } } diff --git a/internal/llm/groq/client.go b/internal/llm/groq/client.go index b643a84..5e1b613 100644 --- a/internal/llm/groq/client.go +++ b/internal/llm/groq/client.go @@ -29,41 +29,15 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio option.WithBaseURL("https://api.groq.com/openai/v1"), ) - // Using llama-3.3-70b-versatile for excellent performance and speed + // Using openai/gpt-oss-20b for excellent performance and speed chatCompletion, err := client.Chat.Completions.New(ctx, openaisdk.ChatCompletionNewParams{ Messages: []openaisdk.ChatCompletionMessageParamUnion{ - openaisdk.SystemMessage( - `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE - -below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message -The git diff is in the second next message.`), + openaisdk.SystemMessage(llm.GetSystemPrompt("groq")), openaisdk.UserMessage(fmt.Sprintf("User added extra context is: %s", additionalContext)), openaisdk.UserMessage(diff), }, - Model: "llama-3.3-70b-versatile", + Model: "openai/gpt-oss-20b", }) if err != nil { return "", fmt.Errorf("error while prompting to Groq: %w", err) diff --git a/internal/llm/groq/client_test.go b/internal/llm/groq/client_test.go index 5200ef0..f544da1 100644 --- a/internal/llm/groq/client_test.go +++ b/internal/llm/groq/client_test.go @@ -36,11 +36,11 @@ func TestBaseURL(t *testing.T) { } // TestModelSelection verifies the correct model is used -// According to Groq docs: llama-3.3-70b-versatile is available +// According to Groq docs: openai/gpt-oss-20b is available func TestModelSelection(t *testing.T) { - expectedModel := "llama-3.3-70b-versatile" - if expectedModel != "llama-3.3-70b-versatile" { - t.Errorf("Model should be llama-3.3-70b-versatile, got %s", expectedModel) + expectedModel := "openai/gpt-oss-20b" + if expectedModel != "openai/gpt-oss-20b" { + t.Errorf("Model should be openai/gpt-oss-20b, got %s", expectedModel) } } diff --git a/internal/llm/kimi/client.go b/internal/llm/kimi/client.go index 2dd7610..ba3c227 100644 --- a/internal/llm/kimi/client.go +++ b/internal/llm/kimi/client.go @@ -41,35 +41,10 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio return "", fmt.Errorf("MOONSHOT_API_KEY environment variable not set") } - systemPrompt := `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE - -below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message -The git diff is in the second next message.` + systemPrompt := llm.GetSystemPrompt("kimi") reqBody := chatRequest{ - Model: "moonshot-v1-auto", + Model: "kimi-k2.5", Messages: []message{ {Role: "system", Content: systemPrompt}, {Role: "user", Content: fmt.Sprintf("User added extra context is: %s", additionalContext)}, diff --git a/internal/llm/kimi/client_test.go b/internal/llm/kimi/client_test.go index e452fe8..fe612ea 100644 --- a/internal/llm/kimi/client_test.go +++ b/internal/llm/kimi/client_test.go @@ -36,11 +36,11 @@ func TestEndpointURL(t *testing.T) { } // TestModelSelection verifies the correct model is used -// According to Moonshot docs: moonshot-v1-auto is available +// According to Moonshot docs: kimi-k2.5 is available func TestModelSelection(t *testing.T) { - expectedModel := "moonshot-v1-auto" - if expectedModel != "moonshot-v1-auto" { - t.Errorf("Model should be moonshot-v1-auto, got %s", expectedModel) + expectedModel := "kimi-k2.5" + if expectedModel != "kimi-k2.5" { + t.Errorf("Model should be kimi-k2.5, got %s", expectedModel) } } @@ -48,7 +48,7 @@ func TestModelSelection(t *testing.T) { // According to Moonshot docs: OpenAI-compatible format with model and messages func TestRequestStructure(t *testing.T) { // Verify the implementation uses: - // 1. Model: "moonshot-v1-auto" + // 1. Model: "kimi-k2.5" // 2. Messages array with role and content // 3. System message with role "system" // 4. User messages with role "user" diff --git a/internal/llm/ollama/client.go b/internal/llm/ollama/client.go index 8b3102d..82f3241 100644 --- a/internal/llm/ollama/client.go +++ b/internal/llm/ollama/client.go @@ -44,83 +44,7 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio } url := fmt.Sprintf("%s/api/generate", baseURL) - systemPrompt := `You are an advanced software engineer and commit message architect specializing in semantic versioning and the Conventional Commits specification. -Your role is to function as an autonomous Git Commit Message Generator that produces highly precise, semantically accurate, and professionally concise commit messages for production-grade software repositories. - ---- - -### Core Directives -1. Focus strictly on functional and semantic intent. - - Consider only changes that alter code logic, structure, behavior, or data flow. - - Ignore formatting-only edits such as whitespace, indentation, import reordering, or comment rewording. - - If all detected changes are non-functional, output exactly: - chore: non-functional formatting or comment update - -2. Never infer intent beyond observable code changes. - - Be more accurate on the changes and dont just tell their were spelling updates but go more specific - - Derive meaning only from what is explicitly shown in the diff. - - When intent is unclear, describe the visible change in neutral, technical terms. - -3. Maintain concise, deterministic phrasing. - - Use the imperative mood (for example, add, fix, refactor, update). - - Avoid passive voice, filler phrases, or redundant words. - - Output must be minimal, direct, and precise. - -4. Enforce structural and stylistic consistency. - - you're not allowed to use backtick in commit message - - Follow the Conventional Commit format exactly. - - Never include additional commentary, explanations, or markdown. - - Do not use emojis, narrative tone, or conversational phrasing. - - never forget to add atleast 3 descriptions for any commit message which should start with a - symbol followed by a space - - Avoid speculative language such as possibly, likely, or should. - ---- - -### Output Format -(): - - - - - - - - - -**Formatting Rules** -- must be one of: feat, fix, refactor, chore, docs, style, test, perf. -- should reference the primary module, function, or file affected (omit if not inferable). -- The summary must: - - Use an imperative verb. - - Stay under 12 words. - - Reflect functional purpose, not internal commentary or aesthetic change. -- Include up to four optional bullet points detailing relevant technical updates. -- Omit bullets when unnecessary. -- Never repeat the main summary in bullets. - ---- - -### Behavioral Logic -- If a diff modifies only comments or spacing, return the fallback commit. -- If changes apply solely to test files, use test: as the type. -- For build or dependency updates, use chore:. -- When mixed functional and non-functional edits occur, focus solely on functional impact. -- If multiple scopes exist, infer the dominant one from filenames or structure. -- If no clear functional change exists, prefer a neutral phrasing like "update logic flow" or "adjust configuration". - ---- - -### Examples - -fix(parser): handle nil pointer during JSON decoding -added nil guard before unmarshalling -prevented runtime panic on malformed input - -refactor(auth): streamline token refresh logic -removed redundant verification checks -consolidated refresh handler for clarity - -chore: non-functional formatting or comment update` + systemPrompt := llm.GetSystemPrompt("ollama") prompt := fmt.Sprintf("%s\n\nUser added extra context is: %s\n\nGit diff:\n%s", systemPrompt, additionalContext, diff) diff --git a/internal/llm/openai/client.go b/internal/llm/openai/client.go index e41bcc1..6767ca4 100644 --- a/internal/llm/openai/client.go +++ b/internal/llm/openai/client.go @@ -27,38 +27,12 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio ) chatCompletion, err := client.Chat.Completions.New(ctx, openaisdk.ChatCompletionNewParams{ Messages: []openaisdk.ChatCompletionMessageParamUnion{ - openaisdk.SystemMessage( - `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIAT FROM YOUR ROLE - -below is some user added context, but dont deviate from the actuall work unless if the the user added extra context in the next message -The git diff is in the second next message.`), + openaisdk.SystemMessage(llm.GetSystemPrompt("openai")), openaisdk.UserMessage(fmt.Sprintf("User added extra context is: %s", additionalContext)), openaisdk.UserMessage(diff), }, - Model: openaisdk.ChatModelGPT4oMini, + Model: openaisdk.ChatModel("gpt-5-mini"), }) if err != nil { return fmt.Sprintf("error while prompting to open-ai at: %v", err), err diff --git a/internal/llm/openai/client_test.go b/internal/llm/openai/client_test.go index 49ce941..56828d1 100644 --- a/internal/llm/openai/client_test.go +++ b/internal/llm/openai/client_test.go @@ -54,14 +54,14 @@ func containsHelper(s, substr string) bool { } // TestModelSelection verifies the correct model is used -// According to OpenAI docs: gpt-4o-mini should be used (ChatModelGPT4oMini) +// According to OpenAI docs: gpt-5-mini should be used func TestModelSelection(t *testing.T) { // Verify the model constant is used correctly in the implementation - // The code uses: openaisdk.ChatModelGPT4oMini + // The code uses: openaisdk.ChatModel("gpt-5-mini") // This matches OpenAI's documented model identifier - expectedModel := "gpt-4o-mini" - if expectedModel != "gpt-4o-mini" { - t.Errorf("Model should be gpt-4o-mini, got %s", expectedModel) + expectedModel := "gpt-5-mini" + if expectedModel != "gpt-5-mini" { + t.Errorf("Model should be gpt-5-mini, got %s", expectedModel) } } @@ -76,7 +76,7 @@ func TestRequestStructure(t *testing.T) { // The code structure matches OpenAI's documented format: // - SystemMessage for system prompt // - UserMessage for user content - // - Model: ChatModelGPT4oMini + // - Model: gpt-5-mini // This test verifies the structure is correct without making API calls // The actual implementation in client.go follows OpenAI's documented structure diff --git a/internal/llm/perplexity/client.go b/internal/llm/perplexity/client.go index 0b6f00d..1c1d437 100644 --- a/internal/llm/perplexity/client.go +++ b/internal/llm/perplexity/client.go @@ -43,32 +43,7 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio return "", fmt.Errorf("PERPLEXITY_API_KEY environment variable not set") } - systemPrompt := `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE - -below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message -The git diff is in the second next message.` + systemPrompt := llm.GetSystemPrompt("perplexity") userPrompt := fmt.Sprintf( "Additional context from user:\n%s\n\nGit diff:\n%s", @@ -77,7 +52,7 @@ The git diff is in the second next message.` ) reqBody := chatRequest{ - Model: "sonar", + Model: "sonar-pro", Messages: []message{ {Role: "system", Content: systemPrompt}, {Role: "user", Content: userPrompt}, diff --git a/internal/llm/perplexity/client_test.go b/internal/llm/perplexity/client_test.go index d0206a6..6734026 100644 --- a/internal/llm/perplexity/client_test.go +++ b/internal/llm/perplexity/client_test.go @@ -60,11 +60,11 @@ func TestEndpointURL(t *testing.T) { } // TestModelSelection verifies the correct model is used -// According to Perplexity docs: sonar is the model name +// According to Perplexity docs: sonar-pro is the model name func TestModelSelection(t *testing.T) { - expectedModel := "sonar" - if expectedModel != "sonar" { - t.Errorf("Model should be sonar, got %s", expectedModel) + expectedModel := "sonar-pro" + if expectedModel != "sonar-pro" { + t.Errorf("Model should be sonar-pro, got %s", expectedModel) } } diff --git a/internal/llm/provider.go b/internal/llm/provider.go index e241a86..c6035ca 100644 --- a/internal/llm/provider.go +++ b/internal/llm/provider.go @@ -39,3 +39,134 @@ func GetProvider(name string) (Provider, error) { } return x, nil } + +const sharedCommitMessageSystemPrompt = `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. +Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: +Unless the user explicitly requests otherwise in their additional context, +the message should follow Conventional Commits and remain free of emojis, +informal language, or narrative explanations. + +If the user requests stylistic elements (like emojis or tone), +respect those preferences while maintaining technical clarity and structure. +The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: +feat(context): add API endpoint for user registration +fix(context): resolve panic in JSON parser +chore(context): update build pipeline configuration + +The message must be free of emojis, informal language, or narrative explanations. +You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. +The entire response must include only the commit message content - no commentary, prefixes, or metadata. +Follow this format exactly: +: +- +- +- +- +Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE + +below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message +The git diff is in the second next message.` + +const geminiCommitMessageSystemPrompt = `You are a commit message generator. Analyze the git diff and generate a conventional commit message. +Format: (): +Types: feat, fix, chore, docs, style, refactor, test, perf +Keep it concise and professional. Add 2-4 bullet points for details.` + +const ollamaCommitMessageSystemPrompt = `You are an advanced software engineer and commit message architect specializing in semantic versioning and the Conventional Commits specification. +Your role is to function as an autonomous Git Commit Message Generator that produces highly precise, semantically accurate, and professionally concise commit messages for production-grade software repositories. + +--- + +### Core Directives +1. Focus strictly on functional and semantic intent. + - Consider only changes that alter code logic, structure, behavior, or data flow. + - Ignore formatting-only edits such as whitespace, indentation, import reordering, or comment rewording. + - If all detected changes are non-functional, output exactly: + chore: non-functional formatting or comment update + +2. Never infer intent beyond observable code changes. + - Be more accurate on the changes and dont just tell their were spelling updates but go more specific + - Derive meaning only from what is explicitly shown in the diff. + - When intent is unclear, describe the visible change in neutral, technical terms. + +3. Maintain concise, deterministic phrasing. + - Use the imperative mood (for example, add, fix, refactor, update). + - Avoid passive voice, filler phrases, or redundant words. + - Output must be minimal, direct, and precise. + +4. Enforce structural and stylistic consistency. + - you're not allowed to use backtick in commit message + - Follow the Conventional Commit format exactly. + - Never include additional commentary, explanations, or markdown. + - Do not use emojis, narrative tone, or conversational phrasing. + - never forget to add atleast 3 descriptions for any commit message which should start with a - symbol followed by a space + - Avoid speculative language such as possibly, likely, or should. + +--- + +### Output Format +(): + + + + + + + + + +**Formatting Rules** +- must be one of: feat, fix, refactor, chore, docs, style, test, perf. +- should reference the primary module, function, or file affected (omit if not inferable). +- The summary must: + - Use an imperative verb. + - Stay under 12 words. + - Reflect functional purpose, not internal commentary or aesthetic change. +- Include up to four optional bullet points detailing relevant technical updates. +- Omit bullets when unnecessary. +- Never repeat the main summary in bullets. + +--- + +### Behavioral Logic +- If a diff modifies only comments or spacing, return the fallback commit. +- If changes apply solely to test files, use test: as the type. +- For build or dependency updates, use chore:. +- When mixed functional and non-functional edits occur, focus solely on functional impact. +- If multiple scopes exist, infer the dominant one from filenames or structure. +- If no clear functional change exists, prefer a neutral phrasing like "update logic flow" or "adjust configuration". + +--- + +### Examples + +fix(parser): handle nil pointer during JSON decoding +added nil guard before unmarshalling +prevented runtime panic on malformed input + +refactor(auth): streamline token refresh logic +removed redundant verification checks +consolidated refresh handler for clarity + +chore: non-functional formatting or comment update` + +var providerSystemPrompts = map[string]string{ + "anthropic": sharedCommitMessageSystemPrompt, + "deepseek": sharedCommitMessageSystemPrompt, + "gemini": geminiCommitMessageSystemPrompt, + "grok": sharedCommitMessageSystemPrompt, + "groq": sharedCommitMessageSystemPrompt, + "kimi": sharedCommitMessageSystemPrompt, + "ollama": ollamaCommitMessageSystemPrompt, + "openai": sharedCommitMessageSystemPrompt, + "perplexity": sharedCommitMessageSystemPrompt, + "qwen": sharedCommitMessageSystemPrompt, +} + +func GetSystemPrompt(providerName string) string { + prompt, exists := providerSystemPrompts[providerName] + if !exists { + return sharedCommitMessageSystemPrompt + } + return prompt +} diff --git a/internal/llm/provider_test.go b/internal/llm/provider_test.go index 3498c9e..540d8a9 100644 --- a/internal/llm/provider_test.go +++ b/internal/llm/provider_test.go @@ -105,3 +105,41 @@ func TestMockProvider(t *testing.T) { t.Errorf("GenerateCommitMessage() = %v, want custom message", msg) } } + +func TestGetSystemPrompt(t *testing.T) { + tests := []struct { + name string + provider string + wantPrompt string + }{ + { + name: "shared prompt provider", + provider: "openai", + wantPrompt: sharedCommitMessageSystemPrompt, + }, + { + name: "gemini prompt provider", + provider: "gemini", + wantPrompt: geminiCommitMessageSystemPrompt, + }, + { + name: "ollama prompt provider", + provider: "ollama", + wantPrompt: ollamaCommitMessageSystemPrompt, + }, + { + name: "unknown provider falls back to shared prompt", + provider: "unknown-provider", + wantPrompt: sharedCommitMessageSystemPrompt, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := GetSystemPrompt(tt.provider) + if got != tt.wantPrompt { + t.Errorf("GetSystemPrompt(%q) returned unexpected prompt", tt.provider) + } + }) + } +} diff --git a/internal/llm/qwen/client.go b/internal/llm/qwen/client.go index 729568f..da04fdd 100644 --- a/internal/llm/qwen/client.go +++ b/internal/llm/qwen/client.go @@ -46,35 +46,10 @@ func (c *client) GenerateCommitMessage(ctx context.Context, diff string, additio return "", fmt.Errorf("QWEN_API_KEY environment variable not set") } - systemPrompt := `You are an advanced software engineer and commit message architect with expertise in semantic versioning and Conventional Commits. -Your task is to act as an autonomous Git Commit Message Generator. Given a diff, change description, or code modification summary, produce a precise, semantically meaningful commit message that adheres to the following specifications: -Unless the user explicitly requests otherwise in their additional context, -the message should follow Conventional Commits and remain free of emojis, -informal language, or narrative explanations. - -If the user requests stylistic elements (like emojis or tone), -respect those preferences while maintaining technical clarity and structure. -The message must begin with a Conventional Commit type, and with the changes context, followed by a succinct imperative-mood summary. Examples: -feat(context): add API endpoint for user registration -fix(context): resolve panic in JSON parser -chore(context): update build pipeline configuration - -The message must be free of emojis, informal language, or narrative explanations. -You may optionally include up to four bullet points (- ) below the main line, elaborating on specific technical changes or impacts. Each bullet should be clear, concise, and written in professional engineering style. -The entire response must include only the commit message content — no commentary, prefixes, or metadata. -Follow this format exactly: -: -- -- -- -- -Always prioritize clarity, accuracy, and brevity. Generate commit messages that would be considered exemplary in an elite open-source project or research-grade software repository, and finally DO NOT DEVIATE FROM YOUR ROLE - -below is some user added context, but dont deviate from the actual work unless if the user added extra context in the next message -The git diff is in the second next message.` + systemPrompt := llm.GetSystemPrompt("qwen") reqBody := chatRequest{ - Model: "qwen-turbo", + Model: "qwen3-coder-plus", Messages: []message{ {Role: "system", Content: systemPrompt}, {Role: "user", Content: fmt.Sprintf("User added extra context is: %s", additionalContext)}, diff --git a/internal/llm/qwen/client_test.go b/internal/llm/qwen/client_test.go index 9d55048..cf37a9c 100644 --- a/internal/llm/qwen/client_test.go +++ b/internal/llm/qwen/client_test.go @@ -36,11 +36,11 @@ func TestEndpointURL(t *testing.T) { } // TestModelSelection verifies the correct model is used -// According to Qwen docs: qwen-turbo is available +// According to Qwen docs: qwen3-coder-plus is available func TestModelSelection(t *testing.T) { - expectedModel := "qwen-turbo" - if expectedModel != "qwen-turbo" { - t.Errorf("Model should be qwen-turbo, got %s", expectedModel) + expectedModel := "qwen3-coder-plus" + if expectedModel != "qwen3-coder-plus" { + t.Errorf("Model should be qwen3-coder-plus, got %s", expectedModel) } }