AX Agent 재생성 흐름과 엔진 마감 문구를 상태 기반으로 정리
Some checks failed
Release Gate / gate (push) Has been cancelled

- regenerate/retry가 MessagePanel 직접 삭제 대신 conversation state 수정 후 RenderMessages 경로를 타도록 정리

- AxAgentExecutionEngine에 UI용 마감 helper를 추가해 취소/오류/빈 응답과 Cowork·Code 완료 문구를 정상 한국어 기준으로 정규화

- Paused/Resumed 실행 이벤트는 debug가 아닐 때 기본 타임라인에서 숨겨 Cowork/Code 노이즈를 축소

- README와 docs/DEVELOPMENT.md에 2026-04-05 18:20 (KST) 기준 작업 이력 반영

- 검증: 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-05 15:55:28 +09:00
parent 57be80af3c
commit ed1b8497c6
4 changed files with 70 additions and 11 deletions

View File

@@ -155,7 +155,7 @@ public sealed class AxAgentExecutionEngine
string? content,
ChatStorageService? storage = null)
{
var normalized = NormalizeAssistantContent(conversation, tab, content);
var normalized = NormalizeAssistantContentForUi(conversation, tab, content);
if (tab is "Cowork" or "Code")
conversation.ShowExecutionHistory = false;
@@ -163,6 +163,47 @@ public sealed class AxAgentExecutionEngine
return normalized;
}
public FinalizedContent FinalizeExecutionContentForUi(string? currentContent, Exception? error = null, bool cancelled = false)
{
if (cancelled)
{
var content = string.IsNullOrWhiteSpace(currentContent) ? "(취소됨)" : currentContent!;
return new FinalizedContent(content, true, "사용자가 작업을 중단했습니다.");
}
if (error != null)
return new FinalizedContent($"오류: {error.Message}", false, error.Message);
return new FinalizedContent(currentContent ?? string.Empty, false, null);
}
public string NormalizeAssistantContentForUi(
ChatConversation conversation,
string runTab,
string? content)
{
if (!string.IsNullOrWhiteSpace(content))
return content;
var latestEventSummary = conversation.ExecutionEvents?
.Where(evt => !string.IsNullOrWhiteSpace(evt.Summary))
.OrderByDescending(evt => evt.Timestamp)
.Select(evt => evt.Summary.Trim())
.FirstOrDefault();
if (!string.IsNullOrWhiteSpace(latestEventSummary))
{
return runTab switch
{
"Cowork" => $"코워크 작업이 완료되었습니다.\n\n{latestEventSummary}",
"Code" => $"코드 작업이 완료되었습니다.\n\n{latestEventSummary}",
_ => latestEventSummary,
};
}
return "(빈 응답)";
}
public FinalizedContent FinalizeExecutionContent(string? currentContent, Exception? error = null, bool cancelled = false)
{
if (cancelled)

View File

@@ -8581,14 +8581,14 @@ public partial class ChatWindow : Window
}
catch (OperationCanceledException)
{
var finalized = _chatEngine.FinalizeExecutionContent(assistantContent, cancelled: true);
var finalized = _chatEngine.FinalizeExecutionContentForUi(assistantContent, cancelled: true);
assistantContent = finalized.Content;
draftCancelled = finalized.Cancelled;
draftFailure = finalized.FailureReason;
}
catch (Exception ex)
{
var finalized = _chatEngine.FinalizeExecutionContent(assistantContent, ex);
var finalized = _chatEngine.FinalizeExecutionContentForUi(assistantContent, ex);
assistantContent = finalized.Content;
draftFailure = finalized.FailureReason;
ShowToast("실패한 요청은 작업 요약에서 다시 시도할 수 있습니다.", "\uE783", 2600);
@@ -10393,6 +10393,10 @@ public partial class ChatWindow : Window
return;
}
if (!string.Equals(logLevel, "debug", StringComparison.OrdinalIgnoreCase)
&& evt.Type is AgentEventType.Paused or AgentEventType.Resumed)
return;
// simple 모드: ToolCall은 건너뜀 (ToolResult만 한 줄로 표시)
if (logLevel == "simple" && evt.Type == AgentEventType.ToolCall)
return;
@@ -10799,9 +10803,8 @@ public partial class ChatWindow : Window
}
}
// UI에서 마지막 AI 응답 제거
if (MessagePanel.Children.Count > 0)
MessagePanel.Children.RemoveAt(MessagePanel.Children.Count - 1);
RenderMessages(preserveViewport: true);
AutoScrollIfNeeded();
// 재전송
await SendRegenerateAsync(conv);
@@ -10913,14 +10916,19 @@ public partial class ChatWindow : Window
// 마지막 assistant 메시지 제거
lock (_convLock)
{
if (conv.Messages.Count > 0 && conv.Messages[^1].Role == "assistant")
var session = ChatSession;
if (session != null)
{
session.RemoveLastAssistantMessage(_activeTab, _storage);
_currentConversation = session.CurrentConversation;
conv = _currentConversation!;
}
else if (conv.Messages.Count > 0 && conv.Messages[^1].Role == "assistant")
{
conv.Messages.RemoveAt(conv.Messages.Count - 1);
}
}
// UI에서 마지막 AI 응답 제거
if (MessagePanel.Children.Count > 0)
MessagePanel.Children.RemoveAt(MessagePanel.Children.Count - 1);
// 피드백을 사용자 메시지로 추가
var feedbackMsg = new ChatMessage
{