using System; namespace AxCopilot.Services.Agent; internal sealed record ToolResultPresentation( string Kind, string Icon, string Label, string Description, string FollowUpHint, string BackgroundHex, string ForegroundHex, string StatusKind, bool NeedsAttention); internal static class ToolResultPresentationCatalog { public static ToolResultPresentation Resolve(AgentEvent evt, string fallbackLabel) { var summary = (evt.Summary ?? string.Empty).Trim(); var tool = (evt.ToolName ?? string.Empty).Trim().ToLowerInvariant(); var baseLabel = string.IsNullOrWhiteSpace(fallbackLabel) ? "도구 결과" : fallbackLabel; var kind = ResolveKind(tool); if (summary.Contains("취소", StringComparison.OrdinalIgnoreCase) || summary.Contains("중단", StringComparison.OrdinalIgnoreCase) || evt.Type == AgentEventType.StopRequested) { return new ToolResultPresentation( "cancel", "\uE711", $"{baseLabel} 취소", "요청이 중단되어 결과가 취소되었습니다.", "필요하면 같은 요청을 다시 실행할 수 있습니다.", "#F8FAFC", "#475569", "cancel", false); } if (summary.Contains("거부", StringComparison.OrdinalIgnoreCase) || summary.Contains("반려", StringComparison.OrdinalIgnoreCase) || summary.Contains("권한 거부", StringComparison.OrdinalIgnoreCase)) { return new ToolResultPresentation( "reject", "\uE783", $"{baseLabel} 거부", "권한이 거부되어 작업이 중단되었습니다.", "권한 모드를 바꾸거나 다시 확인하면 이어서 진행할 수 있습니다.", "#FEF2F2", "#DC2626", "reject", true); } if (summary.Contains("승인 필요", StringComparison.OrdinalIgnoreCase) || summary.Contains("확인 필요", StringComparison.OrdinalIgnoreCase)) { return new ToolResultPresentation( kind, "\uE8D7", $"{baseLabel} 승인 필요", "다음 단계로 진행하려면 사용자 승인이나 확인이 필요합니다.", "승인 후 같은 작업 흐름이 이어집니다.", "#FFF7ED", "#C2410C", "approval_required", true); } if (summary.Contains("부분", StringComparison.OrdinalIgnoreCase) || summary.Contains("일부", StringComparison.OrdinalIgnoreCase)) { return new ToolResultPresentation( kind, "\uE7BA", $"{baseLabel} 부분 완료", "일부 단계만 완료되어 후속 확인이나 재시도가 필요할 수 있습니다.", "후속 단계와 파일 결과를 확인해 주세요.", "#FFFBEA", "#A16207", "partial", true); } if (!evt.Success || evt.Type == AgentEventType.Error) { return new ToolResultPresentation( kind, "\uE783", BuildFailureLabel(kind, baseLabel), BuildFailureDescription(kind), BuildFailureFollowUp(kind), "#FEF2F2", "#DC2626", "error", true); } return new ToolResultPresentation( kind, "\uE73E", BuildSuccessLabel(kind, baseLabel), BuildSuccessDescription(kind), BuildSuccessFollowUp(kind), "#ECFDF5", "#16A34A", "success", false); } private static string ResolveKind(string tool) { if (tool.Contains("file_edit")) return "file_edit"; if (tool.Contains("file_write")) return "file_write"; if (tool.Contains("file_read") || tool.Contains("glob") || tool.Contains("grep") || tool.Contains("folder_map") || tool.Contains("multi_read")) return "filesystem"; if (tool.Contains("file")) return "file"; if (tool.Contains("build") || tool.Contains("test")) return "build_test"; if (tool.Contains("git") || tool.Contains("diff")) return "git"; if (tool is "html_create" or "docx_create" or "excel_create" or "xlsx_create" or "csv_create" or "markdown_create" or "md_create" or "script_create" or "pptx_create") return "document"; if (tool.Contains("document") || tool.Contains("format") || tool.Contains("template")) return "document"; if (tool.Contains("skill")) return "skill"; if (tool.Contains("mcp")) return "mcp"; if (tool.Contains("ask")) return "question"; if (tool.Contains("web") || tool.Contains("fetch") || tool.Contains("http")) return "web"; if (tool.Contains("process") || tool.Contains("bash") || tool.Contains("powershell")) return "command"; return "generic"; } private static string BuildSuccessLabel(string kind, string baseLabel) => kind switch { "file_edit" => "파일 수정 완료", "file_write" => "파일 쓰기 완료", "filesystem" => "파일 탐색 완료", "file" => "파일 작업 완료", "build_test" => "빌드/테스트 완료", "git" => "Git 작업 완료", "document" => "문서 작업 완료", "skill" => "스킬 실행 완료", "mcp" => "MCP 도구 완료", "question" => "질문 요청 완료", "web" => "웹 요청 완료", "command" => "명령 실행 완료", _ => baseLabel, }; private static string BuildFailureLabel(string kind, string baseLabel) => kind switch { "file_edit" => "파일 수정 실패", "file_write" => "파일 쓰기 실패", "filesystem" => "파일 탐색 실패", "file" => "파일 작업 실패", "build_test" => "빌드/테스트 실패", "git" => "Git 작업 실패", "document" => "문서 작업 실패", "skill" => "스킬 실행 실패", "mcp" => "MCP 도구 실패", "question" => "질문 요청 실패", "web" => "웹 요청 실패", "command" => "명령 실행 실패", _ => $"{baseLabel} 실패", }; private static string BuildSuccessDescription(string kind) => kind switch { "file_edit" => "파일 수정 결과가 정상적으로 반영되었습니다.", "file_write" => "새 파일 생성이나 쓰기 작업이 완료되었습니다.", "filesystem" => "질문과 관련된 파일과 구조 정보를 찾았습니다.", "file" => "파일 관련 작업이 정상적으로 끝났습니다.", "build_test" => "빌드나 테스트 단계가 정상적으로 끝났습니다.", "git" => "저장소 상태 확인 또는 변경 작업이 완료되었습니다.", "document" => "문서 산출물 생성 또는 조립이 완료되었습니다.", "skill" => "선택한 스킬이 정상적으로 실행되었습니다.", "mcp" => "등록된 MCP 도구 호출이 완료되었습니다.", "question" => "사용자 응답을 받아 다음 단계로 이어갈 수 있습니다.", "web" => "필요한 웹 정보 조회가 완료되었습니다.", "command" => "명령 실행이 완료되어 결과를 확인할 수 있습니다.", _ => "요청한 작업이 정상적으로 완료되었습니다.", }; private static string BuildFailureDescription(string kind) => kind switch { "file_edit" => "파일 변경 과정에서 문제가 발생했습니다.", "file_write" => "파일 생성 또는 쓰기 과정에서 문제가 발생했습니다.", "filesystem" => "파일이나 폴더를 확인하는 과정에서 문제가 발생했습니다.", "file" => "파일 처리 중 문제가 발생했습니다.", "build_test" => "빌드 또는 테스트 단계에서 실패가 발생했습니다.", "git" => "Git 작업 중 오류가 발생했습니다.", "document" => "문서 생성 또는 조합 과정이 실패했습니다.", "skill" => "스킬 실행 중 문제가 발생했습니다.", "mcp" => "MCP 도구 호출 중 문제가 발생했습니다.", "question" => "사용자 질문/응답 처리 단계에서 문제가 발생했습니다.", "web" => "웹 요청 처리에 실패했습니다.", "command" => "명령 실행 중 오류가 발생했습니다.", _ => "작업 처리 중 오류가 발생했습니다.", }; private static string BuildSuccessFollowUp(string kind) => kind switch { "file_edit" or "file_write" => "변경 내용은 preview나 diff에서 다시 확인할 수 있습니다.", "build_test" => "출력 로그와 후속 수정 필요 여부를 확인해 주세요.", "git" => "브랜치와 변경 수치를 이어서 확인해 주세요.", "document" => "생성된 산출물 경로를 열어 결과를 확인해 주세요.", "skill" => "같은 스킬을 다른 입력으로 이어서 실행할 수 있습니다.", _ => "필요하면 다음 요청으로 이어서 작업할 수 있습니다.", }; private static string BuildFailureFollowUp(string kind) => kind switch { "file_edit" or "file_write" => "대상 파일 경로와 권한, diff 결과를 다시 확인해 주세요.", "build_test" => "실패 로그와 컴파일/테스트 오류 메시지를 먼저 확인해 주세요.", "git" => "브랜치 상태와 충돌 여부를 다시 확인해 주세요.", "document" => "입력 데이터, 출력 형식, 대상 위치를 다시 확인해 주세요.", "skill" => "사용 도구와 스킬 요구사항을 다시 확인해 주세요.", "web" => "연결 상태와 요청 URL을 다시 확인해 주세요.", "mcp" => "MCP 서버 연결 상태와 도구 등록 상태를 다시 확인해 주세요.", _ => "같은 요청을 다시 시도하기 전에 원인 메시지를 먼저 확인해 주세요.", }; }