diff --git a/src/AxCopilot/Views/ChatWindow.MoodMenu.cs b/src/AxCopilot/Views/ChatWindow.MoodMenu.cs index db80eaf..71d1b1e 100644 --- a/src/AxCopilot/Views/ChatWindow.MoodMenu.cs +++ b/src/AxCopilot/Views/ChatWindow.MoodMenu.cs @@ -447,6 +447,10 @@ public partial class ChatWindow SettingsPanel.CloseRequested += OnSettingsPanelClose; SettingsPanel.SettingsChanged -= OnSettingsPanelChanged; SettingsPanel.SettingsChanged += OnSettingsPanelChanged; + // 콜백 연결 — ChatWindow 기존 구현에 위임 + SettingsPanel.ServiceSelectorRequested = () => BtnModelSelector_Click(BtnModelSelector, new System.Windows.RoutedEventArgs()); + SettingsPanel.ModelSelectorRequested = () => BtnModelSelector_Click(BtnModelSelector, new System.Windows.RoutedEventArgs()); + SettingsPanel.WorkFolderBrowseRequested = () => BrowseWorkFolder(); SettingsPanel.IsOpen = true; } } diff --git a/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml b/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml index e2dfaa9..0f0297d 100644 --- a/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml +++ b/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml @@ -291,6 +291,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -303,6 +341,16 @@ + + + + + + + + + diff --git a/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml.cs b/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml.cs index a476fe9..223bc16 100644 --- a/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml.cs +++ b/src/AxCopilot/Views/Controls/AgentSettingsPanel.xaml.cs @@ -1,7 +1,9 @@ +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; +using AxCopilot.Models; using AxCopilot.Services; namespace AxCopilot.Views.Controls; @@ -18,6 +20,15 @@ public partial class AgentSettingsPanel : UserControl private bool _isOpen; private bool _isLoading = true; // 초기 로드 중 이벤트 발생 방지 + /// 서비스 선택 요청 콜백 (ChatWindow.BtnModelSelector_Click으로 위임). + public Action? ServiceSelectorRequested; + + /// 모델 선택 요청 콜백 (ChatWindow.BtnModelSelector_Click으로 위임). + public Action? ModelSelectorRequested; + + /// 작업 폴더 탐색 요청 콜백 (ChatWindow.BrowseWorkFolder로 위임). + public Action? WorkFolderBrowseRequested; + /// 설정 패널 열림/닫힘 상태. public bool IsOpen { @@ -78,6 +89,7 @@ public partial class AgentSettingsPanel : UserControl // 탭별 설정 표시 PanelCoworkSettings.Visibility = activeTab == "Cowork" ? Visibility.Visible : Visibility.Collapsed; PanelCodeSettings.Visibility = activeTab == "Code" ? Visibility.Visible : Visibility.Collapsed; + PanelWorkFolder.Visibility = activeTab == "Code" ? Visibility.Visible : Visibility.Collapsed; if (activeTab == "Cowork") { @@ -92,6 +104,11 @@ public partial class AgentSettingsPanel : UserControl // 도구 토글 동적 생성 BuildToolToggles(settings, toolRegistry); + // 작업 폴더 표시 (Code 탭) + UpdateWorkFolder(settings); + // MCP 서버 목록 표시 + BuildMcpServerList(settings); + _isLoading = false; } @@ -100,7 +117,8 @@ public partial class AgentSettingsPanel : UserControl { TxtCurrentTab.Text = tab; PanelCoworkSettings.Visibility = tab == "Cowork" ? Visibility.Visible : Visibility.Collapsed; - PanelCodeSettings.Visibility = tab == "Code" ? Visibility.Visible : Visibility.Collapsed; + PanelCodeSettings.Visibility = tab == "Code" ? Visibility.Visible : Visibility.Collapsed; + PanelWorkFolder.Visibility = tab == "Code" ? Visibility.Visible : Visibility.Collapsed; } private void BuildToolToggles(SettingsService settings, @@ -159,12 +177,105 @@ public partial class AgentSettingsPanel : UserControl private void BtnServiceSelector_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { - // TODO: 서비스 선택 팝업 (Ollama/vLLM/Gemini/Claude) + ServiceSelectorRequested?.Invoke(); } private void BtnModelSelector_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { - // TODO: 모델 선택 팝업 — ChatWindow의 기존 모델 선택 로직 재사용 + ModelSelectorRequested?.Invoke(); + } + + private void BtnWorkFolderBrowse_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + WorkFolderBrowseRequested?.Invoke(); + } + + private void UpdateWorkFolder(SettingsService settings) + { + var folder = settings.Settings.Llm.WorkFolder; + if (TxtWorkFolder == null) return; + TxtWorkFolder.Text = string.IsNullOrWhiteSpace(folder) + ? "(미지정)" + : System.IO.Path.GetFileName(folder) is { Length: > 0 } name ? name : folder; + TxtWorkFolder.ToolTip = folder; + } + + private void BuildMcpServerList(SettingsService settings) + { + if (PanelMcpServers == null) return; + PanelMcpServers.Children.Clear(); + + var servers = settings.Settings.Llm.McpServers; + if (servers == null || servers.Count == 0) + { + PanelMcpServers.Children.Add(new TextBlock + { + Text = "등록된 MCP 서버 없음", + FontSize = 11, + Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, + Margin = new Thickness(0, 0, 0, 4), + }); + return; + } + + foreach (var server in servers) + { + var grid = new System.Windows.Controls.Grid { Margin = new Thickness(0, 0, 0, 6) }; + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(8) }); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + + var dot = new System.Windows.Shapes.Ellipse + { + Width = 6, Height = 6, + Fill = server.Enabled + ? new SolidColorBrush(Color.FromRgb(0x38, 0xA1, 0x69)) + : new SolidColorBrush(Color.FromRgb(0x9E, 0x9E, 0x9E)), + VerticalAlignment = VerticalAlignment.Center, + }; + Grid.SetColumn(dot, 0); + + var nameLabel = new TextBlock + { + Text = server.Name, + FontSize = 11, + Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.White, + VerticalAlignment = VerticalAlignment.Center, + Margin = new Thickness(6, 0, 0, 0), + TextTrimming = System.Windows.TextTrimming.CharacterEllipsis, + }; + Grid.SetColumn(nameLabel, 1); + + var chk = new CheckBox + { + IsChecked = server.Enabled, + Tag = server.Name, + VerticalAlignment = VerticalAlignment.Center, + }; + if (TryFindResource("ToggleSwitch") is Style toggleStyle) + chk.Style = toggleStyle; + chk.Checked += McpToggle_Changed; + chk.Unchecked += McpToggle_Changed; + Grid.SetColumn(chk, 2); + + grid.Children.Add(dot); + grid.Children.Add(nameLabel); + grid.Children.Add(chk); + PanelMcpServers.Children.Add(grid); + } + } + + private void McpToggle_Changed(object sender, RoutedEventArgs e) + { + if (_isLoading || sender is not CheckBox chk || chk.Tag is not string name) return; + var app = System.Windows.Application.Current as App; + var settings = app?.SettingsService; + if (settings == null) return; + var server = settings.Settings.Llm.McpServers?.FirstOrDefault(s => s.Name == name); + if (server == null) return; + server.Enabled = chk.IsChecked == true; + settings.Save(); + SettingsChanged?.Invoke(this, EventArgs.Empty); } private void TxtApiEndpoint_LostFocus(object sender, RoutedEventArgs e)