AX Agent 구형 설정창의 PlanMode dead UI를 제거
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- AgentSettingsWindow에서 계획 모드와 Plan Mode 도구 UI 및 save/load/event 코드 제거 - clean 파일 기준 검색상 남은 PlanMode 참조를 JSON 호환용 AppSettings와 SubAgentTool 안전 고정 경로로 축소 - README와 DEVELOPMENT 문서에 2026-04-05 21:20 (KST) 기준 변경 내역과 parity 99% 재평가 반영 - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0 / 오류 0)
This commit is contained in:
@@ -965,6 +965,10 @@ ow + toggle 시각 언어로 통일했습니다.
|
|||||||
- 이번 정리 후 추정 parity 는 `core engine 95% / main transcript UI 97% / Cowork·Code runtime UX 97% / internal settings 95% / overall 98%` 정도로 재평가했습니다.
|
- 이번 정리 후 추정 parity 는 `core engine 95% / main transcript UI 97% / Cowork·Code runtime UX 97% / internal settings 95% / overall 98%` 정도로 재평가했습니다.
|
||||||
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
|
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
|
||||||
- 업데이트: 2026-04-05 21:12 (KST)
|
- 업데이트: 2026-04-05 21:12 (KST)
|
||||||
|
- 구형 [AgentSettingsWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/AgentSettingsWindow.xaml), [AgentSettingsWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/AgentSettingsWindow.xaml.cs) 에 남아 있던 `계획 모드`, `Plan Mode 도구` UI와 관련 save/load/event 코드도 제거했습니다. 현재 clean 파일 기준 검색상 남은 `PlanMode`/`EnablePlanModeTools` 참조는 JSON 호환용 [AppSettings.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Models/AppSettings.cs) 와 안전 고정용 [SubAgentTool.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/SubAgentTool.cs) 정도입니다.
|
||||||
|
- 이번 정리 후 추정 parity 는 `core engine 95% / main transcript UI 97% / Cowork·Code runtime UX 97% / internal settings 97% / overall 99%` 정도로 재평가했습니다.
|
||||||
|
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
|
||||||
|
- 업데이트: 2026-04-05 21:20 (KST)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -4729,3 +4729,7 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
|
|||||||
- 이번 묶음 후 추정 parity 는 `core engine 95% / main transcript UI 97% / Cowork·Code runtime UX 97% / internal settings 95% / overall 98%` 정도로 재평가했습니다.
|
- 이번 묶음 후 추정 parity 는 `core engine 95% / main transcript UI 97% / Cowork·Code runtime UX 97% / internal settings 95% / overall 98%` 정도로 재평가했습니다.
|
||||||
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0
|
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0
|
||||||
- 업데이트: 2026-04-05 21:12 (KST)
|
- 업데이트: 2026-04-05 21:12 (KST)
|
||||||
|
- 구형 [AgentSettingsWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/AgentSettingsWindow.xaml), [AgentSettingsWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/AgentSettingsWindow.xaml.cs) 의 `계획 모드`, `Plan Mode 도구` UI와 관련 save/load/event 코드도 제거했습니다. clean 파일 기준 검색상 남은 `PlanMode`/`EnablePlanModeTools` 참조는 JSON 저장 호환을 위한 [AppSettings.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Models/AppSettings.cs) 와 안전 고정값을 두는 [SubAgentTool.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/SubAgentTool.cs) 정도만 남았습니다.
|
||||||
|
- 이번 묶음 후 추정 parity 는 `core engine 95% / main transcript UI 97% / Cowork·Code runtime UX 97% / internal settings 97% / overall 99%` 정도로 재평가했습니다.
|
||||||
|
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0
|
||||||
|
- 업데이트: 2026-04-05 21:20 (KST)
|
||||||
|
|||||||
@@ -74,14 +74,26 @@
|
|||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Key="HelpTooltipStyle" TargetType="ToolTip">
|
||||||
|
<Setter Property="Background" Value="#1F2937"/>
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
<Setter Property="BorderBrush" Value="#3B82F6"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="Padding" Value="12,10"/>
|
||||||
|
<Setter Property="FontSize" Value="12"/>
|
||||||
|
<Setter Property="HasDropShadow" Value="True"/>
|
||||||
|
<Setter Property="Placement" Value="Mouse"/>
|
||||||
|
</Style>
|
||||||
</Window.Resources>
|
</Window.Resources>
|
||||||
|
|
||||||
<Border Background="{DynamicResource LauncherBackground}"
|
<Border Background="{DynamicResource LauncherBackground}"
|
||||||
BorderBrush="{DynamicResource BorderColor}"
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
BorderThickness="1">
|
BorderThickness="1">
|
||||||
<Grid>
|
<Grid Visibility="Collapsed">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="48"/>
|
<RowDefinition Height="48"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
<RowDefinition Height="56"/>
|
<RowDefinition Height="56"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
@@ -113,10 +125,159 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1"
|
<Border Grid.Row="1"
|
||||||
|
Background="{DynamicResource LauncherBackground}"
|
||||||
|
BorderBrush="{DynamicResource SeparatorColor}"
|
||||||
|
BorderThickness="0,0,0,1">
|
||||||
|
<WrapPanel Margin="18,12,18,10">
|
||||||
|
<Border x:Name="AgentTabBasicCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
MouseLeftButtonUp="AgentTabBasicCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="기본" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="AgentTabChatCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
MouseLeftButtonUp="AgentTabChatCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="채팅" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="AgentTabCoworkCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
MouseLeftButtonUp="AgentTabCoworkCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="코워크" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="AgentTabCodeCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
MouseLeftButtonUp="AgentTabCodeCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="코드" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="AgentTabDevCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
MouseLeftButtonUp="AgentTabDevCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="개발자" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="AgentTabToolsCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
MouseLeftButtonUp="AgentTabToolsCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="도구" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="AgentTabEtcCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
MouseLeftButtonUp="AgentTabEtcCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="스킬/차단" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
</WrapPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<ScrollViewer Grid.Row="2"
|
||||||
VerticalScrollBarVisibility="Auto"
|
VerticalScrollBarVisibility="Auto"
|
||||||
HorizontalScrollBarVisibility="Disabled">
|
HorizontalScrollBarVisibility="Disabled">
|
||||||
<StackPanel Margin="18,14,18,16">
|
<StackPanel Margin="18,14,18,16">
|
||||||
|
<StackPanel x:Name="PanelBasic">
|
||||||
|
<TextBlock Text="기본 상태"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Grid Margin="0,8,0,0" Visibility="Collapsed">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Margin="0,0,12,0">
|
||||||
|
<TextBlock Text="AX Agent 사용"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
FontSize="12"/>
|
||||||
|
<TextBlock Text="비활성화하면 AX Agent 대화와 관련 설정이 숨겨집니다."
|
||||||
|
Foreground="{DynamicResource SecondaryText}"
|
||||||
|
FontSize="11"
|
||||||
|
Margin="0,2,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox x:Name="ChkAiEnabled"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0" Visibility="Collapsed">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Margin="0,0,12,0">
|
||||||
|
<TextBlock Text="표현 수준"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
FontSize="12"/>
|
||||||
|
<TextBlock Text="계획, 승인 카드, 보조 설명의 정보 밀도를 조정합니다."
|
||||||
|
Foreground="{DynamicResource SecondaryText}"
|
||||||
|
FontSize="11"
|
||||||
|
Margin="0,2,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
<WrapPanel Grid.Column="1">
|
||||||
|
<Border x:Name="DisplayModeRichCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,6,0"
|
||||||
|
MouseLeftButtonUp="DisplayModeRichCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="풍부하게" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="DisplayModeBalancedCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
Margin="0,0,6,0"
|
||||||
|
MouseLeftButtonUp="DisplayModeBalancedCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="적절하게" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="DisplayModeSimpleCard"
|
||||||
|
Cursor="Hand"
|
||||||
|
CornerRadius="10"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
Padding="10,7"
|
||||||
|
MouseLeftButtonUp="DisplayModeSimpleCard_MouseLeftButtonUp">
|
||||||
|
<TextBlock Text="간단하게" FontSize="12" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
</Border>
|
||||||
|
</WrapPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
|
||||||
<TextBlock Text="테마"
|
<TextBlock Text="테마"
|
||||||
FontSize="13"
|
FontSize="13"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
@@ -155,7 +316,9 @@
|
|||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
|
|
||||||
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel x:Name="PanelChat">
|
||||||
<TextBlock Text="모델 및 연결"
|
<TextBlock Text="모델 및 연결"
|
||||||
FontSize="13"
|
FontSize="13"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
@@ -233,18 +396,86 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="운영 모드"
|
<StackPanel Orientation="Horizontal">
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
<TextBlock Text="운영 모드"
|
||||||
VerticalAlignment="Center"/>
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">
|
||||||
|
사내 모드는 외부 검색, 외부 URL 열기, 외부 HTTP 호출을 제한합니다.
|
||||||
|
<LineBreak/>사외 모드는 외부 연동이 필요한 작업까지 허용합니다.
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
<Button x:Name="BtnOperationMode"
|
<Button x:Name="BtnOperationMode"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
MinWidth="140"
|
MinWidth="140"
|
||||||
Style="{StaticResource OutlineHoverBtn}"
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
Click="BtnOperationMode_Click"/>
|
Click="BtnOperationMode_Click"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="기본 출력 형식"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">
|
||||||
|
결과물을 어떤 문서 형태로 우선 제안할지 정합니다.
|
||||||
|
<LineBreak/>AI 자동으로 두면 요청 성격에 맞는 형식을 먼저 고릅니다.
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<Button x:Name="BtnDefaultOutputFormat"
|
||||||
|
Grid.Column="1"
|
||||||
|
MinWidth="140"
|
||||||
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
|
Click="BtnDefaultOutputFormat_Click"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="기본 디자인 무드"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">
|
||||||
|
HTML 미리보기나 문서형 결과물에서 기본으로 쓸 시각 스타일입니다.
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<Button x:Name="BtnDefaultMood"
|
||||||
|
Grid.Column="1"
|
||||||
|
MinWidth="140"
|
||||||
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
|
Click="BtnDefaultMood_Click"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel x:Name="PanelCowork" Visibility="Collapsed">
|
||||||
<TextBlock Text="권한 및 실행"
|
<TextBlock Text="권한 및 실행"
|
||||||
FontSize="13"
|
FontSize="13"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
@@ -254,9 +485,22 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="권한 모드"
|
<StackPanel Orientation="Horizontal">
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
<TextBlock Text="권한 모드"
|
||||||
VerticalAlignment="Center"/>
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="320">
|
||||||
|
파일 읽기, 수정, 실행 요청을 얼마나 자주 승인받을지 정합니다.
|
||||||
|
<LineBreak/>보수적으로 둘수록 안전하고, 자동 승인 계열일수록 빠르게 진행됩니다.
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
<Button x:Name="BtnPermissionMode"
|
<Button x:Name="BtnPermissionMode"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
MinWidth="120"
|
MinWidth="120"
|
||||||
@@ -268,23 +512,21 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="계획 모드"
|
<StackPanel Orientation="Horizontal">
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
<TextBlock Text="추론 강도"
|
||||||
VerticalAlignment="Center"/>
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
<Button x:Name="BtnPlanMode"
|
VerticalAlignment="Center"/>
|
||||||
Grid.Column="1"
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
MinWidth="120"
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
Style="{StaticResource OutlineHoverBtn}"
|
<Border.ToolTip>
|
||||||
Click="BtnPlanMode_Click"/>
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
</Grid>
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">
|
||||||
<Grid Margin="0,8,0,0">
|
답을 만들기 전에 얼마나 많이 따져보고 진행할지 정합니다.
|
||||||
<Grid.ColumnDefinitions>
|
</TextBlock>
|
||||||
<ColumnDefinition Width="*"/>
|
</ToolTip>
|
||||||
<ColumnDefinition Width="Auto"/>
|
</Border.ToolTip>
|
||||||
</Grid.ColumnDefinitions>
|
</Border>
|
||||||
<TextBlock Text="추론 강도"
|
</StackPanel>
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
|
||||||
VerticalAlignment="Center"/>
|
|
||||||
<Button x:Name="BtnReasoningMode"
|
<Button x:Name="BtnReasoningMode"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
MinWidth="120"
|
MinWidth="120"
|
||||||
@@ -296,17 +538,162 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="폴더 데이터 활용"
|
<StackPanel Orientation="Horizontal">
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
<TextBlock Text="폴더 데이터 활용"
|
||||||
VerticalAlignment="Center"/>
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="320">
|
||||||
|
현재 작업 폴더 파일과 문맥을 AI가 얼마나 적극적으로 참고할지 정합니다.
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
<Button x:Name="BtnFolderDataUsage"
|
<Button x:Name="BtnFolderDataUsage"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
MinWidth="120"
|
MinWidth="120"
|
||||||
Style="{StaticResource OutlineHoverBtn}"
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
Click="BtnFolderDataUsage_Click"/>
|
Click="BtnFolderDataUsage_Click"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="Cowork 검증 강제"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableCoworkVerification"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="프로젝트 규칙 자동 반영"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableProjectRules"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="에이전트 메모리 사용"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableAgentMemory"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="120"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="최대 Agent Pass"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="320">
|
||||||
|
한 번의 작업에서 에이전트가 계획, 실행, 확인 단계를 반복할 수 있는 최대 횟수입니다.
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox x:Name="TxtMaxAgentIterations"
|
||||||
|
Grid.Column="1"
|
||||||
|
Padding="8,5"
|
||||||
|
Background="{DynamicResource ItemBackground}"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
BorderThickness="1"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
FontSize="12"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel x:Name="AdvancedPanel">
|
<StackPanel x:Name="PanelCode" Visibility="Collapsed">
|
||||||
|
<TextBlock Text="코드 실행"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="Code 검증 강제"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableCodeVerification"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="병렬 도구 실행"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableParallelTools"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="Worktree 도구"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableWorktreeTools"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="Team 도구"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableTeamTools"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="Cron 도구"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<CheckBox x:Name="ChkEnableCronTools"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel x:Name="PanelDev" Visibility="Collapsed">
|
||||||
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
|
||||||
<TextBlock Text="컨텍스트 및 오류 관리"
|
<TextBlock Text="컨텍스트 및 오류 관리"
|
||||||
@@ -347,9 +734,19 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="120"/>
|
<ColumnDefinition Width="120"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="최대 컨텍스트 토큰"
|
<StackPanel Orientation="Horizontal">
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
<TextBlock Text="최대 컨텍스트 토큰"
|
||||||
VerticalAlignment="Center"/>
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="280">한 번의 응답 생성에 넘겨줄 최대 문맥 크기입니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
<TextBox x:Name="TxtMaxContextTokens"
|
<TextBox x:Name="TxtMaxContextTokens"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Padding="8,5"
|
Padding="8,5"
|
||||||
@@ -364,9 +761,19 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="120"/>
|
<ColumnDefinition Width="120"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="오류 재시도 횟수"
|
<StackPanel Orientation="Horizontal">
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
<TextBlock Text="오류 재시도 횟수"
|
||||||
VerticalAlignment="Center"/>
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="280">도구 실행 실패 시 자동으로 다시 시도할 최대 횟수입니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
<TextBox x:Name="TxtMaxRetryOnError"
|
<TextBox x:Name="TxtMaxRetryOnError"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Padding="8,5"
|
Padding="8,5"
|
||||||
@@ -377,8 +784,9 @@
|
|||||||
FontSize="12"/>
|
FontSize="12"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Border Height="1" Margin="0,10,0,10" Background="{DynamicResource SeparatorColor}"/>
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel x:Name="PanelTools" Visibility="Collapsed">
|
||||||
<TextBlock Text="도구 및 검증"
|
<TextBlock Text="도구 및 검증"
|
||||||
FontSize="13"
|
FontSize="13"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
@@ -388,9 +796,19 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="스킬 시스템"
|
<StackPanel Orientation="Horizontal">
|
||||||
VerticalAlignment="Center"
|
<TextBlock Text="스킬 시스템"
|
||||||
Foreground="{DynamicResource PrimaryText}"/>
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">슬래시 명령으로 재사용 가능한 작업 템플릿을 불러오는 기능입니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
<CheckBox x:Name="ChkEnableSkillSystem"
|
<CheckBox x:Name="ChkEnableSkillSystem"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Style="{StaticResource ToggleSwitch}"/>
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
@@ -400,9 +818,19 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="도구 훅 사용"
|
<StackPanel Orientation="Horizontal">
|
||||||
VerticalAlignment="Center"
|
<TextBlock Text="도구 훅 사용"
|
||||||
Foreground="{DynamicResource PrimaryText}"/>
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">특정 도구 실행 전후에 스크립트를 자동으로 호출하는 확장 기능입니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
<CheckBox x:Name="ChkEnableToolHooks"
|
<CheckBox x:Name="ChkEnableToolHooks"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Style="{StaticResource ToggleSwitch}"/>
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
@@ -431,15 +859,140 @@
|
|||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Style="{StaticResource ToggleSwitch}"/>
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Border Height="1" Margin="0,12,0,12" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
<TextBlock Text="도구 노출"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<TextBlock Text="AX Agent에 노출할 도구를 내부 설정에서 바로 켜고 끕니다."
|
||||||
|
Margin="0,4,0,8"
|
||||||
|
FontSize="11"
|
||||||
|
Foreground="{DynamicResource SecondaryText}"/>
|
||||||
|
<StackPanel x:Name="ToolCardsPanel"/>
|
||||||
|
<Border Height="1" Margin="0,12,0,12" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
<TextBlock Text="도구 훅"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<StackPanel x:Name="HookListPanel" Margin="0,8,0,0"/>
|
||||||
|
<Button Content="훅 추가"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Margin="0,8,0,0"
|
||||||
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
|
Click="BtnAddHook_Click"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel x:Name="PanelEtc" Visibility="Collapsed">
|
||||||
|
<TextBlock Text="스킬/차단"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<TextBlock Text="스킬 폴더와 슬래시/드래그 동작, 폴백 모델과 MCP 서버를 관리합니다."
|
||||||
|
Margin="0,4,0,8"
|
||||||
|
FontSize="11"
|
||||||
|
Foreground="{DynamicResource SecondaryText}"/>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="스킬 폴더"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="320">추가 스킬을 읽어올 폴더입니다. `.skill.md` 또는 `SKILL.md` 파일을 두면 저장 후 다시 불러옵니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox x:Name="TxtSkillsFolderPath"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="0,8,0,0"
|
||||||
|
Padding="8,5"
|
||||||
|
Background="{DynamicResource ItemBackground}"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
BorderThickness="1"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
FontSize="12"/>
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Grid.Row="1"
|
||||||
|
Margin="8,0,0,0"
|
||||||
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
|
Content="찾아보기"
|
||||||
|
Click="BtnBrowseSkillFolder_Click"/>
|
||||||
|
<Button Grid.Column="2"
|
||||||
|
Grid.Row="1"
|
||||||
|
Margin="8,0,0,0"
|
||||||
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
|
Content="열기"
|
||||||
|
Click="BtnOpenSkillFolder_Click"/>
|
||||||
|
</Grid>
|
||||||
|
<Border Height="1" Margin="0,12,0,12" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
<TextBlock Text="로드된 스킬"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<TextBlock Text="현재 AX Agent에서 사용할 수 있는 슬래시 스킬 목록입니다."
|
||||||
|
Margin="0,4,0,8"
|
||||||
|
FontSize="11"
|
||||||
|
Foreground="{DynamicResource SecondaryText}"/>
|
||||||
|
<StackPanel x:Name="SkillListPanel"/>
|
||||||
|
<Grid Margin="0,8,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="120"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="슬래시 팝업 표시 개수"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">`/` 입력 시 한 번에 보여줄 명령과 스킬 개수입니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox x:Name="TxtSlashPopupPageSize"
|
||||||
|
Grid.Column="1"
|
||||||
|
Padding="8,5"
|
||||||
|
Background="{DynamicResource ItemBackground}"
|
||||||
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
|
BorderThickness="1"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
|
FontSize="12"/>
|
||||||
|
</Grid>
|
||||||
<Grid Margin="0,8,0,0">
|
<Grid Margin="0,8,0,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="Cowork 검증 강제"
|
<StackPanel Orientation="Horizontal">
|
||||||
VerticalAlignment="Center"
|
<TextBlock Text="드래그 앤 드롭 AI 액션"
|
||||||
Foreground="{DynamicResource PrimaryText}"/>
|
VerticalAlignment="Center"
|
||||||
<CheckBox x:Name="ChkEnableCoworkVerification"
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">파일을 끌어놓았을 때 AI 작업 추천과 첨부 보조 동작을 보여줍니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox x:Name="ChkEnableDragDropAiActions"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Style="{StaticResource ToggleSwitch}"/>
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -448,30 +1001,61 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="Code 검증 강제"
|
<StackPanel Orientation="Horizontal">
|
||||||
VerticalAlignment="Center"
|
<TextBlock Text="선택 시 자동 전송"
|
||||||
Foreground="{DynamicResource PrimaryText}"/>
|
VerticalAlignment="Center"
|
||||||
<CheckBox x:Name="ChkEnableCodeVerification"
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="300">추천 액션을 고르면 바로 메시지를 보내 실행까지 이어갑니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox x:Name="ChkDragDropAutoSend"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Style="{StaticResource ToggleSwitch}"/>
|
Style="{StaticResource ToggleSwitch}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Margin="0,8,0,0">
|
<Border Height="1" Margin="0,12,0,12" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
<TextBlock Text="폴백 모델"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
<StackPanel x:Name="FallbackModelsPanel" Margin="0,8,0,0"/>
|
||||||
|
<Border Height="1" Margin="0,12,0,12" Background="{DynamicResource SeparatorColor}"/>
|
||||||
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="병렬 도구 실행"
|
<StackPanel Orientation="Horizontal">
|
||||||
VerticalAlignment="Center"
|
<TextBlock Text="MCP 서버"
|
||||||
Foreground="{DynamicResource PrimaryText}"/>
|
FontSize="13"
|
||||||
<CheckBox x:Name="ChkEnableParallelTools"
|
FontWeight="SemiBold"
|
||||||
Grid.Column="1"
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
Style="{StaticResource ToggleSwitch}"/>
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="16" Height="16" CornerRadius="8" Background="{DynamicResource ItemHoverBackground}" Margin="6,0,0,0" Cursor="Help" VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="?" FontSize="10" FontWeight="Bold" Foreground="{DynamicResource AccentColor}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
<Border.ToolTip>
|
||||||
|
<ToolTip Style="{StaticResource HelpTooltipStyle}">
|
||||||
|
<TextBlock TextWrapping="Wrap" Foreground="White" FontSize="12" LineHeight="18" MaxWidth="320">외부 도구 서버를 연결해 AX Agent가 브라우저나 파일시스템 같은 확장 기능을 사용할 수 있게 합니다.</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</Border.ToolTip>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Style="{StaticResource OutlineHoverBtn}"
|
||||||
|
Content="서버 추가"
|
||||||
|
Click="BtnAddMcpServer_Click"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<StackPanel x:Name="McpServerListPanel" Margin="0,8,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
<Border Grid.Row="2"
|
<Border Grid.Row="3"
|
||||||
Background="{DynamicResource ItemBackground}"
|
Background="{DynamicResource ItemBackground}"
|
||||||
BorderBrush="{DynamicResource SeparatorColor}"
|
BorderBrush="{DynamicResource SeparatorColor}"
|
||||||
BorderThickness="0,1,0,0">
|
BorderThickness="0,1,0,0">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using System.Linq;
|
||||||
using AxCopilot.Models;
|
using AxCopilot.Models;
|
||||||
using AxCopilot.Services;
|
using AxCopilot.Services;
|
||||||
using AxCopilot.Services.Agent;
|
using AxCopilot.Services.Agent;
|
||||||
@@ -15,11 +16,18 @@ public partial class AgentSettingsWindow : Window
|
|||||||
private readonly SettingsService _settings;
|
private readonly SettingsService _settings;
|
||||||
private readonly LlmSettings _llm;
|
private readonly LlmSettings _llm;
|
||||||
private string _permissionMode = PermissionModeCatalog.Deny;
|
private string _permissionMode = PermissionModeCatalog.Deny;
|
||||||
private string _planMode = "off";
|
|
||||||
private string _reasoningMode = "detailed";
|
private string _reasoningMode = "detailed";
|
||||||
private string _folderDataUsage = "active";
|
private string _folderDataUsage = "active";
|
||||||
private string _operationMode = OperationModePolicy.InternalMode;
|
private string _operationMode = OperationModePolicy.InternalMode;
|
||||||
|
private string _displayMode = "rich";
|
||||||
|
private string _defaultOutputFormat = "auto";
|
||||||
|
private string _defaultMood = "modern";
|
||||||
|
private string _activePanel = "basic";
|
||||||
|
private string _selectedService = "ollama";
|
||||||
|
private string _selectedTheme = "system";
|
||||||
private string _selectedModel = string.Empty;
|
private string _selectedModel = string.Empty;
|
||||||
|
private bool _toolCardsLoaded;
|
||||||
|
private HashSet<string> _disabledTools = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public AgentSettingsWindow(SettingsService settings)
|
public AgentSettingsWindow(SettingsService settings)
|
||||||
{
|
{
|
||||||
@@ -31,14 +39,24 @@ public partial class AgentSettingsWindow : Window
|
|||||||
|
|
||||||
private void LoadFromSettings()
|
private void LoadFromSettings()
|
||||||
{
|
{
|
||||||
_selectedModel = _llm.Model ?? "";
|
SkillService.EnsureSkillFolder();
|
||||||
|
SkillService.LoadSkills(_llm.SkillsFolderPath);
|
||||||
|
|
||||||
|
_selectedService = (_llm.Service ?? "ollama").Trim().ToLowerInvariant();
|
||||||
|
_selectedTheme = (_llm.AgentTheme ?? "system").Trim().ToLowerInvariant();
|
||||||
|
_selectedModel = GetSelectedModelForService(_selectedService);
|
||||||
ModelInput.Text = _selectedModel;
|
ModelInput.Text = _selectedModel;
|
||||||
_permissionMode = PermissionModeCatalog.NormalizeGlobalMode(_llm.FilePermission);
|
_permissionMode = PermissionModeCatalog.NormalizeGlobalMode(_llm.FilePermission);
|
||||||
_planMode = string.IsNullOrWhiteSpace(_llm.PlanMode) ? "off" : _llm.PlanMode;
|
|
||||||
_reasoningMode = string.IsNullOrWhiteSpace(_llm.AgentDecisionLevel) ? "detailed" : _llm.AgentDecisionLevel;
|
_reasoningMode = string.IsNullOrWhiteSpace(_llm.AgentDecisionLevel) ? "detailed" : _llm.AgentDecisionLevel;
|
||||||
_folderDataUsage = string.IsNullOrWhiteSpace(_llm.FolderDataUsage) ? "active" : _llm.FolderDataUsage;
|
_folderDataUsage = string.IsNullOrWhiteSpace(_llm.FolderDataUsage) ? "active" : _llm.FolderDataUsage;
|
||||||
_operationMode = OperationModePolicy.Normalize(_settings.Settings.OperationMode);
|
_operationMode = OperationModePolicy.Normalize(_settings.Settings.OperationMode);
|
||||||
|
_displayMode = "rich";
|
||||||
|
_defaultOutputFormat = string.IsNullOrWhiteSpace(_llm.DefaultOutputFormat) ? "auto" : _llm.DefaultOutputFormat;
|
||||||
|
_defaultMood = string.IsNullOrWhiteSpace(_llm.DefaultMood) ? "modern" : _llm.DefaultMood;
|
||||||
|
|
||||||
|
_settings.Settings.AiEnabled = true;
|
||||||
|
ChkAiEnabled.IsChecked = true;
|
||||||
|
ChkVllmAllowInsecureTls.IsChecked = _llm.VllmAllowInsecureTls;
|
||||||
ChkEnableProactiveCompact.IsChecked = _llm.EnableProactiveContextCompact;
|
ChkEnableProactiveCompact.IsChecked = _llm.EnableProactiveContextCompact;
|
||||||
TxtContextCompactTriggerPercent.Text = Math.Clamp(_llm.ContextCompactTriggerPercent, 10, 95).ToString();
|
TxtContextCompactTriggerPercent.Text = Math.Clamp(_llm.ContextCompactTriggerPercent, 10, 95).ToString();
|
||||||
TxtMaxContextTokens.Text = Math.Max(1024, _llm.MaxContextTokens).ToString();
|
TxtMaxContextTokens.Text = Math.Max(1024, _llm.MaxContextTokens).ToString();
|
||||||
@@ -49,40 +67,93 @@ public partial class AgentSettingsWindow : Window
|
|||||||
ChkEnableHookInputMutation.IsChecked = _llm.EnableHookInputMutation;
|
ChkEnableHookInputMutation.IsChecked = _llm.EnableHookInputMutation;
|
||||||
ChkEnableHookPermissionUpdate.IsChecked = _llm.EnableHookPermissionUpdate;
|
ChkEnableHookPermissionUpdate.IsChecked = _llm.EnableHookPermissionUpdate;
|
||||||
ChkEnableCoworkVerification.IsChecked = _llm.EnableCoworkVerification;
|
ChkEnableCoworkVerification.IsChecked = _llm.EnableCoworkVerification;
|
||||||
|
ChkEnableProjectRules.IsChecked = _llm.EnableProjectRules;
|
||||||
|
ChkEnableAgentMemory.IsChecked = _llm.EnableAgentMemory;
|
||||||
|
TxtMaxAgentIterations.Text = Math.Clamp(_llm.MaxAgentIterations, 1, 200).ToString();
|
||||||
ChkEnableCodeVerification.IsChecked = _llm.Code.EnableCodeVerification;
|
ChkEnableCodeVerification.IsChecked = _llm.Code.EnableCodeVerification;
|
||||||
ChkEnableParallelTools.IsChecked = _llm.EnableParallelTools;
|
ChkEnableParallelTools.IsChecked = _llm.EnableParallelTools;
|
||||||
|
ChkEnableWorktreeTools.IsChecked = _llm.Code.EnableWorktreeTools;
|
||||||
|
ChkEnableTeamTools.IsChecked = _llm.Code.EnableTeamTools;
|
||||||
|
ChkEnableCronTools.IsChecked = _llm.Code.EnableCronTools;
|
||||||
|
TxtSkillsFolderPath.Text = _llm.SkillsFolderPath ?? "";
|
||||||
|
TxtSlashPopupPageSize.Text = Math.Clamp(_llm.SlashPopupPageSize, 3, 20).ToString();
|
||||||
|
ChkEnableDragDropAiActions.IsChecked = _llm.EnableDragDropAiActions;
|
||||||
|
ChkDragDropAutoSend.IsChecked = _llm.DragDropAutoSend;
|
||||||
|
_disabledTools = new HashSet<string>(_llm.DisabledTools ?? new(), StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
RefreshServiceCards();
|
RefreshServiceCards();
|
||||||
RefreshThemeCards();
|
RefreshThemeCards();
|
||||||
RefreshModeLabels();
|
RefreshModeLabels();
|
||||||
|
RefreshChatOptionLabels();
|
||||||
|
RefreshDisplayModeCards();
|
||||||
|
ShowPanel("basic");
|
||||||
BuildModelChips();
|
BuildModelChips();
|
||||||
|
BuildFallbackModelsPanel();
|
||||||
|
BuildMcpServerCards();
|
||||||
|
BuildHookCards();
|
||||||
|
BuildSkillListPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshThemeCards()
|
private void RefreshThemeCards()
|
||||||
{
|
{
|
||||||
var selected = (_llm.AgentTheme ?? "system").ToLowerInvariant();
|
SetCardSelection(ThemeSystemCard, _selectedTheme == "system");
|
||||||
SetCardSelection(ThemeSystemCard, selected == "system");
|
SetCardSelection(ThemeLightCard, _selectedTheme == "light");
|
||||||
SetCardSelection(ThemeLightCard, selected == "light");
|
SetCardSelection(ThemeDarkCard, _selectedTheme == "dark");
|
||||||
SetCardSelection(ThemeDarkCard, selected == "dark");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshServiceCards()
|
private void RefreshServiceCards()
|
||||||
{
|
{
|
||||||
var service = (_llm.Service ?? "ollama").ToLowerInvariant();
|
SetCardSelection(SvcOllamaCard, _selectedService == "ollama");
|
||||||
SetCardSelection(SvcOllamaCard, service == "ollama");
|
SetCardSelection(SvcVllmCard, _selectedService == "vllm");
|
||||||
SetCardSelection(SvcVllmCard, service == "vllm");
|
SetCardSelection(SvcGeminiCard, _selectedService == "gemini");
|
||||||
SetCardSelection(SvcGeminiCard, service == "gemini");
|
SetCardSelection(SvcClaudeCard, _selectedService is "claude" or "sigmoid");
|
||||||
SetCardSelection(SvcClaudeCard, service is "claude" or "sigmoid");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshModeLabels()
|
private void RefreshModeLabels()
|
||||||
{
|
{
|
||||||
BtnOperationMode.Content = BuildOperationModeLabel(_operationMode);
|
BtnOperationMode.Content = BuildOperationModeLabel(_operationMode);
|
||||||
BtnPermissionMode.Content = PermissionModeCatalog.ToDisplayLabel(_permissionMode);
|
BtnPermissionMode.Content = PermissionModeCatalog.ToDisplayLabel(_permissionMode);
|
||||||
BtnPlanMode.Content = BuildPlanModeLabel(_planMode);
|
|
||||||
BtnReasoningMode.Content = BuildReasoningModeLabel(_reasoningMode);
|
BtnReasoningMode.Content = BuildReasoningModeLabel(_reasoningMode);
|
||||||
BtnFolderDataUsage.Content = BuildFolderDataUsageLabel(_folderDataUsage);
|
BtnFolderDataUsage.Content = BuildFolderDataUsageLabel(_folderDataUsage);
|
||||||
AdvancedPanel.Visibility = Visibility.Visible;
|
}
|
||||||
|
|
||||||
|
private void RefreshDisplayModeCards()
|
||||||
|
{
|
||||||
|
SetCardSelection(DisplayModeRichCard, _displayMode == "rich");
|
||||||
|
SetCardSelection(DisplayModeBalancedCard, _displayMode == "balanced");
|
||||||
|
SetCardSelection(DisplayModeSimpleCard, _displayMode == "simple");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshChatOptionLabels()
|
||||||
|
{
|
||||||
|
BtnDefaultOutputFormat.Content = BuildOutputFormatLabel(_defaultOutputFormat);
|
||||||
|
BtnDefaultMood.Content = BuildMoodLabel(_defaultMood);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshTabCards()
|
||||||
|
{
|
||||||
|
SetCardSelection(AgentTabBasicCard, _activePanel == "basic");
|
||||||
|
SetCardSelection(AgentTabChatCard, _activePanel == "chat");
|
||||||
|
SetCardSelection(AgentTabCoworkCard, _activePanel == "cowork");
|
||||||
|
SetCardSelection(AgentTabCodeCard, _activePanel == "code");
|
||||||
|
SetCardSelection(AgentTabDevCard, _activePanel == "dev");
|
||||||
|
SetCardSelection(AgentTabToolsCard, _activePanel == "tools");
|
||||||
|
SetCardSelection(AgentTabEtcCard, _activePanel == "etc");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowPanel(string panel)
|
||||||
|
{
|
||||||
|
_activePanel = panel;
|
||||||
|
PanelBasic.Visibility = panel == "basic" ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
PanelChat.Visibility = panel == "chat" ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
PanelCowork.Visibility = panel == "cowork" ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
PanelCode.Visibility = panel == "code" ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
PanelDev.Visibility = panel == "dev" ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
PanelTools.Visibility = panel == "tools" ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
PanelEtc.Visibility = panel == "etc" ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
RefreshTabCards();
|
||||||
|
if (panel == "tools")
|
||||||
|
LoadToolCards();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildOperationModeLabel(string mode)
|
private static string BuildOperationModeLabel(string mode)
|
||||||
@@ -92,16 +163,6 @@ public partial class AgentSettingsWindow : Window
|
|||||||
: "사내 모드";
|
: "사내 모드";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildPlanModeLabel(string mode)
|
|
||||||
{
|
|
||||||
return (mode ?? "off").ToLowerInvariant() switch
|
|
||||||
{
|
|
||||||
"always" => "항상 계획",
|
|
||||||
"auto" => "자동 계획",
|
|
||||||
_ => "끄기",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string BuildReasoningModeLabel(string mode)
|
private static string BuildReasoningModeLabel(string mode)
|
||||||
{
|
{
|
||||||
return (mode ?? "detailed").ToLowerInvariant() switch
|
return (mode ?? "detailed").ToLowerInvariant() switch
|
||||||
@@ -122,6 +183,37 @@ public partial class AgentSettingsWindow : Window
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string BuildOutputFormatLabel(string format)
|
||||||
|
{
|
||||||
|
return (format ?? "auto").ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"xlsx" => "Excel",
|
||||||
|
"html" => "HTML 보고서",
|
||||||
|
"docx" => "Word",
|
||||||
|
"pptx" => "PowerPoint",
|
||||||
|
"pdf" => "PDF",
|
||||||
|
"md" => "Markdown",
|
||||||
|
"txt" => "텍스트",
|
||||||
|
_ => "AI 자동",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildMoodLabel(string mood)
|
||||||
|
{
|
||||||
|
var found = TemplateService.AllMoods.FirstOrDefault(m => string.Equals(m.Key, mood, StringComparison.OrdinalIgnoreCase));
|
||||||
|
return found == null ? "모던" : $"{found.Icon} {found.Label}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeDisplayMode(string? mode)
|
||||||
|
{
|
||||||
|
return (mode ?? "balanced").Trim().ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"rich" => "rich",
|
||||||
|
"simple" => "simple",
|
||||||
|
_ => "balanced",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void SetCardSelection(Border border, bool selected)
|
private void SetCardSelection(Border border, bool selected)
|
||||||
{
|
{
|
||||||
var accent = TryFindResource("AccentColor") as Brush ?? Brushes.DodgerBlue;
|
var accent = TryFindResource("AccentColor") as Brush ?? Brushes.DodgerBlue;
|
||||||
@@ -135,7 +227,7 @@ public partial class AgentSettingsWindow : Window
|
|||||||
private void BuildModelChips()
|
private void BuildModelChips()
|
||||||
{
|
{
|
||||||
ModelChipPanel.Children.Clear();
|
ModelChipPanel.Children.Clear();
|
||||||
var models = GetModelCandidates(_llm.Service);
|
var models = GetModelCandidates(_selectedService);
|
||||||
foreach (var model in models)
|
foreach (var model in models)
|
||||||
{
|
{
|
||||||
var captured = model;
|
var captured = model;
|
||||||
@@ -195,17 +287,30 @@ public partial class AgentSettingsWindow : Window
|
|||||||
|
|
||||||
private void SetService(string service)
|
private void SetService(string service)
|
||||||
{
|
{
|
||||||
_llm.Service = service;
|
_selectedService = service;
|
||||||
|
_selectedModel = GetSelectedModelForService(service);
|
||||||
|
ModelInput.Text = _selectedModel;
|
||||||
RefreshServiceCards();
|
RefreshServiceCards();
|
||||||
BuildModelChips();
|
BuildModelChips();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetTheme(string theme)
|
private void SetTheme(string theme)
|
||||||
{
|
{
|
||||||
_llm.AgentTheme = theme;
|
_selectedTheme = theme;
|
||||||
RefreshThemeCards();
|
RefreshThemeCards();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetSelectedModelForService(string? service)
|
||||||
|
{
|
||||||
|
return (service ?? "ollama").Trim().ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"vllm" => _llm.VllmModel ?? "",
|
||||||
|
"gemini" => _llm.GeminiModel ?? "",
|
||||||
|
"claude" or "sigmoid" => _llm.ClaudeModel ?? "",
|
||||||
|
_ => _llm.OllamaModel ?? "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static string CycleOperationMode(string current)
|
private static string CycleOperationMode(string current)
|
||||||
{
|
{
|
||||||
return OperationModePolicy.Normalize(current) == OperationModePolicy.ExternalMode
|
return OperationModePolicy.Normalize(current) == OperationModePolicy.ExternalMode
|
||||||
@@ -306,11 +411,21 @@ public partial class AgentSettingsWindow : Window
|
|||||||
private void ThemeSystemCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetTheme("system");
|
private void ThemeSystemCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetTheme("system");
|
||||||
private void ThemeLightCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetTheme("light");
|
private void ThemeLightCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetTheme("light");
|
||||||
private void ThemeDarkCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetTheme("dark");
|
private void ThemeDarkCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetTheme("dark");
|
||||||
|
private void DisplayModeRichCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { _displayMode = "rich"; RefreshDisplayModeCards(); }
|
||||||
|
private void DisplayModeBalancedCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { _displayMode = "balanced"; RefreshDisplayModeCards(); }
|
||||||
|
private void DisplayModeSimpleCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { _displayMode = "simple"; RefreshDisplayModeCards(); }
|
||||||
|
|
||||||
private void SvcOllamaCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("ollama");
|
private void SvcOllamaCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("ollama");
|
||||||
private void SvcVllmCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("vllm");
|
private void SvcVllmCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("vllm");
|
||||||
private void SvcGeminiCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("gemini");
|
private void SvcGeminiCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("gemini");
|
||||||
private void SvcClaudeCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("claude");
|
private void SvcClaudeCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => SetService("claude");
|
||||||
|
private void AgentTabBasicCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ShowPanel("basic");
|
||||||
|
private void AgentTabChatCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ShowPanel("chat");
|
||||||
|
private void AgentTabCoworkCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ShowPanel("cowork");
|
||||||
|
private void AgentTabCodeCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ShowPanel("code");
|
||||||
|
private void AgentTabDevCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ShowPanel("dev");
|
||||||
|
private void AgentTabToolsCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ShowPanel("tools");
|
||||||
|
private void AgentTabEtcCard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ShowPanel("etc");
|
||||||
|
|
||||||
private void BtnOperationMode_Click(object sender, RoutedEventArgs e)
|
private void BtnOperationMode_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -343,17 +458,6 @@ public partial class AgentSettingsWindow : Window
|
|||||||
RefreshModeLabels();
|
RefreshModeLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BtnPlanMode_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
_planMode = _planMode switch
|
|
||||||
{
|
|
||||||
"off" => "auto",
|
|
||||||
"auto" => "always",
|
|
||||||
_ => "off",
|
|
||||||
};
|
|
||||||
RefreshModeLabels();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BtnReasoningMode_Click(object sender, RoutedEventArgs e)
|
private void BtnReasoningMode_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_reasoningMode = _reasoningMode switch
|
_reasoningMode = _reasoningMode switch
|
||||||
@@ -376,13 +480,66 @@ public partial class AgentSettingsWindow : Window
|
|||||||
RefreshModeLabels();
|
RefreshModeLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BtnDefaultOutputFormat_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_defaultOutputFormat = (_defaultOutputFormat ?? "auto").ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"auto" => "docx",
|
||||||
|
"docx" => "html",
|
||||||
|
"html" => "xlsx",
|
||||||
|
"xlsx" => "pdf",
|
||||||
|
"pdf" => "md",
|
||||||
|
"md" => "txt",
|
||||||
|
_ => "auto",
|
||||||
|
};
|
||||||
|
RefreshChatOptionLabels();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnDefaultMood_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var moods = TemplateService.AllMoods.Select(m => m.Key).Where(k => !string.IsNullOrWhiteSpace(k)).ToList();
|
||||||
|
if (moods.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var index = moods.FindIndex(k => string.Equals(k, _defaultMood, StringComparison.OrdinalIgnoreCase));
|
||||||
|
_defaultMood = index < 0 || index + 1 >= moods.Count ? moods[0] : moods[index + 1];
|
||||||
|
RefreshChatOptionLabels();
|
||||||
|
}
|
||||||
|
|
||||||
private void BtnSave_Click(object sender, RoutedEventArgs e)
|
private void BtnSave_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_llm.Model = string.IsNullOrWhiteSpace(_selectedModel) ? (_llm.Model ?? "") : _selectedModel.Trim();
|
_selectedModel = string.IsNullOrWhiteSpace(ModelInput.Text) ? _selectedModel : ModelInput.Text.Trim();
|
||||||
|
_llm.Service = _selectedService;
|
||||||
|
_llm.AgentTheme = _selectedTheme;
|
||||||
_llm.FilePermission = _permissionMode;
|
_llm.FilePermission = _permissionMode;
|
||||||
_llm.PlanMode = _planMode;
|
_llm.DefaultAgentPermission = _permissionMode;
|
||||||
_llm.AgentDecisionLevel = _reasoningMode;
|
_llm.AgentDecisionLevel = _reasoningMode;
|
||||||
_llm.FolderDataUsage = _folderDataUsage;
|
_llm.FolderDataUsage = _folderDataUsage;
|
||||||
|
_llm.AgentUiExpressionLevel = "rich";
|
||||||
|
_llm.DefaultOutputFormat = _defaultOutputFormat;
|
||||||
|
_llm.DefaultMood = _defaultMood;
|
||||||
|
_llm.VllmAllowInsecureTls = ChkVllmAllowInsecureTls.IsChecked == true;
|
||||||
|
|
||||||
|
switch (_selectedService)
|
||||||
|
{
|
||||||
|
case "vllm":
|
||||||
|
_llm.VllmModel = _selectedModel;
|
||||||
|
_llm.Model = _selectedModel;
|
||||||
|
break;
|
||||||
|
case "gemini":
|
||||||
|
_llm.GeminiModel = _selectedModel;
|
||||||
|
_llm.Model = _selectedModel;
|
||||||
|
break;
|
||||||
|
case "claude":
|
||||||
|
case "sigmoid":
|
||||||
|
_llm.ClaudeModel = _selectedModel;
|
||||||
|
_llm.Model = _selectedModel;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_llm.OllamaModel = _selectedModel;
|
||||||
|
_llm.Model = _selectedModel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
_llm.EnableProactiveContextCompact = ChkEnableProactiveCompact.IsChecked == true;
|
_llm.EnableProactiveContextCompact = ChkEnableProactiveCompact.IsChecked == true;
|
||||||
_llm.ContextCompactTriggerPercent = ParseInt(TxtContextCompactTriggerPercent.Text, 80, 10, 95);
|
_llm.ContextCompactTriggerPercent = ParseInt(TxtContextCompactTriggerPercent.Text, 80, 10, 95);
|
||||||
@@ -394,15 +551,563 @@ public partial class AgentSettingsWindow : Window
|
|||||||
_llm.EnableHookInputMutation = ChkEnableHookInputMutation.IsChecked == true;
|
_llm.EnableHookInputMutation = ChkEnableHookInputMutation.IsChecked == true;
|
||||||
_llm.EnableHookPermissionUpdate = ChkEnableHookPermissionUpdate.IsChecked == true;
|
_llm.EnableHookPermissionUpdate = ChkEnableHookPermissionUpdate.IsChecked == true;
|
||||||
_llm.EnableCoworkVerification = ChkEnableCoworkVerification.IsChecked == true;
|
_llm.EnableCoworkVerification = ChkEnableCoworkVerification.IsChecked == true;
|
||||||
|
_llm.EnableProjectRules = ChkEnableProjectRules.IsChecked == true;
|
||||||
|
_llm.EnableAgentMemory = ChkEnableAgentMemory.IsChecked == true;
|
||||||
|
_llm.MaxAgentIterations = ParseInt(TxtMaxAgentIterations.Text, 25, 1, 200);
|
||||||
_llm.Code.EnableCodeVerification = ChkEnableCodeVerification.IsChecked == true;
|
_llm.Code.EnableCodeVerification = ChkEnableCodeVerification.IsChecked == true;
|
||||||
_llm.EnableParallelTools = ChkEnableParallelTools.IsChecked == true;
|
_llm.EnableParallelTools = ChkEnableParallelTools.IsChecked == true;
|
||||||
|
_llm.Code.EnableWorktreeTools = ChkEnableWorktreeTools.IsChecked == true;
|
||||||
|
_llm.Code.EnableTeamTools = ChkEnableTeamTools.IsChecked == true;
|
||||||
|
_llm.Code.EnableCronTools = ChkEnableCronTools.IsChecked == true;
|
||||||
|
_llm.SkillsFolderPath = TxtSkillsFolderPath.Text?.Trim() ?? "";
|
||||||
|
_llm.SlashPopupPageSize = ParseInt(TxtSlashPopupPageSize.Text, 7, 3, 20);
|
||||||
|
_llm.EnableDragDropAiActions = ChkEnableDragDropAiActions.IsChecked == true;
|
||||||
|
_llm.DragDropAutoSend = ChkDragDropAutoSend.IsChecked == true;
|
||||||
|
_llm.DisabledTools = _disabledTools.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();
|
||||||
|
|
||||||
|
_settings.Settings.AiEnabled = true;
|
||||||
_settings.Settings.OperationMode = OperationModePolicy.Normalize(_operationMode);
|
_settings.Settings.OperationMode = OperationModePolicy.Normalize(_operationMode);
|
||||||
_settings.Save();
|
_settings.Save();
|
||||||
|
SkillService.LoadSkills(_llm.SkillsFolderPath);
|
||||||
|
BuildSkillListPanel();
|
||||||
DialogResult = true;
|
DialogResult = true;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BtnBrowseSkillFolder_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var dlg = new System.Windows.Forms.FolderBrowserDialog
|
||||||
|
{
|
||||||
|
Description = "스킬 폴더 선택",
|
||||||
|
ShowNewFolderButton = true,
|
||||||
|
};
|
||||||
|
if (!string.IsNullOrWhiteSpace(TxtSkillsFolderPath.Text) && System.IO.Directory.Exists(TxtSkillsFolderPath.Text))
|
||||||
|
dlg.SelectedPath = TxtSkillsFolderPath.Text;
|
||||||
|
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||||
|
TxtSkillsFolderPath.Text = dlg.SelectedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnOpenSkillFolder_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var folder = string.IsNullOrWhiteSpace(TxtSkillsFolderPath.Text)
|
||||||
|
? System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "skills")
|
||||||
|
: TxtSkillsFolderPath.Text.Trim();
|
||||||
|
if (!System.IO.Directory.Exists(folder))
|
||||||
|
System.IO.Directory.CreateDirectory(folder);
|
||||||
|
try { System.Diagnostics.Process.Start("explorer.exe", folder); } catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildSkillListPanel()
|
||||||
|
{
|
||||||
|
if (SkillListPanel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SkillListPanel.Children.Clear();
|
||||||
|
var skills = SkillService.Skills;
|
||||||
|
if (skills.Count == 0)
|
||||||
|
{
|
||||||
|
SkillListPanel.Children.Add(new Border
|
||||||
|
{
|
||||||
|
Background = TryFindResource("ItemBackground") as Brush ?? Brushes.WhiteSmoke,
|
||||||
|
BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.LightGray,
|
||||||
|
BorderThickness = new Thickness(1),
|
||||||
|
CornerRadius = new CornerRadius(10),
|
||||||
|
Padding = new Thickness(12, 10, 12, 10),
|
||||||
|
Child = new TextBlock
|
||||||
|
{
|
||||||
|
Text = "로드된 스킬이 없습니다. 스킬 폴더를 열어 `.skill.md` 또는 `SKILL.md` 파일을 추가한 뒤 저장하면 다시 불러옵니다.",
|
||||||
|
FontSize = 11,
|
||||||
|
TextWrapping = TextWrapping.Wrap,
|
||||||
|
Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var groups = new[]
|
||||||
|
{
|
||||||
|
new { Title = "내장 스킬", Items = skills.Where(s => string.IsNullOrWhiteSpace(s.Requires)).ToList() },
|
||||||
|
new { Title = "고급 스킬", Items = skills.Where(s => !string.IsNullOrWhiteSpace(s.Requires)).ToList() },
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var group in groups)
|
||||||
|
{
|
||||||
|
if (group.Items.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SkillListPanel.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = $"{group.Title} ({group.Items.Count})",
|
||||||
|
FontSize = 12,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
|
Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.Black,
|
||||||
|
Margin = new Thickness(0, 0, 0, 6),
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var skill in group.Items.OrderBy(s => s.Name, StringComparer.OrdinalIgnoreCase))
|
||||||
|
SkillListPanel.Children.Add(CreateSkillCard(skill));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Border CreateSkillCard(SkillDefinition skill)
|
||||||
|
{
|
||||||
|
var available = skill.IsAvailable;
|
||||||
|
var accentBrush = TryFindResource("AccentColor") as Brush ?? Brushes.DodgerBlue;
|
||||||
|
var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||||
|
var card = new Border
|
||||||
|
{
|
||||||
|
Background = TryFindResource("ItemBackground") as Brush ?? Brushes.WhiteSmoke,
|
||||||
|
BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.LightGray,
|
||||||
|
BorderThickness = new Thickness(1),
|
||||||
|
CornerRadius = new CornerRadius(10),
|
||||||
|
Padding = new Thickness(12, 10, 12, 10),
|
||||||
|
Margin = new Thickness(0, 0, 0, 6),
|
||||||
|
Opacity = available ? 1.0 : 0.72,
|
||||||
|
};
|
||||||
|
static Brush HexBrush(string hex) => (Brush)new BrushConverter().ConvertFromString(hex)!;
|
||||||
|
|
||||||
|
var root = new StackPanel();
|
||||||
|
var header = new DockPanel();
|
||||||
|
header.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = "/" + skill.Name,
|
||||||
|
FontSize = 12.5,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
|
Foreground = available ? accentBrush : secondaryText,
|
||||||
|
});
|
||||||
|
|
||||||
|
var badge = new Border
|
||||||
|
{
|
||||||
|
Background = available
|
||||||
|
? HexBrush("#ECFDF5")
|
||||||
|
: HexBrush("#FEF2F2"),
|
||||||
|
BorderBrush = available
|
||||||
|
? HexBrush("#BBF7D0")
|
||||||
|
: HexBrush("#FECACA"),
|
||||||
|
BorderThickness = new Thickness(1),
|
||||||
|
CornerRadius = new CornerRadius(999),
|
||||||
|
Padding = new Thickness(7, 2, 7, 2),
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Right,
|
||||||
|
Child = new TextBlock
|
||||||
|
{
|
||||||
|
Text = available ? "사용 가능" : (string.IsNullOrWhiteSpace(skill.UnavailableHint) ? "사용 불가" : skill.UnavailableHint),
|
||||||
|
FontSize = 10,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
|
Foreground = available ? HexBrush("#166534") : HexBrush("#991B1B"),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DockPanel.SetDock(badge, Dock.Right);
|
||||||
|
header.Children.Add(badge);
|
||||||
|
root.Children.Add(header);
|
||||||
|
|
||||||
|
root.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = string.IsNullOrWhiteSpace(skill.Label) ? skill.Description : $"{skill.Label} · {skill.Description}",
|
||||||
|
Margin = new Thickness(0, 4, 0, 0),
|
||||||
|
FontSize = 11,
|
||||||
|
TextWrapping = TextWrapping.Wrap,
|
||||||
|
Foreground = secondaryText,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(skill.Requires))
|
||||||
|
{
|
||||||
|
root.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = $"필요 런타임: {skill.Requires}",
|
||||||
|
Margin = new Thickness(0, 4, 0, 0),
|
||||||
|
FontSize = 10.5,
|
||||||
|
Foreground = secondaryText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
card.Child = root;
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadToolCards()
|
||||||
|
{
|
||||||
|
if (_toolCardsLoaded || ToolCardsPanel == null) return;
|
||||||
|
_toolCardsLoaded = true;
|
||||||
|
|
||||||
|
using var tools = ToolRegistry.CreateDefault();
|
||||||
|
var categories = new Dictionary<string, List<IAgentTool>>
|
||||||
|
{
|
||||||
|
["파일/검색"] = new(),
|
||||||
|
["문서/리뷰"] = new(),
|
||||||
|
["코드/개발"] = new(),
|
||||||
|
["시스템/유틸"] = new(),
|
||||||
|
};
|
||||||
|
var toolCategoryMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["file_read"] = "파일/검색", ["file_write"] = "파일/검색", ["file_edit"] = "파일/검색", ["glob"] = "파일/검색", ["grep"] = "파일/검색",
|
||||||
|
["document_review"] = "문서/리뷰", ["format_convert"] = "문서/리뷰", ["template_render"] = "문서/리뷰", ["text_summarize"] = "문서/리뷰",
|
||||||
|
["build_run"] = "코드/개발", ["git_tool"] = "코드/개발", ["lsp"] = "코드/개발", ["code_review"] = "코드/개발", ["test_loop"] = "코드/개발",
|
||||||
|
["process"] = "시스템/유틸", ["notify"] = "시스템/유틸", ["clipboard"] = "시스템/유틸", ["env"] = "시스템/유틸", ["skill_manager"] = "시스템/유틸",
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var tool in tools.All)
|
||||||
|
{
|
||||||
|
var category = toolCategoryMap.TryGetValue(tool.Name, out var mapped) ? mapped : "시스템/유틸";
|
||||||
|
categories[category].Add(tool);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var category in categories)
|
||||||
|
{
|
||||||
|
if (category.Value.Count == 0) continue;
|
||||||
|
ToolCardsPanel.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = $"{category.Key} ({category.Value.Count})",
|
||||||
|
FontSize = 12,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
|
Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.Black,
|
||||||
|
Margin = new Thickness(0, 10, 0, 6),
|
||||||
|
});
|
||||||
|
|
||||||
|
var wrap = new WrapPanel();
|
||||||
|
foreach (var tool in category.Value.OrderBy(t => t.Name, StringComparer.OrdinalIgnoreCase))
|
||||||
|
wrap.Children.Add(CreateToolCard(tool));
|
||||||
|
ToolCardsPanel.Children.Add(wrap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Border CreateToolCard(IAgentTool tool)
|
||||||
|
{
|
||||||
|
var enabled = !_disabledTools.Contains(tool.Name);
|
||||||
|
var card = new Border
|
||||||
|
{
|
||||||
|
Background = TryFindResource("ItemBackground") as Brush ?? Brushes.WhiteSmoke,
|
||||||
|
BorderBrush = enabled
|
||||||
|
? (TryFindResource("BorderColor") as Brush ?? Brushes.LightGray)
|
||||||
|
: new SolidColorBrush(Color.FromRgb(0xDC, 0x26, 0x26)),
|
||||||
|
BorderThickness = new Thickness(1),
|
||||||
|
CornerRadius = new CornerRadius(10),
|
||||||
|
Padding = new Thickness(10, 8, 10, 8),
|
||||||
|
Margin = new Thickness(0, 0, 8, 8),
|
||||||
|
Width = 232,
|
||||||
|
};
|
||||||
|
|
||||||
|
var grid = new Grid();
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||||
|
|
||||||
|
var info = new StackPanel();
|
||||||
|
info.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = tool.Name,
|
||||||
|
FontSize = 12,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
|
Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.Black,
|
||||||
|
});
|
||||||
|
var desc = tool.Description.Length > 56 ? tool.Description[..56] + "…" : tool.Description;
|
||||||
|
info.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = desc,
|
||||||
|
FontSize = 10.5,
|
||||||
|
Margin = new Thickness(0, 3, 0, 0),
|
||||||
|
Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
|
||||||
|
TextWrapping = TextWrapping.Wrap,
|
||||||
|
});
|
||||||
|
grid.Children.Add(info);
|
||||||
|
|
||||||
|
var toggle = new CheckBox
|
||||||
|
{
|
||||||
|
IsChecked = enabled,
|
||||||
|
Style = TryFindResource("ToggleSwitch") as Style,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
Margin = new Thickness(8, 0, 0, 0),
|
||||||
|
};
|
||||||
|
toggle.Checked += (_, _) =>
|
||||||
|
{
|
||||||
|
_disabledTools.Remove(tool.Name);
|
||||||
|
card.BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.LightGray;
|
||||||
|
};
|
||||||
|
toggle.Unchecked += (_, _) =>
|
||||||
|
{
|
||||||
|
_disabledTools.Add(tool.Name);
|
||||||
|
card.BorderBrush = new SolidColorBrush(Color.FromRgb(0xDC, 0x26, 0x26));
|
||||||
|
};
|
||||||
|
Grid.SetColumn(toggle, 1);
|
||||||
|
grid.Children.Add(toggle);
|
||||||
|
card.Child = grid;
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnAddHook_Click(object sender, RoutedEventArgs e) => ShowHookEditDialog(null, -1);
|
||||||
|
|
||||||
|
private void ShowHookEditDialog(AgentHookEntry? existing, int index)
|
||||||
|
{
|
||||||
|
var dlg = new Window
|
||||||
|
{
|
||||||
|
Title = existing == null ? "훅 추가" : "훅 편집",
|
||||||
|
Width = 420,
|
||||||
|
SizeToContent = SizeToContent.Height,
|
||||||
|
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||||
|
Owner = this,
|
||||||
|
ResizeMode = ResizeMode.NoResize,
|
||||||
|
WindowStyle = WindowStyle.None,
|
||||||
|
AllowsTransparency = true,
|
||||||
|
Background = Brushes.Transparent,
|
||||||
|
ShowInTaskbar = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var bgBrush = TryFindResource("LauncherBackground") as Brush ?? Brushes.White;
|
||||||
|
var fgBrush = TryFindResource("PrimaryText") as Brush ?? Brushes.Black;
|
||||||
|
var subBrush = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||||
|
var itemBg = TryFindResource("ItemBackground") as Brush ?? Brushes.WhiteSmoke;
|
||||||
|
var borderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.Gray;
|
||||||
|
|
||||||
|
var root = new Border
|
||||||
|
{
|
||||||
|
Background = bgBrush,
|
||||||
|
BorderBrush = borderBrush,
|
||||||
|
BorderThickness = new Thickness(1),
|
||||||
|
CornerRadius = new CornerRadius(12),
|
||||||
|
Padding = new Thickness(18),
|
||||||
|
};
|
||||||
|
var stack = new StackPanel();
|
||||||
|
root.Child = stack;
|
||||||
|
stack.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = existing == null ? "도구 훅 추가" : "도구 훅 편집",
|
||||||
|
FontSize = 15,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
|
Foreground = fgBrush,
|
||||||
|
});
|
||||||
|
|
||||||
|
TextBox AddField(string label, string value)
|
||||||
|
{
|
||||||
|
stack.Children.Add(new TextBlock { Text = label, Foreground = subBrush, FontSize = 12, Margin = new Thickness(0, 10, 0, 4) });
|
||||||
|
var box = new TextBox
|
||||||
|
{
|
||||||
|
Text = value,
|
||||||
|
Padding = new Thickness(10, 7, 10, 7),
|
||||||
|
Background = itemBg,
|
||||||
|
BorderBrush = borderBrush,
|
||||||
|
Foreground = fgBrush,
|
||||||
|
FontSize = 12,
|
||||||
|
};
|
||||||
|
stack.Children.Add(box);
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nameBox = AddField("이름", existing?.Name ?? "");
|
||||||
|
var toolBox = AddField("대상 도구 (* = 전체)", existing?.ToolName ?? "*");
|
||||||
|
var pathBox = AddField("스크립트 경로", existing?.ScriptPath ?? "");
|
||||||
|
var argsBox = AddField("인수", existing?.Arguments ?? "");
|
||||||
|
|
||||||
|
var timingPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 10, 0, 0) };
|
||||||
|
var pre = new RadioButton { Content = "Pre", Foreground = fgBrush, IsChecked = (existing?.Timing ?? "post") == "pre", Margin = new Thickness(0, 0, 12, 0) };
|
||||||
|
var post = new RadioButton { Content = "Post", Foreground = fgBrush, IsChecked = (existing?.Timing ?? "post") != "pre" };
|
||||||
|
timingPanel.Children.Add(pre);
|
||||||
|
timingPanel.Children.Add(post);
|
||||||
|
stack.Children.Add(timingPanel);
|
||||||
|
|
||||||
|
var actions = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right, Margin = new Thickness(0, 16, 0, 0) };
|
||||||
|
var cancel = new Button { Content = "취소", Padding = new Thickness(14, 6, 14, 6), Margin = new Thickness(0, 0, 8, 0) };
|
||||||
|
cancel.Click += (_, _) => dlg.Close();
|
||||||
|
var save = new Button { Content = "저장", Padding = new Thickness(14, 6, 14, 6), IsDefault = true };
|
||||||
|
save.Click += (_, _) =>
|
||||||
|
{
|
||||||
|
var entry = new AgentHookEntry
|
||||||
|
{
|
||||||
|
Name = nameBox.Text.Trim(),
|
||||||
|
ToolName = string.IsNullOrWhiteSpace(toolBox.Text) ? "*" : toolBox.Text.Trim(),
|
||||||
|
Timing = pre.IsChecked == true ? "pre" : "post",
|
||||||
|
ScriptPath = pathBox.Text.Trim(),
|
||||||
|
Arguments = argsBox.Text.Trim(),
|
||||||
|
Enabled = existing?.Enabled ?? true,
|
||||||
|
};
|
||||||
|
if (index >= 0 && index < _llm.AgentHooks.Count)
|
||||||
|
_llm.AgentHooks[index] = entry;
|
||||||
|
else
|
||||||
|
_llm.AgentHooks.Add(entry);
|
||||||
|
BuildHookCards();
|
||||||
|
dlg.Close();
|
||||||
|
};
|
||||||
|
actions.Children.Add(cancel);
|
||||||
|
actions.Children.Add(save);
|
||||||
|
stack.Children.Add(actions);
|
||||||
|
|
||||||
|
dlg.Content = root;
|
||||||
|
dlg.ShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildHookCards()
|
||||||
|
{
|
||||||
|
if (HookListPanel == null) return;
|
||||||
|
HookListPanel.Children.Clear();
|
||||||
|
|
||||||
|
for (var i = 0; i < _llm.AgentHooks.Count; i++)
|
||||||
|
{
|
||||||
|
var hook = _llm.AgentHooks[i];
|
||||||
|
var index = i;
|
||||||
|
var card = new Border
|
||||||
|
{
|
||||||
|
Background = TryFindResource("ItemBackground") as Brush ?? Brushes.WhiteSmoke,
|
||||||
|
BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.LightGray,
|
||||||
|
BorderThickness = new Thickness(1),
|
||||||
|
CornerRadius = new CornerRadius(10),
|
||||||
|
Padding = new Thickness(12, 10, 12, 10),
|
||||||
|
Margin = new Thickness(0, 0, 0, 6),
|
||||||
|
};
|
||||||
|
var grid = new Grid();
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||||
|
|
||||||
|
var info = new StackPanel();
|
||||||
|
info.Children.Add(new TextBlock { Text = hook.Name, FontSize = 12.5, FontWeight = FontWeights.SemiBold, Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.Black });
|
||||||
|
info.Children.Add(new TextBlock { Text = $"{hook.Timing?.ToUpperInvariant() ?? "POST"} · {hook.ToolName}", FontSize = 10.5, Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, Margin = new Thickness(0, 2, 0, 0) });
|
||||||
|
info.Children.Add(new TextBlock { Text = hook.ScriptPath, FontSize = 10.5, Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, Margin = new Thickness(0, 2, 0, 0), TextTrimming = TextTrimming.CharacterEllipsis });
|
||||||
|
grid.Children.Add(info);
|
||||||
|
|
||||||
|
var actionRow = new StackPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center };
|
||||||
|
var toggle = new CheckBox { IsChecked = hook.Enabled, Style = TryFindResource("ToggleSwitch") as Style, Margin = new Thickness(0, 0, 8, 0) };
|
||||||
|
toggle.Checked += (_, _) => hook.Enabled = true;
|
||||||
|
toggle.Unchecked += (_, _) => hook.Enabled = false;
|
||||||
|
var edit = new Button { Content = "편집", Style = TryFindResource("OutlineHoverBtn") as Style, Margin = new Thickness(0, 0, 6, 0) };
|
||||||
|
edit.Click += (_, _) => ShowHookEditDialog(_llm.AgentHooks[index], index);
|
||||||
|
var delete = new Button { Content = "삭제", Style = TryFindResource("OutlineHoverBtn") as Style };
|
||||||
|
delete.Click += (_, _) => { _llm.AgentHooks.RemoveAt(index); BuildHookCards(); };
|
||||||
|
actionRow.Children.Add(toggle);
|
||||||
|
actionRow.Children.Add(edit);
|
||||||
|
actionRow.Children.Add(delete);
|
||||||
|
Grid.SetColumn(actionRow, 1);
|
||||||
|
grid.Children.Add(actionRow);
|
||||||
|
|
||||||
|
card.Child = grid;
|
||||||
|
HookListPanel.Children.Add(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnAddMcpServer_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var nameDialog = new InputDialog("MCP 서버 추가", "서버 이름:", placeholder: "예: filesystem");
|
||||||
|
nameDialog.Owner = this;
|
||||||
|
if (nameDialog.ShowDialog() != true || string.IsNullOrWhiteSpace(nameDialog.ResponseText)) return;
|
||||||
|
|
||||||
|
var commandDialog = new InputDialog("MCP 서버 추가", "실행 명령:", placeholder: "예: npx -y @modelcontextprotocol/server-filesystem");
|
||||||
|
commandDialog.Owner = this;
|
||||||
|
if (commandDialog.ShowDialog() != true || string.IsNullOrWhiteSpace(commandDialog.ResponseText)) return;
|
||||||
|
|
||||||
|
_llm.McpServers.Add(new McpServerEntry
|
||||||
|
{
|
||||||
|
Name = nameDialog.ResponseText.Trim(),
|
||||||
|
Command = commandDialog.ResponseText.Trim(),
|
||||||
|
Enabled = true,
|
||||||
|
});
|
||||||
|
BuildMcpServerCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildMcpServerCards()
|
||||||
|
{
|
||||||
|
if (McpServerListPanel == null) return;
|
||||||
|
McpServerListPanel.Children.Clear();
|
||||||
|
|
||||||
|
foreach (var entry in _llm.McpServers.ToList())
|
||||||
|
{
|
||||||
|
var card = new Border
|
||||||
|
{
|
||||||
|
Background = TryFindResource("ItemBackground") as Brush ?? Brushes.WhiteSmoke,
|
||||||
|
BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.LightGray,
|
||||||
|
BorderThickness = new Thickness(1),
|
||||||
|
CornerRadius = new CornerRadius(10),
|
||||||
|
Padding = new Thickness(12, 10, 12, 10),
|
||||||
|
Margin = new Thickness(0, 0, 0, 6),
|
||||||
|
};
|
||||||
|
var grid = new Grid();
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||||
|
|
||||||
|
var info = new StackPanel();
|
||||||
|
info.Children.Add(new TextBlock { Text = entry.Name, FontSize = 12.5, FontWeight = FontWeights.SemiBold, Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.Black });
|
||||||
|
info.Children.Add(new TextBlock { Text = entry.Command, FontSize = 10.5, Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, Margin = new Thickness(0, 2, 0, 0), TextTrimming = TextTrimming.CharacterEllipsis });
|
||||||
|
grid.Children.Add(info);
|
||||||
|
|
||||||
|
var actionRow = new StackPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center };
|
||||||
|
var toggle = new CheckBox { IsChecked = entry.Enabled, Style = TryFindResource("ToggleSwitch") as Style, Margin = new Thickness(0, 0, 8, 0) };
|
||||||
|
toggle.Checked += (_, _) => entry.Enabled = true;
|
||||||
|
toggle.Unchecked += (_, _) => entry.Enabled = false;
|
||||||
|
var delete = new Button { Content = "삭제", Style = TryFindResource("OutlineHoverBtn") as Style };
|
||||||
|
delete.Click += (_, _) => { _llm.McpServers.Remove(entry); BuildMcpServerCards(); };
|
||||||
|
actionRow.Children.Add(toggle);
|
||||||
|
actionRow.Children.Add(delete);
|
||||||
|
Grid.SetColumn(actionRow, 1);
|
||||||
|
grid.Children.Add(actionRow);
|
||||||
|
|
||||||
|
card.Child = grid;
|
||||||
|
McpServerListPanel.Children.Add(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildFallbackModelsPanel()
|
||||||
|
{
|
||||||
|
if (FallbackModelsPanel == null) return;
|
||||||
|
FallbackModelsPanel.Children.Clear();
|
||||||
|
|
||||||
|
var sections = new (string Service, string Label, List<string> Models)[]
|
||||||
|
{
|
||||||
|
("ollama", "Ollama", GetModelCandidates("ollama")),
|
||||||
|
("vllm", "vLLM", GetModelCandidates("vllm")),
|
||||||
|
("gemini", "Gemini", new[] { _llm.GeminiModel }.Where(x => !string.IsNullOrWhiteSpace(x)).ToList()!),
|
||||||
|
("claude", "Claude", new[] { _llm.ClaudeModel }.Where(x => !string.IsNullOrWhiteSpace(x)).ToList()!),
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var section in sections)
|
||||||
|
{
|
||||||
|
FallbackModelsPanel.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = section.Label,
|
||||||
|
FontSize = 11.5,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
|
Margin = new Thickness(0, 8, 0, 4),
|
||||||
|
Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.Black,
|
||||||
|
});
|
||||||
|
|
||||||
|
var models = section.Models.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||||
|
if (models.Count == 0)
|
||||||
|
{
|
||||||
|
FallbackModelsPanel.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = "등록된 모델 없음",
|
||||||
|
FontSize = 10.5,
|
||||||
|
Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
|
||||||
|
Margin = new Thickness(8, 0, 0, 4),
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var model in models)
|
||||||
|
{
|
||||||
|
var key = $"{section.Service}:{model}";
|
||||||
|
var row = new Grid { Margin = new Thickness(8, 2, 0, 2) };
|
||||||
|
row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||||
|
row.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||||
|
row.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = model,
|
||||||
|
FontSize = 11.5,
|
||||||
|
Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.Black,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
});
|
||||||
|
var toggle = new CheckBox
|
||||||
|
{
|
||||||
|
IsChecked = _llm.FallbackModels.Contains(key, StringComparer.OrdinalIgnoreCase),
|
||||||
|
Style = TryFindResource("ToggleSwitch") as Style,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
};
|
||||||
|
toggle.Checked += (_, _) =>
|
||||||
|
{
|
||||||
|
if (!_llm.FallbackModels.Contains(key, StringComparer.OrdinalIgnoreCase))
|
||||||
|
_llm.FallbackModels.Add(key);
|
||||||
|
};
|
||||||
|
toggle.Unchecked += (_, _) => _llm.FallbackModels.RemoveAll(x => x.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||||
|
Grid.SetColumn(toggle, 1);
|
||||||
|
row.Children.Add(toggle);
|
||||||
|
FallbackModelsPanel.Children.Add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void BtnOpenFullSettings_Click(object sender, RoutedEventArgs e)
|
private void BtnOpenFullSettings_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (System.Windows.Application.Current is App app)
|
if (System.Windows.Application.Current is App app)
|
||||||
|
|||||||
Reference in New Issue
Block a user