diff --git a/README.md b/README.md
index 29bde15..482255c 100644
--- a/README.md
+++ b/README.md
@@ -1351,3 +1351,6 @@ MIT License
- 업데이트: 2026-04-06 18:34 (KST)
- 다른 앱에서 타이핑할 때도 AX Copilot가 키 입력 훅 경로에서 과하게 개입하던 부분을 줄였다. [InputListener.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Core/InputListener.cs)는 이제 모든 키다운마다 시스템 파일 대화상자 판정을 하지 않고, 실제 핫키 메인 키·캡처 메인 키·키 필터가 필요한 경우에만 억제 창 검사를 수행한다.
- [SnippetExpander.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Core/SnippetExpander.cs)는 추적 중이 아닐 때 `;` 시작 키 외에는 즉시 반환하도록 바꿨다. 이전에는 일반 타이핑 중에도 모든 키마다 `Ctrl/Alt/Shift` 상태를 읽고 버퍼 로직을 거쳤는데, 이제는 실제 스니펫 시작 상황에서만 그런 검사를 하게 되어 글로벌 키보드 훅의 평상시 부담을 줄였다.
+업데이트: 2026-04-06 20:18 (KST)
+- AX Agent 메시지 마크다운 렌더에 코드 심볼 강조를 추가해 Cowork/Code 답변의 파일 경로·camelCase/PascalCase·snake_case가 더 선명하게 보이도록 조정했다.
+- 코드 탭 입력부 위에 저장소/브랜치/변경 수치를 보여주는 Git 요약 배너를 추가해 `claude-code` 스타일의 repo context를 더 빠르게 읽을 수 있게 맞췄다.
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
index 6da5a78..bf4d32c 100644
--- a/docs/DEVELOPMENT.md
+++ b/docs/DEVELOPMENT.md
@@ -5018,3 +5018,5 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
- Document update: 2026-04-06 18:34 (KST) - `SnippetExpander.cs` now short-circuits immediately for normal typing unless snippet tracking is already active or the current key is the `;` trigger. This removes repeated `GetAsyncKeyState` and buffer logic from ordinary typing in other apps and makes the low-level hook substantially lighter under continuous input.
+업데이트: 2026-04-06 20:18 (KST)
+- Improved AX Agent markdown rendering for Cowork/Code by highlighting file paths plus code-like symbols, and added a compact repository summary banner above the Code composer to surface branch and diff context closer to `claude-code`.
diff --git a/src/AxCopilot/Services/MarkdownRenderer.cs b/src/AxCopilot/Services/MarkdownRenderer.cs
index e427b9b..68172ad 100644
--- a/src/AxCopilot/Services/MarkdownRenderer.cs
+++ b/src/AxCopilot/Services/MarkdownRenderer.cs
@@ -12,6 +12,9 @@ namespace AxCopilot.Services;
///
public static class MarkdownRenderer
{
+ private static readonly Brush FilePathBrush = new SolidColorBrush(Color.FromRgb(0x3B, 0x82, 0xF6));
+ private static readonly Brush CodeSymbolBrush = new SolidColorBrush(Color.FromRgb(0xF2, 0x8C, 0x79));
+
public static StackPanel Render(string markdown, Brush textColor, Brush secondaryColor, Brush accentColor, Brush codeBg)
{
var panel = new StackPanel();
@@ -272,19 +275,34 @@ public static class MarkdownRenderer
/// 파일 경로 활성 여부 (설정 연동).
public static bool EnableFilePathHighlight { get; set; } = true;
+ /// 코드 심볼 강조 활성 여부 (설정/탭 연동).
+ public static bool EnableCodeSymbolHighlight { get; set; } = true;
+
+ private static readonly Regex CodeSymbolPattern = new(
+ @"(?일반 텍스트에서 파일 경로 패턴을 감지하여 파란색으로 강조합니다.
private static void AddPlainTextWithFilePaths(InlineCollection inlines, string text)
{
- if (!EnableFilePathHighlight)
+ if (!EnableFilePathHighlight && !EnableCodeSymbolHighlight)
{
inlines.Add(new Run(text));
return;
}
- var matches = FilePathPattern.Matches(text);
- if (matches.Count == 0)
+ MatchCollection? matches = null;
+ if (EnableFilePathHighlight)
+ matches = FilePathPattern.Matches(text);
+ if (matches == null || matches.Count == 0)
{
- inlines.Add(new Run(text));
+ AddPlainTextWithCodeSymbols(inlines, text);
return;
}
@@ -293,18 +311,54 @@ public static class MarkdownRenderer
{
// 매치 전 텍스트
if (pm.Index > lastIndex)
- inlines.Add(new Run(text[lastIndex..pm.Index]));
+ AddPlainTextWithCodeSymbols(inlines, text[lastIndex..pm.Index]);
// 파일 경로 — 파란색 강조
inlines.Add(new Run(pm.Value)
{
- Foreground = new SolidColorBrush(Color.FromRgb(0x3B, 0x82, 0xF6)), // #3B82F6
+ Foreground = FilePathBrush,
FontWeight = FontWeights.Medium,
});
lastIndex = pm.Index + pm.Length;
}
// 남은 텍스트
+ if (lastIndex < text.Length)
+ AddPlainTextWithCodeSymbols(inlines, text[lastIndex..]);
+ }
+
+ private static void AddPlainTextWithCodeSymbols(InlineCollection inlines, string text)
+ {
+ if (string.IsNullOrEmpty(text))
+ return;
+
+ if (!EnableCodeSymbolHighlight)
+ {
+ inlines.Add(new Run(text));
+ return;
+ }
+
+ var matches = CodeSymbolPattern.Matches(text);
+ if (matches.Count == 0)
+ {
+ inlines.Add(new Run(text));
+ return;
+ }
+
+ var lastIndex = 0;
+ foreach (Match match in matches)
+ {
+ if (match.Index > lastIndex)
+ inlines.Add(new Run(text[lastIndex..match.Index]));
+
+ inlines.Add(new Run(match.Value)
+ {
+ Foreground = CodeSymbolBrush,
+ FontWeight = FontWeights.SemiBold,
+ });
+ lastIndex = match.Index + match.Length;
+ }
+
if (lastIndex < text.Length)
inlines.Add(new Run(text[lastIndex..]));
}
diff --git a/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs b/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs
index c16fbdd..664855e 100644
--- a/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs
+++ b/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs
@@ -78,6 +78,7 @@ public partial class ChatWindow
UpdateDataUsageUI();
RefreshContextUsageVisual();
ScheduleGitBranchRefresh();
+ UpdateGitBranchUi(_currentGitBranchName, GitBranchFilesText?.Text ?? "", GitBranchAddedText?.Text ?? "", GitBranchDeletedText?.Text ?? "", _currentGitTooltip ?? "", BtnGitBranch?.Visibility ?? Visibility.Collapsed);
}
private void UpdateDataUsageUI()
diff --git a/src/AxCopilot/Views/ChatWindow.GitBranchPresentation.cs b/src/AxCopilot/Views/ChatWindow.GitBranchPresentation.cs
index 139d5df..bd0c3a9 100644
--- a/src/AxCopilot/Views/ChatWindow.GitBranchPresentation.cs
+++ b/src/AxCopilot/Views/ChatWindow.GitBranchPresentation.cs
@@ -33,9 +33,76 @@ public partial class ChatWindow
GitBranchDeletedText.Text = deletedText;
if (GitBranchSeparator != null)
GitBranchSeparator.Visibility = visibility;
+
+ UpdateCodeRepoSummaryUi(branchName, filesText, addedText, deletedText, tooltip, visibility);
});
}
+ private void UpdateCodeRepoSummaryUi(string? branchName, string filesText, string addedText, string deletedText, string tooltip, Visibility visibility)
+ {
+ if (CodeRepoSummaryBar == null)
+ return;
+
+ var isVisible = visibility == Visibility.Visible &&
+ string.Equals(_activeTab, "Code", StringComparison.OrdinalIgnoreCase) &&
+ !string.IsNullOrWhiteSpace(GetCurrentWorkFolder());
+
+ CodeRepoSummaryBar.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed;
+ if (!isVisible)
+ return;
+
+ var gitRoot = _currentGitRoot ?? ResolveGitRoot(GetCurrentWorkFolder());
+ var repoName = !string.IsNullOrWhiteSpace(gitRoot)
+ ? System.IO.Path.GetFileName(gitRoot.TrimEnd('\\', '/'))
+ : "저장소";
+ var normalizedBranch = string.IsNullOrWhiteSpace(branchName) ? "detached" : branchName!;
+
+ if (CodeRepoSummaryRepoLabel != null)
+ CodeRepoSummaryRepoLabel.Text = repoName;
+ if (CodeRepoSummaryBranchLabel != null)
+ CodeRepoSummaryBranchLabel.Text = normalizedBranch;
+ if (CodeRepoSummaryDetailText != null)
+ {
+ var details = new List();
+ if (!string.IsNullOrWhiteSpace(filesText))
+ details.Add($"변경 파일 {filesText}");
+ if (!string.IsNullOrWhiteSpace(addedText))
+ details.Add(addedText);
+ if (!string.IsNullOrWhiteSpace(deletedText))
+ details.Add(deletedText);
+
+ CodeRepoSummaryDetailText.Text = details.Count > 0
+ ? string.Join(" · ", details)
+ : "현재 저장소 컨텍스트와 변경 상태를 기준으로 작업합니다.";
+ CodeRepoSummaryDetailText.ToolTip = string.IsNullOrWhiteSpace(tooltip) ? null : tooltip;
+ }
+
+ if (CodeRepoSummaryAddedPill != null && CodeRepoSummaryAddedText != null)
+ {
+ var hasAdded = !string.IsNullOrWhiteSpace(addedText);
+ CodeRepoSummaryAddedPill.Visibility = hasAdded ? Visibility.Visible : Visibility.Collapsed;
+ CodeRepoSummaryAddedText.Text = hasAdded ? addedText : "";
+ }
+
+ if (CodeRepoSummaryDeletedPill != null && CodeRepoSummaryDeletedText != null)
+ {
+ var hasDeleted = !string.IsNullOrWhiteSpace(deletedText);
+ CodeRepoSummaryDeletedPill.Visibility = hasDeleted ? Visibility.Visible : Visibility.Collapsed;
+ CodeRepoSummaryDeletedText.Text = hasDeleted ? deletedText : "";
+ }
+ }
+
+ private async void CodeRepoSummaryBar_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ e.Handled = true;
+ if (BtnGitBranch == null)
+ return;
+
+ await RefreshGitBranchStatusAsync();
+ BuildGitBranchPopup();
+ GitBranchPopup.IsOpen = true;
+ }
+
private void BuildGitBranchPopup()
{
if (GitBranchItems == null)
diff --git a/src/AxCopilot/Views/ChatWindow.MessageBubblePresentation.cs b/src/AxCopilot/Views/ChatWindow.MessageBubblePresentation.cs
index 2e03bd8..d1cc7c0 100644
--- a/src/AxCopilot/Views/ChatWindow.MessageBubblePresentation.cs
+++ b/src/AxCopilot/Views/ChatWindow.MessageBubblePresentation.cs
@@ -51,10 +51,12 @@ public partial class ChatWindow
var userCodeBgBrush = TryFindResource("HintBackground") as Brush ?? Brushes.DarkGray;
MarkdownRenderer.EnableFilePathHighlight =
(System.Windows.Application.Current as App)?.SettingsService?.Settings.Llm.EnableFilePathHighlight ?? true;
+ MarkdownRenderer.EnableCodeSymbolHighlight = true;
bubble.Child = MarkdownRenderer.Render(content, primaryText, secondaryText, accentBrush, userCodeBgBrush);
}
else
{
+ MarkdownRenderer.EnableCodeSymbolHighlight = false;
bubble.Child = new TextBlock
{
Text = content,
@@ -176,6 +178,9 @@ public partial class ChatWindow
var app = System.Windows.Application.Current as App;
MarkdownRenderer.EnableFilePathHighlight =
app?.SettingsService?.Settings.Llm.EnableFilePathHighlight ?? true;
+ MarkdownRenderer.EnableCodeSymbolHighlight =
+ string.Equals(_activeTab, "Cowork", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(_activeTab, "Code", StringComparison.OrdinalIgnoreCase);
var codeBgBrush = TryFindResource("HintBackground") as Brush ?? Brushes.DarkGray;
if (IsBranchContextMessage(content))
{
diff --git a/src/AxCopilot/Views/ChatWindow.xaml b/src/AxCopilot/Views/ChatWindow.xaml
index bfe27a2..3bb9a81 100644
--- a/src/AxCopilot/Views/ChatWindow.xaml
+++ b/src/AxCopilot/Views/ChatWindow.xaml
@@ -1699,6 +1699,97 @@
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+