plan_select.go

v0.6.1
Doc Versions Source
1
package tui
2
3
import (
4
	"fmt"
5
	"strings"
6
7
	tea "github.com/charmbracelet/bubbletea"
8
	"github.com/charmbracelet/lipgloss"
9
	"sourcecraft.dev/bigbes/claudio/provider"
10
)
11
12
func (m Model) showPlanPicker(plans []provider.Plan) Model {
13
	m.plans = plans
14
	m.planCursor = 0
15
	// Pre-select the current plan if one is saved.
16
	if pc, ok := m.cfg.Providers[m.selected]; ok && pc.Plan != "" {
17
		for i, p := range plans {
18
			if p.Key == pc.Plan {
19
				m.planCursor = i
20
				break
21
			}
22
		}
23
	}
24
	m.phase = phaseSelectPlan
25
	return m
26
}
27
28
func (m Model) updateSelectPlan(msg tea.Msg) (tea.Model, tea.Cmd) {
29
	switch msg := msg.(type) {
30
	case tea.KeyMsg:
31
		switch msg.String() {
32
		case "ctrl+c", "q":
33
			m.quitting = true
34
			return m, tea.Quit
35
		case "esc":
36
			m.phase = phaseSelect
37
			return m, nil
38
		case "up", "k":
39
			if m.planCursor > 0 {
40
				m.planCursor--
41
			}
42
		case "down", "j":
43
			if m.planCursor < len(m.plans)-1 {
44
				m.planCursor++
45
			}
46
		case "enter":
47
			selected := m.plans[m.planCursor]
48
			pc := m.cfg.Providers[m.selected]
49
			pc.Plan = selected.Key
50
			m.cfg.Providers[m.selected] = pc
51
			// Continue to model picker if available.
52
			if models, ok := provider.StaticModels[m.selected]; ok {
53
				return m.showStaticModelPicker(models), nil
54
			}
55
			m.phase = phaseDone
56
			m.launchAfterConfig = true
57
			return m, tea.Quit
58
		}
59
	}
60
	return m, nil
61
}
62
63
func (m Model) viewSelectPlan() string {
64
	reg := provider.Registry[m.selected]
65
	var b strings.Builder
66
	b.WriteString(logoStyle.Render(logo))
67
	b.WriteString("\n\n")
68
	b.WriteString(promptStyle.Render(fmt.Sprintf(" Select plan for %s", reg.Name)))
69
	b.WriteString("\n\n")
70
71
	for i, plan := range m.plans {
72
		cur := "  "
73
		if i == m.planCursor {
74
			cur = cursorStyle.Render("▸ ")
75
		}
76
		name := plan.Name
77
		if i == m.planCursor {
78
			name = cursorStyle.Render(name)
79
		}
80
		desc := descStyle.Render("      " + plan.Description)
81
		fmt.Fprintf(&b, " %s%s\n%s\n", cur, name, desc)
82
	}
83
84
	b.WriteString("\n")
85
	b.WriteString(hintStyle.Render(" ↑/↓ navigate • enter select • esc back"))
86
87
	content := b.String()
88
	if m.width > 0 && m.height > 0 {
89
		return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, content)
90
	}
91
	return content
92
}
93
94
func (m Model) showStaticModelPicker(models []provider.StaticModel) Model {
95
	var familyOrder []string
96
	familyMap := make(map[string][]PickerItem)
97
	seen := make(map[string]bool)
98
	for _, sm := range models {
99
		if !seen[sm.Family] {
100
			seen[sm.Family] = true
101
			familyOrder = append(familyOrder, sm.Family)
102
		}
103
		familyMap[sm.Family] = append(familyMap[sm.Family], PickerItem{ID: sm.ID, Name: sm.Name, ContextLength: 0})
104
	}
105
	m.phase = phaseSelectModel
106
	m.pickerProvider = m.selected
107
	m.families = familyOrder
108
	m.familyModels = familyMap
109
	m.preSelectModel()
110
	return m
111
}
112

Source Files