탭 전환 빈 대화 누적 방지: 저장 게이트 + 목록 노이즈 필터
Some checks failed
Release Gate / gate (push) Has been cancelled

- ChatSessionStateService.SaveCurrentConversation에 persistable-content 검사 추가

- 무의미한 빈 새 대화는 저장/탭 기억 대상에서 제외

- ChatWindow 대화 목록에서 빈 노이즈 항목 필터링

- ChatSessionStateServiceTests 회귀 추가 및 문서 이력(2026-04-04 15:48 KST) 동기화
This commit is contained in:
2026-04-04 15:49:12 +09:00
parent 73a4111100
commit f8669c735d
5 changed files with 162 additions and 7 deletions

View File

@@ -91,6 +91,7 @@ public sealed class ChatSessionStateService
{
var normalizedTab = NormalizeTab(tab);
var rememberedId = GetConversationId(normalizedTab);
var hadRememberedConversation = !string.IsNullOrWhiteSpace(rememberedId);
if (!string.IsNullOrWhiteSpace(rememberedId))
{
var loaded = storage.Load(rememberedId);
@@ -115,6 +116,30 @@ public sealed class ChatSessionStateService
RememberConversation(normalizedTab, null);
}
if (!hadRememberedConversation)
{
var latestMeta = storage.LoadAllMeta()
.Where(c => string.Equals(NormalizeTab(c.Tab), normalizedTab, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(c => c.Pinned)
.ThenByDescending(c => c.UpdatedAt)
.FirstOrDefault();
if (latestMeta != null)
{
var loaded = storage.Load(latestMeta.Id);
if (loaded != null)
{
loaded.Tab = normalizedTab;
var normalized = NormalizeLoadedConversation(loaded);
CurrentConversation = loaded;
RememberConversation(normalizedTab, loaded.Id);
if (normalized)
try { storage.Save(loaded); } catch { }
return loaded;
}
}
}
RememberConversation(normalizedTab, null);
return CreateFreshConversation(normalizedTab, settings);
}
@@ -209,13 +234,15 @@ public sealed class ChatSessionStateService
var conv = CurrentConversation;
if (conv == null) return;
try { storage.Save(conv); } catch { }
var conversationTab = NormalizeTab(conv.Tab);
if (conv.Messages.Count > 0
|| (conv.ExecutionEvents?.Count ?? 0) > 0
|| (conv.AgentRunHistory?.Count ?? 0) > 0
|| (conv.DraftQueueItems?.Count ?? 0) > 0)
RememberConversation(conversationTab, conv.Id);
if (!HasPersistableContent(conv))
{
RememberConversation(conversationTab, null);
return;
}
try { storage.Save(conv); } catch { }
RememberConversation(conversationTab, conv.Id);
}
public void ClearCurrentConversation(string tab)
@@ -571,6 +598,26 @@ public sealed class ChatSessionStateService
return "Chat";
}
private static bool HasPersistableContent(ChatConversation conv)
{
if ((conv.Messages?.Count ?? 0) > 0) return true;
if ((conv.ExecutionEvents?.Count ?? 0) > 0) return true;
if ((conv.AgentRunHistory?.Count ?? 0) > 0) return true;
if ((conv.DraftQueueItems?.Count ?? 0) > 0) return true;
if (conv.Pinned) return true;
if (!string.IsNullOrWhiteSpace(conv.WorkFolder)) return true;
if (!string.IsNullOrWhiteSpace(conv.SystemCommand)) return true;
if (!string.IsNullOrWhiteSpace(conv.ParentId)) return true;
if (!string.IsNullOrWhiteSpace(conv.Permission)) return true;
if (!string.IsNullOrWhiteSpace(conv.DataUsage)) return true;
if (!string.IsNullOrWhiteSpace(conv.OutputFormat)) return true;
if (!string.IsNullOrWhiteSpace(conv.Mood)) return true;
if (!string.IsNullOrWhiteSpace(conv.Preview)) return true;
if (!string.Equals(conv.Category, ChatCategory.General, StringComparison.OrdinalIgnoreCase)) return true;
if (!string.Equals((conv.Title ?? "").Trim(), "새 대화", StringComparison.OrdinalIgnoreCase)) return true;
return false;
}
private static bool NormalizeLoadedConversation(ChatConversation conversation)
{
var changed = false;

View File

@@ -2756,6 +2756,16 @@ public partial class ChatWindow : Window
// 탭 필터 — 현재 활성 탭의 대화만 표시
items = items.Where(i => string.Equals(i.Tab, _activeTab, StringComparison.OrdinalIgnoreCase)).ToList();
// 탭 전환 과정에서 저장된 "빈 새 대화" 노이즈 항목은 목록에서 숨김
items = items.Where(i =>
i.Pinned
|| !string.IsNullOrWhiteSpace(i.ParentId)
|| !string.Equals((i.Title ?? "").Trim(), "새 대화", StringComparison.OrdinalIgnoreCase)
|| !string.IsNullOrWhiteSpace(i.Preview)
|| i.AgentRunCount > 0
|| i.FailedAgentRunCount > 0
|| !string.Equals(i.Category, ChatCategory.General, StringComparison.OrdinalIgnoreCase)
).ToList();
_failedConversationCount = items.Count(i => i.FailedAgentRunCount > 0);
_runningConversationCount = items.Count(i => i.IsRunning);
_spotlightConversationCount = items.Count(i => i.FailedAgentRunCount > 0 || i.AgentRunCount >= 3);