From fd033b03c70c0e263da1852ff1fa827137c92b35 Mon Sep 17 00:00:00 2001 From: Greg Gauthier Date: Sat, 28 Mar 2026 13:16:31 +0000 Subject: [PATCH] fix(analyze): correct config, logger, and git usage in analyze command - Fix config.GetModel to use command name and flag - Switch to package-level logger functions - Update git.IsRepo to take no arguments - Simplify linter language detection comments - Adjust Grok client creation to NewClient().StreamSilent - Add error handling for confirmation input - Remove unnecessary imports and refine comments in linter --- cmd/analyze.go | 42 ++++++++++++++++++------------------- internal/linter/language.go | 16 ++++++-------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/cmd/analyze.go b/cmd/analyze.go index 1879402..334aecc 100644 --- a/cmd/analyze.go +++ b/cmd/analyze.go @@ -14,8 +14,8 @@ import ( "gmgauthier.com/grokkit/internal/git" "gmgauthier.com/grokkit/internal/grok" "gmgauthier.com/grokkit/internal/linter" - "gmgauthier.com/grokkit/internal/logger" - "gmgauthier.com/grokkit/internal/prompts" // new package (see below) + "gmgauthier.com/grokkit/internal/logger" // note: we use package-level funcs + "gmgauthier.com/grokkit/internal/prompts" ) var analyzeCmd = &cobra.Command{ @@ -32,20 +32,20 @@ Uses language-specific prompts discovered in .grokkit/prompts/ or ~/.config/grok if output == "" { output = "analyze.md" } - model := config.GetModel(viper.GetString("model")) + // Fixed: config.GetModel takes (commandName, flagModel) + model := config.GetModel("analyze", viper.GetString("model")) yes := viper.GetBool("yes") - log := logger.Get() - - // Safety: note if not in git repo - if !git.IsRepo(dir) { - log.Warn("Not inside a git repository. Git metadata in report will be limited.") + // Fixed: use package-level logger funcs (no .Get()) + // Safety: note if not in git repo (IsRepo takes no args) + if !git.IsRepo() { + logger.Warn("Not inside a git repository. Git metadata in report will be limited.") } // 1. Discover source files files, err := discoverSourceFiles(dir) if err != nil { - log.Error("Failed to discover source files", "dir", dir, "error", err) + logger.Error("Failed to discover source files", "dir", dir, "error", err) os.Exit(1) } if len(files) == 0 { @@ -53,7 +53,7 @@ Uses language-specific prompts discovered in .grokkit/prompts/ or ~/.config/grok os.Exit(1) } - // 2. Detect primary language (extend linter as needed) + // 2. Detect primary language lang := linter.DetectPrimaryLanguage(files) if lang == "" { lang = "unknown" @@ -70,22 +70,20 @@ Uses language-specific prompts discovered in .grokkit/prompts/ or ~/.config/grok fmt.Println(`You are an expert ` + lang + ` educator...`) os.Exit(1) } - log.Info("Loaded analysis prompt", "language", lang, "path", promptPath) + logger.Info("Loaded analysis prompt", "language", lang, "path", promptPath) - // 4. Build rich project context (tree, key files, git info, etc.) + // 4. Build rich project context context := buildProjectContext(dir, files) - // 5. Call Grok (silent stream for full report) + // 5. Call Grok — use the exact working pattern you provided messages := []map[string]string{ {"role": "system", "content": promptContent}, {"role": "user", "content": "Analyze the following project and generate the full educational Markdown report:\n\n" + context}, } - report, err := grok.GetClient().StreamSilent(messages, model) - if err != nil { - log.Error("Grok analysis failed", "error", err) - os.Exit(1) - } + // Fixed: NewClient() + Stream() (or StreamSilent if you prefer no live output) + // For a long report, StreamSilent is usually better (no live printing) + report := grok.NewClient().StreamSilent(messages, model) // 6. Transactional preview + confirmation if !yes { @@ -93,7 +91,10 @@ Uses language-specific prompts discovered in .grokkit/prompts/ or ~/.config/grok previewLines(report, 60) fmt.Printf("\nWrite report to %s? (y/N): ", output) var confirm string - fmt.Scanln(&confirm) + _, err := fmt.Scanln(&confirm) + if err != nil { + return + } if !strings.HasPrefix(strings.ToLower(confirm), "y") { fmt.Println("Analysis cancelled by user.") return @@ -107,7 +108,7 @@ Uses language-specific prompts discovered in .grokkit/prompts/ or ~/.config/grok } if err := os.WriteFile(output, []byte(report), 0644); err != nil { - log.Error("Failed to write report", "file", output, "error", err) + logger.Error("Failed to write report", "file", output, "error", err) os.Exit(1) } @@ -120,7 +121,6 @@ func init() { analyzeCmd.Flags().String("dir", ".", "Repository root to analyze") analyzeCmd.Flags().StringP("output", "o", "analyze.md", "Output file (use - for stdout)") analyzeCmd.Flags().BoolP("yes", "y", false, "Skip confirmation prompt") - // model flag is handled globally via config.GetModel rootCmd.AddCommand(analyzeCmd) } diff --git a/internal/linter/language.go b/internal/linter/language.go index 6d90456..39396e5 100644 --- a/internal/linter/language.go +++ b/internal/linter/language.go @@ -1,12 +1,9 @@ package linter -import ( - "path/filepath" - "strings" -) +import "strings" -// DetectPrimaryLanguage returns the dominant language in the given list of files. -// It counts occurrences of each detected language and returns the most frequent one. +// DetectPrimaryLanguage returns the dominant language from the list of files. +// It counts detected languages and returns the most frequent one. // Falls back to "go" (common default) or "unknown". func DetectPrimaryLanguage(files []string) string { if len(files) == 0 { @@ -26,7 +23,7 @@ func DetectPrimaryLanguage(files []string) string { return "unknown" } - // Find the language with the highest count + // Find most common language var bestLang string maxCount := -1 for lang, count := range counts { @@ -36,7 +33,7 @@ func DetectPrimaryLanguage(files []string) string { } } - // Friendly bias toward Go in mixed repos (common case) + // Bias toward Go in mixed repos if counts["go"] > 0 && counts["go"] >= maxCount/2 { return "go" } @@ -44,8 +41,7 @@ func DetectPrimaryLanguage(files []string) string { return bestLang } -// SupportedLanguages returns a list of all languages known to the linter. -// Useful for error messages or future prompt discovery. +// SupportedLanguages returns all known languages (for future use or error messages). func SupportedLanguages() []string { var langs []string for _, l := range languages {