From c3ab2f2442b01ab478ec79d4fcdee048924fda22 Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sat, 4 Oct 2025 21:49:48 +0530 Subject: [PATCH 1/8] cobra setup --- LICENSE | 21 --------------------- cmd/root.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/server.go | 40 ++++++++++++++++++++++++++++++++++++++++ go.mod | 3 +++ go.sum | 8 ++++++++ main.go | 11 +++++++++++ 6 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 cmd/root.go create mode 100644 cmd/server.go create mode 100644 main.go diff --git a/LICENSE b/LICENSE index aa95b5f..e69de29 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Leo Gavin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..235a5de --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,51 @@ +/* +Copyright © 2025 NAME HERE + +*/ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + + + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "commit-msg", + Short: "A brief description of your application", + Long: `A longer description that spans multiple lines and likely contains +examples and usage of using your application. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + // 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) + } +} + +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") +} + + diff --git a/cmd/server.go b/cmd/server.go new file mode 100644 index 0000000..34ba6b4 --- /dev/null +++ b/cmd/server.go @@ -0,0 +1,40 @@ +/* +Copyright © 2025 NAME HERE + +*/ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// serverCmd represents the server command +var serverCmd = &cobra.Command{ + Use: "server", + Short: "A brief description of your command", + Long: `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("server called") + }, +} + +func init() { + rootCmd.AddCommand(serverCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // serverCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/go.mod b/go.mod index 31b87c3..ea24350 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/google/generative-ai-go v0.19.0 github.com/openai/openai-go/v3 v3.0.1 github.com/pterm/pterm v0.12.80 + github.com/spf13/cobra v1.10.1 google.golang.org/api v0.223.0 ) @@ -31,9 +32,11 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gookit/color v1.5.4 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/spf13/pflag v1.0.9 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect diff --git a/go.sum b/go.sum index a6d5c71..27c0828 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,7 @@ github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -61,6 +62,8 @@ github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQ github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= @@ -90,8 +93,13 @@ github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaK github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/main.go b/main.go new file mode 100644 index 0000000..bb5db05 --- /dev/null +++ b/main.go @@ -0,0 +1,11 @@ +/* +Copyright © 2025 NAME HERE + +*/ +package main + +import "github.com/dfanso/commit-msg/cmd" + +func main() { + cmd.Execute() +} From 17d5e748762f7c090c3a5ce8f31f78febbb1a3eb Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sun, 5 Oct 2025 12:28:40 +0530 Subject: [PATCH 2/8] added save llm cli cmd --- cmd/commit-msg/main.go | 145 +---------------------------------------- 1 file changed, 2 insertions(+), 143 deletions(-) diff --git a/cmd/commit-msg/main.go b/cmd/commit-msg/main.go index d7bc5a2..8486c8a 100644 --- a/cmd/commit-msg/main.go +++ b/cmd/commit-msg/main.go @@ -1,149 +1,8 @@ package main -import ( - "log" - "os" - - "github.com/atotto/clipboard" - "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" -) +import cmd "github.com/dfanso/commit-msg/cmd/cli" // main is the entry point of the commit message generator func main() { - // Validate COMMIT_LLM and required API keys - commitLLM := os.Getenv("COMMIT_LLM") - var apiKey string - - switch commitLLM { - case "google": - apiKey = os.Getenv("GOOGLE_API_KEY") - if apiKey == "" { - log.Fatalf("GOOGLE_API_KEY is not set") - } - case "grok": - apiKey = os.Getenv("GROK_API_KEY") - if apiKey == "" { - log.Fatalf("GROK_API_KEY is not set") - } - case "chatgpt": - apiKey = os.Getenv("OPENAI_API_KEY") - if apiKey == "" { - log.Fatalf("OPENAI_API_KEY is not set") - } - case "claude": - apiKey = os.Getenv("CLAUDE_API_KEY") - if apiKey == "" { - log.Fatalf("CLAUDE_API_KEY is not set") - } - default: - log.Fatalf("Invalid COMMIT_LLM value: %s", commitLLM) - } - - // 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 - if os.Getenv("COMMIT_LLM") == "google" { - commitMsg, err = gemini.GenerateCommitMessage(config, changes, apiKey) - } else if os.Getenv("COMMIT_LLM") == "chatgpt" { - commitMsg, err = chatgpt.GenerateCommitMessage(config, changes, apiKey) - } else if os.Getenv("COMMIT_LLM") == "claude" { - commitMsg, err = claude.GenerateCommitMessage(config, changes, apiKey) - } else { - 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) + cmd.Execute() } From f29c332d0a409697dec2bac603ae340257fbd690 Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sun, 5 Oct 2025 13:20:43 +0530 Subject: [PATCH 3/8] read api keys from config file --- cmd/cli/createMsg.go | 140 +++++++++++++++++++++++++++++ cmd/cli/llmSetup.go | 53 +++++++++++ cmd/{ => cli}/root.go | 49 ++++++++--- cmd/cli/store/store.go | 195 +++++++++++++++++++++++++++++++++++++++++ cmd/server.go | 40 --------- go.mod | 2 + go.sum | 9 ++ main.go | 11 --- 8 files changed, 436 insertions(+), 63 deletions(-) create mode 100644 cmd/cli/createMsg.go create mode 100644 cmd/cli/llmSetup.go rename cmd/{ => cli}/root.go (55%) create mode 100644 cmd/cli/store/store.go delete mode 100644 cmd/server.go delete mode 100644 main.go diff --git a/cmd/cli/createMsg.go b/cmd/cli/createMsg.go new file mode 100644 index 0000000..63c8c26 --- /dev/null +++ b/cmd/cli/createMsg.go @@ -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) + +} \ No newline at end of file diff --git a/cmd/cli/llmSetup.go b/cmd/cli/llmSetup.go new file mode 100644 index 0000000..e146558 --- /dev/null +++ b/cmd/cli/llmSetup.go @@ -0,0 +1,53 @@ +package cmd + +import ( + "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", + + } + + apiKey, err := apiKeyPrompt.Run() + if err != nil { + return fmt.Errorf("invalid API Key") + } + + 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 { + fmt.Println("Update LLM config") + return nil +} diff --git a/cmd/root.go b/cmd/cli/root.go similarity index 55% rename from cmd/root.go rename to cmd/cli/root.go index 235a5de..c567c2b 100644 --- a/cmd/root.go +++ b/cmd/cli/root.go @@ -1,6 +1,5 @@ /* Copyright © 2025 NAME HERE - */ package cmd @@ -10,18 +9,11 @@ import ( "github.com/spf13/cobra" ) - - // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ - Use: "commit-msg", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, + 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) { }, @@ -36,6 +28,36 @@ func Execute() { } } +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, @@ -46,6 +68,9 @@ func init() { // 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(llmCmd) + llmCmd.AddCommand(llmSetupCmd) + llmCmd.AddCommand(llmUpdateCmd) + rootCmd.AddCommand(creatCommitMsg) } - diff --git a/cmd/cli/store/store.go b/cmd/cli/store/store.go new file mode 100644 index 0000000..5050dff --- /dev/null +++ b/cmd/cli/store/store.go @@ -0,0 +1,195 @@ +package store + +import ( + "encoding/json" + "errors" + "fmt" + "log" + "os" + "path/filepath" + "runtime" +) + +type LLMProvider struct { + LLM string `json:"model"` + APIKey string `json:"api_key"` +} + +type Config struct { + Default string `json:"default"` + LLMProviders []LLMProvider `json:"models"` +} + +func Save(LLMConfig LLMProvider) error { + + cfg := Config{ + LLMConfig.LLM, + []LLMProvider{LLMConfig}, + } + + + configPath, err := getConfigPath() + if err != nil { + return err + } + + isConfigExists := checkConfig(configPath) + if !isConfigExists { + err := createConfigFile(configPath) + if err != nil { + log.Fatal(err) + } + } + + + data, err := os.ReadFile(configPath) + if err != nil { + fmt.Println("Error", err) + log.Fatal(err) + } + + if len(data) > 0 { + err = json.Unmarshal(data, &cfg) + if err != nil { + fmt.Println("unmarshal error", err) + log.Fatal(err) + } + } + + + updated := false + for i, p := range cfg.LLMProviders { + if p.LLM == LLMConfig.LLM { + cfg.LLMProviders[i] = LLMConfig + updated = true + break + } + } + + if !updated { + cfg.LLMProviders = append(cfg.LLMProviders, LLMConfig) + } + + cfg.Default = LLMConfig.LLM + + file, err := os.OpenFile(configPath, os.O_CREATE| os.O_WRONLY| os.O_TRUNC, 0600) + if err != nil { + fmt.Println("error opening file") + } + defer file.Close() + + data, err = json.MarshalIndent(cfg, "", " ") + if err != nil { + return err + } + + return os.WriteFile(configPath, data, 0600) +} + + +func checkConfig(configPath string) bool { + + _,err := os.Stat(configPath) + if err != nil ||os.IsNotExist(err) { + return false + } + + return true +} + + +func createConfigFile(configPath string) error { + + err := os.MkdirAll(filepath.Dir(configPath), 0700) + if err != nil { + return err + } + + return nil + +} + +func getConfigPath() (string, error) { + + appName := "commit-msg" + + switch runtime.GOOS { + + case "windows": + localAppData := os.Getenv("LOCALAPPDATA") + if localAppData == "" { + localAppData = filepath.Join(os.Getenv("USERPROFILE"), "AppData", "Local") + } + + return filepath.Join(localAppData, appName, "config.json"), nil + + case "darwin": + + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + + return filepath.Join(home, "Library", "Application Support", appName, "config.json"), nil + + default: + + configHome := os.Getenv("XDG_CONFIG_HOME") + if configHome == "" { + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + + configHome = filepath.Join(home, ".config") + } + + return filepath.Join(configHome, appName, "config.json"), nil + } + +} + + +func DefaultLLMKey() (*LLMProvider, error) { + + var cfg Config + var useModel LLMProvider + + configPath, err := getConfigPath() + if err != nil { + return nil, err + } + + isConfigExists := checkConfig(configPath) + if !isConfigExists { + return nil, errors.New("config file Not exists") + } + + + data, err := os.ReadFile(configPath) + if err != nil { + fmt.Println("Error", err) + return nil, err + } + + + if len(data) > 0 { + err = json.Unmarshal(data, &cfg) + if err != nil { + fmt.Println("unmarshal error", err) + return nil, err + } + } else { + return nil, errors.New("config file is empty") + } + + defaultLLM := cfg.Default + + for i, p := range cfg.LLMProviders { + if p.LLM == defaultLLM { + useModel= cfg.LLMProviders[i] + return &useModel, nil + } + } + return nil, errors.New("not found default model in config") +} \ No newline at end of file diff --git a/cmd/server.go b/cmd/server.go deleted file mode 100644 index 34ba6b4..0000000 --- a/cmd/server.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright © 2025 NAME HERE - -*/ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -// serverCmd represents the server command -var serverCmd = &cobra.Command{ - Use: "server", - Short: "A brief description of your command", - Long: `A longer description that spans multiple lines and likely contains examples -and usage of using your command. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("server called") - }, -} - -func init() { - rootCmd.AddCommand(serverCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // serverCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} diff --git a/go.mod b/go.mod index ea24350..99570d6 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ toolchain go1.24.7 require ( github.com/atotto/clipboard v0.1.4 github.com/google/generative-ai-go v0.19.0 + github.com/manifoldco/promptui v0.9.0 github.com/openai/openai-go/v3 v3.0.1 github.com/pterm/pterm v0.12.80 github.com/spf13/cobra v1.10.1 @@ -23,6 +24,7 @@ require ( cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/longrunning v0.5.7 // indirect + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/containerd/console v1.0.5 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect diff --git a/go.sum b/go.sum index 27c0828..fe4be9b 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,12 @@ github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= @@ -74,6 +80,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -157,6 +165,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go deleted file mode 100644 index bb5db05..0000000 --- a/main.go +++ /dev/null @@ -1,11 +0,0 @@ -/* -Copyright © 2025 NAME HERE - -*/ -package main - -import "github.com/dfanso/commit-msg/cmd" - -func main() { - cmd.Execute() -} From c360146324e77dddbee6de0585351395035b03f1 Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sun, 5 Oct 2025 16:39:44 +0530 Subject: [PATCH 4/8] added delete, set default, change api key options --- cmd/cli/llmSetup.go | 62 +++++++++++++- cmd/cli/root.go | 2 +- cmd/cli/store/store.go | 179 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 235 insertions(+), 8 deletions(-) diff --git a/cmd/cli/llmSetup.go b/cmd/cli/llmSetup.go index e146558..27f6eb4 100644 --- a/cmd/cli/llmSetup.go +++ b/cmd/cli/llmSetup.go @@ -48,6 +48,66 @@ func SetupLLM() error { } func UpdateLLM() error { - fmt.Println("Update LLM config") + + SavedModels, err := store.ListSavedModels() + if err != nil { + fmt.Println(err) + } + + 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 { + fmt.Println(err) + } + + + prompt = promptui.Select{ + Label: "Select Option", + Items: options, + } + opNo,_,err := prompt.Run() + if err != nil { + fmt.Println(err) + } + + apiKeyprompt := promptui.Prompt { + Label: "Enter API Key", + } + + + switch opNo { + case 0: + err := store.ChangeDefault(model) + if err != nil { + return err + } + fmt.Printf("%s set as default", model) + case 1: + apiKey, err := apiKeyprompt.Run() + if err != nil { + return err + } + store.UpdateAPIKey(model, apiKey) + fmt.Printf("%s API Key Updated", model) + case 2: + err := store.DeleteModel(model) + if err == nil { + fmt.Printf("%s model deleted", model) + } + + + } + return nil } diff --git a/cmd/cli/root.go b/cmd/cli/root.go index c567c2b..8b3d565 100644 --- a/cmd/cli/root.go +++ b/cmd/cli/root.go @@ -68,9 +68,9 @@ func init() { // 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) - rootCmd.AddCommand(creatCommitMsg) } diff --git a/cmd/cli/store/store.go b/cmd/cli/store/store.go index 5050dff..38a8e0d 100644 --- a/cmd/cli/store/store.go +++ b/cmd/cli/store/store.go @@ -72,11 +72,6 @@ func Save(LLMConfig LLMProvider) error { cfg.Default = LLMConfig.LLM - file, err := os.OpenFile(configPath, os.O_CREATE| os.O_WRONLY| os.O_TRUNC, 0600) - if err != nil { - fmt.Println("error opening file") - } - defer file.Close() data, err = json.MarshalIndent(cfg, "", " ") if err != nil { @@ -149,7 +144,6 @@ func getConfigPath() (string, error) { } - func DefaultLLMKey() (*LLMProvider, error) { var cfg Config @@ -192,4 +186,177 @@ func DefaultLLMKey() (*LLMProvider, error) { } } return nil, errors.New("not found default model in config") +} + + +func ListSavedModels() (*Config, error){ + + var cfg Config + + configPath, err := getConfigPath() + if err != nil { + log.Fatal(err) + } + + isConfigExists := checkConfig(configPath) + if !isConfigExists { + log.Fatal("config file not exists") + } + + data, err := os.ReadFile(configPath) + if err != nil { + fmt.Println("Error", err) + log.Fatal(err) + } + + if len(data) > 0 { + err = json.Unmarshal(data, &cfg) + if err != nil { + fmt.Println("unmarshal error", err) + log.Fatal(err) + } + } else { + fmt.Println("Config file is empty, Please add atlead one LLM Key") + return nil, errors.New("config file is empty") + } + + + return &cfg, nil + +} + + +func ChangeDefault(Model string) error { + + var cfg Config + + configPath, err := getConfigPath() + if err != nil { + return err + } + + isConfigExists := checkConfig(configPath) + if !isConfigExists { + return errors.New("config file not exists") + } + + data, err := os.ReadFile(configPath) + if err != nil { + return err + } + + if len(data) > 0 { + err = json.Unmarshal(data, &cfg) + if err != nil { + return err + } + } + + cfg.Default = Model + + data, err = json.MarshalIndent(cfg, "", " ") + if err != nil { + return err + } + + return os.WriteFile(configPath, data, 0600) +} + + +func DeleteModel(Model string) error { + + var cfg Config + var newCfg Config + + configPath, err := getConfigPath() + if err != nil { + return err + } + + isConfigExists := checkConfig(configPath) + if !isConfigExists { + return errors.New("config file not exists") + } + + data, err := os.ReadFile(configPath) + if err != nil { + return err + } + + if len(data) > 0 { + err = json.Unmarshal(data, &cfg) + if err != nil { + return err + } + } + + + if Model == cfg.Default { + if len(cfg.LLMProviders) > 1 { + fmt.Println("Please set other model as default, Cant delete default model") + return nil + } else { + return os.WriteFile(configPath, []byte("{}"), 0600) + } + } else { + + for _,p := range cfg.LLMProviders { + + if p.LLM != Model { + newCfg.LLMProviders = append(newCfg.LLMProviders, p) + } + } + + newCfg.Default = cfg.Default + + data, err = json.MarshalIndent(newCfg, "", " ") + if err != nil { + return err + } + return os.WriteFile(configPath, data, 0600) + + } +} + + +func UpdateAPIKey(Model, APIKey string) error { + + var cfg Config + + + configPath, err := getConfigPath() + if err != nil { + return err + } + + isConfigExists := checkConfig(configPath) + if !isConfigExists { + return errors.New("config file not exists") + } + + data, err := os.ReadFile(configPath) + if err != nil { + return err + } + + if len(data) > 0 { + err = json.Unmarshal(data, &cfg) + if err != nil { + return err + } + } + + for i, p := range cfg.LLMProviders { + if p.LLM == Model { + cfg.LLMProviders[i].APIKey = APIKey + } + } + + data, err = json.MarshalIndent(cfg, "", " ") + if err != nil { + return err + } + + return os.WriteFile(configPath, data, 0600) + } \ No newline at end of file From 19a624664e19127419da448dcfab27cbe90991d0 Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sun, 5 Oct 2025 18:31:04 +0530 Subject: [PATCH 5/8] fixed file issues --- cmd/cli/llmSetup.go | 22 +++++++++++++++------- cmd/cli/store/store.go | 27 ++++++++++++--------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/cmd/cli/llmSetup.go b/cmd/cli/llmSetup.go index 27f6eb4..788a5ee 100644 --- a/cmd/cli/llmSetup.go +++ b/cmd/cli/llmSetup.go @@ -1,6 +1,7 @@ package cmd import ( + "fmt" "github.com/dfanso/commit-msg/cmd/cli/store" @@ -51,7 +52,12 @@ func UpdateLLM() error { SavedModels, err := store.ListSavedModels() if err != nil { - fmt.Println(err) + return err + } + + if len(SavedModels.LLMProviders) == 0{ + fmt.Println("No model exists, Please add atleast one model") + return nil } models := []string{} @@ -68,7 +74,7 @@ func UpdateLLM() error { _,model,err := prompt.Run() if err != nil { - fmt.Println(err) + return err } @@ -98,15 +104,17 @@ func UpdateLLM() error { if err != nil { return err } - store.UpdateAPIKey(model, apiKey) + 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 { - fmt.Printf("%s model deleted", model) + if err != nil { + return err } - - + fmt.Printf("%s model deleted", model) } return nil diff --git a/cmd/cli/store/store.go b/cmd/cli/store/store.go index 38a8e0d..9d3b37f 100644 --- a/cmd/cli/store/store.go +++ b/cmd/cli/store/store.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "log" "os" "path/filepath" "runtime" @@ -37,22 +36,24 @@ func Save(LLMConfig LLMProvider) error { if !isConfigExists { err := createConfigFile(configPath) if err != nil { - log.Fatal(err) + return err } } data, err := os.ReadFile(configPath) - if err != nil { - fmt.Println("Error", err) - log.Fatal(err) + if errors.Is(err, os.ErrNotExist){ + data = []byte("{}") + } else if + err != nil { + return err } + if len(data) > 0 { err = json.Unmarshal(data, &cfg) if err != nil { - fmt.Println("unmarshal error", err) - log.Fatal(err) + return err } } @@ -162,7 +163,6 @@ func DefaultLLMKey() (*LLMProvider, error) { data, err := os.ReadFile(configPath) if err != nil { - fmt.Println("Error", err) return nil, err } @@ -170,7 +170,6 @@ func DefaultLLMKey() (*LLMProvider, error) { if len(data) > 0 { err = json.Unmarshal(data, &cfg) if err != nil { - fmt.Println("unmarshal error", err) return nil, err } } else { @@ -195,25 +194,23 @@ func ListSavedModels() (*Config, error){ configPath, err := getConfigPath() if err != nil { - log.Fatal(err) + return nil, err } isConfigExists := checkConfig(configPath) if !isConfigExists { - log.Fatal("config file not exists") + return nil, errors.New("config file not exists") } data, err := os.ReadFile(configPath) if err != nil { - fmt.Println("Error", err) - log.Fatal(err) + return nil, err } if len(data) > 0 { err = json.Unmarshal(data, &cfg) if err != nil { - fmt.Println("unmarshal error", err) - log.Fatal(err) + return nil, err } } else { fmt.Println("Config file is empty, Please add atlead one LLM Key") From 14ef8b7c84480ca1a9f41764b78cddc0311b8f54 Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sun, 5 Oct 2025 18:34:46 +0530 Subject: [PATCH 6/8] removed debugging code --- cmd/cli/llmSetup.go | 2 +- cmd/cli/store/store.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/cli/llmSetup.go b/cmd/cli/llmSetup.go index 788a5ee..9e0eb8d 100644 --- a/cmd/cli/llmSetup.go +++ b/cmd/cli/llmSetup.go @@ -84,7 +84,7 @@ func UpdateLLM() error { } opNo,_,err := prompt.Run() if err != nil { - fmt.Println(err) + return err } apiKeyprompt := promptui.Prompt { diff --git a/cmd/cli/store/store.go b/cmd/cli/store/store.go index 9d3b37f..df41e92 100644 --- a/cmd/cli/store/store.go +++ b/cmd/cli/store/store.go @@ -213,8 +213,7 @@ func ListSavedModels() (*Config, error){ return nil, err } } else { - fmt.Println("Config file is empty, Please add atlead one LLM Key") - return nil, errors.New("config file is empty") + return nil, errors.New("config file is empty, Please add atlead one LLM Key") } From 69d68943303e24449641a0e3cd9719b954ae084f Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sun, 5 Oct 2025 21:11:09 +0530 Subject: [PATCH 7/8] fixed licence issue --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/LICENSE b/LICENSE index e69de29..b2e6ea4 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Leo Gavin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From 49792b561edd0bea4683a50ce0023f6206041c2d Mon Sep 17 00:00:00 2001 From: GauravJangra9988 Date: Sun, 5 Oct 2025 21:58:35 +0530 Subject: [PATCH 8/8] fixed some issues --- cmd/cli/llmSetup.go | 11 ++++++----- cmd/cli/store/store.go | 14 +++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/cmd/cli/llmSetup.go b/cmd/cli/llmSetup.go index 9e0eb8d..e4f40e9 100644 --- a/cmd/cli/llmSetup.go +++ b/cmd/cli/llmSetup.go @@ -1,7 +1,7 @@ package cmd import ( - + "errors" "fmt" "github.com/dfanso/commit-msg/cmd/cli/store" @@ -24,12 +24,13 @@ func SetupLLM() error { apiKeyPrompt := promptui.Prompt{ Label: "Enter API Key", + Mask: '*', } apiKey, err := apiKeyPrompt.Run() if err != nil { - return fmt.Errorf("invalid API Key") + return fmt.Errorf("failed to read API Key: %w", err) } LLMConfig := store.LLMProvider{ @@ -55,9 +56,9 @@ func UpdateLLM() error { return err } - if len(SavedModels.LLMProviders) == 0{ - fmt.Println("No model exists, Please add atleast one model") - return nil + if len(SavedModels.LLMProviders) == 0 { + return errors.New("no model exists, Please add atleast one model Run: 'commit llm setup'") + } models := []string{} diff --git a/cmd/cli/store/store.go b/cmd/cli/store/store.go index df41e92..35a2502 100644 --- a/cmd/cli/store/store.go +++ b/cmd/cli/store/store.go @@ -44,8 +44,7 @@ func Save(LLMConfig LLMProvider) error { data, err := os.ReadFile(configPath) if errors.Is(err, os.ErrNotExist){ data = []byte("{}") - } else if - err != nil { + } else if err != nil { return err } @@ -166,16 +165,18 @@ func DefaultLLMKey() (*LLMProvider, error) { return nil, err } - - if len(data) > 0 { + fmt.Println(len(data)) + if len(data) > 2 { err = json.Unmarshal(data, &cfg) if err != nil { return nil, err } } else { - return nil, errors.New("config file is empty") + return nil, errors.New("config file is empty, Please add atlead one LLM Key") } + + defaultLLM := cfg.Default for i, p := range cfg.LLMProviders { @@ -289,8 +290,7 @@ func DeleteModel(Model string) error { if Model == cfg.Default { if len(cfg.LLMProviders) > 1 { - fmt.Println("Please set other model as default, Cant delete default model") - return nil + return fmt.Errorf("cannot delete %s while it is default, set other model default first", Model) } else { return os.WriteFile(configPath, []byte("{}"), 0600) }