feat: refactor
This commit is contained in:
+5
-177
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -175,7 +174,7 @@ func runConfigure(onboarding bool) error {
|
||||
}
|
||||
|
||||
// Save configuration
|
||||
if err := saveConfig(result.Config); err != nil {
|
||||
if err := config.Save(result.Config); err != nil {
|
||||
return fmt.Errorf("failed to save config: %w", err)
|
||||
}
|
||||
|
||||
@@ -224,179 +223,6 @@ func showNextSteps(cfg *config.Config) {
|
||||
fmt.Printf("Config file location: %s\n", configPath)
|
||||
}
|
||||
|
||||
func saveConfig(cfg *config.Config) error {
|
||||
configPath, err := config.GetConfigPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.Create(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create config file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var sb strings.Builder
|
||||
|
||||
// Header
|
||||
sb.WriteString(`# Hyprvoice Configuration
|
||||
# Generated by hyprvoice configure
|
||||
# Changes are applied immediately without daemon restart.
|
||||
|
||||
`)
|
||||
|
||||
// Keywords (must be before any table definitions)
|
||||
if len(cfg.Keywords) > 0 {
|
||||
sb.WriteString("# Keywords help transcription and LLM spell names/terms correctly\n")
|
||||
sb.WriteString("keywords = [")
|
||||
for i, kw := range cfg.Keywords {
|
||||
if i > 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%q", kw))
|
||||
}
|
||||
sb.WriteString("]\n\n")
|
||||
}
|
||||
|
||||
// Providers section
|
||||
if len(cfg.Providers) > 0 {
|
||||
sb.WriteString("# API Keys for providers\n")
|
||||
for name, pc := range cfg.Providers {
|
||||
sb.WriteString(fmt.Sprintf("[providers.%s]\n", name))
|
||||
sb.WriteString(fmt.Sprintf(" api_key = %q\n", pc.APIKey))
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
// Recording
|
||||
sb.WriteString(`# Audio Recording Configuration
|
||||
[recording]
|
||||
`)
|
||||
sb.WriteString(fmt.Sprintf(" sample_rate = %d\n", cfg.Recording.SampleRate))
|
||||
sb.WriteString(fmt.Sprintf(" channels = %d\n", cfg.Recording.Channels))
|
||||
sb.WriteString(fmt.Sprintf(" format = %q\n", cfg.Recording.Format))
|
||||
sb.WriteString(fmt.Sprintf(" buffer_size = %d\n", cfg.Recording.BufferSize))
|
||||
sb.WriteString(fmt.Sprintf(" device = %q\n", cfg.Recording.Device))
|
||||
sb.WriteString(fmt.Sprintf(" channel_buffer_size = %d\n", cfg.Recording.ChannelBufferSize))
|
||||
sb.WriteString(fmt.Sprintf(" timeout = %q\n", cfg.Recording.Timeout.String()))
|
||||
sb.WriteString("\n")
|
||||
|
||||
// Transcription
|
||||
sb.WriteString(`# Speech Transcription Configuration
|
||||
[transcription]
|
||||
`)
|
||||
sb.WriteString(fmt.Sprintf(" provider = %q\n", cfg.Transcription.Provider))
|
||||
sb.WriteString(fmt.Sprintf(" language = %q\n", cfg.Transcription.Language))
|
||||
sb.WriteString(fmt.Sprintf(" model = %q\n", cfg.Transcription.Model))
|
||||
sb.WriteString("\n")
|
||||
|
||||
// LLM
|
||||
sb.WriteString(`# LLM Post-Processing Configuration
|
||||
[llm]
|
||||
`)
|
||||
sb.WriteString(fmt.Sprintf(" enabled = %v\n", cfg.LLM.Enabled))
|
||||
if cfg.LLM.Provider != "" {
|
||||
sb.WriteString(fmt.Sprintf(" provider = %q\n", cfg.LLM.Provider))
|
||||
}
|
||||
if cfg.LLM.Model != "" {
|
||||
sb.WriteString(fmt.Sprintf(" model = %q\n", cfg.LLM.Model))
|
||||
}
|
||||
sb.WriteString("\n")
|
||||
|
||||
sb.WriteString(" [llm.post_processing]\n")
|
||||
sb.WriteString(fmt.Sprintf(" remove_stutters = %v\n", cfg.LLM.PostProcessing.RemoveStutters))
|
||||
sb.WriteString(fmt.Sprintf(" add_punctuation = %v\n", cfg.LLM.PostProcessing.AddPunctuation))
|
||||
sb.WriteString(fmt.Sprintf(" fix_grammar = %v\n", cfg.LLM.PostProcessing.FixGrammar))
|
||||
sb.WriteString(fmt.Sprintf(" remove_filler_words = %v\n", cfg.LLM.PostProcessing.RemoveFillerWords))
|
||||
sb.WriteString("\n")
|
||||
|
||||
sb.WriteString(" [llm.custom_prompt]\n")
|
||||
sb.WriteString(fmt.Sprintf(" enabled = %v\n", cfg.LLM.CustomPrompt.Enabled))
|
||||
if cfg.LLM.CustomPrompt.Prompt != "" {
|
||||
sb.WriteString(fmt.Sprintf(" prompt = %q\n", cfg.LLM.CustomPrompt.Prompt))
|
||||
}
|
||||
sb.WriteString("\n")
|
||||
|
||||
// Injection
|
||||
sb.WriteString(`# Text Injection Configuration
|
||||
[injection]
|
||||
`)
|
||||
sb.WriteString(" backends = [")
|
||||
for i, b := range cfg.Injection.Backends {
|
||||
if i > 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%q", b))
|
||||
}
|
||||
sb.WriteString("]\n")
|
||||
sb.WriteString(fmt.Sprintf(" ydotool_timeout = %q\n", cfg.Injection.YdotoolTimeout.String()))
|
||||
sb.WriteString(fmt.Sprintf(" wtype_timeout = %q\n", cfg.Injection.WtypeTimeout.String()))
|
||||
sb.WriteString(fmt.Sprintf(" clipboard_timeout = %q\n", cfg.Injection.ClipboardTimeout.String()))
|
||||
sb.WriteString("\n")
|
||||
|
||||
// Notifications
|
||||
sb.WriteString(`# Desktop Notification Configuration
|
||||
[notifications]
|
||||
`)
|
||||
sb.WriteString(fmt.Sprintf(" enabled = %v\n", cfg.Notifications.Enabled))
|
||||
sb.WriteString(fmt.Sprintf(" type = %q\n", cfg.Notifications.Type))
|
||||
|
||||
// Write custom messages if any
|
||||
msgs := cfg.Notifications.Messages
|
||||
if hasCustomMessages(msgs) {
|
||||
sb.WriteString("\n [notifications.messages]\n")
|
||||
if msgs.RecordingStarted.Title != "" || msgs.RecordingStarted.Body != "" {
|
||||
sb.WriteString(" [notifications.messages.recording_started]\n")
|
||||
sb.WriteString(fmt.Sprintf(" title = %q\n", msgs.RecordingStarted.Title))
|
||||
sb.WriteString(fmt.Sprintf(" body = %q\n", msgs.RecordingStarted.Body))
|
||||
}
|
||||
if msgs.Transcribing.Title != "" || msgs.Transcribing.Body != "" {
|
||||
sb.WriteString(" [notifications.messages.transcribing]\n")
|
||||
sb.WriteString(fmt.Sprintf(" title = %q\n", msgs.Transcribing.Title))
|
||||
sb.WriteString(fmt.Sprintf(" body = %q\n", msgs.Transcribing.Body))
|
||||
}
|
||||
if msgs.LLMProcessing.Title != "" || msgs.LLMProcessing.Body != "" {
|
||||
sb.WriteString(" [notifications.messages.llm_processing]\n")
|
||||
sb.WriteString(fmt.Sprintf(" title = %q\n", msgs.LLMProcessing.Title))
|
||||
sb.WriteString(fmt.Sprintf(" body = %q\n", msgs.LLMProcessing.Body))
|
||||
}
|
||||
if msgs.ConfigReloaded.Title != "" || msgs.ConfigReloaded.Body != "" {
|
||||
sb.WriteString(" [notifications.messages.config_reloaded]\n")
|
||||
sb.WriteString(fmt.Sprintf(" title = %q\n", msgs.ConfigReloaded.Title))
|
||||
sb.WriteString(fmt.Sprintf(" body = %q\n", msgs.ConfigReloaded.Body))
|
||||
}
|
||||
if msgs.OperationCancelled.Title != "" || msgs.OperationCancelled.Body != "" {
|
||||
sb.WriteString(" [notifications.messages.operation_cancelled]\n")
|
||||
sb.WriteString(fmt.Sprintf(" title = %q\n", msgs.OperationCancelled.Title))
|
||||
sb.WriteString(fmt.Sprintf(" body = %q\n", msgs.OperationCancelled.Body))
|
||||
}
|
||||
if msgs.RecordingAborted.Body != "" {
|
||||
sb.WriteString(" [notifications.messages.recording_aborted]\n")
|
||||
sb.WriteString(fmt.Sprintf(" body = %q\n", msgs.RecordingAborted.Body))
|
||||
}
|
||||
if msgs.InjectionAborted.Body != "" {
|
||||
sb.WriteString(" [notifications.messages.injection_aborted]\n")
|
||||
sb.WriteString(fmt.Sprintf(" body = %q\n", msgs.InjectionAborted.Body))
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := file.WriteString(sb.String()); err != nil {
|
||||
return fmt.Errorf("failed to write config content: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasCustomMessages(msgs config.MessagesConfig) bool {
|
||||
return msgs.RecordingStarted.Title != "" || msgs.RecordingStarted.Body != "" ||
|
||||
msgs.Transcribing.Title != "" || msgs.Transcribing.Body != "" ||
|
||||
msgs.LLMProcessing.Title != "" || msgs.LLMProcessing.Body != "" ||
|
||||
msgs.ConfigReloaded.Title != "" || msgs.ConfigReloaded.Body != "" ||
|
||||
msgs.OperationCancelled.Title != "" || msgs.OperationCancelled.Body != "" ||
|
||||
msgs.RecordingAborted.Body != "" ||
|
||||
msgs.InjectionAborted.Body != ""
|
||||
}
|
||||
|
||||
func modelCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "model",
|
||||
@@ -509,8 +335,10 @@ func printModelLine(m provider.Model) {
|
||||
parts = append(parts, "llm")
|
||||
}
|
||||
|
||||
// streaming indicator
|
||||
if m.Streaming {
|
||||
// mode capabilities indicator
|
||||
if m.SupportsBothModes() {
|
||||
parts = append(parts, "batch+streaming")
|
||||
} else if m.SupportsStreaming {
|
||||
parts = append(parts, "streaming")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user