wip: refactoring tui
This commit is contained in:
@@ -3,7 +3,6 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"log/slog"
|
||||
|
||||
@@ -20,20 +19,14 @@ import (
|
||||
type App struct {
|
||||
Client *client.ClientWithResponses
|
||||
Events *client.Client
|
||||
Provider *client.ProviderInfo
|
||||
Model *client.ProviderModel
|
||||
Session *client.SessionInfo
|
||||
Messages []client.MessageInfo
|
||||
|
||||
LogsOLD any // TODO: Define LogService interface when needed
|
||||
HistoryOLD any // TODO: Define HistoryService interface when needed
|
||||
PermissionsOLD any // TODO: Define PermissionService interface when needed
|
||||
Status status.Service
|
||||
Status status.Service
|
||||
|
||||
PrimaryAgentOLD AgentService
|
||||
|
||||
watcherCancelFuncs []context.CancelFunc
|
||||
cancelFuncsMutex sync.Mutex
|
||||
watcherWG sync.WaitGroup
|
||||
|
||||
// UI state
|
||||
filepickerOpen bool
|
||||
completionDialogOpen bool
|
||||
@@ -70,13 +63,9 @@ func New(ctx context.Context) (*App, error) {
|
||||
Client: httpClient,
|
||||
Events: eventClient,
|
||||
Session: &client.SessionInfo{},
|
||||
Messages: []client.MessageInfo{},
|
||||
PrimaryAgentOLD: agentBridge,
|
||||
Status: status.GetService(),
|
||||
|
||||
// TODO: These services need API endpoints:
|
||||
LogsOLD: nil, // logging.GetService(),
|
||||
HistoryOLD: nil, // history.GetService(),
|
||||
PermissionsOLD: nil, // permission.GetService(),
|
||||
}
|
||||
|
||||
// Initialize theme based on configuration
|
||||
@@ -128,13 +117,12 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At
|
||||
go a.Client.PostSessionChatWithResponse(ctx, client.PostSessionChatJSONRequestBody{
|
||||
SessionID: a.Session.Id,
|
||||
Parts: parts,
|
||||
ProviderID: "anthropic",
|
||||
ModelID: "claude-sonnet-4-20250514",
|
||||
ProviderID: a.Provider.Id,
|
||||
ModelID: a.Model.Id,
|
||||
})
|
||||
|
||||
// The actual response will come through SSE
|
||||
// For now, just return success
|
||||
|
||||
return tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
@@ -169,6 +157,22 @@ func (a *App) ListMessages(ctx context.Context, sessionId string) ([]client.Mess
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (a *App) ListProviders(ctx context.Context) ([]client.ProviderInfo, error) {
|
||||
resp, err := a.Client.PostProviderListWithResponse(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode() != 200 {
|
||||
return nil, fmt.Errorf("failed to list sessions: %d", resp.StatusCode())
|
||||
}
|
||||
if resp.JSON200 == nil {
|
||||
return []client.ProviderInfo{}, nil
|
||||
}
|
||||
|
||||
providers := *resp.JSON200
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
// initTheme sets the application theme based on the configuration
|
||||
func (app *App) initTheme() {
|
||||
cfg := config.Get()
|
||||
@@ -207,11 +211,5 @@ func (app *App) SetCompletionDialogOpen(open bool) {
|
||||
|
||||
// Shutdown performs a clean shutdown of the application
|
||||
func (app *App) Shutdown() {
|
||||
// Cancel all watcher goroutines
|
||||
app.cancelFuncsMutex.Lock()
|
||||
for _, cancel := range app.watcherCancelFuncs {
|
||||
cancel()
|
||||
}
|
||||
app.cancelFuncsMutex.Unlock()
|
||||
app.watcherWG.Wait()
|
||||
// TODO: cleanup?
|
||||
}
|
||||
|
||||
@@ -17,33 +17,6 @@ func NewAgentServiceBridge(client *client.ClientWithResponses) *AgentServiceBrid
|
||||
return &AgentServiceBridge{client: client}
|
||||
}
|
||||
|
||||
// Run sends a message to the chat API
|
||||
func (a *AgentServiceBridge) Run(ctx context.Context, sessionID string, text string, attachments ...Attachment) (string, error) {
|
||||
// TODO: Handle attachments when API supports them
|
||||
if len(attachments) > 0 {
|
||||
// For now, ignore attachments
|
||||
// return "", fmt.Errorf("attachments not supported yet")
|
||||
}
|
||||
|
||||
part := client.MessagePart{}
|
||||
part.FromMessagePartText(client.MessagePartText{
|
||||
Type: "text",
|
||||
Text: text,
|
||||
})
|
||||
parts := []client.MessagePart{part}
|
||||
|
||||
go a.client.PostSessionChatWithResponse(ctx, client.PostSessionChatJSONRequestBody{
|
||||
SessionID: sessionID,
|
||||
Parts: parts,
|
||||
ProviderID: "anthropic",
|
||||
ModelID: "claude-sonnet-4-20250514",
|
||||
})
|
||||
|
||||
// The actual response will come through SSE
|
||||
// For now, just return success
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Cancel cancels the current generation - NOT IMPLEMENTED IN API YET
|
||||
func (a *AgentServiceBridge) Cancel(sessionID string) error {
|
||||
// TODO: Not implemented in TypeScript API yet
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
// AgentService defines the interface for agent operations
|
||||
type AgentService interface {
|
||||
Run(ctx context.Context, sessionID string, text string, attachments ...Attachment) (string, error)
|
||||
Cancel(sessionID string) error
|
||||
IsBusy() bool
|
||||
IsSessionBusy(sessionID string) bool
|
||||
|
||||
@@ -335,7 +335,10 @@ func (m *statusCmp) projectDiagnostics() string {
|
||||
|
||||
func (m statusCmp) model() string {
|
||||
t := theme.CurrentTheme()
|
||||
model := "Claude Sonnet 4" // models.SupportedModels[coder.Model]
|
||||
model := "None"
|
||||
if m.app.Model != nil {
|
||||
model = *m.app.Model.Name
|
||||
}
|
||||
|
||||
return styles.Padded().
|
||||
Background(t.Secondary()).
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package dialog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/sst/opencode/internal/config"
|
||||
"github.com/sst/opencode/internal/tui/app"
|
||||
"github.com/sst/opencode/internal/tui/layout"
|
||||
"github.com/sst/opencode/internal/tui/styles"
|
||||
"github.com/sst/opencode/internal/tui/theme"
|
||||
"github.com/sst/opencode/internal/tui/util"
|
||||
"github.com/sst/opencode/pkg/client"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -16,24 +20,25 @@ const (
|
||||
maxDialogWidth = 40
|
||||
)
|
||||
|
||||
// ModelSelectedMsg is sent when a model is selected
|
||||
type ModelSelectedMsg struct {
|
||||
// Model models.Model
|
||||
}
|
||||
|
||||
// CloseModelDialogMsg is sent when a model is selected
|
||||
type CloseModelDialogMsg struct{}
|
||||
type CloseModelDialogMsg struct {
|
||||
Provider *client.ProviderInfo
|
||||
Model *client.ProviderModel
|
||||
}
|
||||
|
||||
// ModelDialog interface for the model selection dialog
|
||||
type ModelDialog interface {
|
||||
tea.Model
|
||||
layout.Bindings
|
||||
|
||||
SetProviders(providers []client.ProviderInfo)
|
||||
}
|
||||
|
||||
type modelDialogCmp struct {
|
||||
// models []models.Model
|
||||
// provider models.ModelProvider
|
||||
// availableProviders []models.ModelProvider
|
||||
app *app.App
|
||||
availableProviders []client.ProviderInfo
|
||||
provider client.ProviderInfo
|
||||
model *client.ProviderModel
|
||||
|
||||
selectedIdx int
|
||||
width int
|
||||
@@ -100,10 +105,28 @@ var modelKeys = modelKeyMap{
|
||||
}
|
||||
|
||||
func (m *modelDialogCmp) Init() tea.Cmd {
|
||||
m.setupModels()
|
||||
// cfg := config.Get()
|
||||
// modelInfo := GetSelectedModel(cfg)
|
||||
// m.availableProviders = getEnabledProviders(cfg)
|
||||
// m.hScrollPossible = len(m.availableProviders) > 1
|
||||
|
||||
// m.provider = modelInfo.Provider
|
||||
// m.hScrollOffset = findProviderIndex(m.availableProviders, m.provider)
|
||||
|
||||
// m.setupModelsForProvider(m.provider)
|
||||
|
||||
m.availableProviders, _ = m.app.ListProviders(context.Background())
|
||||
m.hScrollOffset = 0
|
||||
m.hScrollPossible = len(m.availableProviders) > 1
|
||||
m.provider = m.availableProviders[m.hScrollOffset]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *modelDialogCmp) SetProviders(providers []client.ProviderInfo) {
|
||||
m.availableProviders = providers
|
||||
}
|
||||
|
||||
func (m *modelDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
@@ -121,7 +144,7 @@ func (m *modelDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.switchProvider(1)
|
||||
}
|
||||
case key.Matches(msg, modelKeys.Enter):
|
||||
// return m, util.CmdHandler(ModelSelectedMsg{Model: m.models[m.selectedIdx]})
|
||||
return m, util.CmdHandler(CloseModelDialogMsg{Provider: &m.provider, Model: &m.provider.Models[m.selectedIdx]})
|
||||
case key.Matches(msg, modelKeys.Escape):
|
||||
return m, util.CmdHandler(CloseModelDialogMsg{})
|
||||
}
|
||||
@@ -138,8 +161,8 @@ func (m *modelDialogCmp) moveSelectionUp() {
|
||||
if m.selectedIdx > 0 {
|
||||
m.selectedIdx--
|
||||
} else {
|
||||
// m.selectedIdx = len(m.models) - 1
|
||||
// m.scrollOffset = max(0, len(m.models)-numVisibleModels)
|
||||
m.selectedIdx = len(m.provider.Models) - 1
|
||||
m.scrollOffset = max(0, len(m.provider.Models)-numVisibleModels)
|
||||
}
|
||||
|
||||
// Keep selection visible
|
||||
@@ -150,12 +173,12 @@ func (m *modelDialogCmp) moveSelectionUp() {
|
||||
|
||||
// moveSelectionDown moves the selection down or wraps to top
|
||||
func (m *modelDialogCmp) moveSelectionDown() {
|
||||
// if m.selectedIdx < len(m.models)-1 {
|
||||
// m.selectedIdx++
|
||||
// } else {
|
||||
// m.selectedIdx = 0
|
||||
// m.scrollOffset = 0
|
||||
// }
|
||||
if m.selectedIdx < len(m.provider.Models)-1 {
|
||||
m.selectedIdx++
|
||||
} else {
|
||||
m.selectedIdx = 0
|
||||
m.scrollOffset = 0
|
||||
}
|
||||
|
||||
// Keep selection visible
|
||||
if m.selectedIdx >= m.scrollOffset+numVisibleModels {
|
||||
@@ -167,16 +190,16 @@ func (m *modelDialogCmp) switchProvider(offset int) {
|
||||
newOffset := m.hScrollOffset + offset
|
||||
|
||||
// Ensure we stay within bounds
|
||||
// if newOffset < 0 {
|
||||
// newOffset = len(m.availableProviders) - 1
|
||||
// }
|
||||
// if newOffset >= len(m.availableProviders) {
|
||||
// newOffset = 0
|
||||
// }
|
||||
if newOffset < 0 {
|
||||
newOffset = len(m.availableProviders) - 1
|
||||
}
|
||||
if newOffset >= len(m.availableProviders) {
|
||||
newOffset = 0
|
||||
}
|
||||
|
||||
m.hScrollOffset = newOffset
|
||||
// m.provider = m.availableProviders[m.hScrollOffset]
|
||||
// m.setupModelsForProvider(m.provider)
|
||||
m.provider = m.availableProviders[m.hScrollOffset]
|
||||
m.setupModelsForProvider(m.provider.Id)
|
||||
}
|
||||
|
||||
func (m *modelDialogCmp) View() string {
|
||||
@@ -184,33 +207,32 @@ func (m *modelDialogCmp) View() string {
|
||||
baseStyle := styles.BaseStyle()
|
||||
|
||||
// Capitalize first letter of provider name
|
||||
// providerName := strings.ToUpper(string(m.provider)[:1]) + string(m.provider[1:])
|
||||
// title := baseStyle.
|
||||
// Foreground(t.Primary()).
|
||||
// Bold(true).
|
||||
// Width(maxDialogWidth).
|
||||
// Padding(0, 0, 1).
|
||||
// Render(fmt.Sprintf("Select %s Model", providerName))
|
||||
title := baseStyle.
|
||||
Foreground(t.Primary()).
|
||||
Bold(true).
|
||||
Width(maxDialogWidth).
|
||||
Padding(0, 0, 1).
|
||||
Render(fmt.Sprintf("Select %s Model", m.provider.Name))
|
||||
|
||||
// Render visible models
|
||||
// endIdx := min(m.scrollOffset+numVisibleModels, len(m.models))
|
||||
// modelItems := make([]string, 0, endIdx-m.scrollOffset)
|
||||
//
|
||||
// for i := m.scrollOffset; i < endIdx; i++ {
|
||||
// itemStyle := baseStyle.Width(maxDialogWidth)
|
||||
// if i == m.selectedIdx {
|
||||
// itemStyle = itemStyle.Background(t.Primary()).
|
||||
// Foreground(t.Background()).Bold(true)
|
||||
// }
|
||||
// modelItems = append(modelItems, itemStyle.Render(m.models[i].Name))
|
||||
// }
|
||||
endIdx := min(m.scrollOffset+numVisibleModels, len(m.provider.Models))
|
||||
modelItems := make([]string, 0, endIdx-m.scrollOffset)
|
||||
|
||||
for i := m.scrollOffset; i < endIdx; i++ {
|
||||
itemStyle := baseStyle.Width(maxDialogWidth)
|
||||
if i == m.selectedIdx {
|
||||
itemStyle = itemStyle.Background(t.Primary()).
|
||||
Foreground(t.Background()).Bold(true)
|
||||
}
|
||||
modelItems = append(modelItems, itemStyle.Render(*m.provider.Models[i].Name))
|
||||
}
|
||||
|
||||
scrollIndicator := m.getScrollIndicators(maxDialogWidth)
|
||||
|
||||
content := lipgloss.JoinVertical(
|
||||
lipgloss.Left,
|
||||
// title,
|
||||
// baseStyle.Width(maxDialogWidth).Render(lipgloss.JoinVertical(lipgloss.Left, modelItems...)),
|
||||
title,
|
||||
baseStyle.Width(maxDialogWidth).Render(lipgloss.JoinVertical(lipgloss.Left, modelItems...)),
|
||||
scrollIndicator,
|
||||
)
|
||||
|
||||
@@ -225,22 +247,22 @@ func (m *modelDialogCmp) View() string {
|
||||
func (m *modelDialogCmp) getScrollIndicators(maxWidth int) string {
|
||||
var indicator string
|
||||
|
||||
// if len(m.models) > numVisibleModels {
|
||||
// if m.scrollOffset > 0 {
|
||||
// indicator += "↑ "
|
||||
// }
|
||||
// if m.scrollOffset+numVisibleModels < len(m.models) {
|
||||
// indicator += "↓ "
|
||||
// }
|
||||
// }
|
||||
if len(m.provider.Models) > numVisibleModels {
|
||||
if m.scrollOffset > 0 {
|
||||
indicator += "↑ "
|
||||
}
|
||||
if m.scrollOffset+numVisibleModels < len(m.provider.Models) {
|
||||
indicator += "↓ "
|
||||
}
|
||||
}
|
||||
|
||||
if m.hScrollPossible {
|
||||
if m.hScrollOffset > 0 {
|
||||
indicator = "← " + indicator
|
||||
}
|
||||
// if m.hScrollOffset < len(m.availableProviders)-1 {
|
||||
// indicator += "→"
|
||||
// }
|
||||
if m.hScrollOffset < len(m.availableProviders)-1 {
|
||||
indicator += "→"
|
||||
}
|
||||
}
|
||||
|
||||
if indicator == "" {
|
||||
@@ -262,70 +284,26 @@ func (m *modelDialogCmp) BindingKeys() []key.Binding {
|
||||
return layout.KeyMapToSlice(modelKeys)
|
||||
}
|
||||
|
||||
func (m *modelDialogCmp) setupModels() {
|
||||
// cfg := config.Get()
|
||||
// modelInfo := GetSelectedModel(cfg)
|
||||
// m.availableProviders = getEnabledProviders(cfg)
|
||||
// m.hScrollPossible = len(m.availableProviders) > 1
|
||||
//
|
||||
// m.provider = modelInfo.Provider
|
||||
// m.hScrollOffset = findProviderIndex(m.availableProviders, m.provider)
|
||||
//
|
||||
// m.setupModelsForProvider(m.provider)
|
||||
}
|
||||
|
||||
func GetSelectedModel(cfg *config.Config) string {
|
||||
return "Claude Sonnet 4"
|
||||
// agentCfg := cfg.Agents[config.AgentPrimary]
|
||||
// selectedModelId := agentCfg.Model
|
||||
// return models.SupportedModels[selectedModelId]
|
||||
}
|
||||
|
||||
func getEnabledProviders(cfg *config.Config) []string {
|
||||
return []string{"anthropic", "openai", "google"}
|
||||
// var providers []models.ModelProvider
|
||||
// for providerId, provider := range cfg.Providers {
|
||||
// if !provider.Disabled {
|
||||
// providers = append(providers, providerId)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Sort by provider popularity
|
||||
// slices.SortFunc(providers, func(a, b models.ModelProvider) int {
|
||||
// rA := models.ProviderPopularity[a]
|
||||
// rB := models.ProviderPopularity[b]
|
||||
//
|
||||
// // models not included in popularity ranking default to last
|
||||
// if rA == 0 {
|
||||
// rA = 999
|
||||
// }
|
||||
// if rB == 0 {
|
||||
// rB = 999
|
||||
// }
|
||||
// return rA - rB
|
||||
// })
|
||||
// return providers
|
||||
}
|
||||
|
||||
// findProviderIndex returns the index of the provider in the list, or -1 if not found
|
||||
func findProviderIndex(providers []string, provider string) int {
|
||||
for i, p := range providers {
|
||||
if p == provider {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
// func findProviderIndex(providers []string, provider string) int {
|
||||
// for i, p := range providers {
|
||||
// if p == provider {
|
||||
// return i
|
||||
// }
|
||||
// }
|
||||
// return -1
|
||||
// }
|
||||
|
||||
func (m *modelDialogCmp) setupModelsForProvider(_ string) {
|
||||
m.selectedIdx = 0
|
||||
m.scrollOffset = 0
|
||||
|
||||
func (m *modelDialogCmp) setupModelsForProvider(provider string) {
|
||||
// cfg := config.Get()
|
||||
// agentCfg := cfg.Agents[config.AgentPrimary]
|
||||
// selectedModelId := agentCfg.Model
|
||||
|
||||
// m.provider = provider
|
||||
// m.models = getModelsForProvider(provider)
|
||||
m.selectedIdx = 0
|
||||
m.scrollOffset = 0
|
||||
|
||||
// Try to select the current model if it belongs to this provider
|
||||
// if provider == models.SupportedModels[selectedModelId].Provider {
|
||||
@@ -342,28 +320,8 @@ func (m *modelDialogCmp) setupModelsForProvider(provider string) {
|
||||
// }
|
||||
}
|
||||
|
||||
func getModelsForProvider(provider string) []string {
|
||||
return []string{"Claude Sonnet 4"}
|
||||
// var providerModels []models.Model
|
||||
// for _, model := range models.SupportedModels {
|
||||
// if model.Provider == provider {
|
||||
// providerModels = append(providerModels, model)
|
||||
// }
|
||||
// }
|
||||
|
||||
// reverse alphabetical order (if llm naming was consistent latest would appear first)
|
||||
// slices.SortFunc(providerModels, func(a, b models.Model) int {
|
||||
// if a.Name > b.Name {
|
||||
// return -1
|
||||
// } else if a.Name < b.Name {
|
||||
// return 1
|
||||
// }
|
||||
// return 0
|
||||
// })
|
||||
|
||||
// return providerModels
|
||||
}
|
||||
|
||||
func NewModelDialogCmp() ModelDialog {
|
||||
return &modelDialogCmp{}
|
||||
func NewModelDialogCmp(app *app.App) ModelDialog {
|
||||
return &modelDialogCmp{
|
||||
app: app,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,15 @@ import (
|
||||
)
|
||||
|
||||
type SessionSelectedMsg = *client.SessionInfo
|
||||
type ModelSelectedMsg struct {
|
||||
Provider client.ProviderInfo
|
||||
Model client.ProviderModel
|
||||
}
|
||||
|
||||
type SessionClearedMsg struct{}
|
||||
type CompactSessionMsg struct{}
|
||||
|
||||
// TODO: remove
|
||||
type StateUpdatedMsg struct {
|
||||
State map[string]any
|
||||
}
|
||||
|
||||
@@ -168,16 +168,27 @@ func (a appModel) Init() tea.Cmd {
|
||||
return dialog.ShowInitDialogMsg{Show: shouldShow}
|
||||
})
|
||||
|
||||
cmds = append(cmds, func() tea.Msg {
|
||||
providers, _ := a.app.ListProviders(context.Background())
|
||||
return state.ModelSelectedMsg{Provider: providers[0], Model: providers[0].Models[0]}
|
||||
})
|
||||
|
||||
return tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (a appModel) updateAllPages(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmds []tea.Cmd
|
||||
var cmd tea.Cmd
|
||||
|
||||
for id := range a.pages {
|
||||
a.pages[id], cmd = a.pages[id].Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
s, cmd := a.status.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
a.status = s.(core.StatusCmp)
|
||||
|
||||
return a, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
@@ -201,12 +212,10 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
for i, m := range a.app.Messages {
|
||||
if m.Id == msg.Properties.Info.Id {
|
||||
a.app.Messages[i] = msg.Properties.Info
|
||||
slog.Debug("Updated message", "message", msg.Properties.Info)
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: nil})
|
||||
}
|
||||
}
|
||||
a.app.Messages = append(a.app.Messages, msg.Properties.Info)
|
||||
slog.Debug("Appended message", "message", msg.Properties.Info)
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: nil})
|
||||
}
|
||||
|
||||
@@ -287,6 +296,19 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
a.app.Messages, _ = a.app.ListMessages(context.Background(), msg.Id)
|
||||
return a.updateAllPages(msg)
|
||||
|
||||
case dialog.CloseModelDialogMsg:
|
||||
a.showModelDialog = false
|
||||
slog.Debug("closing model dialog", "msg", msg)
|
||||
if msg.Provider != nil && msg.Model != nil {
|
||||
return a, util.CmdHandler(state.ModelSelectedMsg{Provider: *msg.Provider, Model: *msg.Model})
|
||||
}
|
||||
return a, nil
|
||||
|
||||
case state.ModelSelectedMsg:
|
||||
a.app.Provider = &msg.Provider
|
||||
a.app.Model = &msg.Model
|
||||
return a.updateAllPages(msg)
|
||||
|
||||
case dialog.CloseCommandDialogMsg:
|
||||
a.showCommandDialog = false
|
||||
return a, nil
|
||||
@@ -309,24 +331,6 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
status.Info("Theme changed to: " + msg.ThemeName)
|
||||
return a, cmd
|
||||
|
||||
case dialog.CloseModelDialogMsg:
|
||||
a.showModelDialog = false
|
||||
return a, nil
|
||||
|
||||
case dialog.ModelSelectedMsg:
|
||||
a.showModelDialog = false
|
||||
|
||||
// TODO: Agent model update not implemented in API yet
|
||||
// model, err := a.app.PrimaryAgent.Update(config.AgentPrimary, msg.Model.ID)
|
||||
// if err != nil {
|
||||
// status.Error(err.Error())
|
||||
// return a, nil
|
||||
// }
|
||||
|
||||
// status.Info(fmt.Sprintf("Model changed to %s", model.Name))
|
||||
status.Info("Model selection not implemented in API yet")
|
||||
return a, nil
|
||||
|
||||
case dialog.ShowInitDialogMsg:
|
||||
a.showInitDialog = msg.Show
|
||||
return a, nil
|
||||
@@ -476,6 +480,18 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
a.showThemeDialog = false
|
||||
a.showFilepicker = false
|
||||
|
||||
// Load providers and show the dialog
|
||||
providers, err := a.app.ListProviders(context.Background())
|
||||
if err != nil {
|
||||
status.Error(err.Error())
|
||||
return a, nil
|
||||
}
|
||||
if len(providers) == 0 {
|
||||
status.Warn("No providers available")
|
||||
return a, nil
|
||||
}
|
||||
a.modelDialog.SetProviders(providers)
|
||||
|
||||
a.showModelDialog = true
|
||||
return a, nil
|
||||
}
|
||||
@@ -907,7 +923,7 @@ func New(app *app.App) tea.Model {
|
||||
quit: dialog.NewQuitCmp(),
|
||||
sessionDialog: dialog.NewSessionDialogCmp(),
|
||||
commandDialog: dialog.NewCommandDialogCmp(),
|
||||
modelDialog: dialog.NewModelDialogCmp(),
|
||||
modelDialog: dialog.NewModelDialogCmp(app),
|
||||
permissions: dialog.NewPermissionDialogCmp(),
|
||||
initDialog: dialog.NewInitDialogCmp(),
|
||||
themeDialog: dialog.NewThemeDialogCmp(),
|
||||
|
||||
Reference in New Issue
Block a user