diff --git a/internal/ui/dialog/actions.go b/internal/ui/dialog/actions.go index 2776d886d49d979fd7673fb830dfa9d9a11f9006..5c96f1c96111222a270a4529d39bfaac4162205c 100644 --- a/internal/ui/dialog/actions.go +++ b/internal/ui/dialog/actions.go @@ -36,9 +36,10 @@ type ActionSelectSession struct { // ActionSelectModel is a message indicating a model has been selected. type ActionSelectModel struct { - Provider catwalk.Provider - Model config.SelectedModel - ModelType config.SelectedModelType + Provider catwalk.Provider + Model config.SelectedModel + ModelType config.SelectedModelType + ReAuthenticate bool } // Messages for commands diff --git a/internal/ui/dialog/models.go b/internal/ui/dialog/models.go index 2f729e19995790fc1bb57fbea4b80191195df8da..d77d8952fc1d9a413d35cc3a4c3ae315e0881c60 100644 --- a/internal/ui/dialog/models.go +++ b/internal/ui/dialog/models.go @@ -70,7 +70,7 @@ const ( // ModelsID is the identifier for the model selection dialog. const ModelsID = "models" -const defaultModelsDialogMaxWidth = 70 +const defaultModelsDialogMaxWidth = 73 // Models represents a model selection dialog. type Models struct { @@ -84,6 +84,7 @@ type Models struct { Tab key.Binding UpDown key.Binding Select key.Binding + Edit key.Binding Next key.Binding Previous key.Binding Close key.Binding @@ -124,6 +125,10 @@ func NewModels(com *common.Common, isOnboarding bool) (*Models, error) { key.WithKeys("enter", "ctrl+y"), key.WithHelp("enter", "confirm"), ) + m.keyMap.Edit = key.NewBinding( + key.WithKeys("ctrl+e"), + key.WithHelp("ctrl+e", "edit"), + ) m.keyMap.UpDown = key.NewBinding( key.WithKeys("up", "down"), key.WithHelp("↑/↓", "choose"), @@ -181,7 +186,7 @@ func (m *Models) HandleMsg(msg tea.Msg) Action { } m.list.SelectNext() m.list.ScrollToSelected() - case key.Matches(msg, m.keyMap.Select): + case key.Matches(msg, m.keyMap.Select, m.keyMap.Edit): selectedItem := m.list.SelectedItem() if selectedItem == nil { break @@ -192,10 +197,13 @@ func (m *Models) HandleMsg(msg tea.Msg) Action { break } + isEdit := key.Matches(msg, m.keyMap.Edit) + return ActionSelectModel{ - Provider: modelItem.prov, - Model: modelItem.SelectedModel(), - ModelType: modelItem.SelectedModelType(), + Provider: modelItem.prov, + Model: modelItem.SelectedModel(), + ModelType: modelItem.SelectedModelType(), + ReAuthenticate: isEdit, } case key.Matches(msg, m.keyMap.Tab): if m.isOnboarding { @@ -309,27 +317,35 @@ func (m *Models) ShortHelp() []key.Binding { m.keyMap.Select, } } - return []key.Binding{ + h := []key.Binding{ m.keyMap.UpDown, m.keyMap.Tab, m.keyMap.Select, - m.keyMap.Close, } + if m.isSelectedConfigured() { + h = append(h, m.keyMap.Edit) + } + h = append(h, m.keyMap.Close) + return h } // FullHelp returns the full help view. func (m *Models) FullHelp() [][]key.Binding { - return [][]key.Binding{ - { - m.keyMap.Select, - m.keyMap.Next, - m.keyMap.Previous, - m.keyMap.Tab, - }, - { - m.keyMap.Close, - }, + return [][]key.Binding{m.ShortHelp()} +} + +func (m *Models) isSelectedConfigured() bool { + selectedItem := m.list.SelectedItem() + if selectedItem == nil { + return false + } + modelItem, ok := selectedItem.(*ModelItem) + if !ok { + return false } + providerID := string(modelItem.prov.ID) + _, isConfigured := m.com.Config().Providers.Get(providerID) + return isConfigured } // setProviderItems sets the provider items in the list. diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index d4f2d4f7309d7f1f4e68546b96c49009bf6f8624..1088212a91ef0810bce7c5316a1bb33cad204b46 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -1266,11 +1266,11 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd { ) // Attempt to import GitHub Copilot tokens from VSCode if available. - if isCopilot && !isConfigured() { + if isCopilot && !isConfigured() && !msg.ReAuthenticate { m.com.Config().ImportCopilot() } - if !isConfigured() { + if !isConfigured() || msg.ReAuthenticate { m.dialog.CloseDialog(dialog.ModelsID) if cmd := m.openAuthenticationDialog(msg.Provider, msg.Model, msg.ModelType); cmd != nil { cmds = append(cmds, cmd)