에이전트 진행 표시 구조를 claude-code식 row 기반으로 재정리
Some checks failed
Release Gate / gate (push) Has been cancelled

- AgentTranscriptDisplayCatalog를 row presentation 중심으로 재구성해 thinking/waiting/compact/tool activity/permission/tool result/status를 타입별로 분리함
- PermissionRequestPresentationCatalog와 ToolResultPresentationCatalog를 정리해 권한 요청과 결과 상태를 행위/상태 기준으로 더 명확하게 표현함
- ChatWindow.AgentEventRendering에서 process feed 계열 이벤트를 GroupKey 기준으로 병합해 append 수를 줄이고 진행 흐름이 기본 transcript에 남도록 조정함
- FooterPresentation에서 Cowork/Chat 프리셋 안내 카드가 execution event 이후 자동으로 숨겨지도록 하고 입력 워터마크와 footer 기본 문구를 정리함
- render_messages 성능 로그에 processFeed append/merge 수치와 rowKindCounts를 추가해 %APPDATA%\\AxCopilot\\perf 기준 실검증이 가능하도록 함
- 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-09 14:49:53 +09:00
parent 33c1db4dae
commit 227f5ab0d3
9 changed files with 867 additions and 548 deletions

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -47,9 +47,9 @@ public partial class ChatWindow
return preset.Description.Trim();
if (string.Equals(_activeTab, "Cowork", StringComparison.OrdinalIgnoreCase))
return "선택 작업 유형에 맞춰 문서·데이터·파일 작업 흐름으로 이어집니다.";
return "선택 작업 유형에 맞춰 문서, 데이터, 파일 작업 흐름으로 이어집니다.";
return "선택 대화 주제에 맞춰 응답 방향과 초안 흐름을 정리합니다.";
return "선택 대화 주제에 맞춰 응답 방향과 초안 흐름을 정리합니다.";
}
private void UpdateFolderBar()
@@ -74,7 +74,7 @@ public partial class ChatWindow
}
else
{
FolderPathLabel.Text = "폴더를 선택하세요";
FolderPathLabel.Text = "폴더를 선택하세요.";
FolderPathLabel.ToolTip = null;
}
@@ -129,7 +129,7 @@ public partial class ChatWindow
memory.Load(workFolder);
var docs = memory.InstructionDocuments;
var learned = memory.All.Count;
var includePolicy = _settings.Settings.Llm.AllowExternalMemoryIncludes ? "외부 include 허용" : "외부 include 차단";
var includePolicy = _settings.Settings.Llm.AllowExternalMemoryIncludes ? "?몃? include ?덉슜" : "?몃? include 李⑤떒";
var auditEnabled = _settings.Settings.Llm.EnableAuditLog;
var recentIncludeEntries = AuditLogService.LoadRecent("MemoryInclude", maxCount: 5, daysBack: 3);
@@ -143,7 +143,7 @@ public partial class ChatWindow
var panel = new StackPanel { Margin = new Thickness(2) };
panel.Children.Add(new TextBlock
{
Text = "메모리 상태",
Text = "硫붾え由??곹깭",
FontSize = 13,
FontWeight = FontWeights.SemiBold,
Foreground = primaryText,
@@ -151,7 +151,7 @@ public partial class ChatWindow
});
panel.Children.Add(new TextBlock
{
Text = $"계층형 규칙 {docs.Count}개 · 학습 메모리 {learned}개 · {includePolicy}",
Text = $"怨꾩링??洹쒖튃 {docs.Count}媛?쨌 ?숈뒿 硫붾え由?{learned}媛?쨌 {includePolicy}",
FontSize = 11.5,
Foreground = secondaryText,
TextWrapping = TextWrapping.Wrap,
@@ -163,7 +163,7 @@ public partial class ChatWindow
panel.Children.Add(CreateSurfacePopupSeparator());
panel.Children.Add(new TextBlock
{
Text = "적용 중 규칙",
Text = "?곸슜 以?洹쒖튃",
FontSize = 12,
FontWeight = FontWeights.SemiBold,
Foreground = primaryText,
@@ -177,7 +177,7 @@ public partial class ChatWindow
{
panel.Children.Add(new TextBlock
{
Text = $"{docs.Count - 6}개 규칙",
Text = $"??{docs.Count - 6}媛?洹쒖튃",
FontSize = 11,
Foreground = secondaryText,
Margin = new Thickness(8, 2, 8, 4),
@@ -188,7 +188,7 @@ public partial class ChatWindow
panel.Children.Add(CreateSurfacePopupSeparator());
panel.Children.Add(new TextBlock
{
Text = "최근 include 감사",
Text = "理쒓렐 include 媛먯궗",
FontSize = 12,
FontWeight = FontWeights.SemiBold,
Foreground = primaryText,
@@ -199,7 +199,7 @@ public partial class ChatWindow
{
panel.Children.Add(new TextBlock
{
Text = "감사 로그가 꺼져 있어 include 이력은 기록되지 않습니다.",
Text = "媛먯궗 濡쒓렇媛€ 爰쇱졇 ?덉뼱 include ?대젰?€ 湲곕줉?섏? ?딆뒿?덈떎.",
FontSize = 11,
Foreground = secondaryText,
TextWrapping = TextWrapping.Wrap,
@@ -210,7 +210,7 @@ public partial class ChatWindow
{
panel.Children.Add(new TextBlock
{
Text = "최근 3일간 include 감사 기록이 없습니다.",
Text = "理쒓렐 3?쇨컙 include 媛먯궗 湲곕줉???놁뒿?덈떎.",
FontSize = 11,
Foreground = secondaryText,
Margin = new Thickness(8, 0, 8, 6),
@@ -245,7 +245,7 @@ public partial class ChatWindow
return path;
var directory = Path.GetDirectoryName(path);
return string.IsNullOrWhiteSpace(directory) ? fileName : $"{fileName} · {directory}";
return string.IsNullOrWhiteSpace(directory) ? fileName : $"{fileName} {directory}";
}
catch
{
@@ -266,14 +266,14 @@ public partial class ChatWindow
var stack = new StackPanel { Margin = new Thickness(8, 2, 8, 4) };
stack.Children.Add(new TextBlock
{
Text = $"[{doc.Label}] 우선순위 {doc.Priority}",
Text = $"[{doc.Label}] ?곗꽑?쒖쐞 {doc.Priority}",
FontSize = 11.5,
FontWeight = FontWeights.SemiBold,
Foreground = primaryText,
});
stack.Children.Add(new TextBlock
{
Text = meta.Count == 0 ? doc.Layer : $"{doc.Layer} · {string.Join(" · ", meta)}",
Text = meta.Count == 0 ? doc.Layer : $"{doc.Layer} {string.Join(" ", meta)}",
FontSize = 10.5,
Foreground = secondaryText,
TextWrapping = TextWrapping.Wrap,
@@ -297,13 +297,13 @@ public partial class ChatWindow
private Border BuildMemoryPopupAuditRow(AuditEntry entry, Brush primaryText, Brush secondaryText, Brush okBrush, Brush warnBrush, Brush dangerBrush)
{
var statusBrush = entry.Success ? okBrush : dangerBrush;
var statusText = entry.Success ? "허용" : "차단";
var statusText = entry.Success ? "?덉슜" : "李⑤떒";
var resultBrush = entry.Success ? secondaryText : warnBrush;
var stack = new StackPanel { Margin = new Thickness(8, 2, 8, 4) };
stack.Children.Add(new TextBlock
{
Text = $"{statusText} · {entry.Timestamp:HH:mm:ss}",
Text = $"{statusText} {entry.Timestamp:HH:mm:ss}",
FontSize = 11.5,
FontWeight = FontWeights.SemiBold,
Foreground = statusBrush,
@@ -359,8 +359,9 @@ public partial class ChatWindow
!string.IsNullOrWhiteSpace(m.Content) &&
(string.Equals(m.Role, "user", StringComparison.OrdinalIgnoreCase) ||
string.Equals(m.Role, "assistant", StringComparison.OrdinalIgnoreCase))) == true;
var hasVisibleExecution = conversation?.ExecutionEvents?.Count > 0;
if (string.Equals(_activeTab, "Code", StringComparison.OrdinalIgnoreCase) || hasVisibleMessages || _isStreaming)
if (string.Equals(_activeTab, "Code", StringComparison.OrdinalIgnoreCase) || hasVisibleMessages || hasVisibleExecution || _isStreaming)
{
SelectedPresetGuide.Visibility = Visibility.Collapsed;
SelectedPresetGuideTitle.Text = "";
@@ -394,3 +395,4 @@ public partial class ChatWindow
SelectedPresetGuide.Visibility = Visibility.Visible;
}
}