add model list CLI command with provider/type filters
This commit is contained in:
@@ -4,11 +4,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/leonardotrapani/hyprvoice/internal/bus"
|
"github.com/leonardotrapani/hyprvoice/internal/bus"
|
||||||
"github.com/leonardotrapani/hyprvoice/internal/config"
|
"github.com/leonardotrapani/hyprvoice/internal/config"
|
||||||
"github.com/leonardotrapani/hyprvoice/internal/daemon"
|
"github.com/leonardotrapani/hyprvoice/internal/daemon"
|
||||||
|
"github.com/leonardotrapani/hyprvoice/internal/models/whisper"
|
||||||
|
"github.com/leonardotrapani/hyprvoice/internal/provider"
|
||||||
"github.com/leonardotrapani/hyprvoice/internal/tui"
|
"github.com/leonardotrapani/hyprvoice/internal/tui"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -31,6 +34,7 @@ func init() {
|
|||||||
versionCmd(),
|
versionCmd(),
|
||||||
stopCmd(),
|
stopCmd(),
|
||||||
configureCmd(),
|
configureCmd(),
|
||||||
|
modelCmd(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,3 +395,135 @@ func hasCustomMessages(msgs config.MessagesConfig) bool {
|
|||||||
msgs.RecordingAborted.Body != "" ||
|
msgs.RecordingAborted.Body != "" ||
|
||||||
msgs.InjectionAborted.Body != ""
|
msgs.InjectionAborted.Body != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func modelCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "model",
|
||||||
|
Short: "Manage transcription models",
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(modelListCmd())
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func modelListCmd() *cobra.Command {
|
||||||
|
var providerFilter string
|
||||||
|
var typeFilter string
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Short: "List available transcription and LLM models",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return runModelList(providerFilter, typeFilter)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringVar(&providerFilter, "provider", "", "filter by provider name")
|
||||||
|
cmd.Flags().StringVar(&typeFilter, "type", "", "filter by type: transcription, llm")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func runModelList(providerFilter, typeFilter string) error {
|
||||||
|
// parse type filter
|
||||||
|
var filterType *provider.ModelType
|
||||||
|
if typeFilter != "" {
|
||||||
|
switch strings.ToLower(typeFilter) {
|
||||||
|
case "transcription":
|
||||||
|
t := provider.Transcription
|
||||||
|
filterType = &t
|
||||||
|
case "llm":
|
||||||
|
t := provider.LLM
|
||||||
|
filterType = &t
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid type: %s (use 'transcription' or 'llm')", typeFilter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get providers to iterate
|
||||||
|
providerNames := provider.ListProviders()
|
||||||
|
sort.Strings(providerNames)
|
||||||
|
|
||||||
|
// filter by provider if specified
|
||||||
|
if providerFilter != "" {
|
||||||
|
found := false
|
||||||
|
for _, name := range providerNames {
|
||||||
|
if name == providerFilter {
|
||||||
|
providerNames = []string{name}
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return fmt.Errorf("unknown provider: %s", providerFilter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, providerName := range providerNames {
|
||||||
|
p := provider.GetProvider(providerName)
|
||||||
|
if p == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
models := p.Models()
|
||||||
|
if filterType != nil {
|
||||||
|
models = provider.ModelsOfType(p, *filterType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(models) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// print provider header
|
||||||
|
fmt.Printf("\n%s:\n", providerName)
|
||||||
|
|
||||||
|
for _, m := range models {
|
||||||
|
printModelLine(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printModelLine(m provider.Model) {
|
||||||
|
// build prefix: checkmark for installed local models
|
||||||
|
prefix := " "
|
||||||
|
if m.Local {
|
||||||
|
if whisper.IsInstalled(m.ID) {
|
||||||
|
prefix = " [x]"
|
||||||
|
} else {
|
||||||
|
prefix = " [ ]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build suffix parts
|
||||||
|
var parts []string
|
||||||
|
|
||||||
|
// type indicator
|
||||||
|
if m.Type == provider.LLM {
|
||||||
|
parts = append(parts, "llm")
|
||||||
|
}
|
||||||
|
|
||||||
|
// streaming indicator
|
||||||
|
if m.Streaming {
|
||||||
|
parts = append(parts, "streaming")
|
||||||
|
}
|
||||||
|
|
||||||
|
// size for local models
|
||||||
|
if m.LocalInfo != nil && m.LocalInfo.Size != "" {
|
||||||
|
parts = append(parts, m.LocalInfo.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// build line
|
||||||
|
line := fmt.Sprintf("%s %s", prefix, m.ID)
|
||||||
|
if m.Description != "" {
|
||||||
|
line += fmt.Sprintf(" - %s", m.Description)
|
||||||
|
}
|
||||||
|
if len(parts) > 0 {
|
||||||
|
line += fmt.Sprintf(" [%s]", strings.Join(parts, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(line)
|
||||||
|
}
|
||||||
|
|||||||
@@ -235,3 +235,14 @@ Started: Sun Feb 1 12:22:47 AM CET 2026
|
|||||||
- Note: Threads field, ToTranscriberConfig, and template were already done in Task 16
|
- Note: Threads field, ToTranscriberConfig, and template were already done in Task 16
|
||||||
- Added comprehensive tests for whisper-cpp validation and threads auto-detection
|
- Added comprehensive tests for whisper-cpp validation and threads auto-detection
|
||||||
- All tests passing, typecheck passes
|
- All tests passing, typecheck passes
|
||||||
|
|
||||||
|
### Task 24: Add model list CLI command
|
||||||
|
- Created `modelCmd()` returning cobra.Command with Use: 'model'
|
||||||
|
- Created `modelListCmd()` subcommand with Use: 'list'
|
||||||
|
- Added `--provider` flag to filter by provider name
|
||||||
|
- Added `--type` flag to filter by 'transcription' or 'llm'
|
||||||
|
- Iterates all providers sorted alphabetically, gets Models(), filters by type
|
||||||
|
- For local models: shows [x] if installed via whisper.IsInstalled(), [ ] if not
|
||||||
|
- Shows: Model ID, Description, [streaming] tag if applicable, [size] for local models
|
||||||
|
- Groups output by provider with headers
|
||||||
|
- All tests passing, typecheck passes
|
||||||
+1
-1
@@ -575,7 +575,7 @@
|
|||||||
"Output includes size for local models",
|
"Output includes size for local models",
|
||||||
"Typecheck passes"
|
"Typecheck passes"
|
||||||
],
|
],
|
||||||
"passes": false
|
"passes": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Add model download CLI command",
|
"title": "Add model download CLI command",
|
||||||
|
|||||||
Reference in New Issue
Block a user