From 3362d6bd6ed7dc87a2656defaa12070c60050b04 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Thu, 9 Oct 2025 15:26:43 -0300 Subject: [PATCH] fix(ui): improvements Signed-off-by: Carlos Alexandro Becker --- internal/llm/agent/mcp-tools.go | 12 ++- .../components/dialogs/commands/commands.go | 83 +++++++++++-------- 2 files changed, 52 insertions(+), 43 deletions(-) diff --git a/internal/llm/agent/mcp-tools.go b/internal/llm/agent/mcp-tools.go index 599e261d5fdea34755f8623a07e35e0fe8d3070e..0b61e9b4f463fec2440653aaa82088129b42e8fe 100644 --- a/internal/llm/agent/mcp-tools.go +++ b/internal/llm/agent/mcp-tools.go @@ -336,13 +336,11 @@ func doGetMCPTools(ctx context.Context, permissions permission.Service, cfg *con updateMcpTools(name, tools) updateMcpPrompts(name, prompts) mcpClients.Set(name, c) - updateMCPState( - name, MCPStateConnected, nil, c, - MCPCounts{ - Tools: len(tools), - Prompts: len(prompts), - }, - ) + counts := MCPCounts{ + Tools: len(tools), + Prompts: len(prompts), + } + updateMCPState(name, MCPStateConnected, nil, c, counts) }(name, m) } wg.Wait() diff --git a/internal/tui/components/dialogs/commands/commands.go b/internal/tui/components/dialogs/commands/commands.go index 5e9d1fa1b2e47b8284bbb65cd0a48d3230049a08..245f517f2868026e92b55ced42c2a3a9502820d4 100644 --- a/internal/tui/components/dialogs/commands/commands.go +++ b/internal/tui/components/dialogs/commands/commands.go @@ -29,8 +29,12 @@ const ( defaultWidth int = 70 ) +type CommandType uint + +func (c CommandType) String() string { return []string{"System", "User", "MCP"}[c] } + const ( - SystemCommands int = iota + SystemCommands CommandType = iota UserCommands MCPPrompts ) @@ -59,10 +63,10 @@ type commandDialogCmp struct { commandList listModel keyMap CommandsDialogKeyMap help help.Model - commandType int // SystemCommands, UserCommands, or MCPPrompts - userCommands []Command // User-defined commands - mcpPrompts []Command // MCP prompts - sessionID string // Current session ID + selected CommandType // Selected SystemCommands, UserCommands, or MCPPrompts + userCommands []Command // User-defined commands + mcpPrompts []Command // MCP prompts + sessionID string // Current session ID ctx context.Context cancel context.CancelFunc } @@ -110,7 +114,7 @@ func NewCommandDialog(sessionID string) CommandsDialog { width: defaultWidth, keyMap: DefaultCommandsDialogKeyMap(), help: help, - commandType: SystemCommands, + selected: SystemCommands, sessionID: sessionID, } } @@ -126,7 +130,7 @@ func (c *commandDialogCmp) Init() tea.Cmd { // Subscribe to MCP events c.ctx, c.cancel = context.WithCancel(context.Background()) return tea.Batch( - c.SetCommandType(c.commandType), + c.SetCommandType(c.selected), c.subscribeMCPEvents(), ) } @@ -149,7 +153,7 @@ func (c *commandDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { c.wWidth = msg.Width c.wHeight = msg.Height return c, tea.Batch( - c.SetCommandType(c.commandType), + c.SetCommandType(c.selected), c.commandList.SetSize(c.listWidth(), c.listHeight()), ) case pubsub.Event[agent.MCPEvent]: @@ -157,7 +161,7 @@ func (c *commandDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if msg.Type == pubsub.UpdatedEvent { c.mcpPrompts = LoadMCPPrompts() // If we're currently viewing MCP prompts, refresh the list - if c.commandType == MCPPrompts { + if c.selected == MCPPrompts { return c, tea.Batch( c.SetCommandType(MCPPrompts), c.subscribeMCPEvents(), @@ -184,23 +188,23 @@ func (c *commandDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if len(c.userCommands) == 0 && len(c.mcpPrompts) == 0 { return c, nil } - // Cycle through command types: System -> User -> MCP -> System - nextType := (c.commandType + 1) % 3 - // Skip empty types - for { - if nextType == UserCommands && len(c.userCommands) == 0 { - nextType = (nextType + 1) % 3 - } else if nextType == MCPPrompts && len(c.mcpPrompts) == 0 { - nextType = (nextType + 1) % 3 - } else { - break + switch c.selected { + case SystemCommands: + if len(c.userCommands) > 0 { + return c, c.SetCommandType(UserCommands) } - // Prevent infinite loop - if nextType == c.commandType { - return c, nil + if len(c.mcpPrompts) > 0 { + return c, c.SetCommandType(MCPPrompts) } + return c, nil + case UserCommands: + if len(c.mcpPrompts) > 0 { + return c, c.SetCommandType(MCPPrompts) + } + return c, c.SetCommandType(SystemCommands) + case MCPPrompts: + return c, c.SetCommandType(SystemCommands) } - return c, c.SetCommandType(nextType) case key.Matches(msg, c.keyMap.Close): if c.cancel != nil { c.cancel() @@ -247,17 +251,24 @@ func (c *commandDialogCmp) Cursor() *tea.Cursor { func (c *commandDialogCmp) commandTypeRadio() string { t := styles.CurrentTheme() - choices := []string{"System", "User", "MCP"} - iconSelected := "◉" - iconUnselected := "○" - - icons := make([]string, 3) - for i := range icons { - if i == c.commandType { - icons[i] = iconSelected - } else { - icons[i] = iconUnselected + + selected := func(i CommandType) string { + if i == c.selected { + return "◉" } + return "○" + } + + choices := []string{SystemCommands.String()} + icons := []string{selected(SystemCommands)} + + if len(c.userCommands) > 0 { + choices = append(choices, UserCommands.String()) + icons = append(icons, selected(UserCommands)) + } + if len(c.mcpPrompts) > 0 { + choices = append(choices, MCPPrompts.String()) + icons = append(icons, selected(MCPPrompts)) } parts := make([]string, 0, 6) @@ -272,11 +283,11 @@ func (c *commandDialogCmp) listWidth() int { return defaultWidth - 2 // 4 for padding } -func (c *commandDialogCmp) SetCommandType(commandType int) tea.Cmd { - c.commandType = commandType +func (c *commandDialogCmp) SetCommandType(commandType CommandType) tea.Cmd { + c.selected = commandType var commands []Command - switch c.commandType { + switch c.selected { case SystemCommands: commands = c.defaultCommands() case UserCommands: