summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-02 09:24:23 +0300
committerPaul Buetow <paul@buetow.org>2026-04-02 09:24:23 +0300
commit6ce9123de04ffff961cbf1da73648679216ff637 (patch)
tree7a8c12f3499b0a62471627773fde9588a14c9261 /internal
parentfaee049f51a3e6125a710fae3e713638bd68dd48 (diff)
Fix verification gate lint and test issues
Diffstat (limited to 'internal')
-rw-r--r--internal/audio/gemini_provider.go10
-rw-r--r--internal/audio/provider.go2
-rw-r--r--internal/audio/provider_test.go2
-rw-r--r--internal/gui/app.go7
-rw-r--r--internal/gui/generator.go2
-rw-r--r--internal/image/nanobanana.go2
-rw-r--r--internal/image/openai.go17
-rw-r--r--internal/models/lister.go82
-rw-r--r--internal/phonetic/fetcher.go8
-rw-r--r--internal/phonetic/fetcher_test.go6
-rw-r--r--internal/processor/processor.go2
-rw-r--r--internal/processor/processor_test.go6
-rw-r--r--internal/translation/translator.go8
-rw-r--r--internal/translation/translator_test.go4
14 files changed, 104 insertions, 54 deletions
diff --git a/internal/audio/gemini_provider.go b/internal/audio/gemini_provider.go
index 1d82f2d..5662454 100644
--- a/internal/audio/gemini_provider.go
+++ b/internal/audio/gemini_provider.go
@@ -33,7 +33,7 @@ var _ Provider = (*GeminiProvider)(nil)
func NewGeminiProvider(config *Config) (Provider, error) {
normalized := normalizeGeminiConfig(config)
if normalized.GoogleAPIKey == "" {
- return nil, errors.New("Google API key is required")
+ return nil, errors.New("google API key is required")
}
client, err := genai.NewClient(context.Background(), &genai.ClientConfig{
@@ -56,7 +56,7 @@ func (p *GeminiProvider) GenerateAudio(ctx context.Context, text string, outputF
return err
}
if p == nil || p.client == nil || p.config == nil {
- return errors.New("Gemini client not initialized")
+ return errors.New("gemini client not initialized")
}
prompt := p.buildPrompt(text)
@@ -69,7 +69,7 @@ func (p *GeminiProvider) GenerateAudio(ctx context.Context, text string, outputF
genai.NewContentFromText(prompt, genai.RoleUser),
}, req)
if err != nil {
- return fmt.Errorf("Gemini API error: %w", err)
+ return fmt.Errorf("gemini API error: %w", err)
}
audioData, mimeType, err := extractAudioData(response)
@@ -92,7 +92,7 @@ func (p *GeminiProvider) Name() string {
// IsAvailable checks if the Google API key is configured.
func (p *GeminiProvider) IsAvailable() error {
if p == nil || p.config == nil || strings.TrimSpace(p.config.GoogleAPIKey) == "" {
- return errors.New("Google API key not configured")
+ return errors.New("google API key not configured")
}
return nil
@@ -183,7 +183,7 @@ func writeGeminiAudioFile(outputFile string, audioData []byte, mimeType string)
ext := strings.ToLower(filepath.Ext(outputFile))
if ext != ".wav" {
- return fmt.Errorf("Gemini TTS only supports .wav output files, got %q", outputFile)
+ return fmt.Errorf("gemini TTS only supports .wav output files, got %q", outputFile)
}
encoded, err := encodePCMAsWAV(audioData)
diff --git a/internal/audio/provider.go b/internal/audio/provider.go
index 06ed6d0..b7f6bd9 100644
--- a/internal/audio/provider.go
+++ b/internal/audio/provider.go
@@ -67,7 +67,7 @@ func NewProvider(config *Config) (Provider, error) {
return NewOpenAIProvider(config)
case "gemini":
if config.GoogleAPIKey == "" {
- return nil, fmt.Errorf("Google API key is required")
+ return nil, fmt.Errorf("google API key is required")
}
return NewGeminiProvider(config)
default:
diff --git a/internal/audio/provider_test.go b/internal/audio/provider_test.go
index 64fbcc7..c13e823 100644
--- a/internal/audio/provider_test.go
+++ b/internal/audio/provider_test.go
@@ -98,7 +98,7 @@ func TestNewProvider(t *testing.T) {
name: "nil config uses defaults",
config: nil,
wantErr: true,
- errMsg: "Google API key is required",
+ errMsg: "google API key is required",
},
{
name: "openai provider without key",
diff --git a/internal/gui/app.go b/internal/gui/app.go
index a69b178..5d24e6d 100644
--- a/internal/gui/app.go
+++ b/internal/gui/app.go
@@ -629,8 +629,9 @@ func (a *Application) onSubmit() {
return
}
- // Handle English to Bulgarian translation first if needed
- if translationDirection == "en-to-bg" {
+ // Handle translation first if needed.
+ switch translationDirection {
+ case "en-to-bg":
a.updateStatus(fmt.Sprintf("Translating '%s' to Bulgarian...", secondaryText))
bulgarian, err := a.translateEnglishToBulgarian(secondaryText)
if err != nil {
@@ -643,7 +644,7 @@ func (a *Application) onSubmit() {
a.currentWord = bulgarian
a.saveTranslation()
needsTranslation = false
- } else if translationDirection == "bg-to-en" {
+ case "bg-to-en":
a.updateStatus(fmt.Sprintf("Translating '%s' to English...", bulgarianText))
english, err := a.translateWord(bulgarianText)
if err != nil {
diff --git a/internal/gui/generator.go b/internal/gui/generator.go
index 45cd7bc..f19f46e 100644
--- a/internal/gui/generator.go
+++ b/internal/gui/generator.go
@@ -383,7 +383,7 @@ func (a *Application) newImageSearcher() (promptAwareImageClient, error) {
config = DefaultConfig()
}
if config.GoogleAPIKey == "" {
- return nil, fmt.Errorf("Google API key is required for image generation")
+ return nil, fmt.Errorf("google API key is required for image generation")
}
nanoBananaConfig := &image.NanoBananaConfig{
diff --git a/internal/image/nanobanana.go b/internal/image/nanobanana.go
index 7c1ba26..ae67513 100644
--- a/internal/image/nanobanana.go
+++ b/internal/image/nanobanana.go
@@ -419,7 +419,7 @@ func (c *NanoBananaClient) generateText(ctx context.Context, model, systemPrompt
MaxOutputTokens: maxOutputTokens,
})
if err != nil {
- return "", fmt.Errorf("Gemini API error: %w", err)
+ return "", fmt.Errorf("gemini API error: %w", err)
}
text := strings.TrimSpace(resp.Text())
diff --git a/internal/image/openai.go b/internal/image/openai.go
index 79fbe38..7673b7d 100644
--- a/internal/image/openai.go
+++ b/internal/image/openai.go
@@ -207,16 +207,17 @@ func (c *OpenAIClient) Download(ctx context.Context, url string) (io.ReadCloser,
// GetAttribution returns the required attribution text
func (c *OpenAIClient) GetAttribution(result *SearchResult) string {
- attribution := fmt.Sprintf("Image generated by OpenAI DALL-E\n\n")
- attribution += fmt.Sprintf("Model: %s\n", c.model)
- attribution += fmt.Sprintf("Size: %s\n", c.size)
+ var attribution strings.Builder
+ attribution.WriteString("Image generated by OpenAI DALL-E\n\n")
+ fmt.Fprintf(&attribution, "Model: %s\n", c.model)
+ fmt.Fprintf(&attribution, "Size: %s\n", c.size)
if c.model == "dall-e-3" {
- attribution += fmt.Sprintf("Quality: %s\n", c.quality)
- attribution += fmt.Sprintf("Style: %s\n", c.style)
+ fmt.Fprintf(&attribution, "Quality: %s\n", c.quality)
+ fmt.Fprintf(&attribution, "Style: %s\n", c.style)
}
- attribution += fmt.Sprintf("\nPrompt used:\n%s\n", c.lastPrompt)
- attribution += fmt.Sprintf("\nGenerated at: %s\n", time.Now().Format("2006-01-02 15:04:05"))
- return attribution
+ fmt.Fprintf(&attribution, "\nPrompt used:\n%s\n", c.lastPrompt)
+ fmt.Fprintf(&attribution, "\nGenerated at: %s\n", time.Now().Format("2006-01-02 15:04:05"))
+ return attribution.String()
}
// Name returns the name of the provider
diff --git a/internal/models/lister.go b/internal/models/lister.go
index c798dc6..ca3d3a2 100644
--- a/internal/models/lister.go
+++ b/internal/models/lister.go
@@ -66,7 +66,9 @@ func (l *Lister) ListAvailableModels() error {
return fmt.Errorf("no API keys found. Set OPENAI_API_KEY and/or GOOGLE_API_KEY environment variable(s) or configure them in .totalrecall.yaml")
}
- fmt.Fprintln(l.out, "Available Models:")
+ if err := l.writeLine("Available Models:"); err != nil {
+ return err
+ }
printedSection := false
if l.openAIKey != "" {
@@ -78,7 +80,9 @@ func (l *Lister) ListAvailableModels() error {
if l.geminiKey != "" {
if printedSection {
- fmt.Fprintln(l.out)
+ if err := l.writeLine(""); err != nil {
+ return err
+ }
}
if err := l.printGeminiModels(); err != nil {
return err
@@ -118,26 +122,42 @@ func (l *Lister) printOpenAIModels() error {
sort.Strings(imageModels)
sort.Strings(chatModels)
- fmt.Fprintln(l.out, "OpenAI Models:")
- fmt.Fprintln(l.out, " Text-to-Speech (TTS) Models:")
+ if err := l.writeLine("OpenAI Models:"); err != nil {
+ return err
+ }
+ if err := l.writeLine(" Text-to-Speech (TTS) Models:"); err != nil {
+ return err
+ }
if len(ttsModels) == 0 {
- fmt.Fprintln(l.out, " No TTS models found")
+ if err := l.writeLine(" No TTS models found"); err != nil {
+ return err
+ }
} else {
for _, model := range ttsModels {
- fmt.Fprintf(l.out, " %s\n", model)
+ if err := l.writeLine(" " + model); err != nil {
+ return err
+ }
}
}
- fmt.Fprintln(l.out, " Image Generation Models:")
+ if err := l.writeLine(" Image Generation Models:"); err != nil {
+ return err
+ }
if len(imageModels) == 0 {
- fmt.Fprintln(l.out, " No image models found")
+ if err := l.writeLine(" No image models found"); err != nil {
+ return err
+ }
} else {
for _, model := range imageModels {
- fmt.Fprintf(l.out, " %s\n", model)
+ if err := l.writeLine(" " + model); err != nil {
+ return err
+ }
}
}
- fmt.Fprintln(l.out, " Chat/Translation Models (for Bulgarian translation):")
+ if err := l.writeLine(" Chat/Translation Models (for Bulgarian translation):"); err != nil {
+ return err
+ }
if len(chatModels) > 10 {
// Show only relevant models
relevantModels := []string{}
@@ -147,12 +167,18 @@ func (l *Lister) printOpenAIModels() error {
}
}
for _, model := range relevantModels {
- fmt.Fprintf(l.out, " %s\n", model)
+ if err := l.writeLine(" " + model); err != nil {
+ return err
+ }
+ }
+ if err := l.writeFormatted(" ... and %d more models\n", len(chatModels)-len(relevantModels)); err != nil {
+ return err
}
- fmt.Fprintf(l.out, " ... and %d more models\n", len(chatModels)-len(relevantModels))
} else {
for _, model := range chatModels {
- fmt.Fprintf(l.out, " %s\n", model)
+ if err := l.writeLine(" " + model); err != nil {
+ return err
+ }
}
}
@@ -164,7 +190,7 @@ func (l *Lister) printGeminiModels() error {
return fmt.Errorf("failed to initialize Gemini client: %w", l.geminiInitErr)
}
if l.geminiClient == nil {
- return fmt.Errorf("Gemini client not initialized")
+ return fmt.Errorf("gemini client not initialized")
}
ctx := context.Background()
@@ -189,14 +215,36 @@ func (l *Lister) printGeminiModels() error {
sort.Strings(geminiModels)
- fmt.Fprintln(l.out, "Gemini Models:")
+ if err := l.writeLine("Gemini Models:"); err != nil {
+ return err
+ }
if len(geminiModels) == 0 {
- fmt.Fprintln(l.out, " No Gemini models found")
+ if err := l.writeLine(" No Gemini models found"); err != nil {
+ return err
+ }
return nil
}
for _, model := range geminiModels {
- fmt.Fprintf(l.out, " %s\n", model)
+ if err := l.writeLine(" " + model); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (l *Lister) writeLine(text string) error {
+ if _, err := fmt.Fprintln(l.out, text); err != nil {
+ return fmt.Errorf("write model list output: %w", err)
+ }
+
+ return nil
+}
+
+func (l *Lister) writeFormatted(format string, args ...any) error {
+ if _, err := fmt.Fprintf(l.out, format, args...); err != nil {
+ return fmt.Errorf("write model list output: %w", err)
}
return nil
diff --git a/internal/phonetic/fetcher.go b/internal/phonetic/fetcher.go
index e6f9694..5d39fc3 100644
--- a/internal/phonetic/fetcher.go
+++ b/internal/phonetic/fetcher.go
@@ -88,7 +88,7 @@ var fetchGeminiPhonetic = func(ctx context.Context, client *genai.Client, word s
MaxOutputTokens: phoneticMaxTokens,
})
if err != nil {
- return "", fmt.Errorf("Gemini API error: %w", err)
+ return "", fmt.Errorf("gemini API error: %w", err)
}
phoneticInfo := strings.TrimSpace(resp.Text())
@@ -181,13 +181,13 @@ func (f *Fetcher) fetchWithOpenAI(ctx context.Context, word string) (string, err
func (f *Fetcher) fetchWithGemini(ctx context.Context, word string) (string, error) {
if f.googleAPIKey == "" {
- return "", fmt.Errorf("Google API key not configured")
+ return "", fmt.Errorf("google API key not configured")
}
if f.geminiInitErr != nil {
- return "", fmt.Errorf("Gemini client initialization failed: %w", f.geminiInitErr)
+ return "", fmt.Errorf("gemini client initialization failed: %w", f.geminiInitErr)
}
if f.geminiClient == nil {
- return "", fmt.Errorf("Gemini client not initialized")
+ return "", fmt.Errorf("gemini client not initialized")
}
return fetchGeminiPhonetic(ctx, f.geminiClient, word)
diff --git a/internal/phonetic/fetcher_test.go b/internal/phonetic/fetcher_test.go
index c577d5d..7fa74e8 100644
--- a/internal/phonetic/fetcher_test.go
+++ b/internal/phonetic/fetcher_test.go
@@ -45,8 +45,8 @@ func TestFetchAndSave_NoGoogleAPIKey(t *testing.T) {
t.Fatal("expected error for missing Google API key")
}
- if err.Error() != "Google API key not configured" {
- t.Fatalf("expected Google API key error, got %v", err)
+ if err.Error() != "google API key not configured" {
+ t.Fatalf("expected google API key error, got %v", err)
}
}
@@ -205,7 +205,7 @@ func TestFetchAndSave_GeminiInitFailure(t *testing.T) {
t.Fatal("expected Gemini init failure")
}
- if err.Error() != "Gemini client initialization failed: context canceled" {
+ if err.Error() != "gemini client initialization failed: context canceled" {
t.Fatalf("unexpected Gemini init error: %v", err)
}
}
diff --git a/internal/processor/processor.go b/internal/processor/processor.go
index 036fa79..8536b98 100644
--- a/internal/processor/processor.go
+++ b/internal/processor/processor.go
@@ -793,7 +793,7 @@ func (p *Processor) newNanoBananaImageSearcher() (image.ImageSearcher, error) {
}
if nanoBananaConfig.APIKey == "" {
- return nil, fmt.Errorf("Google API key is required for image generation")
+ return nil, fmt.Errorf("google API key is required for image generation")
}
return newNanoBananaImageClient(nanoBananaConfig), nil
diff --git a/internal/processor/processor_test.go b/internal/processor/processor_test.go
index b746a84..e75fa8d 100644
--- a/internal/processor/processor_test.go
+++ b/internal/processor/processor_test.go
@@ -212,7 +212,7 @@ func TestNewProcessor_ExplicitGeminiTranslationProvider(t *testing.T) {
if err == nil {
t.Fatal("Expected error for missing Google API key")
}
- if err.Error() != "Google API key not found" {
+ if err.Error() != "google API key not found" {
t.Fatalf("Expected Gemini provider error, got: %v", err)
}
}
@@ -1248,8 +1248,8 @@ func TestNewImageSearcherConfiguredNanoBananaRequiresGoogleAPIKey(t *testing.T)
if err == nil {
t.Fatal("expected error when Google API key is missing for Nano Banana")
}
- if got := err.Error(); got != "Google API key is required for image generation" {
- t.Fatalf("newImageSearcher() error = %q, want %q", got, "Google API key is required for image generation")
+ if got := err.Error(); got != "google API key is required for image generation" {
+ t.Fatalf("newImageSearcher() error = %q, want %q", got, "google API key is required for image generation")
}
}
diff --git a/internal/translation/translator.go b/internal/translation/translator.go
index 09a1e67..b2e997e 100644
--- a/internal/translation/translator.go
+++ b/internal/translation/translator.go
@@ -172,13 +172,13 @@ func (t *Translator) translateWithOpenAI(prompt string) (string, error) {
func (t *Translator) translateWithGemini(prompt string) (string, error) {
if t.googleAPIKey == "" {
- return "", fmt.Errorf("Google API key not found")
+ return "", fmt.Errorf("google API key not found")
}
if t.geminiInitErr != nil {
- return "", fmt.Errorf("Gemini client initialization failed: %w", t.geminiInitErr)
+ return "", fmt.Errorf("gemini client initialization failed: %w", t.geminiInitErr)
}
if t.geminiClient == nil {
- return "", fmt.Errorf("Gemini client not initialized")
+ return "", fmt.Errorf("gemini client not initialized")
}
ctx, cancel := context.WithTimeout(context.Background(), translationTimeout)
@@ -192,7 +192,7 @@ func (t *Translator) translateWithGemini(prompt string) (string, error) {
MaxOutputTokens: translationMaxTokens,
})
if err != nil {
- return "", fmt.Errorf("Gemini API error: %w", err)
+ return "", fmt.Errorf("gemini API error: %w", err)
}
translation := strings.TrimSpace(resp.Text())
diff --git a/internal/translation/translator_test.go b/internal/translation/translator_test.go
index 49f1f15..f73079c 100644
--- a/internal/translation/translator_test.go
+++ b/internal/translation/translator_test.go
@@ -89,8 +89,8 @@ func TestTranslateWord_ExplicitGeminiRequiresGoogleAPIKey(t *testing.T) {
if err == nil {
t.Fatal("Expected error for missing Google API key")
}
- if err.Error() != "Google API key not found" {
- t.Fatalf("Expected 'Google API key not found' error, got: %v", err)
+ if err.Error() != "google API key not found" {
+ t.Fatalf("Expected 'google API key not found' error, got: %v", err)
}
}