-
Notifications
You must be signed in to change notification settings - Fork 19
Cli interface #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Cli interface #46
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
c3ab2f2
cobra setup
GauravJangra9988 17d5e74
added save llm cli cmd
GauravJangra9988 f29c332
read api keys from config file
GauravJangra9988 c360146
added delete, set default, change api key options
GauravJangra9988 19a6246
fixed file issues
GauravJangra9988 14ef8b7
removed debugging code
GauravJangra9988 ad280f2
Merge branch 'main' into cli-interface
GauravJangra9988 69d6894
fixed licence issue
GauravJangra9988 3439290
Merge branch 'cli-interface' of https://github.com/GauravJangra9988/c…
GauravJangra9988 49792b5
fixed some issues
GauravJangra9988 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "log" | ||
| "os" | ||
|
|
||
| "github.com/atotto/clipboard" | ||
| "github.com/dfanso/commit-msg/cmd/cli/store" | ||
| "github.com/dfanso/commit-msg/internal/chatgpt" | ||
| "github.com/dfanso/commit-msg/internal/claude" | ||
| "github.com/dfanso/commit-msg/internal/display" | ||
| "github.com/dfanso/commit-msg/internal/gemini" | ||
| "github.com/dfanso/commit-msg/internal/git" | ||
| "github.com/dfanso/commit-msg/internal/grok" | ||
| "github.com/dfanso/commit-msg/internal/stats" | ||
| "github.com/dfanso/commit-msg/pkg/types" | ||
| "github.com/pterm/pterm" | ||
| ) | ||
|
|
||
|
|
||
| func CreateCommitMsg () { | ||
|
|
||
| // Validate COMMIT_LLM and required API keys | ||
| useLLM,err := store.DefaultLLMKey() | ||
| if err != nil { | ||
| log.Fatal(err) | ||
| } | ||
|
|
||
| commitLLM := useLLM.LLM | ||
| apiKey := useLLM.APIKey | ||
|
|
||
|
|
||
| // Get current directory | ||
| currentDir, err := os.Getwd() | ||
| if err != nil { | ||
| log.Fatalf("Failed to get current directory: %v", err) | ||
| } | ||
|
|
||
| // Check if current directory is a git repository | ||
| if !git.IsRepository(currentDir) { | ||
| log.Fatalf("Current directory is not a Git repository: %s", currentDir) | ||
| } | ||
|
|
||
| // Create a minimal config for the API | ||
| config := &types.Config{ | ||
| GrokAPI: "https://api.x.ai/v1/chat/completions", | ||
| } | ||
|
|
||
| // Create a repo config for the current directory | ||
| repoConfig := types.RepoConfig{ | ||
| Path: currentDir, | ||
| } | ||
|
|
||
| // Get file statistics before fetching changes | ||
| fileStats, err := stats.GetFileStatistics(&repoConfig) | ||
| if err != nil { | ||
| log.Fatalf("Failed to get file statistics: %v", err) | ||
| } | ||
|
|
||
| // Display header | ||
| pterm.DefaultHeader.WithFullWidth(). | ||
| WithBackgroundStyle(pterm.NewStyle(pterm.BgDarkGray)). | ||
| WithTextStyle(pterm.NewStyle(pterm.FgLightWhite)). | ||
| Println("🚀 Commit Message Generator") | ||
|
|
||
| pterm.Println() | ||
|
|
||
| // Display file statistics with icons | ||
| display.ShowFileStatistics(fileStats) | ||
|
|
||
| if fileStats.TotalFiles == 0 { | ||
| pterm.Warning.Println("No changes detected in the Git repository.") | ||
| return | ||
| } | ||
|
|
||
| // Get the changes | ||
| changes, err := git.GetChanges(&repoConfig) | ||
| if err != nil { | ||
| log.Fatalf("Failed to get Git changes: %v", err) | ||
| } | ||
|
|
||
| if len(changes) == 0 { | ||
| pterm.Warning.Println("No changes detected in the Git repository.") | ||
| return | ||
| } | ||
|
|
||
| pterm.Println() | ||
|
|
||
| // Show generating spinner | ||
| spinnerGenerating, err := pterm.DefaultSpinner. | ||
| WithSequence("⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"). | ||
| Start("🤖 Generating commit message...") | ||
| if err != nil { | ||
| log.Fatalf("Failed to start spinner: %v", err) | ||
| } | ||
|
|
||
| var commitMsg string | ||
|
|
||
| switch commitLLM { | ||
|
|
||
| case "Gemini": | ||
| commitMsg, err = gemini.GenerateCommitMessage(config, changes, apiKey) | ||
|
|
||
| case "OpenAI": | ||
| commitMsg, err = chatgpt.GenerateCommitMessage(config, changes, apiKey) | ||
|
|
||
| case "Claude": | ||
| commitMsg, err = claude.GenerateCommitMessage(config, changes, apiKey) | ||
|
|
||
| default: | ||
| commitMsg, err = grok.GenerateCommitMessage(config, changes, apiKey) | ||
| } | ||
|
|
||
|
|
||
| if err != nil { | ||
| spinnerGenerating.Fail("Failed to generate commit message") | ||
| log.Fatalf("Error: %v", err) | ||
| } | ||
|
|
||
| spinnerGenerating.Success("✅ Commit message generated successfully!") | ||
|
|
||
| pterm.Println() | ||
|
|
||
| // Display the commit message in a styled panel | ||
| display.ShowCommitMessage(commitMsg) | ||
|
|
||
| // Copy to clipboard | ||
| err = clipboard.WriteAll(commitMsg) | ||
| if err != nil { | ||
| pterm.Warning.Printf("⚠️ Could not copy to clipboard: %v\n", err) | ||
| } else { | ||
| pterm.Success.Println("📋 Commit message copied to clipboard!") | ||
| } | ||
|
|
||
| pterm.Println() | ||
|
|
||
| // Display changes preview | ||
| display.ShowChangesPreview(fileStats) | ||
|
|
||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
|
|
||
| "github.com/dfanso/commit-msg/cmd/cli/store" | ||
| "github.com/manifoldco/promptui" | ||
| ) | ||
|
|
||
|
|
||
| func SetupLLM() error { | ||
|
|
||
| providers := []string{"OpenAI", "Claude", "Gemini", "Grok"} | ||
| prompt := promptui.Select{ | ||
| Label: "Select LLM", | ||
| Items: providers, | ||
| } | ||
|
|
||
| _, model, err := prompt.Run() | ||
| if err != nil { | ||
| return fmt.Errorf("prompt failed") | ||
| } | ||
|
|
||
| apiKeyPrompt := promptui.Prompt{ | ||
| Label: "Enter API Key", | ||
| Mask: '*', | ||
|
|
||
| } | ||
|
|
||
| apiKey, err := apiKeyPrompt.Run() | ||
| if err != nil { | ||
| return fmt.Errorf("failed to read API Key: %w", err) | ||
| } | ||
|
|
||
| LLMConfig := store.LLMProvider{ | ||
| LLM: model, | ||
| APIKey: apiKey, | ||
| } | ||
|
|
||
|
|
||
|
|
||
| err = store.Save(LLMConfig) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| fmt.Println("LLM model added") | ||
| return nil | ||
| } | ||
|
|
||
| func UpdateLLM() error { | ||
|
|
||
| SavedModels, err := store.ListSavedModels() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if len(SavedModels.LLMProviders) == 0 { | ||
| return errors.New("no model exists, Please add atleast one model Run: 'commit llm setup'") | ||
GauravJangra9988 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| } | ||
|
|
||
| models := []string{} | ||
| options := []string{"Set Default", "Change API Key", "Delete"} | ||
|
|
||
| for _, p := range SavedModels.LLMProviders { | ||
| models = append(models, p.LLM) | ||
| } | ||
|
|
||
| prompt := promptui.Select{ | ||
| Label: "Select from saved models", | ||
| Items: models, | ||
| } | ||
|
|
||
| _,model,err := prompt.Run() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
|
|
||
| prompt = promptui.Select{ | ||
| Label: "Select Option", | ||
| Items: options, | ||
| } | ||
| opNo,_,err := prompt.Run() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| apiKeyprompt := promptui.Prompt { | ||
| Label: "Enter API Key", | ||
| } | ||
GauravJangra9988 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| switch opNo { | ||
| case 0: | ||
| err := store.ChangeDefault(model) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| fmt.Printf("%s set as default", model) | ||
GauravJangra9988 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| case 1: | ||
| apiKey, err := apiKeyprompt.Run() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| err = store.UpdateAPIKey(model, apiKey) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| fmt.Printf("%s API Key Updated", model) | ||
| case 2: | ||
| err := store.DeleteModel(model) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| fmt.Printf("%s model deleted", model) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| /* | ||
| Copyright © 2025 NAME HERE <EMAIL ADDRESS> | ||
GauravJangra9988 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| */ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "os" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| // rootCmd represents the base command when called without any subcommands | ||
| var rootCmd = &cobra.Command{ | ||
| Use: "commit", | ||
| Short: "CLI tool to write commit message", | ||
| Long: `Write a commit message with AI of your choice`, | ||
| // Uncomment the following line if your bare application | ||
| // has an action associated with it: | ||
| // Run: func(cmd *cobra.Command, args []string) { }, | ||
| } | ||
|
|
||
| // Execute adds all child commands to the root command and sets flags appropriately. | ||
| // This is called by main.main(). It only needs to happen once to the rootCmd. | ||
| func Execute() { | ||
| err := rootCmd.Execute() | ||
| if err != nil { | ||
| os.Exit(1) | ||
| } | ||
| } | ||
|
|
||
| var llmCmd = &cobra.Command{ | ||
| Use: "llm", | ||
| Short: "Manage LLM configuration", | ||
| } | ||
|
|
||
| var llmSetupCmd = &cobra.Command{ | ||
| Use: "setup", | ||
| Short: "Setup your LLM provider and API key", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| return SetupLLM() | ||
| }, | ||
| } | ||
|
|
||
| var llmUpdateCmd = &cobra.Command{ | ||
| Use: "update", | ||
| Short: "Update or Delete LLM Model", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| return UpdateLLM() | ||
| }, | ||
| } | ||
|
|
||
| var creatCommitMsg = &cobra.Command{ | ||
| Use: ".", | ||
| Short: "Create Commit Message", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| CreateCommitMsg() | ||
| return nil | ||
| }, | ||
| } | ||
|
|
||
| func init() { | ||
| // Here you will define your flags and configuration settings. | ||
| // Cobra supports persistent flags, which, if defined here, | ||
| // will be global for your application. | ||
|
|
||
| // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.commit-msg.yaml)") | ||
|
|
||
| // Cobra also supports local flags, which will only run | ||
| // when this action is called directly. | ||
| rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") | ||
| rootCmd.AddCommand(creatCommitMsg) | ||
| rootCmd.AddCommand(llmCmd) | ||
| llmCmd.AddCommand(llmSetupCmd) | ||
| llmCmd.AddCommand(llmUpdateCmd) | ||
| } | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.