model.go

v0.6.2
Doc Versions Source
1
package tui
2
3
import (
4
	"strings"
5
6
	tea "github.com/charmbracelet/bubbletea"
7
	"github.com/charmbracelet/lipgloss"
8
	"sourcecraft.dev/bigbes/claudio/config"
9
	"sourcecraft.dev/bigbes/claudio/provider"
10
)
11
12
func (m Model) Cfg() *config.Config     { return m.cfg }
13
func (m Model) Quitting() bool          { return m.quitting }
14
func (m Model) LaunchAfterConfig() bool { return m.launchAfterConfig }
15
16
func (m Model) Init() tea.Cmd { return nil }
17
18
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
19
	if msg, ok := msg.(tea.WindowSizeMsg); ok {
20
		m.width = msg.Width
21
		m.height = msg.Height
22
	}
23
	switch m.phase {
24
	case phaseSelect:
25
		return m.updateSelect(msg)
26
	case phaseInputKey:
27
		return m.updateInput(msg)
28
	case phaseSelectPlan:
29
		return m.updateSelectPlan(msg)
30
	case phaseLoadingModels:
31
		return m.updateLoadingModels(msg)
32
	case phaseSelectModel:
33
		return m.updateSelectModel(msg)
34
	case phaseFilePicker:
35
		return m.updateFilePicker(msg)
36
	default:
37
		return m, tea.Quit
38
	}
39
}
40
41
func (m Model) View() string {
42
	switch m.phase {
43
	case phaseSelect:
44
		return m.viewSelect()
45
	case phaseInputKey:
46
		return m.viewInput()
47
	case phaseSelectPlan:
48
		return m.viewSelectPlan()
49
	case phaseLoadingModels:
50
		return m.viewLoadingModels()
51
	case phaseSelectModel:
52
		return m.viewSelectModel()
53
	case phaseFilePicker:
54
		return m.viewFilePicker()
55
	default:
56
		return ""
57
	}
58
}
59
60
func (m *Model) recomputeFilter() {
61
	query := strings.ToLower(m.filterInput.Value())
62
	m.filteredIdx = nil
63
	for i, e := range m.entries {
64
		if query == "" || strings.Contains(strings.ToLower(e.Name), query) || strings.Contains(strings.ToLower(e.Key), query) {
65
			m.filteredIdx = append(m.filteredIdx, i)
66
		}
67
	}
68
	if m.cursor >= len(m.filteredIdx) {
69
		m.cursor = max(0, len(m.filteredIdx)-1)
70
	}
71
}
72
73
// preSelectModel positions cursors on the currently active model.
74
func (m *Model) preSelectModel() {
75
	m.familyCursor = 0
76
	m.modelCursor = 0
77
	m.modelFocus = false
78
79
	pc := m.cfg.Providers[m.pickerProvider]
80
	current := pc.Model
81
	if current == "" {
82
		if reg, ok := provider.Registry[m.pickerProvider]; ok {
83
			current = reg.Model
84
		}
85
	}
86
	for fi, fam := range m.families {
87
		for mi, item := range m.familyModels[fam] {
88
			if item.ID == current {
89
				m.familyCursor = fi
90
				m.modelCursor = mi
91
				return
92
			}
93
		}
94
	}
95
}
96
97
func (m Model) pickerLabel() string {
98
	if reg, ok := provider.Registry[m.pickerProvider]; ok {
99
		return reg.Name
100
	}
101
	return m.pickerProvider
102
}
103
104
func (m Model) viewLoadingModels() string {
105
	label := m.pickerLabel()
106
	var b strings.Builder
107
	b.WriteString(logoStyle.Render(logo))
108
	b.WriteString("\n\n")
109
	b.WriteString(promptStyle.Render(" Fetching available " + label + " models..."))
110
	content := b.String()
111
	if m.width > 0 && m.height > 0 {
112
		return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, content)
113
	}
114
	return content
115
}
116

Source Files