AX Agent background conversation ??? UI ?? ??

?? ??? ?? ??? ?? ?? ?? ??? ??? ?? ?? ?? ???? ??? ????.

ChatStreamingUiPolicy? ?? ??? ??? ActiveConversation ???? ???, ChatWindow? ??? ??? ?? ??? ????.

AgentProgressHintTimer? StreamMetricsLabel? background conversation ????? ??? UI? ?? ??? ??? ????, ?? ???? README/DEVELOPMENT ??? ????.

??: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_background_conversation_live_ui\\ -p:IntermediateOutputPath=obj\\verify_background_conversation_live_ui\\
??: dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ChatStreamingUiPolicyTests|AppStateServiceTests" -p:OutputPath=bin\\verify_background_conversation_live_ui_tests\\ -p:IntermediateOutputPath=obj\\verify_background_conversation_live_ui_tests\\
This commit is contained in:
2026-04-15 22:37:13 +09:00
parent 82e58bde57
commit e2553a10ae
7 changed files with 52 additions and 7 deletions

View File

@@ -2302,3 +2302,10 @@ MIT License
- 테스트:
- `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_tab_loop_isolation\\ -p:IntermediateOutputPath=obj\\verify_tab_loop_isolation\\` 경고 0 / 오류 0
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "AppStateServiceTests" -p:OutputPath=bin\\verify_tab_loop_isolation_tests\\ -p:IntermediateOutputPath=obj\\verify_tab_loop_isolation_tests\\` 통과 45
?낅뜲?댄듃: 2026-04-15 22:39 (KST)
- AX Agent 媛숈? ???덉쓽 ?ㅻⅨ ?€?붾? 蹂닿퀬 ?덉쓣 ??, ?щ쒕? ?꾨씪?대툕 移대뱶?€ ?ㅽ뻾 以??ㅽ???ㅻ벐 ?ㅼ븘?섎굹??븯?쇰뒗 ?뚭?瑜??섏젙?덉뒿?덈떎. `src/AxCopilot/Views/ChatStreamingUiPolicy.cs`?먯꽌 ?곷떒 ?쇱씠釉?媛€?대뱶 ?몄텧??`ActiveConversation`?먯꽌留?媛€?ν븯寃?留뚮뱾???낅땲??
- `src/AxCopilot/Views/ChatWindow.xaml.cs`??`GetGuideVisibilityForActiveTab()`?쇰줈 ?꾩옱 ?좏깮?섏씠吏€???ㅽ듃由щ컢 媛€?ν꽦???듬났 愿€由ы븯怨? `RefreshStreamingControlsForActiveTab()`?먯꽌 ?쇱씠釉?移대뱶, ?곹깭 諛?, ?낅젰李?諛붾줈 ???쒓컙쨌?좏겙 ?섏씠釉붿쓣 媛숈? 湲곗쨪?쇰줈 泥섎━?섎룄濡?留욎톬?듬땲??
- `src/AxCopilot/Views/ChatWindow.AgentStatusPresentation.cs`?€ `src/AxCopilot/Views/ChatWindow.StatusPresentation.cs`?먯꽌 idle ?€?몄뿉 background conversation?댁뼱?ㅽ듃由щ컢 ?뚰듃?€ 硫뷀듃由?以꾩쓣 ?ㅼ떆 ?뚮━吏€ ?딆쾶 ??諛꾧퉴吏€ 媛숈? ?대? ?쇱씠釉?UI媛€ 媛꾩슂?먯뿉 寃⑥?蹂댁씠吏€ ?딄쾶 ?섏젙?덉뒿?덈떎.
- 寃€利?
- `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_background_conversation_live_ui\\ -p:IntermediateOutputPath=obj\\verify_background_conversation_live_ui\\` 寃쎄퀬 0 / ?ㅻ쪟 0
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ChatStreamingUiPolicyTests|AppStateServiceTests" -p:OutputPath=bin\\verify_background_conversation_live_ui_tests\\ -p:IntermediateOutputPath=obj\\verify_background_conversation_live_ui_tests\\` ?듦낵 49

View File

@@ -1625,3 +1625,12 @@ UI ?遺우쁽????域뱀뮆???귐뗫솯?醫딆춦 ???袁る퓮 ?臾믩씜 ??疫
- `src/AxCopilot/Services/AppStateService.cs``GetAgentRunForTab(...)`과 탭 지정 `ApplyAgentEvent(...)`를 지원하도록 확장했고, `src/AxCopilot/Views/ChatWindow.ConversationListPresentation.cs`, `src/AxCopilot/Views/ChatWindow.TaskSummary.cs`가 현재 활성 탭의 run 메타를 읽도록 변경했습니다.
- 테스트: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_tab_loop_isolation\\ -p:IntermediateOutputPath=obj\\verify_tab_loop_isolation\\` 경고 0 / 오류 0
- 테스트: `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "AppStateServiceTests" -p:OutputPath=bin\\verify_tab_loop_isolation_tests\\ -p:IntermediateOutputPath=obj\\verify_tab_loop_isolation_tests\\` 통과 45
업데이트: 2026-04-15 22:39 (KST)
- AX Agent 동일 탭 내 background conversation 표시 정책을 다시 정리했습니다. 기존 `src/AxCopilot/Views/ChatStreamingUiPolicy.cs``BackgroundConversation`에도 상단 라이브 가이드를 유지하도록 되어 있어, 사용자가 같은 탭의 다른 대화를 보고 있을 때 idle 타이머가 다시 실행중 카드와 상태 바를 살려내는 회귀가 있었습니다.
- `ChatStreamingUiPolicy.ShouldShowTopLevelGuide(...)``ActiveConversation` 전용으로 좁히고, `src/AxCopilot/Views/ChatWindow.xaml.cs`에는 `GetGuideVisibilityForActiveTab()`를 추가해 `RefreshStreamingControlsForActiveTab()`와 실시간 이벤트 렌더 분기가 동일한 가시성 기준을 공유하도록 맞췄습니다.
- `src/AxCopilot/Views/ChatWindow.AgentStatusPresentation.cs``AgentProgressHintTimer_Tick(...)`는 background conversation 상태에서 `RemoveAgentLiveCard(animated: false)`, `HideStreamingStatusBar()`, `HideStickyProgress()`를 유지하고 실행 힌트 상태만 탭별로 보존합니다. 이로써 사용자가 다른 대화에 머무는 동안에는 실행중 카드가 다시 생기지 않고, 실제 실행 대화로 돌아왔을 때만 최신 run 상태가 다시 복원됩니다.
- `src/AxCopilot/Views/ChatWindow.StatusPresentation.cs``UpdateStreamMetricsLabel(...)`도 같은 기준을 따르도록 조정했습니다. `_isStreaming`만 보던 기존 로직과 달리, 현재 활성 대화가 실제 스트리밍 대화일 때만 시간/토큰 라벨을 표시해 background conversation에서 메트릭 줄이 다시 나타나는 회귀를 막습니다.
- 테스트: `src/AxCopilot.Tests/Views/ChatStreamingUiPolicyTests.cs`의 상단 가이드 가시성 기대값을 갱신했습니다.
- 검증:
- `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_background_conversation_live_ui\\ -p:IntermediateOutputPath=obj\\verify_background_conversation_live_ui\\` 경고 0 / 오류 0
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ChatStreamingUiPolicyTests|AppStateServiceTests" -p:OutputPath=bin\\verify_background_conversation_live_ui_tests\\ -p:IntermediateOutputPath=obj\\verify_background_conversation_live_ui_tests\\` 통과 49

View File

@@ -27,8 +27,8 @@ public class ChatStreamingUiPolicyTests
[Theory]
[InlineData(nameof(StreamingGuideVisibility.Hidden), false)]
[InlineData(nameof(StreamingGuideVisibility.ActiveConversation), true)]
[InlineData(nameof(StreamingGuideVisibility.BackgroundConversation), true)]
public void ShouldShowTopLevelGuide_ShouldKeepGuideVisibleForBackgroundConversation(
[InlineData(nameof(StreamingGuideVisibility.BackgroundConversation), false)]
public void ShouldShowTopLevelGuide_ShouldOnlyShowGuideForVisibleStreamingConversation(
string visibilityName,
bool expected)
{

View File

@@ -24,7 +24,7 @@ internal static class ChatStreamingUiPolicy
}
internal static bool ShouldShowTopLevelGuide(StreamingGuideVisibility visibility)
=> visibility != StreamingGuideVisibility.Hidden;
=> visibility == StreamingGuideVisibility.ActiveConversation;
internal static bool ShouldRenderConversationBoundContent(StreamingGuideVisibility visibility)
=> visibility == StreamingGuideVisibility.ActiveConversation;

View File

@@ -319,6 +319,19 @@ public partial class ChatWindow
return;
}
var guideVisibility = GetGuideVisibilityForActiveTab();
if (!ChatStreamingUiPolicy.ShouldShowTopLevelGuide(guideVisibility))
{
RemoveAgentLiveCard(animated: false);
HideStreamingStatusBar();
HideStickyProgress();
UpdateLiveAgentProgressHint(null, runTab: _activeTab);
UpdateStreamMetricsLabel(
(int)Math.Max(0, _tabCumulativeInputTokens.GetValueOrDefault(_activeTab)),
(int)Math.Max(0, _tabCumulativeOutputTokens.GetValueOrDefault(_activeTab)));
return;
}
// _streamingTabs.Contains(_activeTab)가 위에서 이미 검증됨 — _streamRunTab은 다른 탭 시작 시 덮어써질 수 있으므로 _activeTab 사용
var runTab = _activeTab;
if (!string.Equals(runTab, "Cowork", StringComparison.OrdinalIgnoreCase)

View File

@@ -236,12 +236,18 @@ public partial class ChatWindow
{
if (StreamMetricsLabel == null) return;
if (!_isStreaming)
if (!_isStreaming || !ChatStreamingUiPolicy.ShouldShowTopLevelGuide(GetGuideVisibilityForActiveTab()))
{
StreamMetricsLabel.Visibility = Visibility.Collapsed;
return;
}
if (inputTokens == 0 && outputTokens == 0)
{
inputTokens = (int)Math.Max(0, _tabCumulativeInputTokens.GetValueOrDefault(_activeTab));
outputTokens = (int)Math.Max(0, _tabCumulativeOutputTokens.GetValueOrDefault(_activeTab));
}
StreamMetricsLabel.Visibility = Visibility.Visible;
var elapsedText = "0s";

View File

@@ -1684,9 +1684,7 @@ public partial class ChatWindow : Window
private void RefreshStreamingControlsForActiveTab()
{
var isOwningTab = _streamingTabs.Contains(_activeTab);
var guideVisibility = ChatStreamingUiPolicy.ResolveGuideVisibility(
isOwningTab,
isOwningTab && IsStreamingConversationVisible(_activeTab));
var guideVisibility = GetGuideVisibilityForActiveTab();
var shouldShowTopLevelGuide = ChatStreamingUiPolicy.ShouldShowTopLevelGuide(guideVisibility);
// 실행 중에도 Send 버튼 표시 — 메시지가 큐에 추가됨
@@ -1724,6 +1722,10 @@ public partial class ChatWindow : Window
if (pendingUiEvent != null)
UpdateAgentLiveCardV2(pendingUiEvent);
}
UpdateStreamMetricsLabel(
(int)Math.Max(0, _tabCumulativeInputTokens.GetValueOrDefault(_activeTab)),
(int)Math.Max(0, _tabCumulativeOutputTokens.GetValueOrDefault(_activeTab)));
}
private void TrackStreamingConversation(string tab, ChatConversation conversation)
@@ -1759,6 +1761,14 @@ public partial class ChatWindow : Window
}
}
private StreamingGuideVisibility GetGuideVisibilityForActiveTab()
{
var isOwningTab = _streamingTabs.Contains(_activeTab);
return ChatStreamingUiPolicy.ResolveGuideVisibility(
isOwningTab,
isOwningTab && IsStreamingConversationVisible(_activeTab));
}
private void ClearStreamingConversation(string tab, ChatConversation? expectedConversation = null)
{
var normalizedTab = NormalizeTabName(tab);