From 660f4e5a32961d077d337c3b62a6713ec39a3b6d Mon Sep 17 00:00:00 2001 From: lacvet Date: Sun, 5 Apr 2026 12:26:51 +0900 Subject: [PATCH] =?UTF-8?q?AX=20Agent=20=EC=B5=9C=EC=A2=85=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EC=BB=A4=EB=B0=8B=20=ED=9D=90=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=EC=97=94=EC=A7=84=EC=9C=BC=EB=A1=9C=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AxAgentExecutionEngine에 FinalizeAssistantTurn을 추가해 assistant 최종 내용 정규화, Cowork/Code 실행 로그 접힘, 메시지 커밋을 한 메서드로 통합함 - SendMessageAsync와 SendRegenerateAsync가 동일한 엔진 마무리 경로를 타도록 정리해 UI 쪽 중복 후처리를 줄임 - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ 경고 0 / 오류 0 --- README.md | 2 ++ docs/DEVELOPMENT.md | 3 +++ .../Services/Agent/AxAgentExecutionEngine.cs | 15 +++++++++++++++ src/AxCopilot/Views/ChatWindow.xaml.cs | 11 ++--------- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1ef4a50..18c4d3a 100644 --- a/README.md +++ b/README.md @@ -739,9 +739,11 @@ ow + toggle 시각 언어로 통일했습니다. - 같은 파일에서 `메시지 편집 후 재생성`, `피드백 후 재생성` 경로도 직접 `AddMessageBubble(...)`를 꽂지 않고 `RenderMessages()` 축으로 다시 돌리게 맞췄습니다. 재생성 경로 자체도 `Cowork/Code`에서는 일반 LLM 호출이 아니라 `ResolveExecutionMode(...)` + `RunAgentLoopAsync(...)`를 타도록 바꿔, 코워크/코드가 채팅 재생성 때 일반 Chat 경로로 잘못 떨어지던 문제를 줄였습니다. - 이어서 [AxAgentExecutionEngine.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/AxAgentExecutionEngine.cs)에 `PrepareExecution(...)`, `NormalizeAssistantContent(...)`를 추가하고, [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 일반 전송과 재생성이 모두 같은 준비 함수를 타도록 정리했습니다. 이제 실행 모드 판정, 프롬프트 스택 구성, 전송 메시지 조립, 최종 assistant 내용 보정이 한 엔진 축에서 처리됩니다. - 이 변경으로 `SendMessageAsync()`와 `SendRegenerateAsync()`가 각자 따로 Cowork/Code 시스템 프롬프트와 실행 모드를 계산하던 중복 분기가 줄었고, 이후 Cowork/Code 엔진을 `claw-code` 기준으로 더 밀 때도 준비 로직은 엔진 한 곳만 고치면 되게 정리했습니다. +- 이어서 `FinalizeAssistantTurn(...)`를 엔진에 추가해, 최종 assistant 내용 정규화와 Cowork/Code 실행 로그 접힘 처리, assistant 메시지 커밋을 전송/재생성 공통으로 같은 메서드에서 처리하게 바꿨습니다. 이제 채팅 마무리 단계도 UI 코드가 아니라 엔진이 더 많이 책임집니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 - 업데이트: 2026-04-05 12:24 (KST) - 업데이트: 2026-04-05 12:31 (KST) +- 업데이트: 2026-04-05 12:36 (KST) --- diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 7e36461..4d18f6a 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4492,4 +4492,7 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - [AxAgentExecutionEngine.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/AxAgentExecutionEngine.cs)에 `PreparedExecution` record와 `PrepareExecution(...)` 메서드를 추가해, 실행 모드 판정(`ResolveExecutionMode`)과 프롬프트 스택 조합(`BuildPromptStack`), 최종 전송 메시지 준비(`PrepareTurn`)를 한 번에 묶도록 정리했습니다. - 같은 엔진에 `NormalizeAssistantContent(...)`도 옮겨서, 최종 assistant 텍스트가 비었을 때 최근 실행 이벤트 요약을 어떻게 대체할지까지 UI가 아니라 엔진이 책임지게 바꿨습니다. 이건 `claw-code`처럼 UI보다 세션/실행 레이어가 메시지 결과를 더 많이 책임지게 만드는 방향의 일부입니다. - [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 는 새 `PrepareExecutionForConversation(...)`을 통해 일반 전송과 재생성 모두 같은 엔진 준비 경로를 사용합니다. 그래서 Cowork/Code 시스템 프롬프트 선택, 실행 모드 판정, 프롬프트 스택 구성, outbound message 조립이 각 메서드마다 중복 구현되지 않게 됐고, 다음 단계부터는 AgentLoop 완료 처리와 후속 큐 정리도 같은 방식으로 더 엔진 쪽으로 밀 수 있는 상태가 됐습니다. +- 업데이트: 2026-04-05 12:36 (KST) +- [AxAgentExecutionEngine.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/AxAgentExecutionEngine.cs)에 `FinalizeAssistantTurn(...)`를 추가해, 최종 assistant 텍스트 정규화와 `Cowork/Code`의 `ShowExecutionHistory=false` 처리, assistant 메시지 커밋을 한 메서드에 묶었습니다. +- [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 의 `SendMessageAsync()`와 `SendRegenerateAsync()`는 더 이상 직접 `NormalizeAssistantContent(...)`와 `CommitAssistantMessage(...)`를 따로 호출하지 않고, 둘 다 `FinalizeAssistantTurn(...)`으로 마무리합니다. 이로써 AX Agent 채팅 엔진의 “준비 → 실행 → 최종 커밋” 축이 한 단계 더 짧고 일관되게 정리됐습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0 diff --git a/src/AxCopilot/Services/Agent/AxAgentExecutionEngine.cs b/src/AxCopilot/Services/Agent/AxAgentExecutionEngine.cs index a64e67b..2ceb7ad 100644 --- a/src/AxCopilot/Services/Agent/AxAgentExecutionEngine.cs +++ b/src/AxCopilot/Services/Agent/AxAgentExecutionEngine.cs @@ -133,6 +133,21 @@ public sealed class AxAgentExecutionEngine return assistant; } + public string FinalizeAssistantTurn( + ChatSessionStateService? session, + ChatConversation conversation, + string tab, + string? content, + ChatStorageService? storage = null) + { + var normalized = NormalizeAssistantContent(conversation, tab, content); + if (tab is "Cowork" or "Code") + conversation.ShowExecutionHistory = false; + + CommitAssistantMessage(session, conversation, tab, normalized, storage); + return normalized; + } + public string NormalizeAssistantContent( ChatConversation conversation, string runTab, diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index a29656a..8b6b0a1 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -8465,14 +8465,10 @@ public partial class ChatWindow : Window SetStatusIdle(); } - assistantContent = _chatEngine.NormalizeAssistantContent(conv, runTab, assistantContent); - if (runTab is "Cowork" or "Code") - conv.ShowExecutionHistory = false; - lock (_convLock) { var session = ChatSession; - _chatEngine.CommitAssistantMessage(session, conv, runTab, assistantContent, _storage); + assistantContent = _chatEngine.FinalizeAssistantTurn(session, conv, runTab, assistantContent, _storage); _currentConversation = session?.CurrentConversation ?? conv; conv = _currentConversation!; } @@ -11022,13 +11018,10 @@ public partial class ChatWindow : Window SetStatusIdle(); } - assistantContent = _chatEngine.NormalizeAssistantContent(conv, runTab, assistantContent); - if (runTab is "Cowork" or "Code") - conv.ShowExecutionHistory = false; lock (_convLock) { var session = ChatSession; - _chatEngine.CommitAssistantMessage(session, conv, runTab, assistantContent, _storage); + assistantContent = _chatEngine.FinalizeAssistantTurn(session, conv, runTab, assistantContent, _storage); _currentConversation = session?.CurrentConversation ?? conv; conv = _currentConversation!; }