권한·도구 결과 카드 callout 구조 도입
Some checks failed
Release Gate / gate (push) Has been cancelled

권한 요청과 도구 결과 transcript 안내를 단순 보조 문구에서 callout 카드 구조로 정리했습니다.

권한 요청은 확인 포인트, 도구 결과는 다음 권장 작업으로 보여주도록 바꿔 카드 성격 차이를 더 분명하게 만들었습니다.

README와 DEVELOPMENT 문서를 갱신했고 dotnet build 기준 경고 0 / 오류 0을 확인했습니다.
This commit is contained in:
2026-04-06 13:43:19 +09:00
parent 571d4bfaca
commit ec0ed7fb1c
3 changed files with 77 additions and 7 deletions

View File

@@ -1218,3 +1218,5 @@ MIT License
- 같은 metadata가 모두 회색 chip으로 보이던 부분을 보강했다. [ChatWindow.AgentEventRendering.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs) 의 보조 chip 색을 `주의 필요=빨강`, `검토 권장/후속 점검=앰버`, `미리보기 권장=파랑`, `승인 후 계속=오렌지`로 나눠, 권한 요청과 도구 결과 상태가 시각적으로도 더 즉시 구분되게 맞췄다.
- 업데이트: 2026-04-06 13:14 (KST)
- [ChatWindow.AgentEventRendering.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs)에 권한 요청/도구 결과 카테고리 chip을 추가했다. 이제 `명령 실행`, `파일 수정`, `웹 요청`, `Git`, `문서`, `스킬`, `MCP` 같은 종류가 상태 chip과 함께 보여서, 어떤 성격의 요청/결과인지 transcript에서 더 빨리 파악할 수 있다.
- 업데이트: 2026-04-06 13:20 (KST)
- [ChatWindow.AgentEventRendering.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs)의 metadata 안내를 callout 구조로 바꿨다. 권한 요청은 `확인 포인트`, 도구 결과는 `다음 권장 작업` 카드형 안내로 보여줘, 같은 transcript 안에서도 요청과 결과의 UX가 더 분리되어 보이게 정리했다.

View File

@@ -4948,3 +4948,4 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
- Document update: 2026-04-06 13:01 (KST) - Permission events now surface `ActionHint`, `Severity`, and `RequiresPreview` through inline cues such as `미리보기 권장`, `주의 필요`, and `검토 권장`, while tool-result events surface `FollowUpHint`, `NeedsAttention`, and `StatusKind` through cues such as `확인 필요`, `승인 후 계속`, and `후속 점검`.
- Document update: 2026-04-06 13:08 (KST) - Refined the transcript chips to visually differentiate metadata states instead of rendering every cue in the same neutral style. `ChatWindow.AgentEventRendering.cs` now uses blue for preview guidance, red for high-severity attention, amber for review/partial follow-up, and orange for approval-required continuation cues.
- Document update: 2026-04-06 13:14 (KST) - Added kind/category chips to permission and tool-result transcript banners so the action domain is visible at a glance. `ChatWindow.AgentEventRendering.cs` now surfaces labels such as `명령 실행`, `파일 수정`, `웹 요청`, `Git`, `문서`, `스킬`, and `MCP` alongside the status-oriented chips.
- Document update: 2026-04-06 13:20 (KST) - Replaced the plain guidance line with typed callout boxes in `ChatWindow.AgentEventRendering.cs`. Permission requests now show an `확인 포인트` callout, while tool results show a `다음 권장 작업` callout, making the two transcript surfaces read differently even when they share the same chip language.

View File

@@ -83,6 +83,40 @@ public partial class ChatWindow
};
}
private Border CreateAgentMetaCallout(string title, string body, Brush titleBrush, Brush background, Brush borderBrush)
{
return new Border
{
Background = background,
BorderBrush = borderBrush,
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(7, 5, 7, 5),
Margin = new Thickness(11, 2, 0, 0),
Child = new StackPanel
{
Children =
{
new TextBlock
{
Text = title,
FontSize = 7.75,
FontWeight = FontWeights.SemiBold,
Foreground = titleBrush,
},
new TextBlock
{
Text = body,
FontSize = 8.1,
Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.DimGray,
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness(0, 1, 0, 0),
}
}
}
};
}
private static string GetPermissionKindLabel(string kind)
{
return kind switch
@@ -215,14 +249,47 @@ public partial class ChatWindow
if (!string.IsNullOrWhiteSpace(guidance))
{
var clipped = guidance.Length > 92 ? guidance[..92] + "..." : guidance;
stack.Children.Add(new TextBlock
if (permissionPresentation != null)
{
Text = clipped,
FontSize = 8.15,
Foreground = secondaryText,
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness(11, 1, 0, 0),
});
var titleBrush = string.Equals(permissionPresentation.Severity, "high", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#B91C1C")
: string.Equals(permissionPresentation.Severity, "medium", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#A16207")
: BrushFromHex("#2563EB");
var background = string.Equals(permissionPresentation.Severity, "high", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FFF7F7")
: string.Equals(permissionPresentation.Severity, "medium", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FFFBEB")
: BrushFromHex("#EFF6FF");
var border = string.Equals(permissionPresentation.Severity, "high", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FECACA")
: string.Equals(permissionPresentation.Severity, "medium", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FDE68A")
: BrushFromHex("#BFDBFE");
stack.Children.Add(CreateAgentMetaCallout("확인 포인트", clipped, titleBrush, background, border));
}
else if (toolResultPresentation != null)
{
var titleBrush = string.Equals(toolResultPresentation.StatusKind, "error", StringComparison.OrdinalIgnoreCase)
|| string.Equals(toolResultPresentation.StatusKind, "reject", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#B91C1C")
: string.Equals(toolResultPresentation.StatusKind, "approval_required", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#C2410C")
: BrushFromHex("#A16207");
var background = string.Equals(toolResultPresentation.StatusKind, "error", StringComparison.OrdinalIgnoreCase)
|| string.Equals(toolResultPresentation.StatusKind, "reject", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FFF7F7")
: string.Equals(toolResultPresentation.StatusKind, "approval_required", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FFF7ED")
: BrushFromHex("#FFFBEB");
var border = string.Equals(toolResultPresentation.StatusKind, "error", StringComparison.OrdinalIgnoreCase)
|| string.Equals(toolResultPresentation.StatusKind, "reject", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FECACA")
: string.Equals(toolResultPresentation.StatusKind, "approval_required", StringComparison.OrdinalIgnoreCase)
? BrushFromHex("#FED7AA")
: BrushFromHex("#FDE68A");
stack.Children.Add(CreateAgentMetaCallout("다음 권장 작업", clipped, titleBrush, background, border));
}
}
if (chipRow.Children.Count > 0)