91 lines
2.3 KiB
Go
91 lines
2.3 KiB
Go
package tui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"ai-agent/internal/config"
|
|
|
|
"charm.land/bubbles/v2/list"
|
|
"charm.land/lipgloss/v2"
|
|
)
|
|
|
|
type modelItem struct {
|
|
name string
|
|
size string
|
|
capability string
|
|
isCurrent bool
|
|
}
|
|
|
|
func (i modelItem) Title() string {
|
|
title := i.name
|
|
if i.isCurrent {
|
|
title += " ●"
|
|
}
|
|
return title
|
|
}
|
|
|
|
func (i modelItem) Description() string {
|
|
return fmt.Sprintf("%s · %s", i.size, i.capability)
|
|
}
|
|
|
|
func (i modelItem) FilterValue() string { return i.name }
|
|
|
|
type ModelPickerState struct {
|
|
List list.Model
|
|
Models []config.Model
|
|
CurrentModel string
|
|
}
|
|
|
|
func newModelPickerState(models []config.Model, currentModel string, isDark bool, title string) *ModelPickerState {
|
|
capLabels := map[config.ModelCapability]string{
|
|
config.CapabilitySimple: "Fast",
|
|
config.CapabilityMedium: "Balanced",
|
|
config.CapabilityComplex: "Capable",
|
|
config.CapabilityAdvanced: "Advanced",
|
|
}
|
|
items := make([]list.Item, len(models))
|
|
selectedIdx := 0
|
|
for i, model := range models {
|
|
if model.Name == currentModel {
|
|
selectedIdx = i
|
|
}
|
|
items[i] = modelItem{
|
|
name: model.Name,
|
|
size: model.Size,
|
|
capability: capLabels[model.Capability],
|
|
isCurrent: model.Name == currentModel,
|
|
}
|
|
}
|
|
delegate := list.NewDefaultDelegate()
|
|
delegate.Styles = list.NewDefaultItemStyles(isDark)
|
|
delegate.SetSpacing(0)
|
|
const pickerW = 50
|
|
pickerH := len(models)*delegate.Height() + 2
|
|
if pickerH > 20 {
|
|
pickerH = 20
|
|
}
|
|
l := list.New(items, delegate, pickerW, pickerH)
|
|
l.Title = title
|
|
l.SetShowStatusBar(false)
|
|
l.SetShowHelp(false)
|
|
l.SetShowPagination(false)
|
|
l.SetFilteringEnabled(false)
|
|
l.DisableQuitKeybindings()
|
|
l.Select(selectedIdx)
|
|
return &ModelPickerState{
|
|
List: l,
|
|
Models: models,
|
|
CurrentModel: currentModel,
|
|
}
|
|
}
|
|
|
|
func (m *Model) renderModelPicker() string {
|
|
ps := m.modelPickerState
|
|
if ps == nil {
|
|
return ""
|
|
}
|
|
const maxW = 50
|
|
box := lipgloss.NewStyle().Border(lipgloss.RoundedBorder()).BorderForeground(m.styles.FocusIndicator.GetForeground()).Padding(0, 1).Width(maxW)
|
|
return box.Render(ps.List.View())
|
|
}
|