AX Agent 완료 직후 저장 경로를 정리해 Cowork·Code 실행 기록 누락을 방지
Some checks failed
Release Gate / gate (push) Has been cancelled

- ChatWindow에 PersistConversationSnapshot을 추가해 중간 저장, 최종 저장, 지연 저장 flush를 한 경로로 통합

- ResetStreamingUiState에서 대기 중인 실행 이벤트 저장을 먼저 flush 하도록 바꿔 마지막 이벤트 누락 가능성을 차단

- RunAgentLoopAsync 내부의 중복 저장/RememberConversation 호출을 제거하고 FinalizeConversationTurn 단일 완료 경로로 정리

- README와 DEVELOPMENT 문서에 2026-04-05 13: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 12:48:13 +09:00
parent f18f48789a
commit 0b1bc5f32f
3 changed files with 28 additions and 23 deletions

View File

@@ -8321,15 +8321,7 @@ public partial class ChatWindow : Window
return;
lastAutoSaveUtc = DateTime.UtcNow;
try
{
_storage.Save(conv);
ChatSession?.RememberConversation(originTab, conv.Id);
}
catch (Exception ex)
{
Services.LogService.Debug($"대화 중간 저장 실패: {ex.Message}");
}
PersistConversationSnapshot(originTab, conv, "대화 중간 저장 실패");
}
TryPersistConversation(force: true);
@@ -8500,16 +8492,6 @@ public partial class ChatWindow : Window
{
_agentLoop.ActiveTab = runTab;
var response = await _agentLoop.RunAsync(sendMessages.ToList(), cancellationToken);
try
{
_storage.Save(conversation);
ChatSession?.RememberConversation(originTab, conversation.Id);
}
catch (Exception ex)
{
Services.LogService.Debug($"에이전트 루프 저장 실패: {ex.Message}");
}
if (_settings.Settings.Llm.NotifyOnComplete)
{
var title = string.Equals(runTab, "Code", StringComparison.OrdinalIgnoreCase)
@@ -8560,6 +8542,7 @@ public partial class ChatWindow : Window
private void ResetStreamingUiState()
{
FlushPendingConversationPersists();
_cursorTimer.Stop();
_elapsedTimer.Stop();
_typingTimer.Stop();
@@ -8590,8 +8573,7 @@ public partial class ChatWindow : Window
RenderMessages(preserveViewport: true);
AutoScrollIfNeeded();
try { _storage.Save(conversation); } catch (Exception ex) { Services.LogService.Debug($"대화 저장 실패: {ex.Message}"); }
ChatSession?.RememberConversation(rememberTab, conversation.Id);
PersistConversationSnapshot(rememberTab, conversation, "대화 저장 실패");
SyncTabConversationIdsFromSession();
RefreshConversationList();
}
@@ -8646,6 +8628,23 @@ public partial class ChatWindow : Window
_conversationPersistTimer.Start();
}
private void PersistConversationSnapshot(string rememberTab, ChatConversation conversation, string failureLabel)
{
if (conversation == null || string.IsNullOrWhiteSpace(conversation.Id))
return;
_pendingConversationPersists.Remove(conversation.Id);
try
{
_storage.Save(conversation);
ChatSession?.RememberConversation(rememberTab, conversation.Id);
}
catch (Exception ex)
{
Services.LogService.Debug($"{failureLabel}: {ex.Message}");
}
}
private void FlushPendingConversationPersists()
{
if (_pendingConversationPersists.Count == 0)
@@ -8653,8 +8652,7 @@ public partial class ChatWindow : Window
foreach (var conversation in _pendingConversationPersists.Values.ToList())
{
try { _storage.Save(conversation); }
catch (Exception ex) { Services.LogService.Debug($"대화 지연 저장 실패: {ex.Message}"); }
PersistConversationSnapshot(conversation.Tab ?? _activeTab, conversation, "대화 지연 저장 실패");
}
_pendingConversationPersists.Clear();