diff --git a/README.md b/README.md index 65ebd95..f2e716d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # AX Commander +- 업데이트: 2026-04-15 23:52 (KST) +- AX Agent 채팅 본문이 오른쪽 여백을 더 활용하도록 반응형 폭 계산을 넓혔습니다. `src/AxCopilot/Views/ChatWindow.ResponsePresentation.cs`에서 본문 최대폭을 `1040`, 입력창 폭을 `980` 기준까지 확장하고 `MessageList` 폭 계산도 함께 조정해 큰 창에서 process feed와 응답 본문이 너무 이르게 잘리지 않도록 맞췄습니다. +- `src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs`, `src/AxCopilot/Views/ChatWindow.V2LiveProgressPresentation.cs`에서는 process feed 헤더/이벤트 줄과 라이브 thinking 줄을 말줄임 우선 대신 줄바꿈 우선으로 바꿨습니다. 필요한 미리보기 카드만 기존 ellipsis를 유지하고, 나머지 진행 로그는 같은 폭 안에서 더 길게 읽히도록 정리했습니다. +- `src/AxCopilot/Views/ChatWindow.xaml`은 입력창 위 상태 행의 `PulseDotBar`와 `StreamMetricsLabel` 간 간격을 다시 잡아 우측 시간·토큰 표시가 붙어 있으면서도 좌측 진행 문구 폭을 덜 잠식하도록 조정했습니다. +- 검증: + - `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_chat_width_wrap\\ -p:IntermediateOutputPath=obj\\verify_chat_width_wrap\\` 경고 0 / 오류 0 + - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ChatStreamingUiPolicyTests|ChatWindowSlashPolicyTests" -p:OutputPath=bin\\verify_chat_width_wrap_tests\\ -p:IntermediateOutputPath=obj\\verify_chat_width_wrap_tests\\` 통과 74 + - 업데이트: 2026-04-15 22:45 (KST) - HTML 보고서 뒤쪽으로 갈수록 폰트 크기와 카드 레이아웃이 흔들리던 raw body 호환 문제를 보강했습니다. `src/AxCopilot/Services/Agent/TemplateService.cs`에 `h4`, `dl`, `matrix`, `comparison`, `decision_matrix`, `board_report`, `metrics`, `roadmap` 같은 레거시 블록 전용 CSS를 추가해, 구조화 섹션이 아닌 자유 본문 HTML로 생성된 보고서도 앞부분과 같은 문서 톤을 유지하도록 맞췄습니다. - 특히 `roadmap` 안의 ``가 기존 전역 `.timeline` 블록 스타일과 충돌해 뒤쪽 일정/담당 배지가 세로 타임라인처럼 깨지던 문제를 별도 override로 분리했습니다. 다크 모드와 모바일 레이아웃도 함께 맞춰 이후 생성되는 HTML 보고서가 같은 문제를 반복하지 않도록 정리했습니다. diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 0d32311..83c00f0 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1695,3 +1695,11 @@ UI ?遺우쁽????域뱀뮆???귐뗫솯?醫딆춦 ???袁る퓮 ?臾믩씜 ??疫 - 검증: - `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_project_scaffold_layout\\ -p:IntermediateOutputPath=obj\\verify_project_scaffold_layout\\` 경고 0 / 오류 0 - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "IntentGateServiceTests|ProjectScaffoldProfileCatalogTests|SkillServiceRuntimePolicyTests|AgentLoopCodeQualityTests" -p:OutputPath=bin\\verify_project_scaffold_layout_tests\\ -p:IntermediateOutputPath=obj\\verify_project_scaffold_layout_tests\\` 통과 183 +업데이트: 2026-04-15 23:52 (KST) +- AX Agent 채팅 본문 반응형 폭 계산을 조정했습니다. `src/AxCopilot/Views/ChatWindow.ResponsePresentation.cs`의 본문 상한을 `1040`, 입력창 상한을 `980`까지 넓히고 `MessageList` 최대 폭도 함께 늘려 넓은 창에서 process feed와 본문 로그가 불필요하게 조기 잘리지 않도록 정리했습니다. +- `src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs`는 process feed 헤더, 실행 이력 요약, 배너 헤더를 줄바꿈 우선으로 변경했습니다. 기존 `CharacterEllipsis`는 3줄 미리보기처럼 요약 카드가 실제로 필요한 곳에만 남기고, 이벤트 본문/요약 줄은 가능한 한 전체 문장을 읽을 수 있게 했습니다. +- `src/AxCopilot/Views/ChatWindow.V2LiveProgressPresentation.cs`에서는 라이브 thinking 로그를 Grid 기반으로 바꾸고 최대 길이도 화면 폭에 따라 확장해, 실시간 진행 카드 아래 로그가 오른쪽 여백을 더 활용하면서 자연스럽게 줄바꿈되도록 맞췄습니다. +- `src/AxCopilot/Views/ChatWindow.xaml`은 `PulseDotBar`와 `StreamMetricsLabel` 사이 간격을 다시 조정해 입력창 위 우측 시간/토큰 메트릭이 고정되면서도 좌측 진행 문구 폭을 과하게 잠식하지 않도록 보정했습니다. +- 검증: + - `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_chat_width_wrap\\ -p:IntermediateOutputPath=obj\\verify_chat_width_wrap\\` 경고 0 / 오류 0 + - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ChatStreamingUiPolicyTests|ChatWindowSlashPolicyTests" -p:OutputPath=bin\\verify_chat_width_wrap_tests\\ -p:IntermediateOutputPath=obj\\verify_chat_width_wrap_tests\\` 통과 74 diff --git a/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs b/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs index 78fb080..83983ba 100644 --- a/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs +++ b/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs @@ -287,6 +287,7 @@ public partial class ChatWindow MaxWidth = msgMaxWidth, Margin = new Thickness(62, 1, 12, 1), }; + var headerTextMaxWidth = Math.Max(180, msgMaxWidth - 28); if (liveWaitingStyle) { @@ -324,6 +325,8 @@ public partial class ChatWindow FontSize = 12, Foreground = secondaryText, VerticalAlignment = VerticalAlignment.Center, + TextWrapping = TextWrapping.Wrap, + MaxWidth = headerTextMaxWidth, }); stack.Children.Add(waitRow); } @@ -360,7 +363,8 @@ public partial class ChatWindow FontSize = 12, Foreground = headerColor, VerticalAlignment = VerticalAlignment.Center, - TextTrimming = TextTrimming.CharacterEllipsis, + TextWrapping = TextWrapping.Wrap, + MaxWidth = headerTextMaxWidth, }); stack.Children.Add(headerRow); @@ -543,7 +547,8 @@ public partial class ChatWindow FontSize = 12, Foreground = secondaryText, VerticalAlignment = VerticalAlignment.Center, - TextTrimming = TextTrimming.CharacterEllipsis, + TextWrapping = TextWrapping.Wrap, + MaxWidth = Math.Max(180, msgMaxWidth - 28), }); container.Children.Add(headerRow); @@ -568,7 +573,8 @@ public partial class ChatWindow FontSize = 11, Foreground = secondaryText, Opacity = 0.75, - TextTrimming = TextTrimming.CharacterEllipsis, + TextWrapping = TextWrapping.Wrap, + MaxWidth = Math.Max(180, msgMaxWidth - 16), Margin = new Thickness(0, 1, 0, 0), }; if (!string.IsNullOrWhiteSpace(evt.FilePath)) @@ -1842,6 +1848,7 @@ public partial class ChatWindow MaxWidth = msgMaxWidth2, Margin = new Thickness(62, 1, 12, 1), }; + var headerTextMaxWidth2 = Math.Max(180, msgMaxWidth2 - 28); if (!string.IsNullOrWhiteSpace(evt.RunId)) _runBannerAnchors[evt.RunId] = stack2; @@ -1874,7 +1881,8 @@ public partial class ChatWindow FontSize = 12, Foreground = headerColor2, VerticalAlignment = VerticalAlignment.Center, - TextTrimming = TextTrimming.CharacterEllipsis, + TextWrapping = TextWrapping.Wrap, + MaxWidth = headerTextMaxWidth2, }); stack2.Children.Add(headerRow2); diff --git a/src/AxCopilot/Views/ChatWindow.ResponsePresentation.cs b/src/AxCopilot/Views/ChatWindow.ResponsePresentation.cs index e8bb4c8..3632457 100644 --- a/src/AxCopilot/Views/ChatWindow.ResponsePresentation.cs +++ b/src/AxCopilot/Views/ChatWindow.ResponsePresentation.cs @@ -212,16 +212,19 @@ public partial class ChatWindow /// 채팅 본문 폭을 세 탭에서 동일한 기준으로 맞춥니다. private double GetMessageMaxWidth() { + if (_lastResponsiveMessageWidth >= 100) + return Math.Clamp(_lastResponsiveMessageWidth, 320, 1040); + var hostWidth = _lastResponsiveComposerWidth; if (hostWidth < 100) hostWidth = ComposerShell?.ActualWidth ?? 0; if (hostWidth < 100) hostWidth = MessageList?.ActualWidth ?? 0; if (hostWidth < 100) - hostWidth = 1120; + hostWidth = 1280; - var maxW = hostWidth - 44; - return Math.Clamp(maxW, 320, 760); + var maxW = hostWidth - 24; + return Math.Clamp(maxW, 320, 1040); } private bool UpdateResponsiveChatLayout() @@ -234,17 +237,17 @@ public partial class ChatWindow // 메시지 축과 입력축이 같은 중심선을 공유하도록 // 본문 폭 상한을 조금 더 낮추고 창 폭 변화에 더 부드럽게 반응시킵니다. - var contentWidth = Math.Max(360, viewportWidth - 24); - // 고정 최대폭 — 큰 창에서 안정적, 작은 창에서만 축소 - var messageWidth = Math.Min(contentWidth - 10, 800); - var composerWidth = Math.Min(contentWidth - 24, 760); + var contentWidth = Math.Max(360, viewportWidth - 12); + // 큰 창에서는 본문을 더 넓게 쓰고, 입력창은 약간만 좁게 유지합니다. + var messageWidth = Math.Min(contentWidth - 8, 1040); + var composerWidth = Math.Min(contentWidth - 12, 980); var changed = false; if (Math.Abs(_lastResponsiveMessageWidth - messageWidth) > 8) { _lastResponsiveMessageWidth = messageWidth; if (MessageList != null) - MessageList.MaxWidth = messageWidth + 48; + MessageList.MaxWidth = messageWidth + 64; if (EmptyState != null) EmptyState.MaxWidth = messageWidth; changed = true; diff --git a/src/AxCopilot/Views/ChatWindow.V2LiveProgressPresentation.cs b/src/AxCopilot/Views/ChatWindow.V2LiveProgressPresentation.cs index 5597b3f..68bc7c8 100644 --- a/src/AxCopilot/Views/ChatWindow.V2LiveProgressPresentation.cs +++ b/src/AxCopilot/Views/ChatWindow.V2LiveProgressPresentation.cs @@ -338,18 +338,21 @@ public partial class ChatWindow case AgentEventType.Thinking: { + var thinkingSummaryMaxLength = msgMaxWidth > 900 ? 220 : 140; var thinkText = AgentProgressSummarySanitizer.NormalizeThinkingSummary( agentEvent.Summary, agentEvent.ToolName, - maxLength: 100); + maxLength: thinkingSummaryMaxLength); if (string.IsNullOrWhiteSpace(thinkText)) break; - var thinkRow = new StackPanel + var thinkRow = new Grid { - Orientation = Orientation.Horizontal, Margin = new Thickness(22, 2, 0, 2), }; - thinkRow.Children.Add(new TextBlock + thinkRow.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + thinkRow.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); + + var thinkIcon = new TextBlock { Text = "\uE915", FontFamily = s_segoeIconFont, @@ -357,17 +360,23 @@ public partial class ChatWindow Foreground = new SolidColorBrush(Color.FromRgb(0x59, 0xA5, 0xF5)), VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 4, 0), - }); - thinkRow.Children.Add(new TextBlock + }; + Grid.SetColumn(thinkIcon, 0); + thinkRow.Children.Add(thinkIcon); + + var thinkLabel = new TextBlock { Text = thinkText, FontSize = 10.5, FontStyle = FontStyles.Italic, Foreground = secondaryText, Opacity = 0.82, - TextTrimming = TextTrimming.CharacterEllipsis, - MaxWidth = msgMaxWidth - 60, - }); + TextWrapping = TextWrapping.Wrap, + MaxWidth = Math.Max(180, msgMaxWidth - 52), + VerticalAlignment = VerticalAlignment.Center, + }; + Grid.SetColumn(thinkLabel, 1); + thinkRow.Children.Add(thinkLabel); _v2LiveContainer.Children.Add(thinkRow); AutoScrollIfNeeded(); break; @@ -432,11 +441,12 @@ public partial class ChatWindow return; var narrative = AgentStatusNarrativeCatalog.BuildFromEvent(agentEvent, _activeTab); + var statusSummaryMaxLength = GetMessageMaxWidth() > 900 ? 260 : 180; var normalizedThinking = agentEvent.Type == AgentEventType.Thinking ? AgentProgressSummarySanitizer.NormalizeThinkingSummary( agentEvent.Summary, agentEvent.ToolName, - maxLength: 160) + maxLength: statusSummaryMaxLength) : string.Empty; var message = string.IsNullOrWhiteSpace(normalizedThinking) ? narrative.Message diff --git a/src/AxCopilot/Views/ChatWindow.xaml b/src/AxCopilot/Views/ChatWindow.xaml index 9de9a3e..4884db4 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml +++ b/src/AxCopilot/Views/ChatWindow.xaml @@ -2166,7 +2166,7 @@ @@ -2181,9 +2181,9 @@ + Margin="6,0,18,0"> @@ -2262,7 +2262,7 @@ Visibility="Collapsed" HorizontalAlignment="Right" VerticalAlignment="Bottom" - Margin="12,0,6,2" + Margin="18,0,0,2" FontSize="11" Foreground="{DynamicResource SecondaryText}" Opacity="0.7"