AX Agent 코워크·코드 흐름과 컨텍스트 관리를 claude-code 기준으로 대폭 정리

- 코워크·코드 프롬프트, 도구 선택, 문서 생성/검증 흐름을 claude-code 동등 품질 기준으로 재정렬함

- OpenAI/vLLM 경로의 오래된 tool history를 평탄화하고 최근 이력만 구조화해 컨텍스트 직렬화를 경량화함

- AX Agent UI를 테마 기준으로 재구성하고 플랜 승인/오버레이/이벤트 렌더링/명령 입력 상호작용을 개선함

- 파일 후보 제안, 반복 경로 정체 복구, LSP 보강, 문서·PPT 처리 개선, 설정/서비스 인터페이스 정리를 함께 반영함

- README.md 및 docs/DEVELOPMENT.md를 작업 시점별로 갱신함

- 검증: 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:
2026-04-12 22:02:14 +09:00
parent b8f4df1892
commit fb0bea41f7
137 changed files with 18532 additions and 1144 deletions

View File

@@ -3,6 +3,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
xmlns:local="clr-namespace:AxCopilot.Views"
xmlns:conv="clr-namespace:AxCopilot.Themes"
xmlns:vm="clr-namespace:AxCopilot.ViewModels"
Title="AX Copilot — AX Agent"
Width="1180" Height="880"
MinWidth="780" MinHeight="560"
@@ -23,6 +25,262 @@
</WindowChrome.WindowChrome>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
<conv:HexToBrushConverter x:Key="HexToBrush"/>
<conv:NullToCollapsedConverter x:Key="NullToVis"/>
<!-- ── 글로벌 슬림 커스텀 스크롤바 ── -->
<SolidColorBrush x:Key="ScrollThumbBrush" Color="#888888"/>
<!-- Thumb (드래그 핸들) -->
<Style x:Key="SlimScrollThumb" TargetType="Thumb">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Border CornerRadius="3"
Background="{DynamicResource ScrollThumbBrush}"
Opacity="0.45"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 수직 스크롤바 -->
<Style TargetType="ScrollBar">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Width" Value="6"/>
<Setter Property="MinWidth" Value="6"/>
<Setter Property="Opacity" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid>
<Border Background="Transparent" CornerRadius="3"/>
<Track x:Name="PART_Track" IsDirectionReversed="True">
<Track.Thumb>
<Thumb Style="{StaticResource SlimScrollThumb}"/>
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- 수평 스크롤바도 슬림하게 -->
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="6"/>
<Setter Property="MinHeight" Value="6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid>
<Border Background="Transparent" CornerRadius="3"/>
<Track x:Name="PART_Track" IsDirectionReversed="False">
<Track.Thumb>
<Thumb Style="{StaticResource SlimScrollThumb}"/>
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<!-- ScrollViewer: 호버 시 스크롤바 페이드 인/아웃 -->
<Style TargetType="ScrollViewer">
<Setter Property="OverridesDefaultStyle" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Grid>
<ScrollContentPresenter Margin="{TemplateBinding Padding}"
CanContentScroll="{TemplateBinding CanContentScroll}"
CanHorizontallyScroll="False"
CanVerticallyScroll="False"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"/>
<ScrollBar x:Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{TemplateBinding VerticalOffset}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Margin="0,2,0,2"/>
<ScrollBar x:Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
VerticalAlignment="Bottom"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Value="{TemplateBinding HorizontalOffset}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Margin="2,0,2,1"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_VerticalScrollBar"
Storyboard.TargetProperty="Opacity"
To="1" Duration="0:0:0.15"/>
<DoubleAnimation Storyboard.TargetName="PART_HorizontalScrollBar"
Storyboard.TargetProperty="Opacity"
To="1" Duration="0:0:0.15"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_VerticalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:0.4"/>
<DoubleAnimation Storyboard.TargetName="PART_HorizontalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:0.4"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<CollectionViewSource x:Key="GroupedConversations" Source="{Binding Conversations}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Group"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<!-- ── 대화 목록 항목 DataTemplate ── -->
<DataTemplate x:Key="ConversationItemTemplate" DataType="{x:Type vm:ConversationItemViewModel}">
<Border x:Name="ConvItemBorder"
CornerRadius="5"
Padding="7,4.5,7,4.5"
Cursor="Hand"
Background="Transparent">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Margin" Value="0,1,0,1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBranch}" Value="True">
<Setter Property="Margin" Value="10,1,0,1"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="#104B5EFC"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentColor}"/>
<Setter Property="BorderThickness" Value="1.25,0,0,0"/>
</DataTrigger>
<!-- 호버 효과 (선택 안 된 항목만) -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected}" Value="False"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="#08FFFFFF"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- 아이콘 -->
<TextBlock Grid.Column="0"
Text="{Binding IconText}"
FontFamily="Segoe MDL2 Assets"
FontSize="10.5"
VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{Binding ColorHex, Converter={StaticResource HexToBrush}}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Pinned}" Value="True">
<Setter Property="Foreground" Value="Orange"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsBranch}" Value="True">
<Setter Property="Foreground" Value="#8B5CF6"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<!-- 제목 + 날짜 + 상태 -->
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock x:Name="ConvTitleBlock"
Text="{Binding Title}"
FontSize="11.75"
Foreground="{DynamicResource PrimaryText}"
TextTrimming="CharacterEllipsis">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text="{Binding UpdatedAtText}"
FontSize="9"
Foreground="{DynamicResource HintText}"
Margin="0,1.5,0,0"/>
<TextBlock Text="진행 중"
FontSize="8.8" FontWeight="Medium"
Foreground="#4F46E5"
Margin="0,1.5,0,0"
Visibility="{Binding IsRunning, Converter={StaticResource BoolToVis}}"/>
<TextBlock FontSize="8.9"
Margin="0,1.5,0,0"
TextTrimming="CharacterEllipsis"
Visibility="{Binding HasRunStatus, Converter={StaticResource BoolToVis}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding RunStatusText}"/>
<Setter Property="Foreground" Value="{DynamicResource SecondaryText}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasFailed}" Value="True">
<Setter Property="Foreground" Value="#B91C1C"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
<!-- 카테고리 변경 버튼 (호버 시 표시) -->
<Button x:Name="ConvCatBtn" Grid.Column="2"
Background="Transparent" BorderThickness="0"
Cursor="Hand" Width="20" Height="20" Padding="0"
Opacity="0.72" Visibility="Collapsed"
VerticalAlignment="Center">
<TextBlock Text="&#xE70F;" FontFamily="Segoe MDL2 Assets" FontSize="9"
Foreground="{DynamicResource SecondaryText}"/>
</Button>
</Grid>
</Border>
<DataTemplate.Triggers>
<!-- 호버 시 카테고리 버튼 표시 -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Border}, Path=IsMouseOver}" Value="True">
<Setter TargetName="ConvCatBtn" Property="Visibility" Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<!-- 사이드바 버튼 -->
<Style x:Key="GhostBtn" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
@@ -289,13 +547,16 @@
<Style x:Key="FooterChipBtn" TargetType="Button" BasedOn="{StaticResource OutlineHoverBtn}">
<Setter Property="Padding" Value="10,5"/>
<Setter Property="MinHeight" Value="30"/>
<Setter Property="Background" Value="{DynamicResource LauncherBackground}"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderColor}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd"
Background="{DynamicResource LauncherBackground}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="10"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
@@ -714,6 +975,7 @@
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xE721;" FontFamily="Segoe MDL2 Assets" FontSize="13.5"
Foreground="{DynamicResource SecondaryText}" VerticalAlignment="Center"/>
@@ -760,7 +1022,24 @@
VerticalAlignment="Center"/>
</StackPanel>
</Button>
<Button Grid.Column="4"
<Button x:Name="BtnArchiveFilter" Grid.Column="4"
Style="{StaticResource GhostBtn}"
Padding="7,3.5" MinWidth="50"
Margin="5,0,0,0"
VerticalAlignment="Center"
Click="BtnArchiveFilter_Click"
ToolTip="아카이브 필터 전환">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE7B7;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,3,0"/>
<TextBlock x:Name="ArchiveFilterLabel" Text="보관"
FontSize="12" FontWeight="SemiBold"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
</StackPanel>
</Button>
<Button Grid.Column="5"
Style="{StaticResource GhostBtn}"
Padding="7,4"
Margin="5,0,0,0"
@@ -904,9 +1183,55 @@
</Border>
<!-- 대화 목록 -->
<ScrollViewer Grid.Row="4" VerticalScrollBarVisibility="Auto"
<ScrollViewer x:Name="ConversationListScrollViewer"
Grid.Row="4" VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled">
<StackPanel x:Name="ConversationPanel" Margin="6,0,6,0"/>
<StackPanel>
<!-- 빈 상태 메시지 -->
<TextBlock Text="{Binding EmptyConversationText}"
FontSize="12"
Foreground="{DynamicResource SecondaryText}"
HorizontalAlignment="Center"
Margin="0,20,0,0"
Visibility="{Binding EmptyConversationText, Converter={StaticResource NullToVis}}"/>
<!-- ViewModel-bound ItemsControl (그룹 헤더 + DataTemplate) -->
<ItemsControl x:Name="ConversationItemsControl"
ItemsSource="{Binding Source={StaticResource GroupedConversations}}"
ItemTemplate="{StaticResource ConversationItemTemplate}"
Margin="6,0,6,0">
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
FontSize="12" FontWeight="SemiBold"
Foreground="{DynamicResource SecondaryText}"
Margin="8,10,0,4"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
<!-- 더 보기 버튼 -->
<Border x:Name="LoadMoreBorder"
CornerRadius="8" Cursor="Hand"
Padding="8,10" Margin="6,4,6,4"
Background="Transparent"
Visibility="{Binding HasMoreConversations, Converter={StaticResource BoolToVis}}"
MouseLeftButtonUp="LoadMoreBorder_Click">
<TextBlock HorizontalAlignment="Center" FontSize="12"
Foreground="{DynamicResource AccentColor}">
<Run Text="더 보기 ("/>
<Run Text="{Binding RemainingConversationCount, Mode=OneWay}"/>
<Run Text="개 남음)"/>
</TextBlock>
</Border>
<!-- 레거시 ConversationPanel (Collapsed, 이름변경 TextBlock 검색용으로 유지) -->
<StackPanel x:Name="ConversationPanel" Margin="6,0,6,0" Visibility="Collapsed"/>
</StackPanel>
</ScrollViewer>
<!-- 하단: 삭제 -->
@@ -1008,7 +1333,7 @@
<StackPanel Grid.Column="0" Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Grid VerticalAlignment="Center">
<TextBlock x:Name="ChatTitle" Text="" FontSize="12.25" FontWeight="SemiBold"
<TextBlock x:Name="ChatTitle" Text="{Binding ChatTitle, FallbackValue=''}" FontSize="12.25" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"
VerticalAlignment="Center" TextTrimming="CharacterEllipsis"
MaxWidth="360" Cursor="Hand"
@@ -1380,7 +1705,7 @@
<ListBox x:Name="MessageList" Grid.Row="3"
Background="{DynamicResource LauncherBackground}"
BorderThickness="0"
Padding="24,12,24,8"
Padding="24,12,0,8"
HorizontalContentAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
@@ -1389,7 +1714,7 @@
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingPanel.CacheLength="3"
VirtualizingPanel.CacheLength="1,2"
VirtualizingPanel.CacheLengthUnit="Page"
UseLayoutRounding="True">
<ListBox.ItemsPanel>
@@ -1465,6 +1790,27 @@
VerticalAlignment="Stretch"
MaxWidth="960"
Margin="24,16,24,16">
<!-- 마스코트 캐릭터: EmptyState Grid 위를 자유롭게 돌아다니는 오버레이.
배경 없음(Transparent), 텍스트 위에 겹쳐서 표시. -->
<Canvas x:Name="MascotCanvas"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Visibility="Collapsed" ClipToBounds="False"
IsHitTestVisible="False">
<Image x:Name="MascotImage" Width="300" Height="300"
Canvas.Left="0" Canvas.Top="20"
RenderTransformOrigin="0.5,1.0"
RenderOptions.BitmapScalingMode="NearestNeighbor"
Stretch="Uniform" Opacity="0.92">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="MascotScale" ScaleX="1" ScaleY="1"/>
<RotateTransform x:Name="MascotRotate" Angle="0"/>
<TranslateTransform x:Name="MascotTranslate" X="0" Y="0"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Canvas>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,8,0,8">
@@ -1496,7 +1842,8 @@
Padding="0,4,0,8">
<!-- 대화 주제 버튼 (프리셋에서 동적 생성) -->
<WrapPanel x:Name="TopicButtonPanel" HorizontalAlignment="Center"
Margin="0,0,0,8"/>
Margin="0,0,0,8"
Background="Transparent"/>
</ScrollViewer>
</StackPanel>
</Grid>
@@ -1786,11 +2133,24 @@
VerticalAlignment="Bottom">
<StackPanel HorizontalAlignment="Stretch">
<!-- ── 펄스 닷 애니메이션 (AI 처리 중) ── -->
<Border x:Name="PulseDotBar"
Visibility="Collapsed"
HorizontalAlignment="Left"
Margin="6,0,0,10">
<!-- ── 스트리밍 상태 행: 좌측 펄스 닷 + 우측 경과 시간/토큰 ── -->
<Grid Margin="0,0,0,4">
<TextBlock x:Name="StreamMetricsLabel"
Visibility="Collapsed"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="0,0,4,0"
FontSize="11"
Foreground="{DynamicResource SecondaryText}"
Opacity="0.7"
Text="0:00 · ↓ 0 tokens"/>
<!-- ── 펄스 닷 애니메이션 (AI 처리 중) ── -->
<Border x:Name="PulseDotBar"
Visibility="Collapsed"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="6,0,0,0">
<StackPanel>
<!-- 레거시 펄스 점 (코드비하인드 참조용, 화면에 표시 안 함) -->
<Ellipse x:Name="PulseDot1" Width="7" Height="7" Fill="{DynamicResource AccentColor}" Opacity="0.3" Visibility="Collapsed"/>
@@ -1864,6 +2224,7 @@
Text=""/>
</StackPanel>
</Border>
</Grid>
<Border x:Name="CodeRepoSummaryBar"
Visibility="Collapsed"
@@ -2080,6 +2441,24 @@
<StackPanel x:Name="DraftQueuePanel"
Visibility="Collapsed"
Margin="0,0,0,6"/>
<Border x:Name="FileMentionSuggestionCard"
Visibility="Collapsed"
Background="{DynamicResource HintBackground}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="1"
CornerRadius="12"
Padding="10,8"
Margin="0,0,0,6">
<StackPanel>
<TextBlock x:Name="FileMentionSuggestionTitle"
FontSize="11.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"
Text="파일 후보"/>
<WrapPanel x:Name="FileMentionSuggestionChipPanel"
Margin="0,6,0,0"/>
</StackPanel>
</Border>
<!-- 무지개 글로우 + 입력 영역 (겹침 레이아웃) -->
<Grid>
<!-- 무지개 글로우 외부 테두리 (메시지 전송 시 애니메이션) -->
@@ -2422,7 +2801,7 @@
PreviewKeyDown="InputBox_PreviewKeyDown"
TextChanged="InputBox_TextChanged"
TextWrapping="Wrap"
MinHeight="40" MaxHeight="148"
MinHeight="40" MaxHeight="160"
VerticalScrollBarVisibility="Auto"/>
<!-- 워터마크 (프롬프트 카드 안내문구) -->
<TextBlock x:Name="InputWatermark"
@@ -2529,17 +2908,15 @@
<!-- ── 폴더 바 + 권한 메뉴 (입력 하단, Cowork/Code 탭 전용) ── -->
<Border x:Name="FolderBar" Visibility="Collapsed"
Margin="4,4,4,0"
MinHeight="32"
Margin="0,2,0,0"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="0"
Padding="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <!-- 0: 폴더 아이콘 -->
<ColumnDefinition Width="*"/> <!-- 1: 폴더 경로 -->
<ColumnDefinition Width="Auto"/> <!-- 0: 폴더 -->
<ColumnDefinition Width="*"/> <!-- 1: 여백 -->
<ColumnDefinition Width="Auto"/> <!-- 2: 구분선 -->
<ColumnDefinition Width="Auto"/> <!-- 3: 포맷/디자인 -->
<ColumnDefinition Width="Auto"/> <!-- 4: 구분선 -->
@@ -2548,22 +2925,39 @@
<ColumnDefinition Width="Auto"/> <!-- 7: 메모리 -->
<ColumnDefinition Width="Auto"/> <!-- 8: 구분선 -->
<ColumnDefinition Width="Auto"/> <!-- 9: 권한 -->
<ColumnDefinition Width="Auto"/> <!-- 10: 구분선 -->
<ColumnDefinition Width="Auto"/> <!-- 11: git -->
<ColumnDefinition Width="Auto"/> <!-- 10: 계획 버튼 -->
<ColumnDefinition Width="Auto"/> <!-- 11: 구분선 -->
<ColumnDefinition Width="Auto"/> <!-- 12: git -->
</Grid.ColumnDefinitions>
<!-- 폴더 아이콘 -->
<TextBlock Grid.Column="0" Text="&#xED25;" FontFamily="Segoe MDL2 Assets" FontSize="14"
Foreground="{DynamicResource AccentColor}"
VerticalAlignment="Center" Margin="6,0,4,0"/>
<!-- (A) 폴더 미선택 시: 작은 칩 버튼 -->
<Border x:Name="BtnFolderSelect" Grid.Column="0"
CornerRadius="4" Margin="4,1,0,1"
Padding="6,2,8,2"
BorderThickness="1"
BorderBrush="{DynamicResource SeparatorColor}"
Background="Transparent"
Cursor="Hand" Visibility="Visible"
MouseLeftButtonUp="BtnFolderSelect_Click">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="&#xED25;" FontFamily="Segoe MDL2 Assets" FontSize="10"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="폴더 선택" FontSize="11"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
<!-- 폴더 경로 (클릭 시 최근 폴더 메뉴) -->
<TextBlock x:Name="FolderPathLabel" Grid.Column="1"
Text="폴더를 선택하세요" FontSize="13"
Foreground="{DynamicResource SecondaryText}"
<!-- (B) 폴더 선택 후: 경로 텍스트 -->
<TextBlock x:Name="FolderPathLabel" Grid.Column="0"
Text="{Binding WorkFolderDisplay, FallbackValue=''}"
FontSize="11" Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" TextTrimming="CharacterEllipsis"
Cursor="Hand" MouseLeftButtonUp="FolderPathLabel_Click"
ToolTip="클릭하여 폴더 변경"/>
MaxWidth="300" Cursor="Hand" Margin="6,0,0,0"
Visibility="Collapsed"
MouseLeftButtonUp="FolderPathLabel_CopyClick"
ToolTip="클릭하면 경로가 복사됩니다"/>
<!-- 구분선 -->
<Border Grid.Column="2" Width="1" Height="18" Margin="8,0,4,0"
@@ -2602,24 +2996,42 @@
<!-- 권한 메뉴 -->
<Button x:Name="BtnPermission" Grid.Column="9" Style="{StaticResource FooterChipBtn}"
Padding="10,5" Click="BtnPermission_Click" ToolTip="파일 접근 권한"
BorderThickness="0">
Padding="6,4" Click="BtnPermission_Click" ToolTip="파일 접근 권한"
BorderThickness="0" Background="Transparent">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="PermissionIcon" Text="&#xE8D7;" FontFamily="Segoe MDL2 Assets" FontSize="12"
<TextBlock x:Name="PermissionIcon" Text="&#xE8D7;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock x:Name="PermissionLabel" Text="활용하지 않음" FontSize="12"
<TextBlock x:Name="PermissionLabel" Text="활용하지 않음" FontSize="11"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
<TextBlock Text="&#xE70D;" FontFamily="Segoe MDL2 Assets" FontSize="8"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="4,1,0,0" Opacity="0.6"/>
</StackPanel>
</Button>
<Border x:Name="GitBranchSeparator" Grid.Column="10" Width="1" Height="18" Margin="4,0"
<!-- 계획 버튼 (권한 옆, 계획 존재 시만 표시) -->
<Border x:Name="BtnPlanViewer" Grid.Column="10" Visibility="Collapsed"
CornerRadius="4" Padding="6,3,8,3" Margin="4,0,0,0"
Background="{DynamicResource HintBackground}"
BorderBrush="#10B981" BorderThickness="1"
Cursor="Hand" ToolTip="실행 계획 보기"
MouseLeftButtonUp="BtnPlanViewer_Click">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE8FD;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="#10B981" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock x:Name="PlanViewerLabel" Text="계획" FontSize="12" FontWeight="SemiBold"
Foreground="#10B981" VerticalAlignment="Center"/>
</StackPanel>
</Border>
<Border x:Name="GitBranchSeparator" Grid.Column="11" Width="1" Height="18" Margin="4,0"
Visibility="Collapsed"
Background="{DynamicResource SeparatorColor}"/>
<Button x:Name="BtnGitBranch"
Grid.Column="11"
Grid.Column="12"
Style="{StaticResource FooterChipBtn}"
Padding="10,5"
Margin="2,0,0,0"
@@ -2634,7 +3046,7 @@
VerticalAlignment="Center"
Margin="0,0,4,0"/>
<TextBlock x:Name="GitBranchLabel"
Text="main"
Text="{Binding GitBranchName, FallbackValue='main'}"
FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
@@ -2796,11 +3208,11 @@
Click="BtnToggleExecutionLog_Click"
ToolTip="실행 로그 표시/숨기기">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="ExecutionLogIcon" Text="&#xE7C1;"
<TextBlock x:Name="ExecutionLogIcon" Text="&#xE946;"
FontFamily="Segoe MDL2 Assets" FontSize="8"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,2,0"/>
<TextBlock x:Name="ExecutionLogLabel" Text="실행 로그 0"
<TextBlock x:Name="ExecutionLogLabel" Text="실행이력 · 상세"
FontSize="8.25"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
@@ -2829,20 +3241,7 @@
VerticalAlignment="Center"/>
</StackPanel>
</Border>
<!-- 계획 버튼 (실행 계획 존재 시 표시) -->
<Border x:Name="BtnPlanViewer" Visibility="Collapsed"
CornerRadius="4" Padding="3.5,1" Margin="0,0,5,0"
Background="{DynamicResource HintBackground}"
BorderBrush="{DynamicResource BorderColor}" BorderThickness="1"
Cursor="Hand" ToolTip="실행 계획 보기"
MouseLeftButtonUp="BtnPlanViewer_Click">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE8FD;" FontFamily="Segoe MDL2 Assets" FontSize="9"
Foreground="#10B981" VerticalAlignment="Center" Margin="0,0,3,0"/>
<TextBlock x:Name="PlanViewerLabel" Text="계획" FontSize="9" FontWeight="SemiBold"
Foreground="#10B981" VerticalAlignment="Center"/>
</StackPanel>
</Border>
<!-- 계획 버튼은 하단 툴바(BtnPermission 옆)로 이동됨 -->
<TextBlock x:Name="StatusElapsed" Text="" FontSize="8.25"
Visibility="Collapsed"
Foreground="{DynamicResource SecondaryText}"
@@ -3276,6 +3675,7 @@
Margin="0,0,0,8"/>
<TextBlock x:Name="OverlaySelectedServiceText"
Grid.Column="1"
Text="{Binding ServiceLabel, FallbackValue=''}"
FontSize="12"
Foreground="{DynamicResource PrimaryText}"
Margin="0,0,0,8"/>
@@ -3286,6 +3686,7 @@
<TextBlock x:Name="OverlaySelectedModelText"
Grid.Row="1"
Grid.Column="1"
Text="{Binding ModelLabel, FallbackValue=''}"
FontSize="12"
Foreground="{DynamicResource PrimaryText}"/>
</Grid>
@@ -3791,6 +4192,148 @@
Unchecked="ChkOverlayFeatureToggle_Changed"/>
</Grid>
</Border>
<Border Style="{StaticResource OverlayAdvancedToggleRowStyle}" Margin="0,6,0,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<TextBlock Text="아이콘 글로우 강도"
FontSize="12.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="채팅 본문 런처 아이콘의 글로우(발광) 효과 강도를 조절합니다."
Margin="0,4,0,0"
FontSize="11.5"
TextWrapping="Wrap"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<ComboBox x:Name="CmbOverlayChatIconGlow"
Grid.Column="1"
VerticalAlignment="Center"
Width="100"
Style="{StaticResource OverlayComboBox}"
SelectionChanged="CmbOverlayChatIconGlow_SelectionChanged">
<ComboBoxItem Content="강하게" Tag="strong"/>
<ComboBoxItem Content="적당히" Tag="medium"/>
<ComboBoxItem Content="약하게" Tag="weak"/>
</ComboBox>
</Grid>
</Border>
</StackPanel>
</Border>
<!-- ── 아이콘 애니메이션 설정 ── -->
<Border x:Name="OverlaySectionIconEffects"
Background="Transparent"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="0,1,0,0"
CornerRadius="0"
Padding="0,12,0,0"
Margin="0,0,0,12">
<StackPanel>
<TextBlock Text="아이콘 애니메이션"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="채팅 본문의 런처 아이콘 애니메이션 효과를 조정합니다."
Margin="0,4,0,10"
FontSize="11"
Foreground="{DynamicResource SecondaryText}"/>
<Border Style="{StaticResource OverlayAdvancedToggleRowStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<TextBlock Text="랜덤 애니메이션"
FontSize="12.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="다양한 애니메이션 효과를 랜덤으로 적용합니다. 끄면 숨쉬기 효과만 사용합니다."
Margin="0,4,0,0"
FontSize="11.5"
TextWrapping="Wrap"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<CheckBox x:Name="ChkOverlayEnableChatIconRandomAnim"
Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource ToggleSwitch}"
Checked="ChkOverlayFeatureToggle_Changed"
Unchecked="ChkOverlayFeatureToggle_Changed"/>
</Grid>
</Border>
</StackPanel>
</Border>
<!-- ── 계획 뷰어 스타일 ── -->
<Border x:Name="OverlaySectionPlanViewer"
Background="Transparent"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="0,1,0,0"
CornerRadius="0"
Padding="0,12,0,0"
Margin="0,0,0,12">
<StackPanel>
<TextBlock Text="계획 뷰어"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="문서 계획 승인 시 표시되는 계획 뷰어 창의 스타일을 선택합니다."
Margin="0,4,0,10"
FontSize="11"
Foreground="{DynamicResource SecondaryText}"/>
<Border Style="{StaticResource OverlayAdvancedToggleRowStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<TextBlock Text="새 계획 뷰어 (V2)"
FontSize="12.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="좌측 사이드바 네비게이션 + 우측 마크다운 콘텐츠 레이아웃. 끄면 기존 리스트형 뷰어를 사용합니다."
Margin="0,4,0,0"
FontSize="11.5"
TextWrapping="Wrap"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<CheckBox x:Name="ChkOverlayEnableNewPlanViewer"
Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource ToggleSwitch}"
Checked="ChkOverlayFeatureToggle_Changed"
Unchecked="ChkOverlayFeatureToggle_Changed"/>
</Grid>
</Border>
<Border Style="{StaticResource OverlayAdvancedToggleRowStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<TextBlock Text="새 채팅 렌더링 (V2)"
FontSize="12.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="Claude Code 스타일 상세 실행 이력. 도구 호출·결과가 접힘/펼침 카드로 표시됩니다. 끄면 기존 버블형 렌더링을 사용합니다."
Margin="0,4,0,0"
FontSize="11.5"
TextWrapping="Wrap"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<CheckBox x:Name="ChkOverlayEnableNewChatRendering"
Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource ToggleSwitch}"
Checked="ChkOverlayFeatureToggle_Changed"
Unchecked="ChkOverlayFeatureToggle_Changed"/>
</Grid>
</Border>
</StackPanel>
</Border>
<Border x:Name="OverlayToggleImageInput" Style="{StaticResource OverlayAdvancedToggleRowStyle}">
@@ -4363,6 +4906,7 @@
MinWidth="160"
Style="{StaticResource OverlayComboBox}"
SelectionChanged="CmbOverlayAgentLogLevel_SelectionChanged">
<ComboBoxItem Content="숨김" Tag="hidden"/>
<ComboBoxItem Content="간략" Tag="simple"/>
<ComboBoxItem Content="상세" Tag="detailed"/>
<ComboBoxItem Content="디버그" Tag="debug"/>
@@ -4887,6 +5431,36 @@
Unchecked="ChkOverlayFeatureToggle_Changed"/>
</Grid>
</Border>
<!-- 코워크 완료 후 문서 자동 처리 -->
<Border x:Name="OverlayToggleCoworkOnComplete" Style="{StaticResource OverlayAdvancedToggleRowStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<TextBlock Text="Cowork 완료 후 문서 처리"
FontSize="12.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="작업 완료 시 생성된 문서를 자동으로 열거나 미리보기합니다."
Margin="0,4,0,0"
FontSize="11.5"
TextWrapping="Wrap"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<ComboBox x:Name="CmbOverlayCoworkOnComplete"
Grid.Column="1"
VerticalAlignment="Center"
Width="140"
Style="{StaticResource OverlayComboBox}"
SelectionChanged="CmbOverlayCoworkOnComplete_SelectionChanged">
<ComboBoxItem Content="아무것도 안하기" Tag="none" IsSelected="True"/>
<ComboBoxItem Content="문서 실행" Tag="open"/>
<ComboBoxItem Content="미리보기 뷰어" Tag="preview"/>
</ComboBox>
</Grid>
</Border>
<Border x:Name="OverlayToggleCodeVerification" Style="{StaticResource OverlayAdvancedToggleRowStyle}">
<Grid>
<Grid.ColumnDefinitions>
@@ -5239,6 +5813,57 @@
Unchecked="ChkOverlayFeatureToggle_Changed"/>
</Grid>
</Border>
<Border x:Name="OverlayToggleMascotCharacter" Style="{StaticResource OverlayAdvancedToggleRowStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="캐릭터 출동"
FontSize="12.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<Border Style="{StaticResource OverlayHelpBadge}">
<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">코드 탭의 빈 화면에 마스코트 캐릭터 GIF 애니메이션을 표시합니다. 출동 수가 많을수록 메모리를 많이 사용합니다.
한명: ~150MB, 적게(3): ~450MB, 중간(6): ~900MB, 전부: ~1.5GB</TextBlock>
</ToolTip>
</Border.ToolTip>
</Border>
</StackPanel>
<TextBlock Text="코드 탭 빈 화면에 마스코트 캐릭터를 표시합니다."
Margin="0,4,0,0"
FontSize="11.5"
TextWrapping="Wrap"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<ComboBox x:Name="CmbOverlayMascotLevel"
Grid.Column="1"
VerticalAlignment="Center"
MinWidth="120"
Style="{StaticResource OverlayComboBox}"
SelectionChanged="CmbOverlayMascotLevel_SelectionChanged">
<ComboBoxItem Content="출동 안하기" Tag="none"/>
<ComboBoxItem Content="한명만 출동" Tag="one"/>
<ComboBoxItem Content="적게 출동" Tag="few"/>
<ComboBoxItem Content="중간 출동" Tag="mid"/>
<ComboBoxItem Content="전부 출동" Tag="all"/>
</ComboBox>
</Grid>
</Border>
</StackPanel>
<Border x:Name="OverlayToolsInfoPanel"
Visibility="Collapsed"