AX Agent transcript 권한·도구 결과 표현 정교화 및 이벤트 렌더 분리
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- claw-code 기준으로 transcript display catalog를 파일/문서/빌드/Git/웹/질문/에이전트 축으로 재정의 - 권한 요청 presentation catalog를 명령 실행, 웹 요청, 스킬 실행, 의견 요청, 파일 수정, 파일 접근 타입으로 세분화 - tool result catalog를 성공/실패/거부/취소와 도구 종류에 따라 더 읽기 쉬운 한국어 결과 라벨로 정리 - CreateCompactEventPill, AddAgentEventBanner, GetDecisionBadgeMeta를 ChatWindow.AgentEventRendering.cs로 분리해 메인 창 코드 비중 축소 - README와 DEVELOPMENT 문서에 변경 목적과 검증 결과 반영 - 검증: 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:
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace AxCopilot.Services.Agent;
|
||||
|
||||
internal static class AgentTranscriptDisplayCatalog
|
||||
@@ -5,30 +7,44 @@ internal static class AgentTranscriptDisplayCatalog
|
||||
public static string GetDisplayName(string? rawName, bool slashPrefix = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(rawName))
|
||||
return slashPrefix ? "/스킬" : "도구";
|
||||
return slashPrefix ? "/skill" : "도구";
|
||||
|
||||
var normalized = rawName.Trim();
|
||||
var mapped = normalized.ToLowerInvariant() switch
|
||||
var lowered = normalized.ToLowerInvariant();
|
||||
var mapped = lowered switch
|
||||
{
|
||||
"file_read" => "파일 읽기",
|
||||
"file_write" => "파일 쓰기",
|
||||
"file_edit" => "파일 편집",
|
||||
"file_watch" => "파일 변경 감시",
|
||||
"file_info" => "파일 정보",
|
||||
"file_manage" => "파일 관리",
|
||||
"glob" => "파일 찾기",
|
||||
"grep" => "내용 검색",
|
||||
"folder_map" => "폴더 구조",
|
||||
|
||||
"document_reader" => "문서 읽기",
|
||||
"document_planner" => "문서 계획",
|
||||
"document_assembler" => "문서 조합",
|
||||
"document_review" => "문서 검토",
|
||||
"format_convert" => "형식 변환",
|
||||
"code_search" => "코드 검색",
|
||||
"code_review" => "코드 리뷰",
|
||||
"template_render" => "템플릿 렌더",
|
||||
|
||||
"build_run" => "빌드/실행",
|
||||
"test_loop" => "테스트 루프",
|
||||
"dev_env_detect" => "개발 환경 점검",
|
||||
"git_tool" => "Git",
|
||||
"process" => "프로세스",
|
||||
"glob" => "파일 찾기",
|
||||
"grep" => "내용 검색",
|
||||
"folder_map" => "폴더 맵",
|
||||
"memory" => "메모리",
|
||||
"diff_tool" => "Diff",
|
||||
"diff_preview" => "Diff 미리보기",
|
||||
|
||||
"process" => "명령 실행",
|
||||
"bash" => "Bash",
|
||||
"powershell" => "PowerShell",
|
||||
"web_fetch" => "웹 요청",
|
||||
"http" => "HTTP 요청",
|
||||
"user_ask" => "의견 요청",
|
||||
"suggest_actions" => "다음 작업 제안",
|
||||
|
||||
"task_create" => "작업 생성",
|
||||
"task_update" => "작업 업데이트",
|
||||
"task_list" => "작업 목록",
|
||||
@@ -43,7 +59,10 @@ internal static class AgentTranscriptDisplayCatalog
|
||||
if (!slashPrefix)
|
||||
return mapped;
|
||||
|
||||
return normalized.StartsWith('/') ? normalized : "/" + normalized.Replace(' ', '-');
|
||||
if (normalized.StartsWith('/'))
|
||||
return normalized;
|
||||
|
||||
return "/" + lowered.Replace('_', '-').Replace(' ', '-');
|
||||
}
|
||||
|
||||
public static string GetEventBadgeLabel(AgentEvent evt)
|
||||
@@ -59,22 +78,23 @@ internal static class AgentTranscriptDisplayCatalog
|
||||
|
||||
public static string GetTaskCategoryLabel(string? kind, string? title)
|
||||
{
|
||||
if (string.Equals(kind, "permission", System.StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(kind, "permission", StringComparison.OrdinalIgnoreCase))
|
||||
return "권한";
|
||||
if (string.Equals(kind, "queue", System.StringComparison.OrdinalIgnoreCase))
|
||||
return "큐";
|
||||
if (string.Equals(kind, "hook", System.StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(kind, "queue", StringComparison.OrdinalIgnoreCase))
|
||||
return "대기열";
|
||||
if (string.Equals(kind, "hook", StringComparison.OrdinalIgnoreCase))
|
||||
return "훅";
|
||||
if (string.Equals(kind, "subagent", System.StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(kind, "subagent", StringComparison.OrdinalIgnoreCase))
|
||||
return "에이전트";
|
||||
if (string.Equals(kind, "tool", System.StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(kind, "tool", StringComparison.OrdinalIgnoreCase))
|
||||
return GetToolCategoryLabel(title);
|
||||
|
||||
return "작업";
|
||||
}
|
||||
|
||||
public static string BuildEventSummary(AgentEvent evt, string displayName)
|
||||
{
|
||||
var summary = (evt.Summary ?? "").Trim();
|
||||
var summary = (evt.Summary ?? string.Empty).Trim();
|
||||
if (!string.IsNullOrWhiteSpace(summary))
|
||||
return summary;
|
||||
|
||||
@@ -83,9 +103,11 @@ internal static class AgentTranscriptDisplayCatalog
|
||||
AgentEventType.ToolCall => $"{displayName} 실행 준비",
|
||||
AgentEventType.ToolResult => evt.Success ? $"{displayName} 실행 완료" : $"{displayName} 실행 실패",
|
||||
AgentEventType.SkillCall => $"{displayName} 실행",
|
||||
AgentEventType.PermissionRequest => $"{displayName} 실행 전 사용자 확인 필요",
|
||||
AgentEventType.PermissionGranted => $"{displayName} 실행이 허용됨",
|
||||
AgentEventType.PermissionDenied => $"{displayName} 실행이 거부됨",
|
||||
AgentEventType.PermissionRequest => $"{displayName} 실행 전에 권한 확인이 필요합니다.",
|
||||
AgentEventType.PermissionGranted => $"{displayName} 실행 권한이 승인되었습니다.",
|
||||
AgentEventType.PermissionDenied => $"{displayName} 실행 권한이 거부되었습니다.",
|
||||
AgentEventType.Complete => "에이전트 작업이 완료되었습니다.",
|
||||
AgentEventType.Error => "에이전트 실행 중 오류가 발생했습니다.",
|
||||
_ => summary,
|
||||
};
|
||||
}
|
||||
@@ -97,14 +119,24 @@ internal static class AgentTranscriptDisplayCatalog
|
||||
|
||||
return rawName.Trim().ToLowerInvariant() switch
|
||||
{
|
||||
"file_read" or "file_write" or "file_edit" or "glob" or "grep" or "folder_map" or "file_watch" or "file_info" or "file_manage" => "파일",
|
||||
"build_run" or "test_loop" or "dev_env_detect" => "빌드",
|
||||
"git_tool" or "diff_tool" or "diff_preview" => "Git",
|
||||
"document_reader" or "document_planner" or "document_assembler" or "document_review" or "format_convert" or "template_render" => "문서",
|
||||
"user_ask" => "질문",
|
||||
"suggest_actions" => "제안",
|
||||
"process" => "실행",
|
||||
"spawn_agent" or "wait_agents" => "에이전트",
|
||||
"file_read" or "file_write" or "file_edit" or "glob" or "grep" or "folder_map" or "file_watch" or "file_info" or "file_manage"
|
||||
=> "파일",
|
||||
"build_run" or "test_loop" or "dev_env_detect"
|
||||
=> "빌드",
|
||||
"git_tool" or "diff_tool" or "diff_preview"
|
||||
=> "Git",
|
||||
"document_reader" or "document_planner" or "document_assembler" or "document_review" or "format_convert" or "template_render"
|
||||
=> "문서",
|
||||
"user_ask"
|
||||
=> "질문",
|
||||
"suggest_actions"
|
||||
=> "제안",
|
||||
"process" or "bash" or "powershell"
|
||||
=> "명령",
|
||||
"spawn_agent" or "wait_agents"
|
||||
=> "에이전트",
|
||||
"web_fetch" or "http"
|
||||
=> "웹",
|
||||
_ => "도구",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace AxCopilot.Services.Agent;
|
||||
|
||||
internal sealed record PermissionRequestPresentation(
|
||||
@@ -10,31 +12,52 @@ internal static class PermissionRequestPresentationCatalog
|
||||
{
|
||||
public static PermissionRequestPresentation Resolve(string? toolName, bool pending)
|
||||
{
|
||||
var tool = toolName?.Trim().ToLowerInvariant() ?? "";
|
||||
var tool = (toolName ?? string.Empty).Trim().ToLowerInvariant();
|
||||
|
||||
if (tool.Contains("process") || tool.Contains("bash") || tool.Contains("powershell"))
|
||||
if (tool.Contains("bash") || tool.Contains("powershell") || tool.Contains("process"))
|
||||
{
|
||||
return pending
|
||||
? new PermissionRequestPresentation("\uE756", "명령 권한 요청", "#FEF2F2", "#DC2626")
|
||||
: new PermissionRequestPresentation("\uE73E", "명령 권한 허용", "#ECFDF5", "#059669");
|
||||
? new PermissionRequestPresentation("\uE756", "명령 실행 권한 요청", "#FEF2F2", "#DC2626")
|
||||
: new PermissionRequestPresentation("\uE73E", "명령 실행 권한 승인", "#ECFDF5", "#059669");
|
||||
}
|
||||
|
||||
if (tool.Contains("web") || tool.Contains("fetch") || tool.Contains("http"))
|
||||
{
|
||||
return pending
|
||||
? new PermissionRequestPresentation("\uE774", "네트워크 권한 요청", "#FFF7ED", "#C2410C")
|
||||
: new PermissionRequestPresentation("\uE73E", "네트워크 권한 허용", "#ECFDF5", "#059669");
|
||||
? new PermissionRequestPresentation("\uE774", "웹 요청 권한 요청", "#FFF7ED", "#C2410C")
|
||||
: new PermissionRequestPresentation("\uE73E", "웹 요청 권한 승인", "#ECFDF5", "#059669");
|
||||
}
|
||||
|
||||
if (tool.Contains("file"))
|
||||
if (tool.Contains("skill"))
|
||||
{
|
||||
return pending
|
||||
? new PermissionRequestPresentation("\uE8A5", "파일 권한 요청", "#FFF7ED", "#C2410C")
|
||||
: new PermissionRequestPresentation("\uE73E", "파일 권한 허용", "#ECFDF5", "#059669");
|
||||
? new PermissionRequestPresentation("\uE8A5", "스킬 실행 권한 요청", "#F5F3FF", "#7C3AED")
|
||||
: new PermissionRequestPresentation("\uE73E", "스킬 실행 권한 승인", "#ECFDF5", "#059669");
|
||||
}
|
||||
|
||||
if (tool.Contains("ask"))
|
||||
{
|
||||
return pending
|
||||
? new PermissionRequestPresentation("\uE897", "의견 요청 권한 확인", "#EFF6FF", "#2563EB")
|
||||
: new PermissionRequestPresentation("\uE73E", "의견 요청 권한 승인", "#ECFDF5", "#059669");
|
||||
}
|
||||
|
||||
if (tool.Contains("file_edit") || tool.Contains("file_write") || tool.Contains("edit"))
|
||||
{
|
||||
return pending
|
||||
? new PermissionRequestPresentation("\uE70F", "파일 수정 권한 요청", "#FFF7ED", "#C2410C")
|
||||
: new PermissionRequestPresentation("\uE73E", "파일 수정 권한 승인", "#ECFDF5", "#059669");
|
||||
}
|
||||
|
||||
if (tool.Contains("file") || tool.Contains("glob") || tool.Contains("grep") || tool.Contains("folder"))
|
||||
{
|
||||
return pending
|
||||
? new PermissionRequestPresentation("\uE8A5", "파일 접근 권한 요청", "#FFF7ED", "#C2410C")
|
||||
: new PermissionRequestPresentation("\uE73E", "파일 접근 권한 승인", "#ECFDF5", "#059669");
|
||||
}
|
||||
|
||||
return pending
|
||||
? new PermissionRequestPresentation("\uE897", "권한 요청", "#FFF7ED", "#C2410C")
|
||||
: new PermissionRequestPresentation("\uE73E", "권한 허용", "#ECFDF5", "#059669");
|
||||
: new PermissionRequestPresentation("\uE73E", "권한 승인", "#ECFDF5", "#059669");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace AxCopilot.Services.Agent;
|
||||
|
||||
internal sealed record ToolResultPresentation(
|
||||
@@ -11,27 +13,79 @@ internal static class ToolResultPresentationCatalog
|
||||
{
|
||||
public static ToolResultPresentation Resolve(AgentEvent evt, string fallbackLabel)
|
||||
{
|
||||
var summary = evt.Summary?.Trim() ?? "";
|
||||
var summary = (evt.Summary ?? string.Empty).Trim();
|
||||
var tool = (evt.ToolName ?? string.Empty).Trim().ToLowerInvariant();
|
||||
var baseLabel = string.IsNullOrWhiteSpace(fallbackLabel) ? "도구 결과" : fallbackLabel;
|
||||
|
||||
if (summary.Contains("취소", StringComparison.OrdinalIgnoreCase) ||
|
||||
summary.Contains("중단", StringComparison.OrdinalIgnoreCase) ||
|
||||
evt.Type == AgentEventType.StopRequested)
|
||||
{
|
||||
return new ToolResultPresentation("\uE711", "도구 취소", "#F8FAFC", "#475569", "cancel");
|
||||
return new ToolResultPresentation("\uE711", $"{baseLabel} 취소", "#F8FAFC", "#475569", "cancel");
|
||||
}
|
||||
|
||||
if (summary.Contains("거부", StringComparison.OrdinalIgnoreCase) ||
|
||||
summary.Contains("반려", StringComparison.OrdinalIgnoreCase) ||
|
||||
summary.Contains("권한 거부", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new ToolResultPresentation("\uE783", "도구 거부", "#FEF2F2", "#DC2626", "reject");
|
||||
return new ToolResultPresentation("\uE783", $"{baseLabel} 거부", "#FEF2F2", "#DC2626", "reject");
|
||||
}
|
||||
|
||||
if (!evt.Success || evt.Type == AgentEventType.Error)
|
||||
{
|
||||
return new ToolResultPresentation("\uE783", "도구 실패", "#FEF2F2", "#DC2626", "error");
|
||||
return new ToolResultPresentation(
|
||||
"\uE783",
|
||||
BuildFailureLabel(tool, baseLabel),
|
||||
"#FEF2F2",
|
||||
"#DC2626",
|
||||
"error");
|
||||
}
|
||||
|
||||
return new ToolResultPresentation("\uE73E", fallbackLabel, "#ECFDF5", "#16A34A", "success");
|
||||
return new ToolResultPresentation(
|
||||
"\uE73E",
|
||||
BuildSuccessLabel(tool, baseLabel),
|
||||
"#ECFDF5",
|
||||
"#16A34A",
|
||||
"success");
|
||||
}
|
||||
|
||||
private static string BuildSuccessLabel(string tool, string baseLabel)
|
||||
{
|
||||
if (tool.Contains("file"))
|
||||
return "파일 작업 완료";
|
||||
if (tool.Contains("build") || tool.Contains("test"))
|
||||
return "빌드/테스트 완료";
|
||||
if (tool.Contains("git") || tool.Contains("diff"))
|
||||
return "Git 작업 완료";
|
||||
if (tool.Contains("document") || tool.Contains("format") || tool.Contains("template"))
|
||||
return "문서 작업 완료";
|
||||
if (tool.Contains("skill"))
|
||||
return "스킬 실행 완료";
|
||||
if (tool.Contains("web") || tool.Contains("fetch") || tool.Contains("http"))
|
||||
return "웹 요청 완료";
|
||||
if (tool.Contains("process") || tool.Contains("bash") || tool.Contains("powershell"))
|
||||
return "명령 실행 완료";
|
||||
|
||||
return baseLabel;
|
||||
}
|
||||
|
||||
private static string BuildFailureLabel(string tool, string baseLabel)
|
||||
{
|
||||
if (tool.Contains("file"))
|
||||
return "파일 작업 실패";
|
||||
if (tool.Contains("build") || tool.Contains("test"))
|
||||
return "빌드/테스트 실패";
|
||||
if (tool.Contains("git") || tool.Contains("diff"))
|
||||
return "Git 작업 실패";
|
||||
if (tool.Contains("document") || tool.Contains("format") || tool.Contains("template"))
|
||||
return "문서 작업 실패";
|
||||
if (tool.Contains("skill"))
|
||||
return "스킬 실행 실패";
|
||||
if (tool.Contains("web") || tool.Contains("fetch") || tool.Contains("http"))
|
||||
return "웹 요청 실패";
|
||||
if (tool.Contains("process") || tool.Contains("bash") || tool.Contains("powershell"))
|
||||
return "명령 실행 실패";
|
||||
|
||||
return $"{baseLabel} 실패";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user