- claude-code 선택적 탐색 흐름을 참고해 Cowork/Code 시스템 프롬프트에서 folder_map 상시 선행 지시를 완화하고 glob/grep 기반 좁은 탐색을 우선하도록 조정함 - FolderMapTool 기본 depth를 2로, include_files 기본값을 false로 낮추고 MultiReadTool 최대 파일 수를 8개로 줄여 초기 과탐색 폭을 보수적으로 조정함 - AgentLoopExplorationPolicy partial을 추가해 탐색 범위 분류, broad-scan corrective hint, exploration_breadth 성능 로그를 연결함 - AgentLoopService에 탐색 범위 가이드 주입과 실행 중 탐색 폭 추적을 추가하고, 좁은 질문에서 반복적인 folder_map/대량 multi_read를 교정하도록 정리함 - DocxToHtmlConverter nullable 경고를 수정해 Release 빌드 경고 0 / 오류 0 기준을 다시 충족함 - README와 docs/DEVELOPMENT.md에 2026-04-09 10:36 (KST) 기준 개발 이력을 반영함
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -12,9 +12,108 @@ namespace AxCopilot.Views;
|
||||
|
||||
public partial class ChatWindow
|
||||
{
|
||||
// ── A-1: TopicButtonPanel 이벤트 위임 ──
|
||||
private Border? _lastHoveredTopicBorder;
|
||||
private bool _topicPanelDelegationInitialized;
|
||||
|
||||
/// <summary>프리셋 카드 Border.Tag에 저장하는 메타 데이터.</summary>
|
||||
private sealed class TopicCardTag
|
||||
{
|
||||
public required string Action { get; init; } // "preset" | "etc" | "add" | "custom_preset"
|
||||
public TopicPreset? Preset { get; init; }
|
||||
public required Brush NormalBackground { get; init; }
|
||||
public required Brush HoverBackground { get; init; }
|
||||
public Brush? NormalBorderBrush { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>TopicButtonPanel에 이벤트 위임 핸들러를 1회 등록합니다.</summary>
|
||||
private void InitTopicPanelDelegation()
|
||||
{
|
||||
if (_topicPanelDelegationInitialized || TopicButtonPanel == null)
|
||||
return;
|
||||
_topicPanelDelegationInitialized = true;
|
||||
|
||||
TopicButtonPanel.Background = Brushes.Transparent; // 갭 영역도 히트테스트 대상으로 등록
|
||||
TopicButtonPanel.MouseMove += TopicPanel_DelegatedMouseMove;
|
||||
TopicButtonPanel.MouseLeave += TopicPanel_DelegatedMouseLeave;
|
||||
TopicButtonPanel.PreviewMouseLeftButtonDown += TopicPanel_DelegatedLeftButtonDown;
|
||||
TopicButtonPanel.PreviewMouseRightButtonUp += TopicPanel_DelegatedRightButtonUp;
|
||||
}
|
||||
|
||||
private void TopicPanel_DelegatedMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
var border = FindAncestorWithTag<Border>(e.OriginalSource as DependencyObject);
|
||||
if (ReferenceEquals(border, _lastHoveredTopicBorder))
|
||||
return;
|
||||
|
||||
// 이전 호버 해제
|
||||
if (_lastHoveredTopicBorder?.Tag is TopicCardTag prevTag)
|
||||
{
|
||||
_lastHoveredTopicBorder.Background = prevTag.NormalBackground;
|
||||
if (prevTag.NormalBorderBrush != null)
|
||||
_lastHoveredTopicBorder.BorderBrush = prevTag.NormalBorderBrush;
|
||||
}
|
||||
|
||||
_lastHoveredTopicBorder = border;
|
||||
|
||||
// 새 호버 적용
|
||||
if (border?.Tag is TopicCardTag tag)
|
||||
{
|
||||
border.Background = tag.HoverBackground;
|
||||
border.BorderBrush = TryFindResource("AccentColor") as Brush ?? tag.NormalBorderBrush ?? border.BorderBrush;
|
||||
}
|
||||
}
|
||||
|
||||
private void TopicPanel_DelegatedMouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_lastHoveredTopicBorder?.Tag is TopicCardTag prevTag)
|
||||
{
|
||||
_lastHoveredTopicBorder.Background = prevTag.NormalBackground;
|
||||
if (prevTag.NormalBorderBrush != null)
|
||||
_lastHoveredTopicBorder.BorderBrush = prevTag.NormalBorderBrush;
|
||||
}
|
||||
_lastHoveredTopicBorder = null;
|
||||
}
|
||||
|
||||
private void TopicPanel_DelegatedLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var border = FindAncestorWithTag<Border>(e.OriginalSource as DependencyObject);
|
||||
if (border?.Tag is not TopicCardTag tag)
|
||||
return;
|
||||
|
||||
e.Handled = true;
|
||||
switch (tag.Action)
|
||||
{
|
||||
case "preset" or "custom_preset" when tag.Preset != null:
|
||||
SelectTopic(tag.Preset);
|
||||
break;
|
||||
case "etc":
|
||||
EmptyState.Visibility = Visibility.Collapsed;
|
||||
InputBox.Focus();
|
||||
break;
|
||||
case "add":
|
||||
ShowCustomPresetDialog();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void TopicPanel_DelegatedRightButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var border = FindAncestorWithTag<Border>(e.OriginalSource as DependencyObject);
|
||||
if (border?.Tag is not TopicCardTag tag)
|
||||
return;
|
||||
|
||||
if (tag.Action == "custom_preset" && tag.Preset != null)
|
||||
{
|
||||
e.Handled = true;
|
||||
ShowCustomPresetContextMenu(border, tag.Preset);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>프리셋 대화 주제 버튼을 동적으로 생성합니다.</summary>
|
||||
private void BuildTopicButtons()
|
||||
{
|
||||
_lastHoveredTopicBorder = null;
|
||||
TopicButtonPanel.Children.Clear();
|
||||
TopicButtonPanel.Visibility = Visibility.Visible;
|
||||
if (TopicPresetScrollViewer != null)
|
||||
@@ -52,29 +151,8 @@ public partial class ChatWindow
|
||||
var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
||||
var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||
|
||||
void AttachTopicCardHover(Border card, Brush normalBackground, Brush hoverBackground)
|
||||
{
|
||||
card.MouseEnter += (sender, _) =>
|
||||
{
|
||||
if (sender is Border hovered)
|
||||
{
|
||||
hovered.Background = hoverBackground;
|
||||
hovered.BorderBrush = TryFindResource("AccentColor") as Brush ?? cardBorder;
|
||||
}
|
||||
};
|
||||
card.MouseLeave += (sender, _) =>
|
||||
{
|
||||
if (sender is Border hovered)
|
||||
{
|
||||
hovered.Background = normalBackground;
|
||||
hovered.BorderBrush = cardBorder;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var preset in presets)
|
||||
{
|
||||
var capturedPreset = preset;
|
||||
var buttonColor = BrushFromHex(preset.Color);
|
||||
|
||||
var border = new Border
|
||||
@@ -133,7 +211,7 @@ public partial class ChatWindow
|
||||
|
||||
contentGrid.Children.Add(stack);
|
||||
|
||||
if (capturedPreset.IsCustom)
|
||||
if (preset.IsCustom)
|
||||
{
|
||||
var badge = new Border
|
||||
{
|
||||
@@ -158,17 +236,16 @@ public partial class ChatWindow
|
||||
}
|
||||
|
||||
border.Child = contentGrid;
|
||||
AttachTopicCardHover(border, cardBackground, cardHoverBackground);
|
||||
border.MouseLeftButtonDown += (_, _) => SelectTopic(capturedPreset);
|
||||
|
||||
if (capturedPreset.IsCustom)
|
||||
// A-1: 이벤트 위임 — 개별 람다 대신 Tag에 메타 저장
|
||||
border.Tag = new TopicCardTag
|
||||
{
|
||||
border.MouseRightButtonUp += (sender, args) =>
|
||||
{
|
||||
args.Handled = true;
|
||||
ShowCustomPresetContextMenu(sender as Border, capturedPreset);
|
||||
};
|
||||
}
|
||||
Action = preset.IsCustom ? "custom_preset" : "preset",
|
||||
Preset = preset,
|
||||
NormalBackground = cardBackground,
|
||||
HoverBackground = cardHoverBackground,
|
||||
NormalBorderBrush = cardBorder,
|
||||
};
|
||||
|
||||
TopicButtonPanel.Children.Add(border);
|
||||
}
|
||||
@@ -225,11 +302,12 @@ public partial class ChatWindow
|
||||
});
|
||||
etcGrid.Children.Add(etcStack);
|
||||
etcBorder.Child = etcGrid;
|
||||
AttachTopicCardHover(etcBorder, cardBackground, cardHoverBackground);
|
||||
etcBorder.MouseLeftButtonDown += (_, _) =>
|
||||
etcBorder.Tag = new TopicCardTag
|
||||
{
|
||||
EmptyState.Visibility = Visibility.Collapsed;
|
||||
InputBox.Focus();
|
||||
Action = "etc",
|
||||
NormalBackground = cardBackground,
|
||||
HoverBackground = cardHoverBackground,
|
||||
NormalBorderBrush = cardBorder,
|
||||
};
|
||||
TopicButtonPanel.Children.Add(etcBorder);
|
||||
|
||||
@@ -274,8 +352,13 @@ public partial class ChatWindow
|
||||
|
||||
addGrid.Children.Add(addStack);
|
||||
addBorder.Child = addGrid;
|
||||
AttachTopicCardHover(addBorder, Brushes.Transparent, cardHoverBackground);
|
||||
addBorder.MouseLeftButtonDown += (_, _) => ShowCustomPresetDialog();
|
||||
addBorder.Tag = new TopicCardTag
|
||||
{
|
||||
Action = "add",
|
||||
NormalBackground = Brushes.Transparent,
|
||||
HoverBackground = cardHoverBackground,
|
||||
NormalBorderBrush = cardBorder,
|
||||
};
|
||||
TopicButtonPanel.Children.Add(addBorder);
|
||||
|
||||
UpdateTopicPresetScrollMode();
|
||||
|
||||
Reference in New Issue
Block a user