-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
135 lines (122 loc) · 3.3 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"bufio"
"fmt"
"os/exec"
"strings"
"github.com/charmbracelet/bubbles/spinner"
"github.com/charmbracelet/lipgloss"
tea "github.com/charmbracelet/bubbletea"
)
var (
successStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("10"))
errorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("9"))
infoStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("12"))
boldStyle = lipgloss.NewStyle().Bold(true)
)
type model struct {
spinner spinner.Model
models []string
current int
done bool
failed []string
updating bool
}
func initialModel() model {
s := spinner.New()
s.Spinner = spinner.Dot
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
return model{spinner: s}
}
func (m model) Init() tea.Cmd {
return tea.Batch(m.spinner.Tick, func() tea.Msg {
models, err := getInstalledModels()
if err != nil {
return errorStyle.Render(fmt.Sprintf("Error getting installed models: %v", err))
}
return models
})
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if msg.String() == "q" {
return m, tea.Quit
}
case []string:
m.models = msg
return m, m.updateNext
case spinner.TickMsg:
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
return m, cmd
case string:
if strings.HasPrefix(msg, "Error:") {
m.failed = append(m.failed, m.models[m.current])
}
m.current++
if m.current >= len(m.models) {
m.done = true
return m, tea.Quit
}
return m, m.updateNext
}
return m, nil
}
func (m model) View() string {
if len(m.models) == 0 {
return fmt.Sprintf("%s Fetching installed models...", m.spinner.View())
}
if m.done {
var output strings.Builder
output.WriteString(infoStyle.Render("All model update attempts completed.\n\n"))
if len(m.failed) == 0 {
output.WriteString(successStyle.Render("All models updated successfully!\n"))
} else {
output.WriteString(errorStyle.Render("The following models failed to update:\n"))
for _, model := range m.failed {
output.WriteString(errorStyle.Render(fmt.Sprintf("- %s\n", model)))
}
output.WriteString("\n" + infoStyle.Render("Please check these models manually.\n"))
}
return lipgloss.NewStyle().Margin(0, 2).Render(output.String())
}
return fmt.Sprintf("%s Updating %s... (%d/%d)",
m.spinner.View(),
boldStyle.Render(m.models[m.current]),
m.current+1,
len(m.models))
}
func (m model) updateNext() tea.Msg {
model := m.models[m.current]
cmd := exec.Command("ollama", "pull", model)
output, err := cmd.CombinedOutput()
if err != nil || strings.Contains(string(output), "Error: pull model manifest: file does not exist") {
return fmt.Sprintf("Error: Failed to update %s", model)
}
return fmt.Sprintf("Updated %s successfully", model)
}
func main() {
p := tea.NewProgram(initialModel())
if _, err := p.Run(); err != nil {
fmt.Println("Error running program:", err)
}
}
func getInstalledModels() ([]string, error) {
cmd := exec.Command("ollama", "ls")
output, err := cmd.Output()
if err != nil {
return nil, err
}
var models []string
scanner := bufio.NewScanner(strings.NewReader(string(output)))
// Skip the header line
scanner.Scan()
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
if len(fields) > 0 {
models = append(models, fields[0])
}
}
return models, nil
}